# 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 ```