Final Cartridge III Internals.txt

From ReplayResources
Jump to: navigation, search

Final Cartridge III Internals

text included from Funet Mirror at

Please check the text for credits!

NOTE that the document is not entirely correct - Check Final_Cartridge_III_Internals_Errata.txt

NOTE also that the Funet Url in the document has moved. See above for the correct link.

                         Final Cartridge III Internals

This is version 1.0 of this document, dated 19 Apr 98.
The author is Michael Steil <>.
This document may still contain some errors, I give no warranty that
the supplied information is correct. I appreciate corrections and additional
information on the topic described.
This document may be republished if it is free of charge if it is not altered
in any way. Otherwise my written permission is required. If you can use the
information supplied in this document in your own software, please refer to
this document in the credits of your software.
The latest version of this document can be downloaded using anonymous ftp

This document contains information about the BANKING functions of the FC3
and is supposed to help writers of C64 emulators to implement FC3 emulation.

Table of Contents
1.  Overview
2.  The FC3 ROM Management Register
2.1 Writing into the ROM Management Register
2.2 Reading from the ROM Management Register
3.  The FC3 ROM
3.1 Contents of the FC3 ROM
3.2 The ROM at $DE00 to $DFFF
4.  Practical use of FC3 banking
4.1 Behavior on RESET
4.2 Turning the ROM off
4.3 Turning the ROM on
4.4 Bank to bank jumps
5.  Model of FC3 used for this

1.  Overview
The Final Cartridge III has got 64 KB of ROM that contains all code and data
for its additional functions.

The C64 can only work with up to 16 KB of external ROM at a time, so the
FC3 ROM is divided into four parts, 16 KB each. These are shown in memory
at $8000 to $BFFF. The second 8 KB from $A000 to $BFFF logically fully
replace the built-in BASIC ROM and the first 8 KB behave exactly like normal
internal ROM.

Since ROM at $8000 would cause incompatibility of normal C64 programs
(this can be seen if you look at the Simons' BASIC cartridge, which has
permanent ROM at $8000), the ROM must not been visible by external

Therefore the FC3 ROM can be turned off and on by an additional register
mapped into the C64 I/O expansion area, at $DFFF. In this area, there are
also 512 bytes of ROM that manages turning off and on of the ROM at $8000.

The usual C64 BASIC ROM is not really replaced by the FC3 ROM, it remains
functional the whole time. But during the RESET routine, the FC3, who gains
control at a RESET, installs several vectors at $0300 so that some routines
of the operating system are replaced by superiour routines executed in the

These vectors all point into the ROM at the C64 I/O expansion area.
The code there sets up the FC3 ROM Managing Register to show the right
bank, calls the routine there, turns the ROM off again and continues
behaving just as the original routine, i.e. returning to the caller or
jumping into a loop in the original ROM.

2.  The FC3 ROM Management Register
2.1 Writing into the ROM Management Register
$DFFF: Bits #0-1    number of bank to show at $8000    $3
             2-3    unassigned                         $C
             4-5    what ROM to turn on/off
                    00 turn on all 16 KB of FC3 ROM    $00
                    01 start Freezer                   $10
                    10 turn on first 8 KB of FC3 ROM   $20
                    11 turn off FC3 ROM                $30
             6      unassigned                         $40
             7      =1 -> always show 16 KB of Bank 0  $80

Bits 2-3 and bit 6 have no function, although the FC3 ROM itself always
sets bits 2-3 to 0 and bit 6 to 1.

Bits 4-5 are show a special behavior if the bit combination 01 is stored
into them. This does not just change the ROM configuration, but also start
the built-in Freezer module immediately.

If bit 7 is 1, the other bits will have no function. Then the FC3 logic shows
the first FC3 ROM bank (16 KB) at $8000, just like the value $00 for $DFFF.
Obviously, this is needed during RESET. The FC3 logic sets bit 7 to 1 after
a RESET, so that the FC3 ROM gains control.

The normal value of $DFFF in BASIC is $40, all FC3 ROM is turned off for

2.2 Reading from the ROM Management Register
The ROM Management Register does not return the same values that were
written into it. It can only hold the values $00 and $FF, depending on the
last value written into it.
For written values of $00 to $7F the value returned is
  value returned = ((last value written-1) and 2)/2*$FF
(This is only valid for $00-$0F, $20-$4F and $60-$7F, since all other values
below $80 start the freezer and don't let the testing program read the value
of $DFFF.)
For written values of $80 to $FF, the value returned is always $FF (just as
the written value $00, which has the same effect!)

3.  The FC3 ROM
3.1 Contents of the FC3 ROM
The FC3 ROM is divided into 4 banks of 16 KB each, showing the following
  BANK 0   BASIC, Monitor
  BANK 1   Notepad, BASIC (Bar)
  BANK 2   Desktop, Freezer/Print
  BANK 3   Freezer
