re: STAGENN_UNIT_MAX holds two per-stage caps, PLANE and VESSEL
Reading sub_82261F70 past the table lookup finishes the mechanism the stage index feeds: the section name is built from the 0-based stage index, looked up, and two ints land in the phase -- [phase+356] = PLANE (default 200) [phase+360] = VESSEL (default 20) with the defaults taken when a stage has no entry. Key strings are 0x820A8B14 "PLANE" and 0x820A8B1C "VESSEL"; section and both keys are the game's own names. Surrounding reads (GP_SCRIPT, SCRIPTS, Resource2D, TABLE) plus the pak census's 40 <?xm entries make this an XML config reader. Register discipline mattered twice: in sub_82261F70 r21 is the phase and r31 is the STACK frame, and 0x82273400 lwz r11, 360(r11) in the built-in switch is a vtable slot 90 call, not a phase read. Not settled: the values (a crude zlib scan found no UNIT_MAX, but it did not use the corpus's pak reader, so that is not evidence of absence), and no consumer of the two fields was identified. Docs only; artefacts byte-identical.
This commit is contained in:
@@ -290,6 +290,51 @@ the built-in switch looks like a read of this field. It is not: `r11` had just
|
||||
been loaded from `0(r31)`, so it is the **vptr** — that instruction is a virtual
|
||||
call to **slot 38**. Offset 152 recurs; the base register decides.
|
||||
|
||||
## ✅ (2026-08-27) What `STAGENN_UNIT_MAX` is: two per-stage unit caps, `PLANE` and `VESSEL`
|
||||
|
||||
The lookup in `sub_82261F70` continues straight past the table read. `r21` is the
|
||||
phase there; `r31` is the **stack frame** (`addi r4, r31, 452`, `lwz r11, 376(r31)`
|
||||
— easy to misread as phase fields).
|
||||
|
||||
```
|
||||
82262308 bl 0x824480D0 ; open the config node -> [r31+84]
|
||||
8226230C lwz r11, 152(r21) ; the 0-based stage index
|
||||
8226231C lwzx r4, r11, r10 ; "STAGE(N+1)_UNIT_MAX"
|
||||
82262320 bl 0x82448AA0 ; find that section
|
||||
82262328 bc 4, eq, 0x82262340 ; found -> read two keys
|
||||
; NOT found — defaults:
|
||||
82262334 stw r11(=20), 360(r21)
|
||||
82262338 stw r10(=200), 356(r21)
|
||||
; found:
|
||||
82262348 addi r4, r11, -29932 ; 0x820A8B14 = "PLANE"
|
||||
82262360 stw r11, 356(r21)
|
||||
8226235C addi r4, r10, -29924 ; 0x820A8B1C = "VESSEL"
|
||||
82262368 stw r3, 360(r21)
|
||||
```
|
||||
|
||||
| phase field | config key | default |
|
||||
|---|---|---|
|
||||
| `[phase+356]` | **`PLANE`** | **200** |
|
||||
| `[phase+360]` | **`VESSEL`** | **20** |
|
||||
|
||||
So the section is a per-stage pair of **unit caps** — planes (fighters) and
|
||||
vessels (capital ships) — with the section name built from the stage index and
|
||||
the whole thing falling back to 200/20 when a stage has no entry. All three names
|
||||
are the game's own.
|
||||
|
||||
The surrounding reads name the config itself: `GP_SCRIPT` (`0x820A8244`),
|
||||
`SCRIPTS`, `Resource2D`, `TABLE`. The pak census counts **40 `<?xm` entries**, so
|
||||
this is an XML config reader (`sub_824480D0` open, `sub_82448AA0` find-section,
|
||||
`sub_824482D0` read-int, `sub_82448C50` / `sub_824490E0` others).
|
||||
|
||||
🟡 **The values themselves are not confirmed from the data side.** A crude
|
||||
`Z1`+zlib scan over `dat/*.pak` found no `UNIT_MAX` — but that scan did not use
|
||||
the corpus's own pak reader (`unitgroup.py`), so it is **not** evidence of
|
||||
absence. 🟡 No reader of `[phase+356]` / `[phase+360]` was identified: the
|
||||
offsets recur, and the one ISL-region hit that looked promising
|
||||
(`0x82273400 lwz r11, 360(r11)`) is a **vtable slot 90 call** — `r11` is the
|
||||
vptr — which is built-in 123, consistent with the known mapping.
|
||||
|
||||
🟡 Its neighbours belong to the same cluster: `builtin103` reads
|
||||
`[phase+10156]` and `[phase+10152]` (9 and 7 writers), and a sibling vtable stub
|
||||
clears `[phase+10152]`. The shape is an engine→script status trio, but that is a
|
||||
|
||||
Reference in New Issue
Block a user