1987 · Imagine

About this page

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.

Footprint

Every byte of the C64's 64 KB, one pixel each, 512 to a row. Lit pixels are what this game is: its code, graphics, level data, sound, text, tables and variables, exactly where they sit in memory. Dim areas are screen and working memory; dark is unused.

WhatBytesOf 64 KB
Program64,17097.9 %
Code23,67336.1 %
Graphics25,89639.5 %
Level data5,1207.8 %
Sound3,7245.7 %
Text9501.4 %
Tables3,4765.3 %
Variables1,3312.0 %
Screen, bitmap, colour, stack, I/O1,2802.0 %
Unused860.1 %

Status

Tiersilver
Coverage100 % of the bytes the game uses have a description
Build analysed
Copyagent-draft
Toolshost: Linux 6.18 x86_64, Ubuntu 24.04 cloud container with four cores and no display, emulator: VICE, release v3.13.2, v3.13.2-linux-x86_64-gui.zip, disassembler: regenerator2000 0.9.20, python: 3.11.15, node: 22.22.0
Modelclaude-opus-5-5
Kit version0.0.60

Contributors

Other places to love this game

What the game does, and where we found it

Read this before annotating code. What the game is documented to do, with verification status against the binary. Statuses: open (documented, not found yet), traced (in the code, could not be exercised; say what was tried), confirmed (in the code, consistent with the emulator), live (observed directly), differs (the code does something else). "Absent" is not a status.

Sources:

Features

