Skip to content

Two Colours Per Square

Why Spectrum graphics look the way they do: colour is stored separately from pixels, and far more coarsely.

  • Sinclair ZX Spectrum
  • Machine code

A Spectrum screen is two things stored separately: the pixels, and the colours. They are not the same size, and the difference between them is the reason Spectrum games are recognisable at a glance.

The pixels

The picture is 256 by 192, one bit per pixel — a pixel is lit or it is not. That comes to 6,144 bytes, and those bytes carry no colour information at all.

The colours

Colour lives in a separate table of 768 bytes, sitting immediately after the pixels. There is not one entry per pixel. There is one entry per 8×8 square: the screen is 32 squares across and 24 down, and each square gets a single byte deciding how the whole square is coloured.

That byte is packed like this:

Code
  bit    7        6       5  4  3      2  1  0
       FLASH    BRIGHT      PAPER         INK

INK is the colour of the lit pixels, PAPER the colour of the unlit ones. Three bits each, so eight colours: black, blue, red, magenta, green, cyan, yellow, white. BRIGHT selects a brighter version of all of them, and FLASH swaps ink and paper on a timer.

Eight colours times two brightnesses is sixteen — except black is black at either brightness, so the famous sixteen are fifteen.

The rule that falls out of it

Read the byte again. Within any 8×8 square there is one ink and one paper: not one per pixel, one for the square.

BRIGHT is a single bit covering both of them, so bright ink over ordinary paper is not available. Whatever two colours a square uses, they come from the same eight.

Fifteen distinct colours, all of which can be on screen at once — because BRIGHT is decided per square, not for the whole display. But only two of them inside any one square.

What it looks like

Draw something across a square boundary and each part takes the colours of the square it lands in. Move it a single pixel and a whole 8×8 block changes colour at once.

This is attribute clash. The colour fringing around a moving sprite, the way a character seems to smear the background as it walks — that is not the artist. It is 768 bytes of colour covering 49,152 pixels.

Programmers answered it for fifteen years. Some built sprites to sit on the grid exactly. Some drew the moving parts monochrome and spent colour only on backgrounds that stayed still. Some let it clash and made it part of the style.

The compensation

The asymmetry cuts the other way too, and period code leaned on it hard.

768 bytes of colour against 6,144 of pixels is one eighth the work. Rewriting every colour on the screen costs the same as rewriting the pixels of just three rows of characters — and set against the frame budget from the last unit, that is an enormous difference.

So colour became the cheap thing to animate. Flashing, pulsing, colour-cycling, whole rooms changing hue between frames: all of it is code touching the small table and leaving the big one alone.

What to take from this

Colour on the Spectrum is not a property of a pixel. It is a property of the square the pixel sits in, and there are 768 squares. Sprite sizes, character design, level layout, what moves and what stays put — all downstream of that.

Sources

Sinclair Research, ZX Spectrum BASIC Programming, chapter 16, colours: 768 character positions, each with one INK, one PAPER, a brightness and a flash setting, and ATTR returning 128 for flash, 64 for bright, 8 × PAPER and INK; chapter 24, the memory: the display file from 16384 and the attributes from 22528, stored line by line. Alessandro Grussu, Spectrumpedia, volume 1 (English edition), p. 25: 256 × 192 pixels in a 32 × 24 grid of 8 × 8 blocks, and fifteen colours.