diff --git a/docs/re/structures/savegame-format.md b/docs/re/structures/savegame-format.md index 9b40dbc..18c6a7c 100644 --- a/docs/re/structures/savegame-format.md +++ b/docs/re/structures/savegame-format.md @@ -332,4 +332,46 @@ labels per slot" are not yet separated. The next move is not another probe — i is to find the code that formats `STAGE %02d` and read which offset it loads, which the static DB can answer directly. +### What the screen itself is built from (static, `.rdata`) + +The LOAD/SAVE screen's config **key list is compiled into the executable**, as a +pointer array of key strings — the same shape as the Arsenal's (whose keys sit a +few hundred bytes earlier and match the pak record exactly, which is what +identifies these as config keys rather than loose strings). The save-screen run +starts at **`0x820a0074`**: + +``` +game, replay, LOADING, GAME, REPLAY, SELECTOR, SAVE_BASES, SAVE_MENUS, +LOAD_BASES, LOAD_MENUS, THUMBNAIL, FONT, EX_FONT, AUTO_SAVED, +AUTO_SAVED_DETAIL, MISSION_SELECT, MISSION_SELECT_DETAIL, CLEARED, EMPTY, +EMPTY_DETAIL, SLOT, VOLUME, STRINGS, +GAME_EASY, GAME_NORMAL, GAME_HARD, GAME_VERY_HARD, +STATE_STAND_BY, STATE_STAGE_CLEAR, STATE_GAME_CLEAR, +LOCATE, …, STAGE01 … STAGE16, CLEAR_TIME_RANKING +``` + +Three things fall out, none of which needed the emulator: + +- **There is a fourth difficulty.** `GAME_VERY_HARD` exists alongside EASY / + NORMAL / HARD, while the stage tables only carry `BonusPoint_EASY/NORMAL/HARD`. + So VERY HARD is 🟡 an unlockable tier the stage bonus table does not price. +- **`Game Status` is a three-valued enum** — `STATE_STAND_BY` (what our save + shows as `At Standby`), `STATE_STAGE_CLEAR`, `STATE_GAME_CLEAR`. +- **The screen can label exactly 16 stages**, `STAGE01`…`STAGE16`. That matches + `weapon.tbl`'s `AUTO_SETTINGS` list — `stage01…16` plus `tutorial01…06` and + `challenge01…06` — so **16 is the story-stage count**, and the "22 stages" + figure used elsewhere in these notes counts a different set (🟡 probably story + plus challenge). Worth reconciling before either number is relied on. + +The panel's own field names are here too, with their screen positions: +`Points`, `FlightTime` (`%03d:%02d:%02d`), `ClearTimes`, `CompletionRate`, +`RatioOfClear`, `Index`, `Label`, `Date`, `BrokenData`. + +**This does not name the stage/difficulty save fields**, and it explains why the +probe sweep could not either: the screen selects a *sprite key by index*, so the +value it indexes with is whatever the loader put in the live object — and the +strings are reached through a config lookup, not an immediate, so there is no +`lis/ori` pair to xref back to the selecting code. Chasing it further means +disassembling the save-screen's populate path, not another grep. + Editing beyond a throwaway slot is still the user's call.