Spell-Master Fix Patches
The QuickEdit and WordFinder applications expect to execute from a 128KB Eprom. Their bank switching code uses static addressing, so if Spell-Master is not blown to the last eight banks in a card this will fail. Several fixes are needed to convert this code to relative bank addressing.
My fix makes the following improvements:
Spell-Master now runs in any slot, including slot 0 (see Slot 0 Flash Downgrade )
It now runs in any eight adjacent banks, so fine for RomCombiner compilations of multiple application ROMs on a single card.
It can now run as a RAM app using Installer on OZ 4.0 or lower. Unfortunately the RAM app support in OZ 4.6 through to OZ 5.0 does not guarantee consecutive bank allocation, so Spell-Master must run as card application on those versions.
Method
The Application DORs reveal that the application code resides in SPELL.63 (mostly WordFinder) and SPELL.62 (mostly QuickEdit, though some functions are called from SPELL.63). The remaining six banks, SPELL.56 to SPELL.61, comprise the dictionary.
By disassembling the two application banks using dzasm and searching for OS_Mgb calls, we can find where the code determines the current running bank. Using this it determines which slot it is running from and combines this information with the static bank numbers when switching banks.
This patching task was complicated by the WordFinder bank switching code being situated before the executable entry point, nestled in between the QuickEdit and WordFinder Application DORs. My initial disassembly starting at file offset $01D1 (entry point) had missed this.
SPELL.62
Original code location 1:
; Address $C1B6, or offset $01B6 in SPELL.62
LD A, (IX+0) ; DD 7E 00 Retrieve dictionary bank value from IX
SRL A ; CB 3F
SRL A ; CB 3F
SRL A ; CB 3F
SRL A ; CB 3F
SRL A ; CB 3F Divide it by 32
ADD A, $38 ; C6 38 Add 56 (SPELL.56 is the lowest bank)
LD D, A ; 57 Store this dictionary bank number
LD C, $03 ; 0E 03
OZ OS_Mgb ; E7 5A Get bank bound to segment 3 (running bank), stored in B
LD A, B ; 78
AND $C0 ; E6 C0 Take top two bits (current slot)
OR D ; B2 Combine with dictionary bank number
LD ($1F84), A ; 32 84 1F Store target dictionary bank address
LD L, (IX+1) ; DD 6E 01
LD H, (IX+2) ; DD 66 02
LD ($1F82), HL ; 22 82 1F Store position in full dictionary?
LD C, $02 ; 0E 02
LD B, A ; 47
OZ OS_Mpb ; E7 5D Bind target dictionary bank to segment 2
SCF ; 37
CCF ; 3F
RET ; C9 Return
Patched code location 1:
; Address $C1B6, or offset $01B6 in SPELL.62
LD A, (IX+0) ; DD 7E 00 Retrieve dictionary bank value from IX
SRL A ; CB 3F
SRL A ; CB 3F
SRL A ; CB 3F
SRL A ; CB 3F
SRL A ; CB 3F Divide it by 32
NOP ; 00
NOP ; 00
NOP ; 00
LD C, $03 ; 0E 03
OZ OS_Mgb ; E7 5A Get bank bound to segment 3 (running bank), stored in B
ADD A, B ; 80 Calculate target dictionary bank address...
SUB $06 ; D6 06 ...relative to running bank (3E, or SPELL.62)
NOP ; 00
LD ($1F84), A ; 32 84 1F Store target dictionary bank address
LD L, (IX+1) ; DD 6E 01
LD H, (IX+2) ; DD 66 02
LD ($1F82), HL ; 22 82 1F Store position in full dictionary?
LD C, $02 ; 0E 02
LD B, A ; 47
OZ OS_Mpb ; E7 5D Bind target dictionary bank to segment 2
SCF ; 37
CCF ; 3F
RET ; C9 Return
Original code location 2:
; Address $C286, or offset $0286 in SPELL.62
.hook_function_in_bank_63
; IN:
; A = Position in function jump table ($00 to $0A)
;
PUSH AF ; F5 Store function input on stack
LD C, $03 ; OE 03
OZ OS_Mgb ; E7 5A Get bank bound to segment 3 (running bank), stored in B
LD A, B ; 78
AND $C0 ; E6 C0 Take top two bits (current slot)
OR $3F ; F6 3F Combine with bank 3F (SPELL.63)
LD B, A ; 47
LD C, $01 ; 0E 01
OZ OS_Mpb ; E7 5D Bind SPELL.63 into segment 1
JP $7F80 ; C3 80 7F Jump to $7F80 in segment 1 (file offset $3F80)
Patched code location 2:
SPELL.63
Original code location 1:
Patched code location 1:
Original code location 2:
Patched code location 2:
Download Patches
These patches are published in the IPS format, popular for ROM patches.
Â