re: all savegame variation is in the header; slot region identical -- and my heuristic overstates

Splitting the same comparison at the documented slot-table boundary (save+136):
the header holds 34 words and ALL 12 differing words, while the slot table holds
35 words and ZERO differences. The slot region is byte-identical between the two
same-state saves, so the documented slot fields are untouched by the churn and a
slot-region diff is meaningful where a whole-file diff is not.

Also corrects my own framing from the previous commit. The slot region contains
6 words in the pointer value range that do NOT change across runs -- a pointer
captured from a moving heap would not sit still, so those are data whose values
merely land in 0x70-0x8F / 0xB0-0xBF. The value-range test alone does not
identify a pointer; a third of what it flags here is not one. What identifies a
pointer is being pointer-shaped AND varying, ideally with a shared constant
delta. So '26% of the file is heap addresses' overstates it and the defensible
figure is the 8 header words that are both.

Left the earlier section in place with the correction after it: a value-range
classifier on 32-bit words always has a false-positive rate, and quoting its raw
count as a fact about the format is the error.
This commit is contained in:
Sylpheed RE agent
2026-08-26 07:44:55 +00:00
parent 5d49f54c92
commit c1d01ad36a

View File

@@ -631,3 +631,41 @@ in 12 words**, not 135.
Worth stating because the inflated figure looked plausible: half the file
changing between saves is exactly what one would expect if saves were dense
state, and nothing about it invites a second look.
## ✅ Refinement: every difference is in the HEADER; the slot region is identical
**Same day, one iteration later.** Splitting the same comparison at the
documented slot-table boundary (`save+136`) sharpens the result considerably and
corrects the framing above:
| region | words | pointer-shaped | **differ between same-state saves** |
|---|---|---|---|
| header, `< 0x88` | 34 | 12 | **12 — all of them** |
| slot table, `≥ 0x88` | 35 | 6 | **0** |
**The slot region is byte-identical between the two saves.** Every one of the 12
differing words lives in the header. That is a stronger and more useful statement
than the pointer framing, and it means **the documented slot fields on this page
are untouched by the churn** — they are stable state, and a diff of the slot
region is meaningful in a way that a diff of the whole file is not.
### ⚠️ And my "pointer-shaped" heuristic has false positives
The slot region contains **6 words in the pointer value range that do not
change** — `0x73777174`, `0x770F8877`, `0xBC2B75EF`, `0x8187F76B`,
`0x7BE9C030`, `0x829F6B88`. A pointer captured from a moving heap would not sit
still across two runs, so these are data whose values merely land in
`0x700x8F`/`0xB00xBF`.
So the value-range test alone **does not identify a pointer** — a third of the
words it flags here are not pointers. What identifies one is the *combination*
of pointer-shaped **and** varying across runs, ideally with a shared constant
delta as three of the header words have (`0x101080`). The previous section's
"26 % of the file is heap addresses" overstates it on that basis; the defensible
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.