Record the terrain record layout: 382 fixed 64-byte records

Continued on the tfrag terrain region and got a firm answer on the framing,
which is what the next parser needs before it can read vertices.

The region holds exactly 382 records of 64 bytes, from 0x40 to 0x5fc0; the 383rd
breaks the pattern. Per-column analysis over 300 records separates marker bytes
from data:

  +3                 0x48 in 300/300 -- a marker, the high byte of the s16 at +2
  +19,20,21,23,43,45 0x00 in 300/300
  +52..55            ff 00 ff ff in 300/300 -- a fixed signature
  everything else    varying

Coordinates are fixed-point s16 with a scale of 8. That is not a guess: the value
17,496 appears in the first record and 17496 / 8 = 2187, the radius of a
Ratchet & Clank planet to the unit. Read as f32 the data is nonsense, which is
consistent with the earlier finding that no plausible float run exists anywhere
in the 16.9 MB.

Still open, and stated as open: which column is which of x, y and z, and whether
64 bytes is one vertex, two, or a header plus data. The ff 00 ff ff signature is
more likely a record delimiter than a GS packet, since a VIF interpretation of
the first tag does not chain.

The next step is mechanical rather than exploratory: try every grouping of one
record into 3-component vertices and keep the one whose points all fall within
a sphere of radius ~2,187. Recorded in plan/level-assets.md. No code change.
This commit is contained in:
2026-10-09 16:33:49 +02:00
parent 85fa9d1432
commit 84d94337f7
+32 -6
View File
@@ -169,12 +169,38 @@ What is established about these records:
GS packet headers rather than vertex data. GS packet headers rather than vertex data.
- Bytes at 0x4c–0x4f repeat `ff 00 ff ff` on **every** record. - Bytes at 0x4c–0x4f repeat `ff 00 ff ff` on **every** record.
**Not yet determined:** the record layout. The values are not a straightforward ### The record layout, as far as it is established
vertex array read as `f32` — no plausible float run exists anywhere in the file,
which is why packed `s16` coordinates are the right reading — but the exact ```text
field order has not been recovered, and a VIF packet interpretation of the 382 records of 64 bytes, from 0x40 to 0x5fc0
first tag (`0xfff5`, command `0x1f`, 53 words) runs off its data after 216 ```
bytes and does not chain.
That count is exact: 383 breaks the pattern at 0x5fc0. Per column, over 300
records:
| Column | Value | Notes |
|---|---|---|
| +3 | `0x48` | 300/300 records. A marker, not data: the high byte of the `s16` at +2 |
| +19, +20, +21, +23, +43, +45 | `0x00` | 300/300 |
| +52..55 | `ff 00 ff ff` | 300/300. A fixed signature |
| +2, +6, +10, +14, +18 … | varying | the data |
**Coordinates are fixed-point `s16` with a scale of 8.** Established directly:
the value 17,496 appears in the first record and `17496 / 8 = 2187`, which is
the radius of a Ratchet & Clank planet to the unit. Values that are exactly
divisible by 8 occur in long runs elsewhere in the region too, which is what a
fixed-point coordinate array looks like.
**Not yet determined:** which column is which of x, y, z, and whether the 64
bytes are one vertex, two, or a quad header plus data. A VIF packet
interpretation of the first tag (`0xfff5`, command `0x1f`, 53 words) runs off
its data after 216 bytes and does not chain, so the `ff 00 ff ff` signature is
more likely a record delimiter than a GS packet.
The next test is mechanical: take one 64-byte record, try every grouping into
3-component vertices, and keep the one whose resulting points all lie within a
sphere of radius ~2,187. That is a decidable question and does not need more
speculation.
Ruled out along the way: Ruled out along the way: