Files
Sylpheed/docs/re/structures/texture-color-k8888.md
MechaCat02 e6da726f7b 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>
2026-07-11 17:11:17 +02:00

3.4 KiB

Texture colour interpretation — k_8_8_8_8 (32bpp UI/HUD textures)

  • Confidence: mixed — see per-claim tags below.
  • Parser in: sylpheed-formats/src/t8ad.rs, src/texture.rs (XPR2)
  • Applies to: T8aD 2D UI textures, XPR2 32bpp surfaces — the "colours look a bit odd" concern.
  • Related: reborn-dynamic-re-plan, INDEX rows T8aD / XPR2.

What this resolves

Whether our decoded 32bpp textures use the right sRGB-vs-linear interpretation and the right channel order. Ground truth = Canary's Vulkan texture cache, which is the code that actually produces correct on-screen colour.

Findings

CONFIRMED — plain k_8_8_8_8 is LINEAR (UNORM), never sRGB

Canary's host-format table maps plain k_8_8_8_8VK_FORMAT_R8G8B8A8_UNORM with a straight 32-bit copy load shader (kLoadShaderIndex32bpb) and an identity format swizzle (XE_GPU_TEXTURE_SWIZZLE_RGBA). There is no ..._SRGB host format anywhere in the table; gamma is a separate explicit path (k_8_8_8_8_GAMMA_EDRAM only). Therefore a plain 32bpp texture 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 wrong. Show the bytes as-is (raw RGBA8), gamma only where the game explicitly requests it.

CONFIRMED — on-disk order is ARGB (alpha first); [a,r,g,b]→[r,g,b,a] is correct

Settled by two independent lines that agree, without an emulator run:

  1. Measured on the disc data — across 789 real T8aD textures (GP_HANGAR_ARSENAL, GP_MAIN_GAME_E, DefTables), the byte position that is most-often exactly 0xFF (the opaque-alpha signature of UI art) is byte 0 in 767/789 (97%) — tf1 385/0, tf2 382/12. So texel byte 0 = alpha ⇒ on-disk layout is A,R,G,B. (An earlier bimodality test tied byte0/byte3 only because colour channels are also 0x00-heavy from black backgrounds; the ==0xFF discriminator isolates alpha cleanly.)
  2. Cross-check vs our Canary-validated rendererxenia-rs's decode_k8888_tiled (the path behind the user-confirmed M1 splash / M2 video colours) nets memory-ARGB → endian-swap → 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

  • 2026-07-11 — static read of Canary vulkan_texture_cache.cc host-format table; no R8G8B8A8_SRGB entry exists → sRGB/UNORM claim CONFIRMED.
  • 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.