User Defined Graphics (UDGs)
Custom 8×8 character glyphs on the Sinclair ZX Spectrum
Twenty-one programmer-supplied 8×8 patterns, codes 144 to 164, that the Spectrum's print routine treats as ordinary letters: the manual's route from BASIC into pixel graphics.
A UDG — User Defined Graphic — is a programmer-supplied 8×8 pixel pattern that the Spectrum’s character system treats as if it were one of the resident font glyphs. The manual introduces them as “another copy of the alphabet from A to U. These are characters that you can redefine yourself”. Sinclair BASIC reserves twenty-one slots, character codes 144 to 164, addressed from USR "a" through USR "u"; once defined, a UDG can be printed with PRINT CHR$ 144, typed into a string in graphics mode, or used anywhere a character can. The eight bytes that describe each one live in the UDG buffer — 65368 ($FF58) on a 48K machine — and the system variable UDG ($5C7B, 23675) points to wherever the buffer currently sits.
UDGs are the BASIC programmer’s bridge into pixel art. Without them, the smallest thing a BASIC program could put on screen with PRINT was a character from the ROM font; with them, every character on screen could be a hand-drawn piece of art.
How they work
The ROM’s character set holds 96 glyphs (codes 32 to 127). When the print routine meets a code from 144 to 164 it reduces it to a slot number 0 to 20 (SUB +A5 then ADD A,+15), multiplies by eight and adds the address in UDG — the disassembly’s commentary reads “Fetch the base address of the UDG area” — and draws the eight bytes it finds there exactly as it would draw a letter. Everything downstream, including the attribute write, is the same code path as ordinary text.
Each UDG is exactly 8 bytes. Top row first, bottom row last; within each byte, bit 7 is the leftmost pixel:
Row 0: byte 0 — top pixel row
Row 1: byte 1
...
Row 7: byte 7 — bottom pixel row
So 21 UDGs × 8 bytes = 168 bytes. At switch-on the ROM copies the character forms of the letters A to U into the top 168 bytes of RAM and points UDG at them, so the slots are never empty: an undefined UDG prints as a capital letter. NEW preserves UDG, so a program can leave its graphics in place across a restart.
Defining a UDG in BASIC
The manual’s own method is a loop that pokes eight rows:
10 FOR n=0 TO 7
20 READ b
30 POKE USR "a"+n, b
40 NEXT n
50 PRINT CHR$ 144
60 DATA 24,60,126,90,255,90,36,36
USR with a string argument “is a function to convert a string argument into the address of the first byte in memory for the corresponding user-defined graphic”, so USR "a"+n walks the eight bytes of slot A. The manual suggests writing each row as BIN followed by eight 0s and 1s — “0 for paper, 1 for ink” — so the shape is visible in the listing. Line 50 prints the result at the cursor.
The same loop works for any of the 21 slots. A whole set can be saved and loaded as one block: SAVE "chess" CODE USR "a",21*8 stores “eight bytes for each of 21 graphics”.
Typing a UDG into a listing is a small ritual. Graphics mode “occurs after GRAPHICS (CAPS SHIFT and 9) is pressed, and lasts until it is pressed again or 9 is pressed on its own”; in that mode “each of the letter keys apart from V, W, X, Y and Z, will give a user-defined graphic”. Magazine type-ins had to explain the sequence every time — Computer Gamer’s 1985 tutorial has the reader “press Caps Shift + 9 … until a flashing G appears”.
Defining a UDG in assembly
Assembly programs usually bypass the UDG mechanism and write to the bitmap directly. The design discipline is identical — eight bytes, one bit per pixel, bit 7 leftmost — but the destination is the cell’s own row addresses in the display file rather than the UDG buffer:
Cell (row, col) → top bitmap byte at:
$4000 + (third × $0800) + (row_in_third × $0020) + col
Subsequent rows of the same cell are at +$0100, +$0200, ..., +$0700.
The UDG mechanism is convenient for BASIC programs that want graphics in a string. A machine-code game that wants a sprite at an arbitrary pixel position writes the bytes where the sprite should appear.
Beyond twenty-one
Twenty-one slots was a real limit, and the software market answered it. CRASH reviewed Print ‘n’ Plotter’s Paintbox in its second issue: it “allows you to create four times as many UDG’s as there are in the normal Spectrum BASIC by storing in four banks of 21 UDG sets into memory, which can then be called selectively into the normal UDG area”. The trick is only a change of UDG: point the system variable at a different 168 bytes and the same codes print a different set.