re: three probes for the parsed record all miss -- hypothesis: there is not one

Searched RAM for HP 25000 (200+ hits, too common), for the rare float
AttackVesselPoint 0.08 (64 hits, no window holds the unit's other values, one hit
is a code constant), and for the ID string itself (two copies, each pointed at
from -0x10, but the surrounding 256 words hold none of the numbers because that
region is the IDXD string pool where values are ASCII).

Hypothesis recorded as 🟡: IDXD is reflective and the engine likely reads values
from the pool by key on demand, caching only the per-frame ones -- which is
exactly what the 0x820af844 object contains at any dump depth. If so, a defaulted
field has no value anywhere in data and the default is applied by code at read
time, so Route B for the Ratio/Count family needs the read path or the static
DuckDB route, not more scanning. The 13 Size_Y values worked because Size_Y is
one of the cached fields.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-12 21:00:48 +00:00
parent f4f3bcb20a
commit bab2f9e6ca
2 changed files with 54 additions and 0 deletions

View File

@@ -164,3 +164,35 @@ elsewhere, presumably behind a pointer.
Next probe, therefore, is not a bigger window: search guest RAM for a value that
is distinctive to one unit (e.g. the Acropolis' `HP 25000` = `0x46c35000`) and see
what *other* structure holds it, then map that one.
## Where the rest of the record is — three probes, and a hypothesis
Following "search RAM for a unit-distinctive value" produced no parsed record:
1. **`HP 25000`** (`0x46c35000`, the Acropolis) — **200+ hits**, the search limit.
Too common to anchor on: it is also a generic constant.
2. **`AttackVesselPoint 0.08`** (`0x3da3d70a`, an unusual float) — 64+ hits, and
**none of the eight windows dumped around them contained the unit's other
values** (`Size_X 400`, `Size_Z 1400`, `HP 25000`, `RadarRange 60000`). One hit
sits in the executable range (`0x820b62f4`), i.e. a code/rdata constant.
3. **The ID string itself.** `UN_f101_TCAF_Acropolis` appears **twice** in RAM,
each copy referenced by a pointer exactly **16 bytes before the string**. But a
256-word window around it contains **none** of the unit's numbers — because
that region is the IDXD **string pool**, where `25000.0` is stored as *text*.
🟡 **Hypothesis: there is no flat parsed record.** IDXD is a reflective format,
and the evidence fits the engine reading values out of the pool by key when it
needs them, caching only the few it touches per frame. That is exactly what the
`0x820af844` object looks like: sizes (collision), HP (damage), a couple of
ratios — and nothing else, no matter how deep it is dumped.
If that is right, it reframes Route B. For a **defaulted** field there is no value
in the pool at all, so the default is applied by *code* at read time and can never
be found by scanning data structures. It would have to come from either the read
path (trace where a key hash is looked up and what the miss path substitutes) or
from the title's own code — which is the DuckDB static route this project already
has. The 13 `Size_Y` values recovered above worked precisely because `Size_Y` is
one of the cached, every-frame fields.
This is a hypothesis, not a finding: it explains three negative probes but has not
been confirmed by watching a read happen.