Phase 1 of the roadmap. The disc is now turned into verified asset files, and
the result is checked against a committed hash table rather than against
whatever happens to be on disk.
gc-extract identify disc.iso SCUS_972.68 v1.01 NTSC, ELF SHA-1 matches
gc-extract unpack disc.iso out/ 5135 files, 4,500,106,960 bytes, 10.8s
gc-extract verify out/ table.tsv OK: 5135 files match
All 92 G/*.WAD containers parse. MPEG1 and MPEG2 are raw video and pass
through whole; the other 90 are indexed containers whose extents are extracted
individually.
Formats recovered and written up in docs/formats/:
- iso9660.rs. R&C2 lists its assets in the filesystem, unlike R&C1, so a
directory walk is the primary asset index. Three details that all fail
quietly rather than loudly: directory records store every 32-bit field twice
(little-endian then big-endian), the CD001 signature is at sector offset 1
rather than 0x8001, and the directory flag at record offset 25 is
authoritative where the identifier's trailing slash is not.
- global_wad.rs. Container headers hold a table of extents. All 92 indexed
containers use {offset in sectors, size in bytes}. Measured, not assumed: the
sector-count reading places every entry of all 27 LEVEL<n> and all 27
AUDIO<n> containers out of range, while the byte reading places all of them
correctly. SCENE<n> is the one exception, a flat sector list whose extents
are sized by the next value.
- wad.rs. Insomniac's LZ77 stream: four flag-selected packet classes, with 0-3
trailing literal bytes per packet carried in unused low bits. This is not a
bit stream, which is why it resists the usual LZ77 reading.
- buf.rs. A bounds-checked reader, so untrusted 2003 disc data produces typed
errors rather than panics.
gc-extract carries the three stages and a SHA-1 implementation with FIPS 180-4
test vectors, so identification works without pulling in a crypto dependency.
Verification: 54 unit tests, plus four integration tests that run only when
GC_DISC names a disc. Those four check identification against the recorded
values, cross-check the Rust identifier against tools/identify-disc.py, parse
all 92 containers, and confirm a full unpack matches the committed table. The
committed table is 316 KB of sizes and SHA-1s for all 5,135 files: hashes only,
no game content, so it is safe to version and it turns "matches retail" into
something a test can assert.
docs/plan/disc-pipeline.md records two wrong turns, because both are easy to
repeat and both failed by producing plausible wrong output rather than an
error: the container table was read backwards, and the LZ77 stream was modelled
as a bit stream. The first survived because it happened to be correct on the
one container used for manual checking.
20 lines
842 B
Rust
20 lines
842 B
Rust
//! Video decoding for *Ratchet & Clank: Going Commando* (PS2).
|
|
//!
|
|
//! R&C2 uses the Emotion Engine's **IPU** to stream MPEG-2 video, most visibly
|
|
//! on the title screen where Ratchet watches television. This crate decodes
|
|
//! those streams to raw frames for the host GPU to upload.
|
|
//!
|
|
//! # Note on scale
|
|
//!
|
|
//! The MPEG WADs on this disc total roughly 2.4 GB (about 1.0 GB, 1.3 GB and
|
|
//! 115 MB). Video is a data problem before it is a decoding problem, so the
|
|
//! pipeline needs to stream rather than hold a whole movie in memory.
|
|
//!
|
|
//! # Pipeline
|
|
//!
|
|
//! `bits.rs` -> `vlc.rs` -> `idct.rs` -> `mpeg2.rs`
|
|
//!
|
|
//! MPEG-2 decoding is a solved, well-specified problem, and a general-purpose
|
|
//! decoder will produce correct output. The PS2-specific part is only the
|
|
//! container: how the streams are stored and addressed on the disc.
|