This the multi-page printable view of this section.Click here to print.
Notes about the C64 operating system & memory
CC BY-SA
Peter Mount, Area51.dev & Contributors
Notes about the C64 operating system & memory
Title | Commodore C64 Kernal |
---|---|
Subtitle | Notes about the C64 operating system & memory |
Author | Peter Mount, Area51.dev & Contributors |
Copyright | CC BY-SA |
This license is acceptable for Free Cultural Works.
The licensor cannot revoke these freedoms as long as you follow the license terms.
You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation.
No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material.
You can read the full license here: https://creativecommons.org/licenses/by-sa/4.0/
The following table shows the memory map for the Commodore 64.
Docs | Address | Normal Use | Alternate Use | All RAM mode | ROM Cartridge |
---|---|---|---|---|---|
Page 00 | 0000 | 6510 IO DDR | |||
0001 | 6510 IO Port | ||||
0002 | Free for application use | ||||
0003 | Kernal & BASIC Zero Page | ||||
00FB | User Zero Page | ||||
00FF | BASIC Temp Area | ||||
0100 | Processor Stack | ||||
Page 02 | 0200 | BASIC editor input buffer | |||
0259 | Kernal file tables | ||||
0277 | Kernal Workspace | ||||
02A7 | Free for application use | ||||
Page 03 | 0300 | BASIC workspace | |||
0314 | Kernal Vector table | ||||
0334 | Application Vector table | ||||
033C | Cassette I/O Buffer | ||||
03FC | Free for application use | ||||
0400 | Default screen | 1K Free if screen is mapped elsewhere | |||
0800 | 38K Application memory | 30K Application memory | |||
8000 | Cart ROM Low | ||||
A000 | BASIC ROM | 8K RAM | Cart ROM High | ||
C000 | 4K RAM | ||||
Page D0 | D000 | VIC-II Registers | Character ROM | 4K RAM | As other columns |
D400 | SID Registers | ||||
Page D8 | D800 | Color RAM | |||
Page DC | DC00 | CIA 1 | |||
Page DD | DD00 | CIA 2 | |||
DE00 | Expansion I/O | ||||
DF00 | |||||
Kernal | E000 | KERNAL ROM | 8K RAM | Cart ROM High | |
F000 |
This is useful with BitMap screen mode as you can map the screen beneath the KERNAL rom as the VIC-II chip always sees RAM.
Address | Len | Name | Description | Default | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0000 | 1 | D6510 | 6510 On-Chip I/O DATA Direction Register
| 0xEF | ||||||||||||||||
0001 | 1 | R6510 | 6510 On-Chip I/O Port
| 0x37 | ||||||||||||||||
0002 | 1 | Unused | ||||||||||||||||||
0003 | 2 | ADRAY1 | Vector to routine to convert Number from Floating Point to Signed Integer | 0xB1AA | ||||||||||||||||
0005 | 2 | ADRAY2 | Vector to routine to convert Number from Integer to Floating Point | 0xB391 | ||||||||||||||||
0007 | Used by BASIC and/or Kernal | |||||||||||||||||||
000A | 1 | VERCK | Flag: LOAD or VERIFY
| |||||||||||||||||
000B | Used by BASIC and/or Kernal | |||||||||||||||||||
002B | 2 | TXTTAB | Pointer to start of BASIC program text | 0x0801 | ||||||||||||||||
002D | 2 | VARTAB | Pointer to start of BASIC Variable storage area | End of program +1 | ||||||||||||||||
002F | 2 | ARYTAB | Pointer to start of array variable area | |||||||||||||||||
0031 | 2 | STREND | End of Basic array storage (+1), Start of free ram | |||||||||||||||||
0033 | 2 | FRETOP | Pointer to bottom of string text area Grows downwards from end of BASIC area | |||||||||||||||||
0035 | 2 | FRESPC | Temp pointer for strings | |||||||||||||||||
0037 | 2 | BASMEMSIZ | Highest address used by basic RS232 device can reduce this by 512 bytes for it's buffers | 0x9FFF | ||||||||||||||||
0039 | Used by BASIC | |||||||||||||||||||
0090 | Used by Kernal | |||||||||||||||||||
00CC | 1 | BLNSW | Cursor Blink Enable
| |||||||||||||||||
00CD | Used by Kernal | |||||||||||||||||||
00F7 | 2 | RIBUF | RS232 Input Buffer Pointer 00xx for no buffer, allocate on input, any other value buffer exists | |||||||||||||||||
00F9 | 2 | ROBUF | RS232 Output Buffer Pointer 00xx for no buffer, allocate on output, any other value buffer exists | |||||||||||||||||
00FB | 4 | FREKZP | 4 free bytes of Zero Page for User Programs Guaranteed BASIC will not use these 4 bytes | |||||||||||||||||
00FF | 12 | BASZPT | BASIC temp data area for floating point to ASCII conversion Runs into start of page 1, free for use if conversions not needed |
The C64 uses the 6510 Microprocessor, a variant of the 6502. The main difference is that this Microprocessor contains a built-in 8-bit I/O port, with 6 pins exposed on the 6510. This port is mapped into memory at addresses 0000 & 0001.
Address | Len | Name | Description | Default | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0200 | 89 | BUF | BASIC Line Editor Input Buffer | |||||||||||||||||||
0259 | Kernal File Tables | |||||||||||||||||||||
0259 | 10 | LAT | Active logical file number table | |||||||||||||||||||
0263 | 10 | FAT | Device number for each logical file | |||||||||||||||||||
026D | 10 | SAT | Secondary address for each logical file | |||||||||||||||||||
0277 | 10 | KEYD | Keyboard buffer | |||||||||||||||||||
0281 | 2 | MEMSTR | Start of Memory pointer | 0x0800 | ||||||||||||||||||
0283 | 2 | MEMSIZ | End of Memory pointer Usually this is the first byte of the BASIC ROM | 0xA000 | ||||||||||||||||||
0286 | Screen workspace | |||||||||||||||||||||
0286 | 1 | COLOR | Current Foreground text colour | |||||||||||||||||||
0287 | 1 | GDCOL | Colour of character under Cursor | |||||||||||||||||||
0288 | 1 | HIBASE | Page of Screen Memory | 0x04 | ||||||||||||||||||
0289 | Keyboard workspace | |||||||||||||||||||||
0289 | 1 | XMAX | Max length of keyboard buffer
| |||||||||||||||||||
028A | 1 | RPTFLG | Which keys will repeat
| |||||||||||||||||||
028D | 1 | SHFLAG | Shift/Ctrl/Commodore key pressed
| |||||||||||||||||||
028E | 1 | LSTSHF | Last value of Shift/Ctrl/Commodore key pressed Used with SHFLAG to debounce those keys. Values match those for SHFLAG | |||||||||||||||||||
0291 | 1 | MODE | Shift/Commodore switch Enables/Disables character switching when Shift & Commodore keys are pressed
| |||||||||||||||||||
0292 | 1 | AUTODN | Screen scrolling enabled 0 enables scrolling, any other value disables scrolling | |||||||||||||||||||
0293 | Mock 6551 RS-232 | |||||||||||||||||||||
0293 | 1 | M51CTR | Mock 6551 RS-232 Control Register
| |||||||||||||||||||
0294 | 1 | M51CDR | Mock 6551 RS-232 Command Register
| |||||||||||||||||||
0295 | 2 | M51AJB | Mock 6551 RS-232 Nonstandard Bit Timing Not actually used by Kernal but present for 6551 UART emulation | |||||||||||||||||||
0297 | 1 | M51STAT | Mock 6551 RS-232 Status Register
| |||||||||||||||||||
0298 | 3 | Used by Kernal for RS-232 | ||||||||||||||||||||
029B | RS-232 Buffers | |||||||||||||||||||||
029B | 1 | RIDBE | RS-232 Index to end of receive buffer | |||||||||||||||||||
029C | 1 | RIDBS | RS-232 Index to start of receive buffer | |||||||||||||||||||
029D | 1 | RODBE | RS-232 Index to end of transmit buffer | |||||||||||||||||||
029E | 1 | RODBS | RS-232 Index to start of transmit buffer | |||||||||||||||||||
02A1 | 1 | ENABL | RS-232 Interrupts Enabled
| |||||||||||||||||||
02A2 | Used by Kernal | |||||||||||||||||||||
02A7 | 89 | Unused, available for application use |
Address | Len | Name | Description | Default |
---|---|---|---|---|
0300 | 12 | BASIC Indirect vector table | ||
030C | 4 | Storage for registers with BASIC SYS call 1 byte each for A, X, Y & Status in that order | ||
0310 | 3 | USRPOK | Jump instruction for BASIC USR() function Actual JMP instruction so first byte MUST be 0x4C | 0x4c |
0311 | 2 | USRADD | Address of USR() function This is the address used by USR() when it calls USRPOK | |
0313 | 1 | Unused | ||
0314 | 2 | CINV | IRQ Interrupt Routine Vector | 0xEA31 |
0316 | 2 | CBNV | BRK Interrupt Routine Vector | 0xFE66 |
0318 | 2 | NMINV | NMI Interrupt Routine Vector | 0xFE47 |
031A | Kernal Indirect Vectors | |||
031A | 2 | IOPEN | Kernal OPEN Vector | 0xFE4A |
031C | 2 | ICLOSE | Kernal close Vector | 0xF291 |
031e | 2 | ICHKIN | Kernal CHKIN Vector | 0xF20E |
0320 | 2 | ICKOUT | Kernal CKOUT Vector | 0xF250 |
0322 | 2 | ICLRCH | Kernal CLRCHN Vector | 0xF333 |
0324 | 2 | IBASIN | Kernal CHRIN Vector | 0xF157 |
0326 | 2 | IBSOUT | Kernal CHROUT Vector | 0xF1CA |
0328 | 2 | ISTOP | Kernal STOP Vector | 0xF6ED |
032A | 2 | IGETIN | Kernal GETIN Vector | 0xF13E |
032C | 2 | ICLALL | Kernal CLALL Vector | 0xF32F |
032E | 2 | USRCMD | User-Defined Command Vector Unused on C64, holdover from the PET. | 0xFE66 |
0330 | 2 | ILOAD | Kernal LOAD Vector | 0xF49E |
0332 | 2 | ISAVE | Kernal SAVE Vector | 0xF5DD |
0334 | 8 | Unused, space for 4 user vectors | ||
033C | 192 | TBUFFR | Cassette I/O Buffer | |
03FC | 4 | Unused |
Address | Name | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | Description |
---|---|---|---|---|---|---|---|---|---|---|
D000 | VIC2M0X | M0X | X Coordinate Sprite 0 | |||||||
D001 | VIC2M0Y | M0Y | Y Coordinate Sprite 0 | |||||||
D002 | VIC2M1X | M1X | X Coordinate Sprite 1 | |||||||
D003 | VIC2M1Y | M1Y | Y Coordinate Sprite 1 | |||||||
D004 | VIC2M2X | M2X | X Coordinate Sprite 2 | |||||||
D005 | VIC2M2Y | M2Y | Y Coordinate Sprite 2 | |||||||
D006 | VIC2M3X | M3X | X Coordinate Sprite 3 | |||||||
D007 | VIC2M3Y | M3Y | Y Coordinate Sprite 3 | |||||||
D008 | VIC2M4X | M4X | X Coordinate Sprite 4 | |||||||
D009 | VIC2M4Y | M4Y | Y Coordinate Sprite 4 | |||||||
D00A | VIC2M5X | M5X | X Coordinate Sprite 5 | |||||||
D05B | VIC2M5Y | M5Y | Y Coordinate Sprite 5 | |||||||
D00C | VIC2M6X | M6X | X Coordinate Sprite 6 | |||||||
D00D | VIC2M6Y | M6Y | Y Coordinate Sprite 6 | |||||||
D00E | VIC2M7X | M7X | X Coordinate Sprite 7 | |||||||
D00F | VIC2M7Y | M7Y | Y Coordinate Sprite 7 | |||||||
D010 | VIC2MNX | M7X8 | M6X8 | M5X8 | M4X8 | M3X8 | M2X8 | M1X8 | M0X8 | Bit 8 of X coordinates |
D011 | VIC2CR1 | RST8[1] | ECM | BMM | DEN | RSEL | YSCROLL | Control register 1 | ||
D012 | VIC2RASTER | RASTER[1] | Raster counter | |||||||
D013 | VIC2LPX | LPX | Light pen X | |||||||
D014 | VIC2LPY | LPY | Light pen Y | |||||||
D015 | VIC2SPE | M7E | M6E | M5E | M4E | M3E | M2E | M1E | M0E | Sprite Enabled |
D016 | VIC2CR2 | RES[3] | MCM | CSEL | XSCROLL | Control register 2 | ||||
D017 | VIC2SPYE | M7YE | M6YE | M5YE | M4YE | M3YE | M2YE | M1YE | M0YE | Sprite Y expansion |
D018 | VIC2MPTR | VM13 | VM12 | VM11 | VM10 | CB13 | CB12 | CB11 | Memory pointers | |
D019 | VIC2INTR | IRQ | ILP | IMMC | IMBC | IRST | Interrupt Register | |||
D01A | VIC2INTE | IRQ | ELP | EMMC | EMBC | ERST | Interrupt Enabled | |||
D01B | VIC2SPDP | M7DP | M6DP | M5DP | M4DP | M3DP | M2DP | M1DP | M0DP | Sprite data priority |
D01C | VIC2SPMC | M7MC | M6MC | M5MC | M4MC | M3MC | M2MC | M1MC | M0MC | Sprite multicolour |
D01D | VIC2SPXE | M7XE | M6XE | M5XE | M4XE | M3XE | M2XE | M1XE | M0XE | Sprite X expansion |
D01E | VIC2SPSPCOL | M7M | M6M | M5M | M4M | M3M | M2M | M1M | M0M | Sprite-Sprite collision[2] |
D01F | VIC2SPDCOL | M7D | M6D | M5D | M4D | M3D | M2D | M1D | M0D | Sprite data collision[2] |
D020 | VIC2BORDER | EC | Border colour | |||||||
D021 | VIC2B0C | B0C | Background colour 0 | |||||||
D022 | VIC2B1C | B1C | Background colour 1 | |||||||
D023 | VIC2B2C | B2C | Background colour 2 | |||||||
D024 | VIC2B3C | B3C | Background colour 3 | |||||||
D025 | VIC2SPMM0 | MM0 | Sprite multicolour 0 | |||||||
D026 | VIC2SPMM1 | MM1 | Sprite multicolour 1 | |||||||
D027 | VIC2SPCOL0 | M0C | Sprite 0 colour | |||||||
D028 | VIC2SPCOL1 | M1C | Sprite 1 colour | |||||||
D029 | VIC2SPCOL2 | M2C | Sprite 2 colour | |||||||
D02A | VIC2SPCOL3 | M3C | Sprite 3 colour | |||||||
D02B | VIC2SPCOL4 | M4C | Sprite 4 colour | |||||||
D02C | VIC2SPCOL5 | M5C | Sprite 5 colour | |||||||
D02D | VIC2SPCOL6 | M6C | Sprite 6 colour | |||||||
D02E | VIC2SPCOL7 | M7C | Sprite 7 colour | |||||||
D02E | 0xFF on read, write ignored | Unused | ||||||||
D02F | 0xFF on read, write ignored | Unused | ||||||||
D030 | 0xFF on read, write ignored | Unused | ||||||||
D031 | 0xFF on read, write ignored | Unused | ||||||||
D032 | 0xFF on read, write ignored | Unused | ||||||||
D033 | 0xFF on read, write ignored | Unused | ||||||||
D034 | 0xFF on read, write ignored | Unused | ||||||||
D035 | 0xFF on read, write ignored | Unused | ||||||||
D036 | 0xFF on read, write ignored | Unused | ||||||||
D037 | 0xFF on read, write ignored | Unused | ||||||||
D038 | 0xFF on read, write ignored | Unused | ||||||||
D039 | 0xFF on read, write ignored | Unused | ||||||||
D03A | 0xFF on read, write ignored | Unused | ||||||||
D03B | 0xFF on read, write ignored | Unused | ||||||||
D03C | 0xFF on read, write ignored | Unused | ||||||||
D03D | 0xFF on read, write ignored | Unused | ||||||||
D03E | 0xFF on read, write ignored | Unused | ||||||||
D03F | 0xFF on read, write ignored | Unused |
The VIC-II chip has 64 addressable registers. In the C64 memory map it is mapped to the range 0xD000…0xD3FF with it's registers repeated every 64 bytes.
This means that the following address ranges match those of the first 64 bytes at 0xD000…0xD03F:
Address Range | Equivalent | |
---|---|---|
0xD040 | 0xD07F | Same as 0xD000…0xD03F |
0xD080 | 0xD0BF | Same as 0xD000…0xD03F |
0xD0C0 | 0xD0FF | Same as 0xD000…0xD03F |
0xD100 | 0xD13F | Same as 0xD000…0xD03F |
0xD140 | 0xD17F | Same as 0xD000…0xD03F |
0xD180 | 0xD1BF | Same as 0xD000…0xD03F |
0xD1C0 | 0xD1FF | Same as 0xD000…0xD03F |
0xD200 | 0xD23F | Same as 0xD000…0xD03F |
0xD240 | 0xD27F | Same as 0xD000…0xD03F |
0xD280 | 0xD2BF | Same as 0xD000…0xD03F |
0xD2C0 | 0xD2FF | Same as 0xD000…0xD03F |
0xD300 | 0xD33F | Same as 0xD000…0xD03F |
0xD340 | 0xD37F | Same as 0xD000…0xD03F |
0xD380 | 0xD3BF | Same as 0xD000…0xD03F |
0xD3C0 | 0xD3FF | Same as 0xD000…0xD03F |
Address | Name | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | Description |
---|---|---|---|---|---|---|---|---|---|---|
D400 | SID1FRELOW | FRE1LOW | Frequency voice 1 low byte | |||||||
D401 | SID1FREHIGH | FRE1HIGH | Frequency voice 1 high byte | |||||||
D402 | SID1PWDCLOW | PWDC1LOW | Pulse wave duty cycle voice 1 low byte | |||||||
D403 | SID1PWDCHIGH | PWDC1HIGH | Pulse wave duty cycle voice 1 high byte | |||||||
D404 | SID1CR | noise | pulse | sawtooth | triangle | test | ringmod V3 | synth V3 | gate | Control Register voice 1 |
Address | Len | Name | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | Description |
---|---|---|---|---|---|---|---|---|---|---|---|
D800 | 1000 | COLMEM | Not Connected | Colour | Colour Memory | ||||||
D8E8 | 24 | Not Connected | Unused | Unused |
For each character in every row (40 chars per row; 0-39) and column (25 columns; 0-24) one of 16 colors can be assigned. The color values 0-15 are only used in the lower nibbles. The upper nibbles are undefined and are purely random values.
The colour memory is provided by an MM2114N-3 4Kb (1024x4) static RAM chip.
As this chip only provides 4 bits, the upper nibble is random as it's not connected to anything. It is separate from the onboard 64K RAM
Address | Name | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | Description |
---|---|---|---|---|---|---|---|---|---|---|
DC00 | CIA1PRA | KM7 PAD | KM6 PAD | KM5 | KM4 J2FB LPEN | KM3 J2Dn | KM2 J2Up | KM1 J2Rt | KM0 J2Lt | Data Port A[1,2,3] |
DC01 | CIA1PRB | KM7 TIMB | KM6 TIMA | KM5 | KM4 J1FB LPEN | KM3 J1Dn | KM2 J1Up | KM1 J1Rt | KM0 J1Lt | Data Port B[1,4] |
DC02 | CIA1DDRA | DDA7 | DDA6 | DDA5 | DDA4 | DDA3 | DDA2 | DDA1 | DDA0 | Data Direction Port A |
DC03 | CIA1DDRB | DDB7 | DDB6 | DDB5 | DDB4 | DDB3 | DDB2 | DDB1 | DDB0 | Data Direction Port B |
DC04 | CIA1TIMAL | TIMAL | Timer A Low byte | |||||||
DC05 | CIA1TIMAH | TIMAH | Timer A High byte | |||||||
DC06 | CIA1TIMBL | TIMBL | Timer B Low byte | |||||||
DC07 | CIA1TIMBH | TIMBH | Timer B High byte | |||||||
DC08 | CIA1RTCT | RTCT | Real time clock 1/10s | |||||||
DC09 | CIA1RTCS | RTCS | Real time clock seconds | |||||||
DC0A | CIA1RTCM | RTCM | Real time clock minutes | |||||||
DC0B | CIA1RTCH | RTCH | Real time clock hours | |||||||
DC0C | CIA1SR | SR | Shift register | |||||||
DC0D | CIA1ICS | IRQ Source | Always 0 Unused | IRQ Flag IntRel | SDR IntRel | Alarm IntRel | UTB IntRel | UTA IntRel | Interrupt Control & Status Read top, Write bottom | |
DC0E | CIA1CTA | RTC[5] | SRC[6] | TSRC[7] | Load[8] | RES[9] | OVFL[10] | UNFL1[11] | START | Control Timer A |
DC0F | CIA1CTB | TCOUNT[13] | Load[8] | RES[9] | OVFL[10] | UNFL2[12] | START | Control Timer B |
CIA1 is mapped to addresses 0xDCxx but only occupies 16 bytes. Referencing any address from 0xDC1x…0xDCFx will mirror those at 0xDC0x.
Address | Name | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | Description |
---|---|---|---|---|---|---|---|---|---|---|
DD00 | CIA2PRA | SBDI | SBCI | SBDO | SBCO | SBAO | TXD/PA2 | VICMEM[] | Data Port A[1,2,3] | |
DD01 | CIA2PRB | PB7 DSR | PB6 CTS | PB5 UPJ | PB4 DCD | PB3 RI | PB2 DTR | PB1 RTS | PB0 RXD | User Port PB0-7[4] |
DD02 | CIA2DDRA | DDA7 | DDA6 | DDA5 | DDA4 | DDA3 | DDA2 | DDA1 | DDA0 | Data Direction Port A |
DD03 | CIA2DDRB | DDB7 | DDB6 | DDB5 | DDB4 | DDB3 | DDB2 | DDB1 | DDB0 | Data Direction Port B |
DD04 | CIA2TIMAL | TIMAL | Timer A Low byte | |||||||
DD05 | CIA2TIMAH | TIMAH | Timer A High byte | |||||||
DD06 | CIA2TIMBL | TIMBL | Timer B Low byte | |||||||
DD07 | CIA2TIMBH | TIMBH | Timer B High byte | |||||||
DD08 | CIA2RTCT | RTCT | Real time clock 1/10s | |||||||
DD09 | CIA2RTCS | RTCS | Real time clock seconds | |||||||
DD0A | CIA2RTCM | RTCM | Real time clock minutes | |||||||
DD0B | CIA2RTCH | RTCH | Real time clock hours | |||||||
DD0C | CIA2SR | SR | Shift register | |||||||
DD0D | CIA2ICS | NMI[14] Source | Always 0 Unused | NMI Flag[15] IntRel | SDR IntRel | Alarm IntRel | UTB IntRel | UTA IntRel | Interrupt Control & Status Read top, Write bottom | |
DD0E | CIA2CTA | RTC[5] | SRC[6] | TSRC[7] | Load[8] | RES[9] | OVFL[10] | UNFL1[11] | START | Control Timer A |
DD0F | CIA2CTB | TCOUNT[13] | Load[8] | RES[9] | OVFL[10] | UNFL2[12] | START | Control Timer B |
CIA2 is mapped to addresses 0xDDxx but only occupies 16 bytes. Referencing any address from 0xDD1x…0xDDFx will mirror those at 0xDD0x.
The entries below are the official1 Kernal entry points for the Commodore 64.
1 - Except for CLRLN & CLSR which are from the ROM disassembly but are useful.CLALL | Close all open files |
---|---|
CLOSE | Close a logical file |
LOAD | Load memory from a device |
OPEN | Open a logical file |
SAVE | Save memory to a device |
SETLFS | Setup a logical file |
SETNAM | Set file name |
CHKIN | Open channel for input |
---|---|
CHKOUT | Open channel for output |
CHRIN | Get a character from the input channel |
CHROUT | Output a character |
CLRCHN | Clear I/O channels |
READST | Read status word |
ACPTR | Get data from the serial bus |
---|---|
CIOUT | Transmit a byte over the serial bus |
LISTEN | Command a device on serial bus to LISTEN |
SECOND | Send secondary address for LISTEN |
SETTMO | Set IEEE bus card timeout |
TALK | Command a device on serial bus to TALK |
TKSA | Send secondary address to a device commanded to TALK |
UNLSN | Send an UNLISTEN command |
UNTLK | Send an UNTALK command |
IOBASE | Define I/O memory page |
---|---|
MEMBOT | Set bottom of memory |
MEMTOP | Set top of memory |
RAMTAS | Perform RAM test |
CLRLN | Clear the line X |
---|---|
CLSR | Clear the screen |
PLOT | Set cursor location |
SCREEN | Return screen format |
SETMSG | Control system message output |
Function | Address | Description |
---|---|---|
ACPTR | FFA5 | Get data from the serial bus |
This routine gets a byte of data off the serial bus using full handshaking. The data is returned in the accumulator.
To prepare for this routine the TALK routine must be called first to command the device on the serial bus to send data through the bus. If the input device needs a secondary command, it must be sent by using the TKSA routine before calling this routine.
Errors are returned in the status word. The READST routine is used to read the status word.
Function | Address | Vector | Description |
---|---|---|---|
CHKIN | FFC6 | 031E | Open channel for input |
Any logical file number that has been created by the OPEN routine can be defined as an input channel. Of course, the device you intend opening a channel to must be an input device. Otherwise, an error will occur, and the routine will be aborted.
If you are getting data from anywhere other than the keyboard, this routine must be called before using either the CHRIN or the GETIN routines for data input. If you want to use the input from the keyboard, and no other input channels are opened, then the calls to this routine, and to the OPEN routine are not needed.
Function | Address | Vector | Description |
---|---|---|---|
CHKOUT | FFC9 | 0320 | Open channel for output |
Any logical file number that has been created by the OPEN routine can be defined as an output channel. Of course, the device you intend opening a channel to must be an output device. Otherwise, an error will occur, and the routine will be aborted.
This routine must be called before any data is sent to any output device unless you want to use the screen as your output device. If screen output is desired, and there are no other output channels already defined, then calls to this routine, and to the OPEN routine are not needed.
Function | Address | Description |
---|---|---|
CHRIN | FFCF | Get a character from the input channel |
This routine gets a byte of data from a channel already set up as the input channel by the CHKIN routine. If CHKIN has NOT been used to define another input channel, then all your data is expected from the keyboard.
The data byte is returned in the accumulator. The Y index register is unchanged and is usually used in a loop to store received characters.
The channel remains open after the call.
Input from the keyboard is handled in a special way. First, the cursor is turned on, and blinks until a carriage return is typed on the keyboard. All characters on the line can be retrieved one at a time by calling this routine once for each character. When the carriage return is retrieved, the entire line has been processed. The next time this routine is called, the whole process begins again, i.e., by flashing the cursor.
Example:
.readLine LDY #0 ; Prepare Y register to store data .readLoop JSR CHRIN ; Get next character STA BUF,Y ; Store in BUF (0x200 89 byte basic input buffer) INY CMP #0x0D ; Carriage Return BNE readLoop ; Loop back for next character RTS
This example does no bounds checking so if more than 89 characters are read it will overwrite the Kernal workspace in page 2.
Function | Address | Vector | Description |
---|---|---|---|
CHROUT | FFD2 | 0326 | Output a character |
This routine outputs a character to an already opened channel. Use the OPEN and CHKOUT routines to set up the output channel before calling this routine. If this call is omitted, data is sent to the default output device (number 3, the screen).
The data byte to be output is loaded into the accumulator, and this routine is called. The data is then sent to the specified output device. The channel is left open after the call.
Care must be taken when using this routine to send data to a specific serial device since data will be sent to all open output channels on the bus.
Unless this is desired, all open output channels on the serial bus other than the intended destination channel must be closed by a call to the CLRCHN routine.
Function | Address | Description |
---|---|---|
CINT | FF81 | Initialise screen editor |
This routine sets up the VIC-II chip, clear the screen, set the cursor pointer and the screen editor.
Normally, this routine is called as part of the initialization process of a Commodore 64 program cartridge.
Function | Address | Description |
---|---|---|
CIOUT | FFA8 | Transmit a byte over the serial bus |
This routine is used to send information to devices on the serial bus. A call to this routine will put a data byte onto the serial bus using full serial handshaking.
Before this routine is called, the LISTEN routine must be used to command a device on the serial bus to get ready to receive data. If a device needs a secondary address, it must also be sent by using the SECOND routine.
The accumulator is loaded with a byte to handshake as data on the serial bus. A device must be listening or the status word will return a timeout.
This routine always buffers one character. (The routine holds the previous character to be sent back.) So when a call to the UNLSN routine is made to end the data transmission, the buffered character is sent with an End Or Identify (EOI) set. Then the UNLSN command is sent to the device.
Function | Address | Vector | Description |
---|---|---|---|
CLALL | FFE7 | 032C | Close all open files |
This routine closes all open files. When this routine is called, the pointers into the open file table are reset, closing all files.
Also, the CLRCHN routine is automatically called to reset the I/O channels.
Function | Address | Vector | Description |
---|---|---|---|
CLOSE | FFC3 | 031C | Close a logical file |
This routine is used to close a logical file after all I/O operations have been completed on that file. This routine is called after the accumulator is loaded with the logical file number to be closed - the same number used when the file was opened using the OPEN routine.
Function | Address | Vector | Description |
---|---|---|---|
CLRCHN | FFCC | 0322 | Clear I/O channels |
This routine is called to clear all open channels and restore the I/O channels to their original default values.
It is usually called after opening other I/O channels like a tape or disk drive and using them for input/output operations. The default input device is 0 (keyboard). The default output device is 3 (screen).
This routine is automatically called when the CLALL routine is executed.
Function | Address | Description |
---|---|---|
CLRLN | E9FF | Clear the line X |
This routine clears the line pointed to by X.
Function | Address | Description |
---|---|---|
CLSR | E544 | Clear the screen |
This routine sets up the screen line link table (0x00D9…0x00F2). It then clears the screen line by line using the CLRLN routine. Once that's completed, it then homes the cursor to the top left.
Function | Address | Vector | Description |
---|---|---|---|
GETIN | FFE4 | 032A | Get a character |
If the input channel is the keyboard, this subroutine removes one character from the keyboard queue and returns it as an ASCII value in the accumulator. If the queue is empty, the value returned in the accumulator will be zero.
Characters are put into the queue automatically by an interrupt driven keyboard scan routine which calls the SCNKEY routine. The keyboard buffer can hold up to ten characters. After the buffer is filled, additional characters are ignored until at least one character has been removed from the queue.
If the channel is RS-232, then only the A register is used and a single character is returned. See READST to check validity.
If the channel is serial, cassette, or screen, call BASIN routine.
Function | Address | Description |
---|---|---|
IOBASE | FFF3 | Define I/O memory page |
This routine sets the X and Y registers to the address of the memory section where the memory mapped 110 devices are located. This address can then be used with an offset to access the memory mapped I/O devices in the Commodore 64. The offset is the number of locations from the beginning of the page on which the I/O register you want is located. The X register contains the low order address byte, while the Y register contains the high order address byte.
This routine exists to provide compatibility between the Commodore 64, VIC-20, and potential future models of the Commodore 64. If the I/O locations for a machine language program are set by a call to this routine, they should still remain compatible with future versions of the Commodore 64, the KERNAL and BASIC.
Note: FREKZP (0x00FB) in this example is a 4 byte block of zeropage memory unused by Basic or Kernal and is available for user code.
For the C64 the value returned is 0xDC00 - address of CLA #1
For the C128 the value returned is 0xD000 - address of the VIC chip
Function | Address | Description |
---|---|---|
IOINIT | FF84 | Initialise I/O Devices |
This routine initializes all input/output devices and routines.
It is normally called as part of the initialization procedure of a Commodore 64 program cartridge.
Function | Address | Description |
---|---|---|
LISTEN | FFB1 | Command a device on serial bus to LISTEN |
This routine will command a device on the serial bus to receive data. The accumulator must first be loaded with a device number between 0 and 31. When called, this routine then ORs bit by bit to convert this device number to a talk address. The specified device will then go into listen mode, and be ready to accept information.
Function | Address | Vector | Description |
---|---|---|---|
LOAD | FFD5 | 0330 | Load memory from a device |
This routine LOADs data bytes from any input device directly into the memory. It can also be used for a verify operation, comparing data from a device with the data already in memory, while leaving the data stored in RAM unchanged.
To use, you first need to call SETLFS to set the device to save to. Then SETNAM must be called to set the filename.
The accumulator must be set to 0 for a load or 1 for a verify operation.
If the input device is opened with a secondary address of 0, the header information from the device is ignored. In this case the X & Y registers must contain the starting address for the load.
With a secondary address of 1 the data is loaded into memory starting at the location specified by the header.
This routine returns the highest address of the data loaded on exit.
Function | Address | Description |
---|---|---|
MEMBOT | FF9C | Set bottom of memory |
This routine reads or writes the bottom of memory.
When the Carry flag is set then the bottom memory address is read into the X, Y index registers.
When the Carry flag is clear then the bottom memory address is set to the address in the X, Y index registers.
The value is stored in the MEMSTR variable at 0x281.
Machine | Value |
---|---|
C64 | 0x0800 |
V20 unexpanded | 0x1000 |
V20 with 3K expansion | 0x0400 |
V20 with 8K or more | 0x1200 |
Function | Address | Description |
---|---|---|
MEMTOP | FF99 | Set top of memory |
This routine reads or writes the top of memory.
When the Carry flag is set then the top memory address is read into the X, Y index registers.
When the Carry flag is clear then the top memory address is set to the address in the X, Y index registers.
The value is stored in the MEMSIZ variable at 0x283.
Function | Address | Vector | Description |
---|---|---|---|
OPEN | FFC0 | 031A | Open a logical file |
This routine is used to OPEN a logical file. Once the logical file is set up, it can be used for input/output operations.
Most of the I/O routines call on this routine to create the logical files to operate on. No arguments need to be set up to use this routine, but both the SETLFS and SETNAM routines must be called before using this routine.
Function | Address | Description |
---|---|---|
PLOT | FFF0 | Set cursor location |
This routine either reads or sets the text cursor's location.
A call to this routine with the accumulator carry flag set loads the current position of the cursor on the screen (in X,Y coordinates) into the Y and X registers. Y is the column number of the cursor location (0-39), and X is the row number of the location of the cursor (0-24).
Note: FREKZP (0x00FB) in this example is a 4 byte block of zeropage memory unused by Basic or Kernal and is available for user code.
A call with the carry bit clear moves the cursor to X,Y as determined by the Y and X registers.
Example:
Function | Address | Description |
---|---|---|
RAMTAS | FF87 | Perform RAM test |
This routine is used to test RAM and set the top and bottom of memory pointers accordingly.
It clears locations &00 to &0101 and &0200 to &03FF. It then allocates the cassette buffer, and sets the screen base to $0400.
Normally, this routine is called as part of the initialization process of a Commodore 64 program cartridge.
Function | Address | Description |
---|---|---|
RDTIM | FFDE | Read system clock |
This routine is used to read the system clock. The clock's resolution is a 60th of a second. Three bytes are returned by the routine. The accumulator contains the most significant byte, the X index register contains the next most significant byte, and the Y index register contains the least significant byte.
Note: FREKZP (0x00FB) in this example is a 4 byte block of zeropage memory unused by Basic or Kernal and is available for user code.
Function | Address | Description |
---|---|---|
READST | FFB7 | Read status word |
This routine returns the current status of the I/O devices in the accumulator. The routine is usually called after new communication to an I/O device. The routine gives you information about device status, or errors that have occurred during the I/O operation.
The bits returned in the accumulator contain the following information:
Bit | Cassette Read | Serial Bus R/W | Tape Verify/Load |
---|---|---|---|
0 | write timeout | ||
1 | read timeout | ||
2 | short block | short block | |
3 | long block | long block | |
4 | unrecoverable read error | any mismatch | |
5 | checksum error | checksum error | |
6 | end of file | EOI line | |
7 | end of tape | device not present | end of tape |
Function | Address | Description |
---|---|---|
RESTOR | FF8A | Restore default system & interrup vectors |
This routine restores the default values of all system vectors used in KERNAL and BASIC routines and interrupts.
See the Memory Map for the default vector contents.
The VECTOR routine is used to read and alter individual system vectors.
Function | Address | Vector | Description |
---|---|---|---|
SAVE | FFD8 | 0332 | Save memory to a device |
This routine saves a section of memory to a device.
To use, you first need to call SETLFS to set the device to save to. Then SETNAM must be called to set the filename.
Finally you store the start address in 2 bytes of zero page memory, set X & Y to point to the address immediately after the data to save, and A to the offset within zeropage where the start address was stored.
Any errors are reported via the READST routine.
Note: FREKZP (0x00FB) in this example is a 4 byte block of zeropage memory unused by Basic or Kernal and is available for user code.
Function | Address | Description |
---|---|---|
SCNKEY | FF9F | Scan the keyboard |
This routine scans the Commodore 64 keyboard and checks for pressed keys. It is the same routine called by the interrupt handler. If a key is down, its ASCII value is placed in the keyboard queue. This routine is called only if the normal IRQ interrupt is bypassed.
Function | Address | Description |
---|---|---|
SCREEN | FFED | Return screen format |
This routine returns the format of the screen, e.g., 40 columns in X and 25 lines in Y. The routine can be used to determine what machine a program is running on. This function has been implemented on the Commodore 64 to help upward compatibility of your programs.
Function | Address | Description |
---|---|---|
SECOND | FF93 | Send secondary address for LISTEN |
Function | Address | Description |
---|---|---|
SETLFS | FFBA | Setup a logical file |
This routine sets the logical file number, device address, and secondary address (command number) for other KERNAL routines.
The logical file number is used by the system as a key to the file table created by the OPEN file routine. Device addresses can range from 0 to 31. The following codes are used by the Commodore 64 to stand for the CBM devices listed below:
Address | Device |
---|---|
0 | Keyboard |
1 | Cassette / Datassette |
2 | RS232 |
3 | Screen |
4 | Printer |
8 | Disk drive |
9 | Disk drive |
Device numbers 4 or greater automatically refer to devices on the serial bus.
A command to the device is sent as a secondary address on the serial bus after the device number is sent during the serial attention handshaking sequence. If no secondary address is to be sent, the Y index register should be set to 255.
Function | Address | Description |
---|---|---|
SETMSG | FF90 | Control system message output |
This routine controls the printing of error and control messages by the KERNAL.
Either print error messages or print control messages can be selected by setting the accumulator when the routine is called.
FILE NOT FOUND
is an example of an error message.
PRESS PLAY ON CASSETTE
is an example of a control message.
Bits 6 and 7 of this value determine where the message will come from.
If bit 7 is 1, one of the error messages from the KERNAL is printed.
If bit 6 is set, control messages are printed.
If this is set to 0 then all kernal messages are disabled.
Function | Address | Description |
---|---|---|
SETNAM | FFBD | Set file name |
This routine is used to set up the file name for the OPEN, SAVE, or LOAD routines.
The accumulator must be loaded with the length of the file name. The X and Y registers must be loaded with the address of the file name, in standard 6502 low-byte/high-byte format.
The address can be any valid memory address in the system where a string of characters for the file name is stored.
If no file name is desired, the accumulator must be set to 0, representing a zero file length. The X and Y registers can be set to any memory address in that case.
Function | Address | Description |
---|---|---|
SETTIM | FFDB | Set system clock |
A system clock is maintained by an interrupt routine that updates the clock every 1/60th of a second (one "jiffy"). The clock is three bytes long, which gives it the capability to count up to 5,184,000 jiffies (24 hours). At that point the clock resets to zero.
Before calling this routine to set the clock, the accumulator must contain the most significant byte, the X index register the next most significant byte, and the Y index register the least significant byte of the initial time setting (in jiffies).
Function | Address | Description |
---|---|---|
SETTMO | FFA2 | Set IEEE bus card timeout |
This routine sets the timeout flag for the IEEE bus. When the timeout flag is set, the Commodore 64 will wait for a device on the IEEE port for 64 milliseconds. If the device does not respond to the Commodore 64's Data Address Valid (DAV) signal within that time the Commodore 64 will recognize an error condition and leave the handshake sequence. When this routine is called when the accumulator contains a 0 in bit 7, timeouts are enabled. A 1 in bit 7 will disable the timeouts.
Function | Address | Vector | Description |
---|---|---|---|
STOP | FFE1 | 0328 | Check if key/stop key is pressed |
This routine checks for either the RUN/STOP key or certain other keys are pressed.
If the key was pressed during a UDTIM call, this call returns the z flag set. In addition, the channels will be reset to default values.
In the above example if the STOP key is pressed we jump to the method stopDown
.
This method could reset your application, cancelling some lengthy operation.
If the stop key is not pressed then the z flag will be clear and the accumulator will be set to one of the following keys located on the same keyboard column as the stop key:
C64 key | Accumulator | Vic-20 key | Accumulator |
---|---|---|---|
1 | 0xFE | Cursor Down | 0x7F |
Left arrow | 0xFD | / | 0xBF |
CTRL | 0xFB | , | 0xDF |
2 | 0xF7 | N | 0xEF |
Space | 0xEF | V | 0xF7 |
Commodore | 0xDF | X | 0xFB |
Q | 0xBF | Left Shift | 0xFD |
If no key is down in the STOP column, the routine returns 0xFF on both machines.
Function | Address | Description |
---|---|---|
TALK | FFB4 | Command a device on serial bus to TALK |
To use this routine the accumulator must first be loaded with a device number between 0 and 31.
When called, this routine then ORs bit by bit to convert this device number to a talk address. Then this data is transmitted as a command on the serial bus.
If a secondary address is required then the TKSA routine must be called immediately after this one.
Function | Address | Description |
---|---|---|
TKSA | FF96 | Send secondary address to a device commanded to TALK |
This routine transmits a secondary address on the serial bus for a TALK device. This routine must be called with a number between 0 and 31 in the accumulator. The routine sends this number as a secondary address command over the serial bus. This routine can only be called after a call to the TALK routine. It will not work after a LISTEN.
Function | Address | Description |
---|---|---|
UDTIM | FFEA | Update system clock |
This routine updates the system clock. Normally this routine is called by the normal KERNAL interrupt routine every 1/60th of a second. If the user program processes its own interrupts this routine must be called to update the time. In addition, the <STOP> key routine must be called, if the <STOP> key is to remain functional.
Function | Address | Description |
---|---|---|
UNLISTEN | FFAE | Send an UNLISTEN command |
This routine commands all devices on the serial bus to stop receiving data. Calling this routine results in an UNLISTEN command being transmitted on the serial bus. Only devices previously commanded to listen are affected. This routine is normally used after the Commodore 64 has finished sending data to external devices. Sending the UNLISTEN commands the listening devices to get off the serial bus, so it can be used for other purposes.
Function | Address | Description |
---|---|---|
UNTLK | FFAB | Send an UNTALK command |
This routine commands all devices on the serial bus to stop sending data. Calling this routine results in an UNTALK command being transmitted on the serial bus. Only devices previously commanded to talk are affected.
Function | Address | Description |
---|---|---|
VECTOR | FF8D | Manage RAM Vectors |
This routine manages all system vector jump addresses stored in RAM.
Calling this routine with the the accumulator carry bit set stores the current contents of the RAM vectors in a list pointed to by the X and Y registers.
When this routine is called with the carry clear, the user list pointed to by the X and Y registers is transferred to the system RAM vectors.
The RAM vectors are listed in the memory map.
Function | Address | Vector | Description |
---|---|---|---|
CLSR | E544 | Clear the screen | |
CLRLN | E9FF | Clear the line X | |
CINT | FF81 | Initialise screen editor | |
IOINIT | FF84 | Initialise I/O Devices | |
RAMTAS | FF87 | Perform RAM test | |
RESTOR | FF8A | Restore default system & interrup vectors | |
VECTOR | FF8D | Manage RAM Vectors | |
SETMSG | FF90 | Control system message output | |
SECOND | FF93 | Send secondary address for LISTEN | |
TKSA | FF96 | Send secondary address to a device commanded to TALK | |
MEMTOP | FF99 | Set top of memory | |
MEMBOT | FF9C | Set bottom of memory | |
SCNKEY | FF9F | Scan the keyboard | |
SETTMO | FFA2 | Set IEEE bus card timeout | |
ACPTR | FFA5 | Get data from the serial bus | |
CIOUT | FFA8 | Transmit a byte over the serial bus | |
UNTLK | FFAB | Send an UNTALK command | |
UNLISTEN | FFAE | Send an UNLISTEN command | |
LISTEN | FFB1 | Command a device on serial bus to LISTEN | |
TALK | FFB4 | Command a device on serial bus to TALK | |
READST | FFB7 | Read status word | |
SETLFS | FFBA | Setup a logical file | |
SETNAM | FFBD | Set file name | |
OPEN | FFC0 | 031A | Open a logical file |
CLOSE | FFC3 | 031C | Close a logical file |
CHKIN | FFC6 | 031E | Open channel for input |
CHKOUT | FFC9 | 0320 | Open channel for output |
CLRCHN | FFCC | 0322 | Clear I/O channels |
CHRIN | FFCF | Get a character from the input channel | |
CHROUT | FFD2 | 0326 | Output a character |
LOAD | FFD5 | 0330 | Load memory from a device |
SAVE | FFD8 | 0332 | Save memory to a device |
SETTIM | FFDB | Set system clock | |
RDTIM | FFDE | Read system clock | |
STOP | FFE1 | 0328 | Check if key/stop key is pressed |
GETIN | FFE4 | 032A | Get a character |
CLALL | FFE7 | 032C | Close all open files |
UDTIM | FFEA | Update system clock | |
SCREEN | FFED | Return screen format | |
PLOT | FFF0 | Set cursor location | |
IOBASE | FFF3 | Define I/O memory page |
Function | Address | Vector | Description |
---|---|---|---|
ACPTR | FFA5 | Get data from the serial bus | |
CHKIN | FFC6 | 031E | Open channel for input |
CHKOUT | FFC9 | 0320 | Open channel for output |
CHRIN | FFCF | Get a character from the input channel | |
CHROUT | FFD2 | 0326 | Output a character |
CINT | FF81 | Initialise screen editor | |
CIOUT | FFA8 | Transmit a byte over the serial bus | |
CLALL | FFE7 | 032C | Close all open files |
CLOSE | FFC3 | 031C | Close a logical file |
CLRCHN | FFCC | 0322 | Clear I/O channels |
CLRLN | E9FF | Clear the line X | |
CLSR | E544 | Clear the screen | |
GETIN | FFE4 | 032A | Get a character |
IOBASE | FFF3 | Define I/O memory page | |
IOINIT | FF84 | Initialise I/O Devices | |
LISTEN | FFB1 | Command a device on serial bus to LISTEN | |
LOAD | FFD5 | 0330 | Load memory from a device |
MEMBOT | FF9C | Set bottom of memory | |
MEMTOP | FF99 | Set top of memory | |
OPEN | FFC0 | 031A | Open a logical file |
PLOT | FFF0 | Set cursor location | |
RAMTAS | FF87 | Perform RAM test | |
RDTIM | FFDE | Read system clock | |
READST | FFB7 | Read status word | |
RESTOR | FF8A | Restore default system & interrup vectors | |
SAVE | FFD8 | 0332 | Save memory to a device |
SCNKEY | FF9F | Scan the keyboard | |
SCREEN | FFED | Return screen format | |
SECOND | FF93 | Send secondary address for LISTEN | |
SETLFS | FFBA | Setup a logical file | |
SETMSG | FF90 | Control system message output | |
SETNAM | FFBD | Set file name | |
SETTIM | FFDB | Set system clock | |
SETTMO | FFA2 | Set IEEE bus card timeout | |
STOP | FFE1 | 0328 | Check if key/stop key is pressed |
TALK | FFB4 | Command a device on serial bus to TALK | |
TKSA | FF96 | Send secondary address to a device commanded to TALK | |
UDTIM | FFEA | Update system clock | |
UNLISTEN | FFAE | Send an UNLISTEN command | |
UNTLK | FFAB | Send an UNTALK command | |
VECTOR | FF8D | Manage RAM Vectors |