[img] Pause bugfix for JSW48
 MDFS::Software.JSW.JGH.Docs.Pause/htm Search  

Removing Interface 1 pause crash

If an Interface 1 is connected, when the game pauses it crashes. This is due to an LDIR clearing the BC register, and then later code assumes it still holds the address of the keyboard and tries to IN A,(C) from it. The resultant IN 0 crashes 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 crash
Many 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.

Bugfix 1
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 LDIR with 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,&FE
This can be done with POKE 35587,90:POKE 35600,14:POKE 35601,254.

Bugfix 2
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 replaced with 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 LD BC,&BFFE:

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,&BFFE
This can be done with:
  POKE 35610,60:POKE 35611,202:POKE 35612,1
  POKE 35613,140:POKE 35614,1:POKE 35615,254
and can be applied to the original JSW48 code with the Pause2.hex hex patchfile.

Bugfix 3
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 row
This can be done with: POKE 35615,62:POKE 35620,219:POKE 35621,254 and can be applied with the Pause.hex hex patch file.

Best viewed with Any Browser Valid HTML 4.0! Authored by J.G.Harston
Last update: 20-Apr-2004