TXCM XPR2 resources are the game's world skyboxes (BG_Acheron, BG_Hargenteen, …). The viewer showed only face 0 as a flat 2D image; now it decodes all 6 faces and shows a labelled grid. Formats (Bevy-free): X360Texture::cube_faces_from_xpr2() returns a Cubemap with 6 faces in D3D9 order (+X −X +Y −Y +Z −Z), or None for ordinary 2D textures. Face layout derived from xenia's GetGuestTextureLayout — 6 back-to-back independently- tiled surfaces, per-face stride = tiled-surface-size aligned to the 4 KiB subresource boundary (kTextureSubresourceAlignmentBytes). Verified against real BG_Acheron: data_size == 6 × 0x400000, and all 6 faces decode cleanly (own Python decode + a disc test asserting 6×4 MiB faces and face 0 == the validated from_xpr2 green-planet decode). Extracted a shared decode_surface() helper so the 2D and cube paths are byte-identical; from_xpr2 output unchanged (re-verified). Viewer: new SkyboxPreview resource (6 egui face textures, reusing the existing per-format x360_texture_to_bevy_image); populated in apply_loaded_texture's TXCM branch; freed/reset alongside the other previews (factored free_texture/ free_skybox helpers). Central panel gains a skybox branch rendering a 3-column labelled face grid. DEFERRED (per "do not guess, else defer"): the interactive 3D skybox. Face data + D3D9 order are validated, but wgpu cube-sampling handedness can't be confirmed without eyeballing the GUI — a wrong-oriented skybox is worse than the correct labelled grid. The grid is the reliable deliverable; the 3D look-around is a follow-up once orientation is visually confirmed. (Background agent did the investigation/validation but was blocked from writing files; implemented here in the main tree from its findings, independently re-verified.) 23 formats tests + disc cubemap test pass; viewer/CLI build; face-0 export re-verified as the green planet. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>