Route checks with ports on: timing-invariant checkpoints, SRAM start points only (fixes #34) #44

Merged
Gatchan merged 4 commits from ports-on-checks into main 2026-11-02 23:52:18 +00:00
Owner

Fixes #34 (decision of 2026-11-02, workdocs/decisions.md).

Check definitions: before / after

Before After
Semantic checkpoint (--semantic, route_ports_on.*) every checkpoint key, including party HP after a battle timing-invariant facts only: mode, map/position at the goal, party, event bits, scripted-battle outcome (battles: {...: "won"}), save slot. Keys in a route's EXACT_ONLY (party HP) are compared by exact checks only
Chained routes START = "after:<route>": frame-exact replay of the previous movie, even with ports on after: removed (run_route refuses anything but power_on / sram:<route>); chained routes start from SRAM start points made by the interpreter
Mandatory battles 3 attempts (title, Whelk, Marshal, Figaro escape), each route its own loop behaviours.win_battle, 8 attempts (BATTLE_ATTEMPTS), retries jittered; attempt 1 unchanged, so interpreter movies keep their inputs
rom.ports divergence reported (frame + first differing byte) reported and classified against the timing census (E4, E5, E8 sites, US/JP addresses); an unlisted site prints FINDING. Still not a failure
docs/validation.md — validation doctrine: per-call shadow = exact proof; interpreter movies = frame-exact; ports-on (later native) = goal + timing-invariant checkpoints; rom.ports divergences classified. No cycle charging in bridges

No new gate: route_ports_on.* keeps its place; only its definition changed.

New SRAM start point

title_to_mines_save (power-on, the title route, cliffs, mines save point (33, 22) of map $29, save in slot 1; US 23 834 frames, JP 23 368) is the start point of field_menu_tour (now steps off the save point first; 1 602 / 1 304 frames instead of 10 897 / 10 202) and narshe_to_world_map (62 504 / 56 648 frames instead of 80 001 / 80 910). narshe_to_world_map now saves on a fixed world tile (84, 36): the position after "prove control" depended on input timing (JP ports-on ended on (84, 36) vs (84, 35)). Movies re-recorded; title_to_first_battle_win pads and end hashes unchanged (only the checkpoint comment lines changed).

Evidence

  • Release ctest (all labels, -j2): 61/61 passed, 6 582 s wall (includes regenerating the 4 SRAM start points, 1 988 s of fixtures; cached afterwards).
  • route_ports_on.* (all ports on = battle/Rand on main), US / JP: title_to_first_battle_win ok/ok, title_to_mines_save ok/ok, field_menu_tour ok/ok, narshe_to_world_map ok/ok, narshe_to_figaro ok/ok.
  • rom.ports: US first divergence frame 8792, WRAM $131E, PC $C5:06AF -> E8 (sound driver state/code); JP frame 8678, $131E, PC $C5:06B2 -> E8. No finding.
  • Debug (gcc ASan/UBSan) ctest -LE slow: 24/24; debug rom.ports.*: see comment below. Clang ctest -LE slow: 24/24, no warnings.
  • The whole debug slow suite is not run: under ASan the emulator is ~12x slower (field_menu_tour movie 187 s vs 15 s), i.e. about 20 h on this machine.

🤖 Generated with Claude Code

Fixes #34 (decision of 2026-11-02, `workdocs/decisions.md`). ## Check definitions: before / after | | Before | After | |---|---|---| | Semantic checkpoint (`--semantic`, `route_ports_on.*`) | every checkpoint key, including party HP after a battle | timing-invariant facts only: mode, map/position at the goal, party, event bits, scripted-battle outcome (`battles: {...: "won"}`), save slot. Keys in a route's `EXACT_ONLY` (party HP) are compared by exact checks only | | Chained routes | `START = "after:<route>"`: frame-exact replay of the previous movie, even with ports on | `after:` removed (run_route refuses anything but `power_on` / `sram:<route>`); chained routes start from SRAM start points made by the interpreter | | Mandatory battles | 3 attempts (title, Whelk, Marshal, Figaro escape), each route its own loop | `behaviours.win_battle`, 8 attempts (`BATTLE_ATTEMPTS`), retries jittered; attempt 1 unchanged, so interpreter movies keep their inputs | | `rom.ports` divergence | reported (frame + first differing byte) | reported and classified against the timing census (E4, E5, E8 sites, US/JP addresses); an unlisted site prints `FINDING`. Still not a failure | | `docs/validation.md` | — | validation doctrine: per-call shadow = exact proof; interpreter movies = frame-exact; ports-on (later native) = goal + timing-invariant checkpoints; rom.ports divergences classified. No cycle charging in bridges | No new gate: `route_ports_on.*` keeps its place; only its definition changed. ## New SRAM start point `title_to_mines_save` (power-on, the title route, cliffs, mines save point `(33, 22)` of map $29, save in slot 1; US 23 834 frames, JP 23 368) is the start point of `field_menu_tour` (now steps off the save point first; 1 602 / 1 304 frames instead of 10 897 / 10 202) and `narshe_to_world_map` (62 504 / 56 648 frames instead of 80 001 / 80 910). `narshe_to_world_map` now saves on a fixed world tile (84, 36): the position after "prove control" depended on input timing (JP ports-on ended on (84, 36) vs (84, 35)). Movies re-recorded; `title_to_first_battle_win` pads and end hashes unchanged (only the checkpoint comment lines changed). ## Evidence - Release `ctest` (all labels, -j2): **61/61 passed**, 6 582 s wall (includes regenerating the 4 SRAM start points, 1 988 s of fixtures; cached afterwards). - `route_ports_on.*` (all ports on = `battle/Rand` on main), US / JP: title_to_first_battle_win ok/ok, title_to_mines_save ok/ok, field_menu_tour ok/ok, narshe_to_world_map ok/ok, narshe_to_figaro ok/ok. - `rom.ports`: US first divergence frame 8792, WRAM `$131E`, PC `$C5:06AF` -> E8 (sound driver state/code); JP frame 8678, `$131E`, PC `$C5:06B2` -> E8. No finding. - Debug (gcc ASan/UBSan) `ctest -LE slow`: 24/24; debug `rom.ports.*`: see comment below. Clang `ctest -LE slow`: 24/24, no warnings. - The whole debug slow suite is not run: under ASan the emulator is ~12x slower (field_menu_tour movie 187 s vs 15 s), i.e. about 20 h on this machine. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Timing-invariant checkpoints (battle outcomes; party HP exact only via EXACT_ONLY),
mandatory battles retried up to 8 times with jitter (behaviours.win_battle).
Movies re-recorded: title_to_first_battle_win pads and hashes unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Gatchan/FF6Portage!44
No description provided.