Decode level textures: 8-bit indices through a CSM1 palette
Adds texture.rs and makes the pipeline write gs_ram.bin, which it had been skipping. Nothing could be decoded before this: the CLUTs live there. A level texture is not pixels, it is palette indices -- width*height bytes at core_data[textures_base + data_offset], with colour coming from a 256-entry CLUT at gs_ram[palette * 0x100]. gs_ram is a byte range in the level's data extent header at offset 0x10, 518,656 bytes on level 0. Two PS2 conventions have to be honoured and neither is a design choice: within each 32-entry CLUT group the two middle 8-entry blocks are swapped (bits 3 and 4 of the index are exchanged, an involution), and alpha runs 0..=0x80 rather than 0..=255 with 0x80 fully opaque. The mip chain splits across two buffers: levels 0 and 1 are in the texture block with level 1 immediately after level 0, and levels 2 and 3 are resident in gs_ram at mipmap*0x100 and pad*0x100. Tfrag textures are square so every level halves evenly. Verification is two-layered, because every step here is a table lookup and a wrong CLUT remap still produces a well-formed image of the wrong thing. All 1,595 tfrag textures across all 27 levels decode; 96.8% are fully opaque and 96.3% use more than eight colours. On top of that, `gc-extract dump-texture` writes any texture or mip level as a PPM. Level 0 texture 0 comes back as a clean bevelled metal panel with rivets and specular highlights, and texture 74 as a vent grille whose punched windows are fully transparent. That tool is worth keeping: it is the cheapest way to tell a decode that is merely well-formed from one that is right. The hash table is regenerated for the 27 new gs_ram.bin files, now 5,186 files and 5,685,541,143 bytes.
This commit is contained in:
+8
-1
@@ -14,7 +14,7 @@ early, while they are still cheap to retire.
|
||||
- [x] Repository hygiene in place (pre-commit guard, `.gitignore`, licence
|
||||
record)
|
||||
- [x] **Phase 1 complete.** The disc pipeline runs end to end and is verified
|
||||
against a committed hash table: 5,135 files, 4,500,106,960 bytes, every
|
||||
against a committed hash table: 5,186 files, 5,685,541,143 bytes, every
|
||||
one of the 92 asset containers parsing.
|
||||
- [x] **Phase 2 in progress.** Level containers are parsed through their typed
|
||||
header, and the `data` extent is parsed as a container of byte ranges. The
|
||||
@@ -134,6 +134,13 @@ Phase 1 hands over the extents; this phase works out what each one contains.
|
||||
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.
|
||||
- [x] **Level textures decode.** 8-bit indexed texels plus a 256-entry CSM1
|
||||
CLUT from `gs_ram`, honouring the PS2 CLUT block swap and the 0x80 alpha
|
||||
scale. The pipeline now writes `gs_ram.bin`, which it had been skipping.
|
||||
All 1,595 tfrag textures on all 27 levels decode; 96.8% fully opaque and
|
||||
96.3% with real detail. Verified visually via the new
|
||||
`gc-extract dump-texture`, because a wrong lookup still yields a
|
||||
well-formed image of the wrong thing.
|
||||
- [ ] 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
|
||||
|
||||
Reference in New Issue
Block a user