re: saves can be written back, which settles what the develop blob's 4s mean and refutes the tail

The container's derived fields turned out to be reproducible -- length+10 at
+0x30, payload length at +0x8c, adler32(payload) at +0x8e, everything else
copied -- and savegame_edit.py re-wraps a real save BYTE-IDENTICALLY, which is
the check that those three are the only ones. A hand-written save then loaded.

That replaced a blocked experiment (the tail question needed a mission payout,
and none of the currently developable items even sit in the disputed range) with
a direct one: write the blob, read the Arsenal.

  - controls: 4 at index 9 -> STILETTO BG1 Developed, 21 -> FALCON 9AM
    Developed. A hand-written 4 reaches the screen.
  - tail: 4 at 33 and 45 left their rows dashed (both on screen, not below the
    fold), and 38 left TOMAHAWK ALPHA RAIL GUN at "0 P" -- not owned. So the
    tail is not the weapon.tbl order continued.
  - clearing the real save's {22,26,39,46,47} cost the Tomahawk its Developed
    status, which puts its flag in that set (39 positionally) -- but a uniform
    +1 fails for SPECIAL, so no shift is asserted. Indices >=32 stay marked.

Two behaviours fell out. The title RE-DERIVES developable state on load and
announces it ("You can now develop Broad Sword ..."), so only the 4s are stored
state and a written 2 is pointless. And a no-cost item is bought for 0 P rather
than granted -- TOMAHAWK at "0 P" is what unowned looks like -- which is the
actual reason items read Developed in a save where nothing was spent.

Slot 03 was restored from its archived original (md5 verified); slots 01/02 were
never touched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-11 18:10:28 +00:00
parent f88f4f6847
commit f5f95be0a1
4 changed files with 166 additions and 11 deletions

View File

@@ -135,16 +135,57 @@ either: `blob[39] = 4` would put the Tomahawk right, but then `blob[33] = 4`
lands on `Arrow_27_Rocket` (Stage 2 + 5000 P, unreachable here) and 45/46/47
still land on locked SPECIAL items.
**Status: ❔ NEEDS-HUMAN / needs the next differential.** The value alphabet and
the first 32 indices are settled; the tail is not, and should not be written into
the reimplementation as if it were. The cheap way to settle it is a second
development in a **late** category (CANNON or SPECIAL) — whichever index moves
names the tail directly. It needs points: the balance is 101 P, so it waits on a
mission payout.
### Tested actively, with a hand-written save
Waiting for a mission payout was not necessary. The save container's derived
fields turned out to be reproducible (see
[`savegame_edit.py`](../../tools/re-capture/savegame_edit.py) — the whole
container re-wraps **byte-identically**), so the blob could be *written* and the
result read off the screen. A probe save was built in our own throwaway slot 03
with the blob zeroed except `0, 9, 21, 33, 38, 45 = 4` and `39, 46 = 2`, and it
**loaded**.
What it showed:
- **The controls rendered.** `9` → BEAM shows `STILETTO BG1 Developed`; `21`
MULTIPURPOSE MISSILE shows `FALCON 9AM Developed`. So a hand-written `4` does
reach the screen, and indices 9 and 21 are those items — now by experiment,
not by correlation.
- **The tail probes rendered nothing.** `33` should have made a BOMB/ROCKET row
`Developed` (row 3 of that list, on screen, not below the fold) — it stayed
dashed. `45` should have made a SPECIAL row `Developed` — the SPECIAL tab
stayed entirely empty. And `38` should have been the Tomahawk — instead the
CANNON list showed `TOMAHAWK ALPHA RAIL GUN — 0 P`, i.e. *not owned*.
- **Clearing the real save's tail `4`s cost the Tomahawk its status.** In the
unedited save the Tomahawk reads `Developed` while `blob[38] = 0`; the probe
cleared `{22, 26, 39, 46, 47}` and the Tomahawk stopped being owned — so its
flag is one of the cleared entries, with **39** the positional candidate. A
uniform `+1` shift past index 32 would explain that, but it fails elsewhere:
under it the real save's `45/46/47` are Chaff Flare Dispencer / Shield Doubler
/ Booster, and the SPECIAL tab is empty in that same save.
So the tail is not a shifted copy of the list either. **Status: ❔** — the value
alphabet and indices 031 are settled; indices ≥32 are not, and must not go into
the reimplementation. The next probe is cheap now that saves can be written: set
one tail index at a time and read which row changes.
### Two behaviours the probe exposed
- **`2` is derived, not stored.** On load the title recomputes which items are
developable from its own conditions and *announces the difference* — zeroing
Light Machine Gun MG1 and Broad Sword SG1 produced "You can now develop Broad
Sword …" and both came back priced in the list. Only the owned (`4`) entries
are authoritative state; writing `2` is pointless, and writing `0` over an
item whose conditions are met is undone at load.
- **The free items are bought for zero, not granted.** `TOMAHAWK ALPHA RAIL GUN
— 0 P` is what an unowned no-cost item looks like. That is the real reason a
save where the player never spent points still shows items as `Developed`
(this note previously said "granted" — the mechanism is a 0 P purchase).
## Evidence
- [`captures/arsenal-develop-conditions.csv`](captures/arsenal-develop-conditions.csv) — all 60 conditions blocks.
- [`captures/arsenal-categories-all.png`](captures/arsenal-categories-all.png) — the eight category tabs.
- [`captures/arsenal-gun-below-fold.png`](captures/arsenal-gun-below-fold.png) — Broad Sword SG1, the entry that is not visible without scrolling.
- [`captures/arsenal-probe-save-result.png`](captures/arsenal-probe-save-result.png) — the hand-written save's result: controls at 9/21 render `Developed`, the tail probes render nothing, and the Tomahawk shows `0 P`.
- [`captures/arsenal-gun-list-predevelop.png`](captures/arsenal-gun-list-predevelop.png) · [`captures/arsenal-mg1-developed.png`](captures/arsenal-mg1-developed.png) — the differential itself.