|Pause bugfix for JSW48|
BCregister, and then later code assumes it still holds the address of the keyboard and tries to
IN A,(C)from it. The resultant
IN 0crashes the Interface 1, as shown in the following disassembly:
8B07: LD HL,&9A00 ; Restore attributes of bottom third LD DE,&5A00 LD BC,&0100 ; Copy from &9A00 to &5A00 LDIR ; BC now holds zero! LD A,(&80DE) ; Get border colour OUT (&FE),A ; Set border 8B17: LD A,(&85D1) ; Get a variable CP &FF ; Is it &FF - lost a life? JP Z,&8C01 ; Jump to lose a life LD B,&BF ; BC now holds &BF00 instead of &BFFE LD HL,&85E2 ; HL=>music flags IN A,(C) ; Read from port 0 and crashMany published bugfixes patch the code with a call elsewhere to set the registers correctly. Unfortunately, not only is that not neccessary, most of the published bugfixes actually crash the game in a different way. As Andrew Broad has pointed out, many bugfixes put in a call to &FFF0. Unfortunately, that is the data area for room 63, and if room 63 is ever used, it either corrupts the room data or corrupts the pause bugfix.
None of this is needed. The simplest fix is to realise that if the bottom third of the screen does not have it's colours changed during the pause at &8B00, then the attributes do not need to be restored at &8B07. This can be done by looping until &5A instead of &5B and replacing the
LD C,&FE to restore C correctly:
Original code: Changed to: 8B02 FE 5B CP &5B 8B02 FE 5A CP &5A 8B10 ED B0 LDIR 8B10 0E FE LD C,&FEThis can be done with
POKE 35587,90:POKE 35600,14:POKE 35601,254.
When typing up my commented JSW disassembly I realised that there is another way to fix the pause bug, while allowing the bottom third of the screen to change colour while pausing. The code at &8B17 checks if A holds &FF with
CP &FF. As A is not then used this can be
INC A with the same Z/NZ flag effects, and
is one byte shorter. This means there is enough space to replace the
LD B,&BF with
Original code: Changed to: 8B1A FE FF CP &FF 8B1A 3C INC A 8B1C CA 01 8C JP Z,&8C01 8B1B CA 01 8C JP Z,&8C01 8B1F 06 BF LD B,&BF 8B1E 01 FE BF LD BC,&BFFEThis can be done with:
POKE 35610,60:POKE 35611,202:POKE 35612,1 POKE 35613,140:POKE 35614,1:POKE 35615,254and can be applied to the original JSW48 code with the Pause2.hex hex patchfile.
SkoolKid spotted an even more efficient bugfix, just requiring three pokes. Instead of reading from the corrupted BC, port &FE is read directly, with A preloaded with the high byte of the address.
Original code: Changed to: 8B1F 06 BF LD B,&BF 8B1F 3E BF LD A,&BF ; 'h'-'enter' 8B21 21 E2 85 LD HL,MFLAGS 8B21 21 E2 85 LD HL,MFLAGS 8B24 ED 78 IN A,(C) 8B24 DB FE IN A,(&FE) ; Read keyboard rowThis can be done with:
POKE 35615,62:POKE 35620,219:POKE 35621,254and can be applied with the Pause.hex hex patch file.