← Back to all articles

A Minion on your Spectrum

16 August 2026

Z80TutorialSprites

🤖 AI-generated content: this article was written by an AI assistant (Claude), not by the site's owner — the choice of what to cover and every word of it. See the About page for the full policy.

Something Speccy and something modern: a certain goggle-wearing yellow henchman, running on hardware from 1982. This is a complete, working machine-code program in 321 bytes — not a game, just the beating heart of one: a sprite you steer around the screen with Q A O P (up, down, left, right), with SPACE to exit politely back to BASIC. Every technique in it is a building block you'd use in a real Spectrum game.

16x16 pixel sprite of a small yellow character with a black goggle and cyan dungarees, shown enlarged
Our hero, 16×16 pixels. Original pixel art, affectionately inspired by a certain film franchise's yellow henchmen.

Designing a sprite the Spectrum's way

The Spectrum gives each 8×8 cell exactly one ink and one paper colour — the infamous colour clash. Fight it and you lose; design with it and nobody notices. Our sprite is 16×16 pixels = a tidy 2×2 block of cells, moved in whole-cell steps, so it always owns its cells outright: the top two get bright yellow ink (the face), the bottom two bright cyan (the dungarees). The colour boundary is part of the character design. That's the trick behind most 80s Spectrum sprites.

sprite:
    defb 0x0F,0xF0      ; ....XXXXXXXX....   head
    defb 0x3F,0xFC      ; ..XXXXXXXXXXXX..
    defb 0x7F,0xFE      ; .XXXXXXXXXXXXXX.
    defb 0x7F,0xFE      ; .XXXXXXXXXXXXXX.
    defb 0xF8,0x1F      ; XXXXX......XXXXX   goggle
    defb 0xF9,0x9F      ; XXXXX..XX..XXXXX   the eye
    defb 0xF8,0x1F      ; XXXXX......XXXXX
    defb 0xF0,0x0F      ; XXXX........XXXX   grin
    defb 0xFF,0xFF      ; XXXXXXXXXXXXXXXX   dungarees from here
    defb 0xBF,0xFD      ; X.XXXXXXXXXXXX.X   strap buttons
    ...

Notice you can read the picture straight out of the hex comments — sprites on the Spectrum are just bytes, one bit per pixel.

The infamous screen address

The Spectrum's bitmap is not laid out linearly — the rows are interleaved in thirds (a hardware shortcut that haunted every programmer of the era). For cell-aligned work the classic formula is:

; HL = 0x4000 + ((y & 0x18) << 8) + ((y & 7) << 5) + x
scraddr:
    ld a,(ypos)
    ld c,a
    and 0x18
    or 0x40
    ld h,a
    ld a,c
    and 7
    rrca
    rrca
    rrca            ; (y & 7) << 5, via rotate
    ld c,a
    ld a,(xpos)
    or c
    ld l,a
    ret

Within a cell, moving down one pixel line is just inc h — which is why the sprite is drawn as two 8-line cell halves.

Reading QAOP for yourself

No BASIC, no ROM: the keyboard is hardware you can read directly. Each half-row of keys lives on port 0xFE, selected by the high byte of the address, one bit per key, active low:

    ld a,0xDF       ; half-row P O I U Y
    in a,(0xFE)
    rra             ; bit 0 (P) -> carry
    jr c,notp       ; carry set = not pressed
    ; ... move right ...

Flicker-free movement

The main loop waits for the 50Hz frame interrupt with a single halt, then erases the sprite at its old position and redraws at the new one — all while the TV beam is still near the top of the frame. A small counter moves the character only every fourth frame, which turns “teleporting” into “walking”. And when you press SPACE, one call to the ROM's CLS routine hands you back a tidy BASIC prompt, like nothing ever happened.

A mostly black Spectrum screen with the small yellow and cyan sprite standing mid-screen
Mid-wander. This screenshot was produced by actually executing the program's bytes in an instrumented Z80 interpreter.

Try it, then break it

Then make it yours: redraw the sprite bytes (any character fits in 2×2 cells), change the colours, add a second sprite, make Kempston joystick input work (port 31 — see our interface build), or add pixel-level movement with pre-shifted sprites. That last one is exactly one rabbit hole away from writing an actual game — which is how everyone got started in 1983.