diff --git a/docs/port/HANDOFF.md b/docs/port/HANDOFF.md index 739b12da..3a1324ab 100644 --- a/docs/port/HANDOFF.md +++ b/docs/port/HANDOFF.md @@ -34,7 +34,7 @@ authored version can be deleted. | Q5 | navigation semantics | ✅ answered | **measured**: initial focus varies boot to boot (2× `TUTORIAL`, 1× `NEW GAME`); ⬆⬇ one step, **wraps both ends**; ⬅➡ do nothing; Ⓑ returns to the parent **with focus restored**; Ⓑ on the main menu → title; Ⓑ on the title → nothing — [`menu-navigation-semantics.md`](../re/menu-navigation-semantics.md) | | Q6 | boot sequence + what drives it | 🟡 partial | order observed and the attract cycle timed: ~8–10 s idle → fade to black → **`ADV.wmv` in full (137 s)** → title again. The **movie manifest** supplies the boot-side asset order (slot key = role); the code that decides to advance is still not decoded | | Q7 | transitions | ✅ answered | a **fade through black**, drawn by the screen's own last-painting `.prm` quad. Fade-in ramp is **decoded** from its keyframes; the ~0.4 s fade-out is **measured** (not in the file) — [`screen-transitions.md`](../re/screen-transitions.md) | -| Q8 | menu audio bindings | ❔ open | cue table complete, event binding is not | +| Q8 | menu audio bindings | 🟡 mostly answered | the **UI cue vocabulary is decoded** (`SE_UI_CURSOR`/`DECIDE`/`CANSEL`/`IMPOSI`, all in `Static.slb` per `BANK_SE`); the event binding is a **name match**, and the SE audio is **not extractable yet** — [`menu-audio-cues.md`](../re/menu-audio-cues.md) | | Q9 | video binding + playback rules | ✅ answered | **decoded** from the movie manifest: `ADVERTISE_MOVIE`→`ADV.wmv` (boot intro *and* attract are one asset), `MS00A`→`S00A.wmv` is the new-game intro, `STAFF_ROLL`→the credits reel. 🟡 skippability unsettled — [`movie-binding.md`](../re/movie-binding.md) | | Q10 | music-bank sub-wave roles (intro+loop?) | ✅ answered | **two stems of one performance, played together** — sample-synchronous, equal duration, 32/32 banks. **Concatenating is wrong.** Not a seamless loop either — [`structures/bgm-two-stems.md`](../re/structures/bgm-two-stems.md) | | S1 | Ready Room go/no-go | ✅ **no-go** | it is 2D and enumerates fine (60 builds), but `GP_READY_ROOM.pak` holds **briefing/tactical-map** content, not the six-button Ready Room menu — [`ready-room-probe.md`](../re/ready-room-probe.md) | @@ -139,6 +139,22 @@ authored version can be deleted. every time, while the boot harness deliberately never taps during a movie because it breaks the title. Do not rely on either until it is retested. +* **The menu's sound events are named on the disc.** `tables.pak`'s `SOUNDS` + record carries 322 `SE_*` cues, and the low block is the UI vocabulary — named + after the *event*: `SE_UI_CURSOR` (2), `SE_UI_DECIDE` (3), `SE_UI_CANSEL` (4), + `SE_UI_IMPOSI` (5, the error), `SE_UI_SUB_WIN_OPN`/`_CLS` (8/9), + `SE_UI_SPLASH_IN`/`_OUT` (12/13). ✅ decoded, full list in + [`data/se-ui-cues.txt`](../re/data/se-ui-cues.txt). They all live in **one** + bank — `BANK_SE` is a single field naming `Static.slb`, and 0 of the 322 has + its own `FILES` entry. + 🟡 **Which event fires which cue is a name match**, not a measurement — strong, + because these are the authors' own event names, but nobody has watched the game + emit cue 2 on a d-pad press. The port is authoring it. + ❔ **The SE audio cannot be exported yet.** `Static.slb`'s 8 353 472 readable + bytes contain **0 `RIFF`, 0 `seek`, 0 `WAVE`** — the boundary marker that works + for all 7 620 other banks is simply absent, so an individual cue's wave is not + locatable. Next step is `Pj_Silph.xgs` (in `sound.pak`, TOC 9454). + * **The GamePart id table** — 29 entries at `.rdata 0x820A1630`, confirmed by the executable's own registration strings. ✅ This is the screen vocabulary; which button reaches which entry is Q4 and is *not* part of it. diff --git a/docs/re/INDEX.md b/docs/re/INDEX.md index 0ee65063..18ce09b9 100644 --- a/docs/re/INDEX.md +++ b/docs/re/INDEX.md @@ -152,6 +152,7 @@ files, which is how the same ground got covered twice. | [`ui-quad-class-foothold.md`](ui-quad-class-foothold.md) | The guest's UI quad class — a foothold found from the capture's vertex layout | 🟡 PROBABLE for the identification below (it is a static read, but | | [`menu-navigation-semantics.md`](menu-navigation-semantics.md) | The title menu — how it moves, and where each button goes | ✅ measured: wraps both ends, Ⓑ restores focus, ⬅➡ inert; 4 of 5 destinations driven. 🟡 GamePart id is a name match, ❔ `NEW GAME` untested | | [`screen-transitions.md`](screen-transitions.md) | Between two screens — a fade through black, and where its timing lives | ✅ the fade quad's keyframe group is decoded (disc-wide: per-pak all-or-nothing; `GP_TITLE` = the 6 screens, not the 6 overlays); the ~0.4 s fade-OUT is measured, not on the disc | +| [`menu-audio-cues.md`](menu-audio-cues.md) | Menu audio — the event vocabulary is on the disc, the binding is not | ✅ `SE_UI_*` cue names/ids decoded and `BANK_SE`→`Static.slb` (0/322 in FILES); 🟡 event binding is a name match; ❔ `Static.slb` has no wave boundaries, so SE audio is not extractable | | [`movie-binding.md`](movie-binding.md) | Which movie plays where — boot intro, attract loop, new-game intro | ✅ decoded from the movie manifest (`ADVERTISE_MOVIE`→`ADV.wmv`, `MS00A`→`S00A.wmv`); attract identity confirmed independently by frame matching; 🟡 skippability unsettled | | [`ready-room-probe.md`](ready-room-probe.md) | S1 — the Ready Room probe: no-go, and not for the reason expected | ✅ it is 2D and enumerates (60 builds), but the pak is briefing/tactical-map content; and `kind == 0x3002` finds 0 buttons there | | [`ui-title-build-map.md`](ui-title-build-map.md) | Which `GP_TITLE` build is which screen state | ✅ CONFIRMED for title / `PRESS Ⓐ` / main menu / `EXTRAS` against live captures; the archive is 8 screens × EN/JP, and "6/8/9 are submenus" is withdrawn | diff --git a/docs/re/REFUTED.md b/docs/re/REFUTED.md index bf8b2f7f..efe2bada 100644 --- a/docs/re/REFUTED.md +++ b/docs/re/REFUTED.md @@ -139,6 +139,12 @@ neighbourhood, not just the line. ## Audio +* "every sound cue resolves to its own `.slb` bank" → the 322 `SE_*` cues do not; + **0 of 322** are in `FILES`, and `BANK_SE` puts them all in `Static.slb`. +* "`Static.slb` can be split into waves like any other bank" → it holds **0 + `RIFF`, 0 `seek`, 0 `WAVE`** across all 8 353 472 readable bytes. + [`menu-audio-cues.md`](menu-audio-cues.md) + * "`BGM_001.slb` is three sub-waves (10 KB + 4.47 MB + 4.67 MB)" → the 10 KB is the **bank header**; a bank is **two** waves. * "a music bank's two waves might be intro + loop, two variations, or two halves" diff --git a/docs/re/data/se-ui-cues.txt b/docs/re/data/se-ui-cues.txt new file mode 100644 index 00000000..47f8efbb --- /dev/null +++ b/docs/re/data/se-ui-cues.txt @@ -0,0 +1,326 @@ +Every SE cue on the disc, from tables.pak SOUNDS. 322 cues. +BANK_SE names the single bank they all live in: Static.slb +0 of the 322 has its own entry in FILES (5 135 bank paths). + + 1 SE_UI_START + 2 SE_UI_CURSOR + 3 SE_UI_DECIDE + 4 SE_UI_CANSEL + 5 SE_UI_IMPOSI + 6 SE_UI_WAIT + 7 SE_UI_NEXT + 8 SE_UI_SUB_WIN_OPN + 9 SE_UI_SUB_WIN_CLS + 10 SE_UI_ALART_WIN + 11 SE_UI_PAUSE + 12 SE_UI_SPLASH_IN + 13 SE_UI_SPLASH_OUT + 14 SE_UI_LOAD_CMP + 15 SE_TUT_BOX_CLEAR + 16 SE_TUT_UNIT_IN + 17 SE_UI_WEAPON_PLAN + 18 SE_UI_WEAPON_CREATE + 21 SE_HUD_MIS_LOCK + 22 SE_HUD_LOCK_ALART + 23 SE_HUD_WP_EMPTY + 24 SE_HUD_WP_CHARGED + 25 SE_HUD_DMG_ALARM + 26 SE_HUD_OH_ALART + 27 SE_HUD_OVER_HEAT + 28 SE_HUD_CALL + 29 SE_HUD_EMERG_CALL + 30 SE_HUD_MES_END + 31 SE_HUD_MES_SHAT + 32 SE_HUD_MIS_SEARCH + 33 SE_HUD_INVALID + 34 SE_HUD_MW_CHG + 35 SE_HUD_TRG_CHG + 36 SE_HUD_MOD_CHG + 37 SE_HUD_RADIO_MENU + 38 SE_HUD_RADIO_ORDER + 39 SE_HUD_RADIO_CANSEL + 40 SE_HUD_TM_USE + 41 SE_HUD_TM_INP + 42 SE_HUD_TM_COM + 43 SE_HUD_TM_OK + 44 SE_HUD_TM_ERROR + 45 SE_HUD_RADER_MARKER + 46 SE_HUD_GUIDE + 47 SE_HUD_SUB_TARGET + 48 SE_HUD_SP_CHARGE + 49 SE_HUD_SP_LV_UP + 50 SE_BR_PASS + 51 SE_BR_SHAT + 52 SE_BR_PROGRESS + 53 SE_BR_DECO_1 + 54 SE_BR_FRAME + 55 SE_BR_DECO_2 + 56 SE_BR_HELP + 57 SE_BR_DISP + 58 SE_BR_COWIN + 59 SE_BR_WAIT + 60 SE_BR_NEXT + 61 SE_BR_FRIENDRY + 62 SE_BR_ENEMY + 63 SE_BR_MESS + 64 SE_BR_POINT + 65 SE_BR_MARK + 66 SE_BR_OUT + 67 SE_BR_MAIN_OP + 68 SE_BR_MAIN_CLS + 69 SE_BR_JUMP_OUT + 70 SE_BR_JUMP_IN + 71 SE_BR_PROMETEUS + 72 SE_BR_PLANET_BROKEN + 73 SE_HUD_SP_RETURN + 74 SE_HUD_SP_ATACK + 75 SE_HUD_SP_SLOW + 76 SE_HUD_AAM_SITE_OPN + 77 SE_HUD_AAM_SITE_CLS + 78 SE_HUD_ASM_SITE_OPN + 79 SE_HUD_ASM_SITE_CLS + 81 SE_UI_MISSION_START + 82 SE_UI_MISSION_UPDATE + 83 SE_UI_MISSION_END + 101 SE_SW_nbe01_1 + 102 SE_SW_nbe02_1 + 103 SE_SW_nbe03_1 + 104 SE_SW_nla01_1 + 105 SE_SW_nvu01_1 + 106 SE_SW_nvu02_1 + 107 SE_SW_nvu03_1 + 108 SE_SW_nvu04_1 + 109 SE_SW_nsh01_1 + 110 SE_SW_nsh02_1 + 111 SE_SW_nsh03_1 + 112 SE_SW_nsp01_1 + 113 SE_SW_nsp02_1 + 114 SE_SW_nvu01_2 + 115 SE_SW_nvu01_3 + 116 SE_SW_nvu02_2 + 117 SE_SW_nvu02_3 + 118 SE_SW_nvu02_4 + 119 SE_SW_nvu03_2 + 120 SE_SW_nvu03_3 + 121 SE_SW_nvu04_2 + 122 SE_SW_nla02_1 + 123 SE_SW_SPIT_1 + 201 SE_MW_wvu01_1 + 202 SE_MW_wvu02_1 + 203 SE_MW_wvu03_1 + 204 SE_MW_wvu04_1 + 205 SE_MW_wbe01_1 + 206 SE_MW_wbe02_1 + 207 SE_MW_whb01_1 + 208 SE_MW_whb02_1 + 209 SE_MW_wla01_1 + 210 SE_MW_wla02_1 + 211 SE_MW_wla03_1 + 212 SE_MW_wla04_1 + 213 SE_MW_wAA01_1 + 214 SE_MW_wAA02_1 + 215 SE_MW_wAA03_1 + 216 SE_MW_wAA04_1 + 217 SE_MW_wAA04_2 + 218 SE_MW_wAA05_1 + 219 SE_MW_wAA07_1 + 220 SE_MW_wAA0x_2 + 221 SE_MW_wro01_1 + 222 SE_MW_wro02_1 + 223 SE_MW_wro03_1 + 224 SE_MW_wro04_1 + 225 SE_MW_wAS01_1 + 226 SE_MW_wAS02_1 + 227 SE_MW_wAS03_1 + 228 SE_MW_wAS04_1 + 229 SE_MW_wAS05_1 + 230 SE_MW_wAS0x_2 + 231 SE_MW_wAS0x_3 + 232 SE_MW_wto01_1 + 233 SE_MW_wto01_2 + 234 SE_MW_wto02_1 + 235 SE_MW_wto02_2 + 236 SE_MW_wto03_1 + 237 SE_MW_wto03_2 + 238 SE_MW_wto04_1 + 239 SE_MW_wto04_2 + 240 SE_MW_wbo01_1 + 241 SE_MW_wbo02_1 + 242 SE_MW_wbo03_1 + 243 SE_MW_wbo04_1 + 244 SE_MW_wbo05_1 + 245 SE_MW_wbo06_1 + 246 SE_MW_wbo07_1 + 247 SE_MW_wbo08_1 + 248 SE_MW_wbo09_1 + 249 SE_MW_wKE01_1 + 250 SE_MW_wKE02_1 + 251 SE_MW_wKE03_1 + 252 SE_MW_wgu01_1 + 253 SE_MW_wgu02_1 + 254 SE_MW_wgu03_1 + 255 SE_MW_wgu04_1 + 256 SE_MW_wgu05_1 + 257 SE_MW_wgu05_2 + 258 SE_MW_wgu06_1 + 259 SE_MW_wgu07_1 + 260 SE_MW_wsp01_1 + 261 SE_MW_wsp01_2 + 262 SE_MW_wsp01_3 + 263 SE_MW_L3GP_1 + 264 SE_MW_THOR_1 + 301 SE_SPE_mcm01_1 + 302 SE_SPE_mcm02_1 + 304 SE_SPE_mpr01_1 + 351 SE_SWP_BEAM_1 + 352 SE_SWP_RAILGUN_1 + 353 SE_SWP_PCANNON_1 + 354 SE_SWP_LASER_1 + 355 SE_SWP_BVULCAN_1 + 356 SE_SWP_VULCAN_1 + 357 SE_SWP_AAM_1 + 358 SE_SWP_ASM_1 + 359 SE_SWP_BEAM_2 + 401 SE_EXT_OVER_HEAT + 402 SE_EXT_OH_RECOVER + 403 SE_EXT_EMPTY + 404 SE_EXT_EJECT_H + 405 SE_EXT_EJECT_M + 406 SE_EXT_EJECT_L + 407 SE_EXT_EJECT_FAE + 408 SE_EXT_MGT_OPN + 409 SE_EXT_MGT_CLS + 410 SE_EXT_PHOTON_CHG + 411 SE_EXT_GRAVITY_CHG + 412 SE_EXT_RECHARGE + 413 SE_EXT_RECHG_CMP + 414 SE_EXT_DOUBLER + 415 SE_EXT_SPIT_CHG + 501 SE_DS_ENGINE + 502 SE_DS_POWER_UP + 503 SE_DS_AFTER_BURNER + 504 SE_DS_REVERSE + 505 SE_DS_COCKPIT + 506 SE_DS_POWER_DOWN + 507 SE_DS_AB_END + 508 SE_DS_SIDE + 509 SE_DS_ROLL + 511 SE_ENG_ERAN + 512 SE_ENG_ERAN_Q + 513 SE_ENG_VINDI + 514 SE_ENG_DELTA + 515 SE_ENG_UNE + 516 SE_ENG_ADAN + 517 SE_ENG_SUPPLY + 518 SE_ENG_ATK_S + 519 SE_ENG_ATK_L + 551 SE_ENG_ACRO + 552 SE_ENG_JUN + 553 SE_ENG_KUCHI + 554 SE_ENG_OOGATA + 555 SE_ENG_YUSOU + 556 SE_ENG_BS + 557 SE_ENG_AAF + 558 SE_ENG_ASF + 559 SE_ENG_CARRIER + 560 SE_ENG_MISSILE + 561 SE_ENG_SIDE_S + 562 SE_ENG_SIDE_L + 601 SE_EXP_CRAFT + 602 SE_EXP_EX_CRAFT + 603 SE_EXP_ATK + 604 SE_EXP_OUT + 605 SE_EXP_BS_PART_L + 606 SE_EXP_BS_PART_M + 607 SE_EXP_BS_PART_S + 608 SE_EXP_BS_BREAK_LL + 609 SE_EXP_BS_BREAK_L + 610 SE_EXP_BS_BREAK_M + 611 SE_EXP_BS_BREAK_S + 612 SE_EXP_BS_BREAK_SS + 613 SE_EXP_BS_OMEN + 614 SE_EXP_BS_BOMB + 615 SE_EXP_MISSILE + 616 SE_EXP_TCAF_CRUISER + 617 SE_EXP_MINE + 651 SE_IMP_BM_DMG + 652 SE_IMP_BM + 653 SE_IMP_LS_DMG + 654 SE_IMP_LS + 655 SE_IMP_VULCAN + 656 SE_IMP_SHOTGUN + 657 SE_IMP_FIRE + 658 SE_IMP_MISSILE + 659 SE_IMP_ROCKET + 660 SE_IMP_SMOKE + 661 SE_IMP_TORPEDO + 662 SE_IMP_BOMB + 663 SE_IMP_KINETIC + 681 SE_IMP_BULLET + 683 SE_IMP_BS_BEAM + 684 SE_IMP_BS_RGUN + 685 SE_IMP_BS_PCANNON + 686 SE_IMP_BS_LASER + 687 SE_IMP_BS_BVULCAN + 688 SE_IMP_BS_VULCAN + 689 SE_IMP_BS_AAM + 690 SE_IMP_BS_ASM + 691 SE_IMP_GRV + 701 SE_SHIELD_DOWN + 702 SE_SHIELD_RECHARGE + 703 SE_SHIELD_DOWN_BS + 751 SE_BOSS_CRY + 752 SE_BOSS_CLOSE + 753 SE_BOSS_OPEN + 754 SE_BOSS_STUMBLE + 755 SE_BOSS_MOMENTS + 756 SE_BOSS_ATK_A + 758 SE_BOSS_ATK_C + 759 SE_BOSS_LASER + 760 SE_BOSS_HOMING + 761 SE_BOSS_CHARGE + 762 SE_BOSS_CORE_CHARGE + 763 SE_BOSS_SPREAD + 764 SE_CORE_COLLAPSE + 781 SE_PROME_AMB_1 + 782 SE_PROME_AMB_2 + 783 SE_PROME_AMB_3 + 784 SE_PROME_FIRE + 785 SE_ENV_MINE + 786 SE_HNG_ARM_MV + 787 SE_HNG_MOUNT + 788 SE_HNG_UN_MOUNT + 789 SE_HNG_ARM_UP + 790 SE_HNG_ARM_DWN + 791 SE_HNG_MOUNT_2 + 792 SE_HNG_UN_MOUNT_2 + 793 SE_HNG_MOUNT_3 + 794 SE_HNG_UN_MOUNT_3 + 795 SE_HNG_MOUNT_4 + 796 SE_HNG_UN_MOUNT_4 + 807 SE_ETC_JMP_OP + 808 SE_ETC_JMP_IN + 809 SE_ETC_JMP_OUT + 810 SE_ENV_BS_M + 811 SE_ENV_BS_S + 812 SE_ENV_BS_L + 813 SE_ENV_BS_LL + 814 SE_ENV_CARRIER + 815 SE_ETC_HP_UNE + 816 SE_ETC_HP_ADAN + 817 SE_ETC_HP_ACRO + 818 SE_ENV_WIND + 819 SE_ENV_WIND_TURN + 820 SE_ETC_TURRET_L + 821 SE_ETC_TURRET_M + 822 SE_ETC_TURRET_S + 823 SE_PASS_DS + 824 SE_PASS_ADAN + 825 SE_PASS_ERAN + 826 SE_PASS_PLUS + 827 SE_PASS_TYPEQ + 828 SE_PASS_VINDI + 829 SE_ETC_COLLISION + 830 SE_ETC_SHIELD_DMG + 900 SE_LFE_BOMB + 901 SE_LFE_ENG diff --git a/docs/re/menu-audio-cues.md b/docs/re/menu-audio-cues.md new file mode 100644 index 00000000..275f0332 --- /dev/null +++ b/docs/re/menu-audio-cues.md @@ -0,0 +1,100 @@ +# Menu audio — the event vocabulary is on the disc; the binding is not + +**Status:** ✅ `CONFIRMED` and **decoded** for the cue vocabulary and the bank +that holds it. 🟡 the cue↔event binding is a **name match**, not a measurement. +❔ two negatives with their reach: no cue names a screen's music, and the audio +for an individual SE cue cannot yet be extracted. + +Answers most of [MISSION Q8](../port/MISSION.md). + +## ✅ The UI cue vocabulary — decoded + +`dat/tables.pak`'s sound table has a `SOUNDS` record of 5 798 cues. 322 are `SE_*` +and the **low block is the user-interface vocabulary**, named by the game's +authors after the *events*, not after the sounds: + +| id | cue | id | cue | +|---|---|---|---| +| 1 | `SE_UI_START` | 9 | `SE_UI_SUB_WIN_CLS` | +| **2** | **`SE_UI_CURSOR`** | 10 | `SE_UI_ALART_WIN` | +| **3** | **`SE_UI_DECIDE`** | 11 | `SE_UI_PAUSE` | +| **4** | **`SE_UI_CANSEL`** *(sic)* | 12 | `SE_UI_SPLASH_IN` | +| **5** | **`SE_UI_IMPOSI`** | 13 | `SE_UI_SPLASH_OUT` | +| 6 | `SE_UI_WAIT` | 14 | `SE_UI_LOAD_CMP` | +| 7 | `SE_UI_NEXT` | 17/18 | `SE_UI_WEAPON_PLAN` / `_CREATE` | +| 8 | `SE_UI_SUB_WIN_OPN` | 81–83 | `SE_UI_MISSION_START` / `_UPDATE` / `_END` | + +Full 322-cue list in [`data/se-ui-cues.txt`](data/se-ui-cues.txt). The remaining +blocks are gameplay: `SE_HUD_*` (21–83), `SE_BR_*` briefing (50–72), `SE_SW_*` / +`SE_MW_*` weapons, `SE_DS_*` engine, `SE_EXP_*` explosions, `SE_SHIELD_*`. + +## ✅ They all live in one bank — decoded + +The sound table's `BANK_SE` record is a **single field**: `Static.slb`. And the +disc-wide check agrees — **0 of the 322 `SE_*` cues has an entry in `FILES`**, the +5 135-path list where every voice, briefing and BGM bank is named. SE is the one +family that is not one-cue-one-file. + +`SETTINGS` names the XACT project too: `PATH` = `game:\dat\sound.pak+`, +`PARAM` = `Pj_Silph.xgs`. + +## 🟡 The binding: a name match, and I am calling it that + +MISSION asks which cue fires on **move / confirm / back / error**. Read off the +names: + +| event | cue | +|---|---| +| cursor moves | `SE_UI_CURSOR` (2) | +| Ⓐ confirm | `SE_UI_DECIDE` (3) | +| Ⓑ back | `SE_UI_CANSEL` (4) | +| invalid / error | `SE_UI_IMPOSI` (5) | +| submenu opens / closes | `SE_UI_SUB_WIN_OPN` / `_CLS` (8/9) | +| the splash | `SE_UI_SPLASH_IN` / `_OUT` (12/13) | + +**Nobody has watched the game emit cue 2 on a d-pad press.** This is inference +from identifiers, and it belongs in the same box as Q4's GamePart ids — with one +honest difference worth stating: these are the *authors' own event names*, chosen +to describe when the sound plays, not asset labels I am interpreting. It is a +strong name match. It is still a name match, and the port is authoring it. + +Measuring it needs the guest's cue-play call observed with its argument — the +same instrumentation Q4's residual wants, and not something this container can do +today (it runs `--mute=true` against an SDL dummy device, so there is no audio +path to watch either). + +## ❔ Which BGM per screen — undecodable, reach already recorded + +All 32 BGM cues are named `BGM_001`…`BGM_109`. Nothing in `SOUNDS`, `FILES` or the +bank headers names a screen — see +[`structures/bgm-two-stems.md`](structures/bgm-two-stems.md). Unchanged by this +iteration. + +## ❔ And a new negative: an individual SE's audio is not extractable yet + +`Static.slb` is **8 353 472 readable bytes** (declared 8 970 240 — exactly the +616 768 over-declaration the corpus already records), and it contains +**0 `RIFF`, 0 `seek`, 0 `WAVE`** — scanned over the whole buffer, so this is not +an offset problem. Every other bank on the disc is delimited by `seek` magic at +`data_at + declared_size` (7 620/7 620 in +[`slb-data-offset.md`](structures/slb-data-offset.md)); `Static.slb` is outside +that population. So the route that extracts every voice line and every BGM does +**not** give you `SE_UI_CURSOR`'s audio: the cue is named, the bank is named, and +the wave inside the bank is not locatable by any boundary marker. + +**The named next step is `Pj_Silph.xgs`** — the XACT project file `SETTINGS` +points at, which in XACT is exactly where cue→wave-index lives. It **is** in +`sound.pak`: `name_hash("Pj_Silph.xgs")` resolves to TOC index 9454. ⚠️ Its entry +is 533 bytes at a 2048-aligned offset and carries no `XGSF` magic — and its region +has phase 1728, so those 533 bytes are very likely the *previous* bank's tail +rather than its own (the leading-region effect, [`slb-data-offset.md`] +(structures/slb-data-offset.md)). Locating its real bytes is the first job, not +parsing XACT. + +## For the port + +* the cue **names and ids** are disc facts — use them as the event vocabulary; +* which event fires which cue is **authored from the table above**; +* which BGM plays on which screen is **authored** — nothing on the disc says; +* and the UI **sound effects cannot be exported yet**. That is a gap in the + assets, not in the naming.