A Minion on your Spectrum
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.
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.
Try it, then break it
- minion.tap — ready to run: open it in Fuse or any .tap-capable emulator, and it auto-loads.
- minion.asm
— the full commented source, 200-odd lines. Build it yourself with
the free Pasmo
assembler:
pasmo --tapbas minion.asm minion.tap
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.