From 67cce0e4c00002d06fa687294945e43893c22004 Mon Sep 17 00:00:00 2001 From: Sylpheed RE agent Date: Wed, 26 Aug 2026 07:50:29 +0000 Subject: [PATCH] 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. --- docs/re/structures/savegame-format.md | 45 ++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/docs/re/structures/savegame-format.md b/docs/re/structures/savegame-format.md index 1877e471..afdbf291 100644 --- a/docs/re/structures/savegame-format.md +++ b/docs/re/structures/savegame-format.md @@ -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. \ No newline at end of file +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. \ No newline at end of file