1984 · Progressive Peripherals & Software

About this page

This minisite was contributed by air, jankfoundry. It’s currently claimed by jankfoundry who is editing it to reach a Gold tier standard.

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
Program45,56069.5 %
Code28,07542.8 %
Graphics10,91916.7 %
Level data3,4245.2 %
Sound900.1 %
Text3530.5 %
Tables2,3933.7 %
Variables3060.5 %
Screen, bitmap, colour, stack, I/O11,64017.8 %
ROM the game runs under8,19212.5 %
Unused1440.2 %

Status

Tiersilver (claimed)
Coverage100 % of the bytes the game uses have a description
Build analysedPP&S disk edition; supplied G64, 49 directory entries; WIZ boot
Copyagent-draft
Toolsemulator: release v3.13.2, v3.13.2-linux-x86_64-gui.zip, disassembler: regenerator2000 0.9.20 (local copy of crates.io installation; stdio MCP), host: Linux x86_64, Ubuntu 24.04, no display
Modelgpt-6-astra
Kit version0.0.54

Contributors

Other places to love this game

What the game does, and where we found it

Sources read 2 October 2026:

Feature verification

IDFeature to checkStatusEvidence / question
F01Demonstration, play and construction choiceslivereference/program-menu.png; each choice appears in the supplied image
F02Four ten-level difficulty bandstracedGAME $36AE / $3D85: bases 0,10,20,30; ten-level progression advances bands.
F03Customized levels and randomized Mystery modetracedGAME $36AE/$3831: Customized base40, Mystery bit7; editor accepts files 0–99. Player routes through custom files remain open.
F04Six players taking turnsdiffers; liveFive joystick changes select six players; reference/six-players.png. GAME $34EC wraps seven to one. Manual agrees; wiki says four.
F05Speeds 1–9 chosen while a level drawsdiffers; tracedEngine $90ED accepts digits0–9, broader than the documented 1–9. Default 5 at $80DA; GAME $2B19 computes the delay.
F06Walking and duckinglive; tracedMatched 12-frame control holds position; right moves X172→182. Down selects the duck path at $73B7 when descent is blocked; pose behavior traced.
F07Fire plus direction jumpsliveFrom the same snapshot, up+fire changes Y165→155; right+fire changes X172→182 and Y165→155. Engine $75EE/$7616/$763E.
F08Ropes and ladders have different lateral movementtraced; live; testedNarrow rope glyphs $63/$64 differ from three-piece ladders $65/$66/$67. Original-code replays show catches, centering and one-pixel climbing; prepared emulator cases agree.
F09Falls can kill; jumps can catch ladderstraced; live; testedBounded falling at $7142–$7171; thirteen-pixel clear jump arc and rope/ladder interception at $770B. A prepared one-cell gap kills walking but permits a running jump.
F10Key opens exit and grants spellslive; tracedForced key tile changes $C030 from 0 to 1 and restores charge digit 3. Exit checks the key flag at $7AD2. A checkpointed Burning Bridges route takes the key, enters the exit and reaches the next file load.
F11Treasures award pointsliveForced first-class treasure produces 50 points; original-code comparison covers all 16 class/difficulty combinations. $8464/$84D8.
F12Completion converts remaining bonus to scoretraced; live; testedGAME $3D96 adds50 per remaining bonus unit; setup gives 24 units, timer period is level-specific. 150 prepared original-code payouts and four live cases pass. Resuming the Burning Bridges exit checkpoint settles 2550+17×50=3400 and loads L18T.
F13Extra lives from score and ten-level completionlive; tracedForced 9950+50 gives 10000 and lives6→7. GAME $3BA5 adds ten-level survival lives; $850A detects score-digit crossing. Prepared live milestones at bases0/30 confirm life additions, byte wrap and Expert→Mystery progression.
F14RUN/STOP pause; Q returns to menulive; tracedRUN/STOP pause and resume captured in reference/paused.png and resumed.png. Q matrix code branches to $6400 at $96E1.
F15SPACE or down+fire casts; facing selects directiontracedEngine $7185 accepts SPACE column pattern$EF and port 2 down+fire$0D; $765B debounces and spends a charge. Facing sets projectile direction.
F16Fireball, Magic Missile, Disintegrate and Enchantment kill on hittraced; live; testedAll four use the same removal branch at $8C0F–$8C19, consistent with the manual. Original collision/hit matrix covers every actor type and slot; each spell also removes a forced queued target live. Tests isolate hit processing, not projectile reachability.
F17Freeze immobilizes enemieslive; testedQueued spell 4 turns the target cyan. Original-code timelines verify 109/93/77/61 actor-update passes by difficulty and a shared countdown reset by later hits. $8C1C applies Freeze; $862E restores each original color.
F18Invisibility supplies protection against fatal eventstraced; live; testedGAME $2B6E/$3091/$30B3 gives 32 protected fatal reports, not 32 movement passes. Safe updates preserve it; red hazard death bypasses it. 84 interpreter cases plus live cast, safe controls, all 32 units and subsequent death.
F19Teleport, Feather Fall and Levitate change movementtraced; live; testedGAME $30EE–$3127 and engine $7956/$794E/$7952. Teleport exchanges coordinates and nudges X two pixels; down/up travel moves two Y pixels per update until terrain ends it. Prepared original-code and emulator traces agree.
F20Haste and slow alter movement ratestracedGAME $3128 halves delay plus1; $3132 slows actor horizontal velocity and lengthens delay below64.
F21Portals transport the playertracedEngine $795A dispatches portal/question-mark/directional glyph effects; $79B3 exchanges saved/start coordinates.
F22Moving lifts, gates, pits and trapdoorstracedTypes7–12 have separate motion/stationary handlers; signed elevator velocity and leg duration read at $892A.
F23Ground enemies, flying enemies and aimed hazardstraced; testedEditor DATA establishes type IDs; engine $860E dispatches ground, flying pursuit, random-axis, arrow and falling-rock controllers. Four movement replays compare 960 original-code states including terrain and sprite animation.
F24Thief collects treasure; cat eats rats on contacttraced; testedThief $7F7A invokes treasure callbacks. Cat follows the wizard via the shared ground controller $86BA; collision $7D45 removes a contacted rat. All thirty ordered slot pairs tested with five spell IDs, including Freeze. Cat is exempt from killing the wizard.
F25Cyan monsters are inactivetracedEngine $862E recognizes color 3 and shared freeze phase; collision compares per-level exempt color at $7CFA. All40 supplied headers default that color to 3.
F26Treasure-triggered changes and hidden exitstraced; live; tested$9477 applies 3×2 patches and then player/thief calls level code at $C376. Twenty levels have active callbacks. Simon Says rule checked in 4,096 original-code cases and four live callbacks; its automatic starting pearl and color patch replayed with neutral input. The atlas compares 700 pickup states; neutral-input traces establish hidden-thief operation in Friend or Foe? and Ladder Land. Burning Bridges has a completed checkpointed input route with Intermediate behavior and active hazards; other full room routes remain open.
F27Death animation, retries and player turnstraced; live; testedDeath motion $9526 plus GAME $2C7B/$388E; complete animation captured. Live $2DA3 cases confirm a surviving player retries; final-life loss advances to the next survivor. Completion also settles the account through $373D/$3831. Six accounts, dead-player skipping and wrap are tested.
F28Ten persistent scores, champion name and other initialstraced; live; testedSCOR128-byte layout, GAME $419A insertion and $4745 save; initials entry $8FA6 and champion-name entry $8FB5, both timeout-enabled; the separate $8FC4 entry edits construction titles. A prepared 1000-point account passes original ranking, typed name/initials and SAVE with status0 on a disposable D64; all128 reloaded bytes match, including a separate disk extraction. The supplied disk is unchanged. Additional live six-player and top/bottom-tie records confirm name attribution can reclaim an existing equal score; all three saved records match disk extraction. Status0 alone is insufficient: the empty-drive test also returns zero. Full and write-protected disposable disks have real failure controls; a full disk with existing SCOR succeeds after scratching that record. Held FIRE exhausts three failed SAVE calls; a missing level exhausts four LOAD calls.
F29Commodore key clears scores during startuplive; testedLODR $1117 compares port B with exactly $DF and clears $C100–$C14F. Naturally reached held/released keyboard cases verify eighty cleared bytes and preserved tail; all 256 port values tested.
F30Level drawing, movement and actions produce soundtraced; testedSID writes across title, construction and gameplay. Five effect ports match the original routines write-for-write across60 test cases.
F31Construction edits terrain, player start and colorslive; tracedConstruction loads level0 live. BLDR $35EC positions wizard, $43F6 edits colors, $49A6 edits terrain; separate reference/editor-source.txt. Seven prepared live portal placements verify that its upper-left and upper-middle cells can overwrite existing terrain; the other occupied footprint cells reject placement.
F32Construction chooses six monsters and separate appearancetracedBLDR $36B8 selects six slots; $3906 behavior 0–20, $3A66 shape0–127, $3AB0 animation0–4. Behavior and appearance are separate fields.
F33Construction configures spells and saves/loads level filestraced; liveBLDR $3BE0 spell/charges, $33CF load and $4135 save. Live CTRL-S save and reload of L99T on a private blank disk verifies the $45EF elevator reset. A private game-disk copy is rejected when PPSS loads successfully; the supplied original is unchanged.
F34Level capacity, treasure and fire limitstracedBLDR validates screen0–99 and maintains separate limits of16 treasures and 16 fires at $5088; map has 21 playable rows of40 cells with borders.

