docs(re): add reverse-engineering knowledge base + conventions
Some checks failed
Some checks failed
Establish docs/re/ as the spec-side of the clean-room: - README: confidence tiers (HYPOTHESIS/PROBABLE/CONFIRMED), promotion requires NEW independent evidence, append-only evidence logs, demote-on-contradiction, and a clean-room firewall (describe behaviour + cite addresses; never paste decompiled code). Documents the toolchain (sylpheed.db + zq.py, xenia-rs probes, Wine-Canary oracle) and the join-by-guest-PC method with the VA-equality caveat. - Function/structure templates + a seeded INDEX (9 already-reversed formats). - First entry: texture-color-k8888 — CONFIRMED plain k_8_8_8_8 is linear UNORM (no sRGB), channel order still to be measured. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
38
docs/re/structures/texture-color-k8888.md
Normal file
38
docs/re/structures/texture-color-k8888.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# 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_8` → `VK_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.
|
||||
|
||||
### ❔ HYPOTHESIS — exact source **channel order** (needs measurement, do not infer)
|
||||
Our decoders currently assume on-disk **A8R8G8B8** and reorder `[a,r,g,b] → [r,g,b,a]`. Canary
|
||||
proves the *host* target is R8G8B8A8 identity-swizzled, but the *guest→host* byte order also depends
|
||||
on the texture's runtime **endian** field (e.g. `8in32`), which is set by the game at fetch time and
|
||||
**cannot be read statically** from the format table. So whether our reorder matches is unverified.
|
||||
→ *What would confirm/refute it:* one **measured** decoded texel — either capture Canary's
|
||||
framebuffer over a texture with distinct R≠G≠B pixels of known colour, or patch Canary's already-
|
||||
present-but-unwired `TextureDump` (`src/xenia/gpu/texture_dump.cc`) to dump the decoded texture and
|
||||
diff bytes against our decode. **Measure, don't guess** — a symmetric colour (white logo) can't
|
||||
disambiguate channel order.
|
||||
|
||||
## Evidence log
|
||||
- `2026-07-11` — static read of Canary `src/xenia/gpu/vulkan/vulkan_texture_cache.cc` host-format
|
||||
table + confirmed no `R8G8B8A8_SRGB` entry exists. → sRGB/UNORM claim `CONFIRMED`; channel-order
|
||||
claim remains `HYPOTHESIS` pending a measured texel.
|
||||
Reference in New Issue
Block a user