From bc42c0970eca313075f8e11221db2573c75a6e61 Mon Sep 17 00:00:00 2001 From: "Claude (auto-RE)" Date: Tue, 11 Aug 2026 20:13:01 +0000 Subject: [PATCH] re: the save screen's key table is compiled into the executable -- a 4th difficulty, 3 states, 16 stages Static, no emulator. The LOAD/SAVE screen's config keys sit in .rdata as a pointer array at 0x820a0074, identified as config keys (not loose strings) by the Arsenal's own key list sitting a few hundred bytes earlier and matching its pak record exactly. - GAME_VERY_HARD exists alongside EASY/NORMAL/HARD, while the stage tables only carry BonusPoint_EASY/NORMAL/HARD -- a fourth, unpriced tier. - Game Status is a 3-valued enum: STATE_STAND_BY (our save's "At Standby"), STATE_STAGE_CLEAR, STATE_GAME_CLEAR. - Exactly 16 STAGE sprite keys, matching weapon.tbl's stage01..16 (plus 6 tutorials and 6 challenges). So 16 is the story-stage count and the "22 stages" figure used elsewhere counts a different set -- flagged, not silently changed. Also recovered: the panel's field names and positions (Points, FlightTime %03d:%02d:%02d, ClearTimes, CompletionRate, RatioOfClear, Index, Label, Date, BrokenData). It does NOT name the stage/difficulty save fields, and it explains why the probe sweep could not: the screen picks a sprite key BY INDEX through a config lookup, so there is no lis/ori immediate to xref back to the selecting code. Co-Authored-By: Claude Opus 5 (1M context) --- docs/re/structures/savegame-format.md | 42 +++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) 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.