[hatari-devel] change to ikbd when writing to $fffc02
Nicolas Pomarède
npomarede at corp.free.fr
Wed May 11 18:54:51 CEST 2011
Hello,
after a fix was made to handle the game "uss john young" (on FOF54 for
example), the "Pandemonium Demos" was not working anymore, as some
commands could not be sent to the ikbd (the demo was stuck in an endless
loop).
Looking at the code for uss john young, we have :
000041f4: 207c 0000 4146 303c 0003 MOVEA.L #$00004146,A0
000041fa: 303c 0003 0839 0001 ffff MOVE.W #$0003,D0
000041fe: 0839 0001 ffff fc00 6700 BTST.B #$0001,$fffffc00
00004206: 6700 fff6 13d8 ffff fc02 BEQ.W #$fff6 == 000041fe (FALSE)
0000420a: 13d8 ffff fc02 0839 0001 MOVE.B (A0)+,$fffffc02
00004210: 0839 0001 ffff fc00 6600 BTST.B #$0001,$fffffc00
00004218: 6600 fff6 51c8 ffe0 2039 BNE.W #$fff6 == 00004210 (TRUE)
0000421c: 51c8 ffe0 2039 0000 21ea DBF .W D0,#$ffe0 == 000041fe (FALSE)
00004146: 08 0c 0a 0a (IKBD_Cmd_RelMouseMode + Cmd_SetMouseScale)
-> the games sends 2 commands to the ikbd ; it correctly checks that bit
1 of $fffc00 is set to 0 (tx buffer full) to indicate the transfer is
happening, and then it checks bit 1 goes back to 1 to send the next byte.
Pandemonium Demos :
0008223a: 1018 11c0 fc02 0838 0001 MOVE.B (A0)+,D0
0008223c: 11c0 fc02 0838 0001 fc00 MOVE.B D0,$fffffc02
00082240: 0838 0001 fc00 67f4 1018 BTST.B #$0001,$fffffc00
00082246: 67f4 1018 b03c 00fb 66ec BEQ.B #$fffffff4 == 0008223c (TRUE)
00082248: 1018 b03c 00fb 66ec 4e75 MOVE.B (A0)+,D0
0008224a: b03c 00fb 66ec 4e75 48e7 CMP.B #$fb,D0
0008224e: 66ec 4e75 48e7 0202 46fc BNE.B #$ffffffec == 0008223c (FALSE)
00082250: 4e75 48e7 0202 46fc 2700 RTS.L
082234: 08 12 1a fb IKBD_Cmd_RelMouseMode IKBD_Cmd_TurnMouseOff
IKBD_Cmd_DisableJoysticks
-> the demo write to $fffc02 and if bit 1 is 0, it writes the same byte,
until it is transfered.
1st, this code is wrong, writing the same byte again is pointless, you
just need to check bit 1 of SR, not sending the same byte again.
Fortunately, the ACIA uses some kind of double buffer, so once a
transfer is started, new writes to $fffc02 are ignored (else the
transfer would start from the beginning and it would be endless).
But this means that once a byte is written to $fffc02, we must return
bit 1=0 until the whole byte is transfered, and we should then return
bit 1=1.
Current code in the ikbd was doing a kind of mix of both values : 1st
time, it returned bit 1=0 (buffer full) and next times it returned bit
1=1. But in the case of Pandemonium this didn't work, because the demo
writes again to $fffc02, so we restart from the beginning and bit 1 is
always 0.
So, I added a timer similar to the one already presents when the ikbd
sends bytes to the 68000 : when writing to $fffc02, bit 1 is set to 0
(buffer full) and after ACIA_CYCLES, an internal timer will really
process the byte that was written in $fffc02 and set bit 1 to 1 (TX
buffer empty). During that time, other writes to $fffc02 will be ignored.
A small random number needed to be added, as it seems the number of
cycles is not always constant (else Pandemonium can sometimes enter an
endless loop)
This fixes Pandemonium Demos, as well as staying compatible with Uss
John Young. Don't hesitate to test some of your favorites games (fire
button, ...) to check this didn't break anything.
PS : some new variables are not saved in memory snapshot for now,
because I don't want to break the structure. I will change this if no
regression occur.
Nicolas
More information about the hatari-devel
mailing list