re(units): target missions by roster, harvest S09 — 36 units / 3 439 defaulted values
examples/roster_target.rs ranks stages by how many roster units are still
unharvested. The EnumUnit_S<NN> tables are found by hashing candidate TOC paths
(hash::TOC_NAME_SCHEMES) — UnitRoster::stage can only infer a tag when the roster
carries a UN_S<NN>_ prop, which most do not.
It picked S09 (10 missing). Flying it: 26 -> 36 units, 3 345 -> 4 785 rows,
2 351 -> 3 439 defaulted-on-disc values. New: e102_Battleship, e104_Carrier,
e107_AAFrigate, e011_Attacker_B, e008_TurretPlus, be001_TerrafoamingUnit,
e001_Elan_GR{,_Violeta}, f102_LightCarrier_Inv, f106_Destroyer_Inv.
Also settled: the definition objects are mission-independent. Eleven units appear in
more than one snapshot and four are not byte-identical, but compared through the
layout ZERO mapped fields differ — the 12 differing slots are all unmapped (offsets
4/8/16/20 and 0x250/0x268/0x300-0x308/0x330-0x338: object header and sub-object
pointers). So a harvested value is the definition, not a per-mission tweak, and the
earlier UN_f201_TCAF_Tanker flag resolves the same way. Cross-checks over three
snapshots: 1 052 agree, 0 disagree.
Third angle field found the same way (Through_AngleMaximum = 60 degrees in radians),
so the degrees<->radians rule covers any name containing "Angle".
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NptfmpjdpNCKEez6d2xvA9
This commit is contained in:
@@ -450,3 +450,33 @@ Two things the run pinned down, both cheap to re-learn the hard way:
|
||||
⚠️ One unit's object is **not** byte-identical between the two missions —
|
||||
`UN_f201_TCAF_Tanker`. Either a per-mission override or a field the runtime mutates;
|
||||
the merged CSV holds the later reading, and separating them needs a third snapshot.
|
||||
|
||||
### Targeting the next mission, and the check that these really are definitions (2026-08-13)
|
||||
|
||||
[`examples/roster_target.rs`](../../../crates/sylpheed-formats/examples/roster_target.rs)
|
||||
ranks the stages by how many of their roster units are **not yet harvested**. The
|
||||
rosters are `EnumUnit_S<NN>` tables whose TOC entries store a *path hash*, so the
|
||||
stage label comes from hashing the candidate paths
|
||||
(`hash::TOC_NAME_SCHEMES`) rather than from `UnitRoster::stage`, which can only
|
||||
infer a tag when the roster happens to carry a `UN_S<NN>_…` prop.
|
||||
|
||||
It picked **S09 (10 missing)**; flying it took the file to **36 units / 4 785 rows /
|
||||
3 439 defaulted-on-disc values**, adding `UN_e102_ADAN_Battleship`,
|
||||
`UN_e104_ADAN_Carrier`, `UN_e107_ADAN_AAFrigate`, `UN_e011_ADAN_Attacker_B`,
|
||||
`UN_e008_ADAN_TurretPlus`, `UN_be001_ADAN_TerrafoamingUnit`,
|
||||
`UN_e001_ADAN_Elan_GR{,_Violeta}`, `UN_f102_TCAF_LightCarrier_Inv` and
|
||||
`UN_f106_TCAF_Destroyer_Inv`.
|
||||
|
||||
**The objects are mission-independent — measured, not assumed.** Eleven units appear
|
||||
in more than one snapshot, and four of them are *not* byte-identical across missions.
|
||||
Comparing them **through the layout**: **zero mapped fields differ**. The 12 differing
|
||||
4-byte slots are all **unmapped** — offsets `4/8/16/20` (the object header and name
|
||||
pointer) and `0x250/0x268/0x300–0x308/0x330–0x338` (sub-object pointers) — i.e. guest
|
||||
addresses, not data. So a value harvested in one mission is the unit's definition, not
|
||||
a per-mission tweak, and the earlier `UN_f201_TCAF_Tanker` flag resolves the same way.
|
||||
|
||||
Cross-checks against the disc over the three snapshots: **1 052 agree, 0 disagree.**
|
||||
|
||||
One more angle field turned up the same way as the last: `Through_AngleMaximum`
|
||||
(object `1.0472` = 60° in radians) carries neither an `AV_`/`AA_` token nor `Bank`, so
|
||||
the degrees↔radians rule covers **anything with `Angle` in the name** too.
|
||||
|
||||
Reference in New Issue
Block a user