Decode tfrag texture bindings, vertex colours and light records
Adds level_core.rs (the uncompressed core index header and texture table) and extends tfrag.rs with the data a draw call needs beyond geometry. An ad-gif is five A+D quadwords holding packed fields rather than GS registers; the level load rewrites them in place before drawing. On disc TEX0_1.data_lo indexes the level's texture table, TEX1_1.data_lo is the LOD bias K and data_hi the minification filter, and CLAMP_1 holds both wrap modes. Three things are easy to get wrong here: * K is a signed 12-bit value in 1/16 units, sign-extended by shifting the field up 4 and back down. Retail values are -137..-89 mip-scaled; reading it unsigned gives 1911 instead of -137. * TEX1_1.data_hi is MMIN, and 4 decodes as LinearMipmapNearest, not LinearMipmapLinear as the raw bit layout suggests. * RGBA and the light/normal records are not in the VIF lists at all. They sit at fixed offsets in the patch data block: rgba_size*4 colours at rgba_ofs, vert_count light records at light_ofs+0x10. The tfrag origin lives there too -- if no STROW row supplied one, the quadword at light_ofs is it. The texture table checks out on its own terms: 93 entries at index offset 0x2900 on level 0, and 0x2900 + 93*16 lands exactly on the next range. Verification: an ad-gif index outside the level's table would mean the geometry and the textures were misread independently, so every one is range-checked against real entries. All 27 levels: 47,950 ad-gifs over 18,102 patches, all in range, referencing 1429 of 1595 level texture entries (90%). Each patch's light array is exactly vert_count records and its RGBA array exactly rgba_size*4. Still open: LOD selection and morphing, and the texel data itself.
This commit is contained in:
+8
-3
@@ -20,7 +20,7 @@ early, while they are still cheap to retire.
|
||||
header, and the `data` extent is parsed as a container of byte ranges. The
|
||||
geometry decompresses: level 0 yields 16,969,296 bytes of level content
|
||||
from a 9.7 MB stream.
|
||||
- [ ] Next: tfrag texture bindings, then the geometry directory's class tables.
|
||||
- [ ] Next: tfrag LOD selection and morphing, then the first drawable frame.
|
||||
|
||||
The disc being the exact build the reference projects pin is the single
|
||||
biggest favourable fact so far: no disc conversion, no regional timing work,
|
||||
@@ -128,8 +128,13 @@ Phase 1 hands over the extents; this phase works out what each one contains.
|
||||
rather than positions. Every patch's strips expand to exactly its own
|
||||
`tri_count`: **18,102 patches, 809,879 triangles**, all indices in range.
|
||||
See `plan/level-assets.md` and `gc-formats::tfrag`.
|
||||
- [ ] tfrag shading inputs: the ad-gif texture bindings, per-vertex RGBA and
|
||||
light records, then the LOD switch and morph rules in `TfragProc`.
|
||||
- [x] **tfrag texture bindings and per-vertex data.** The ad-gifs decode to a
|
||||
texture index, wrap modes, minification filter and LOD bias; the level
|
||||
index gained a texture table (`level_core.rs`) for those indices to land
|
||||
in. Per-vertex RGBA and light/normal records recovered from their fixed
|
||||
offsets. All 27 levels: 47,950 ad-gifs, every index in range, 90% of the
|
||||
level texture tables referenced.
|
||||
- [ ] tfrag LOD selection: the switch and morph rules in `TfragProc`.
|
||||
- [ ] `gameplay` — begins `WAD` + a per-level byte, and does *not* decode with
|
||||
the WAD LZ77 decoder. All 27 levels fail identically, so the input is
|
||||
wrong rather than the decoder. Ruled out: bit order, header length, the
|
||||
|
||||
Reference in New Issue
Block a user