fs2port/SESSION_RECOVERY.md

4.6 KiB

FS2 Port Session Recovery

This file is the entry point for resuming work after a session break. Updated 2026-09-06.

How to recover

  1. Read this file (current state + ground rules).
  2. Read ~/.claude/projects/-home-scott-claude-flight/memory/MEMORY.md and follow the indexed entries that are relevant to the current task.
  3. Read port/PORT_STATUS.md for what the port is and how it is verified.
  4. Read port/PORT_64K_AUDIT.md if working on 64K-mode patch hooks.

Build

Disassembly (needs a git build of cc65; the Ubuntu package is too old for .refto and --warnings-as-errors):

export PATH=$PWD/tmp/cc65/bin:$PATH
export CC65_HOME=$PWD/tmp/cc65
make clean && make && make validate

If tmp/cc65 is missing: cd tmp && git clone --depth 1 https://github.com/cc65/cc65.git && cd cc65 && make -j8 bin.

make validate checks the four chunks AND the four overlay sources (src/ovl25.s, ovl2d.s, ovl42.s, ovl2b.s) against the sections extracted from the FS2.1 file (orig/ovl_*.bin).

Port: make -C port (gcc, SDL2). Headless render: port/bin/fs2port --screenshot tmp/x.ppm. Regenerate the symbol header after renaming labels in src/:

ca65 --target apple2 -g -o tmp/complete_g.o src/complete.s
ld65 --config src/asm.cfg --dbgfile tmp/complete.dbg -o /dev/null tmp/complete_g.o
python3 port/tools/genSymbols.py tmp/complete.dbg port/include/fs2Symbols.h

Current state (2026-09-06)

The port is a byte-faithful C translation of the whole program running over a 64K RAM image (see port/PORT_STATUS.md). It matches the 6502 oracle (port/tools/fs2trace.c) tick for tick, byte for byte, on the twelve key scripts of port/tools/verify/regress.sh (boot, flight, modes, edit, ww1, radios, slew, reality, night, course, logdisk, demo).

Key findings this session, in case they need revisiting:

  • The PatchSlot_* slots at $A7E8..$A7FF are rewritten by the scenery file, not by the 64K patch table: LoadSceneryFileCommon reads sector $2B's page over $A7E0. The editor, the WW1 mode and the Ctrl+E page are 6502 overlays inside the FS2.1 file. They are disassembled with semantic labels and per-routine comments (src/ovl*.s) and translated (port/src/ovl*.c).
  • PerspectiveDivide is a non-restoring divide whose quotient for a negative numerator is not the magnitude quotient; chunk5Vertex.c transliterates it register by register (PerspXTable/PerspYTable at $7D80/$7E00 are now labelled in src/chunk5.s).
  • Sector s of the scenery file is file offset (s + 4) * 1024; a loader "page" call moves 1K (four 256-byte pages), clipped at $C000.

Verifying a change

port/tools/verify/regress.sh            # everything (a few minutes)
port/tools/verify/regress.sh flight     # one script
port/tools/verify/compareRun.sh NAME TICKS "KEYS"
python3 port/tools/verify/snapDiff.py tmp/NAME.oracle.snaps tmp/NAME.port.snaps 1 25 all

compareRun.sh leaves per-tick RAM snapshots in tmp/NAME.*.snaps; snapDiff.py names the first differing bytes with their symbols. For draw-level diffs run the oracle with FS2TRACE_DRAWLOG=1 and the port with PORT_DRAW_DUMP=1 and diff the line/span/plot/project lines; for the work counter use FS2TRACE_WATCH=0x32-0x33 and PORT_WORK_TRACE=1. port/tools/codeMap.py maps code and data in an overlay image from its entry points.

Files NOT to delete

  • tmp/cc65/ - the assembler build
  • downloads/scenery/extracted/*.blocks - block lists fs2trace reads
  • orig/ - the original chunks, the disk image and the overlay sections

Ground rules

  • Do not run git for port work. port/ is committed alongside the disassembly, but the user manages it; do not stage or commit port files.
  • Scratch files go in ./tmp/ inside the project, NOT /tmp/.
  • Screenshots go in port/screenshots/, never port/ or /tmp/.
  • Port uses fixed-point math - translate the byte arithmetic; no float reinterpretations.
  • No 6502 emulation in the port. fs2trace keeps its own emulator for offline oracle runs of the real binary; the game never uses it.
  • Byte-identical validation discipline applies to src/*.s: every change must keep make validate green.
  • Style: see the user's global CLAUDE.md. port/tools/style.py is the normaliser (braces, one statement per line, camelCase, alphabetical functions with a prototype block, aligned declaration runs); it is idempotent and safe to re-run after edits.

NEVER Read PNGs

The user views PNGs directly. Compare images with text tools:

port/tools/imgDiagnose.sh diff tmp/mame_boot.png port/screenshots/x.ppm --ascii
port/tools/imgDiagnose.sh stats port/screenshots/x.ppm