Intercepting OSWRCH and calling into the ROM - 72 bytes (0.4%)
§1. OSWRCH routine to intercept VDU 22 and VDU 25.
The following code is copied into our ROM's private workspace at startup (the source of the memory copy is from .gxrOSWRCH up to the start of .notCompatible). This code is required to be in RAM in regular memory (not Sideways ROM) in order to intercept the regular OSWRCH vector. It detects both VDU 22 (PLOT) and VDU 25 (MODE). Executing from the private workspace, this code then selects the GXR ROM and calls into the ROM as needed (see .vdu22Or25EntryPoint). This is sometimes known as "trampoline" code. At the point it is copied into our private workspace, patches are applied to the code to insert the relevant data: * jump address of the previous OSWRCH vector address (used if not VDU 22/25), * set the private workspace page, * set the ROM number for this ROM.
.gxrOSWRCH = $8955 PHA Check for VDU 25 (PLOT) LDA .vduJumpVectorLow CMP #<.vdu25EntryPoint BEQ .continueTestForVDU25 if (VDU 25 found) then branch Check for VDU 22 (MODE) CMP #<.vdu22EntryPoint BEQ .continueTestForVDU22 if (VDU 22 found) then branch Pass on any other call to the original OSWRCH .chainToPreviousOSWRCHHandler = $8961 PLA .jmpOldWRCHPatch = * + 1 JMP $FFFF jump to the next old vector routine ***** VDU 25 ***** .continueTestForVDU25 = $8965 At this point we know the low bytes match, but check the high bytes to be sure LDA .vduJumpVectorHigh CMP #>.vdu25EntryPoint BNE .chainToPreviousOSWRCHHandler if (high bytes don't match) then branch This is a PLOT (the OS has decoded VDU 25 but not all its parameters yet) Change the vdu jump vector to point to our routine '.gxrVDU25EntryPoint' this means our routine will get called once all the PLOT parameters are known LDA #.gxrVDU25EntryPoint - .gxrOSWRCH STA .vduJumpVectorLow .ldaOurWRCHHighPatch = * + 1 LDA #$FF address patched into 'LDA #(our private workspace page)' STA .vduJumpVectorHigh Continue to regular OSWRCH routine BNE .chainToPreviousOSWRCHHandler ALWAYS branch ***** VDU 22 ***** .continueTestForVDU22 = $8978 LDA .vduJumpVectorHigh CMP #>.vdu22EntryPoint BNE .chainToPreviousOSWRCHHandler if (high bytes don't match) then branch This is a MODE change (VDU 22) This happens straight away as we have the only parameter already PLA .jsrOldWRCHPatch = * + 1 JSR $FFFF call the next old vector routine (change MODE) SEC BCS .callIntoROM ALWAYS branch VDU 25 detected, continue with carry clear... .gxrVDU25EntryPoint = $8986 CLC fall through...
§2. Select the GXR ROM and call into the ROM.
On Entry: carry set for VDU 22 (MODE) carry clear for VDU 25 (PLOT)
.callIntoROM = $8987 PHA } LDA .currentlySelectedROM } store A and previously selected ROM PHA } .ldaOurRomBankPatch = * + 1 LDA #$FF } make sure the GXR ROM is selected !if (MACHINE = BBC_B) | (MACHINE = BBC_B_PLUS) { STA .currentlySelectedROM STA .romSelectRegister } else if (MACHINE = ELECTRON) { JSR .selectRom } else { +unknown_machine } JSR .vdu22Or25EntryPoint call into the GXR ROM PLA restore previously selected ROM !if (MACHINE = BBC_B) | (MACHINE = BBC_B_PLUS) { STA .currentlySelectedROM STA .romSelectRegister } else if (MACHINE = ELECTRON) { JSR .selectRom } else { +unknown_machine } PLA restore A RTS [NOTE: end of code that is copied into our private workspace RAM]