The character set
Two hundred and fifty-six characters, eight bytes each. They are IBM Code Page 437 — the set the original PC shipped with, which is why it has box-drawing lines, card suits, Greek letters and three densities of shading alongside the alphabet.
Each glyph is a 6 × 8 cell with the drawing five pixels wide, leaving a column of space to its right so that letters don't touch. The set belongs to the video card, which carries it in its own firmware, so this table is what the screen has to work with.
Row is the high hex digit, column the low one. A is row 4, column 1 — $41, which is also 65, which is also what ASC("A") tells you.
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0x | ||||||||||||||||
| 1x | ||||||||||||||||
| 2x | ||||||||||||||||
| 3x | ||||||||||||||||
| 4x | ||||||||||||||||
| 5x | ||||||||||||||||
| 6x | ||||||||||||||||
| 7x | ||||||||||||||||
| 8x | ||||||||||||||||
| 9x | ||||||||||||||||
| Ax | ||||||||||||||||
| Bx | ||||||||||||||||
| Cx | ||||||||||||||||
| Dx | ||||||||||||||||
| Ex | ||||||||||||||||
| Fx |
What PRINT can reach
Not all of it — and this is the thing that catches people.
PRINT CHR$(n) goes through the Kernal's Chrout, and Chrout's video path passes $20 to $7E through to the screen, honours four control codes (carriage return, line feed, backspace and bell), and discards everything else. That includes every code from $7F up: all the box drawing, all the shading, every accented letter.
So this does nothing at all:
PRINT CHR$(219)The character is there on the card. It is Chrout that will not pass it on.
Getting at the rest
From assembly there is a second routine, VideoChroutRaw, which puts any of the 256 codes on the screen unfiltered. That is how a program draws a box or fills an area with shading — see The screen.
From BASIC, the way to reach the upper half is to redefine the characters you can print. The pattern table is writable, so you can point A at whatever shape you like and then print A.
Which codes are which
| Range | What is in it |
|---|---|
$00–$1F | Faces, card suits, arrows, musical notes. Historically the control codes; here they are pictures |
$20–$7E | Space, punctuation, digits, capitals, lower case — plain ASCII, and the only part PRINT will pass |
$7F | A house |
$80–$AF | Accented letters, currency, fractions, Spanish punctuation |
$B0–$B2 | Light, medium and dark shading — the three densities |
$B3–$DA | Box drawing, single and double lined |
$DB–$DF | Solid blocks: full, half, quarters |
$E0–$FE | Greek letters and math symbols |
$FF | A blank, distinct from space only in that it is a different code |
Where it lives
Not in the ROM. The video card keeps the set in its firmware and copies it into its own memory, at $0800–$0FFF of the card's 64 KB: 2 KB, 256 characters × 8 bytes each, exactly. That copy is the pattern table text mode draws from, and nothing in the computer's own address space holds another.
Because it is a copy, it can be changed and put back. Rewrite a character's eight bytes and every place it appears on the screen changes shape; the Kernal's InitVideo has the card copy its set in again, and VdpLoadFont copies it into any pattern table a program has set up. The screen covers both, and the character-set tricks that make text-mode games work.
📄 Character Set card — the whole grid plus every glyph's name, on three printable pages.

