From a4cf037ac0088b4de9ca6044bfc182fe6beb37a8 Mon Sep 17 00:00:00 2001 From: Sylpheed RE agent Date: Wed, 26 Aug 2026 03:34:28 +0000 Subject: [PATCH] re: census of sound.pak, and the leading-region rule is English-only Every FILES path hashes straight into the sound.pak TOC (5135/5135, path as stored). The archive is then almost fully accounted for: 5100 jpn + 4382 eng + 35 BGM/JNGL = 9517 of 9519. Only eng and jpn resolve -- deu/fra/ita/esp give zero, which is the archive-side measurement behind 'two voice sets shipped'. 718 Japanese banks have no English counterpart. More importantly this bounds an existing result. The leading-region rule from voice-bank-leading-region.md reproduces its five documented banks EXACTLY under eng\etc\ (16384/2048/14336/45056/59392), so the pipeline is sound -- but it holds for only 1571 of 4382 English banks and for ZERO of 5100 Japanese ones. It is a property of some English banks, not of .slb in general, and the Japanese layout is undecoded. I nearly misread this as a broken extractor, because FILES lists jpn paths and those gave non-multiples of 2048. Reproducing the recorded figures exactly under eng is what distinguished a wrong assumption from a wrong reader. --- docs/re/structures/sound-pak-contents.md | 97 ++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 docs/re/structures/sound-pak-contents.md diff --git a/docs/re/structures/sound-pak-contents.md b/docs/re/structures/sound-pak-contents.md new file mode 100644 index 00000000..ae38c90e --- /dev/null +++ b/docs/re/structures/sound-pak-contents.md @@ -0,0 +1,97 @@ +# What is actually in `sound.pak` — and the language substitution + +**✅ Settled 2026-08-26.** `sound.pak`'s 9 519 entries are almost entirely +accounted for: the Japanese voice set, the English voice set, and 35 music / +jingle banks. The `FILES` record in `tables.pak` names the Japanese half, and +the game reaches the English half by **substituting the leading directory**. + +Until now the corpus described `sound.pak` as "~9 519 headerless entries, params +in an unknown table". The table is +[`sound-cue-table.md`](sound-cue-table.md), and this page is the census. + +## The name is the key + +Every path in `FILES` hashes straight into the `sound.pak` TOC with +`name_hash` — **5 135 of 5 135**, using the path exactly as stored +(backslashes, case-insensitive): + + jpn\etc\VOICE_D_257.slb -> name_hash -> TOC entry (offset, size) + +No transformation, no prefix, no stem. Taking the basename instead resolves only +35 — precisely the 35 root-level `BGM_*` / `JNGL_*` banks whose basename *is* +their path, which is the control that shows the full path is what matters. + +This is not luck: the hash's low 24 bits are a residue mod `0x00FFF9D7` and the +top byte is a byte-sum, so for 5 135 probes against 9 519 occupied slots the +expected number of accidental hits is about **0.01**. + +## The census + +| what | entries | +|---|---| +| `jpn\…` — named directly by `FILES` | 5 100 | +| `eng\…` — the same names with the directory substituted | 4 382 | +| `BGM_*.slb`, `JNGL_*.slb` at the root | 35 | +| **total accounted** | **9 517** | +| TOC total | 9 519 | + +**2 entries are unaccounted for.** I did not identify them. + +Only `eng` and `jpn` resolve. `deu`, `fra`, `ita`, `esp` and the alternative +spellings `fre`/`ger`/`spa` produce **zero** hits, which is the measurement +behind the claim that only two voice sets are shipped — the other four languages +are subtitle-only. + +**718 of the 5 100 Japanese banks have no English counterpart.** That is +consistent with the previously recorded finding that a set of lines exists only +undubbed, and it puts a number on it from the archive side. + +## ⚠️ The leading-region rule is English-only + +This is the part that matters most, and it bounds an existing result. + +[`voice-bank-leading-region.md`](../voice-bank-leading-region.md) established +the hybrid layout: a bank may carry a leading headerless XMA1 region before its +first `RIFF`, recognised by the first `RIFF` sitting exactly at +`1392 + n·2048`. That was derived from `VOICE_D_450`–`454`, and it reproduces +**exactly** — all five, at 16 384 / 2 048 / 14 336 / 45 056 / 59 392 bytes, +matching the recorded figures to the byte. The pipeline is sound. + +But those five are `eng\etc\` banks, and the rule does not generalise: + +| set | aligned | misaligned | no `RIFF` | first `RIFF` ≤ 1392 | +|---|---|---|---|---| +| `eng\…` (4 382) | **1 571** | 2 060 | 696 | 55 | +| `jpn\…` (5 100) | **0** | 4 301 | 799 | — | + +**Not one of the 5 100 Japanese banks satisfies the alignment condition.** The +rule describes a third of the English set and none of the Japanese set. + +Being careful about what that does and does not mean: "misaligned" only means +the leading-segment branch does not fire, and `to_xma_riffs` still walks the +bank's sub-waves normally — so this is not evidence that those banks are +broken. What it does mean is that **the leading-region finding is a property of +some English banks, not of `.slb` in general**, and any code or documentation +that treats it as the bank format is overreaching. The Japanese banks are +laid out differently and that layout is **not decoded**. + +## How I nearly got this wrong + +I first resolved the five documented banks through their `FILES` paths, which +are `jpn\etc\…`, and got leading regions of 59 600 / — / 6 352 / 14 544 / +28 880 — none a multiple of 2 048, none matching the recorded figures. The +tempting reading was that my extraction was broken. The alignment condition is +what said otherwise: a broken reader would not produce *exactly* the recorded +numbers for `eng\etc\`, which it then did, for all five. The extraction was +right and the assumption that `FILES`' path was the one the corpus had measured +was wrong. + +## What this does not settle + +* **The 2 unaccounted TOC entries.** +* **The Japanese bank layout.** 4 301 banks have a `RIFF` at an unaligned + offset and 799 have none at all; neither shape has been decoded, and no + Japanese bank has been decoded to audio here. +* **Why 55 English banks have their first `RIFF` at or before 1392**, inside + what the headerless reading treats as the header. +* **Nothing here was run.** This is a static census of the archive.