Routes leave game-made SRAM saves; route narshe_to_figaro starts from them (fixes #26) #36

Merged
Gatchan merged 5 commits from save-points into main 2026-10-30 01:37:33 +00:00
Owner

Routes now leave real SRAM saves made by the game, and the next route starts from them (decision on #22, option 1).

What changed

  • Behaviours (tests/routes/behaviours.py): save_game(slot) (main menu on the world map or at a save point, menu_flags bit 7 checked, Save, slot, Yes on overwrite; read back from SRAM: slot checksum as CalcSaveSlotChecksum computes it, SRAM validity marks, sram_last_slot), continue_game(slot) (title, load menu, Yes), world_dismount (chocobo, B), WorldWalker (world map paths over world_map_tiles, tile-index passability learned from refused steps, random battle starts not mistaken for walls), FieldGrid/field_go with opt-in NPC avoidance (field_obj_map) and avoid tiles, use_entrance, talk_to_object (NPCs found on the object map), ListBattlePolicy (Tools, vertical command cursor).
  • run_route.py: START = "sram:<route>" powers on with that SRAM (seeded WRAM, D2), presses Continue and loads the producer's SAVE_SLOT. A route with SAVE_SLOT writes its 8 KiB SRAM with --record to <startpoints>/<version>/<route>.srm (outside the repository: --startpoints, else $FF6_STARTPOINTS, else others/startpoints next to the repository) and records # startpoint_sram <crc32> slot <n> in the movie; --check compares it. A missing or stale start point is regenerated by replaying the producer's committed movie (must end with the recorded CRC); --make-startpoint does only that; --replay passes --save.
  • ctest: fixture startpoint.narshe_to_world_map.<version> required by the route/movie/route_ports_on tests of narshe_to_figaro.
  • RAM map: menu_flags ($0201), world_vehicle ($20), world_tile_props ($C2), world_tile ($C4), world_map_tiles ($7F0000, 256 rows); ram_map_check 0 errors, 166 JP checks.
  • docs/movies.md: SRAM start points, new behaviours, route table.

Routes

Route Start Frames US / JP Start point SRAM CRC32 US / JP
narshe_to_world_map (re-recorded: ends with a save in slot 1) after title_to_first_battle_win 80001 / 80910 1F8AAA17 / 535A9F1E
narshe_to_figaro (new) sram:narshe_to_world_map 40576 / 34690 8B7180F5 / D8F86E61

narshe_to_figaro: Continue (958 / 658 frames), walk to Figaro Castle, Edgar (intro and name), the Matron (twins' flashback), Edgar again (Kefka at the gate: two soldiers, Kefka), Locke in the courtyard and in Terra's room (night, fire), the guard by the keep (chocobo escape; battle against two M-TekArmors won at the first attempt with Tools/Magic/Fight), world map at (65, 77), chocobo dismounted, saved in slot 1 (party Terra, Locke, Edgar). Checked with screenshots at each stage and RAM-map checkpoints (mode, world position, party, event bits, save slot).

Validation

  • Builds clean: debug, clang, mingw; --fast passes on the three (13/13).
  • Slow suite, release, -j2, run once (machine shared with another agent, so times are inflated): 29/29 passed, with an empty start point directory so the fixtures regenerated the start points (CRC checked).
Test US s JP s
startpoint.narshe_to_world_map (regeneration, file missing) 1531 1552
startpoint.narshe_to_world_map (file present) 0 0
route / movie / route_ports_on narshe_to_world_map 1245 / 1188 / 987 1008 / 946 / 916
route / movie / route_ports_on narshe_to_figaro 454 / 444 / 453 385 / 377 / 367

Time gain (#24)

narshe_to_figaro starts after ~1000 frames of Continue instead of replaying the 80 000-frame narshe_to_world_map movie first: as an after: chain each of its 6 tests would add about one movie.narshe_to_world_map replay (1188 s US, 946 s JP here), i.e. about 6400 s of test time saved per suite run; the start point is regenerated once (about 1550 s here) only when it is missing. The narshe tests themselves still replay from power-on (no save point before the first world map), so the 20-minute target of #24 needs more (e.g. the nightly label for narshe_to_world_map).

Start point files are ROM-derived game data and are never committed.

Fixes #26
Refs #22 #24

🤖 Generated with Claude Code

Routes now leave real SRAM saves made by the game, and the next route starts from them (decision on #22, option 1). ## What changed - **Behaviours** (`tests/routes/behaviours.py`): `save_game(slot)` (main menu on the world map or at a save point, `menu_flags` bit 7 checked, Save, slot, Yes on overwrite; read back from SRAM: slot checksum as `CalcSaveSlotChecksum` computes it, SRAM validity marks, `sram_last_slot`), `continue_game(slot)` (title, load menu, Yes), `world_dismount` (chocobo, B), `WorldWalker` (world map paths over `world_map_tiles`, tile-index passability learned from refused steps, random battle starts not mistaken for walls), `FieldGrid`/`field_go` with opt-in NPC avoidance (`field_obj_map`) and avoid tiles, `use_entrance`, `talk_to_object` (NPCs found on the object map), `ListBattlePolicy` (Tools, vertical command cursor). - **run_route.py**: `START = "sram:<route>"` powers on with that SRAM (seeded WRAM, D2), presses Continue and loads the producer's `SAVE_SLOT`. A route with `SAVE_SLOT` writes its 8 KiB SRAM with `--record` to `<startpoints>/<version>/<route>.srm` (outside the repository: `--startpoints`, else `$FF6_STARTPOINTS`, else `others/startpoints` next to the repository) and records `# startpoint_sram <crc32> slot <n>` in the movie; `--check` compares it. A missing or stale start point is regenerated by replaying the producer's committed movie (must end with the recorded CRC); `--make-startpoint` does only that; `--replay` passes `--save`. - **ctest**: fixture `startpoint.narshe_to_world_map.<version>` required by the route/movie/route_ports_on tests of `narshe_to_figaro`. - **RAM map**: `menu_flags` ($0201), `world_vehicle` ($20), `world_tile_props` ($C2), `world_tile` ($C4), `world_map_tiles` ($7F0000, 256 rows); ram_map_check 0 errors, 166 JP checks. - **docs/movies.md**: SRAM start points, new behaviours, route table. ## Routes | Route | Start | Frames US / JP | Start point SRAM CRC32 US / JP | |---|---|---|---| | `narshe_to_world_map` (re-recorded: ends with a save in slot 1) | after `title_to_first_battle_win` | 80001 / 80910 | 1F8AAA17 / 535A9F1E | | `narshe_to_figaro` (new) | `sram:narshe_to_world_map` | 40576 / 34690 | 8B7180F5 / D8F86E61 | `narshe_to_figaro`: Continue (958 / 658 frames), walk to Figaro Castle, Edgar (intro and name), the Matron (twins' flashback), Edgar again (Kefka at the gate: two soldiers, Kefka), Locke in the courtyard and in Terra's room (night, fire), the guard by the keep (chocobo escape; battle against two M-TekArmors won at the first attempt with Tools/Magic/Fight), world map at (65, 77), chocobo dismounted, saved in slot 1 (party Terra, Locke, Edgar). Checked with screenshots at each stage and RAM-map checkpoints (mode, world position, party, event bits, save slot). ## Validation - Builds clean: debug, clang, mingw; `--fast` passes on the three (13/13). - Slow suite, release, `-j2`, run once (machine shared with another agent, so times are inflated): **29/29 passed**, with an empty start point directory so the fixtures regenerated the start points (CRC checked). | Test | US s | JP s | |---|---|---| | startpoint.narshe_to_world_map (regeneration, file missing) | 1531 | 1552 | | startpoint.narshe_to_world_map (file present) | 0 | 0 | | route / movie / route_ports_on narshe_to_world_map | 1245 / 1188 / 987 | 1008 / 946 / 916 | | route / movie / route_ports_on narshe_to_figaro | 454 / 444 / 453 | 385 / 377 / 367 | ## Time gain (#24) `narshe_to_figaro` starts after ~1000 frames of Continue instead of replaying the 80 000-frame `narshe_to_world_map` movie first: as an `after:` chain each of its 6 tests would add about one `movie.narshe_to_world_map` replay (1188 s US, 946 s JP here), i.e. about 6400 s of test time saved per suite run; the start point is regenerated once (about 1550 s here) only when it is missing. The narshe tests themselves still replay from power-on (no save point before the first world map), so the 20-minute target of #24 needs more (e.g. the `nightly` label for `narshe_to_world_map`). Start point files are ROM-derived game data and are never committed. Fixes #26 Refs #22 #24 🤖 Generated with [Claude Code](https://claude.com/claude-code)
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!36
No description provided.