Skip to content

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, and the name a generation of type-ins used for redefined characters on other machines too.

Look at the ZX Spectrum’s character set and, after the block graphics, you find what Steven Vickers’s manual calls “another copy of the alphabet from A to U”. They look like capital letters, but they are not in the ROM. They are twenty-one blanks for the programmer to fill: “characters that you can redefine yourself, although when the machine is first switched on they are set as letters - they are called user-defined graphics”.

UDGs were how most Spectrum owners first drew their own pictures. A program could turn the letter A into a spaceship, P into a man and Q into a wall, then build a game screen with nothing more than PRINT. The print routine treats a UDG exactly like a letter, so it takes colour, moves with AT and TAB, and sits in strings like any other character. The initials travelled: Computer Gamer’s graphics tutorial in July 1985 used “UDGs” for redefined characters on the VIC-20 and the Commodore 64 as well as the Spectrum.

Twenty-one characters in RAM

The UDGs are character codes 144 to 164, typed from the keyboard in graphics mode. Graphics mode, the manual explains, “occurs after GRAPHICS (CAPS SHIFT and 9) is pressed, and lasts until it is pressed again or 9 is pressed on its own”; in it, “each of the letter keys apart from V, W, X, Y and Z, will give a user-defined graphic”.

Each UDG is eight bytes, one for each row of its 8×8 square, top row first. In each byte bit 7 is the leftmost dot: a 1 shows the ink colour and a 0 the paper. Twenty-one of them take 168 bytes.

Those 168 bytes live at the top of RAM, above RAMTOP, and the system variable UDG at 23675 ($5C7B) holds the address of the first one. When the Spectrum is switched on, the ROM’s start-up routine copies the patterns of the letters A to U out of the ROM character set into the top 168 bytes of memory (the disassembly comments: “Now copy the character forms of the letter ‘A’ to ‘U’”) and points UDG at them. That puts them at 65368 ($FF58) on a 48K Spectrum and 32600 on a 16K one, and it is why an unused UDG prints as a capital letter. NEW clears memory only up to RAMTOP and keeps the value of UDG, so a set of graphics survives it.

How the ROM prints one

The ROM’s print routine sorts character codes into ranges. Codes 32 to 127 come from the character set (normally the ROM’s); 128 to 143, the block graphics, are built on the fly; 165 and above are keywords such as PRINT, which it spells out letter by letter. For codes 144 to 164 it subtracts 165 and adds 21, which leaves a slot number from 0 to 20, then fetches the base address from UDG. From there it runs the same code as an ordinary letter: multiply by eight, add the base, copy eight bytes into the display file and set the square’s colour attribute.

Defining one in BASIC

The manual’s example turns the UDG on P into the Greek letter π. It writes each row in binary with BIN, so the shape can be seen in the listing:

BASIC
  10 FOR n=0 TO 7
  20 READ row: POKE USR "p"+n,row
  30 NEXT n
  40 PRINT CHR$ 159;CHR$ 145
  70 DATA BIN 00000000,BIN 00000000,BIN 00000010,BIN 00111100,BIN 01010100,BIN 00010100,BIN 00010100,BIN 00000000

USR with a string is “a function to convert a string argument into the address of the first byte in memory for the corresponding user-defined graphic”, and the string can be the letter in either case or the graphic itself. USR "p"+n therefore walks through the eight bytes of the P graphic. (The manual’s own version uses INPUT row and asks you to type the eight BIN numbers.) Line 40 prints code 159, which is P (144 + 15), and code 145, which is B. Run on a 48K Spectrum, it prints π followed by a capital B, because B has not been redefined.

A whole set can be kept on tape. The manual suggests SAVE "chess" CODE USR "a",21*8, “eight bytes for each of 21 graphics”, and loading it back with LOAD "chess" CODE USR "a", so the bytes land in the right place even on a Spectrum with a different amount of memory.

More than twenty-one

