Login
Plus/4 EncyclopediaFirstBackNextLast

ROM Banking
Category
Programming/Assembly

Topic
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:

AddressNameOperation
$FCF7Long fetchRead 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
$FCFALong jumpExecute 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


Keywords
banking 



Copyright © Plus/4 World Team, 2001-2024. Support Plus/4 World on Patreon