C64 Font
The Commodore 64 draws text from a character generator holding 8×8 glyphs. Two charsets live in the character ROM, and a program can point the VIC-II at RAM instead to use its own redefined font. Each glyph is 8 bytes, one row per byte, with the top bit on the left.
- Overview
- The character ROM
- Glyph byte format
- Screen codes and PETSCII
- Redefining the font
- Default font
Overview
In text mode the screen is 40×25 character cells. Each cell holds one screen code, and the VIC-II looks up that code's 8×8 shape in the character generator and draws it in the cell's colour. The generator is a table of 256 glyphs, 8 bytes each, so a full charset is 2K.
| Property | Value |
|---|---|
| Cells | 40 × 25 |
| Glyph size | 8 × 8 pixels |
| Bytes per glyph | 8 (one row each) |
| Glyphs per charset | 256 |
| Charset size | 2048 bytes |
The character ROM
The character ROM is 4K and is visible to the VIC-II at $D000–$DFFF in its address space. It holds two 256-glyph charsets of 2K each. The first is the uppercase and graphics set; the second is the upper and lowercase set. A program picks between them at runtime, and each is a full 8×8 font.
| Offset in ROM | Charset |
|---|---|
| $0000–$07FF | Uppercase and graphics (256 glyphs) |
| $0800–$0FFF | Upper and lowercase (256 glyphs) |
Glyph byte format
A glyph is 8 consecutive bytes. Byte 0 is the top pixel row and byte 7 the bottom. In each byte the most significant bit is the leftmost pixel: a 1 draws the character colour, a 0 leaves the background. So the glyph for code c starts at charset base + c × 8.
| Byte | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
|---|---|---|---|---|---|---|---|---|
| 0 (top) | Leftmost pixel … rightmost pixel of the top row | |||||||
| 1–6 | Middle rows, top to bottom | |||||||
| 7 (bottom) | Bottom row, left to right | |||||||
In multicolour character mode a cell can show up to four colours. When the cell's Colour RAM nibble has bit 3 set, the glyph bytes are read two bits per pixel, giving 4×8 double-width pixels whose pairs select the background and two shared colours from $D022 and $D023, plus the low three bits of the cell's colour.
Screen codes and PETSCII
Two numbering schemes exist. PETSCII is Commodore's character encoding used for keyboard input, strings and printing; it resembles ASCII but with its own order and the graphics characters. Screen codes are what actually goes into a screen cell, and they run 0 to 255 as the direct index into the charset.
The two differ: for example the letter A is PETSCII 65 but screen code 1. The KERNAL converts PETSCII to screen codes when it prints, so code you place directly into screen RAM must already be a screen code.
| Scheme | Range | Role |
|---|---|---|
| PETSCII | 0–255 | Keyboard, strings, printing. |
| Screen code | 0–255 | Direct glyph index written to screen RAM. |
Redefining the font
The VIC-II does not have to use the ROM font. The upper bits of the memory-control register $D018 set the character base, in 2K steps, within the current 16K VIC bank. Pointing that base at RAM and filling it with new glyphs replaces the whole charset, so a game can draw with custom tiles and symbols.
The usual method is to copy the ROM font into RAM, edit the glyphs that need to change, then set $D018 to the new base. Two ROM areas, $1000–$1FFF and $9000–$9FFF, are where the character ROM appears to the VIC-II by default, so a redefined font is normally placed elsewhere in the bank.
| Register | Bits | Meaning |
|---|---|---|
| $D018 | 1–3 | Character base within bank, in 2K steps. |
| $DD00 | 0–1 | VIC bank select, so the font must be in that bank. |
Default font
The tool ships the C64 default in Sprites.Platform.C64.Font.DefaultFont, a font object of 256 glyphs, codes 0 to 255, one byte per pixel row, the top bit the leftmost pixel. The platform carries the range as Sprites.Platform.C64.Font.CharStart, 0, and Sprites.Platform.C64.Font.CharCount, 256. The two charsets are extracted from the real C64 character ROM, 256 glyphs each, in screen-code order.