1987 · Pandora

About this page

This minisite was contributed by air, Nico-van-der-Zijden. It’s agent-generated and needs a human editor. Clone https://github.com/gamesexplained/gamesexplained and follow kit/START.md to curate games/c64/into-the-eagles-nest 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.

Status

Tierplatinum
Coverage100 % of the bytes the game uses have a description
Comments checkedAudited & high error rate. Every comment was audited twice, but the last sample of 60 comments had 4 wrong, more than one in 30, so between 3 and 16 % of the listing’s comments are likely wrong. How listings are checked
Build analysedPAL cassette, Pandora, inlay stamped 1986, analysed at the loader's hand-over
Copyagent-draft
Toolshost: Linux 6.6 x86_64 (WSL2) on Windows 11 Pro 10.0.26200, Ubuntu 26.04, Intel x86_64, display through WSLg, emulator: own build of github.com/barryw/vice-mcp, release v3.13.2, commit 1e83aab134; driven through kit/c64/vice.py; check-emulator 57 of 57, disassembler: regenerator2000 0.9.20, publication: Python 3 and node 24; symbols_export.py, listing.py and build.py
Modelclaude-opus-5
Kit version0.0.244

How the listing was checked

Every step that measured the Source tab’s comments or made them more accurate, in the order it happened, with the models that did it. Accuracy of the Source explains each step and what the row above makes of them.

StepByWhat it foundOf the listing
Researchclaude-opus-5Looked the game up online (its manual, reviews or wiki pages) before reading its code.
Annotationclaude-opus-5Wrote the listing’s comments. 100 % of the program is described, in 670 comments.
Port checkclaude-opus-5Checked a page’s port or widget against the game and corrected 1 comment it showed wrong.
the music driver, which took the tune's first notes a tick late where the game takes them in the same call
Sample 1claude-opus-513 of 60 comments wrong, so between 13 and 34 % of the listing is likely wrong. All 13 were then corrected.
every one of the 13 was read against the code again and held; an audit is recommended
Port checkclaude-opus-5-5Checked a page’s port or widget against the game and corrected 21 comments it showed wrong.
the chests, the shot and the tape: open chests put in front of the player in the game, a shot followed frame by frame, and the tape image decoded by the loader's rules, after the contributor questioned the chest odds
Port checkclaude-opus-5-5Checked a page’s port or widget against the game and corrected 2 comments it showed wrong.
the chest widget's odds, checked against tables built by the game's own loop with the sound chip running
Audit 1Nico-van-der-Zijden, with claude-opus-5-5Checked all 667 comments and corrected 205.
and every claim in facts.md, 28 of 114 corrected; made on the contributor's run, not by a maintainer
Sample 2claude-opus-5-55 of 60 comments wrong, so between 4 and 18 % of the listing is likely wrong. All 5 were then corrected.
after the audit, by a checker that took no part in it; made on the contributor's run, not by a maintainer
Audit 2Nico-van-der-Zijden, with claude-opus-5-5Checked all 671 comments and corrected 78.
the comments again, by five new checkers told the kinds of error found; made on the contributor's run, not by a maintainer
Sample 3claude-opus-5-54 of 60 comments wrong, so between 3 and 16 % of the listing is likely wrong. All 4 were then corrected.
after the second audit, by a checker that took no part in it; made on the contributor's run, not by a maintainer
Play tabclaude-opus-5-5Ported the whole game to JavaScript for the Play tab and corrected 14 comments it showed wrong.
the whole game ported routine by routine and held in lockstep with its own code; 14 comments the port showed wrong were corrected

