# Session log — 2026-08-11 (autonomous run) What changed today, in the order a reviewer would want it, with the one item that needs **your decision** called out first. ## Needs a decision from you **Editing save slot 01.** Save files can now be written back ([savegame_edit.py](../../tools/re-capture/savegame_edit.py) re-wraps a real save **byte-identically**), and hand-written saves load. That unblocked several questions by probing throwaway slots. But the **title-menu screens read the auto-save (slot 01)**, so the remaining save-field questions (the difficulty enum, `SHAB.b`) need slot 01 itself edited — the only save with real progress. Not done. Recoverable (full content backup + slot 01's bytes archived), but it is your call. Everything else below was done in throwaway slots. ## Findings, by area ### Save format - **The develop differential**: buying one Arsenal weapon moves exactly three fields — Points `+24` (which **separates it from `+28`**), clear ratio `+8` (so the ratio counts *collection*, not stages), and two entries of the 54-byte blob. Blob alphabet: `0` locked / `2` developable / `4` owned; only the `4`s are stored, `2` is re-derived at load. - **The blob's index space is solved** — it follows `strings.tbl`'s item order, **cut items included**, pinned by four probe saves and closing exactly at 53. - **`SHAB` is the per-stage record table**: record 0 = Stage 01, and `c` is its best clear time in ms (`324773` = the `05:24.77` MISSION SELECT shows). - **Refuted**: every GHAD scalar as stage/difficulty (16 elements probed), and "stage = filled `SHAB` count + 1". ### Formats - **T8aD 96 % → 100 %** of the disc: a surface is a list of **sub-rectangles** (`dst X, dst Y, w, h` per rectangle), not a 256 grid. The "~15 % variants" were a wrong model. - **LSTA**: the count was never unreliable — it counts **sprites *and* `PRMD` primitives** (64/64 exact). - **RATC**: "one level deep" is not a limitation; nested records are **leaves that reference siblings by name** (10 144/10 148 resolve). - **UI screens are fully reconstructible from their bundle** — element list + order (declaration table, with a **parent index**) and placement/animation (keyframe region). **Validated against the running game to ±2 px.** - **Movie ↔ subtitle ↔ voice link solved statically** (101 movies) — `INDEX` had it filed as needing the running game. - **XPR2 channel order confirmed** against the game (hue 23.3° vs 9.3°). ### Meshes — the user-reported viewer bug - Root-caused, **after one wrong turn I corrected in place**: the giant slab on `e106` is not a stray volume but an **XBG7 mis-decode** — the same resource is a 49×23×42 turret in 11 containers and 1600×2100×4800 in 3. - **New detector**: a resource shared across containers must decode to the same bounds. **125 of 681** shared resources fail that check — a measured lower bound on *silent* mis-decodes (distinct from the 814 honest declines). ## Two disc defects found `SUBTITLE_S12B.tbl` (referenced by the movie table, present in **no** language) and `pmbase.t32` (placed by `pmbase.rat`, present **nowhere**). A reimplementation should skip a missing asset rather than treat it as a decode failure. ## Process notes worth keeping - Several "the data is inconsistent" comments meant **our model was incomplete** (T8aD variants, the LSTA count). Re-test such notes rather than routing around them. - A test that walks the *oracle's* items and looks each up in our output **can only fail one way** — it never sees extras. That shape hid the ship bug and, earlier, `include_external`. - When a diagnosis has eliminated every hypothesis and the last step is *a visual*, do the visual first. Three iterations went by before a 30-second render showed it.