The BIOS contains routines to manage and display a clock with minutes and seconds. The routines use quad0 and quad1 as display, the time is counted in the external RAM addresses 01h and 02h. This demo program displays a clock which can be controlled with the joystick. Moving left stops the clock, moving right restarts it. The direction can be changed with moving up and down. To demonstrate how to read back the time the program plays a sound every full minute.
The VSYNC IRQ counts the frames in bits 0-5 of
iram_clock = 03Eh. If the counter reaches 60 it is
reset to 0. This is true even for PAL machines, so the clock is too slow
on PAL. Bit 6 = clock_forward of
iram_clock controls the direction, by setting
clock_stop = bit 7 the clock can be stopped. The
routine doclock has to be called manually every frame. It tests if
the counter is set to 59 and if the clock is active. Then it updates the
time in external RAM and the display in quad0/1. Minutes and seconds are stored
as BCD numbers. If the time hits 00:00 while counting backwards the clock
stops.
To set the start time I simply put the values into external RAM. In this
example I set the time to 1 minute and 1 second. This means the first
visible time is 01:00, because later I set the frame counter to 58
so the first call to doclock will trigger a count and display the
correct time in quad0 and quad1. After setting the time I call
initclock which sets the position on screen and the color of the
clock in the control registers of quad0 and 1. Then I call
waitvsync to make sure that I have enough time between setting the
frame counter and the first doclock. I then set the frame counter
to 58. After that I call gfxon. The main loop starts with
waitvsync so in the meantime the counter is set to 59. This
also means that for one frame the displayed time is 01:01. The call to
doclock then updates the display and decreases the time.
; need to initialise quad0/1
call gfxoff
; set the start time = 01:00
call extramenable
mov r0,#eram_minutes
mov a,#01h ; BCD
movx @r0,a ; 1 minutes
mov r0,#eram_seconds
mov a,#01h ; BCD
movx @r0,a ; 1 second, will roll over
; immediately to 0 seconds
; initialise the display
call vdcenable
mov r3,#020h ; x position
mov r4,#040h ; y position
mov r6,#col_chr_white
call initclock
; activate the clock
call waitvsync ; make sure there is no roll
; over before we want it
mov r0,#iram_clock
mov a,#03Ah
mov @r0,a ; start clock backwards
; rolls over at first VSYNC
; and initialises display in
; first doclock
call gfxon
As usual I use waitvsync to make sure the loop executes once
per frame. When calling doclock it is important to set the Y
position and the color to the same values as in initclock. If you
want to move the clock or change color call initclock again.
loop
call waitvsync ; once per frame
mov r4,#040h ; y position, same as above !!
mov r6,#col_chr_white
call doclock ; update clock, if necessary
After updating the display I test if the seconds are 0. I only want to
start the sound playing once although this part is executed every frame, so I
have to test the frame counter. Because I don't want to play the sound again
and again when the clock stops, I also check if clock_stop is
reset. To ignore the direction bit I use 0FFh-clock_forward and
not the easier to read ~clock_forward because ASL has problems
with the latter, it is expanded to 16 or 32 bits which is too long to fit into a
8 bit register and ASL is too stupid to cut it to 8 bits.
; test the time and play sound every minute
call extramenable
mov r0,#eram_seconds
movx a,@r0
jnz nosound
; only play sound, if count=0 and still counting
mov r0,#iram_clock
mov a,@r0
anl a,#0FFh-clock_forward
jnz nosound
; now play the sound
mov a,#tune_select2
call playsound
nosound
Then I test the joystick. I only explain the test for left/right, up/down is
the same only with R3 and clock_forward. First I test for left by
increasing the X offset. If the joystick was turned left A is now 0. In this
case I set the clock_stop bit and skip the test for right, because
it is impossible to turn the joystick left and right. Now I decrease the X
offset twice which means it is now 0 if the joystick is turned right. In this
case I clear the clock_stop bit. Then I do the same for up/down.
At last I put the new value for iram_clock back and jump to the
beginning of the main loop.
; test the joystick
mov r1,#0
call getjoystick
; get value to manipulate
mov r0,#iram_clock
mov a,@r0
mov r7,a
; test left/right
mov a,r2 ; x offset
inc a
jnz joy_noleft
; left=stop clock
mov a,#clock_stop
orl a,r7 ; set clock_stop
mov r7,a
jmp joy_noright ; left = not right
joy_noleft
dec a
dec a
jnz joy_noright
; right=start clock
mov a,#0FFh-clock_stop
anl a,r7 ; clear clock_stop
mov r7,a
joy_noright
; ...
; up/down left out
; ...
joy_end
; put new value back into iram_clock
mov a,r7
mov @r0,a
jmp loop ; next frame