likely wrong the sample’s range corrected right, or likely right not yet measured

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
Joystick in control port 2 steers the player: up, down, left, rightliveHeld on work/play-mission1.vsf with nothing else moving: each direction moves the player's sprites 8 pixels every 4 frames (work/controls.py), which is the four-frame count at $42AC
The player is drawn as four sprites in a 2×2 blockliveSprites 0 to 3, placed round $02DF and $02E0 by the interrupt's second band
Fire shoots in the direction of travelliveFire alone put a bullet at (147,158), to the player's right; left and fire together put it at (112,167), at the player's left edge (work/fire.py). $45BD takes the direction from the facing in $02B0
Two shots can be in the air at onceconfirmed$463F fires the second once the first has taken eight steps of 8 pixels; each has its own direction, position and distance, in bits 0 and 4 of $02AF
A shot costs one round of ammunitionliveThe panel's ammunition digit went from 9 to 8 on the frame the bullet appeared; $4659 takes one off $02BD in decimal mode
SPACE pauses, and SPACE, the stick or fire resumesliveA tap stops the counter at $02B4; the next tap starts it again (work/pause4.py). The paused game shows "...PAUSING..." on the message line (work/t_hits.py). $5FCB scans one key, row 7 column 4
RESTORE abandons the game and restarts itlivevice_keyboard_restore in play put the machine in the attract loop within two seconds (work/restore.py). The CBM80 signature at $8004 sends the NMI to $8031
Four missions in a castle: rescue each of three captives, then blow the castle upconfirmed$0836 holds 1 to 4; $4010 is the floor the prisoner is on for three of them and $FF for the fourth
The mission the screen calls 1 is the demolitiondiffersThe manual (page 4) says mission four blows the castle up. The digit drawn at $1DBE is five minus $0836, and stepping the screen to 1 gave the briefing "MISSION 1 / BLOW UP THE CASTLE" (work/t_mission2.py)
A second castle, harder, after the first is destroyedopenManual, page 4. Nothing in the code chooses a second set of floor descriptions: the map builder always reads $D000 plus a kilobyte a floor. The only other tile-shaped data, 999 bytes at $8C00, is reached by no instruction, by name, as a pointer or through an index (the references search)
Four floors, named BASEMENT, GROUND FLOOR, FIRST FLOOR and SECOND FLOORconfirmedThe four names, 13 characters and a $00 each, at $1A78, drawn by the floor-select screen at $1AB2; the message line names the same four at $5808
An elevator pass is needed to work the elevatorsconfirmedThe lift is tiles $54 and $55. $5040 reads $02C8, which $5002 sets when a pass is picked up: with one it says "YOU ARE ENTERING THE LIFT." and the main loop takes the player to the floor select, and without one it says "YOU NEED A LIFT PASS !". Not exercised: no lift was reached in play
Four detonators, one per floor, for the demolition missionconfirmed$5F9A to $5F9D, one byte a floor, set by $5386 when a shot reaches a charge, and all four tested at $5F75
Keys open steel doors; a key is spent on eachtraced$50F7 opens a steel door and $02AC counts the keys. Not exercised in play
Wooden doors are opened by shooting themtracedTiles $47 and $48 go to $5192 through $54F3 and $5508
Doors that were opened are locked again while the player is on another floorconfirmedTaking the lift rebuilds the whole floor from its description at $6A4B, so nothing a mission changed in the map survives
Nazi soldiers take two shots each to killconfirmed$6EAA sets bit 6 of the figure's kind byte on the first hit and clears its tiles only on the second
The soldiers shoot back and do great damagediffersThey do not shoot at all. $639F is the only routine that adds to the hit count, its four callers are all the "the tile ahead holds the player" branches of the figures' movement, and the other writes to $02C6 the references search finds clear the count or take hits off it ($4058, $4077, $4F23, $4FA2). C64-Wiki is right and the manual (page 4) is wrong for this version
50 hits kill the playerlive$5BC8 compares the hits with $50, and the count is binary-coded decimal: poked to $49 the game played on, poked to $50 it ended (work/t_death.py)
The player flashes as the limit nearsopenNothing found that changes the player with the hit count: the sprite colour registers are written only at $424D, $4C51 and $4CB2, neither of which reads $02C6, and the references search lists every reader of the hit count as the panel, the save between missions, the nags and the death test
First aid and cold food heal hitsconfirmed$4F08 takes $10 off the hits in decimal mode, which is ten, and $4F90 clears them altogether
Drunken officers are harmless, and worth points when shotopenThe figures are tiles $76 to $C0, and a shot that hits one goes to $6EAA, which finds it on the figure list: the first hit sets bit 6 of its kind in $8500, and a second asks for sound 8, sets bit 5, clears its sixteen tiles from the map and scores 100. Whether one of the four kinds leaves the player alone has not been traced. Tiles $5E to $6D, once read as officers, are the chests
Chests are shot open; shooting an open chest can destroy what is in itconfirmedA closed chest is tiles $5E to $61, and a shot sends it to $5528, which opens it. Jewels showing in an open chest ($66 to $69) are taken by walking into them ($5CB9, $5DA6), and shooting them instead ($55F0) says YOU HAVE SHOT SOME JEWELS. and loses them. Both seen in the game (work/t_chest.py). The chest of ammunition is a different thing, tile $12 in the grid, which $4F62 gives when the player walks onto it and $53BF empties when it is shot
Shooting a closed chest opens it on jewels about one time in seven, and on explosives about one time in tenconfirmed$5598 takes a random number and only one in four is $C0 or more; on that it takes the next and splits it at $80 between jewels, worth 4000 when walked into, and explosives. The two are neighbouring bytes, which the noise makes alike, so jewels win more often; counted on ten tables built with the sound chip running (work/dice_real.py). The other three times it says EMPTY!. Opening a chest never hurts the player
Some chests hold explosives, which are fatal when shotconfirmedOnly when shot once the chest is open on them: $55D5 says FOOL!....EXPLOSIVES. and sets $02D3 to 1, which is the explosion at $5BDD: the border and background run through seventeen colours five times over and the game then ends. Walking into them does nothing. Seen in the game (work/t_chest.py)
Art treasures (paintings, vases, pendants, gemstones) score pointsconfirmed2500 for a painting, 1500 for a vase, 4000 for a pendant and 4000 for a pile of jewels, each queued in $02C5 and paid out a hundred at a time by $5AA0
Ammunition boxes hold 7 rounds eachdiffersA box gives ten: $4F62 adds $10 in decimal mode, and sets 99 when that would pass it. The manual (page 6) says 7
A mission starts with 99 roundslive$02BD reads $99 and the panel's two cells both hold $F9 (work/t_ammo.py); $405E writes $99. The manual says 99 too. C64-Wiki's "maximum is 100 shots" is wrong: the ceiling is 99, and $4F6A says so when a box would carry past it
Captives are escorted back to the starting point, and move more slowly than the playerconfirmed$6C3B gives the prisoner a step every other frame, half the player's rate, and only when he is within ten blocks of the window
A dazed captive is moved on by firing a warning shot in his directionconfirmedA shot that reaches tiles $D4 to $E3 goes to $6E21, which turns the prisoner the way the bullet came
A high score table, "TODAYS REAL HEROES", ten entriesliveThe attract loop shows it, filled with ten PANDORA entries from 10000 down to 1000 (reference/attract-hiscores.png), kept at $0D51
The player types a name on a high scoreconfirmed$0BC1 builds the screen, $09AB scrolls a strip of 48 characters from $0B48, and $0CE7 reads the ten typed characters back off the screen into $081F
A hidden cheat: the name %MAGGOTS!&live$6F3B compares the typed name with $6F31 and sets $603F; with it a mission starts with no hits taken, a key in hand and the ammunition refilled on two frames in three (work/cheattest.py). cheats.md has it in full. No source mentions it
A message line at the bottom of the screenliveRows 23 and 24 of the screen, drawn in the second alphabet; the raster split at line 228 switches the character set for them (work/frame-play.json)
The two kinds of mission are RESCUE THE PRISONER and BLOW UP THE CASTLEliveStored at $1E18 and $1E2C; the briefing was read on screen (work/t_mission2.py)
The game nags a player who stands still, and one who wastes ammunitionconfirmed$5A33 counts the still frames and says "COME ON ! GET ON WITH IT....." at fourteen, and "LETS GET DOWN TO SOME SERIOUS DESTRUCTION !" after seven counts of fire held without moving
A hint when a prisoner is nearconfirmed$6CB4 says "THE PRISONER IS VERY CLOSE." once a floor, when the prisoner comes within ten blocks of the window
An empty chest says sotracedEMPTY! is message 26 at $5889
Music in the attract looplive173 writes to $D400-$D418 in three seconds of the attract loop, and none in three seconds of play with nothing pressed (work/sidwrites.py). The driver at $1947 plays three streams of note numbers and runs on every third frame
Nine sound effects in play, and footstepsconfirmed$6404 starts one of nine on voice 1, chosen by $02D5, and $6790 plays the footsteps on voice 2 at two alternating pitches

Beyond the documentation

Found in the code, not in the manual.

Open questions

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.