FeatureStatusWhere
Title picture: IMAGINE / TAITO, the ship Arkanoid and the Vaus, signed "Jones"liveshow_title_picture $B480; reference/title.png
Input menu: Neos mouse, joystick, keyboard or paddles; 1 or 2 devices; 1 or 2 players; chosen by first letter (N J K P D 1 2); fire startsliveinput_menu $B557, keys $B5BD; reference/menu.png
Joystick: fire on port 1 starts the game from the menulive$B5AC; player 1's stick is port 1, player 2's port 2 with two devices (read_joystick $FDA2)
Story text before round 1livestory_text $B7FE, printed by $B672; reference/story.png
Attract mode: the game plays itselfconfirmedattract_mode $9500: rounds 5, 14, 21, 24 in turn, the Vaus following the ball. Live: round 5 seen
Two players, alternating, each with score, lives and round in a paneltraced$9BE0-$9C31, saved walls $0459/$04F9; the simulator ran a two-player keyboard game, not checked on screen
The Vaus moves left and right; the ball bounces off it, the walls and the brickslivebat_collision $ABB3, move_ball $B334, ball_vs_bricks
The bounce angle depends on where the ball meets the Vaus (search, arcade)confirmedthree zones a side, $ABB3; the inner two are swapped between the sides (facts.md)
Ball speed rises as the round goes on (search, arcade)tracedper brick hit $AF5F, and with time since the life began $ADE7
33 rounds; round 33 is DOH, the boss, hit about 25 times (search)differs33 rounds, confirmed live; Doh takes 23 hits by its counter ($95F4, $B11E, $9637), not tried live
32 rounds of bricks (search)live$8000-$93FF; rounds 2, 3, 4, 10 and 18 drawn live
Bricks of several colours; silver bricks take several hits; gold bricks cannot be destroyed (search, arcade)confirmed$F40E; silver 2 to 5 hits by round group ($F52A); gold never counted ($B010). silver bricks seen live in round 3 (reference/round03.png)
Capsules fall from broken bricks; catching one gives its power (search)livechoose_capsule $B2E6, update_capsule $A995; a green type 2 capsule, letter C, seen falling in round 1, and the $0237 capsule type read live
S: slow the ball (search)traced$A8BA: speed − 1, at least 1
E: enlarge the Vaus (search)traced$AA44, $AD4B: width 4 to $0C
D: disruption, the ball splits into three (search)traced$A8CD, and speed + 1
L: laser, the Vaus fires (search)traced$A870, fire_laser, two shots
C: catch, the ball sticks to the Vaus until fire (search)traced$A8AC; released by fire or after frame $80 ($AA76)
B: break, an exit opens on the right and passing through it ends the round, with a bonus (10,000 in the arcade) (search)differs$A868, $A41F: the exit opens and ends the round, but no bonus is added on that path
P: an extra Vaus (search)traced$A882: lives + 1, capped at 99
Enemies drift down from gates in the top wall and are destroyed by the ball or the Vaus (search, arcade)confirmedupdate_enemies $9F5E; destroyed by ball, laser or Vaus; only the gate at X $47 is ever used. Enemies seen live in round 1
Score, high score, lives and round shown beside the playfieldlivedraw_side_panel $F2B5, update_scores_display $FAFE
Four lives at the start (this game's panel)live$F1D2
Music by Martin Galway; the C64 theme played samples on a fourth voice, the first published sampled sounds on the C64 (search)confirmedthe driver $2615-$3429; drum samples written to the volume register by a sequencer $FEF4 and six drum routines. The composer's name is not in the image
Code by David A. Collier, graphics by Mark Kevin Jones (search)openno names in the image; the title picture is signed "Jones"
Cheat: POKE 39801,189 then SYS 4096 for unlimited lives (search, source page not read)live$9B79: STA $0936,X becomes LDA; lives kept live. SYS 4096 ($1000) is unused leftover code in this image, so the poke works only in a running game
Paddles, Neos mouse and keyboard control (search; also the menu)traced$FE09, $FE43, $FD7B; the simulator ran the menu with each, not tried live
High-score table with name entry (Galway's "High Score Music") (search)differsthe game keeps one high score ($0941-$0943, $FB28) and has no name entry: no writer of a name buffer was found, and the words NAME, ENTER, HALL, FAME, BEST and TOP appear in the image under no constant offset except as chance matches inside code and sound data ($FFC7, $223B, $59B7; work/scripts/textsearch.py)

Beyond the documentation

Found in the code, not in the manual.

FeatureStatusWhere
Extra life every 20,000 pointslivecheck_extra_life $FAA5
Brick values differ by colour: 70 to 130tracedbrick_points $B2C4
The joystick's Vaus moves faster as the ball speeds uptracedjoystick_step $FDBF
A capsule is worth 1,000 points, an enemy 100traced$A9DD, $9F45
Sampled drums play on the title screentraceddrum_play $FEE0
A copy-protection check through CIA 1's serial portlive$5F42; $BA0A

Open questions

How the analysed state was reached

How to get from the contributor's own copy to the analysed state. Someone else must be able to follow this exactly.

The image

arkanoidimagine_1988pal.g64 as uploaded by the contributor (325,814 bytes, SHA-256 0ad3045ebd137dfeebbbb7c19cc597481f7af5a7141ea735cdbff5c4e3a43fe1), copied to work/arkanoid.g64. Its header reads GCR-1541, 42 tracks: a GCR-level copy of a disk. The directory, as VICE's c1541 lists it:

0 "".... ."0:*",8,1" ..
1    "????????????????" prg
254  "arkaniod"         prg
5    "f"                prg
396 blocks free.

The disk's name is the instruction to the player: LOAD"0:*",8,1. All three files read through the standard DOS chain with c1541 -read:

FileLoad addressWhat it is
????????????????$0316-$0401the boot: loaded with ,8,1 it overwrites the KERNAL's RAM vectors, and its output vector $0326 points at a stub at $0363 that puts $F1CA back, loads F with the KERNAL and jumps to $4000
f$4000-$43FFthe fast loader: drive code and the C64 side, which ends in the stack page ($0100-$01FF)
arkaniod$0400-$FFF9the whole game, 64,506 bytes, one file

The arkaniod file is byte for byte the RAM from $0400 to $FFF9 at the hand-over (work/entry.vsf): the fast loader moves nothing and unpacks nothing. The file name's spelling is the disk's. The pictures are Imagine's, the title says "© TAITO 1986 © IMAGINE 1984" on its menu, and no cracker's screen or trainer appears: the image behaves as the original release. The upload's name says 1988; the menu says nothing of the year of this release.

From power-on to play

  1. Power-cycle the emulator (vice_machine_reset, mode: hard). The machine is PAL. VICE's default drive settings (true drive emulation) load it with no vicerc.
  2. Autostart work/arkanoid.g64 (VICE types LOAD"*",8,1, which loads the first file, the boot). Turn warp on: the fast loader runs from the stack page ($0130-$01D8, reading bit pairs from $DD00 and flashing the border) and reaches the hand-over about 76 s of host time after the autostart (measured 5 October 2026). Turn warp off.
  3. The hand-over: the loader sets $01 = $35, masks both CIAs' interrupts, SEI, JMP $9400. A stopping checkpoint on $9400 stops it there; work/entry.vsf was saved at that stop.
  4. The title picture (a bitmap, "IMAGINE / TAITO", the ship and the Vaus, signed "Jones", reference/title.png) shows. Fire on joystick port 2, held a second and a half, brings up the menu (reference/menu-paddles.png, with paddles selected); fire on port 2 on the menu then did nothing.
  5. The menu: "SELECT YOUR INPUT DEVICE": Neos mouse, joystick, keyboard, paddles; 1 or 2 devices; 1 or 2 players, chosen with N, J, K, P, D, 1 and 2. Press J (joystick, reference/menu.png), then fire on joystick port 1: the story text shows (reference/story.png), then the title picture again, then round 1.
  6. Round 1, one player, four lives. work/play-round1.vsf was saved about ten seconds into it (a life already lost, score 1330).

Snapshots in work/, each saved without ROMs:

FileState
entry.vsfthe first instruction of the game, $9400, from a power-cycled machine. The disassembler and the listing are built from this one
play-round1.vsfround 1 under way, step 6

entry.vsf and play-round1.vsf hold the same bytes everywhere but the variables (zero page, $0200-$05FF), screen memory ($C000-$C3FF) and a few scattered bytes in $2400-$2FFF, $5F00, $9400-$BFFF and $F000-$FFFF; the RAM under $D000-$DFFF is identical. The hand-over keeps the start-up code and authored data as loaded, so it is the image analysed.

Steady state

In play: $01 = $35 (RAM at $A000 and $E000, I/O at $D000); the KERNAL is out, so the game owns the hardware vectors. CIA 2 port A ($DD00) low bits %00: video bank 3, $C000-$FFFF. $D018 = $03 outside the splits.

The hand-over runs $9400 (LDA #$35 / STA $01, an undocumented two-byte NOP, JMP $095A), and $095A is written with more undocumented opcodes (NOP abs,X, LAX $F004, NOP zp) around a JSR $B9C3 and a JMP $F000.

The interrupts, from one recorded frame of play (kit/c64/frame.py capture): a chain of raster interrupts, each handler writing the next one's address into $FFFE/$FFFF: $F75E (set on line 247), $FBEE (set on line 21), $F720 (set on line 26). The NMI vector $FFFA/$FFFB alternates between $F855 (set on line 52) and $F903 (set on line 246). Sprite Y positions are written on lines 22-25 and cleared on line 245.

Nothing is reloaded: the whole game is in memory after the one load.

The emulator

release v3.13.2, v3.13.2-linux-x86_64-gui.zip; check-emulator passed 57 of 57 on 5 October 2026. No check failed, so no workaround applies.

The loader, in a paragraph

LOAD"0:*",8,1 brings in a 236-byte file at $0316 that replaces the KERNAL's RAM vectors, so the KERNAL's next character output runs the stub at $0363. That stub restores the output vector, loads the 1 KB file F to $4000 with the KERNAL and jumps to it. F sends drive code to the 1541 and installs a two-bit receiver in the stack page, which reads the arkaniod file over the serial bus's clock and data lines ($DD00), flashing the border on every byte. It then puts the KERNAL's serial bus back with $ED0C/$EDB9/$EDDD/$EDFE (LISTEN, SECOND, CIOUT, UNLISTEN), turns the screen on, and jumps into the game. Not annotated further, by policy.

The symbol map for this game is symbols.json; the listing behind the Source tab is listing.json. Write-ups, facts and symbol maps are CC BY-SA 4.0. The game itself is not hosted here.