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]