re: decode the UnitGroup squadron roster, and correct yesterday's container reading
stage\UnitGroup_S<NN>.tbl is now fully readable. A squadron record is Count
member tuples -- (unit model, message set, n, identity/nameplate) -- followed by
five named fields: Count, SideID, AIID, FormationID, DisableInterval. The
property entries carry their own field names inline, so the tag hash never has
to be inverted.
Two independent self-checks validate it corpus-wide, 1160/1160 each across all
28 stage tables on the disc:
- the length identity len(fields) == Count * 4 + 5, which is what pins the
member-tuple width at 4 and the named-field count at 5;
- agreement with the file's own Enumerate_Squadrons roster, which maps record
key to squadron id independently of the per-record string offset.
Adds tools/re-capture/unitgroup.py (pure static, runs no emulator) with a
--all --check self-check mode, and commits the Stage 02 dump as evidence.
Corrections to the container layout written yesterday, all three wrong:
- the 20-byte "(tag, 0, 0, count, size) section header" does not exist. It
was the file's last 16-byte record followed by a plain npool word. The
corrected layout is uniform across all 28 files; the old one failed on 9.
- squadron ids do not use a separate string base. Every offset in the file is
relative to the one string pool. The earlier "109 of 111" score was an
artefact of the uniform 7-byte id stride and had silently shifted every
name by three entries, which is why 17 TC*-named squadrons came out as
SideID=ADAN. The roster record refuted it outright.
- the roster is not always the last record; 9 stages put it elsewhere, so it
is found by its missing Count.
Refuted and kept: the 4-byte record key is not the squadron id's name hash
(0 of 112).
Not settled: what the key encodes, the member tuple's third field n, and where
the arrival interval values live. DisableInterval is only a per-squadron flag
(Yes for 31 of 1160); the durations, triggers and arrival positions are not in
this file. Formation_*.tbl and EnumSquadron_Test.tbl are next.
This commit is contained in:
@@ -283,10 +283,27 @@ search cannot find a *schedule*.
|
||||
🔴 Refuted along the way: the 16-byte record key is **not** the squadron
|
||||
ID's name hash (0 of 112).
|
||||
|
||||
**First step (next):** read the `UnitGroup` per-record payload — three u32s per
|
||||
entry — and find where the interval *values* live (the file's second section,
|
||||
`Formation_*.tbl`, or `EnumSquadron_Test.tbl`). Also: S17–S23 have no stage
|
||||
record in `GP_MAIN_GAME_E.pak`; find where they are.
|
||||
* ✅ **`UnitGroup` is fully decoded** (2026-08-24). Container and field semantics
|
||||
in [`structures/unit-group-table.md`](structures/unit-group-table.md), tool
|
||||
`tools/re-capture/unitgroup.py`, Stage 02 dump committed at
|
||||
[`data/unitgroup-s02.txt`](data/unitgroup-s02.txt). A squadron record is
|
||||
`Count` member tuples — (unit model, message set, `n`, identity/nameplate) —
|
||||
followed by five named fields `Count / SideID / AIID / FormationID /
|
||||
DisableInterval`. Validated corpus-wide by two independent self-checks, each
|
||||
**1160/1160** across all 28 stage tables: the `Count*4+5` length identity, and
|
||||
agreement with the file's own `Enumerate_Squadrons` roster.
|
||||
🔴 Two refutations recorded: the record key is **not** the squadron-ID name
|
||||
hash, and an earlier "109/111" reading of the squadron-id string base was an
|
||||
artefact of the uniform 7-byte id stride (it shifted every name by three).
|
||||
|
||||
**First step (next):** find where the arrival *interval values* live.
|
||||
`DisableInterval` is only a per-squadron flag (`Yes` for 31 of 1160); the
|
||||
durations, spawn triggers and arrival positions are not in `UnitGroup`. The
|
||||
stage record names two untouched candidates: `Formation_*.tbl` (formation
|
||||
geometry, possibly its timing) and `EnumSquadron_Test.tbl`. Also still open: the
|
||||
4-byte record key, the member field `n`, and the missing S17–S23 stage records
|
||||
(S17 has no `UnitGroup_S17.tbl` either, so the whole stage is absent from
|
||||
`GP_MAIN_GAME_E.pak`).
|
||||
|
||||
## The dynamic-RE state is not in git, and it was gone
|
||||
|
||||
|
||||
Reference in New Issue
Block a user