From 0800e40c80f91f0667dfd8a78440df9decb9a69d Mon Sep 17 00:00:00 2001 From: Sylpheed RE agent Date: Wed, 26 Aug 2026 06:39:40 +0000 Subject: [PATCH] re: lead the .slb page with its settled state, not its history The page is 724 lines of chronological record across 16 sections, several of them superseded readings kept for their reasoning. A reader arriving fresh had to read all of it to know what is currently true. Adds a summary table at the top covering the twelve questions the page answers, each with its confidence, plus the wave-enumeration recipe and an explicit note that everything below is history. Also names the four mistakes recorded below so a reader knows they are deliberate rather than stale. --- docs/re/structures/slb-data-offset.md | 33 +++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/docs/re/structures/slb-data-offset.md b/docs/re/structures/slb-data-offset.md index 7123db12..3e667faa 100644 --- a/docs/re/structures/slb-data-offset.md +++ b/docs/re/structures/slb-data-offset.md @@ -41,6 +41,39 @@ packet stream does not start at a fixed offset. It starts at offset happens to take in `\etc\`, and assuming it everywhere starts the decode mid-packet and throws away almost all of the audio. +## Read this first — the settled state of the `.slb` container + +This page grew as a **chronological record**, and several of its sections are +superseded readings kept for their reasoning. Everything below the summary is +history; this table is what is currently true. + +| question | answer | confidence | +|---|---|---| +| where a bank's headerless stream starts | `first_riff % 2048`, or `scan_data_offset` when there is no `RIFF` | ✅ | +| why that takes four values (1392/1468/1600/1728) | it is a **packing phase**: `(cumulative .pNN segment start) mod 2048`. Not a header. | ✅ | +| what the bytes before it are | the **previous bank's audio** | ✅ | +| where a wave **ends** | `data_at + declared_size`, confirmed by `seek` magic there — **7 620/7 620** | ✅ | +| are the declared `data` sizes honest | **yes**. The TOC window is not the wave boundary. | ✅ | +| a wave's **length in seconds** | `data_bytes / PsuedoBytesPerSec`. **Not** the seek table's sample total, which understates by a median 9.7 %. | ✅ | +| channel count | the byte at `RIFF + 49`. **2.12 % are stereo**; forcing mono yields one frame. | ✅ | +| `seek` chunk layout | `+4` size LE (`8 + 4·packets`), `+8` stream count, `+12` **packet count LE**, `+16` cumulative sample table | ✅ | +| which wave an entry names | the first wave starting at/after its offset, or the second when a leading wave + 12 288-byte block precedes — **7 620/7 620** | ✅ | +| the 12 288-byte block | `seek` chunk + a cue-shaped record + sparse zeros; its first two words are `table[-2]`, `table[-1]` | ✅ / 🟡 | +| what the block's id field refers to | a real cue, but **not** this entry's and **not** a chain | ❔ | +| headerless bank durations | **unrecoverable** — no `seek` table to read, and the first `seek` in the entry usually belongs to the previous bank | ❔ | + +**Enumerating every wave without the TOC**: scan the flat stream for `seek`, +keep chunks where `size == 8 + 4·count` and `seek_pos − count·2048 ≥ 0`. That +yields **9 661 waves with zero false positives** across 1.01 GB. + +**Four mistakes of mine are recorded below rather than deleted**, because each +one's reasoning is the useful part: reading the packet count big-endian; +believing a one-frame decode meant missing audio (it meant stereo); using the +seek table's sample total as a duration; and refuting the leading-segment +hypothesis with a predicate that was wrong by a constant I had not yet found. + +--- + ## The rule XMA1 packets are 2048 bytes and the leading stream is a whole number of them