diff --git a/docs/re/structures/slb-data-offset.md b/docs/re/structures/slb-data-offset.md index 16fb743..e024067 100644 --- a/docs/re/structures/slb-data-offset.md +++ b/docs/re/structures/slb-data-offset.md @@ -1,3 +1,38 @@ +> ✅✅ **SUPERSEDED IN ITS CAUSE (2026-08-26) — see branch `auto/slb-loader`.** +> The four offsets are **not a header size**. They are a *packing phase*: +> +> X = (cumulative start of the .pNN segment holding the bank) mod 2048 +> +> | segment | size | cumulative start | start mod 2048 | +> |---|---|---|---| +> | `sound.p00` | 267 930 992 | 0 | **0** | +> | `sound.p01` | 268 404 812 | 267 930 992 | **1392** | +> | `sound.p02` | 268 404 868 | 536 335 804 | **1468** | +> | `sound.p03` | 268 384 384 | 804 740 672 | **1600** | +> | `sound.p04` | 14 903 296 | 1 073 125 056 | **1728** | +> +> Independently reproduced here: the four values I measured are exactly the +> running sums of the five segment file sizes, mod 2048. The XMA grid is +> 2048-aligned *inside each `.pNN` file*; the segments are not multiples of 2048 +> long; so every join shifts the phase, and the flat concatenation the TOC +> addresses inherits the shift. +> +> Two things I wrote on this page are therefore wrong in their explanation, even +> though the measurements stand: +> +> * **"It varies by language and subdirectory"** — that was a *correlation*, not +> a cause. Directories cluster into segments, so the per-directory table is +> real but explains nothing. +> * **"The header is high-entropy content of a size the loader must know a +> priori"** — there is no header. Those bytes are the **previous bank's +> audio**, which is why they looked like data and had no length field: they +> are data. +> +> The heuristics below (99.62 % packet scan, 99.97 % `seek` residue, 99.95 % +> combined) are all superseded by an exact rule, verified 8 783/8 783 on the +> other branch. `slb.rs` still uses the heuristics; the exact fix needs +> `PakArchive` to expose the segment phase, which is an API change. + # `.slb` leading-stream data offset — 1392 was never a constant **✅ Settled 2026-08-26, verified by decoding.** A bank's leading headerless @@ -256,3 +291,40 @@ that opens a bank by name and seeks to its data; the constant, or the table it indexes, should be visible there. That is static PE work (`/work/*.pe`, offset = VA − 0x82000000), not another pass over the archive — this page has taken the byte-level evidence about as far as it goes. + + +## ⚠️ Disagreement on the declared-`data` question — not resolved + +`auto/slb-loader` **withdraws** the 🟡 finding above that 69.8 % of banks declare +more `data` than they store, reporting instead that declared sizes are exact +(260/260 checked) and that the extra bytes live outside the TOC window but still +in the `.pNN` stream — and specifically that `VOICE_TCAF_608` is not truncated. + +**I could not reproduce that, and the arithmetic is against it.** Walking that +bank's chunks gives a clean, internally consistent structure: + + window = [662 403 072, 662 456 412) size 53 340 + RIFF at +40 380, its size field 761 360 + fmt 32 + Dmmy 4 028 + data 759 808 <-- declared + +The next TOC entry begins at 662 458 368, i.e. **55 296 bytes** after this one +starts. 759 808 bytes of audio cannot fit there. They would have to span roughly +fourteen further TOC windows. + +Both readings agree on the underlying fact — **the declared size exceeds the +TOC window** — and differ on what follows from it. Mine said "truncated", which +was an over-claim I withdraw: the 1 928 non-zero bytes in the 1 956-byte gap +after the window, and the audio-looking bytes at the next entry, are consistent +with a bank's data simply continuing past its window. But "declared sizes are +exact" requires a wave to span many named entries, which is a much stronger +claim than "the bytes are outside the window". + +❔ **Unresolved.** The other branch's own open question — *"which bank in a window +belongs to the entry's name (some windows hold two, ids drift)"* — is the same +question from the other side, and settling it is what would decide this. +**First step**: take `VOICE_TCAF_608`, read 759 808 bytes from its `data` chunk +straight out of the flat stream ignoring window boundaries, and decode. If it +yields ~8 s of continuous speech, the data really does span windows; if it turns +to noise at the window edge, it does not.