1 · Build the workspace

The repo is a Cargo workspace with edition 2024. One library + binary per crate.

git clone https://github.com/AndrewAltimit/legend-of-legaia-re
cd legend-of-legaia-re
cargo build --release
cargo test --workspace --release

Tests gated on a real disc image will skip when LEGAIA_DISC_BIN is unset. CI runs the same way.

2 · Extract assets from a disc image

This repo ships zero Sony bytes. You need a .bin Mode2/2352 image of Legend of Legaia (the NA SCUS-94254 build). Anything else (PAL, JP, Demo) won't match the embedded SHA-256 fingerprints.

./target/release/legaia-extract \
    "/path/to/Legend of Legaia (USA).bin" \
    --out extracted

This runs the full pipeline: verify → ISO walk → PROT.DAT → categorize → streaming-format extract → TIM → PNG.

--skip-png and --skip-verify available if you want to iterate faster on the in-RAM dispatch logic without re-rendering thousands of textures.

3 · Browse the extracted assets

The asset-viewer binary is a winit + wgpu app with five modes. A WASM build of the viewer also runs in this browser.

./target/release/asset-viewer prot extracted/PROT.DAT
./target/release/asset-viewer tmd extracted/.../foo.tmd
./target/release/asset-viewer tim extracted/.../bar.tim
./target/release/asset-viewer stage extracted/.../stage_geom_0123
./target/release/asset-viewer vab extracted/.../bank.vab

Inside the PROT browser: N / P = next/prev entry; PgDn / PgUp = jump 10; Esc = quit. Auto-detects format and shows the first viewable sub-asset.

4 · Stand up Ghidra in Docker

All static analysis runs through the blacktop/ghidra container. The compose file mounts the extracted disc as read-only data and the project + scripts directories as read-write so dumps land back on the host.

docker compose up -d ghidra

# import SCUS_942.54 (one-time)
docker compose exec ghidra /ghidra/support/analyzeHeadless \
    /projects legaia -import /data/SCUS_942.54

# run an analysis script
docker compose exec ghidra /ghidra/support/analyzeHeadless \
    /projects legaia -process SCUS_942.54 \
    -postScript dump_funcs.py -noanalysis -scriptPath /scripts

The container runs as root; chown your output back to your user after each script: chown -R $(id -u):$(id -g) ghidra/scripts/funcs/.

For runtime overlay capture (RAM at 0x801C0000+ while the game runs), see the overlay capture pipeline.

What to read next