diff --git a/docs/port/HANDOFF.md b/docs/port/HANDOFF.md index 3e3177ce..30e44011 100644 --- a/docs/port/HANDOFF.md +++ b/docs/port/HANDOFF.md @@ -170,10 +170,18 @@ authored version can be deleted. executable — those extensions are the authoring tool's). But Canary's `--xma_param_probe=true` logs every stream's head bytes, and searching them in `Static.slb` locates the wave exactly: - **d-pad move → `0x1ec0`, 4 packets / 8 192 B, mono 48 kHz; Ⓑ back → `0x0ec0`, - 2 packets / 4 096 B.** Each matched at one offset only, and they are contiguous + **d-pad move → `0x1ec0` (4 pkts / 8 192 B, 0.533 s); Ⓐ confirm → `0x5d6c0` + (6 pkts / 12 288 B, 1.016 s); Ⓑ back → `0x0ec0` (2 pkts / 4 096 B, 0.344 s)** — + every cue the five screens need. Move and back reproduce with identical head + bytes across **two independent boots**. Each matched at one offset only, and + the first two are contiguous (`0x0ec0 + 4096 = 0x1ec0`) — the bank is a packed run of whole 2 048-byte packets with no delimiters, which is why nothing could be scanned for. + ❔ **⬅ and ➡ play nothing distinct** — no new stream on either, so leave them + silent (the probe dedups, so this excludes a *distinct* invalid cue, not a + quiet replay of an already-heard one). + 🟡 The Ⓐ press both confirms and opens a screen, so whether its wave is the cue + named `SE_UI_DECIDE` or `SE_UI_SUB_WIN_OPN` is not separated. ⚠️ The order is **not** cue-id order, so the index must be observed per cue, not counted. ✅ **The slices decode**: 0.533 s, 0.344 s and 1.016 s of mono 48 kHz audio with the attack-and-decay shape of UI blips, via @@ -258,7 +266,8 @@ here until 2026-08-28 and is now settled.) | | what | why it is stuck | |---|---|---| -| 🟡 | **cue NAME → event binding** (Q8) | the event→**wave** binding is now measured; that the cursor's wave is the cue *named* `SE_UI_CURSOR` is still read off the authors' identifiers | +| 🟡 | **cue NAME → event binding** (Q8) | event→**wave** is measured for move/confirm/back; that the cursor's wave is the cue *named* `SE_UI_CURSOR` is still read off the authors' identifiers | +| ❔ | **the other ~319 SE cues** (Q8) | located one at a time by triggering them; only the three the menu needs have been done | | 🟡 | **the paint-order tie-break** (Q3) | eight candidates refuted; costs one element's blend on one screen | | 🟡 | **GamePart ids behind the buttons** (Q4) | the *screens* are measured; the ids are a name match onto the executable's class names | | ❔ | **the boot transitions in code** (Q6) | bounded as code-not-data, not proven. `sub_821C6458` — the substantial function in `GamePart_Title`'s neighbourhood — has **not been read** | diff --git a/docs/re/data/se-cue-runtime-offsets.txt b/docs/re/data/se-cue-runtime-offsets.txt index 027fc721..ce5d4331 100644 --- a/docs/re/data/se-cue-runtime-offsets.txt +++ b/docs/re/data/se-cue-runtime-offsets.txt @@ -8,7 +8,7 @@ event packets bytes channels/rate offset in Static.slb ------------------------- ------- ------ -------------- -------------------- d-pad move (cursor) 4 8192 mono 48000 Hz 0x1ec0 B / back (cancel) 2 4096 mono 48000 Hz 0x0ec0 -(played before any input) 6 12288 mono 48000 Hz 0x5d6c0 +A / confirm (title->menu) 6 12288 mono 48000 Hz 0x5d6c0 Each head matched at exactly ONE offset. The first two are contiguous: 0x0ec0 + 4096 = 0x1ec0. @@ -29,3 +29,11 @@ DECODED 2026-08-28 with tools/re-capture/slb_extract_wave.py + ffmpeg's xma1: CONTROL: the same synthesized RIFF wrapper applied to BGM_001.slb's first wave (offset 14336, stereo) decodes to 173.808875 s -- identical to the duration obtained from that bank's own on-disc RIFF header. The wrapper is correct. + +SECOND RUN 2026-08-28 -- independent boot, same probe: + * d-pad move and B reproduced with IDENTICAL head bytes and sizes (2 of 2 runs). + * The 12288-byte wave fires on the A that advances title -> main menu, together + with the two stereo BGM stems (the menu's music starting). Counting from the + title rather than the menu is what attributed it. + * Left and Right fired NO new stream -- no distinct invalid cue. (Dedup caveat: + a press replaying an already-heard wave would also log nothing.) diff --git a/docs/re/menu-audio-cues.md b/docs/re/menu-audio-cues.md index 351eb255..3f4651f7 100644 --- a/docs/re/menu-audio-cues.md +++ b/docs/re/menu-audio-cues.md @@ -159,7 +159,7 @@ bytes**. Searching those bytes in `Static.slb` finds the wave. |---|---|---|---|---| | **d-pad move** (cursor) | 4 | 8 192 | mono 48 kHz | **`0x1ec0`** | | **Ⓑ back** (cancel) | 2 | 4 096 | mono 48 kHz | **`0x0ec0`** | -| played before any input | 6 | 12 288 | mono 48 kHz | `0x5d6c0` | +| **Ⓐ confirm** (title → main menu) | 6 | 12 288 | mono 48 kHz | **`0x5d6c0`** | Each head matched at **exactly one** offset. Reference data in [`data/se-cue-runtime-offsets.txt`](data/se-cue-runtime-offsets.txt). @@ -198,7 +198,7 @@ slb_extract_wave.py Static.slb 0x1ec0 4 # -> Static_0x1ec0.riff -> 0.533 s |---|---|---|---|---|---|---| | d-pad move | `0x1ec0` | 4 | **0.533 s** | 2 085 | 29 813 | sharp attack, monotonic decay | | Ⓑ back | `0x0ec0` | 2 | **0.344 s** | 2 985 | 16 973 | attack, peak in frame 2 | -| pre-input cue | `0x5d6c0` | 6 | **1.016 s** | 4 327 | 32 767 | peaks in frame 3, long decay | +| **Ⓐ confirm** | `0x5d6c0` | 6 | **1.016 s** | 4 327 | 32 767 | peaks in frame 3, long decay | All three are mono 48 kHz, audible from sample 0, and have the percussive attack-and-decay shape of UI blips — not silence, not noise. @@ -216,3 +216,40 @@ The bitrates are consistent too: 8 192 B / 0.533 s ≈ 15.4 kB/s, 4 096 / 0.344 it from the disc, and the corpus keeps measurements and tooling rather than extracted game audio. The offsets, packet counts and this tool are the deliverable. + +## The three cues the milestone needs are bound — 2026-08-28, second run + +A second, independent boot repeated the probe and pinned the one that was still +unattributed. + +| event | wave | packets / bytes | runs agreeing | +|---|---|---|---| +| **d-pad move** | `Static.slb+0x1ec0` | 4 / 8 192 | **2 of 2** — identical head bytes | +| **Ⓑ back** | `Static.slb+0x0ec0` | 2 / 4 096 | **2 of 2** — identical head bytes | +| **Ⓐ confirm** | `Static.slb+0x5d6c0` | 6 / 12 288 | newly bound this run | + +The `0x5d6c0` wave was previously logged as "played before any input", because +the first run only started counting at the main menu. Counting from the **title** +instead shows it appears exactly on the Ⓐ that advances title → main menu, along +with the two stereo BGM stems (the menu's music starting). + +So move / confirm / back — everything the five-screen milestone needs — are +located and decodable. + +🟡 **What that Ⓐ measurement does not separate.** The same press both *confirms* +and *opens a screen*, so this wave could be the cue the vocabulary calls +`SE_UI_DECIDE` or the one it calls `SE_UI_SUB_WIN_OPN`. The port needs *a* sound +on confirm and this is the one the game plays there; which name it carries is not +established. + +## ❔ ⬅ and ➡ play nothing distinct + +[`menu-navigation-semantics.md`](menu-navigation-semantics.md) measured that +left/right do not move the cursor. They also **fire no new XMA stream** — so +there is no distinct "invalid" cue on the main menu, and `SE_UI_IMPOSI` was not +observed. The port should leave left/right silent. + +⚠️ **Reach of that negative:** the probe dedups on head bytes, so a press that +replayed an *already-heard* wave would log nothing. At that point in the run the +cursor, confirm and BGM waves had all been heard. So this excludes a **distinct** +invalid cue; it cannot exclude left/right quietly replaying one of those three.