Commit Graph
3 Commits
Author SHA1 Message Date
ReaperOfVeriod 4ca0308499 SBlk body head: the DAW size, stored twice
Picked sound_bank rather than tie, where three discriminators have now come back
negative and a fourth would be guesswork.

The body after the 24-byte head opens with twelve words. Six are settled across
all 27 levels:

    word   value                 note
    0      varies per level      not identified; 27 distinct
    1      60                    constant
    2      varies per level      not identified; 23 distinct
    3      0                     constant
    4      daw_size              == the header's daw_size, exactly
    5      daw_size              the same value again
    6,7,8  0                     constant
    9      127                   constant
    10     1                     constant
    11     0                     constant

Level 0's words 4 and 5 are both 1,482,000, and daw_size is 1,482,000.

THE POINTER THAT WAS NOT ONE

Words 4 and 5 were briefly recorded as pointers into the DAW region. They are not.
The test that promoted them was "does this value fall inside [daw_offset,
daw_offset + daw_size)" -- and the DAW region is ~1.5 MB starting near the front of
a ~1.5 MB extent, so almost any plausible 32-bit word lands inside it. 1,482,000 is
merely just under the top of exactly that range.

A range test is not an identification. What survives is EQUALITY with daw_size,
exact on all 27 levels and asserted, which is a claim that can fail rather than one
that is almost always true.

That is the fourth time this session a plausible reading of a single number has had
to be withdrawn for something falsifiable: the 305x class-ID slot, the UV-corner
texcoords, the VIF code word, and now this. The pattern is consistent enough to be
worth stating as a rule -- a test that passes almost always is measuring the shape
of the data, not a property of it.

Word 0 gets one note: levels 1 and 4 hold 13,042,052 and 13,042,054, two apart,
while their daw_sizes differ by 63,504. Whatever it is, it is not a size.

The remainder of the SBlk body -- the per-sound record table -- is still undecoded,
so sound_bank stays open. A SBlkBodyHead struct carries the twelve words with the
constants asserted in its docs.

259 tests.
2026-10-14 03:06:36 +02:00
ReaperOfVeriod 28ab7e094b SBlk head characterised: four constants and one word that is not a count
sound_bank's head was parsed but never characterised. Across all 27 levels the
SBlk region opens identically for its first twelve bytes:

    +0x00 "SBlk"   +0x04 1   +0x08 4   +0x0c "DAW\0"   +0x10 0

and +0x14 is the only word that varies. It varies with its low sixteen bits zero
on all 27, leaving 0x0092..0x0103 -- 146 to 259.

That is the shape of a record count, and it tracks the body length at close to
100 bytes per unit. It is not one:

    body / field_14     91.2 .. 110.8 across 27 levels
    any stride 0..80 with body = stride*word + constant exactly:  no

So the test asserts the negative too. If a stride ever makes the relation exact
on all 27, sound_bank_sblk_head_is_constant_apart_from_one_word fails and asks
for the record size to be revisited. A near-miss at 100 bytes/record is exactly
what hardens into a name the next time somebody glances at it; the constants are
also checked individually so a real deviation names which one moved.

The DAW region begins with sixteen zero bytes then block-structured data with
16-byte periodicity and slowly varying nibbles -- consistent with block
compressed audio, not decoded. Recorded as such.

Two mistakes, both mine, both the same shape as earlier ones:

1. The constructor bound `format_tag` with a `let` BEFORE the two words that
   precede it in the file, consuming bytes 4..8 and shifting every field after
   it. The struct literal listed the names in the right order; the statements did
   not. A scratch script reading the same bytes gave the opposite answer, which
   is what exposed it. Fixed, with a comment, because "read the lets in file
   order" gets undone otherwise.

2. Inserting the new test ahead of an existing one stranded that test's #[test]
   on my doc comment -- silently unregistering
   tie_vertex_element_is_16_bytes_with_fixed_texcoords. This is the SAME mistake
   as two commits ago and I made it again. It again surfaced only as clippy's
   "never used" rather than as a missing test. Restored and verified by listing
   the registered tests rather than trusting the count.

240 tests, clippy clean, both tie vertex tests confirmed present.
2026-10-13 07:29:07 +02:00
ReaperOfVeriod 2dcc6e9710 Parse the sound bank container framing
A level's sound extent is two regions: an `SBlk` descriptor table and the
sample data that follows it. Four u32 at the head describe the layout, and
the invariant that establishes it is sblk_offset + sblk_size == daw_offset,
which holds on all 27 levels. That is what pins the field meanings; the
numbers alone are ambiguous about which of them is the offset.

DAW is a format tag inside the SBlk header, not a region signature. It
occurs exactly once in the entire extent, at sblk_offset + 12, naming the
sample format -- the sample data itself starts at daw_offset with no
signature at all, roughly 19 KB away on level 0. Reading it as a region
magic is the obvious reading and it is wrong.

daw_size never reaches the end of the file. The tail is positive on all 27
levels, 232 to 1,848 bytes, so the field describes less than the region
it names; the test asserts that direction rather than inventing a size
that fits.

523,720 SBlk and 37,649,008 DAW bytes across the 27 levels.

The sample format inside DAW is not decoded. It looks like VAG/ADPCM from
the nibble packing, and it has no bearing on drawing anything, so it stays
open rather than getting a half-answer.
2026-10-11 02:15:33 +02:00