Zero-copy parsing and generation of Nintendo Switch file formats.
Turns a byte buffer into a validated view of every format it covers, and builds each of them back out of its parts. Nothing is copied to read an image and nothing is written to disk to produce one, so the same definitions serve a host-side packer and code running on the console.
The crate is organized in three layers, each usable on its own:
raw--#[repr(C)]binary structure definitions backed byzerocopy. Direct field access, no parsing overhead, no allocator.read-- Parsing wrappers over the raw structures. Validate magic numbers and sizes once, then hand out parts without further checks, and report a typed error per format. No allocator.write-- Builders that assemble a format and return the finished image as a byte buffer, so the caller chooses where the artifact lands. Needs a heap; the builders that walk a directory need a filesystem too.
A fourth module, elf, extracts the segments of a linked ELF binary and hands them to the NRO and
NSO builders.
| Format | Description | raw |
read |
write |
|---|---|---|---|---|
| NRO | Nintendo Relocatable Object (homebrew) | ✓ | ✓ | ✓ |
| NSO | Nintendo Software Object (system module) | ✓ | ✓ | ✓ |
| KIP | Kernel Initial Process | ✓ | ✓ | ✓ |
| NACP | Nintendo Application Control Property | ✓ | ✓ | ✓ |
| NPDM | Nintendo Program Description Metadata | ✓ | ✓ | ✓ |
| RomFS | Read-only filesystem image | ✓ | ✓ | ✓ |
| PFS0 | Partition filesystem archive | ✓ | ✓ | ✓ |
| MOD0 | Module header embedded in executables | ✓ | ✓ | |
| NCA | Nintendo Content Archive | ✓ | ✓ | ✓ |
| CNMT | Content meta naming every NCA of a title | ✓ | ✓ | ✓ |
It does not sign, encrypt, or verify anything: an NPDM's ACID signature is stored and reproduced but never checked, and an NSO's segment hashes are computed on write yet left to the caller on read.
It does decompress, but never behind an accessor. A reader borrows its buffer and has nowhere to put
expanded bytes, so expanding is a separate call that allocates and can fail -- Kip1Segment and
Nso each offer one, and a segment slice always comes back exactly as the file stores it.
NCA is where the encryption line is most visible, because an NCA on disk is encrypted throughout.
NcaBuilder produces the plaintext container and every hash covering it, then names what is still
owed; the caller supplies the keyset and the ciphers. Reading runs the same way in reverse: Nca
takes a buffer the caller has already decrypted, and an image still in ciphertext fails its magic
check rather than parsing into nonsense. Hashing stays here because a hash is part of the layout --
it is what makes the recorded offsets checkable -- while encryption is a transformation applied to a
layout that is already correct.
[dependencies]
nx-object = { git = "https://github.com/nx-std/nx-object" }The default build carries every format and the standard library. A consumer that wants less -- one
format, or a build with no allocator and no OS -- selects it through the crate's Cargo features,
which are documented on each entry in Cargo.toml.
just check --all-targets --all-features # compile check
just clippy --all-targets --all-features # lint
just test --all-features # cargo nextest run (falls back to cargo test)
just check-unused-deps # cargo machete
just fmt # cargo +nightly fmt --all
# The bare-metal half, the way CI builds it
just check --no-default-features --features all-formats,alloc --target aarch64-unknown-none
just clippy --no-default-features --features all-formats,alloc --target aarch64-unknown-noneEvery format the crate covers is documented on the switchbrew wiki, except RomFS, whose layout the console inherits unchanged from the 3DS.
MIT. See LICENSE.