Commodore 64 · 1982 · Commodore

About this page

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
Program7,24111.0 %
Code2,9754.5 %
Graphics2,3993.7 %
Level data9281.4 %
Sound1900.3 %
Text1100.2 %
Tables5850.9 %
Variables540.1 %
Screen, bitmap, colour, stack, I/O5,3768.2 %
Unused52,91980.7 %

Status

Tiergold
Coverage100 % of the bytes the game uses have a description
Build analysedCOPYRIGHT 1982 BY COMMODORE AND HAL LABORATORY
Copyagent
Toolsemulator: VICE x64sc 3.10 with vice-mcp, disassembler: regenerator2000 0.9.20
Modelclaude-opus-5 (Claude Code)
Kit version0.0.1

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), confirmed (traced in the code), live (also observed in the emulator), differs (the code does something else). "Absent" is not a status.

Sources:

Features

FeatureStatusWhere
Land the ship on one of three siteslivecheck_on_pad $E3B5, pad tables $E3E7$E3F8
Three sites carry different score multipliers, 2x, 5x and 10xlivetouchdown $E55C; measured 1600, 4000 and 8000 for a perfect landing
Vertical velocity must be low enough to landlivetouchdown $E56E; the limit is $0048
Score depends on the landing velocitylivetouchdown $E581, base is 80 minus the velocity
Score is multiplied by the number painted beside the padlivetouchdown $E586$E59F
A successful landing refuels the shiplivetouchdown $E5E0, 70 units per point scored
Fuel depletes while thrustinglivemove_ship; 111 per pass for the main engine, 30 for a side jet
Main thruster lifts the ship (F1 or fire)liveread_controls $EB9C, move_ship $E328
Left manoeuvring thruster on A, moves the ship rightliveread_controls $EBC9; world X rose with A held
Right manoeuvring thruster on D, moves the ship leftliveread_controls $EBC9; world X fell with D held
Joystick in port 1: left, right and firetracedread_controls $EB7A$EB99. Could not be exercised: see "Open questions"
The ship is destroyed by touching the rocklivemain_loop $E144 reads $D01F, sprite-to-background collision
The ship is destroyed by landing too fastlivelanding_too_fast $E624, prints SORRY NO BONUS
A velocity gauge in m/s on the right of the screenlivedraw_velocity_gauge $EC01, draw_hud $ED7C
A yellow band on the gauge marks a safe landing speeddiffersOne yellow cell at screen row 12 covers velocities 0 to 63; the code accepts up to 71 and accepts every upward velocity. See below
Score and high score on screenlivedraw_scores $EE5A; both are 4-digit BCD shown with a trailing zero
Fuel bar on screenlivedraw_fuel_bar $EBD6
The game ends when the tank is emptydiffersRunning dry cuts the engines and prints OUT OF FUEL, but the game continues until the next impact (explode $E4C7)
The view zooms in near a landing sitelivezone_for_position $E1C4, close_view_sprites $E3A1
Difficulty increases as the game goes onlivegravity_table $E0DE, indexed by the landing number, capped at 16
"For a perfect landing on the 10x platform you can grab 7.000 points" (C64-Wiki)differsA perfect landing on the x10 pad scores 800, shown as 8000. Measured live
Attract sequence with a demonstration flightliveattract_demo $E9F2
Title screen with the Commodore wordmarklivedraw_title_logo $F266, reference/boot-title-logo.png

Beyond the documentation

Found in the code, not in the manual, each verified live.

FindingEvidence
A ship that arrives climbing scores more than a perfect stop. The bonus is an 8-bit 80 − velocity, so a velocity of −16 gives a base of 96. Landing at −16 on the x10 pad shows 960 X 10= 9600, above the 8000 of a perfect stop.touchdown $E581; measured by entering touchdown with the velocity poked
The safe speed is 8 units wider than the yellow cell, and the boundary is one pixel wide. The yellow cell covers velocities 0 to 63; the landing test accepts up to 71. The needle moves in steps of 8, so 71 (lands, 900 points) and 72 (SORRY NO BONUS) are one eighth of a character apart, and both are below the yellow.draw_velocity_gauge $EC01 and touchdown $E56E; markers read out of screen column 39 for 13 velocities
The last 255 units of fuel can never be spent. move_ship clears both thrust flags when the fuel high byte is zero, so the low byte is frozen.With fuel $01FF and F1 held, the ship lifted and the tank fell to $00B2. With $00FF it did neither
Every score on screen is ten times the number the game counts. The status line prints four BCD digits and then a fixed 0 that is part of the static template.hud_text_template $ED2C, draw_scores $EE5A, draw_bonus_line $E738
There is no frame sync and no interrupt during play. The only cli is in the attract entry; play runs with interrupts masked and times itself with a counting loop.attract_entry $E7A9, start_game $E093; a checkpoint on the interrupt handler took 0 hits over 5 seconds of play
The flashing PUSH F1 TO START prompt is the only thing the interrupt does, apart from watching for F1.irq_tick $EB46 writes 18 colour cells at $DBCA, exactly the 18 characters at screen $07CA
A pad is a single line in the world, matched exactly. A ship descending faster than one world unit per pass can step over it, and then dies on the rock instead of being told it landed too fast.check_on_pad $E3B9 compares both bytes of Y for equality
The zoom is four hand-drawn pictures, not a scaled one. Each view has its own run-length stream; the only thing actually scaled is the sprite, doubled through $D017 and $D01D.view_stream_lo/_hi $ECD4, close_view_sprites $E3A1
The explosion is the lander. explode increments the sprite pointer seven times from the lander shape, so frame 0 of the fireball is the ship itself.explode_frame_loop $E473
The character set and the sprites share one 2 KB block. Glyphs $80$FF are the sprite bitmaps seen as 8×8 cells, and nothing ever selects them.$D018=$1E, sprite pointers $F0$FF resolve into $3C00$3FFF
A Commodore badge is carved into the rock in all four views, as terrain data rather than as an overlay.glyphs $0C$0F appear in all four decoded streams
The crash fuel penalty is clamped. Impact speed shifted right by four comes off the fuel high byte, but any speed above $01FF costs the same 31 high bytes.explode $E498; $0200 and $0300 both cost $1F00

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

