cridecoder 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cridecoder-0.1.0/.github/copilot-Instructions.md +51 -0
- cridecoder-0.1.0/.github/workflows/ci.yml +32 -0
- cridecoder-0.1.0/.github/workflows/release-crate.yml +21 -0
- cridecoder-0.1.0/.github/workflows/release-python.yml +139 -0
- cridecoder-0.1.0/.gitignore +32 -0
- cridecoder-0.1.0/AGENTS.md +74 -0
- cridecoder-0.1.0/Cargo.lock +561 -0
- cridecoder-0.1.0/Cargo.toml +40 -0
- cridecoder-0.1.0/LICENSE +21 -0
- cridecoder-0.1.0/PKG-INFO +107 -0
- cridecoder-0.1.0/README.md +88 -0
- cridecoder-0.1.0/examples/debug_acb.rs +43 -0
- cridecoder-0.1.0/examples/test_acb.rs +33 -0
- cridecoder-0.1.0/examples/test_hca.rs +45 -0
- cridecoder-0.1.0/examples/test_usm.rs +31 -0
- cridecoder-0.1.0/pyproject.toml +25 -0
- cridecoder-0.1.0/src/acb/afs.rs +141 -0
- cridecoder-0.1.0/src/acb/consts.rs +79 -0
- cridecoder-0.1.0/src/acb/extractor.rs +201 -0
- cridecoder-0.1.0/src/acb/track.rs +390 -0
- cridecoder-0.1.0/src/acb/utf.rs +426 -0
- cridecoder-0.1.0/src/acb.rs +13 -0
- cridecoder-0.1.0/src/hca/ath.rs +109 -0
- cridecoder-0.1.0/src/hca/bitreader.rs +226 -0
- cridecoder-0.1.0/src/hca/cipher.rs +136 -0
- cridecoder-0.1.0/src/hca/decoder.rs +1346 -0
- cridecoder-0.1.0/src/hca/hca_file.rs +453 -0
- cridecoder-0.1.0/src/hca/imdct.rs +328 -0
- cridecoder-0.1.0/src/hca/tables.rs +154 -0
- cridecoder-0.1.0/src/hca.rs +12 -0
- cridecoder-0.1.0/src/lib.rs +27 -0
- cridecoder-0.1.0/src/python.rs +152 -0
- cridecoder-0.1.0/src/reader.rs +144 -0
- cridecoder-0.1.0/src/usm/extractor.rs +616 -0
- cridecoder-0.1.0/src/usm/metadata.rs +691 -0
- cridecoder-0.1.0/src/usm.rs +12 -0
- cridecoder-0.1.0/tests/integration_tests.rs +405 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Copilot Instructions for cridecoder
|
|
2
|
+
|
|
3
|
+
## Project Context
|
|
4
|
+
|
|
5
|
+
This is a pure Rust library (`cridecoder`) for decoding CRI Middleware audio/video formats (ACB, HCA, USM). The CRI format implementation is based on [vgmstream](https://github.com/vgmstream/vgmstream). It also provides optional Python bindings via pyo3/maturin.
|
|
6
|
+
|
|
7
|
+
## Code Style
|
|
8
|
+
|
|
9
|
+
- **Rust edition**: 2021
|
|
10
|
+
- **Error handling**: Use `thiserror` derive macros for error enums
|
|
11
|
+
- **Binary I/O**: Use the `reader.rs` wrapper around `byteorder` for all binary reading
|
|
12
|
+
- **Text encoding**: CRI formats use Shift-JIS; use `encoding_rs::SHIFT_JIS` for decoding
|
|
13
|
+
- **Module structure**: Use Rust 2018+ flat module style (`src/acb.rs` + `src/acb/` directory), not `mod.rs`
|
|
14
|
+
- **Feature gates**: Python bindings use `#[cfg(feature = "python")]` — pure Rust builds should not depend on pyo3
|
|
15
|
+
- **Tests**: Unit tests are inline `#[cfg(test)] mod tests`, integration tests are in `tests/`
|
|
16
|
+
|
|
17
|
+
## Important Notes
|
|
18
|
+
|
|
19
|
+
- The `ClHca` struct (HCA decoder state) is very large (~200KB on stack). Use `RUST_MIN_STACK=16777216` when running integration tests
|
|
20
|
+
- ACB files may contain embedded AWB data or reference external `.awb` files
|
|
21
|
+
- HCA files support encryption — use `HcaDecoder::set_key()` or `KeyTest` for key testing
|
|
22
|
+
- USM files contain interleaved video (M2V) and audio (ADX) chunks with XOR masking
|
|
23
|
+
|
|
24
|
+
## Public API
|
|
25
|
+
|
|
26
|
+
```rust
|
|
27
|
+
// ACB
|
|
28
|
+
pub fn extract_acb_from_file(path, output_dir) -> Result<Option<Vec<String>>>
|
|
29
|
+
pub fn extract_acb(reader, output_dir, awb_reader) -> Result<Vec<String>>
|
|
30
|
+
|
|
31
|
+
// HCA
|
|
32
|
+
pub struct HcaDecoder { ... }
|
|
33
|
+
impl HcaDecoder {
|
|
34
|
+
pub fn from_file(path) -> Result<Self>
|
|
35
|
+
pub fn from_reader(reader) -> Result<Self>
|
|
36
|
+
pub fn info(&self) -> &HcaInfo
|
|
37
|
+
pub fn decode_to_wav(&mut self, writer) -> Result<()>
|
|
38
|
+
pub fn decode_all(&mut self) -> Result<Vec<f32>>
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// USM
|
|
42
|
+
pub fn extract_usm_file(path, output_dir, key, export_audio) -> Result<Vec<PathBuf>>
|
|
43
|
+
pub fn extract_usm(reader, output_dir, name, key, export_audio) -> Result<Vec<PathBuf>>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Testing
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
cargo test # Unit tests only
|
|
50
|
+
RUST_MIN_STACK=16777216 cargo test # Full test suite (needs test fixture files)
|
|
51
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
env:
|
|
10
|
+
CARGO_TERM_COLOR: always
|
|
11
|
+
RUST_MIN_STACK: "16777216"
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
test:
|
|
15
|
+
name: Test (Rust)
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v5
|
|
19
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
20
|
+
- uses: Swatinem/rust-cache@v2
|
|
21
|
+
- run: cargo test
|
|
22
|
+
- run: cargo clippy -- -D warnings
|
|
23
|
+
|
|
24
|
+
fmt:
|
|
25
|
+
name: Formatting
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/checkout@v5
|
|
29
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
30
|
+
with:
|
|
31
|
+
components: rustfmt
|
|
32
|
+
- run: cargo fmt --all --check
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: Release Crate
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish-crate:
|
|
10
|
+
name: Publish to crates.io
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v5
|
|
14
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
15
|
+
- uses: Swatinem/rust-cache@v2
|
|
16
|
+
- name: Verify package
|
|
17
|
+
run: cargo publish --dry-run
|
|
18
|
+
- name: Publish
|
|
19
|
+
run: cargo publish
|
|
20
|
+
env:
|
|
21
|
+
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
name: Release Python
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
# ──────────────────────────────────────────────
|
|
13
|
+
# Build wheels for Linux (x86_64, aarch64)
|
|
14
|
+
# ──────────────────────────────────────────────
|
|
15
|
+
linux:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
strategy:
|
|
18
|
+
matrix:
|
|
19
|
+
target: [x86_64, aarch64]
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v5
|
|
22
|
+
- name: Build wheels
|
|
23
|
+
uses: PyO3/maturin-action@v1
|
|
24
|
+
with:
|
|
25
|
+
target: ${{ matrix.target }}
|
|
26
|
+
args: --release --out dist --find-interpreter
|
|
27
|
+
sccache: "true"
|
|
28
|
+
manylinux: auto
|
|
29
|
+
- name: Upload wheels
|
|
30
|
+
uses: actions/upload-artifact@v5
|
|
31
|
+
with:
|
|
32
|
+
name: wheels-linux-${{ matrix.target }}
|
|
33
|
+
path: dist
|
|
34
|
+
|
|
35
|
+
# ──────────────────────────────────────────────
|
|
36
|
+
# Build wheels for macOS (x86_64, aarch64)
|
|
37
|
+
# ──────────────────────────────────────────────
|
|
38
|
+
macos:
|
|
39
|
+
runs-on: macos-15
|
|
40
|
+
strategy:
|
|
41
|
+
matrix:
|
|
42
|
+
target: [x86_64, aarch64]
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v5
|
|
45
|
+
- uses: actions/setup-python@v5
|
|
46
|
+
with:
|
|
47
|
+
python-version: |
|
|
48
|
+
3.9
|
|
49
|
+
3.10
|
|
50
|
+
3.11
|
|
51
|
+
3.12
|
|
52
|
+
3.13
|
|
53
|
+
3.14
|
|
54
|
+
3.14t
|
|
55
|
+
allow-prereleases: true
|
|
56
|
+
- name: Build wheels
|
|
57
|
+
uses: PyO3/maturin-action@v1
|
|
58
|
+
with:
|
|
59
|
+
target: ${{ matrix.target }}
|
|
60
|
+
args: --release --out dist --find-interpreter
|
|
61
|
+
sccache: "true"
|
|
62
|
+
- name: Upload wheels
|
|
63
|
+
uses: actions/upload-artifact@v5
|
|
64
|
+
with:
|
|
65
|
+
name: wheels-macos-${{ matrix.target }}
|
|
66
|
+
path: dist
|
|
67
|
+
|
|
68
|
+
# ──────────────────────────────────────────────
|
|
69
|
+
# Build wheels for Windows (x86_64)
|
|
70
|
+
# ──────────────────────────────────────────────
|
|
71
|
+
windows:
|
|
72
|
+
runs-on: windows-latest
|
|
73
|
+
steps:
|
|
74
|
+
- uses: actions/checkout@v5
|
|
75
|
+
- uses: actions/setup-python@v5
|
|
76
|
+
with:
|
|
77
|
+
python-version: |
|
|
78
|
+
3.9
|
|
79
|
+
3.10
|
|
80
|
+
3.11
|
|
81
|
+
3.12
|
|
82
|
+
3.13
|
|
83
|
+
3.14
|
|
84
|
+
3.14t
|
|
85
|
+
allow-prereleases: true
|
|
86
|
+
- name: Build wheels
|
|
87
|
+
uses: PyO3/maturin-action@v1
|
|
88
|
+
with:
|
|
89
|
+
target: x64
|
|
90
|
+
args: --release --out dist --find-interpreter
|
|
91
|
+
sccache: "true"
|
|
92
|
+
- name: Upload wheels
|
|
93
|
+
uses: actions/upload-artifact@v5
|
|
94
|
+
with:
|
|
95
|
+
name: wheels-windows-x64
|
|
96
|
+
path: dist
|
|
97
|
+
|
|
98
|
+
# ──────────────────────────────────────────────
|
|
99
|
+
# Build source distribution
|
|
100
|
+
# ──────────────────────────────────────────────
|
|
101
|
+
sdist:
|
|
102
|
+
runs-on: ubuntu-latest
|
|
103
|
+
steps:
|
|
104
|
+
- uses: actions/checkout@v5
|
|
105
|
+
- name: Build sdist
|
|
106
|
+
uses: PyO3/maturin-action@v1
|
|
107
|
+
with:
|
|
108
|
+
command: sdist
|
|
109
|
+
args: --out dist
|
|
110
|
+
- name: Upload sdist
|
|
111
|
+
uses: actions/upload-artifact@v5
|
|
112
|
+
with:
|
|
113
|
+
name: wheels-sdist
|
|
114
|
+
path: dist
|
|
115
|
+
|
|
116
|
+
# ──────────────────────────────────────────────
|
|
117
|
+
# Publish all wheels + sdist to PyPI
|
|
118
|
+
# ──────────────────────────────────────────────
|
|
119
|
+
publish:
|
|
120
|
+
name: Publish to PyPI
|
|
121
|
+
runs-on: ubuntu-latest
|
|
122
|
+
needs: [linux, macos, windows, sdist]
|
|
123
|
+
if: github.event_name == 'release'
|
|
124
|
+
environment:
|
|
125
|
+
name: pypi
|
|
126
|
+
url: https://pypi.org/p/cridecoder
|
|
127
|
+
permissions:
|
|
128
|
+
id-token: write
|
|
129
|
+
steps:
|
|
130
|
+
- uses: actions/download-artifact@v5
|
|
131
|
+
with:
|
|
132
|
+
pattern: wheels-*
|
|
133
|
+
merge-multiple: true
|
|
134
|
+
path: dist/
|
|
135
|
+
- name: Publish to PyPI
|
|
136
|
+
uses: PyO3/maturin-action@v1
|
|
137
|
+
with:
|
|
138
|
+
command: upload
|
|
139
|
+
args: --non-interactive --skip-existing dist/*
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Generated by Cargo
|
|
2
|
+
# will have compiled files and executables
|
|
3
|
+
debug
|
|
4
|
+
target
|
|
5
|
+
|
|
6
|
+
# These are backup files generated by rustfmt
|
|
7
|
+
**/*.rs.bk
|
|
8
|
+
|
|
9
|
+
# MSVC Windows builds of rustc generate these, which store debugging information
|
|
10
|
+
*.pdb
|
|
11
|
+
|
|
12
|
+
# Generated by cargo mutants
|
|
13
|
+
# Contains mutation testing data
|
|
14
|
+
**/mutants.out*/
|
|
15
|
+
|
|
16
|
+
# RustRover
|
|
17
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
18
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
19
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
20
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
21
|
+
#.idea/
|
|
22
|
+
|
|
23
|
+
# Test output
|
|
24
|
+
test_output_acb/
|
|
25
|
+
test_output_usm/
|
|
26
|
+
|
|
27
|
+
# Test data files (large binary)
|
|
28
|
+
*.acb
|
|
29
|
+
*.usm
|
|
30
|
+
*.hca
|
|
31
|
+
*.wav
|
|
32
|
+
*.m2v
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
|
|
5
|
+
**cridecoder** is a pure Rust library for decoding CRI Middleware formats, with optional Python bindings via pyo3/maturin.
|
|
6
|
+
|
|
7
|
+
### Credits
|
|
8
|
+
|
|
9
|
+
CRI format implementation is based on [vgmstream](https://github.com/vgmstream/vgmstream).
|
|
10
|
+
|
|
11
|
+
## Architecture
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
src/
|
|
15
|
+
├── lib.rs # Crate root, re-exports public API, #[pymodule] (behind "python" feature)
|
|
16
|
+
├── reader.rs # Binary reader utilities (endianness, primitive types, alignment)
|
|
17
|
+
├── acb.rs # ACB module root (re-exports submodules)
|
|
18
|
+
├── acb/
|
|
19
|
+
│ ├── consts.rs # ACB/UTF constants and helpers
|
|
20
|
+
│ ├── utf.rs # CRI UTF table parser
|
|
21
|
+
│ ├── afs.rs # AFS2 archive parser
|
|
22
|
+
│ ├── track.rs # Track list extraction from ACB
|
|
23
|
+
│ └── extractor.rs # ACB extraction logic
|
|
24
|
+
├── hca.rs # HCA module root (re-exports submodules)
|
|
25
|
+
├── hca/
|
|
26
|
+
│ ├── decoder.rs # Core HCA decoder (ClHca, header parsing, block decoding)
|
|
27
|
+
│ ├── hca_file.rs # High-level HcaDecoder with streaming, WAV output, key testing
|
|
28
|
+
│ ├── tables.rs # Lookup tables for HCA decoding
|
|
29
|
+
│ ├── cipher.rs # HCA encryption/decryption cipher
|
|
30
|
+
│ ├── ath.rs # ATH (Absolute Threshold of Hearing) tables
|
|
31
|
+
│ ├── bitreader.rs # Bit-level reader/writer
|
|
32
|
+
│ └── imdct.rs # Inverse MDCT transform
|
|
33
|
+
├── usm.rs # USM module root (re-exports submodules)
|
|
34
|
+
├── usm/
|
|
35
|
+
│ ├── extractor.rs # USM extraction (video/audio stream demuxing)
|
|
36
|
+
│ └── metadata.rs # USM metadata reading and JSON export
|
|
37
|
+
└── python.rs # Python bindings (behind "python" feature)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Key Types
|
|
41
|
+
|
|
42
|
+
- `extract_acb_from_file()` / `extract_acb()` — ACB extraction entry points
|
|
43
|
+
- `HcaDecoder` — High-level HCA to WAV/PCM decoder
|
|
44
|
+
- `extract_usm_file()` / `extract_usm()` — USM extraction entry points
|
|
45
|
+
- `ClHca` — Low-level HCA decoder state machine
|
|
46
|
+
|
|
47
|
+
## Building
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Pure Rust
|
|
51
|
+
cargo build
|
|
52
|
+
cargo test # Unit tests only
|
|
53
|
+
RUST_MIN_STACK=16777216 cargo test # Unit + integration tests (HCA needs larger stack)
|
|
54
|
+
|
|
55
|
+
# Python extension
|
|
56
|
+
python3 -m maturin build --release
|
|
57
|
+
|
|
58
|
+
# crates.io dry run
|
|
59
|
+
cargo publish --dry-run --allow-dirty
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Testing
|
|
63
|
+
|
|
64
|
+
- **Unit tests**: Inline `#[cfg(test)] mod tests` in most modules
|
|
65
|
+
- **Integration tests**: `tests/integration_tests.rs` — requires `se_0126_01.acb` and `0703.usm` test fixtures in project root
|
|
66
|
+
- Integration tests need `RUST_MIN_STACK=16777216` due to large `ClHca` struct
|
|
67
|
+
|
|
68
|
+
## Conventions
|
|
69
|
+
|
|
70
|
+
- Use `thiserror` for error types
|
|
71
|
+
- Use `byteorder` for binary reading via the `reader.rs` wrapper
|
|
72
|
+
- Use `encoding_rs` for Shift-JIS text decoding (CRI uses Shift-JIS strings)
|
|
73
|
+
- Public API lives in module root files (`acb.rs`, `hca.rs`, `usm.rs`); internals are `mod` (private)
|
|
74
|
+
- Python bindings are behind `#[cfg(feature = "python")]` so they're opt-in
|