Narrow the collision header to two fields plus a third used by five levels

Range measured: all 27 levels that carry collision, reading the 0x40-byte
header each.

Method: read +0x00, +0x04 and +0x08, then check +0x08..+0x40 for zero.

Result:

  u32@+0x00 is 0x40 on 27 of 27 -- the header is self-sizing
  u32@+0x04 is the payload size, 20 distinct values across the disc
  bytes +0x08..+0x40 zero on 22 of 27

Five levels carry a large non-zero word at +0x08:

  level  7  1248048        level 12  2541616
  level  9  1766832        level 13  3376592
                      level 14  4060640

So the header is not two fields and 56 bytes of padding: there is a third field
most levels leave at zero and five use. Whether it is a size, an offset or a
second block's length is not established, and nothing measured here separates
those readings. Exposed as CollisionHeader::field_08.

Correction: the collision header was previously described as self-describing
across its full 0x40, which is true for 22 levels and overstates the case for
the other five.

Still not decoded: the payload. It contains ascending u32 runs on levels 0 and
2 -- level 0 at +280 with deltas 12, 12, 12 then a jump, level 2 at +13868 with
deltas 204, 204, 200, 196 -- but irregular deltas fit neither a flat table nor a
simple stride, and level 1's apparent run is a byte-shift false positive.
Nothing about the payload is asserted.
This commit is contained in:
2026-10-12 02:49:25 +02:00
parent 51348b214d
commit 5610d173b0
2 changed files with 49 additions and 0 deletions
+11
View File
@@ -27,6 +27,15 @@ pub struct CollisionHeader {
pub header_size: u32,
/// Size of the payload that follows.
pub payload_size: u32,
/// The word at `+0x08`.
///
/// Measured on all 27 levels that carry collision: the rest of the 0x40
/// header is zero padding on 22 of them, but **5 levels carry a large
/// non-zero word here** -- 1,248,048, 1,766,832, 2,541,616, 3,376,592 and
/// 4,060,640, on levels 7, 9, 12, 13 and 14. Meaning not established; it
/// is a size, an offset, or a second block's length, and nothing here
/// distinguishes those.
pub field_08: u32,
}
impl CollisionHeader {
@@ -39,6 +48,7 @@ impl CollisionHeader {
Ok(CollisionHeader {
header_size: b.u32("collision header size")?,
payload_size: b.u32("collision payload size")?,
field_08: b.u32("collision +0x08")?,
})
}
}
@@ -108,6 +118,7 @@ mod tests {
const BASE: usize = 16;
fn core(header_size: u32, payload_size: u32) -> Vec<u8> {
#[allow(clippy::let_and_return)]
let mut v = vec![0u8; BASE + 64];
v[BASE..BASE + 4].copy_from_slice(&header_size.to_le_bytes());
v[BASE + 4..BASE + 8].copy_from_slice(&payload_size.to_le_bytes());