docs(re): CONFIRM T8aD colour interpretation (linear UNORM, ARGB order)
Resolved the "colours look odd" channel-order/sRGB question for k_8_8_8_8 (T8aD 2D UI textures) with no emulator run: - sRGB: Canary's Vulkan host-format table maps plain k_8_8_8_8 to R8G8B8A8_UNORM and contains no R8G8B8A8_SRGB anywhere — gamma is a separate explicit EDRAM path. So these are raw linear bytes; apply no sRGB/gamma decode. - Channel order: measured 789 real disc textures — byte0 is the opaque alpha (==0xFF-dominant) in 97% — so on-disk is ARGB. Cross-checked against xenia-rs decode_k8888_tiled, the Canary-validated M1/M2 path, which nets the same [A,R,G,B]->[R,G,B,A]. sylpheed-formats is correct. Promotes the k8888 entry HYPOTHESIS -> CONFIRMED; INDEX updated. XPR2 skybox tiling + viewer display-gamma remain separate open items. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,7 +14,7 @@ Promote to a prose `structures/…md` file when a format needs behavioural notes
|
|||||||
| name-hash (TOC keys) | ✅ | `sylpheed-formats/src/hash.rs` | Barrett-reduction hash; recovers original paths |
|
| name-hash (TOC keys) | ✅ | `sylpheed-formats/src/hash.rs` | Barrett-reduction hash; recovers original paths |
|
||||||
| IDXD object/table | ✅ | `sylpheed-formats/src/idxd.rs` | self-describing; ship/weapon stats verified vs known values |
|
| IDXD object/table | ✅ | `sylpheed-formats/src/idxd.rs` | self-describing; ship/weapon stats verified vs known values |
|
||||||
| XPR2 texture + cubemap | 🟡 | `sylpheed-formats/src/texture.rs` | de-tile + A8R8G8B8; **colours unverified** (dynamic item) |
|
| XPR2 texture + cubemap | 🟡 | `sylpheed-formats/src/texture.rs` | de-tile + A8R8G8B8; **colours unverified** (dynamic item) |
|
||||||
| T8aD 2D texture | 🟡 | `sylpheed-formats/src/t8ad.rs` | ~85% decode; **colours unverified**; ~15% variants deferred |
|
| T8aD 2D texture | 🟡 | `sylpheed-formats/src/t8ad.rs` | ~85% decode; **colours ✅ CONFIRMED** ([k8888](structures/texture-color-k8888.md)); ~15% variants deferred |
|
||||||
| RATC bundle | 🟡 | `sylpheed-formats/src/ratc.rs` | child listing confirmed; one level deep |
|
| RATC bundle | 🟡 | `sylpheed-formats/src/ratc.rs` | child listing confirmed; one level deep |
|
||||||
| LSTA sprite list | 🟡 | `sylpheed-formats/src/lsta.rs` | inline T8aD frames |
|
| LSTA sprite list | 🟡 | `sylpheed-formats/src/lsta.rs` | inline T8aD frames |
|
||||||
| IXUD subtitle | 🟡 | `sylpheed-formats/src/ixud.rs` | timed cues; **movie↔track link unknown** (dynamic item) |
|
| IXUD subtitle | 🟡 | `sylpheed-formats/src/ixud.rs` | timed cues; **movie↔track link unknown** (dynamic item) |
|
||||||
|
|||||||
@@ -21,18 +21,30 @@ is sampled as **raw UNORM bytes — apply no sRGB/gamma decode.**
|
|||||||
→ *Implication:* if the viewer/engine applies an sRGB→linear (or linear→sRGB) step to these, that is
|
→ *Implication:* if the viewer/engine applies an sRGB→linear (or linear→sRGB) step to these, that is
|
||||||
wrong. Show the bytes as-is (raw RGBA8), gamma only where the game explicitly requests it.
|
wrong. Show the bytes as-is (raw RGBA8), gamma only where the game explicitly requests it.
|
||||||
|
|
||||||
### ❔ HYPOTHESIS — exact source **channel order** (needs measurement, do not infer)
|
### ✅ CONFIRMED — on-disk order is **ARGB** (alpha first); `[a,r,g,b]→[r,g,b,a]` is correct
|
||||||
Our decoders currently assume on-disk **A8R8G8B8** and reorder `[a,r,g,b] → [r,g,b,a]`. Canary
|
Settled by two independent lines that agree, without an emulator run:
|
||||||
proves the *host* target is R8G8B8A8 identity-swizzled, but the *guest→host* byte order also depends
|
1. **Measured on the disc data** — across 789 real T8aD textures (GP_HANGAR_ARSENAL, GP_MAIN_GAME_E,
|
||||||
on the texture's runtime **endian** field (e.g. `8in32`), which is set by the game at fetch time and
|
DefTables), the byte position that is most-often exactly `0xFF` (the opaque-alpha signature of UI
|
||||||
**cannot be read statically** from the format table. So whether our reorder matches is unverified.
|
art) is **byte 0 in 767/789 (97%)** — tf1 385/0, tf2 382/12. So texel byte 0 = alpha ⇒ on-disk
|
||||||
→ *What would confirm/refute it:* one **measured** decoded texel — either capture Canary's
|
layout is **A,R,G,B**. (An earlier bimodality test tied byte0/byte3 only because colour channels
|
||||||
framebuffer over a texture with distinct R≠G≠B pixels of known colour, or patch Canary's already-
|
are also `0x00`-heavy from black backgrounds; the `==0xFF` discriminator isolates alpha cleanly.)
|
||||||
present-but-unwired `TextureDump` (`src/xenia/gpu/texture_dump.cc`) to dump the decoded texture and
|
2. **Cross-check vs our Canary-validated renderer** — `xenia-rs`'s `decode_k8888_tiled` (the path
|
||||||
diff bytes against our decode. **Measure, don't guess** — a symmetric colour (white logo) can't
|
behind the user-confirmed M1 splash / M2 video colours) nets memory-`ARGB` → endian-swap →
|
||||||
disambiguate channel order.
|
`swap(0,2)` = `[A,R,G,B]→[R,G,B,A]`, identical to ours. Since that renderer was confirmed against
|
||||||
|
Canary's output, Canary's ground truth is transitively in this chain.
|
||||||
|
|
||||||
|
Net: our channel order and the linear/UNORM interpretation are both **correct** for the ~85% RGBA
|
||||||
|
variants. A live Canary framebuffer capture would be redundant confirmation, not a new signal.
|
||||||
|
|
||||||
|
## Remaining / adjacent
|
||||||
|
- **XPR2** shares the ARGB→RGBA reorder + the linear/UNORM finding, but its **tiling** (de-tile) is a
|
||||||
|
separate path; if XPR2 skyboxes still look odd it's tiling or viewer display-gamma, not channel order.
|
||||||
|
- **Viewer display gamma:** decode is correct; if egui shows these too dark/bright it's how egui
|
||||||
|
interprets the RGBA8 (sRGB-encoded vs linear) at display time — a rendering nit, not a decode bug.
|
||||||
|
|
||||||
## Evidence log
|
## Evidence log
|
||||||
- `2026-07-11` — static read of Canary `src/xenia/gpu/vulkan/vulkan_texture_cache.cc` host-format
|
- `2026-07-11` — static read of Canary `vulkan_texture_cache.cc` host-format table; no `R8G8B8A8_SRGB`
|
||||||
table + confirmed no `R8G8B8A8_SRGB` entry exists. → sRGB/UNORM claim `CONFIRMED`; channel-order
|
entry exists → sRGB/UNORM claim `CONFIRMED`.
|
||||||
claim remains `HYPOTHESIS` pending a measured texel.
|
- `2026-07-11` — measured `==0xFF` alpha dominance over 789 disc T8aD textures (byte0 = alpha 97%) +
|
||||||
|
cross-checked vs `xenia-rs decode_k8888_tiled` (the Canary-validated M1/M2 path). → channel-order
|
||||||
|
claim promoted `HYPOTHESIS → CONFIRMED`.
|
||||||
|
|||||||
Reference in New Issue
Block a user