Commit Graph

9 Commits

Author SHA1 Message Date
sylph-decoder
9bacd69f6c re: bgm-two-stems.md said the menu's bank is undecodable from the disc, and its own page decodes it
The Status line and the section heading both read 'undecodable from the disc' while
a later section of the same page decodes it three ways, one of them static from the
executable -- GamePart_Title's handler does li r5, 1103. A reader who stops at the
top concludes the opposite of what the page establishes.

The surviving content is the reason the CUE TABLE cannot answer it: 32 BGM cues
named by number with no screen name, with SOUNDS, FILES and the bank headers all
searched. A negative about one search location, written as a negative about the
disc -- the same method-versus-subject error as the SE-audio heading, in the first
line a reader sees.

It propagated: the port's BLOCKED.md carries 'which BGM the menu plays -- not on
the disc' in the same words.

Found by applying sylpheed-port's 'get the category right' discipline to my own
noisy impossibility sweep, after measuring what the false positives actually were
rather than assuming they were infrastructural.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-31 02:22:28 +00:00
sylph-decoder
b410c94445 re: run the identity control on the coherence estimator -- it is exact, and the refutation strengthens
sylpheed-port disqualified a difference instrument of their own and named the rule:
before asking whether an instrument can measure a difference, ask whether it
returns zero for no difference. Mine had never had that test -- its positive
control was a filtered copy at 0.94, which I had taken as the ceiling.

Identity reads 1.0000 in every band, and a linear filter with NO delay also reads
1.0000. The 0.94 was entirely the 12 ms delay's windowing cost. So the ceiling for
a filtered copy is 1.0 and the measured 0.027 midrange is further from it than the
original control implied.

It also adds an argument the first pass missed: a delay depresses coherence
uniformly (0.9288..0.9380 flat), while the measurement is 0.027 midrange against
0.83 at HF. The shape is inconsistent with a delayed filtered copy too, which was
the remaining route by which a rear pair could have produced it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-31 00:09:43 +00:00
sylph-decoder
dcfb53bc9b re: a bank's wave 1 is not a filtered copy of wave 0 -- and my own discriminator cannot finish the job
Coherence on BGM_103, the menu's bank, with controls run first: a real linear
filter of wave 0 reads 0.93-0.94 in every band, a different bank reads 0.001, and
wave 0 misaligned by 1 s reads 0.004-0.057. The measurement reads 0.027 at 1-4 kHz,
so the 'wave 1 is wave 0 filtered' model is refuted.

The frequency structure is inverted relative to any mic-pair or reverb model:
coherence rises with frequency (0.169 -> 0.827) while energy falls (71 % -> 0.2 %),
and a rear pair decorrelates fastest at HF. In the midrange the two waves are 13x
further apart than the two channels of one wave.

But the L-R control is what limits the tool and it is recorded as such: within one
wave, genuinely one performance in two channels, coherence is only 0.221-0.497. So
'same performance' does not imply high coherence here, my positive control was the
wrong model of the rear-pair reading, and the 🟡 is NOT settled. The tool tests for
linear filtering and neither surviving reading requires it.

Also corrects MISSION's Q10 row, which still carried the refuted three-sub-wave
premise and had directed work at a dead question for days. Its gate is in fact met.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 20:17:23 +00:00
sylph-decoder
1d770b65eb re: land the loop-point correction where the claim actually lives
The port found its exporter still shipping 'no loop-point field has been
identified anywhere' in the field manifest.json concatenates, days after the
correction existed in other fields. Auditing this corpus the same way found the
same failure here: the refuted sentence was still standing untouched in
bgm-two-stems.md -- where anyone looking up BGM behaviour arrives -- and in
HANDOFF.md, the one page the port is told to read. My correction had gone into a
NEW page only.

Both fixed in place, each naming the refutation rather than quietly deleting the
old claim, and each carrying the measured window [9.44, 71.31] s at 61.87 s.

METHOD entry: writing a correction down is not landing it. Grep the corpus for
the CLAIM, not for the file you were working in. Plus the port's trap in doing
that audit -- a replacement that quotes the refuted sentence in order to name it
will match a substring search from inside the paragraph saying it is false.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
2026-08-30 10:20:04 +00:00
sylph-decoder
c1f3608b07 formats: a music bank's third sub-wave was its own header
The port hit `sound_bank_riffs("BGM_103.slb")` returning three against a census
that says two, and refused to guess which to drop. It was our reader.

