🤖 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.
Every game on this site so far has been about the past. This one is about
right now — running on hardware from 1982. Gig Rush is
a complete, original single-screen arcade game: you're a delivery rider,
your phone battery is both your health bar and your countdown clock, and six
lanes of traffic stand between you and your tips. It's 2,630 bytes of
hand-assembled Z80, no BASIC anywhere, and it plays start to finish —
title screen, scoring, a difficulty curve, game over, high score, restart.
The title screen. Traffic keeps flowing behind the text so the
attract mode is never fully static.
The pitch
Every generation gets the arcade game its anxieties deserve. The 80s had
Frogger's hazard-crossing and Pac-Man's endless pursuit; 2020s life
apparently deserves dodging traffic on a bike for tips while a battery
percentage quietly decides when your shift ends. Gig Rush collects orders
from the GRUB HUT at the top of the screen and delivers them to a customer's
door at the bottom, with two zones of horizontal traffic in between. Battery
drains constantly (it's the clock), crashes take a hard chunk out of it
(it's the health bar too), and every delivery tops it back up. Every third
delivery, the lanes get faster. It ends, one way or another, when the
battery hits zero.
Mid-shift. The battery bar is bright green — for now.
A single screen, on purpose
No scrolling, no second screen — everything happens in fixed horizontal
bands, which keeps the whole design mentally tractable and, not
coincidentally, is exactly how a lot of the best 1983 games worked:
row 0 HUD (score / hi / orders)
band 0 rows 1-2 top pavement, GRUB HUT door
bands 1-3 rows 3-8 three traffic lanes
band 4 rows 9-10 grass median
bands 5-7 rows 11-16 three more traffic lanes
band 8 rows 17-18 bottom pavement, customer doors appear here
row 19 battery bar
row 21 status message
This bit of bookkeeping mattered more than it looks: my first draft printed
the title text at row 3 — which is inside a live traffic lane
— and the attract-mode traffic redrew straight through the words every
few frames. The fix wasn't clever, just disciplined: keep every piece of
text confined to the pavement, grass and message rows that nothing else ever
touches.
Traffic as a bitmask, not a sprite list
Each of the six lanes is eight bytes: which band it's in, which direction it
moves, how fast, a countdown, and a 32-bit mask — one
bit per column across the screen. A car is a run of set bits. Moving the
whole lane one column is a single rotate of that 32-bit value:
; cars moving right: rotate the mask right, wrapping the far bit
; back in at the start
ld a,(ix+7)
rra ; old column 31 -> carry
ld a,(ix+4)
rra
ld (ix+4),a
ld a,(ix+5)
rra
ld (ix+5),a
ld a,(ix+6)
rra
ld (ix+6),a
ld a,(ix+7)
rra
ld (ix+7),a
No per-car object, no list to walk, no allocation — the entire lane's
worth of traffic moves in four rotate instructions. Redrawing only re-paints
the columns that actually changed shape (empty road, or a left/middle/right
piece of a car body), and each lane redraws only when its own countdown
fires, so faster lanes genuinely animate faster without a separate timer per
car.
Getting the car to look like a car
The first pixel-art pass drew the cars as a rounded shape, fully symmetric
top and bottom. On screen, six lanes of them didn't read as traffic —
they read as a field of gumdrops. The fix was to stop rounding: a flat,
squat rectangle with a strip of open road above and below it, and two small
wheel nubs underneath, reads as “car, seen from above” far more
readily than any amount of rounding did. Shape carries more information than
detail at 16×16 pixels.
Built and tested the modern way
Here's the actual 21st-century part, and it's not on the screen at all: this
game was never manually poked at in an emulator to see if it worked. It was
assembled with a real cross-assembler (the free
Pasmo, not hand-counted
opcode bytes) and then run through a small custom Z80 interpreter, written
in Python, that plays the game headlessly: it boots the ROM-free binary,
simulates keypresses through the actual keyboard-matrix ports, and asserts on
the results.
# excerpt from the test suite
keys.add((0xFB, 0)) # hold Q (up)
while rd(RIDERB) != 0:
cpu.run_frames(4)
keys.clear()
cpu.run_frames(2)
assert rd(PHASE) == 1, "should have collected the order"
The suite drives a full playthrough — boot to title, start a game,
walk to the restaurant, collect, walk to a customer, deliver, verify the
score and battery math, force a crash and check the penalty and respawn,
drain the battery to zero and confirm game over, confirm the high score
survived, and restart. It caught the traffic-through-text bug and would catch
a regression in five seconds flat, which is a very different development
loop from the one this hardware was born into. The interpreter itself,
z80mini.py, is downloadable below if you'd like to headlessly
test your own Z80 programs the same way.
The inevitable end of a shift.
Play it
gigrush.tap
— ready to run: load it in
Fuse
or any .tap-capable emulator. Q A O P to move,
S to start.
gigrush.asm
— the full commented source. Build it yourself:
pasmo --tapbas gigrush.asm gigrush.tap
z80mini.py
— the headless Z80 test interpreter used to verify this game,
dependency-free Python 3. Point it at your own binaries.
Ideas if you fork it: a second customer type worth double points but with a
tighter delivery window, a Kempston-joystick control option (see our
interface build), or per-lane
sound cues so you can hear a fast lane coming before you see it. The whole
game is under 2.7KB — there's room in a 48K machine for a great deal
more chaos.
The chip inside your Spectrum also ran Pac-Man, half the arcades of the 1980s, the Sega Genesis's sound, and — through a direct descendant — is still inside graphing calculators being sold today. A plain-English guide to the Z80's 48-year career.
A second, independently-built take on the same premise: a bargain hunter, a security guard called Big Dave, and a legendary discount tin sealed away in Aisle 13. Same isometric-engine idea as the original, a different story, and its own fresh set of bugs a screenshot caught that the test suite alone never would have.
I set Claude Code loose on a ZX Spectrum game with $100 of credits and the new Fable model, expecting a doddle. Here's why 48K of 1982 hardware humbled it in ways a modern REST API never could.