From 84d94337f79c0fe1dfebc9488ae616a135b75b1a Mon Sep 17 00:00:00 2001 From: ReaperOfVeriod Date: Fri, 9 Oct 2026 16:33:49 +0200 Subject: [PATCH] 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. --- docs/plan/level-assets.md | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/docs/plan/level-assets.md b/docs/plan/level-assets.md index 52e16e5..2207d0e 100644 --- a/docs/plan/level-assets.md +++ b/docs/plan/level-assets.md @@ -169,12 +169,38 @@ What is established about these records: GS packet headers rather than vertex data. - Bytes at 0x4c–0x4f repeat `ff 00 ff ff` on **every** record. -**Not yet determined:** the record layout. The values are not a straightforward -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 -field order has not been recovered, and a VIF packet interpretation of the -first tag (`0xfff5`, command `0x1f`, 53 words) runs off its data after 216 -bytes and does not chain. +### The record layout, as far as it is established + +```text +382 records of 64 bytes, from 0x40 to 0x5fc0 +``` + +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: