Oct 4, 2026 · Updated Oct 11, 2026 · @Craig Taylor
Screen codes are the values stored in screen memory, and are different from PETSCII. These are the codes of the upper-case character set; codes 128 to 255 are the same characters in reverse video.
| Codes | Characters |
|---|---|
| 0 | @ |
| 1-26 | A to Z (lower-case a to
z in the lower-case set) |
| 27-31 | [, £, ], ↑,
← |
| 32 | Space |
| 33-47 | ! " # $ % & ' ( ) * + , - . / |
| 48-57 | 0 to 9 |
| 58-63 | : ; < = > ? |
| 64-127 | Graphics characters; in the lower-case set, 65-90 are A
to Z |
| 128-255 | Codes 0-127 in reverse video |
To convert a letter's PETSCII code to its screen code in the
upper-case set, subtract 64: PETSCII 65, A, is screen code
1. Digits and most punctuation have the same value in both. Screen codes
256 and above are used only in the VIC-IV's two-byte character modes;
Chapter 12 describes them.
The first 16 palette entries are the C64's colours, used by COLOR, BORDER, BACKGROUND and colour RAM. CTRL with 1 to 8 types the first eight, and MEGA with 1 to 8 the second eight.
| Code | Colour | Code | Colour |
|---|---|---|---|
| 0 | Black | 8 | Orange |
| 1 | White | 9 | Brown |
| 2 | Red | 10 | Light red |
| 3 | Cyan | 11 | Dark grey |
| 4 | Purple | 12 | Grey |
| 5 | Green | 13 | Light green |
| 6 | Blue | 14 | Light blue |
| 7 | Yellow | 15 | Light grey |
Entries 16 to 31 hold an alternate "rainbow" set, selected for text with ESC S and returned with ESC U, and entries 32 to 255 are free for programs to define with PALETTE.
PETSCII is the character code used by PRINT, CHR$, ASC,
GET and the keyboard. Codes 32 to 95 follow ASCII closely; the rest hold
control codes and graphics.
| Codes | Contents |
|---|---|
| 0-31 | Control codes |
| 32-63 | Space, punctuation and digits, as in ASCII |
| 64-95 | @, letters A to Z, and [ £ ] ↑ ← |
| 96-127 | Graphics characters |
| 128-159 | Control codes |
| 160-191 | Graphics characters |
| 192-223 | The same characters as 96-127 |
| 224-254 | The same characters as 160-190 |
| 255 | π |
In the lower-case set, 65-90 are lower-case letters and 193-218 are capitals.
Printing these codes performs an action rather than showing a
character. They can be typed into strings in quote mode, or produced
with CHR$.
| Code | Action | Code | Action |
|---|---|---|---|
| 5 | White | 129 | Orange |
| 13 | Return | 133-140 | F1, F3, F5, F7, F2, F4, F6, F8 |
| 14 | Lower-case set | 141 | Shifted return |
| 17 | Cursor down | 142 | Upper-case set |
| 18 | Reverse on | 144 | Black |
| 19 | Home | 145 | Cursor up |
| 20 | Delete | 146 | Reverse off |
| 27 | Escape: starts an escape sequence | 147 | Clear screen |
| 28 | Red | 148 | Insert |
| 29 | Cursor right | 149-155 | Brown, light red, dark grey, grey, light green, light blue, light grey |
| 30 | Green | 156 | Purple |
| 31 | Blue | 157 | Cursor left |
| 158 | Yellow | ||
| 159 | Cyan |
These are the C64's control codes, which the MEGA65 keeps;
PRINT CHR$(27); "X" sends an escape sequence, as Chapter 2
describes. The MEGA65 also defines further codes, such as for tabs and
flashing text; the Book's character appendix lists them all.
Each hexadecimal digit stands for four binary digits, so conversion between the two needs only this table:
| Hex | Binary | Decimal | Hex | Binary | Decimal |
|---|---|---|---|---|---|
| 0 | 0000 | 0 | 8 | 1000 | 8 |
| 1 | 0001 | 1 | 9 | 1001 | 9 |
| 2 | 0010 | 2 | A | 1010 | 10 |
| 3 | 0011 | 3 | B | 1011 | 11 |
| 4 | 0100 | 4 | C | 1100 | 12 |
| 5 | 0101 | 5 | D | 1101 | 13 |
| 6 | 0110 | 6 | E | 1110 | 14 |
| 7 | 0111 | 7 | F | 1111 | 15 |
$D0 is therefore %11010000, and
%10100101 is $A5.
To convert hex to decimal, multiply each digit by its place value and add:
| Place | Value |
|---|---|
| 1st digit from the right | 1 |
| 2nd | 16 |
| 3rd | 256 |
| 4th | 4,096 |
| 5th | 65,536 |
| 6th | 1,048,576 |
| 7th | 16,777,216 |
So $D020 is 13 × 4096 + 0 × 256 + 2 × 16 + 0 = 53,280.
In BASIC 65 the conversions are built in: PRINT $D020 gives
53280, PRINT HEX$(53280) gives D020,
PRINT %1010 gives 10, and PRINT STRBIN$(10)
gives the binary digits.
| Hex | Decimal | Meaning |
|---|---|---|
$FF |
255 | Largest byte |
$100 |
256 | One page |
$2000 |
8,192 | 8KB, one MAP block |
$10000 |
65,536 | 64KB, one bank |
$100000 |
1,048,576 | 1MB, one MAP megabyte |
$8000000 |
134,217,728 | Start of attic RAM |
$FF80000 |
267,911,168 | Start of colour RAM |
The row gives the opcode's high digit and the column its low digit:
LDA # is in row A, column 9, so its opcode is
$A9. Mode abbreviations are those of Chapter 10: bp is base
page, (bp),Z indirect indexed by Z, rel16 a 16-bit branch,
and (d,SP),Y stack-relative. The 45GS02's flat and quad
instructions are prefixed forms of these opcodes, as Chapter 10
describes. This map follows the cc65 CPU reference and the Book's
4510/45GS02 opcode table (MEGA65 Book, Appendix L). Opcode
$62 uses the cc65 name RTN; the Book writes the same
instruction as RTS #$nn.
| x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | |
|---|---|---|---|---|---|---|---|---|
| 0x | BRK | ORA (bp,X) | CLE | SEE | TSB bp | ORA bp | ASL bp | RMB0 bp |
| 1x | BPL rel | ORA (bp),Y | ORA (bp),Z | BPL rel16 | TRB bp | ORA bp,X | ASL bp,X | RMB1 bp |
| 2x | JSR abs | AND (bp,X) | JSR (abs) | JSR (abs,X) | BIT bp | AND bp | ROL bp | RMB2 bp |
| 3x | BMI rel | AND (bp),Y | AND (bp),Z | BMI rel16 | BIT bp,X | AND bp,X | ROL bp,X | RMB3 bp |
| 4x | RTI | EOR (bp,X) | NEG | ASR A | ASR bp | EOR bp | LSR bp | RMB4 bp |
| 5x | BVC rel | EOR (bp),Y | EOR (bp),Z | BVC rel16 | ASR bp,X | EOR bp,X | LSR bp,X | RMB5 bp |
| 6x | RTS | ADC (bp,X) | RTN imm | BSR rel16 | STZ bp | ADC bp | ROR bp | RMB6 bp |
| 7x | BVS rel | ADC (bp),Y | ADC (bp),Z | BVS rel16 | STZ bp,X | ADC bp,X | ROR bp,X | RMB7 bp |
| 8x | BRA rel | STA (bp,X) | STA (d,SP),Y | BRA rel16 | STY bp | STA bp | STX bp | SMB0 bp |
| 9x | BCC rel | STA (bp),Y | STA (bp),Z | BCC rel16 | STY bp,X | STA bp,X | STX bp,Y | SMB1 bp |
| Ax | LDY imm | LDA (bp,X) | LDX imm | LDZ imm | LDY bp | LDA bp | LDX bp | SMB2 bp |
| Bx | BCS rel | LDA (bp),Y | LDA (bp),Z | BCS rel16 | LDY bp,X | LDA bp,X | LDX bp,Y | SMB3 bp |
| Cx | CPY imm | CMP (bp,X) | CPZ imm | DEW bp | CPY bp | CMP bp | DEC bp | SMB4 bp |
| Dx | BNE rel | CMP (bp),Y | CMP (bp),Z | BNE rel16 | CPZ bp | CMP bp,X | DEC bp,X | SMB5 bp |
| Ex | CPX imm | SBC (bp,X) | LDA (d,SP),Y | INW bp | CPX bp | SBC bp | INC bp | SMB6 bp |
| Fx | BEQ rel | SBC (bp),Y | SBC (bp),Z | BEQ rel16 | PHW imm16 | SBC bp,X | INC bp,X | SMB7 bp |
| x8 | x9 | xA | xB | xC | xD | xE | xF | |
|---|---|---|---|---|---|---|---|---|
| 0x | PHP | ORA imm | ASL A | TSY | TSB abs | ORA abs | ASL abs | BBR0 |
| 1x | CLC | ORA abs,Y | INC A | INZ | TRB abs | ORA abs,X | ASL abs,X | BBR1 |
| 2x | PLP | AND imm | ROL A | TYS | BIT abs | AND abs | ROL abs | BBR2 |
| 3x | SEC | AND abs,Y | DEC A | DEZ | BIT abs,X | AND abs,X | ROL abs,X | BBR3 |
| 4x | PHA | EOR imm | LSR A | TAZ | JMP abs | EOR abs | LSR abs | BBR4 |
| 5x | CLI | EOR abs,Y | PHY | TAB | MAP | EOR abs,X | LSR abs,X | BBR5 |
| 6x | PLA | ADC imm | ROR A | TZA | JMP (abs) | ADC abs | ROR abs | BBR6 |
| 7x | SEI | ADC abs,Y | PLY | TBA | JMP (abs,X) | ADC abs,X | ROR abs,X | BBR7 |
| 8x | DEY | BIT imm | TXA | STY abs,X | STY abs | STA abs | STX abs | BBS0 |
| 9x | TYA | STA abs,Y | TXS | STX abs,Y | STZ abs | STA abs,X | STZ abs,X | BBS1 |
| Ax | TAY | LDA imm | TAX | LDZ abs | LDY abs | LDA abs | LDX abs | BBS2 |
| Bx | CLV | LDA abs,Y | TSX | LDZ abs,X | LDY abs,X | LDA abs,X | LDX abs,Y | BBS3 |
| Cx | INY | CMP imm | DEX | ASW abs | CPY abs | CMP abs | DEC abs | BBS4 |
| Dx | CLD | CMP abs,Y | PHX | PHZ | CPZ abs | CMP abs,X | DEC abs,X | BBS5 |
| Ex | INX | SBC imm | EOM / NOP | ROW abs | CPX abs | SBC abs | INC abs | BBS6 |
| Fx | SED | SBC abs,Y | PLX | PLZ | PHW abs | SBC abs,X | INC abs,X | BBS7 |
BBR and BBS take a base page address and an 8-bit branch offset.
This is a quick reference to the registers used in this book. The MEGA65 Book's register appendices document every register and bit. Most of these need the VIC-IV (MEGA65) I/O personality.
| Address | Name | Purpose | Chapter |
|---|---|---|---|
$00 |
CPU port direction | $41 forces full speed, $40 releases
it |
8 |
$01 |
CPU port | C64-style banking | 5 |
$D011, $D012 |
Control, raster | Raster compare bit 8 and bits 7-0 | 8 |
$D019, $D01A |
IRQ flags, mask | Raster interrupt acknowledge and enable | 8 |
$D020, $D021 |
Border, background | Screen colours | 12 |
$D02F |
KEY | Knock to select the I/O personality | 5 |
$D030 |
VIC-III control | ROM banking, CRAM2K | 5 |
$D031 |
VIC-III control | H640, FAST, ATTR, BPM, V400 | 8, 12 |
$D04C, $D04E |
TEXTXPOS, TEXTYPOS | Text area position | 12 |
$D051 |
NORRDEL, DBLRR | Raster rewrite buffer timing | 12 |
$D052, $D053 |
FNRASTER | Physical raster line | 8 |
$D054 |
CHR16, FCLRLO, FCLRHI, VFAST | Two-byte characters, full colour, 40.5 MHz | 8, 12 |
$D057 |
SPRX64EN | 64-pixel-wide sprites | 12 |
$D058, $D059 |
LINESTEP | Bytes per character row | 12 |
$D05D bit 7 |
HOTREG | Hot register behaviour | 12 |
$D05E |
CHRCOUNT | Characters per row (low byte) | 12 |
$D060-$D062 |
SCRNPTR | Screen memory address | 12 |
$D064, $D065 |
COLPTR | Colour RAM offset | 12 |
$D06C-$D06E |
SPRPTRADR | Sprite pointer list address | 12 |
$D06F bit 7 |
PALNTSC | Set in NTSC mode | 8, 13 |
$D079, $D07A |
RASCMP | Physical raster compare | 8 |
$D100-$D3FF |
Palette | Red, green and blue, nybble-swapped | 12 |
$D400-$D47F |
SIDs | Four SIDs, $20 bytes each |
13 |
$D600-$D606 |
UART | Serial port | 17 |
$D60A, $D610, $D619 |
Keyboard queue | MODKEY, ASCIIKEY, PETSCIIKEY | 16 |
$D611, $D613, $D614 |
Keyboard matrix | Modifiers, column data, column select | 16 |
$D63C |
SIDMODE | 6581 or 8580 behaviour | 13 |
$D640-$D67F |
Hypervisor traps | Hypervisor services | 8, 11 |
$D6E0 onward |
Ethernet | Ethernet controller | 17 |
$D6F4, $D6F5 |
MIXREGSEL, MIXREGDATA | Audio mixer coefficients | 13 |
$D700-$D707 |
DMAgic | DMA list address and triggers | 5, 8 |
$D70F |
DIVBUSY, MULBUSY | Math accelerator status | 5 |
$D711 |
AUDEN, NOMIX | Audio DMA control | 13 |
$D720-$D75F |
Audio DMA | Four channels of 16 registers | 13 |
$D768-$D77F |
Math accelerator | DIVOUT, MULTINA, MULTINB, MULTOUT | 5 |
$DC00, $DC01 |
CIA 1 ports | Joysticks and keyboard | 16 |
$FFD7110 |
RTC | Real-time clock | 17 |
Many C64 programs run unchanged in C64 mode. Converting one to MEGA65 mode lets it use the MEGA65's speed, memory and graphics, but several differences need attention.
| C64 | MEGA65 mode |
|---|---|
BASIC starts at $0801 |
BASIC starts at $2001; programs are relinked when
loaded |
Screen at $0400, 40 columns |
Screen at $0800, usually 80 columns; use PRINT,
T@& and C@& rather than fixed
addresses |
Sprite pointers at 2040 ($07F8) |
Sprite pointers at $0FF8 by default; better still, use
SPRITE and MOVSPR |
POKE to $D000-$DFFF |
Works when BANK is 128, the default |
| Variable names that contain BASIC 65 keywords | Must be renamed: BASIC 65 has many more keywords, such as COLOR, PEN and BANK |
| Delay loops | Run about forty times faster at 40.5 MHz; replace with SLEEP or VSYNC |
GET A$ : IF A$ = "" THEN ... |
Works, or use GETKEY |
| Tokens | C64 BASIC tokens mean the same in BASIC 65 |
$FF81-$FFF3 work unchanged, as Chapter 11 describes.$01 banking should set it explicitly, and must allow for
MAP and $D030 as Chapter 5 describes.C65 BASIC 10 programs are close relatives of BASIC 65 and often run with small changes, mostly to graphics commands, which changed between BASIC 10 and BASIC 65. C65 machine language runs on the 45GS02, which executes every 4510 instruction.
The machine-language monitor is entered with MONITOR from BASIC, by a
BRK instruction, or by holding RUN/STOP while pressing reset. It accepts
32-bit addresses and treats every number as hexadecimal unless it has a
prefix: + decimal, & octal, %
binary, ' a PETSCII character (MEGA65 Book, Appendix
O).
| Command | Format | Purpose |
|---|---|---|
| A | A address instruction |
Assemble an instruction; the monitor then offers the next address |
| B | B address |
Show memory as character bitmaps |
| C | C from to with |
Compare two memory ranges |
| D | D [from [to]] |
Disassemble |
| F | F from to byte |
Fill memory with a byte |
| G | G [address] |
Jump to an address |
| H | H from to data |
Hunt for bytes or text in memory |
| J | J address |
Call a subroutine, as with JSR |
| L | L "name" [, unit [, address]] |
Load a file into memory |
| M | M [from [to]] |
Show memory as hexadecimal and text |
| R | R |
Show the registers |
| S | S "name", unit, from, to |
Save memory to a file |
| T | T from to destination |
Transfer (copy) memory |
| V | V "name" [, unit [, address]] |
Verify memory against a file |
| X | X |
Return to BASIC |
| @ | @ [command] |
Disk command, status or directory |
Memory and registers shown by M and R can be changed by moving the cursor onto the display, typing over the values and pressing RETURN, as in other Commodore monitors. Chapter 7 walks through a first program entered with the monitor, and Chapter 8 covers debugging with it, with BRK breakpoints, and with Matrix Mode.