diff --git a/docs/re/f2-no-gain-field-in-tables.md b/docs/re/f2-no-gain-field-in-tables.md index 30385364..f7c25651 100644 --- a/docs/re/f2-no-gain-field-in-tables.md +++ b/docs/re/f2-no-gain-field-in-tables.md @@ -102,7 +102,7 @@ did not open. |---|---|---| | `tables.pak` cue records | ✅ exhaustive, with a passing control | **no gain-like field** | | `sound.pak` bank headers | ✅ all 9 519 entries | **no readable header to carry one** | -| the executable, around `sub_821C5580` | ❌ **not checked** | — | +| the executable, around `sub_821C5580` | ✅ **CHECKED** | **the play call passes no gain** | **For the port, unchanged: author nothing yet.** But the shape of the answer is now visible. If the executable also has no per-cue gain, the honest conclusion is @@ -113,3 +113,65 @@ balance rather than transcribing a table, and it would be *undecodable* rather than *decoded* — which the port must know, because a mix authored in ignorance and a mix authored deliberately look identical in the file and differ entirely in how much they can be trusted. + +## ✅ Third site checked 2026-09-02 — the play call carries no volume + +`sub_821C5580`'s cue-1103 site, read out of the image: + +``` +821C5608 li r11,1103 +821C560C li r5,1103 ; the CUE ID +821C5610 li r4,4 ; a constant beside it -- category/bus, not a level +821C561C lwz r3,0(r29) ; the sound object +821C5620 bl 0x8217ACF8 ; play(this, 4, 1103) +``` + +And the callee's prologue confirms the shape: + +``` +8217AD00 stfd f30,-72(r1) ; callee-SAVED floats -- it uses floats internally +8217AD10 or r29,r5,r5 ; r5 = cue id, with sentinels: +8217AD18 cmpi r29,-2 ; -2 -> take the id from this+136 +8217AD24 cmpi r29,-1 ; -1 -> return -1 +``` + +> **The call is `play(this, category, cue_id)`. No volume is passed — no float +> argument is set up by the caller at all**, and the three integer arguments are +> accounted for. + +⚠️ **What this does not exclude, and it is the honest limit.** The callee *saves* +`f30`/`f31`, so it uses floats internally and could look a level up for itself. +"No gain is passed" is not "no gain exists" — but it does mean **there is nothing +at this site for the port to transcribe.** + +## 🔴 F2's answer: **undecodable, with reach** — all three sites checked + +| site | checked | result | +|---|---|---| +| `tables.pak` cue records | ✅ exhaustive, passing control | no gain-like field, and numbers carry names here so one would have had a name | +| `sound.pak` bank headers | ✅ all 9 519 entries | no readable header to carry one | +| the executable's play path | ✅ | call passes `(this, category, cue_id)`, no volume | + +**So: the port authors the mix, and it now knows it is authoring.** That is the +outcome this question existed to make explicit rather than accidental. The one +authored value the game itself exposes is the **user-facing sound options screen** +(`po_sound_scr.prt`, `tables.pak` object #15) — a runtime master, not a per-cue +table. + +📌 **The port's own measurement is the best evidence available for the shape of +the fix**: `confirm` peaking at −0.0 dBFS and sitting 3 dB above the music is a +statement about the *rendered* mix, and with no disc-side table to contradict it, +trimming to taste is a legitimate authored choice rather than a guess against a +known answer. + +## Refutation attempt, recorded per the adversarial duty + +**Target:** the play-test's premise that *"a cue record commonly carries a volume +beside its wave index"*. + +**Result: REFUTED for this game, across all three sites where it could live.** The +premise is a sound generalisation about audio middleware and it does not hold +here: the cue record is an id and a name, the bank exposes no header, and the play +call takes a category rather than a level. Recorded because it was a *good* prior — +it is what sent me to the right three places — and being wrong about where a value +lives is different from being wrong to look.