Programming/Assembly
The banking of RAM or ROM is determined by writing to the "shadow registers" at $FF3E/$FF3F.
$FF3E: writing any value to this address causes the ROM to be accessible. $FF3F: writing any value to this address causes the RAM to be accessible.
When ROM is accessible, the banking can be controlled as follows: LO ROM ($8000-$BFFF) and HI ROM ($C000-$FBFF) are determined by writing to the appropriate ROM LATCH address.
Bank | ROM latch | LO ROM | HI ROM | $00 | $FDD0 | BASIC | KERNAL | $01 | $FDD1 | (FUNCTION LO) | KERNAL | $02 | $FDD2 | CARTRIDGE 1 LO | KERNAL | $03 | $FDD3 | CARTRIDGE 2 LO | KERNAL | $04 | $FDD4 | BASIC | (FUNCTION HI) | $05 | $FDD5 | (FUNCTION LO) | (FUNCTION HI) | $06 | $FDD6 | CARTRIDGE 1 LO | (FUNCTION HI) | $07 | $FDD7 | CARTRIDGE 2 LO | (FUNCTION HI) | $08 | $FDD8 | BASIC | CARTRIDGE 1 HI | $09 | $FDD9 | (FUNCTION LO) | CARTRIDGE 1 HI | $0A | $FDDA | CARTRIDGE 1 LO | CARTRIDGE 1 HI | $0B | $FDDB | CARTRIDGE 2 LO | CARTRIDGE 1 HI | $0C | $FDDC | BASIC | CARTRIDGE 2 HI | $0D | $FDDD | (FUNCTION LO) | CARTRIDGE 2 HI | $0E | $FDDE | CARTRIDGE 1 LO | CARTRIDGE 2 HI | $0F | $FDDF | CARTRIDGE 2 LO | CARTRIDGE 2 HI |
Notes: * Function LO/HI marked with parentheses above are not available on C16. * The memory area between $FC00-$FFFF will always be the KERNAL ROM, regardless of the values written to $FDDx.
Due to this behavior the interrupt handler is always executed from the KERNAL ROM (assuming ROM is enabled by fantom register $FF3E). It pages in the default ROM bank ($00) and makes a jump to the vector at $0314. If You want to create your own interrupt handler You have to use that vector, using $FFFE is not possible. At the end of the interrupt You should jump to $FCBE as it restores the original ROM bank (using zero page variable $FB to make an indexed write $FDD0,X) so it's important to set $FB to your ROM bank too.
Example:
LDX #$nn for the values, see above table STX $FDD0,x STX $FB
The KERNAL provides the following helper functions for calling subroutines (long jump) and reading data (long fetch) from other ROM banks:
Address | Name | Operation |
---|
$FCF7 | Long fetch | Read data from other ROM bank Inputs: * X: bank to read from * A: bank to return * $BE: address to read from * Y: index to read from (LDA ($BE),Y) Outputs: * A: byte read from the other bank Registers overwritten: X | $FCFA | Long jump | Execute subroutine from other bank Inputs: * X: bank to read from * A: bank to return * $05F0: address of subroutine to execute * $05F2: value of A for subroutine call * $05F3: value of X for subroutine call * $05F4: status register for subroutine call * Y: index to read from (LDA ($BE),Y) Outputs: * $05F2: value of A at subroutine return * $05F3: value of X at subroutine return * $05F4: status register at subroutine return Registers overwritten: A, X |
banking |