#game-cube #wii #iso #file-format #read-file #wbfs #rvz

bin+lib nodtool

CLI tool for verifying and converting GameCube and Wii disc images

8 stable releases

1.4.4 Oct 18, 2024
1.4.3 Oct 5, 2024
1.3.0 Sep 29, 2024

#973 in Parser implementations

Download history 165/week @ 2024-08-30 276/week @ 2024-09-06 58/week @ 2024-09-13 23/week @ 2024-09-20 298/week @ 2024-09-27 723/week @ 2024-10-04 136/week @ 2024-10-11 190/week @ 2024-10-18 18/week @ 2024-10-25 12/week @ 2024-11-01

366 downloads per month

MIT/Apache

2.5MB
5.5K SLoC

nod Build Status Latest Version Api Rustdoc Rust Version

Library for traversing & reading Nintendo Optical Disc (GameCube and Wii) images.

Originally based on the C++ library nod, but does not currently support authoring.

Currently supported file formats:

  • ISO (GCM)
  • WIA / RVZ
  • WBFS (+ NKit 2 lossless)
  • CISO (+ NKit 2 lossless)
  • NFS (Wii U VC)
  • GCZ
  • TGC

CLI tool

This crate includes a command-line tool called nodtool.

Download the latest release from the releases page, or install it using Cargo:

cargo install --locked nodtool

info

Displays information about a disc image.

nodtool info /path/to/game.iso

extract

Extracts the contents of a disc image to a directory.

nodtool extract /path/to/game.iso [outdir]

For Wii U VC titles, use content/hif_000000.nfs:

nodtool extract /path/to/game/content/hif_000000.nfs [outdir]

convert

Converts any supported format to raw ISO.

nodtool convert /path/to/game.wia /path/to/game.iso

verify

Hashes the contents of a disc image and verifies it.

nodtool verify /path/to/game.iso

Library example

Opening a disc image and reading a file:

use std::io::Read;

// Open a disc image and the first data partition.
let disc = nod::Disc::new("path/to/file.iso")
    .expect("Failed to open disc");
let mut partition = disc.open_partition_kind(nod::PartitionKind::Data)
    .expect("Failed to open data partition");

// Read partition metadata and the file system table.
let meta = partition.meta()
    .expect("Failed to read partition metadata");
let fst = meta.fst()
    .expect("File system table is invalid");

// Find a file by path and read it into a string.
if let Some((_, node)) = fst.find("/MP3/Worlds.txt") {
    let mut s = String::new();
    partition
        .open_file(node)
        .expect("Failed to open file stream")
        .read_to_string(&mut s)
        .expect("Failed to read file");
    println!("{}", s);
}

Converting a disc image to raw ISO:

// Enable `rebuild_encryption` to ensure the output is a valid ISO.
let options = nod::OpenOptions { rebuild_encryption: true, ..Default::default() };
let mut disc = nod::Disc::new_with_options("path/to/file.rvz", &options)
    .expect("Failed to open disc");

// Read directly from the open disc and write to the output file.
let mut out = std::fs::File::create("output.iso")
    .expect("Failed to create output file");
std::io::copy(&mut disc, &mut out)
    .expect("Failed to write data");

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies

~19–32MB
~486K SLoC