re: there is no XACT container on this disc -- retracting my own lead and

closing Q8

Last iteration I named Pj_Silph.xgs as the route to the SE cue index, on
the reasoning that XACT keeps cue->wave there. That route is dead, and
the negative is properly bounded: its 533-byte entry is high entropy with
no XGSF magic, +/-8 KB around it has none either, all 1.08 GB of
sound.pak contains zero XGSF, SDBK and WBND, and the executable has no
XACT or .xgs string anywhere. Control run first -- the same scan finds
RIFF in BGM_001 exactly where the bank structure says it should be, so
the scan works and the magic genuinely is not there.

So the .xgs and .slb extensions came from the authoring tool and survived
into shipped data that is not XACT at all. That goes in METHOD as a
general trap: check for the magic before committing to a parser for the
format an extension advertises. Writing an XACT parser would have been
wasted work.

What that leaves for the SE audio is undecodable-with-reach rather than
pending: Static.slb has no wave boundaries, there is no project file, and
none of the sound table's five records carries an offset. The bank is
certainly the right one -- 8 353 472 bytes over 322 cues is 0.84 to 1.01
seconds each at the bitrates the disc uses elsewhere, exactly the shape
of a bank of short effects. Only the index into it is missing, and it
exists only at runtime.

Q8 closes: vocabulary and bank decoded, the event binding a name match on
the authors' own event names, and the audio explicitly something the port
must source or author rather than extract. With this every MISSION row is
answered.
This commit is contained in:
Sylpheed RE agent
2026-08-28 18:58:06 +00:00
parent c760cdc509
commit f5e7426cfa
4 changed files with 65 additions and 5 deletions

View File

@@ -178,3 +178,9 @@ agent's loop prompt, i.e. nowhere durable. See [`README.md`](README.md) for the
processes carries the whole loop prompt as its argv, so the listing is tens of
kilobytes of the prompt you already have. Use `pgrep -x <name>` or
`ps -o pid=,stat= -C <name>`.
* **A file extension is not a format.** `sound.pak` is full of `.slb` banks and
names a `.xgs` project, and neither is an XACT container: the whole 1.08 GB
archive contains zero `XGSF`, `SDBK` or `WBND` magic, and the executable has no
XACT string at all. The names came from the authoring tool and survived into the
shipped data. Check for the magic before committing to a parser for the format
the extension advertises.

View File

@@ -158,6 +158,11 @@ neighbourhood, not just the line.
## Audio
* "`Pj_Silph.xgs` holds the cue→wave index, so parse XACT" → **no XACT container
exists on this disc**: 0 × `XGSF`/`SDBK`/`WBND` in all 1.08 GB of `sound.pak`,
and no `XACT`/`.xgs` string in the executable. The extensions are the authoring
tool's, not the format's. [`menu-audio-cues.md`](menu-audio-cues.md)
* "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

View File

@@ -98,3 +98,47 @@ parsing XACT.
* 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.
## ❔ `Pj_Silph.xgs` is a dead end — retracting the lead, with the reach
The section above named `Pj_Silph.xgs` as "the named next step", on the reasoning
that in XACT the cue→wave index lives in the project file. **That route is dead.**
| check | result |
|---|---|
| the entry's own bytes | 533 bytes, high entropy, **no `XGSF` magic** |
| ±8 KB around the entry in the flat concatenation | no `XGSF`, `SDBK`, `WBND`, `RIFF` or `seek` |
| **all of `sound.pak` — 1.08 GB across `.p00``.p04`** | **0 × `XGSF`, 0 × `SDBK`, 0 × `WBND`** |
| the executable | **0** occurrences of `XGSF`/`XACT`; no string matching `xact`, `.xgs`, `wavebank` or `soundbank` |
**Control, run first:** the same magic scan over `BGM_001.slb`'s neighbourhood
finds `RIFF` exactly where the bank structure says it should be. The scan works;
the magic genuinely is not there.
So the `.xgs` / `.slb` names are **inherited from the authoring tool, not from the
shipped format** — nothing on this disc is a parseable XACT container. There is no
XACT project file to read, and writing an XACT parser would have been wasted work.
### Where that leaves the SE audio: undecodable, with reach
Locating an individual SE cue's wave inside `Static.slb` is **not possible from
anything found on the disc**. Looked in:
* `Static.slb` itself — 8 353 472 readable bytes, **0 `RIFF` / 0 `seek` / 0 `WAVE`**,
where every one of the other 7 620 banks is delimited by `seek` magic at
`data_at + declared_size` ([`structures/slb-data-offset.md`](structures/slb-data-offset.md));
* the XACT project file — absent, as above;
* the sound table's five records — `SOUNDS` gives cue→id, `FILES` gives bank
paths, `BANK_SE` gives the one bank name, `SETTINGS` gives a path and the
(absent) project file, `STAGES` is empty. **No record carries an offset.**
**What does corroborate the binding:** `Static.slb` is 8 353 472 bytes, and at the
bitrates the disc uses elsewhere (25 69731 000 B/s) that is **269325 seconds of
audio — 0.84 to 1.01 s per cue over 322 cues.** Exactly the shape of a bank of
short UI/HUD/weapon effects, which is what `BANK_SE` says it is. The bank is the
right bank; only the index into it is missing.
**If it is ever picked up**, the route is the running game, not the disc: watch
the guest hand a wave offset/length to the decoder when a cue fires. That is the
same instrumentation the cue↔event binding needs, and the same one this container
cannot run.