MDFS::Software.JSW.JGH.Pause/htm Search

Bugfixes and patches to the JSW48 Game Engine

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:
8B00:  INC HL       ; Increment pointer to attributes
       LD A,H       ; Get high byte
       CP &5B       ; Has it passed end of screen at &5AFF?
       JR NZ,&8AF3  ; Loop for 24 screen lines
       RET

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
       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 Pause.hex hex patchfile. This is now my preferred pause bugfix.