Decode the tie LOD block header; establish the payload is variable-length
TieBlockHeader parses the block's own 16 bytes, measured over the 922 blocks where "the next packets offset ends this block" holds, across all 27 levels. A real-disc test asserts every figure. +0x00 count multiple of 16 on 922/922; 16..2096; 72 distinct disc-wide +0x02 zero on 922/922 +0x04 ONE OF FOUR VALUES DISC-WIDE: 0x501, 0xa02, 0xf03, 0x1404 +0x06 15 distinct, 0x0206..0x0512 +0x08 135 distinct, 0x0b05..0x4ee4 +0x0a 45 distinct +0x0c 94 distinct, 0x010e..0x0553 +0x0e zero on 914/922 +0x04 is packed rather than a magnitude: four values across the whole disc with the two bytes moving independently, low 1-4 and high 5/10/15/20 in lockstep. That it is a texture index paired with a scale is a guess; that it is two fields is not. The count is not a record count -- block_size minus the header is divisible by it on 0 of 922, for any record size and any header up to 512 bytes. On the payload, a control was needed and changed the answer. Reading blocks as 3 x f32 triples, 53-64% of reads land within +/-5000 of origin, against 16% for a uniform-random control of identical length. So the content is float-shaped and genuinely not random. But the rate is flat across every start offset and every stride tried, 53-65% throughout. A statistic that cannot separate the right stride from the wrong one cannot identify a stride -- rule 4's exact case. Flatness plus a count that does not tile means the records are variable length. That killed two readings. A VIF1 command walk consumes 0 of 88 blocks exactly, so it is not a VIF1 CPU-format stream. wad::decompress rejects the block at every start offset, so it is not WAD LZ77. Scanning every (start, stride) pair from 0x10 to 0x7f for byte positions with a small distinct-value vocabulary finds none: every position takes all 256 values at every alignment. For float payload that is expected, so the scan found nothing rather than confirming anything -- worth saying, because "no fields found" here is uninformative, not evidence against fields. Still open: what the payload holds. Established: variable-length, float-shaped, non-random, not LZ77, not VIF1. Not established: any record boundary.
This commit is contained in:
@@ -1166,3 +1166,58 @@ the kind of field that gets mistaken for a pointer. It is now
|
||||
**Still not decoded:** what the 16 bytes hold. `i16[0]` at `+4` takes 8,969
|
||||
distinct values on level 0 and is not the two-valued field a 12-unit sample
|
||||
suggested; the word at `+0` is not a run offset.
|
||||
|
||||
## tie: the LOD block header, decoded
|
||||
|
||||
Over the **922** blocks where "the next `packets` offset ends this block" holds,
|
||||
the block's own 16-byte header is measured. `gc_formats::tie::TieBlockHeader`
|
||||
parses it and a real-disc test asserts every line below.
|
||||
|
||||
+0x00 u16 count multiple of 16 on 922/922; range 16..2096;
|
||||
72 distinct values disc-wide
|
||||
+0x02 u16 zero on 922/922
|
||||
+0x04 u16 ONE OF FOUR VALUES DISC-WIDE: 0x501, 0xa02, 0xf03,
|
||||
0x1404 -- low byte 1..4, high byte 5/10/15/20
|
||||
+0x06 u16 15 distinct, 0x0206..0x0512
|
||||
+0x08 u16 135 distinct, 0x0b05..0x4ee4
|
||||
+0x0a u16 45 distinct
|
||||
+0x0c u16 94 distinct, 0x010e..0x0553
|
||||
+0x0e u16 zero on 914/922
|
||||
|
||||
**`+0x04` is packed, not a magnitude.** Four values across the whole disc, with
|
||||
the two bytes moving independently (low 1-4, high 5/10/15/20 in lockstep), is two
|
||||
small fields sharing a word. That it is a texture index paired with a scale is a
|
||||
guess; that it is two fields is not.
|
||||
|
||||
**The count is not a record count.** `block_size - header` is divisible by it on
|
||||
**0 of 922** blocks, for *any* record size and *any* header up to 512 bytes.
|
||||
Combined with block sizes always being multiples of 16, that rules out a uniform
|
||||
stride without a header.
|
||||
|
||||
### What the payload is, and what retired the coordinate reading
|
||||
|
||||
The payload is **not random**, and that took a control to establish. Reading each
|
||||
block as 3 x `f32` triples, 53-64% of reads land within +/-5000 of origin; a
|
||||
uniform-random control of identical length gives **16%**. So the content really
|
||||
is float-shaped.
|
||||
|
||||
But the rate is **flat across every start offset and every stride tried**
|
||||
(0x10..0x40 start, 8/12/16/20/24 stride: 53-65% throughout). A statistic that
|
||||
cannot distinguish the right stride from the wrong one cannot identify a stride,
|
||||
which is rule 4's exact case. The flatness is the informative part: combined
|
||||
with the count not tiling, it says the records are **variable length**.
|
||||
|
||||
A VIF1 command walk was implemented and tested against the blocks: it consumes
|
||||
**0 of 88** exactly. So the payload is variable-length and not a VIF1 CPU-format
|
||||
stream. Not WAD LZ77 either -- `wad::decompress` rejects the block at every
|
||||
start offset tried.
|
||||
|
||||
Scanning every (start, stride) pair from 0x10 to 0x7f for byte positions with a
|
||||
small distinct-value vocabulary -- the signature of integer index fields -- finds
|
||||
**none**: every byte position takes all 256 values at every alignment. For float
|
||||
payload that is expected, and it is why the field scan found nothing rather than
|
||||
confirming anything.
|
||||
|
||||
**Still open: what the payload holds.** Established is that it is variable-length,
|
||||
float-shaped, non-random, not LZ77, and not VIF1. Not established is any record
|
||||
boundary.
|
||||
|
||||
Reference in New Issue
Block a user