Took the biggest of the five unowned base-solver blocks, sub_822215D0 (205/206). Grep-and-READ first, and it paid. PGHUD* pointed at mission-script-manifest.md, which documents HudResource's 24 fields -- but hud-config.md owns the whole family: all 16 records in the six GP_MAIN_GAME_*2D paks, 419 distinct asset paths. Stopping at the first grep hit would have "discovered" a documented table for the second time in three iterations. Control: counting PG* field names straight off the paks reproduces that document's own numbers exactly -- Sight 35, Radar 29, Marker 27, Wing 23, Manuva 15; HudResource 23 PG* + HUD_RES_FONT = its stated 24. The increment: the executable carries its own roster. sub_822215D0 reads a 205-name block at base 0x820A0000, 205/205 PG*-prefixed, zero partials -- PGHUD 77, PGTARGET 31, PGGAUGE 25, PGMANUVA 16, PGMARK 12, PGWARNING 10, PGMARKTGT 9. The disc has 228 distinct PG* names; 200 are in both, 5 code-only, 28 disc-only. 200 + 5 = 205 and 200 + 28 = 228, closing both ways. Four of the five code-only names are printf families whose stem is a disc field (PGHUD_HIT_NUM_EFF%d, PGHUD_HIT_NUM_RED%d, PGREMAIN_NUM%d, PGTIMER_NUM%d) and all four stems sit in the disc-only 28: the code builds indexed instance names from a base name the table declares. After pairing, the residual is one code-only name (PGMANUVA_EFF0) and 24 disc-only ones, listed in the doc. Not settled: what the block is for -- the function body was not read. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
151 lines
7.7 KiB
Markdown
151 lines
7.7 KiB
Markdown
# ✅ The in-game HUD configuration — 16 records, and a per-stage resource table
|
||
|
||
The `GP_MAIN_GAME_*2D.pak` archives carry **six IDXD entries** that are the
|
||
in-game counterpart of `tables.pak`'s menu configs. Only `HudResource` had been
|
||
opened ([mission-script-manifest](mission-script-manifest.md)); the other
|
||
**fifteen** records had not. No `docs/re/` file mentions `ArmsStatus`,
|
||
`RangeFinder`, `Radar`, `Sight`, `Wing`, `NamePlate` or `ResourceTable` —
|
||
checked before writing this. Artefact `../data/hud-config.txt` (697 lines),
|
||
regenerator `tools/re-capture/hud_config.py`.
|
||
|
||
| entry | records |
|
||
|---|---|
|
||
| `0x10b9d584`, `0x4abcfc43` | **16** — `ArmsStatus`, `Map`, `ArmsItem`, `RangeFinder`, `Marker`, `Manuva`, `Number`, `HudResource`, `NamePlate`, `ActiveArm`, `Information`, `Wing`, `ArmsItemFile`, `Radar`, `Speed`, `Sight` |
|
||
| `0x927b29f8`, `0xccb12a6b` | **13** — `ObjectiveMarker_{Acropolis,SubObjective,Guard,WayPoint,Tanker,Target}`, `TutorialMarker_{…}`, `Enumerate_ObjectiveMarkers`, `Parameters` |
|
||
| `0x59ecbedd` | `Face` — 52 positional `pjf001_*.t32` portrait sprites |
|
||
| `0x87fd28c0` | `ResourceTable` — 58 positional entries |
|
||
|
||
Between them these name **419** distinct asset paths. That is the whole flight
|
||
HUD: the arms panel (`ArmsStatus` 16, `ActiveArm` 13, `ArmsItemFile` 59), the
|
||
range finder (10), the target/lock markers and their HP-gauge strips (`Marker`
|
||
27), the manoeuvre gauge (`Manuva` 15), the radar (29), the reticle (`Sight`
|
||
35), the wingman panel (`Wing` 23), nameplates (60), speed (9), and the digit
|
||
strips (`Number`, `%d`-templated: `pghud_speed_num%d.t32`, `pgtimer_num%d.t32`,
|
||
`pglockon_%d.t32`).
|
||
|
||
🔑 The values carry **subdirectory prefixes** the corpus had not seen —
|
||
`ArmsSt\`, `ActvArm\`, `RangeF\`, `Marker\`, `Manuva\`, `Map\`, `Speed\`,
|
||
`Radar\`, `Sight\`, `Wing\`, `Hitmark\`, `Lockon\`, `Info\`.
|
||
|
||
## 🧪 The whole in-game HUD is NOT name-hash addressed
|
||
|
||
Taking the config's **own exact path strings** — no guessing left in the loop:
|
||
|
||
> **419 distinct `.prt` / `.t32` / `.tbl` values; 0 resolve as a pak entry**
|
||
> under 10 prefixes. The four config FILENAMES (`HudResource.tbl`,
|
||
> `HudMarkerResource.tbl`, and their `_S26` overrides) resolve to nothing
|
||
> either.
|
||
|
||
The `.t32` sprites certainly exist — the E2D pak holds **574 T8aD** entries. So
|
||
the 2D pak's contents are simply **not addressed by `name_hash` of the name the
|
||
config uses**, and that closes the previous iteration's puzzle properly: the 28
|
||
"dangling" `.prt` names were never a missing-asset story, they are 28 of a set
|
||
where **none** of the 419 resolves.
|
||
|
||
⚠️ This supersedes the framing in
|
||
[mission-script-manifest](mission-script-manifest.md#-the-other-six-values-do-not-resolve--with-a-working-control):
|
||
the right statement is not "these five/28 are absent" but "**the in-game asset
|
||
namespace is not the archive namespace**".
|
||
|
||
## ✅ `ResourceTable` — a per-stage HUD config table
|
||
|
||
58 positional fields = **29 pairs**, alternating
|
||
`HudResource.tbl` / `HudMarkerResource.tbl`. Exactly one pair differs — index
|
||
**25**, which reads `HudResource_S26.tbl` / `HudMarkerResource_S26.tbl`.
|
||
**Identical in all six language paks.**
|
||
|
||
🟡 The reading: the table is indexed by **stage number − 1**, so 29 entries
|
||
cover S1…S29 (the numbering [that runs to S29 with S17 absent](stage-numbering-and-player-craft.md)),
|
||
and index 25 is **S26 — the one stage with its own HUD configuration**. The
|
||
arithmetic is exact and the `_S26` suffix names the same stage, but nothing here
|
||
proves the indexing, so this is **a reading, not adopted**.
|
||
|
||
## ✅ The objective / tutorial MARKER records
|
||
|
||
`hud-config.md` listed these as "in the artefact but unread". Opened now — and
|
||
they are portable HUD data, 11 records of **12 named fields** each:
|
||
|
||
```
|
||
ObjectiveMarker_Target ColorNormal 0xFFFF0000 Emph1 0xFFFF0000 Emph2 0xFF800000
|
||
Normal pgmark_ob.t32 NormalSub pgmark_ob_s.t32
|
||
Emphasis pgmark_em_ob.prt EmphasisSub pgmark_em_ob_s.prt
|
||
HPGauge 2 HPGaugeSub 0 BlinkCycle 0x800
|
||
RadarCursorType (blank) TutorialTarget No
|
||
```
|
||
|
||
* **Colour is ARGB**, three per marker: `ColorNormal`, `ColorEmphasis1`,
|
||
`ColorEmphasis2`. Objectives are **red** `0xFFFF0000`, guard/waypoint **green**
|
||
`0xFF20FF20`, Acropolis/tanker **cyan** `0xFF00FFFF`, sub-objective **yellow**
|
||
`0xFFFFFF00`, and every `TutorialMarker_*` is **amber** `0xFFFFA010`.
|
||
* Each marker carries a `Normal` sprite and an `Emphasis` part, optionally with
|
||
`…Sub` companions; `HPGauge` is 0 / 1 / 2; `RadarCursorType` is `Circle`
|
||
(Acropolis, tanker), `Rectangle` (guard) or blank; `BlinkCycle` is `0x800`
|
||
on all eleven.
|
||
* `TutorialTarget` is `Yes` on exactly the five `TutorialMarker_*` records and
|
||
`No` on the six `ObjectiveMarker_*` — the two families are otherwise the same
|
||
shape.
|
||
|
||
**`Parameters` (4 fields) binds the roles**:
|
||
|
||
```
|
||
TargetMarker ObjectiveMarker_Target
|
||
HelpMarker ObjectiveMarker_SubObjective
|
||
TutoTargetMarker TutorialMarker_Target
|
||
ReloadDispTime 0.1
|
||
```
|
||
|
||
**`Enumerate_ObjectiveMarkers`** is the 11-name roster of the set — the same
|
||
shape as the `Enumerate_Squadrons` record [unit-group-table](unit-group-table.md)
|
||
uses.
|
||
|
||
⚠️ `pgmark_em_ob_s.prt` here is one of the 28 names
|
||
[archive-naming](archive-naming.md) shows resolving nowhere — consistent with
|
||
the namespace finding, not a missing asset.
|
||
|
||
## 🟡 Not settled
|
||
|
||
* How the 2D pak's 574 T8aD and 130 RATC entries *are* addressed, if not by
|
||
`name_hash` of the config path. That is now the question.
|
||
* What `HudMarkerResource.tbl` is — presumably the 13-record marker entry, but
|
||
the filename does not resolve, so the pairing is by content, not by hash.
|
||
* ~~`Parameters` and `Enumerate_ObjectiveMarkers` unread.~~ **Opened above.**
|
||
|
||
## ✅ The executable's own `PG*` block — `sub_822215D0` (2026-08-27)
|
||
|
||
Found by the base-solver ([[player-tuning-tables]]); reproduce from
|
||
[`../data/name-block-bases.txt`](../data/name-block-bases.txt) (the
|
||
`sub_822215D0` section) against `hud_config.py`'s record dump.
|
||
|
||
✅ **The disc side above is confirmed independently.** Counting `PG*`-prefixed
|
||
field names straight off the paks gives `Sight` 35, `Radar` 29, `Marker` 27,
|
||
`Wing` 23, `Manuva` 15 — **the same numbers this document already states**, and
|
||
`HudResource` 23 `PG*` + `HUD_RES_FONT` = its documented 24. A re-derivation
|
||
that lands on the same counts is the control for what follows.
|
||
|
||
🔑 **What this document did not say: the executable carries its own roster.**
|
||
`sub_822215D0` reads a **205-name** block at base `0x820A0000` — **205/205 are
|
||
`PG*`-prefixed, zero partials** — led by `PGHUD` 77, `PGTARGET` 31, `PGGAUGE` 25,
|
||
`PGMANUVA` 16, `PGMARK` 12, `PGWARNING` 10, `PGMARKTGT` 9.
|
||
|
||
| | |
|
||
|---|---:|
|
||
| distinct `PG*` names **on the disc** (across all 16 records) | **228** |
|
||
| the code block | **205** |
|
||
| in both | **200** |
|
||
| code-only | **5** |
|
||
| disc-only | **28** |
|
||
|
||
`200 + 5 = 205` and `200 + 28 = 228` — the arithmetic closes both ways.
|
||
|
||
⚠️ **Four of the five "code-only" names are printf families whose stem is a disc
|
||
field**: `PGHUD_HIT_NUM_EFF%d`, `PGHUD_HIT_NUM_RED%d`, `PGREMAIN_NUM%d`,
|
||
`PGTIMER_NUM%d` — and `PGHUD_HIT_NUM_EFF`, `PGHUD_HIT_NUM_RED`, `PGREMAIN_NUM`,
|
||
`PGTIMER_NUM` are all four sitting in the disc-only 28. **The code builds indexed
|
||
instance names from a base name the table declares.** Pair them off and the real
|
||
residual is **one** code-only name — `PGMANUVA_EFF0` — and **24** disc-only ones
|
||
(`PGHUD_LOCATOR`, `PGHUD_CAMERA`, `PGHUD_PITCH_*`, `PGHUD_YAW*`, `PGLOCKON`, …),
|
||
i.e. elements the table names that this particular function never mentions.
|
||
|
||
🟡 What the block is *for* is not settled: whether it is a lookup table, a
|
||
registration order, or a paint list. The function was not read.
|