re: audit the legacy IDXD reader against the real field table — and fix a test that encoded its error

With the record table decoded there is finally a ground truth to check the
old string-pool reader against. It infers `key -> value` from pool adjacency,
which is a consequence of how records are written, not a rule of the format.

Verified by hand against the disc, with an independent parser:

* `FCSRange` = 500000.0 — the module docs' own canonical example of a field
  "left at its default" that "omits the value string".
* `ShieldRatio` = 1.0, where `tests/pak_idxd_disc.rs` asserted None with the
  comment "a defaulted/omitted field must be None". That test encoded the
  false belief; it now keeps the None as a deliberate characterisation of the
  legacy reader, with the true value asserted beside it.
* `get_raw("Model")` on GP_HANGAR_ARSENAL returns the first record's model for
  every record — silent corruption, not an absent value. New test pins four
  records that disagree with it.

The cause is the flat API having no way to name a record: only 548 of 6325
objects have one. `HP` on the DeltaSaber answers 1000.0, the hull, while 63
Turret_* records each carry their own 100.0 (measured — a first draft said 34,
taken from a report rather than from the disc).

Disc-wide rates are recorded as single-source and labelled as such: get_raw
52% wrong, typed getters 38% miss, but 100% correct on single-record objects.

Also records a negative result: the 504 unnamed field keys were NOT recovered.
A 572464-string dictionary and 73191 variants gave 0/42. The key deltas do
prove the preimage ends with the two decimal digits.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
This commit is contained in:
Sylpheed RE agent
2026-08-25 21:42:51 +00:00
parent af32540190
commit 9141ea2b24
4 changed files with 206 additions and 1 deletions

View File

@@ -1033,6 +1033,27 @@ premise was wrong.**
Candidates: the **7 `.embsec_` sections** (VAs 0x84D0000–0x86AC000, ~129 KB
total, executable) or a hashed record in `hidden/MiscBin.pak`. **Finding it
gives the actual per-phase clear condition for every stage.**
* 🟡 **(2026-08-25) The legacy IDXD string-pool reader is wrong far more often
than assumed** — now measurable for the first time, since the record table gives
a ground truth. Verified by hand: `FCSRange` (the module doc's own canonical
"field with no value") is really `500000.0`; `ShieldRatio` is `1.0` where a
**committed test asserted `None` and called it defaulted**; and
`get_raw("Model")` on the hangar table returns the *first* record's model for
every record — silent corruption, not an absent value. Single-source disc-wide
rates: `get_raw` 52 % wrong, typed getters 38 % miss — but **100 % correct on the
548 single-record objects**, so all the damage is the flat API having no way to
say *which* record it means. ▶️ **Open work:** re-read every per-record number in
this corpus through `IdxdObject::record`; highest value first — hangar models,
weapon `Power`/`Acceleration`/`MinimumVelocity`, turret and subsystem stats.
See [`idxd-legacy-reader-audit.md`](idxd-legacy-reader-audit.md).
* ❌ **(2026-08-25) The 504 unnamed IDXD field keys were NOT recovered.** All sit
in `GP_READY_ROOM.pak`'s sound-bank table (6 identical objects × 2 records × 42
keys). A dictionary of 572 464 strings — every pool string disc-wide, PE ASCII
and UTF-16 runs, every identifier in this repo — plus 73 191 case/affix variants
gave **0/42**. The key deltas across `stage01…stage16` do prove the preimage
**ends with the two decimal digits**, and a meet-in-the-middle found nothing
word-like at ≤8 lowercase chars. 32 bits is not invertible without the right
wordlist; parked.
* ✅ **(2026-08-25) The IDXD/IXUD container is fully decoded** — the "binary
node/index region" in front of the string pool is a **uniform 16-byte record
array** `{name_hash, name_off, field_begin, field_end}` sorted by hash, then a