`to_xma_riffs`'s hybrid branch derives a leading packet stream's start as
`first_riff % XMA1_PACKET`. That is right only when the bank header is smaller
than one 2048-byte packet -- true of the voice banks the branch was written for
(1392/1468/1600/1728), false of a music bank, whose header is exactly five
packets. The modulus returned 0 and the whole 10 240-byte header was emitted as
sub-wave 0.

The header states its own length, so the guard needs no threshold: BE u32 0x800
at +0x18 with the bank id repeated at +0x00 and +0x20, header length in blocks at
+0x24. Disc-wide over sound.pak's 9 519 entries, 28 match at offset 0 -- every
music bank, ids 1001-1023 and 1101-1105 -- and on 28/28 the declared header ends
EXACTLY at the first RIFF. Zero have a gap, so a header and a leading packet
stream never coexist here; zero false positives among the other 9 491.

Controlled rather than argued: decoding the emitted region through the same
chain, on the same bank, in the same run gives 0.009 s of PCM where the bank's
real wave 0 gives 87.744 s against a declared 87.75. The region is also 99.1%
zero bytes. And the oracle had already said two -- the XMA probe at the main menu
saw exactly two streams, at BGM_103's two declared wave sizes.

BGM_106-109 are deliberately NOT in the 28: their entries start mid-bank, so they
have no header at offset 0 and their leading region is real audio. The
VOICE_D_453 recovery is untouched and its tests still pass, 10/10 green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014voBspJ6kFncNErZJuZcLw
2026-08-29 12:30:16 +00:00
Sylpheed RE agent
86e52b01d0 re: the menu's music is BGM_103 -- found by accident while chasing Q6,
confirmed three ways

Chasing where the event code comes from, sub_821C5580 turned out to do
two things worth having.

For Q6 it arms the outer gate: li r11,3 ; stw r11,16(r28) is exactly the
value sub_821C7850 tests before dispatching, which answers the "what does
this+16 == 3 gate on" question I left open last iteration. It then passes
r5 = [r27+4], an event read out of a structure, so the vocabulary is
still not enumerable. Of the four callers of sub_821C7850, three pass
constants -- 0, 0 and 5 -- and this one does not.

The accident is a few instructions earlier: li r5, 1103 into a sound-play
call. 1103 is a BGM cue id, BGM_103. That closes a residual I had written
off as undecodable: which bank the menu plays. The cue table genuinely
cannot say, since its BGM entries are numeric -- but the code can, and it
checks out three independent ways. The census says BGM_103.slb is two
waves of 3876864 and 3930112 bytes; the XMA probe at the main menu saw
two stereo streams of 3876864 and 3930112 bytes. Byte for byte on both.

That also corrects me. bgm-two-stems.md said those observed sizes matched
no bank's declared waves and inferred the decoder gets a window rather
than a whole wave. Wrong on both counts -- I had checked only the BGM_0xx
rows of the census because that was the block on screen. METHOD gets it:
check a measurement against the whole reference set, not the part you
happened to be reading.
2026-08-28 20:10:41 +00:00
Sylpheed RE agent
0d7199bc22 re: the UI sound effects ARE extractable -- retracting "cannot be
extracted", and the tool was in the build all along

Two iterations ago I closed Q8 by declaring the SE audio undecodable:
Static.slb has no wave boundaries, there is no XACT container anywhere,
and I said the index "exists only at runtime" as though that put it out
of reach. The disc half of that stands. The conclusion did not.

This build of Canary carries a cvar called xma_param_probe, added by this
project, whose own comment says it logs each XMA stream's parameters and
head bytes so raw sound.pak entries can be matched to real decode params.
It has been sitting in the startup CONFIG DUMP of every log I have read
this session.

Run with it, driving the main menu: a d-pad move spawns a new mono 48 kHz
stream of 4 packets / 8192 bytes, and B spawns a different one of 2
packets / 4096 bytes. Searching their logged head bytes in Static.slb
finds each at exactly one offset -- 0x1ec0 and 0x0ec0 -- and the two are
contiguous, 0x0ec0 + 4096 = 0x1ec0. So the bank is a packed run of whole
2048-byte packets with no delimiters, which is precisely why the seek
scan found nothing: there is nothing to find. A wave is (offset, packet
count) and nothing else.

