re: XPR2 channel order confirmed against the running game -- the second "dynamic unknown" closed
INDEX carried XPR2 as "colours unverified (dynamic item)". The failure mode that matters is a swapped red/blue channel: invisible on greys, invisible without ground truth, and it poisons every asset silently. Method: pick an asset that is strongly asymmetric in hue and has known in-game appearance. DeltaSaber_T.xpr (1024x1024 Dxt1, 11 mips) decodes to white/grey panels with orange-rust accents; the game renders the same hull in the ARSENAL scene. decoded texture : 1073 warm px, 0 cool, median saturated hue 23.3 deg in-game render : 916 warm px, 124 cool, median saturated hue 9.3 deg Both orange/red; a red<->blue swap would put the texture at ~200 deg. The cool pixels are the blue UI behind the model and the 14 deg offset is the hangar's red key light -- neither can move a hue by 180. Stated as a bounded result, not "colours are correct": a hue-family comparison cannot see a gamma/sRGB error, premultiplied alpha, or a per-channel scale, so exact fidelity stays open and needs a flat unlit known-value surface. Cubemap face ordering untouched. BG_Earth.xpr (A8R8G8B8 cubemap face) decoding to a coherent nebula is corroboration for the de-tile step, not proof. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,7 +13,7 @@ Promote to a prose `structures/…md` file when a format needs behavioural notes
|
|||||||
| IPFB `.pak` archive | ✅ | `sylpheed-formats/src/pak.rs` + `tests/pak_idxd_disc.rs` | header + 12-byte TOC, Z1/zlib payloads |
|
| IPFB `.pak` archive | ✅ | `sylpheed-formats/src/pak.rs` + `tests/pak_idxd_disc.rs` | header + 12-byte TOC, Z1/zlib payloads |
|
||||||
| 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` + [colour check](xpr2-colour-check.md) | de-tile + A8R8G8B8 and DXT1. **Channel order ✅ confirmed against the running game**: the Delta Saber's decoded atlas is orange-dominant (median saturated hue 23.3°, *zero* cool pixels) and the game renders the same hull at 9.3° — a red↔blue swap would sit at ≈200°. Exact fidelity (gamma/sRGB curve, premultiplied alpha, per-channel scale) is 🟡 untested, since a hue comparison cannot see it; cubemap face ordering ❔ |
|
||||||
| T8aD 2D texture | 🟡 | `sylpheed-formats/src/t8ad.rs` | ~85% decode; **colours ✅ CONFIRMED** ([k8888](structures/texture-color-k8888.md)); ~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 |
|
||||||
|
|||||||
BIN
docs/re/captures/xpr2-colour-check-deltasaber.png
Normal file
BIN
docs/re/captures/xpr2-colour-check-deltasaber.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 580 KiB |
51
docs/re/xpr2-colour-check.md
Normal file
51
docs/re/xpr2-colour-check.md
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# XPR2 colours: channel order ✅ confirmed against the running game
|
||||||
|
|
||||||
|
[`INDEX`](INDEX.md) carried XPR2 as 🟡 with **"colours unverified (dynamic
|
||||||
|
item)"**. The failure mode that matters for a texture decoder is a **swapped red
|
||||||
|
and blue channel** — it is invisible on greys and on anything you have no ground
|
||||||
|
truth for, and it silently poisons every asset. This settles that one, and is
|
||||||
|
explicit about what it does *not* settle.
|
||||||
|
|
||||||
|
## Method
|
||||||
|
|
||||||
|
Pick an asset whose in-game appearance is unambiguous and **strongly
|
||||||
|
asymmetric in hue** — the Delta Saber's livery is white/grey panels with
|
||||||
|
orange-rust accents, so a red↔blue swap would render it cyan. Then compare the
|
||||||
|
decoded texture against the game rendering the same asset.
|
||||||
|
|
||||||
|
- **Decoded:** `hidden/resource3d/DeltaSaber_T.xpr` — 1024×1024, **Dxt1**, 11 mip
|
||||||
|
levels — exported with `sylpheed-cli texture export`.
|
||||||
|
- **In-game:** the Delta Saber standing in the ARSENAL scene, captured at
|
||||||
|
`x 700..830, y 180..480` of the framebuffer so the crop is hull, not UI.
|
||||||
|
|
||||||
|
Both images were resampled to 96×96 and every pixel classified; for the
|
||||||
|
saturated pixels (`max−min ≥ 50`) the median hue was taken.
|
||||||
|
|
||||||
|
| | warm px (`R > B+40`) | cool px (`B > R+40`) | median hue of saturated px |
|
||||||
|
|---|---|---|---|
|
||||||
|
| decoded texture | **1073** | **0** | **23.3°** (orange) |
|
||||||
|
| in-game render | 916 | 124 | **9.3°** (orange-red) |
|
||||||
|
|
||||||
|
**Both land in the orange/red family; a red↔blue swap would put the decoded
|
||||||
|
texture at ≈200° (azure).** The 124 cool pixels in the game crop are the blue UI
|
||||||
|
panel behind the model, and the 14° offset is the hangar's red key lighting
|
||||||
|
tinting the lit model — both expected, neither able to move a hue by 180°.
|
||||||
|
|
||||||
|
Evidence: [`captures/xpr2-colour-check-deltasaber.png`](captures/xpr2-colour-check-deltasaber.png)
|
||||||
|
— decoded atlas beside the in-game hull.
|
||||||
|
|
||||||
|
## What this establishes, and what it does not
|
||||||
|
|
||||||
|
✅ **Channel order is right** for the XPR2 path, on a DXT1 texture with mips.
|
||||||
|
Separately, `BG_Earth.xpr` decodes as a 1024×1024 **A8R8G8B8** cubemap face and
|
||||||
|
produces a coherent nebula rather than noise, so the de-tile step is sound on
|
||||||
|
that path too — though a nebula has no ground truth, so it is corroboration, not
|
||||||
|
proof.
|
||||||
|
|
||||||
|
🟡 **Exact colour fidelity is still open.** A hue-family comparison cannot see a
|
||||||
|
gamma/sRGB curve error, a premultiplied-alpha mistake, or a small per-channel
|
||||||
|
scale — all of which preserve hue. Settling those needs a flat, unlit,
|
||||||
|
known-value surface rather than a lit hero model.
|
||||||
|
|
||||||
|
❔ The `~15 %` of T8aD variants noted elsewhere and the XPR2 **cubemap face
|
||||||
|
ordering** are untouched by this.
|
||||||
Reference in New Issue
Block a user