result-screens.md left this explicitly open: "the selection has not been shown".
It is shown now. Both screens that reference EX_ names carry the same
five-instruction idiom immediately before the choice - sub_822814D8 at 0x822815b4
and sub_8227A3A0 at 0x8227a408:
lwz r11, 4(rX) the owning object
lwz r11, 184(r11) a mode word at +184
addi r11, r11, -3
cntlzw r11, r11
rlwinm r11, r11, 27, 31, 31 r11 = 1 iff [+184] == 3
cmpli cr6, 0, r11, 0x0
bc 12, 4*cr6+eq, <plain> not 3 -> STAGE_RESULT / OVERVIEW
else -> EX_STAGE_RESULT / EX_OVERVIEW
cntlzw of zero is 32, and rotating left 27 lifts bit 5 into bit 31, so the
sequence is a branchless equals-3 test. The equal-to-zero branch takes the plain
name, so EX_ is chosen exactly when the word is 3.
A partition over the three key-list loaders the corpus already names:
loads +184 does not
references EX_ names 2 0
does not 0 1
sub_822814D8 and sub_8227A3A0 both load it; sub_82286BC8, which references no EX_
name, has no +184 access at all. Both off-diagonal cells are empty.
3 is the game's own EXTRA. challenge-mission-gate already established the
vocabulary for this constant at a three-way switch: == 3 is EXTRA, == 5 or 6 is
CHALLENGE, otherwise FILE. So the prefix reads literally - EX_ is the EXTRA
variant.
That REFINES the doc's tentative reading rather than confirming it. The section
proposed "EX_ = the challenge-mission debriefing" by analogy with _EXn on asset
names; the measured constant is EXTRA, which in the game's own three-way
vocabulary is a DIFFERENT kind from CHALLENGE (5/6).
Boundary of what was measured: the EXTRA = 3 constant is established at +144 of
the stage-loader class, while the word tested here is at +184 of [object + 4].
Same constant and the same EX/EXTRA naming, but two different offsets in what may
be two different objects - that the two fields are the same field is NOT shown,
only that both compare a mode word against 3.
All seventeen artefacts byte-identical.
134 lines
6.6 KiB
Markdown
134 lines
6.6 KiB
Markdown
# ✅ The debriefing and pilot-record screens — `STAGE_RESULT`, `OVERVIEW`, `EX_OVERVIEW`
|
|
|
|
- **Where:** `tables.pak` (the menu config pak), records `STAGE_RESULT`, `OVERVIEW`,
|
|
`EX_OVERVIEW`; key lists compiled into the executable at `sub_822814D8` and
|
|
`sub_8227A3A0` (found by the base-solver, [[player-tuning-tables]]).
|
|
- **Related:** [[mission-scoring]] owns the *rules* (`Score_*` in the stage
|
|
settings); this is the *readout*. [[savegame-format]] documents the same
|
|
compiled-key-list shape for the LOAD/SAVE screen.
|
|
|
|
## The shape was already known — for other screens
|
|
|
|
[[savegame-format]] establishes it: *"the LOAD/SAVE screen's config key list is
|
|
compiled into the executable, as a pointer array of key strings — the same shape
|
|
as the Arsenal's (whose keys sit a few hundred bytes earlier and match the pak
|
|
record exactly)"*, run starting `0x820A0074`. **`sub_82286BC8`'s 18-name block is
|
|
exactly that list** — 17 of its 18 are a `tables.pak` field or record name, so it
|
|
is the documented save-screen list and nothing new. Its lone residual is
|
|
**`PLAYER_AMMO_LESS_10`**, which is not a `tables.pak` name at all.
|
|
|
|
## ✅ Two more screens, and the key lists match their records exactly
|
|
|
|
| block | names | all present in `tables.pak`? |
|
|
|---|---:|---|
|
|
| `sub_822814D8` | 24 | **24 / 24** |
|
|
| `sub_8227A3A0` | 21 | **21 / 21** |
|
|
|
|
And the arithmetic closes against the records themselves:
|
|
|
|
* **`sub_822814D8` = the debriefing screen.** 24 names = 2 screen ids
|
|
(`STAGE_RESULT`, `EX_STAGE_RESULT`) + **21 `stage_*` fields** + one sound cue
|
|
(`SE_BOSS_CORE_CHARGE`). The `tables.pak` record `STAGE_RESULT` has **exactly
|
|
21 fields** (2 objects, both 21).
|
|
* **`sub_8227A3A0` = the pilot record / career screen.** 21 names = 5 screen ids
|
|
(`LAST_RESULT`, `EX_BASE`, `EX_MAIN`, `EX_OVERVIEW`, `OVERVIEW`) + **7
|
|
`ex_overview_*`** + **9 `overview_*`**. The records `EX_OVERVIEW` and
|
|
`OVERVIEW` have **exactly 7 and 9 fields** (2 objects each).
|
|
|
|
`2+21+1 = 24` and `5+7+9 = 21`, with 21/7/9 measured independently off the pak.
|
|
|
|
### The debriefing readout, in full
|
|
|
|
```
|
|
stage_num_shoot_down_aircrafts stage_points_shoot_down_aircrafts
|
|
stage_num_shoot_down_ships stage_points_shoot_down_ships
|
|
stage_points_shoot_down_others
|
|
stage_weight_shoot_down
|
|
stage_num_main_objectives stage_points_main_objectives
|
|
stage_num_sub_objectives stage_points_sub_objectives
|
|
stage_clear_time stage_points_clear_time
|
|
stage_shoot_down_ratio stage_points_shoot_down_ratio
|
|
stage_damages_friendly_ships stage_points_damages_friendly_ships
|
|
stage_damages_wingman stage_points_damages_wingman
|
|
stage_points_friendly_fire
|
|
stage_total_points stage_rank
|
|
```
|
|
|
|
🔑 **Nine `num`/`points` pairs plus three points-only lines** — the screen shows
|
|
a raw count *and* its score contribution for kills by class, objectives, time,
|
|
ratio and both damage categories; `friendly_fire`, `shoot_down_others` and
|
|
`weight` have no counter column. That is the same partition
|
|
[[mission-scoring]] measures on the settings side.
|
|
|
|
### The career readout
|
|
|
|
`overview_points`, `_total_play_time`, `_clear_stages`, `_retry_times`,
|
|
`_shoot_down_aircrafts`, `_shoot_down_ships`, `_shoot_down_weight` — seven, and
|
|
`OVERVIEW` adds **`overview_rank`** and **`overview_medals`**. The `EX_` twin has
|
|
the seven and neither of the two, which is what makes `EX_` the reduced variant
|
|
rather than a different screen.
|
|
|
|
🟡 Not settled: what `EX_` means (a second profile? the online/leaderboard
|
|
variant?) — **but see
|
|
[stage-numbering-and-player-craft](stage-numbering-and-player-craft.md):
|
|
`_EXn` on an asset name is measured to mean "the n-th challenge mission", which
|
|
makes "`EX_` = the challenge-mission debriefing" a consistent reading of why
|
|
this twin drops `overview_rank` and `overview_medals`. Not adopted — the
|
|
selection has not been shown** — `EX_BASE`, `EX_MAIN`, `EX_STAGE_RESULT` and `EX_FONT` are keys with
|
|
**no record of that name**, so the prefix is a screen-id convention, not a table.
|
|
And `PLAYER_AMMO_LESS_10` is unexplained.
|
|
|
|
**Reproduce:** parse `tables.pak` with `tools/re-capture/unitgroup.py` and count
|
|
the fields of the three records; take the key lists from the `sub_822814D8` /
|
|
`sub_8227A3A0` / `sub_82286BC8` sections of [`../data/name-block-bases.txt`](../data/name-block-bases.txt).
|
|
|
|
## ✅ The `EX_` selection, shown at last — a mode word tested against 3
|
|
|
|
The section above left this open: "**the selection has not been shown**". It is
|
|
shown now. Both screens that reference `EX_` names carry the *same five-instruction
|
|
idiom* immediately before the choice — `sub_822814D8` at `0x822815b4` and
|
|
`sub_8227A3A0` at `0x8227a408`:
|
|
|
|
```asm
|
|
lwz r11, 4(rX) ; the owning object
|
|
lwz r11, 184(r11) ; a mode word at +184
|
|
addi r11, r11, -3
|
|
cntlzw r11, r11
|
|
rlwinm r11, r11, 27, 31, 31 ; r11 = 1 iff [+184] == 3
|
|
cmpli cr6, 0, r11, 0x0
|
|
bc 12, 4*cr6+eq, <plain> ; not 3 -> STAGE_RESULT / OVERVIEW
|
|
; else -> EX_STAGE_RESULT / EX_OVERVIEW
|
|
```
|
|
|
|
`cntlzw` of zero is 32; rotating left 27 lifts bit 5 into bit 31, so the sequence
|
|
is a branchless **"equals 3"** test. The equal-to-zero branch takes the *plain*
|
|
name, so **`EX_` is chosen exactly when the word is 3**.
|
|
|
|
A small partition over the three key-list loaders the corpus already names:
|
|
|
|
| | loads `+184` | does not |
|
|
|---|---|---|
|
|
| **references `EX_` names** | **2** | 0 |
|
|
| **does not** | 0 | **1** |
|
|
|
|
`sub_822814D8` and `sub_8227A3A0` both load it; `sub_82286BC8`, which references
|
|
no `EX_` name, has no `+184` access at all. Both off-diagonal cells are empty.
|
|
|
|
### 🔑 3 is the game's own `EXTRA` — and that is *not* `CHALLENGE`
|
|
|
|
[[challenge-mission-gate]] already established the vocabulary for this constant
|
|
at a three-way switch: `== 3` → **`EXTRA`**, `== 5 or 6` → **`CHALLENGE`**,
|
|
otherwise `FILE`. So the prefix reads literally: **`EX_` is the `EXTRA` variant**.
|
|
|
|
⚠️ **This refines the tentative reading above rather than confirming it.** That
|
|
section proposed "`EX_` = the challenge-mission debriefing" by analogy with
|
|
`_EXn` on asset names. The measured constant is `EXTRA`, which in the game's own
|
|
three-way vocabulary is a *different* kind from `CHALLENGE` (5/6). `EX_` tracks
|
|
`EXTRA` specifically.
|
|
|
|
⚠️ **The boundary of what was measured:** the `EXTRA = 3` constant is established
|
|
at **`+144`** of the stage-loader class, while the word tested here is at
|
|
**`+184`** of `[object + 4]`. Same constant, same `EX`/`EXTRA` naming, two
|
|
different offsets in what may be two different objects — **that the two fields
|
|
are the same field is not shown**, only that both compare a mode word against 3.
|