
We are now getting to the stage where we have to deal with time. For our initial prototype we want our matches to last a specific amount of time before we end the match, compare the scores and decided on who has won. To do this we have to track the time.
; There is a specific hardware register that can be used on the Amiga to help us do this that resides in the I/O port chip which is equiped with 60 Hertz clock and a 24 bit counter. The manual ‘http://wiki.pegasos.hu/index.php/Amiga_Machine_Language_(Chapter_5)’ quotes
“These 24 bits can’t be read at once,for instance with a MOVE.L command,because the register is divided into three bytes.The low byte is at address $BFE801,the middle at $BFE901,and the high byte with bits 16-23 at $BFEA01.”
It even gives us a nice example to use it
gettime:
MOVE.B $bfea01,D7 ;hi-byte in D0
LSL.L #4,D7 ;shift twice by 4 bits
LSL.L #4,D7 ;(8 bits shifted)
MOVE.B $bfe901,D7 ;get mid-byte
LSL.L #4,D7
LSL.L #4,D7 ;shift again
MOVE.B $bfe801,D7 ;get the lo-byte
RTS ;done
From the listing we can see that the elapsed time is in 1/50th of a second (remember 50hz clock!). So we know that when 50 of these pass we have passed one second. From this we can create a very basic timer for our game. Lets get started in modifying our current code.
ExecBase = 4
OpenLib = -552
OpenLibVersion = 34
CloseLib = -414
PutString = -948
MOVE.L #OpenLibVersion,D0
LEA DosName,A1
MOVE.L ExecBase,A6
JSR OpenLib(A6)
MOVE.L D0,A6
MOVE.L #TitleString,D1
JSR PutString(A6)
MOVE.L #InstructionString,D1
JSR PutString(A6)
title_page:
MOVE.B $bfec01,D0 ; Keypress
NOT.B D0
ROR.B #1,D0 ; D0 now contains the raw key
CMP.B #$45,D0 ;Check for esc
BEQ quit
CMP.B #$21,D0 ;Check for 'S'
BEQ game_loop
BNE title_page
The above code hasn’t changed from before but the following lines is where we get into tracking time.
BSR gettime ;put the current time into D7
MOVE.L D7,D6 ;save to D6
As you can see we call our gettime routine and store the value in D6
MOVE.B #0000,Seconds
MOVE.B #0000,Minutes
We have declared the memory space for ‘Seconds’ and ‘Minutes’ at the bottom of our listing and we give them initial integer value of 0. We have also initialised D7 with the current time.
game_loop:
BSR gettime ;put the current time into D7
SUB.B D6,D7 ;elapse time in 1 50th of a sec in d7
CMP.B #$32,d7 ;elaspe time > hex 32 (50) so 50 50ths = 1 sec
BGE.B add_second
BLT.B display
;Here we call gettime and subtract the time in D6 from the time in D7 to get the elapsed time in 50ths of a second. We the compare the value to see if we have 50 of these 50ths of a second (in other words a whole second). If we do then we branch to the code that deals with incrementing seconds. Note we have to supply 50 in hex. The following code shows how the seconds are dealt with;
add_second:
BSR gettime ;put the current time into d7
MOVE.L d7,D6 ;save to D6
ADD.B #0001,Seconds
CMP.B #0060,Seconds
BGE.B add_minute
BLT.B display
add_minute
MOVE.B #0000,Seconds
ADD.B #0001,Minutes
You will first notice that the gettime routine is called to get the current time and store it in both D7 and D6. This is done straight away to keep our timer accurate otherwise we risk loosing time by running operations and then calling the gettime function.
The next operation adds one to our seconds and then we check to see if our seconds have hit 60. If so we increase the minutes and zero the seconds before displaying the output to screen.
That’s it really the next is our display code and mouse button check to exit the game loop.
display:
MOVE.B Seconds,D1
LEA buffer,a0 ;pointer to the buffer
JSR deci_4
MOVE.L #SecondsText,D1
JSR PutString(A6)
MOVE.L #buffer,D1
JSR PutString(A6)
MOVE.L #newline,D1
JSR PutString(A6)
CLR.L buffer
MOVE.B Minutes,D1
LEA buffer,a0 ;pointer to the buffer
JSR deci_4
MOVE.L #MinutesText,D1
JSR PutString(A6)
MOVE.L #buffer,D1
JSR PutString(A6)
MOVE.L #newline,D1
JSR PutString(A6)
CLR.L buffer
LEA buffer,a0 ;pointer to the buffer
MOVE.L d7,D1
JSR byte ;test subroutine
MOVE.L #buffer,D1
JSR PutString(A6)
MOVE.L #newline,D1
JSR PutString(A6)
We have added the following code to check to see if we have hit the 5 minute limit for the match. If so we exit the main game loop and branch to the end_match code
CMP.B #0005,Minutes
BGE.B end_match
BTST #6,$bfe001
BNE game_loop
We have created this section to end the match. This jumps to the code to quit and will be called after the mouse button is pressed to quit the main game loop or when the time is up.
end_match:
JSR quit
The following has been lifted from the manual as explained earlier;
gettime:
MOVE.B $bfea01,D7 ;hi-byte in D0
LSL.L #4,D7 ;shift twice by 4 bits
LSL.L #4,D7 ;(8 bits shifted)
MOVE.B $bfe901,D7 ;get mid-byte
LSL.L #4,D7
LSL.L #4,D7 ;shift again
MOVE.B $bfe801,D7 ;get the lo-byte
RTS ;done
And the rest is our base conversion code for decimal to ascii.
deci_4: ;subroutine-four digit numbers
DIVU #1000,D1 ;divide by 1000
BSR digit ;evaluate result-move remainder
DIVU #100,D1 ;divide by 100
BSR digit ;evaluate result and move
DIVU #10,D1 ;divide by 10
BSR digit ;evaluate result-move remainder
;evaluate the remainder directly
digit:
ADD #$30,D1 ;convert result into ASCII
MOVE.B D1,(a0)+ ;move it into buffer
CLR D1 ;erase lower word
SWAP D1 ;move the remainder down
RTS ;return
byte:
MOVE D1,D2 ;move value into D2
LSR #4,D2 ;move upper nibble into lower nibble
BSR nibble ;convert D2
MOVE.B D2,(A0)+ ;put character into buffer
MOVE D1,D2 ;value in D2
BSR nibble ;convert lower nibble
MOVE.B D2,(A0)+ ;and put it in buffer
RTS ;done
nibble:
AND #$0f,D2 ;just keep low byte
ADD #$30,D2 ;add $30
CMP #$3a,D2 ;was it a digit?
BCS ok ;yes:done
ADD #7,D2 ;else add 7
ok:
RTS ;done
quit:
MOVE.L #QuitString,D1
JSR PutString(A6)
MOVE.L A6,A1
MOVE.L ExecBase,A6
JSR CloseLib(A6)
RTS
buffer:
blk.b 9,0 ;space for long word data
DosName: DC.B "dos.library",0
TitleString: DC.B "Stop Watch",10,0
InstructionString: DC.B "Press 's' to Start or 'Esc' to quit.",10,0
QuitString: DC.B "Quit",10,0
newline: DC.B 10+'',0
SecondsText: DC.B "SECONDS: " ,10,0
Seconds: DS.B 1
Minutes: DS.B 1
MinutesText: DC.B "MINUTES: ",10,0
asciiSecs: DS.L 1
asciiMins: DS.L 1
The end result of this code will be a simple display of the seconds and minutes within the CLI.
Leave a Reply