Egghead.page Logo

How to Create Custom Graphics on Sinclair ZX81

The Sinclair ZX81 allowed users to overcome its basic display limitations by redefining the standard character set through memory manipulation. This guide explains the process of creating User Defined Graphics (UDGs) by copying font data to RAM and altering specific byte values. We will cover the use of POKE commands, the structure of the 8x8 pixel grid, and how to redirect the system to recognize these new custom shapes for games and applications.

Understanding the ZX81 Character Set

The Sinclair ZX81 was designed as an affordable entry into home computing, relying heavily on a text-based display mode. By default, the computer utilized a character set stored in Read-Only Memory (ROM), which included standard alphanumeric symbols and a limited selection of block graphics. These built-in characters were fixed, meaning users could not alter them without moving the data into Random Access Memory (RAM). To create custom graphics, programmers had to bypass the ROM restrictions and establish a new character definition table in writable memory.

The 8x8 Pixel Grid System

Every character on the ZX81 screen was constructed from an 8x8 pixel grid. Each row of pixels within a character corresponded to a single byte of data, meaning one complete character required eight bytes of memory. The value of each byte determined which pixels were turned on or off within that row. By calculating the decimal equivalent of binary patterns, users could design specific shapes. For example, a byte value of 255 would light up all eight pixels in a row, while a value of 0 would leave the row blank. This binary mapping allowed for the creation of sprites, icons, and unique game elements that did not exist in the standard font.

Moving the Character Set to RAM

Because the original character set was locked in ROM, the first step in creating custom graphics was to copy the existing set into RAM. This ensured that the system still had access to standard letters and numbers while allowing specific entries to be modified. Users typically reserved a section of memory at the top of the available RAM to store this new character table. Once the data was copied, the system needed to be informed that the location of the character set had changed. This was achieved by modifying the system variable known as CHARS, which held the memory address of the current character definition table.

Using POKE Commands to Redefine Characters

With the character set safely located in RAM, users could alter specific characters using BASIC POKE commands. To change a character, the programmer calculated the memory address of the specific byte within the new table corresponding to the desired character code. They then POKEed the new decimal values into those addresses. For instance, to redefine a symbol to look like a small alien sprite, eight consecutive POKE commands would be issued to update each row of the 8x8 grid. After updating the data, a final POKE command was often required to update the CHARS variable address, pointing the ZX81 to the new custom table in RAM instead of the original ROM location.

Limitations and Memory Management

Creating custom graphics on the ZX81 required careful memory management, particularly on machines with only 1KB of internal RAM. Duplicating the entire character set consumed a significant portion of available memory, leaving less space for program code and variables. Users with the 16KB RAM expansion pack had much more freedom to design extensive custom graphic sets without crashing the system. Despite these constraints, the ability to redefine characters unlocked a new level of creativity, enabling developers to produce more visually engaging games and demonstrations that pushed the hardware beyond its original specifications.