work/jupiter-lander.d64, a 174,848-byte disk image. The directory shows a disk named c64.com with one program between two del separators:

NameTypeBlocks
jup.lander+2/remprg28

This is not the original release. It is a crack of the cartridge by the group Remember, release #213, dated 24-03-00, credited on its own screen to Fungus: "supplied, cracked from cartridge, +2 trained, and docs typed by". The +2 is two trainer options. Findings should be qualified as being about this release; the engine itself identifies only as COPYRIGHT 1982 BY COMMODORE AND HAL LABORATORY on its instruction screen.

From power-on to play

  1. Attach the image to drive 8 and autostart it. On a PAL C64 with a 1541, the load takes about 45 seconds.
  2. A "REMEMBER" logo with a scrolling message appears. Press space.
  3. Four pages of documentation typed in by the cracker follow. Space turns the page, run/stop exits. The documentation is the cracker's transcript of the manual, not the game's own text, and it disagrees with the game on one point: it dates the game 1981, the game's own screen says 1982.
  4. The trainer menu appears as two questions:

`` INFINATE FUEL ? (Y/N) NO BACKGROUND COLLISION ? (Y/N) ``

Answer N to both. Everything recorded in facts.md is the untrained game. Answering Y patches the engine and would make the fuel and collision findings meaningless.

The second N has to go through the KERNAL keyboard buffer rather than the key matrix. With the vice-mcp server, vice_keyboard_matrix works for the first answer and vice_keyboard_type for the second.

  1. The Commodore title logo flashes up, then the game's own instruction screen, which alternates with a demonstration flight. Hold F1 for about three seconds on the instruction screen to start a game. A short press is not enough: the game only looks at F1 inside its interrupt handler, which runs about 59 times a second, and the emulator's short taps can fall between two looks.
  2. F1 is also the up thruster, so the same press that starts the game fires the engine.

Snapshots

FileState
work/play-inflight.vsfpaused in flight, lander descending towards the x5 pad, fuel partly used. This is the snapshot everything downstream is read from.
work/play-descent.vsfa second play snapshot, caught during the explosion after a crash

Save them without ROMs. The 64 KB RAM image then starts at file offset 209 and is byte-for-byte what the CPU sees, except at $0000 and $0001: the processor port is stored separately in the C64MEM module header and the two RAM bytes underneath it hold unrelated values. Colour RAM is not at $D800 in the image; it lives in the VIC-II module. Reading it back through the emulator after loading the snapshot is easier than finding it in the file, and the emulator must be paused immediately after the load or the game runs on and the screen no longer matches.

Steady state

| Range | What | |---|---| | $0000-$0032 | all of the game's variables | | $0400-$07E7 | screen, with sprite pointers at $07F8 | | $3800-$3BFF | 128 character glyphs | | $3C00-$3FFF | 16 sprite shapes, sharing the same 2 KB block | | $E000-$F450 | the entire engine: code, tables, text, terrain | | $F451-$FFF9 | zero | | $FFFA-$FFFF | the three hardware vectors |

Everything between $0800 and $1DFF is the cracker's loader, trainer and documentation text. The game never touches it.

The loader, in a paragraph

The crack is a single 28-block program that loads at $0801, shows the group's logo and scroller, pages through the typed-in documentation, asks the two trainer questions, then installs the cartridge image into RAM at $E000-$F450 together with the character set and sprites at $3800-$3FFF, switches the ROMs out through $01 and jumps to the cartridge's own entry point at $E037. The original was an 8 KB cartridge mapped where the KERNAL normally sits, which is why the engine's addresses run from $E000 and why all three hardware vectors point into it. The loader is 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.