Kernal 64 / 128
by Craig Taylor (ctalkobt@gmail.com)
Originally written for C= Hacking Issue #3
(c) 2006 Craig Taylor
============================================
+--------------+
| Introduction |
+--------------+
When Commodore introduced the PET ages ago before the Vic-20 and Commodore 64,
128 they set in the highest memory locations a series of jumps to other routines
so that users didn't need bother checking if any revisions had been made. They
were assured that the address they were jumping to, would indeed, be the address
that would print out a character or whatnot.
The KERNAL has grown since Commodore first introduced it, the C=128 KERNAL has
fifty-seven seperate routines which are available to programmers. These routines
handle functions relating to the serial devices (the bulk of them), the screen
and miscellanous system routines such as scanning the keyboard, updating and
reading the system clock (TI$).
+-------------------+
| Table of Routines |
+-------------------+
The following table lists the available routines, their function, address,
their name, and registers affected upon exit. In addation, on the left of each
line are the group that I have catagorized them under: Video(Vid), System(Sys),
and Serial(Ser).
--------+---------+---------+---------------------------------------+-----------
| |Registers| |Group
Address | NAME | A X Y F | Descritption |Vid Sys Ser
--------+---------+---------+---------------------------------------+-----------
FF47/128|SPINSPOUT| * | Initializes I/O for fast serial | ***
FF4A/128| CLOSEALL| * * * | Close all files on a device | ***
FF4D/128| C64MODE | | Switches to C=64 mode | ***
FF50/128| DMACALL | * * | Send DMA command to REU | ***
FF53/128| BOOTCALL| * * * | Attempts to run boot sector | *** ***
FF56/128| PHOENIX | * * * | Initalizes external/internal cartri. | ***
FF59/128| LKUPLA | * * * * | Looks up logical device # | *** ***
FF5C/128| LKUPSA | * * * * | Looks up for secondary address | *** ***
FF5F/128| SWAPPER | * * * | Switches betten 40 / 80 column screen |***
FF62/128| DLCHAR | * * * | Initializes 80 column character set |***
FF65/128| PFKEY | * * * * | Installs a function key definition | ***
FF68/128| SETBNK | | Sets bank for any I/O operations | *** ***
FF6B/128| GETCFG | * | Get MMU configuration for a given bank| ***
FF6E/128| JSRFAR | | Jumps to a subroutine in another bank | ***
FF71/128| JMPFAR | | Starts executing code in another bank | ***
FF74/128| INDFET | * * * | Execute a LDA(fetvec),Y from a bank | ***
FF77/128| INDSTA | * * | Stores a value indirectly in a bank | ***
FF7A/128| INDCMP | * * | Compares a value indirectly in a bank | ***
FF7D/128| PRIMM | | Outputs null-terminated string |*** ***
////////|/////////|/////////|///////////////////////////////////////|///////////
FF81 | CINT | * * * | Setup VIC,screen values, 8563... |***
FF84 | IOINIT | * * * | Initialize VIC,SID,8563,CIA for system|*** ***
FF87 | RAMTAS | * * * | Initialize ram. | ***
FF8D | VECTOR | * * | Reads or Writes to Kernal RAM Vectors | ***
FF90 | SETMSG | | Sets Kernal Messages On/Off. | ***
FF93 | SECND | * | Sends secondary address after LISTN | *** ***
FF96 | TKSA | * | Sends secondary address after TALK | *** ***
FF99 | MEMTOP | * * | Read or set the top of system RAM. | ***
FF9C | MEMBOT | * * | Read or set the bottom of system RAM. | ***
FF9F | KEY | | Scans Keyboard | ***
FFA2 | SETMO | | -- Unimplemented Subroutine in All -- | [N/A]
FFA5 | ACPTR | * | Grabs byte from current talker | *** ***
FFA8 | CIOUT | * | Output byte to current listener | *** ***
FFAB | UNTLK | * | Commands device to stop talking | *** ***
FFAE | UNLSN | * | Commands device to stop listening | *** ***
FFB1 | LISTN | * | Commands device to begin listening | *** ***
FFB4 | TALK | * | Commands device to begin talking | *** ***
FFB7 | READSS | * | Returns I/O status byte | ***
FFBA | SETLFS | | Sets logical #, device #, secondary # | ***
FFBD | SETNAM | | Sets pointer to filename. | ***
FFC0 | OPEN | * * * * | Opens up a logical file. | ***
FFC3 | CLOSE | * * * * | Closes a logical file. | ***
FFC6 | CHKIN | * * * * | Set input channel | ***
FFC9 | CHKOUT | * * * * | Set output channel | ***
FFCC | CLRCH | * * | Restore default channels | ***
FFCF | BASIN | * * | Input from channel | ***
FFD2 | BSOUT | * * | Output to channel (aka CHROUT) |*** ***
FFD5 | LOAD | * * * * | Load data from file | ***
FFD8 | SAVE | * * * * | Save data to file | ***
FFDB | SETTIM | | Sets internal (TI$) clock | ***
FFDE | RDTIM | * * * | Reads internal (TI$) clock | ***
FFE1 | STOP | * * | Scans and check for STOP key | ***
FFE4 | GETIN | * * * * | Reads buffered data from file | ***
FFE7 | CLALL | * * | Close all open files and channels | ***
FFEA | UDTIM | * * | Updates internal (TI$) clock | ***
FFED | SCRORG | * * * | Returns current window/screen size |***
FFF0 | PLOT | * * * | Read or set cursor position |***
FFF3 | IOBASE | * * | Read base of I/O block | ***
--------+---------+---------+---------------------------------------+-----------
+--------------------------+
| The Routines Themselves. |
+--------------------------+
A. Error handling
For the routines in the KERNAL that return status codes (indicated by the FL
status in the chart) the carry is set if there is an error. Otherwise, the
carry returned is clear. If the carry is set, the error code is returned in the
accumalator:
+-----------------------------------+
.A |Meaning | NOTE: Some of the I/O routines |
----+------------------------------ | indicate the error code via |
0 | Stop Key pressed | the READST routine when |
1 | Too Many Open Files | setting the carry. |
2 | File Already Open +------------------------------------
3 | File Not Open
4 | File Not Found
5 | Device Not Present
6 | File Was Not Opened As Input
7 | File Was Not Opened As Output
8 | File Name Not Present
9 | Illegal Device Number
41 | File Read Error
B. Device Numbers:
The following table lists the "standard" device numbers used by the C= Kernal.
+---------+----------------------------+
|Device # | Device Name |
+---------+----------------------------+
| 0 | Keyboard (standard input) |
| 1 | Cassette |
| 2 | RS-232 |
| 3 | Screen (standard output) |
| 4 - 30| Serial Bus Devices |
| 4-7 | Printers (typically)|
| 8-30| Disk Drives (typically)|
+---------+----------------------------+
C. Routine Descriptions.
Due to space limitations a fully-detailed, descriptive summary of the KERNAL
routines is not feasible. However, listed below is a description of what each
routine does, expected parameters and any notes on C=128/C=64 differences as
well as notes to clarify any possibly confusing details.
---------------------------------------------------------------------------
Routine : SPINSPOUT ** 128 ONLY **
Kernal Address: $FF47
Description : Setup CIA for BURT protocol.
Registers In : .C = 0 -> SPINP (input)
.C = 1 -> SPOUT (output)
Registers Out : .A destroyed
Memory Changed: CIA, MMU.
Routine : CLOSEALL ** 128 ONLY **
Kernal Address: $FF4A
Description : Close all files on a device.
Registers In : .A = device # (0-31)
Registers Out : .A, .X, .Y used.
Memory Changed: None.
Routine : C64MODE ** 128 ONLY **
Kernal Address: $FF4D
Description : Switches to C64 Mode
Registers In : None.
Registers Out : None.
Memory Changed: -ALL- This routine initializes and calls the C64 cold start
routine. There is no way to switch out of C64 mode once this
routine is entered.
Routine : DMACALL ** 128 ONLY **
Kernal Address: $FF50
Description : Perform DMA command (for REU)
Registers In : .X = Bank, .Y = DMA controller command
NOTE: REU registers must have been previously setup.
Registers Out : .A, .X used
Memory Changed: Dependenant upon REU registers, REU command.
Routine : BOOTCALL ** 128 ONLY **
Kernal Address: $FF53
Description : Attempts to load and execute boot sector from a drive.
Registers In : .A = drive # in ascii (usually '0' / $30)
.X = device #
Registers Out : .A, .X, .Y used. .C = 1 if I/O error.
Memory Changed: As per boot sector.
Routine : PHOENIX ** 128 ONLY **
Kernal Address: $FF56
Description : Initalizes external / internatal cartridges,check for disk boot
Registers In : None.
Registers Out : .A, .X, .Y used.
Memory Changed: Calls any auto-start catridges that are installed on the system
Routine : LKUPLA ** 128 ONLY **
Kernal Address: $FF59
Description : Search file tables for a given logical device #.
Registers In : .A = Logical Device #.
Registers Out : .C = 0 if found -> .A = Logical Device #,
.X = Logical File #,
.Y = Logical Secondary #.
.C =1 if not found.
Memory Changed: None.
Routine : LKUPSA ** 128 ONLY **
Kernal Address: $FF5C
Description : Search file tables for a given secondary address.
Registers In : .Y = Secondary address to search for.
Registers Out : As LKUPLA (see LKUPLA).
Memory Changed: None.
Routine : SWAPPER ** 128 ONLY **
Kernal Address: $FF5F
Description : Switches between 40 / 80 column screen.
Registers In : None.
Registers Out : .A, .X, .Y destroyed.
Memory Changed: Screen Editor Locations.
Routine : DLCHAR ** 128 ONLY **
Kernal Address: $FF62
Description : Initializes 80 column character set.
Registers In : None.
Registers Out : .A, .X, .Y destroyed.
Memory Changed: None.
Routine : PFKEY ** 128 ONLY **
Kernal Address: $FF65
Description : Installs a function key definition
Registers In : .A = pointer to Z-P address (3 bytes : address lo/hi/bank.)
.Y = length, .X = key # (9 = Shift RUN/STOP, 10 = HELP).
Registers Out : .C = 1 if No room, .C = 0 if successful.
.A, .X, .Y destroyed.
Memory Changed: Function Key Table modified.
Routine : SETBNK ** 128 ONLY **
Kernal Address: $FF68
Description : Sets bank for any future I/O operations
Registers In : .A = Memory Bank, .X = Bank where filename is.
Registers Out : None.
Memory Changed: None.
Routine : GETCFG ** 128 ONLY **
Kernal Address: $FF6B
Description : Get MMU configuration for a given bank.
Registers In : None.
Registers Out : None.
Memory Changed:
Routine : JSRFAR ** 128 ONLY **
Kernal Address: $FF6E
Description : Jumps to a subroutine in another bank.
Registers In : None. (See JMPFAR for mem locations IN)
Registers Out : None. (See JMPFAR for mem locations OUT)
Routine : JMPFAR ** 128 ONLY **
Kernal Address: $FF71
Description : Starts executing code in another bank.
Registers In : None.
Memory In : $02 - Bank (0-15)
$03 - PC high
$04 - PC lo
$05 - .S (Processor status)
$06 - .A
$07 - .X
$08 - .Y
Registers Out : None.
Memory Out : As memory in.
Routine : INDFET ** 128 ONLY **
Kernal Address: $FF74
Description : Execute a LDA(fetvec),Y from a bank.
Registers In : .A - pointer to Z-Page location holding address
.X - Bank (0-15), .Y - Index.
Registers Out : .A = data, .X - destroyed.
Memory Changed: None.
Routine : INDSTA ** 128 ONLY **
Kernal Address: $FF77
Description : Execute a STA(stavec),Y in a bank.
Registers In : .A - pointer to Z-Page location holding address
.X - Bank (0-15), .Y - Index.
Registers Out : .X - Destroyed.
Memory Changed: As per registers.
Routine : INDCMP ** 128 ONLY **
Kernal Address: $FF7A
Description : Executes a CMP(cmpvec),Y in a bank.
Registers In : .A = data, .X = Bank (0-15), .Y - Z-Page ptr.
Registers Out : .X destroyed, Flags set accordingly.
Memory Changed: None.
Routine : PRIMM ** 128 ONLY **
Kernal Address: $FF7D
Description : Prints null terminated string following JSR to current channel
Registers In : None.
Registers Out : None.
Memory Changed: Dependent upon current device.
Example :
[ . . . ]
JSR $FF7D ; JSR to primm, / print following string.
.ASC "Hi World!" ; String to print.
.BYT $00 ; IMPORTANT: Null Terminated.
[ . . . ]
---------------------------------------------------------------------------
Routine : CINT
Kernal Address: $FF81
Description : Setup VIC, screen values, (128: 8563)...
Registers In : None.
Registers Out : None.
Memory Changed: Screen Editor Locations.
Routine : IOINIT
Kernal Address: $FF84
Description : Initializes pertinant display and i/o devices
Registers In : C64: None. | C128: $0A04/bit 7
| 0 - Full Setup.
| 1 - Partial Setup. (no 8563 char)
Registers Out : .A, .X, .Y destroyed.
Memory Changed: CIA's, VIC, 8502 port, (C128: also optionally 8563).
Note : This routine automatically distinguishes a PAL system from a
NTSC system and sets PALCNT accordingly for use in the
time routines.
Routine : RAMTAS
Kernal Address: $FF87
Description : Clears Z-Page, Sets RS-232 buffers, top/bot Ram.
Registers In : None.
Registers Out : .A, .X, .Y destroyed.
Memory Changed: Z-Page, Rs-232 buffers, top/bot Ram ptrs
Routine : VECTOR
Kernal Address: $FF8D
Description : Copies / Stores KERNAL indirect RAM vectors.
Registers In : .C = 0 (Set KERNAL Vectors) | .C = 1 (Duplicate KERNAL vectors)
.XY = address of vectors | .XY = address of user vectors
Registers Out : .A, .Y destroyed | .A, .Y destroyed.
Memory Changed: KERNAL Vectors changed | Vectors written to .XY
Note : This routine is rarely used, usually the vectors are directly
changed themselves. The vectors, in order, are :
C128: IRQ,BRK,NMI,OPEN,CLOSE,CHKIN,CHKOUT,CLRCH,BASIN,BSOUT
STOP,GETIN,CLALL,EXMON (monitor),LOAD,SAVE
C64 : IRQ,BRK,NMI,OPEN,CLOSE,CHKIN,CHKOUT,CLRCH,BASIN,BSOUT
STOP,GETIN,CLALL,USRCMD (not used),LOAD,SAVE
Routine : SETMSG
Kernal Address: $FF90
Description : Set control of KERNAL control and error messages.
Registers In : .A bit 7 = KERNAL Control Messages (1 = on)
bit 6 = KERNAL Error Messages (1 = on)
Registers Out : None.
Note : KERNAL Control messages are those defined as Loading, Found etc
... KERNAL Error messages are I/O ERROR # messages which are
listed as follows:
Routine : SECND
Kernal Address: $FF93
Description : Sends secondary address to device after a LISTN
Registers In : .A = secondary address
Registers Out : .A used.
Memory Changed: None.
Note : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
Routine : TKSA
Kernal Address: $FF96
Description : Sends secondary address to device after TALK
Registers In : .A = secondary address.
Registers Out : .A used.
Memory Changed: None.
Note : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
Routine : MEMTOP
Kernal Address: $FF99
Description : Read or Set top of System Ram
Registers In : .C = 1 (Read MemTop) | .C = 0 (Set MemTop)
| .XY = top of memory
Registers Out : .XY = top of memory | None.
Memory Changed: None. | Top of memory changed.
Note : On the C=128, this routine refers to the top of BANK 0 RAM, not
BANK 1 RAM.
Routine : MEMBOT
Kernal Address: $FF9C
Description : Read or Set bottom of System Ram
Registers In : .C = 1 (Read MemBot) | .C = 0 (Set MemBot)
| .XY = bottom of memory.
Registers Out : .XY = bottom of memory | None.
Memory Changed: None. | Bottom of Memory changed.
Note : On the C=128, this routine refers to the bottom of BANK 0 RAM,
not, BANK 1 RAM.
Routine : KEY
Kernal Address: $FF9F
Description : Scans Keyboard
Registers In : None.
Registers Out : None.
Memory Changed: Relevant System Keyboard Values
Routine : SETMO
Kernal Address: $FFA2
Description : This is a routine who's code never made it into any versions
of the KERNAL on the C64, Vic-20 and C128. Thus it is of no
pratical use.
Routine : ACPTR
Kernal Address: $FFA5
Description : Get byte from current talker.
Registers In : None.
Registers Out : .A = data byte.
Memory Changed: None.
Note : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
Routine : CIOUT
Kernal Address: $FFA8
Description : Output byte to current listener.
Registers In : .A = byte.
Registers Out : .A used.
Memory Changed: None.
Note : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
Routine : UNTLK
Kernal Address: $FFAB
Description : Commands current TALK device to stop TALKING.
Registers In : None.
Registers Out : .A used.
Memory Changed: None.
Note : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
Routine : UNLSN
Kernal Address: $FFAE
Description : Commands current listening device to stop listening.
Registers In : None.
Registers Out : .A used.
Memory Changed: None.
Note : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
Routine : LISTN
Kernal Address: $FFB1
Description : Commands device to begin listening.
Registers In : .A = device #.
Registers Out : .A used.
Note : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
Routine : TALK
Kernal Address: $FFB4
Description : Commands device to begin talking.
Registers In : .A = device #.
Registers Out : .A used.
Memory Changed: None.
Note : Low level serial I/O - recommended use OPEN,CLOSE,CHROUT etc..
Routine : READSS
Kernal Address: $FFB7
Description : Return I/O status byte.
Registers In : None.
Registers Out : .A = status byte. (see section on ERROR messages).
Memory Changed: None.
Routine : SETLFS
Kernal Address: $FFBA
Description : Set logical file #, device #, secondary # for I/O.
Registers In : .A = logical file #, .X = device #, .Y = secondary #
Registers Out : None.
Memory Changed: None.
Routine : SETNAM
Kernal Address: $FFBD
Description : Sets pointer to filename in preperation for OPEN.
Registers In : .A = string length, .XY = string address.
Registers Out : None.
Memory Changed: None.
Note : To specify _no_ filename specify a length of 0.
Routine : OPEN
Kernal Address: $FFC0
Description : Open up file that has been setup by SETNAM,SETLFS
Registers In : None.
Registers Out : .A = error code, .X,.Y destroyed.
.C = 1 if error.
Memory Changed: None.
Routine : CLOSE
Kernal Address: $FFC3
Description : Close a logical file.
Registers In : .A = logical file #.
Registers Out : .A = error code, .X,.Y destroyed.
.C = 1 if error
Memory Changed: None.
Routine : CHKIN
Kernal Address: $FFC6
Description : Sets input channel.
Registers In : .X = logical file #.
Registers Out : .A = error code, .X,.Y destroyed.
.C = 1 if error
Memory Changed: None.
Routine : CHKOUT
Kernal Address: $FFC9
Description : Sets output channel.
Registers In : .X = logical file #.
Registers Out : .A = error code, .X,.Y destroyed.
.C = 1 if error
Memory Changed: None.
Routine : CLRCH
Kernal Address: $FFCC
Description : Restore default input and output channels.
Registers In : None.
Registers Out : .A, .X used.
Memory Changed: None.
Routine : BASIN
Kernal Address: $FFCF
Description : Read character from current input channel.
Cassette - Returned one character a time from cassette buffer.
Rs-232 - Return one character at a time, waiting until
character is ready.
Serial - Returned one character at time, waiting if nessc.
Screen - Read from current cursor position.
Keyboard - Read characters as a string, then return them
individually upon each call until all characters
have been passed ($0d is the EOL).
Registers In : None.
Registers Out : .A = character or error code, .C = 1 if error.
Memory Changed: None.
Routine : BSOUT aka CHROUT
Kernal Address: $FFD2
Description : Output byte to current channel
Registers In : .A = Byte
Registers Out : .C = 1 if ERROR (examine READST)
Memory Changed: Dependent upon current device.
Routine : LOAD
Kernal Address: $FFD5
Description : Loads file into memory (setup via SETLFS,SETNAM)..
Registers In : .A = 0 - Load, Non-0 = Verify
.XY = load address (if secondary address = 0)
Registers Out : .A = error code .C = 1 if error.
.XY = ending address
Memory Changed: As per registers / data file.
Routine : SAVE
Kernal Address: $FFD8
Description : Save section of memory to a file.
Registers In : .A = Z-page ptr to start adress
.XY = end address
Registers Out : .A = error code, .C = 1 if error.
.XY = used.
Memory Changed: None.
Routine : SETTIM
Kernal Address: $FFDB
Description : Set internal clock (TI$).
Registers In : .AXY - Clock value in jiffies (1/60 secs).
Registers Out : None.
Memory Changed: Relevant system time locations set.
Routine : RDTIM
Kernal Address: $FFDE
Description : Reads internal clock (TI$)
Registers In : None.
Registers Out : .AXY - Clock value in jiffies (1/60 secs).
Memory Changed: None.
Routine : STOP
Kernal Address: FFE1
Description : Scans STOP key.
Registers In : None.
Registers Out : .A = last keyboard row, .X = destroyed (if stop key)
Memory Changed: None.
Note : The last keyboard row is as follows:
.A -> | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
KEY: |STOP |Q |C= |SPACE|2 |CTRL |<- |1
Routine : GETIN
Kernal Address: $FFE4
Description : Read buffered data from file.
Keyboard - Read from keyboard buffer, else return null ($00).
Rs-232 - Read from Rs-232 buffer, else null is returned.
Serial - See BASIN
Cassette - See BASIN
Screen - See BASIN
Registers In : None.
Registers Out : .A = character, .C = 1 if error.
.XY = used.
Memory Changed: None.
Routine : CLALL
Kernal Address: $FFE7
Description : Close all open files and channels.
Registers In : None.
Registers Out : .AX used.
Memory Changed: None.
Note : This routine does not _actually_ close the files, rather it
removes their prescense from the file tables held in memory.
It's recommended to use close to close files instead of using
this routine.
Routine : UDTIME
Kernal Address: $FFEA
Description : Update internal (TI$) clock by 1 jiffie (1/60 sec).
Registers In : None.
Registers Out : .A,.X destroyed.
Memory Changed: Relevant system time locations changed.
Routine : SCRORG
Kernal Address: $FFED
Description : Returns current window/screen size
Registers In : None.
Registers Out : .X - Window Row Max
.Y - Window Col Max
.A - Screen Col Max (128 only, 64 unchanged)
Memory Changed: None
Routine : PLOT
Kernal Address: $FFF0
Description : Read or set cursor position.
Registers In : .C = 1 (Read) | .C = 0 (Set)
None. | .X = Col
| .Y = Row
Registers Out : .C = 1 (Read) | .C = 0 (Set)
.X = Current Col | None.
.Y = Current Row |
Memory Changed: None | Screen Editor Locations.
Routine : IOBASE
Kernal Address: $FFF3
Description : Returns base of I/O Block
Registers In : None.
Registers Out : .XY = address of I/O block ($D000)
Memory Changed: Screen Editor Locations.