re: correct my last two savegame sections -- they analysed the COMPRESSED stream

Both preceding sections split the file at 0x88 and called everything after it
the slot table. Wrong: this page already documents the container as GDHA + a
146-byte header + a zlib stream, and savegame.rs implements it. 0x88 is where
the Z1/zlib payload begins (5a31 = 'Z1', 78da = zlib), so the bytes I treated as
slot fields are deflate output.

Invalidated: the '6 pointer-shaped words in the slot region' are not words and
not pointers, so the false-positive rate I derived from them measured nothing.

Survives with different reasoning: 'the slot region is byte-identical' is true
because the two COMPRESSED streams are identical, which does imply identical
payloads -- and inflating both confirms it, 545 bytes byte-for-byte equal.

Stands and is better founded: all 12 differing words are in the header, which is
the only uncompressed region and therefore the only place a word-wise diff means
anything.

Done correctly, the result is a confirmation rather than a discovery: inflating
all three payloads reproduces the documented clear-ratio field stepping 5 -> 6
on the developed save.

The lesson: I found Z1/78da by inspection and nearly wrote it up as new. It was
already decoded four sections above where I was appending. Reading the whole
page first would have saved two wrong commits, and the wrongness was not
cosmetic -- a pointer census ran over deflate output and produced a
plausible-looking table.
This commit is contained in:
Sylpheed RE agent
2026-08-26 07:50:29 +00:00
parent 91074d1ba7
commit 67cce0e4c0

View File

@@ -668,4 +668,47 @@ figure is the 8 header words that are both pointer-shaped and moving.
I am leaving the earlier section in place with this correction after it, because
the mistake is instructive: a value-range classifier on 32-bit words will always
have a false-positive rate, and quoting its raw count as a fact about the format
is the error.
is the error.
## ❌❌ CORRECTION — my two sections above analysed the COMPRESSED stream
**Same day, immediately after.** Both preceding sections split the file at
`0x88` and called everything after it "the slot table". That is wrong, and this
page already says so further up: the container is `GDHA` + a **146-byte header**
+ a **zlib stream**, and `savegame.rs` has implemented that all along. `0x88`
is where the `Z1`/zlib payload begins — `5a31` is `Z1`, `78da` is the zlib
header — so the bytes I was treating as slot fields are **compressed data**.
What that invalidates, precisely:
* ❌ **The "6 pointer-shaped words in the slot region"** are not words and not
pointers. They are deflate output. Classifying compressed bytes by value range
is meaningless, and the "false-positive rate" I drew from them measured
nothing.
* 🟡 **"The slot region is byte-identical between the two saves"** is *true* but
for a different reason than I gave: the two **compressed streams** are
identical. That does still imply identical payloads — a deterministic deflate
of the same input — and inflating both confirms it directly: **545 bytes,
byte-for-byte equal**. So the conclusion survives; the reasoning did not.
* ✅ **"All 12 differing words are in the header"** stands, and is now better
founded: the header is the only *uncompressed* region, so it is the only place
a word-wise diff means anything at all.
**The useful result, done correctly.** Inflating all three payloads (545 bytes
each, declared size matching in 3 of 3):
stage02-5pct ... 00000005 ... payload identical to game02
game02-samestate ... 00000005 ...
game03-developed ... 00000006 ... and 0x00001005 -> 0x00000065
`5 → 6` on a developed weapon is exactly the **clear-ratio** behaviour this page
already documents at payload `+8`, reproduced here from the captures. That is a
confirmation of an existing reading, not a new one.
### The lesson worth keeping
I found `Z1`/`78da` by inspection and was one step from writing it up as a
discovery. It was already decoded, in this same file, four sections above where
I was appending. **Reading the whole page before analysing its subject would
have saved two wrong commits** — and the wrongness was not cosmetic: an entire
pointer census ran over deflate output and produced a plausible-looking table.