Parse the sky block: 149 sub-objects with a bounding sphere, and correct the count field
Range measured: all 27 levels, each sky region from the core index's sky offset to the next region. Method: read the 32-bit offset table at +0x20, bounded by staying inside the region, and parse each sub-object it names. Result: 149 sub-objects across 27 levels. Each opens with a count, then a bounding sphere of four floats at +0x10, then a texture offset at +0x20 and dimensions at +0x24/+0x26: +000: 26 00 00 00 | 00 00 00 00 00 00 00 00 00 00 00 00 +010: e0 8d b2 c1 | 9f d6 f6 3d | ef fc fb be | 1c 61 4e 41 +020: 90 99 05 00 | 1d 00 | 1d 00 | 00 00 e8 00 ... Count 1 to 38, width 3 to 81, radius 1.95 to 14.56, and the radius is positive on 149 of 149 -- the same sphere shape and the same reasoning as the shrub class header's. Correction to an earlier claim: the word at +0x0c is not the sub-object count. It reads 5 on level 0 where the table holds 6 entries, 3 on level 1 against 4, 7 on level 3 against 8, and 196617 on level 2 against 4. Across the disc offsets.len() == count+1 holds on 10 of 27 levels. The field is reported as SkyHeader::field_0c and nothing depends on it; the offset table enumerates the sub-objects and is self-limiting. That earlier claim came from level 0 alone, where 5 against 6 looked like a consistent off-by-one. It is not an off-by-one -- it is a field that happens to be small on most levels and is not a count at all. gc_formats::sky parses the header and the sub-objects. The gated test asserts the sphere is finite, the radius positive where positive at all, the dimensions non-zero, and the sub-object list non-empty on every level.
This commit is contained in:
@@ -1296,3 +1296,38 @@ signature; the RAM header is populated state.
|
||||
`ShrubPacketHeader::parse` and `Shrub::packet_headers()` expose this, and the
|
||||
gated test asserts all four invariants plus the size alignment on every packet
|
||||
of every bounded span.
|
||||
|
||||
## Sky: the sub-object table, and a count field that is not a count
|
||||
|
||||
**Range measured:** all 27 levels, each sky region from the core index's `sky`
|
||||
offset to the next region.
|
||||
|
||||
**Method:** read the 32-bit offset table at `+0x20`, bounded by staying inside
|
||||
the region, and parse each sub-object it names.
|
||||
|
||||
**Result: 149 sub-objects across 27 levels.** Each opens with a count, then a
|
||||
bounding sphere of four floats at `+0x10`, then a texture offset at `+0x20` and
|
||||
dimensions at `+0x24`/`+0x26`:
|
||||
|
||||
+000: 26 00 00 00 | 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
+010: e0 8d b2 c1 | 9f d6 f6 3d | ef fc fb be | 1c 61 4e 41
|
||||
+020: 90 99 05 00 | 1d 00 | 1d 00 | 00 00 e8 00 ...
|
||||
|
||||
Count 1 to 38, width 3 to 81, radius 1.95 to 14.56, and the radius is positive
|
||||
on **149 of 149** -- the same sphere shape and the same reasoning as the shrub
|
||||
class header's.
|
||||
|
||||
**Correction to an earlier claim.** The word at `+0x0c` is **not** the
|
||||
sub-object count. It reads 5 on level 0 where the table holds 6 entries, 3 on
|
||||
level 1 against 4, 7 on level 3 against 8, and 196,617 on level 2 against 4.
|
||||
Across the disc `offsets.len() == count + 1` holds on **10 of 27** levels. The
|
||||
field is reported as `SkyHeader::field_0c` and nothing depends on it; the
|
||||
offset table enumerates the sub-objects and is self-limiting.
|
||||
|
||||
That earlier claim came from level 0 alone, where 5 against 6 looked like a
|
||||
consistent off-by-one. It is not an off-by-one -- it is a field that happens to
|
||||
be small on most levels and is not a count at all.
|
||||
|
||||
`gc_formats::sky` parses the header and the sub-objects, and the gated test
|
||||
asserts the sphere is finite, the radius positive where it is positive at all,
|
||||
the dimensions non-zero, and the sub-object list non-empty on every level.
|
||||
|
||||
Reference in New Issue
Block a user