Skip to content

Commit a9a1fb3

Browse files
LinuxJessiclaude
andcommitted
Improvement run ported from the Xenosaga I kit: LZSS maps, package textures, PSMT4, hidden text
Five lessons from the XS1 extractor re-checked against XS3; each paid off: * xcpack.py: Xc MR-package layer with the engine's four LZSS decoders (from the SLUS loader FUN_001b7330 dispatch). Every E3_* field map is compressed (98/168 on Disc 1); chr-decode and the browse sweep now decompress transparently, `xc-unpack` writes the stored form. Editing commands refuse compressed packages (no recompressor yet). * browse --kinds package_textures: decodes the ~20,900 textures inside .chr/.wpn/.map packages and .esd/.esp/.sme effect files, sha1 de-dup, package_textures.csv manifest. * chrtex.py: PSMT4 (fmt 0x14) entries decode (derived against the proven PSMT8 path); strip count read from the table header (8-strip maps were stamping entry 0 over the canvas); txy v2 second upload bank overlaid (118/315 E3_CIT01 entries were blank); exceptions instead of sys.exit. * text kind: .txd menu-text tables decoded (not RenderWare), .sb scene banks decoded (field dialogue + EUC-JP writer notes), mnu/us/*.bin and .dat string tables sniffed, .t manifests copied. * xtx_decode.py: coherence-ranked CLUT selection with per-block rescue for the 8 swizzled UI sheets (XS1 issue-#1 selector). * soundbanks kind: DTPK banks embedded in .sme bundles. * Fix: `textures` + `textures_png` together (the default) never produced PNGs because of an early return. Docs: docs/UPDATES.md (new, newest-first change log with before/after panels), disc-catalog corrections (.txd/.sb/.map/.xep/.sme, Xc version table), chr-txy-format spec additions, README and GUI wiring. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
1 parent a5313f6 commit a9a1fb3

15 files changed

Lines changed: 1394 additions & 117 deletions

‎README.md‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,20 @@ from "point at an ISO" through "browse decoded textures and movies."*
3636
voiced line as WAV, and the entire game's compiled MIPS code as a
3737
disassembly dump. Real extraction; nothing reconstructed or upscaled.*
3838

39+
**New (2026-09-24):** `browse --kinds package_textures` now decodes the
40+
~20,900 textures that live *inside* other files — every character,
41+
weapon, field-map and effect texture on the disc (the field maps turned
42+
out to be LZSS-compressed; that is cracked too) — and the `text` kind
43+
recovers the menu text tables and the in-map dialogue from the `.txd` /
44+
`.sb` files. Details and what to re-run: [docs/UPDATES.md](docs/UPDATES.md).
45+
46+
![Before/after: field-map textures, 4-bit entries and the two-bank fix](docs/screenshots/improve-psmt4-banks.png)
47+
48+
*Left: a battle backdrop as the old decoder saw it; right: the same 4-bit
49+
entry decoded. Below: field-map entries that were blank until the second
50+
texture bank was overlaid. More panels (UI sheets, effect sprites, a whole
51+
compressed town map) in `docs/UPDATES.md`.*
52+
3953
## Quick start — GUI (recommended)
4054

4155
Most people will want this path. **It opens in your browser; nothing is
@@ -320,7 +334,7 @@ Disc 2 is the same flow with a fresh `--work` directory, using `Lba0.txt` +
320334
| `scan` | Walks every LBA row, resolves to `(container, local_offset)`, writes manifest. |
321335
| `extract` | Slice bytes per the manifest into a mirrored tree. |
322336
| `verify` | Cross-check extracted file sizes (and optionally SHA-1) against the manifest. |
323-
| `browse` | Build a sibling `browse/` tree. Categories (`--kinds`): `images` (JPG copy), `text` (TXT/MES copy), `textures` (XTX/TM2/TXD/TXY/BMP/PNG raw copy), `textures_png` (XTX/TM2 → PNG decode, Pillow needed), `audio` (ADX → WAV, ffmpeg), `movies` (SFD → H.264 MP4, ffmpeg), `carved` (JPGs carved from `credit.bin`-style containers). |
337+
| `browse` | Build a sibling `browse/` tree. Categories (`--kinds`): `images` (JPG copy), `text` (TXT/MES/T copy, `.txd` menu-text tables decoded, dialogue/database strings sniffed out of `.sb`/`.bin`/`.dat` as `*.strings.txt`), `textures` (XTX/TM2/TXY/BMP/PNG raw copy), `textures_png` (XTX/TM2 → PNG decode, Pillow needed), `package_textures` (every texture inside `.chr`/`.wpn`/`.map` packages and `.esd`/`.esp`/`.sme` effect files → PNG + `package_textures.csv`, pure Python), `audio` (ADX → WAV, ffmpeg), `soundbanks` (DAP → per-cue WAV, incl. the banks inside `.sme`), `movies` (SFD → H.264 MP4, ffmpeg), `carved` (JPGs carved from `credit.bin`-style containers). |
324338
| `code-extract` | Run 7-Zip over the ISO to pull the non-X3 files (SLUS, OVL, IRX, SYSTEM.CNF) into a directory. |
325339
| `disasm` | MIPS R5900 disassembly + `lui`/`addiu` string xrefs for SLUS / OVL ELFs. Needs `capstone`. |
326340

@@ -332,6 +346,7 @@ Disc 2 is the same flow with a fresh `--work` directory, using `Lba0.txt` +
332346
| `repack-extract` | Pull any one file out of an ISO via the Lba tables (all three tables, both discs). |
333347
| `repack-patch` | Write a file back into an ISO in place, read-back verified. Same-size by default; `--pad` allows resizes up to the slot's sector allocation. |
334348
| `repack-tree` | Patch an entire mod directory that mirrors the game tree (`mymod/mdl/chr/...` → `\mdl\chr\...`). `--dry-run` previews. GUI card 14. |
349+
| `xc-unpack` | Inspect an `Xc` MR package (`.chr`/`.map`/`.wpn`/`.sme`): version, sub-resources; `--out` writes it decompressed (the field maps are LZSS-packed on disc — see `xcpack.py`). |
335350

336351
Full loop and the disc model's rules: [docs/REPACK.md](docs/REPACK.md).
337352
Underlying module works standalone too: [`repack.py`](repack.py).
@@ -340,7 +355,7 @@ Underlying module works standalone too: [`repack.py`](repack.py).
340355

341356
| Command | What it does |
342357
|-----------------|--------------|
343-
| `chr-decode` | Decode every texture inside a `.chr` (or `.wpn`/`.sme`) to PNG, plus the raw atlas + index map. |
358+
| `chr-decode` | Decode every texture inside a `.chr` (or `.wpn`/`.map`, compressed maps included) to PNG — 8-bit, 4-bit and raw-CT32 entries — plus the raw atlas + index map. |
344359
| `chr-palettes` | Export each texture's 256-color CLUT as an editable 16×16 PNG swatch (one pixel = one color). |
345360
| `chr-import-palettes` | Write edited swatch PNGs back into a `.chr` (lossless round-trip for untouched entries). |
346361
| `chr-import-entry` | Repaint a texture from a same-size PNG, quantized to its existing palette (experimental). |

0 commit comments

Comments
 (0)