Twenty-one characters are not many for a game. Because the ROM looks up the address in UDG every time, a program can point it somewhere else. The +2 manual’s description of the variable says “you can change this, for instance, to save space by having fewer user-defined graphics”, and the same trick gives more: keep several sets of 168 bytes in memory and switch between them with two POKEs. David Laine’s Machine Code Applications for the ZX Spectrum used UDG as a pointer to a block of sprite data, “switching amongst them is done by changing the contents of UDG”.

Utilities did the same job for BASIC programmers. CRASH’s second issue, in March 1984, reviewed Print ‘n’ Plotter’s Paintbox, a £9.95 drawing package by Joe Gillespie, whose UDG editor “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 later Spectrums took two away. On the 128K machines the codes for T and U became the new keywords SPECTRUM and PLAY; the +2 manual notes that they “have replaced the user defined graphics characters for the keys T and U (values 163 and 164) under 128 BASIC”. In 48 BASIC all 21 are still there.

Machine-code games usually skipped the mechanism altogether. The print routine can only place a character on the 8×8 grid, so a game that wanted a sprite at any pixel position wrote its bytes into the display file itself, though its graphics were often designed as 8×8 blocks in exactly the same format. See Character graphics.

On other machines

Other computers offered the same idea in different sizes:

  • BBC Micro: by default 32 characters can be defined with VDU 23, followed by the character code and its eight row bytes, and they occupy memory from &C00 to &CFF. The command *FX 20 “explodes” the allocation so that every character from 32 to 255 can be redefined, at the cost of more memory.
  • Amstrad CPC: SYMBOL defines a character from eight row values, and SYMBOL AFTER sets how many can be redefined. The default is 240, “giving 16 user defined characters”; SYMBOL AFTER 32 makes the whole set from 32 to 255 redefinable.
  • Commodore 64: there is no separate UDG area. The video chip reads all 256 characters from one set, so a program copies the ROM characters into RAM, changes the ones it wants and points the chip at the copy. Commodore’s Programmer’s Reference Guide warns that “it is an all or nothing process”, and has BASIC fence off the memory first with POKE 52,48:POKE56,48:CLR.

Sources

  • Steven Vickers, Sinclair ZX Spectrum BASIC Programming, edited by Robin Bradbeer (Sinclair Research, 1982; second edition 1983): chapter 1 (graphics mode), chapter 14, pp. 92–94 (user-defined graphics, BIN, USR, the π example), chapter 20, pp. 147–148 (saving and loading the set), chapter 24, p. 168 (NEW and RAMTOP).
  • Ian Logan and Frank O’Hara, The Complete Spectrum ROM Disassembly (Melbourne House, 1983): PO-ANY and PO-T&UDG at 0B24 and 0B52, the start-up routine at 11CB, and the USR string function at 34BC.
  • The Guide to the Spectrum ROM (Hilderbay): the UDG variable at $5C7B.
  • Sinclair ZX Spectrum +2 manual (Amstrad, 1986): the UDG system variable, and T and U in 128 BASIC.
  • David Laine, Machine Code Applications for the ZX Spectrum (Sunshine): switching data blocks through UDG.
  • CRASH issue 2, March 1984, p. 72: review of Paintbox.
  • Andrew C. Bray, Adrian C. Dickens and Mark A. Holmes, The Advanced User Guide for the BBC Micro (Cambridge Microcomputer Centre, 1983): OSBYTE &14 (*FX 20) and page &C00.
  • Amstrad, CPC664 User Instructions (1985), chapter 3: SYMBOL and SYMBOL AFTER.
  • Commodore, Commodore 64 Programmer’s Reference Guide (1982), pp. 108–110: programmable characters.
  • Computer Gamer issue 4, July 1985: graphics tutorial covering UDGs on the VIC-20, Commodore 64 and Spectrum.
  • The Home Computer Course, part 19: a VDU 23 character definition on the BBC Micro.

See also

Checked. Verified against primary sources and signed off by a person.