From cb7b0aa4616861d671d5618b817d079970976ae4 Mon Sep 17 00:00:00 2001 From: Sylpheed RE agent Date: Tue, 25 Aug 2026 09:34:58 +0000 Subject: [PATCH] re: S18-S23 stage records were never missing; only S17 is absent The 'S17-S23 have no stage record' gap was an artefact of enumerating by the literal 'Stage_S'. Tutorial records omit it -- they name no per-stage .xpr and pull AIParams/weapons/strings/subobjectives/nameplate/collision from a shared _Tutorial set -- so all six were skipped. stagetbl.py Stage_S18 returns a full six-record definition and always would have. Counting distinct *_S names across all 1119 decompressed entries: UnitGroup and Route cover 28 stages (S01-S16, S18-S23, S24-S29); Stage literal and AIParams cover 22; SUBObjectiveSettings 16 (story only). S17 appears in none -- it is not a stage that lost its data, it does not exist. Tutorial records carry the same Phase_1/2/3 structure as story stages, so the tutorial is not a special mission type at the data layer. Refuted en route: GP_TUTORIAL.pak does not hold the config -- 2 RATC entries, zero IDXD, like GP_CHALLENGE.pak. --- docs/re/data/stage-tutorial-records.txt | 226 +++++++++++++++++++ docs/re/structures/stage-definition-table.md | 51 ++++- docs/re/structures/stage-mission-tables.md | 5 + 3 files changed, 280 insertions(+), 2 deletions(-) create mode 100644 docs/re/data/stage-tutorial-records.txt diff --git a/docs/re/data/stage-tutorial-records.txt b/docs/re/data/stage-tutorial-records.txt new file mode 100644 index 0000000..c0ee5d3 --- /dev/null +++ b/docs/re/data/stage-tutorial-records.txt @@ -0,0 +1,226 @@ +########## S18 +=== Stage_S18 definition record (6 records) === +-- 'StageResource' (15 fields) + 087ca0d2 EnumerateLocalString = EnumLocalString_Tutorial.tbl + 106df3ec EnumerateWeapon = EnumWeapon_Tutorial.tbl + 114eccbb CollisionMeshes = CollisionSet_Tutorial.bin + 2cffd1e7 EnumerateNullFrame = Route_S18.tbl + 33d9c14c EnumerateCharacter = + 46f5c611 EnumerateUnit = EnumUnit_S18.tbl + 550ade77 EnumerateFormation = FormationSet_S18.tbl + 6d8b50c4 BackGroundID = Original + 77dd6f98 NamePlate = nameplate_Tutorial.tbl + 8b001bd6 EnumerateSubobjective = SUBObjectiveSettings_Tutorial.tbl + 8cbff946 BackGroundPackage = + 945c9dcb EnumerateAIParams = AIParams_Tutorial.tbl + e8ac2b0d StageResourcePackage = + f19c4815 MessageSet = StageMessageSet_Tutorial.tbl + f37fdac5 EnumerateSquadron = UnitGroup_S18.tbl +-- 'LodResource' (1 fields) + 9cbba07e LodEnumTable = game:\hidden\DefTables.pak+EnumLODSet_Tutorial.tbl +-- 'Phase_1' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'Phase_2' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'Phase_3' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'MotionResource' (1 fields) + f314d3e4 MotionEnumTable = game:\hidden\DefTables.pak+EnumGameModel_Tutorial.tbl +########## S19 +=== Stage_S19 definition record (6 records) === +-- 'StageResource' (15 fields) + 087ca0d2 EnumerateLocalString = EnumLocalString_Tutorial.tbl + 106df3ec EnumerateWeapon = EnumWeapon_Tutorial.tbl + 114eccbb CollisionMeshes = CollisionSet_Tutorial.bin + 2cffd1e7 EnumerateNullFrame = Route_S19.tbl + 33d9c14c EnumerateCharacter = + 46f5c611 EnumerateUnit = EnumUnit_S19.tbl + 550ade77 EnumerateFormation = FormationSet_S19.tbl + 6d8b50c4 BackGroundID = Original + 77dd6f98 NamePlate = nameplate_Tutorial.tbl + 8b001bd6 EnumerateSubobjective = SUBObjectiveSettings_Tutorial.tbl + 8cbff946 BackGroundPackage = + 945c9dcb EnumerateAIParams = AIParams_Tutorial.tbl + e8ac2b0d StageResourcePackage = + f19c4815 MessageSet = StageMessageSet_Tutorial.tbl + f37fdac5 EnumerateSquadron = UnitGroup_S19.tbl +-- 'LodResource' (1 fields) + 9cbba07e LodEnumTable = game:\hidden\DefTables.pak+EnumLODSet_Tutorial.tbl +-- 'Phase_1' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'Phase_2' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'Phase_3' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'MotionResource' (1 fields) + f314d3e4 MotionEnumTable = game:\hidden\DefTables.pak+EnumGameModel_Tutorial.tbl +########## S20 +=== Stage_S20 definition record (6 records) === +-- 'StageResource' (15 fields) + 087ca0d2 EnumerateLocalString = EnumLocalString_Tutorial.tbl + 106df3ec EnumerateWeapon = EnumWeapon_Tutorial.tbl + 114eccbb CollisionMeshes = CollisionSet_Tutorial.bin + 2cffd1e7 EnumerateNullFrame = Route_S20.tbl + 33d9c14c EnumerateCharacter = + 46f5c611 EnumerateUnit = EnumUnit_S20.tbl + 550ade77 EnumerateFormation = FormationSet_S20.tbl + 6d8b50c4 BackGroundID = Original + 77dd6f98 NamePlate = nameplate_Tutorial.tbl + 8b001bd6 EnumerateSubobjective = SUBObjectiveSettings_Tutorial.tbl + 8cbff946 BackGroundPackage = + 945c9dcb EnumerateAIParams = AIParams_Tutorial.tbl + e8ac2b0d StageResourcePackage = + f19c4815 MessageSet = StageMessageSet_Tutorial.tbl + f37fdac5 EnumerateSquadron = UnitGroup_S20.tbl +-- 'LodResource' (1 fields) + 9cbba07e LodEnumTable = game:\hidden\DefTables.pak+EnumLODSet_Tutorial.tbl +-- 'Phase_1' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'Phase_2' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'Phase_3' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'MotionResource' (1 fields) + f314d3e4 MotionEnumTable = game:\hidden\DefTables.pak+EnumGameModel_Tutorial.tbl +########## S21 +=== Stage_S21 definition record (6 records) === +-- 'StageResource' (15 fields) + 087ca0d2 EnumerateLocalString = EnumLocalString_Tutorial.tbl + 106df3ec EnumerateWeapon = EnumWeapon_Tutorial.tbl + 114eccbb CollisionMeshes = CollisionSet_Tutorial.bin + 2cffd1e7 EnumerateNullFrame = Route_S21.tbl + 33d9c14c EnumerateCharacter = + 46f5c611 EnumerateUnit = EnumUnit_S21.tbl + 550ade77 EnumerateFormation = FormationSet_S21.tbl + 6d8b50c4 BackGroundID = Original + 77dd6f98 NamePlate = nameplate_Tutorial.tbl + 8b001bd6 EnumerateSubobjective = SUBObjectiveSettings_Tutorial.tbl + 8cbff946 BackGroundPackage = + 945c9dcb EnumerateAIParams = AIParams_Tutorial.tbl + e8ac2b0d StageResourcePackage = + f19c4815 MessageSet = StageMessageSet_Tutorial.tbl + f37fdac5 EnumerateSquadron = UnitGroup_S21.tbl +-- 'LodResource' (1 fields) + 9cbba07e LodEnumTable = game:\hidden\DefTables.pak+EnumLODSet_Tutorial.tbl +-- 'Phase_1' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'Phase_2' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'Phase_3' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'MotionResource' (1 fields) + f314d3e4 MotionEnumTable = game:\hidden\DefTables.pak+EnumGameModel_Tutorial.tbl +########## S22 +=== Stage_S22 definition record (6 records) === +-- 'StageResource' (19 fields) + 087ca0d2 EnumerateLocalString = EnumLocalString_Tutorial.tbl + 106df3ec EnumerateWeapon = EnumWeapon_Tutorial.tbl + 114eccbb CollisionMeshes = CollisionSet_Tutorial.bin + 2cffd1e7 EnumerateNullFrame = Route_S22.tbl + 33d9c14c EnumerateCharacter = + 46f5c611 EnumerateUnit = EnumUnit_S22.tbl + 550ade77 EnumerateFormation = FormationSet_S22.tbl + 6d8b50c4 BackGroundID = Original + 764727ae WingmanIconID_0 = + 774727af WingmanIconID_1 = PGHUD_WING2 + 77dd6f98 NamePlate = nameplate_Tutorial.tbl + 784727b0 WingmanIconID_2 = PGHUD_WING3 + 794727b1 WingmanIconID_3 = PGHUD_WING4 + 8b001bd6 EnumerateSubobjective = SUBObjectiveSettings_Tutorial.tbl + 8cbff946 BackGroundPackage = + 945c9dcb EnumerateAIParams = AIParams_Tutorial.tbl + e8ac2b0d StageResourcePackage = + f19c4815 MessageSet = StageMessageSet_Tutorial.tbl + f37fdac5 EnumerateSquadron = UnitGroup_S22.tbl +-- 'LodResource' (1 fields) + 9cbba07e LodEnumTable = game:\hidden\DefTables.pak+EnumLODSet_Tutorial.tbl +-- 'Phase_1' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'Phase_2' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'Phase_3' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'MotionResource' (1 fields) + f314d3e4 MotionEnumTable = game:\hidden\DefTables.pak+EnumGameModel_Tutorial.tbl +########## S23 +=== Stage_S23 definition record (6 records) === +-- 'StageResource' (15 fields) + 087ca0d2 EnumerateLocalString = EnumLocalString_Tutorial.tbl + 106df3ec EnumerateWeapon = EnumWeapon_Tutorial.tbl + 114eccbb CollisionMeshes = CollisionSet_Tutorial.bin + 2cffd1e7 EnumerateNullFrame = Route_S23.tbl + 33d9c14c EnumerateCharacter = + 46f5c611 EnumerateUnit = EnumUnit_S23.tbl + 550ade77 EnumerateFormation = FormationSet_S23.tbl + 6d8b50c4 BackGroundID = Original + 77dd6f98 NamePlate = nameplate_Tutorial.tbl + 8b001bd6 EnumerateSubobjective = SUBObjectiveSettings_Tutorial.tbl + 8cbff946 BackGroundPackage = + 945c9dcb EnumerateAIParams = AIParams_Tutorial.tbl + e8ac2b0d StageResourcePackage = + f19c4815 MessageSet = StageMessageSet_Tutorial.tbl + f37fdac5 EnumerateSquadron = UnitGroup_S23.tbl +-- 'LodResource' (1 fields) + 9cbba07e LodEnumTable = game:\hidden\DefTables.pak+EnumLODSet_Tutorial.tbl +-- 'Phase_1' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'Phase_2' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'Phase_3' (4 fields) + 44c33b91 AsteroidDefinition = + abf237d1 MapPath = mapmesh_box_500km.rgn + abf6366e MapMesh = mapmesh_box_500km.col + d5a83345 BackgroundResourceID = +-- 'MotionResource' (1 fields) + f314d3e4 MotionEnumTable = game:\hidden\DefTables.pak+EnumGameModel_Tutorial.tbl diff --git a/docs/re/structures/stage-definition-table.md b/docs/re/structures/stage-definition-table.md index c9a6c7c..1e0de93 100644 --- a/docs/re/structures/stage-definition-table.md +++ b/docs/re/structures/stage-definition-table.md @@ -48,8 +48,55 @@ AsteroidDefinition = test_s8p1_asteroid.tbl | S10–S16 | `UnitGroup_S10..S16.tbl` | `0x8f9efd2f` … `0x95c3f32f` | | S24–S29 | `UnitGroup_S24..S29.tbl` | `0x94e0c625` … `0x99ff9325` | -**Not settled:** S17–S23 have no stage record in `GP_MAIN_GAME_E.pak`. They may -live in another pak, or be named differently. Not yet searched. +~~**Not settled:** S17–S23 have no stage record in `GP_MAIN_GAME_E.pak`.~~ +**Searched 2026-08-25 — half of that was wrong.** See below. + +## ✅ S18–S23 DO have stage records; only S17 is genuinely absent + +The gap was an artefact of how the table above was built, not a fact about the +disc. `stagetbl.py Stage_S18` returns a full six-record definition and always +would have — it was simply never run. + +What made them look missing: the tutorial records **do not contain the string +`Stage_S18`**, because unlike a story stage they name no per-stage 3D scene +(`game:\hidden\Resource3D\Stage_S02.xpr` has no tutorial counterpart) and they +pull most tables from a **shared `_Tutorial` set** instead of per-stage ones. An +enumeration keyed on the `Stage_S` literal therefore skipped all six. + +Counting distinct `*_S` table names across every decompressed entry of +`GP_MAIN_GAME_E.pak` (1119 entries) gives the real split: + +| family | stages | count | +|---|---|---| +| `UnitGroup_S.tbl` | S01–S16, **S18–S23**, S24–S29 | 28 | +| `Route_S.tbl` | same | 28 | +| `Stage_S` *(literal)* | S01–S16, S24–S29 | 22 | +| `AIParams_S.tbl` | S01–S16, S24–S29 | 22 | +| `SUBObjectiveSettings_S.tbl` | S01–S16 only | 16 | + +**S17 appears in none of the five** — not as a roster, route, record or scene. It +is not a stage that lost its data; it does not exist. That matches the family +split in [challenge-mission-gate](../challenge-mission-gate.md): story S01–S16, +tutorial S18–S23, challenge S24–S29, with 17 simply unused. + +Per-stage vs shared, from the six records (`data/stage-tutorial-records.txt`): + +* **per-stage**: `Route_S.tbl`, `EnumUnit_S.tbl`, `FormationSet_S.tbl`, + `UnitGroup_S.tbl` +* **shared across all six**: `AIParams_Tutorial.tbl`, `EnumWeapon_Tutorial.tbl`, + `EnumLocalString_Tutorial.tbl`, `SUBObjectiveSettings_Tutorial.tbl`, + `StageMessageSet_Tutorial.tbl`, `nameplate_Tutorial.tbl`, + `CollisionSet_Tutorial.bin`, `EnumGameModel_Tutorial.tbl`, + `EnumLODSet_Tutorial.tbl` +* `BackGroundID = Original`, `BackGroundPackage` empty, `EnumerateCharacter` empty + +They carry the same **`Phase_1`/`Phase_2`/`Phase_3`** structure as a story stage, +so the tutorial is not a special-cased mission type at the data layer. + +🔴 **Refuted en route:** `GP_TUTORIAL.pak` holds the tutorial stage config. It does +not — it has **2 entries, both RATC**, zero IDXD objects, exactly like +`GP_CHALLENGE.pak`. It is the UI screen; the missions live in +`GP_MAIN_GAME_E.pak` with everything else. ## ✅ `MapPath` / `MapMesh` name the MiscBin objects diff --git a/docs/re/structures/stage-mission-tables.md b/docs/re/structures/stage-mission-tables.md index 1db9810..1612ddc 100644 --- a/docs/re/structures/stage-mission-tables.md +++ b/docs/re/structures/stage-mission-tables.md @@ -139,6 +139,11 @@ port directly. * The route-name kind letters `F`, `S`, `A`, `M`, `B`. * What activates or completes a sub-objective. * `StageMessageSet_S.tbl` does not resolve in `GP_MAIN_GAME_E.pak`. +* ✅ **S18–S23 stage records found (2026-08-25)** — they were never missing; the + tutorial records omit the `Stage_S` literal (no per-stage `.xpr`, shared + `_Tutorial` tables) so a literal-keyed enumeration skipped them. **S17 alone is + genuinely absent** from all five table families. See + [stage-definition-table](stage-definition-table.md). * The `UnitGroup` record key and its member field `n` remain ❔ from [unit-group-table.md](unit-group-table.md). `n` is now a little more suspicious: routes are per-squadron, so `n` is unlikely to be a spawn count.