Vision2 Fix Patch
32KB Eprom Constraint
Vision2 was sold as a 32KB EPROM. As explained in the Developer Notes, cards smaller than 1MB are addressable at repeating intervals within that Slot's address space. This allows OZ to easily scan the top bank of a card, without needing to know its size.
By default, Vision2 cannot run from other card sizes because its DORs presume it will occupy the last two banks, but its bank binding code presumes it will occupy the first two banks. Both conditions will only hold true for a 32KB card.
Crash on New OZ Versions
Vision2 will crash when launched on OZ versions later than 4.0, which makes it a pretty dangerous thing to have on a card. Accidentally launching it could lose work in other applications.
Earlier Patch
RomCombiner includes patches to lift the restrictive card limitations for both Vision2 (full version) and for Vision/L (reduced feature version).
Consider the Z88 bank layout:
Banks &00 - &3F are internal Slot 0 (lower half ROM, upper half RAM)
Banks &40 - &7F are wired to Slot 1 (usually RAM for Expanded mode in old OZ)
Banks &80 - &BF are wired to Slot 2
Banks &C0 - &FF are wired to Slot 3 (usually EPROM, only Slot with 12V)
The patch amends the following byte values in the application's own bank binding code:
Original | Patched | Impact |
---|---|---|
C0 | FE | Slot 3, changes 1st bank to penultimate bank |
C1 | FF | Slot 3, changes 2nd bank to last bank |
80 | BE | Slot 2, changes 1st bank to penultimate bank |
81 | BF | Slot 2, changes 2nd bank to last bank |
Vision is limited to running in Slots 2 or 3 only, which is understandable considering early OZ versions needed a RAM card in Slot 1 specifically, for an Expanded machine. The patch bundled with RomCombiner does not ease that limitation, nor does it allow Vision to run from any other banks than 63 and 62 - which does rather get in the way of making a compilation ROM on a flashcard.
A Better Solution
Reading through this section of Developer Notes, this part jumped out at me:
If your applications requires access to other banks in your card then you can use the bank switching call, OS_Mpb, to bind them in. However, your card could be placed in any of the three slots so you need to determine where your card is. This can simply be done by using OS_Mgb while running ROM'ed code and then using bank offsets relative to this value.
I could simply re-write this part of the code by disassembling it, and convert the bank binding to be relative to the running bank. OS_Mgb needs the segment this is bound to, information which is stated in the Application DOR.
My patch makes the following improvements:
Vision2 now runs in any slot, including slot 0 (see Slot 0 Flash Downgrade )
It now runs in any pair of 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.
If the ROM checks fail, the application will now exit with a fatal error instead of crashing the Z88 by getting stuck in a never-ending loop.
Crucially the application will now exit if it is launched on an OZ version newer than 4.0, to avoid a hard crash.
Original Code, Annotated Disassembly
; Address $C039, or offset $0039 in VIS206.62
.bind_banks_slot3
XOR A ; AF A = 0
LD BC, $CA01 ; 01 01 CA
OZ OS_Mpb ; E7 5D Bind 1st bank in slot 3 (B), to segment 1 (C), assumes 32K Eprom
XOR A ; AF A = 0
LD BC, $CB02 ; 01 02 CB
OZ OS_Mpb ; E7 5D Bind 2nd bank in slot 3 (B), to segment 2 (C), assumes 32K Eprom
.rom_check_slot3
LD A, ($400B) ; 3A 0B 40 Read byte $0B in VIS206.62 from segment 1 (which starts at $4000)
CP '_' ; FE 5F Compare with '_'
JR NZ, bind_banks_slot2 ; 20 0A If no match, relative jump to try slot 2
LD A, ($4012) ; 3A 12 40 Read byte $12 in VIS206.62 from segment 1
CP ' ' ; FE 20 Compare with ' '
JR NZ, bind_banks_slot2 ; 20 03 If no match, relative jump to try slot 2
JP continue ; C3 73 40 Checks passed, continue execution
.bind_banks_slot2
XOR A ; AF A = 0
LD BC, $8A01 ; 01 01 8A
OZ OS_Mpb ; E7 5D Bind 1st bank in slot 2 (B), to segment 1 (C), assumes 32K Eprom
XOR A ; AF A = 0
LD BC, $8B02 ; 01 02 8B
OZ OS_Mpb ; E7 5D Bind 2nd bank in slot 2 (B), to segment 2 (C), assumes 32K Eprom
.rom_check_slot2
LD A, ($400B) ; 3A 0B 40 Read byte $0B in VIS206.62 from segment 1 (which starts at $4000)
CP '_' ; FE 5F Compare with '_'
JR NZ, bind_banks_slot3 ; 20 D0 If no match, relative jump to try slot 3 again (endless loop)
LD A, ($4012) ; 3A 12 40 Read byte $12 in VIS206.62 from segment 1
CP ' ' ; FE 20 Compare with ' '
JR NZ, bind_banks_slot3 ; 20 C9 If no match, relative jump to try slot 3 again (endless loop)
JP continue ; C3 73 40 Checks passed, continue execution
.continue
CALL $49FC ; CD FC 49
Replacement Code
; Address $C039, or offset $0039 in VIS206.62
.bind_banks_relative
LD C, $03 ; OE 03 Application DOR states we are running in segment 3
OZ OS_Mgb ; E7 5A Get bank bound to segment 3, stored in B
LD A, B ; 78 Store it in A for later
LD C, $01 ; 0E 01
OZ OS_Mpb ; E7 5D Re-bind this bank to segment 1 (from original code)
LD C, $02 ; 0E 02
LD B, A ; 47 Retrieve stored bank
INC B ; 04 Increment it so as to target the 2nd application bank VIS206.63
OZ OS_Mpb ; E7 5D Bind the 2nd bank to segment 2
.rom_check
LD A, ($400B) ; 3A 0B 40 Read byte $0B in VIS206.62 from segment 1 (which starts at $4000)
CP '_' ; FE 5F Compare with '_'
JR NZ, badbank ; 20 07 If no match, relative jump to bad bank error
LD A, ($4012) ; 3A 12 40 Read byte $12 in VIS206.62 from segment 1
CP ' ' ; FE 20 Compare with ' '
JR Z, check_os_ver ; 28 04 If match, relative jump to check OS version
.bad_bank
LD A, RC_Bank ; 3E 34 Set error code for 'Bad Bank' fatal error
OZ OS_Bye ; E7 21 Exit application
.check_os_ver
LD A, FA_PTR ; 3E 01
LD DE, $0000 ; 11 00 00
LD IX, $FFFF ; DD 21 FF FF
OZ OS_Frm ; E7 48 Return OZ revision number in (C)
LD A, C ; 79
CP $05 ; FE 05 OZ 2.x - 3.x will return $03, OZ 4.0 returns $04
JP C, original_continue ; DA 73 40 Continue in segment 1 if OZ =< 4.0
LD A, RC_Quit ; 3E 67 Set error code for 'Request application to quit' fatal error
OZ OS_Bye ; E7 21 Exit application to prevent crash
.spare_bytes
NOP ; 00
NOP ; 00
NOP ; 00
NOP ; 00
.original_continue
CALL $49FC ; CD FC 49
Download Patch
This patch is published in the IPS format, popular for ROM patches.