Picture references

Open questions

Open rows describe what was searched and what remains unverified. Traced facts have source evidence; live facts also have an emulator observation. Forced-state tests establish a code response, not a player route.

Verification scope

Madhouse rotates 839 cells and skips the arrow at $C700; For Your Ice Only erodes its glyph on early indices too. work/audit_room_rules.js checks all forty callback entries and both treasure callers. The checks listed in facts.md also cover pickup deltas, actor motion, prepared movement and native register/boundary details; isolated fixtures do not establish full room routes.

How the analysed state was reached

Image and tools

The contributor supplied a G64 with the eight-byte GCR-1541 header, version 0 and 84 half-track entries (42 tracks). It is a disk image, not a frozen running game. SHA-256: 040b0615ab6dc3d741ee7bb85b59352a7c4c1a6fca0276672b9ab71ffa398c81.

The directory has 49 entries: WIZ, SCOR, LODR, CHRW, SPRW, M.L., GAME, BLDR, L00T through L39T, and PPSS. The PP&S introduction and credits appear; no trainer menu was observed. Work used a copy in work/wizard.g64, leaving the supplied original alone. The companion NBZ was retained privately but was not used to boot.

Measured on 2 October 2026: vice-mcp release v3.13.2, v3.13.2-linux-x86_64-gui.zip; regenerator2000 0.9.20. Linux x86_64 with a virtual display. This clone uses MCP ports 6511 and 3001, set in the ignored tools/mcp-ports.json, because other sessions use the defaults. The disassembler is served through the kit's stdio bridge. A fixture verified binary inspection, tracing, labels, comments and clean shutdown.