Bank 0 contains the modified RESET routine that gains control over the
computer during startup. Therefore it has the CBM80 signature at $8004.
It also contains all additional and modified BASIC commands as well as the
fast disk access routines and the built-in machine language monitor.
Bank 1 contains the Desktop Notepad program as well as the menu bar routines
for BASIC.
Bank 2 contains the whole Desktop with all its extensions, including
Calculator, Clock, Preferences, BASIC Preferences and Disk Operations
(Notepad is on bank 1), and the print menu and printing routines of the
Bank 3 contains the Freezer program and the compression routines.

3.2 The ROM at $DE00 to $DFFF
The 512 bytes of ROM at $DE00 to $DFFF cannot be turned off. This piece of
ROM is always visible.
It is mirrored from $1E00 to $1EFF of bank 0.

4.  Practical use of FC3 banking
4.1 Behavior on RESET
On a RESET, the FC3 logic sets bit 7 of the FC3 ROM Management Register to
1. This means that the cartridge turns on bank 0 of ROM, shown at $8000 to
$BFFF. The C64 KERNAL ROM sees the CBM80 signature at $8004 and jumps into
the FC3 ROM. The FC3 RESET routine copies its own vectors into the vector
table and jumps back to the normal C64 RESET routine at $E397, after turning
itself off.

4.2 Turning the ROM off
Turning itself off and continuing execution in normal ROM is achieved this
 .,80D5 A9 E3    LDA #$E3
 .,80D7 48       PHA
 .,80D8 A9 96    LDA #$96
 .,80DA 48       PHA
 .,80DB 4C 0F DE JMP $DE0F
The routine first pushes the value $E396 onto the stack and jumps to the
FC3 ROM in the C64 I/O expansion area.
The routine there looks like this:
 .,DE0F 48       PHA
 .,DE10 A9 70    LDA #$70
 .,DE12 D0 F4    BNE $DE08 (branch always)
 (continued there)
 .,DE0B 68       PLA
 .,DE0C 60       RTS
This piece of code turns off the FC3 ROM at $8000, preserving A.
Since the caller routine has pushed the value $E396 onto the stack,
the processor will continue executing code at $E397.

The ROM stays turned off until the KERNAL RESET routine reaches $A480.
The program uses the vector at $0302 to jump to the INPUT routine. This
jump is trapped by the FC3:

Table of vectors at $0300 occupied by the FC3:
 :0302   -> $DE41   INPUT
 :0304   -> $DF8D   convert BASIC line into tokens
 :0306   -> $DE49   LIST
 :0308   -> $DE73   get address of BASIC statement
 :030a   -> $DE4F   evaluate expression
 :0330   -> $DE21   LOAD
 :0332   -> $DE35   SAVE

4.3 Turning the ROM on
The routines in the $DE00 ROM all work much the same. They all set $DFFF, so
that the right ROM bank is shown at $8000 and execute the routine there.
As an example, this is where the INPUT vector points at:
 .,DE41  A5 01     LDA $01
 .,DE43  20 1A DE  JSR $DE1A
 .,DE46  4C FE 81  JMP $81FE
 (the subroutine)
 .,DE1A  09 07     ORA #$07
 .,DE1C  85 01     STA $01
 .,DE1E  D0 E5     BNE $DE05
 (continued there)
 .,DE05  48        PHA
 .,DE06  A9 40     LDA #$40
 .,DE08  8D FF DF  STA $DFFF
 .,DE0B  68        PLA
 .,DE0C  60        RTS
As you can see, this piece of code (that is highly optimizied for size!)
turns on all ROM's using the 6510 I/O Port, turns on bank 0 of the FC3 ROM at
$8000 and jumps there. The routine there must return using the same piece
of code as the routine shown above at $80D5.

4.4 Bank to bank jumps
If a routine situated in the FC3 ROM wants to jump to a routine on another
bank, it will do it like this: It has to push the address of the routine that
has to be called (minus 1) onto the stack first. Then it loads the value that
has to be stored in $DFFF (containing the number of the bank of the routine
that has to be called) into A and jumps to $DE01:
 .,DE01  8D FF DF  STA $DFFF
 .,DE04  60        RTS
This small routine stores the value into the FC3 ROM Management Register
and jumps to the routine whose address has been pushed on the stack, using
the RTS instruction. Note that that the second routine cannot jump back
using a RTS, but has to do the same to jump onto another bank as the first
routine has done before.

5.  Model of FC3 used for this
For the experiments, the following model of an FC3 was used:
   DESKTOP         V1.0
   Calculator      V1.2
   Clock           V1.0
   Notepad         V1.2
   Preferences     V1.2
   Disk Operations V1.1
   Basic           V1.2
   DATE: DEC 1988

   Bank 0   3d3b0cbb   
   Bank 1   439d1b97   
   Bank 2   033952e7   
   Bank 3   7e99ec76   

Help me make this document grow!                 Greetings to RRBYC,FTGLJRWUAH,M
End of "Final Cartridge III Internals",  (C)M. Steil <>