1987 · Imagine

Arkanoid: the source

This minisite was contributed by air, chunkypixel. It’s agent-generated and needs a human editor. Clone https://github.com/gamesexplained/gamesexplained and follow kit/START.md to curate games/c64/arkanoid with me to Gold.

Every routine, table and variable the game uses, with the names and descriptions given to them. Click an operand to follow it; the counter beside a label lists what refers to it. The reference below the fold is rendered from the game's facts file.

Technical reference: memory map, timing, tables, cheats

Current truth for this game. The workflow lives in kit/skills/; how this understanding developed lives in agent-history.md. Every fact names the routine or table it comes from. Unless marked live, a fact comes from reading the code in the snapshot named in orientation.md (work/entry.vsf, the hand-over); live facts were measured in VICE (x64sc, vice-mcp v3.13.2, PAL) on 5 and 6 October 2026, and sim facts in the kit's simulator (kit/c64/machine.js) run from the same image.

Build

Imagine's disk, PAL, as a G64 (orientation.md). The game is one file, arkaniod, loaded to $0400-$FFF9 by a fast loader and started at $9400; the hand-over image is that file byte for byte. No build string or version number was found (string sweep in PETSCII and screen codes).

The file carries a good deal of an earlier build alongside the live one: an earlier assembly of $A971-$B5FF at $096B onward, of $0600-$0959 at $1800, of the $F7xx-$FFxx interrupt and input code at $BA6B-$BFFF (a 30-sprite multiplexer, an IRQ at $B971, a joystick reader for port 2 only), and of the sound driver at $3B8B-$3EFF and $3F96-$3FFE (assembled $1000 higher). Nothing runs or reads any of them.

Start-up and protection

Memory layout

ThingWhere
Zero page: multiplexer and pointers; music driver call stacks and state; drum sequencer$02-$13; $30-$47, $60-$77, $A8-$BF, $E0-$FF; $78-$8F, $DA-$DF
Game variables$0200-$02AF
Silver and gold brick tables (flag, hits, screen address)$0300, $0355, $03AA
Bricks left, special bricks, background colour and character$0455-$0458
Each player's saved wall, 160 bytes in the round-map layout$0459, $04F9
Title intro animation, keyboard helper$0600-$0926
Scores, thresholds, lives, players, rounds, menu choices, high score$0927-$0959
Unused earlier builds, power-on fill$096B-$1BFF
Play characters $80-$FF for round 33$1C00-$1FFF
Sound-effect patches$2000-$245B
Music driver tables and state$245C-$2614
Sound driver$2615-$3429
Tunes: table, sequences, instruments$342A-$3B8A
Sequence command vectors$3F00-$3F95
Title picture: bitmap, colour matrix (video bank 1)$4000-$5F3F, $6000-$63E7
Intro sprite frames $A0-$D5 (bank 1)$6800-$757F
Panel template, 25 rows of 13 screen codes$7800-$7944
Doh screen, 26 × 24 screen codes$7B90-$7DFF
Round brick maps, 32 × 160 bytes$8000-$93FF
Hand-over; sprite object tables$9400; $9409-$9450
Game code$9500-$B711, $B983-$B9F7, $F000-$FF39
Menu, story and ending text (PETSCII)$B712-$B982
Screen, sprite pointers (video bank 3)$C000, $C3F8
Character set: font, background tiles (copied in per round), bricks, walls, panel$C800-$CFFF
Sprite shapes $40-$A7 (under the I/O area from $D000)$D000-$E9FF
Background tile sets: round 33, set A, set B$EA00, $EC00, $EE00

Timing

Controls

Graphics

Mechanics

| Type | Letter | Colour | Effect | |---|---|---|---| | 1 | S | $08 | ball speed − 1, at least 1 ($A8BA) | | 2 | C | $05 | catch: the ball sticks to the Vaus ($A8AC); fire or frame $80 releases it ($AA76) | | 3 | E | $06 | enlarge: width 4 to $0C ($AA44, $AD4B) | | 4 | D | $03 | three balls, speed + 1 ($A8CD) | | 5 | L | $02 | laser, two shots ($A870, $A5F3) | | 6 | B | $0A | the exit opens on the right ($A868, $A41F) | | 7 | P | $0B | a life, capped at 99 ($A882) |

