Repository navigation
v0.3.0
A correctness and performance release. HCA, ACB and USM decoding now matches the reference implementations (vgmstream's clHCA, PyCriCodecs and WannaCRI) on real game assets, HCA decoding and USM decryption are SIMD-accelerated, and encrypted HCA can be decoded with keys. Existing calls keep working and the new parameters are optional; Rust code that names the type of UtfTable's map fields needs a small change.
⚠️ Breaking changes
- Rust only: the public
UtfTable::constantsandUtfTable::rowsfields now holdrustc_hash::FxHashMap<String, Value>instead ofstd::collections::HashMap<String, Value>. Code that names the old map type needs to useFxHashMapfrom therustc-hashcrate or let the type be inferred. (#9)
Added
- Decode type-56 encrypted HCA by passing the optional
keyandsubkeyparameters todecode_hcaanddecode_hca_bytes. Unencrypted files are unaffected, and ACB extraction now reads each AWB's subkey from AFS2 automatically. (#10) - Ship Python type information:
cridecoder.pyistubs and a PEP 561py.typedmarker, so editors and type checkers see typed signatures for all 12 exported functions. (#10) - Pick the USM output extension from the stream's codec: VP9 video is written as
.ivf(otherwise.m2v) and HCA audio as.hca(otherwise.adx). (#10) - Write a
smplloop chunk into WAV files decoded from looping HCA. (#10)
Fixed
- Compute the HCA resolution with an unsigned shift, as clHCA does, which fixes subtly wrong coefficients. (#10)
- Trim the trailing encoder padding of HCA streams, so decoded audio has the true sample count. (#10)
- Name ACB tracks after the cue they belong to; names were bound to the reference index and could be mismatched. (#10)
- Give tracks from HCA-MX cue sheets the
.hcaextension. (#10) - Keep reading USM streams past the first
#CONTENTS END, which cut longer streams short. (#10) - Apply the audio XOR mask to ADX audio only. (#10)
- Fix the order of the video-mask passes in
UsmBuilder, so a USM it builds extracts back to the original data. (#10) - Skip ACB cues with unhandled reference types instead of failing the whole extraction. (#10)
- Validate VBR,
@UTFversions and EOF bounds, fall back from UTF-8 to Shift-JIS and UTF-16 when decoding CRI strings, and align AFS2 next offsets. (#10)
Performance
- Vectorize the HCA inverse MDCT with NEON on aarch64 and SSE2 or runtime-detected AVX2 on x86_64. Output stays bit-identical (no FMA), and decoding is about 1.3–1.5× faster than clHCA at
-O3. (#10) - Decrypt USM packets in place with auto-vectorized code. The de-mask itself goes from about 3 to 40 GB/s, and end-to-end extraction of an encrypted USM is about 3.2–3.4× faster. (#10)
- Compute HCA frame CRC16 with slicing-by-8; it was about 12% of decode time. (#10)
- Dequantize HCA with a register-resident bit accumulator: the decode core goes from 106.1 to 78.4 ms (about 26% faster) on a 4.5 MB stereo HCA. (#8)
- Speed up the HCA bit reader and turn the decode lookup tables into compile-time constants: the decode core goes from 120.6 to 113.1 ms (about 6% faster) on a 4.5 MB stereo HCA. (#6)
- Speed up ACB track extraction: duplicate-name checks are now linear and parsed UTF rows use FxHash. A synthetic 2000-track ACB extracts about 2.7× faster (6.15 to 2.26 ms). (#9)
Artifacts
- crates.io:
cridecoder0.3.0 - PyPI:
cridecoder0.3.0
Maintenance
Full Changelog: v0.2.3...v0.3.0