1984 · Software Projects

Jet Set Willy: the source

This minisite awaits a maintainer’s check. Models this site has not proven yet worked on it (gpt-6 and one whose name was not recorded), so its claims have not been tested against the game (how the check works).

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

Verification work

Collection logic, collisions, guardians, arrows, ropes and winning route remain verification leads. The source export’s own tests do not verify these claims here. The interactive draft stays private until normal coverage/verification confirms it.

Annotation checks

The 60 room records carry individual descriptions naming their captured room title and four exit ids. The sprite bank has 172 individual 64-byte records, each described as 21 three-byte rows plus alignment; sprite pointer arithmetic follows the C64 platform reference. Ghidra operand labels retain their actual offcut addresses. Post-row data descriptions were moved back to the row they describe; duplicate comments on the following row were removed. Runtime guardian work arrays, copied room glyphs and the indirect vector page are excluded from the authored-data ledger.

Checked room and rope transfers

Retained copyright and restart behavior

The retained loading-complete/copyright code spans $3A02-$3CD2. Its four-color checker at $3C23 first treats any entered byte with bit 7 set as incomplete, then compares all four bytes with $3A81-$3A84. A controlled correct code reached $3C3A; changing each individual digit reached $3C4E; one $FF slot reached $3C00. The success routine copied all nine bytes of its cartridge header from $3C62 to $8000. The captured expected-color base word is $2C57; its origin is open and no unpatched protection-sheet layout is inferred.

RESTORE versus reset (live): both reach the success header's entry stub $0FA0. RESTORE preserves DDR $2F and port $36, and the jump to $A000 fetches the RAM title's JMP $A744. A CPU reset, checked with a positive checkpoint at KERNAL reset entry $FCE2, reaches the stub with DDR $00 and port readback $17. Clearing bit 0 in the port latch cannot drive the banking pins while the direction register is zero. At the subsequent $A000 jump, CPU-visible bytes are BASIC ROM 94 E3 7B, while physical RAM contains 4C 44 A7. The stub never initializes the direction register. This finding applies to the captured CMM disk image.

The third trainer answer led through the retained decompressor: a store checkpoint stopped with PC $011E after writing $22 to the gap byte $3CDE, matching the later title/play capture. This identifies its producer, not the purpose of the surrounding gap. A packed-data relocation also wrote $AEBD; that byte changed again to its final captured value during unpacking. These observations do not establish an active gameplay consumer.

Retained-copy phase (live): the observed CMM boot hit the copyright entry $3C23 without hitting execution checkpoints at $D002 or $0334. Its RLE decompressor's final jump is $0140: JMP $3C23, after writing port $37. The controlled retained-bootstrap result remains valid, but it does not describe this disk's executed hand-over. The word $1002 preceding that retained bootstrap is recorded as a prefix of unknown original file role.

The copyright input display uses pointer $28 for an unset slot and pointers $29-$2C for color indexes 0-3. With the observed prior-phase VIC bank $0000, these select five addressed 64-byte slots at $0A00-$0B3F, whose contents overlap predecessor editor code.

RLE image (independent decode and live writes): at the third trainer answer, a 79-byte decoder is installed in $0100-$014E. It reads the relocated stream from $521B-$FFFF and emits 63,511 bytes at $07E8-$FFFE. A byte-for-byte independent decode matched that entire interval in the real cold hand-over snapshot. Ordinary bytes are literals; $BA introduces a repeat count and repeated value, with a zero count byte introducing the extended count. Watchpoints caught the final decoder writing the low retained tail, the gap after copyright code and the title-side tail at PC $011E. Their remaining semantic consumers are open; producing bytes does not establish that the gameplay uses them. The decoder lives in the stack area and is not a code block in the later play listing.

Retained text-buffer editor (traced and controlled calls): $0B41-$0F00 contains a predecessor command loop, character/repeat parsing, a 27-entry @-through-Z dispatch table and buffer-editing helpers. Some of its entry/UI callbacks have been replaced by gameplay code, and the routine at $0EF2 is truncated after $0F00. Its identity as a particular editor product is unknown. Direct calls to $0D34 inserted HELLO into a scratch buffer and advanced the pointer by five; $0D46 converted 00, 12, 4A and FF into the matching one-byte outputs. These calls do not demonstrate a working editor UI or player-accessible command interface. The preserved fragment stays Byte in the play listing so that predecessor callback addresses do not become false gameplay control-flow links.

The retained copyright display's pointer calculations address $0A00-$0B3F in its observed bank, but those low-memory bytes overlap predecessor editor contents. The CMM boot bypasses the entry/display path and reaches its accepted comparison state directly. They are described as addressed slots, not asserted to be intact original copyright artwork.

Item, jump and death checks

Review verification, 3 October 2026

node games/c64/jet-set-willy/reference/review-checks.js runs 44 controlled checks against bytes in the committed listing. Four editor inputs distinguish rejected byte-1 spaces, accepted decimal digits and a non-digit. Four title-loop inputs distinguish fire alone, Return, another key with fire and another key without fire. All 34 rope-directory pointers and trajectory-pointer calls match their address formulas; both eight-byte bit-mask tables match entry by entry. These simulator calls confirm routine contracts, not legal routes from ordinary play.

The rope storage ends at $1ABC: the pointer directory is $1856-$1899; the active attachment windows start at $189C and cover seventeen 32-byte windows through $1ABB. The preceding pair at $189A/$189B is $80,$04; no independent header role is claimed. $2233-$2239 crosses from the final six ascending masks into the first inverted mask.

A fresh CMM boot on 3 October 2026 with VICE MCP v3.13.2, console mode and dummy sound reached the title with all trainers disabled. Holding port-2 fire for 120 frames with $50/$51 both zero produced no execution hits at $A7EE; Return then reached THE BATHROOM. The private play snapshot matches all 7,415 code bytes and 560 word bytes of the preceding listing. Twenty-four byte-data bytes differ at the title glyph area $79E0 onward; these differing bytes are not treated as immutable. Source was rebuilt from the fresh play snapshot. Coverage measures 59,668 of 59,668 tracked bytes; this does not close the loaded-image audit or the open mechanics in the scope notes.

Cheats

No newly tested pokes are published. The Source tab exposes the named state fields and their consumers; modifying them is not evidence of a reachable gameplay state.

routines tables variables strings branch labels

Loading listing…