verify-footprint passed. The emulator check passed 54 of 57 cases, including exact stopping and stepping, persistent input, snapshot equality and equality after restart. The failed checks were watch-store, watch-load and warp: their fixed host-speed thresholds failed (39 watchpoint hits; warp 71 passes/s, normal 46/s). Nonzero counters and the precise frame tests worked. Game timing must therefore be measured in emulated frames or cycles, not host seconds. The startup liveness check was corrected to accept positive progress on a busy host.

Power-on to the canonical snapshot

  1. Start the emulator through python3 kit/scripts/tools.py vice. Hard-reset, resume execution, and call vice_autostart on the local G64 with program: "WIZ" and run: true. Leave the drive's processor enabled. This run used the bundled 1541-II drive ROM and PAL video.
  2. The copyright screen is followed by two illustrated loading screens. Enable WarpMode while loading if desired. On this host they took several minutes; wait for the screen states rather than assuming a fixed host delay.
  3. This image's protection loop can stay on the second illustration. Its routine at $19A3 reads 128 bytes from track 3, sector 3, XORing them into $7000–$707F, and the loop at $195C waits for the first byte to become $4C. True-drive reads in this run supplied only one of the two protected sector patterns. The direct vice_disk_read_sector call supplied the other.
  4. If still in that loop, stop at an execution checkpoint at $195C. Check $FB before intervening: when it is 1, resume to the next hit without changing RAM. The loader rejects a first-attempt success at $1973–$1977; the fresh-boot check on 3 October 2026 succeeded on attempt 2. With $FB no longer 1, read $7000–$707F from RAM and the first 128 bytes returned by vice_disk_read_sector for unit 8, track 3, sector 3. XOR the two byte arrays. In this image their first bytes are $44 and $08; the result starts $4C,$9F,$8E and has $4C every third byte through offset 117, a valid jump table. Only when those checks pass, write the result to $7000. Remove the checkpoint and resume. Do not alter $FB, the program counter or the loader code. The loader then writes marker $FA to $99F0 at $1986 and to $58FF at $1989, observed with store watchpoints, and proceeds to the title. This applies the loader's own computation to bytes from the supplied disk; no engine instruction or disk file is patched.
  5. At the program menu, move port 2 down from Demonstration to Play the Game (three frames of down worked here), release, then press fire. For the later menus, hold fire for 90 frames and release for at least 30; brief presses can miss their slower polling loops.
  6. While GAME loads, set an execution checkpoint at $0819, its SYS entry. When it stops, before executing the jump to $2245, save without ROMs. work/entry.vsf is the canonical disassembly and listing snapshot. It is an actual stopped machine after the disk loader, including the protection table already produced in RAM.