That splits Q8's binding cleanly. Event -> WAVE is now measured: the port
can have the audio. Event -> cue NAME is still a name match on the
authors' identifiers, and the page says so.

The same run settled something for Q10 too. Sitting on the main menu, TWO
stereo 48 kHz streams were decoding simultaneously. bgm-two-stems.md said
that observation was what it needed and that this container could not
make it; it can, and a music bank's two waves are now measured as
simultaneous rather than only inferred.

METHOD gets the general lesson, because it cost two iterations: check
what instrumentation the local build already has before declaring a
question blocked on tooling.
2026-08-28 19:30:03 +00:00
Sylpheed RE agent
2c4005795b port: audit the handoff -- four stale statements, a broken link, and the
residue in one place

Every MISSION row is answered, so this iteration checked the deliverable
itself rather than opening new scope: an answer that is not reachable
from HANDOFF.md has not been delivered, and I have been editing that page
by surgical replacement for a dozen iterations.

Four things were wrong or stale:

- the Q5 row still said initial focus was 2x TUTORIAL, 1x NEW GAME while
  its own bullet said four boots -- I updated the body last time and not
  the row;
- the Q2 bullet still described the other four main-menu destinations as
  "likely by name -- an inference, not a measurement", which Q4 has since
  MEASURED, and it listed GP_MISSION_SELECT as a main-menu destination
  when MISSION SELECT lives under EXTRAS;
- the Q1 bullet claimed that if the game presents at 60 Hz "nothing else
  on this page changes". That is now false: Q7's declared fade-in lengths
  are keyframe-derived and would halve. The same bullet also missed that
  the transition capture is a SECOND independent measurement supporting
  1 unit = 1/60 s -- the quad is declared black for 12 units, 0.20 s
  under the conversion, and the capture measured the plateau at
  0.17-0.23 s. Recorded as corroboration, not proof, because the plateau
  spans two screens' fades and cannot separate them;
- bgm-two-stems.md linked ../port/MISSION.md from inside structures/,
  which resolves nowhere.

Also named the two videos actually in scope, since "3.3 GB of video, two
files are in scope" is not much use without the filenames.

And added a What Is Still Open section. With every row green the residue
was scattered across eight pages; it is now one table with why each item
is stuck. Two entries share a single unblocker -- an emulator whose audio
path can be observed -- and they are the only ones that would change a
port decision.
2026-08-28 19:02:49 +00:00
Sylpheed RE agent
b3c8632006 re: a music bank is two stems that play together -- not intro+loop, and
not something to concatenate

Q10, and it starts by withdrawing the question's own premise. BGM_001 is
not three sub-waves of 10 KB / 4.47 MB / 4.67 MB: the 10 KB is the bank
header. A bank is exactly TWO waves, and across all 32 BGM banks on the
disc the two always have the SAME duration -- equal to 0.01 s over
lengths from 37 s to 277 s. That alone kills intro+loop and kills two
halves of one piece, both of which require unequal lengths.

Four banks appear to break the rule and do not: BGM_106-109 are the known
leading-region straddle, and the giveaway is that the entry named
BGM_107.slb contains BANK id=1108. The seek packet counts pin each join
exactly, so they realign to the same two-equal-waves shape rather than
being dropped as noise. That trap goes in METHOD.

Then the roles, by decoding both waves to PCM. They are
sample-synchronous: transient-envelope correlation searched over +/-5 s
peaks at lag +0.00 s, and both waves stop at the same millisecond,
167.663 s. Two stems of one performance, meant to sound at once. Wave 1
is quieter, has almost no bass and is far more L/R-decorrelated, which
reads as a surround-rear pair or a second intensity layer -- I cannot
separate those two from the file, and say so: ChannelMask is 0x0002 on
both, and this game's channel metadata is already documented as
meaningless.

Two things the port needs that are NOT on the disc, both marked as
authored: the track is not a seamless loop (BGM_001 fades out and is
followed by 6.15 s of silence, no loop-point field found), and nothing
names which bank the menu plays -- all 32 BGM cues are numeric.
2026-08-28 18:13:10 +00:00