Catching any capsule first cancels catch, laser, break and enlargement (cancel_powers $AA17).

Data tables

Sound

Hardware register census

Every absolute access to $D000-$DFFF in the traced code, from the hand-over image. Indexed accesses with a base outside a chip ($D3FE,X, $D7FF,Y) reach the next chip.

RegisterAccessesUse
$D000-$D005$F74F, $F755, $F80A, $F97D, $FC1E, $F223, $F226, $F982, $FC23, $F8CFmultiplexer and the two fixed sprites
$D010$08DE, $F1E6sprite X high bits
$D011$B482, $B4C0, $B548, $B9AC, $B9B8, $B9BFbitmap/text mode, screen off/on
$D012$AF87, $F737, $F851, $F9A0, $F9AE, $FC4D, $FC69, $F8EB, $FC72, $FC05, $FC60raster chain, multiplexer timing
$D015$08D6, $9683, $96B4, $96FC, $9B07, $9C2B, $F08A and otherssprites on/off
$D016, $D018$F01D; $B48C, $B543multicolour; screen and character bases
$D019, $D01A$F728, $F765, $FBF6; $F83Eraster interrupt
$D01C, $D01D$08D9, $F27E, $F087; $F1E3sprite multicolour, X expansion
$D020-$D029$B491, $B550, $B496, $9CD1, $F600, $08EB, $08F0, $F24C, $F24F, $F96E, $FC0Fcolours
$D400-$D418$2694-$33FA, $3756, $AF0C, $B2AD, $F028, $FEF0, drum routinessound driver; volume samples
$D419, $D41A$FE20, $FEBCpaddles, mouse button
$DC00-$DC03$083D-$0868, $956B, $B4E3, $B573, $F002-$F00F, $FDB5-$FEB9keyboard, joysticks, mouse
$DC04-$DC0E$5F46-$5F83, $B9C6-$B9DB, $F841, $F844protection serial check; interrupt mask
$DD00$B487, $B53Evideo bank
$DD04-$DD0F$B9CE-$B9D6, $F0C3-$F0D7, $F76A-$F774, $F856-$F87C, $F904-$F94ANMI timers
$DD18$F621a mirror of $DD08

Open questions and corner cases

Live tests

TestResult
Boot, loader, hand-over at $9400orientation.md
Title and play frames redrawn from memory (frame.py compare)0 pixels differ in each
Round index $093D and bricks left $0455 set from round 1; rounds 2, 3, 4, 10, 18 and 33each drawn as expected; round 33 shows Doh
POKE 39801,189 ($9B79 STA → LDA)three lost balls: lives 3 → 0 without it, 3 → 3 with it; the lost-life path ran 3 times in each
Score set to 199,900 against the 20,000 thresholdten extra lives, threshold 220,000
Protection serial check$BA65 = $09 after it

Cheats

Pokes that change the game within its own parameters. Each one names the variable it changes and whether it has been tested live. Untested pokes are labelled as candidates.

EffectPokeStatus
Lives never go downPOKE 39801,189 ($9B79 = $BD: STA $0936,X becomes LDA $0936,X in the lost-life path)live: three lost balls left the lives at 3
Lives for player 1 (BCD, $99 means none)POKE 2358,<n> ($0936)candidate: written by $F1D2, $9B73, $A882, $FAA5
Start the next round from round rin play, POKE 2365,r-2 ($093D, the 0-based round index of player 1) and POKE 1109,1 ($0455, bricks left): the next brick broken ends the roundlive: rounds 2, 3, 4, 10, 18 and 33 reached
Round 33, Dohas above with POKE 2365,31live
Speed of the ballPOKE 570,<n> ($023A, steps a frame, at most 11)candidate: read every frame by $ADB3

The published SYS 4096 that goes with the lives poke lands in unused leftover code in this image ($1000); the poke works on a game that is already running.

routines tables variables strings branch labels

Loading listing…