From entry to play

Remove the entry checkpoint and resume. Choose Beginner, then one player, then press fire once more on the instruction to begin. Leave the number keys untouched for the default speed 5. The first level is Playground. Wait for the level to finish drawing and for the player to appear; turn WarpMode off. Stop between instructions with the kit's pause() and save work/play-round1.vsf. reference/playground.png shows that state. Port-2 right for 12 PAL frames moved sprite 7 from X=172 to X=182 while other objects advanced; reference/playground-moved.png records the response.

Snapshot choice and memory

At entry $00/$01 = $2F/$37; the RAM IRQ vector is $7D6A and NMI vector $7D6F. In play the same banking remains, IRQ is $7CBF, and NMI remains $7D6F. The live PC was $8E62, inside the disk's machine-code image. These are observations, not a claim about an interrupt's rate.

In play $DD00=$C4 selects VIC bank $C000; $D018=$13 selects screen $C400 and charset $C800. The font matches CHRW byte-for-byte. SPRW loads from disk at $4000 and is relocated to $E000–$FFFF; 8190 of its 8192 bytes match the snapshot, with the two bytes at $FFFA/$FFFB changed to $FE43. This sprite RAM lies beneath the KERNAL ROM and must be included in analysis.

GAME occupies $0801–$4A88. M.L. occupies $5800–$9F6F. Comparing the canonical entry with Playground finds 307 changed bytes in GAME and four at $8AB7–$8ABA in M.L.; font and sprite RAM are identical. The entry image preserves the initialization values. The meaning of the changed ranges is established in facts and symbols, rather than presumed from the comparison.

Levels are separate L00T–L39T files. A gameplay snapshot contains one loaded level; the level format and the complete disk set must be checked separately. BLDR is a separate construction program, not simultaneously resident with GAME.

Loader summary

WIZ loads LODR, whose illustrated sequence loads the shared machine routines and graphics, relocates sprites under ROM, and combines the two protected sector patterns into the engine's jump table. Its title menu then loads GAME or BLDR into the low program area. The program begins through SYS 2073 and a jump at $0819. The protection assist above is the only intervention before that hand-over; the loader is not the subject of the annotation pass.

Fresh-boot check, 3 October 2026

A hard reset and WIZ autostart from a disposable copy of the supplied G64, using the guarded assist above, reached GAME through the program menu. All 45,560 listed resident bytes at the fresh $0819 stop matched the canonical listing. Joystick selection of Beginner and one player reached Playground through its normal load/setup, with wizard (172,165), six lives in all six account slots, and the documented banking and interrupt vectors. This establishes the assisted boot recipe; it is not a claim that the protected image booted without assistance.

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.