RVZSharp 1.0.0

dotnet add package RVZSharp --version 1.0.0
                    
NuGet\Install-Package RVZSharp -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="RVZSharp" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RVZSharp" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="RVZSharp" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add RVZSharp --version 1.0.0
                    
#r "nuget: RVZSharp, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package RVZSharp@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=RVZSharp&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=RVZSharp&version=1.0.0
                    
Install as a Cake Tool

RVZSharp

A pure managed C# library and CLI (.NET 8 / 9 / 10) for decoding and encoding Dolphin RVZ disc images (GameCube/Wii). RVZ is the successor of the WIA format; RVZSharp decodes RVZ files back to the original disc image (.iso) byte-for-byte, including:

dotnet add package RVZSharp
  • all five compression methods: NONE, BZIP2, LZMA, LZMA2, Zstandard (100% managed codecs — ZstdSharp.Port, SharpZipLib, and a vendored 7-Zip LZMA/LZMA2 decoder, see THIRD-PARTY-NOTICES.md);
  • the RVZ packing scheme (Lagged Fibonacci PRNG padding reconstruction);
  • Wii partition reconstruction: SHA-1 hash trees (h0/h1/h2), hash exceptions, and AES-128-CBC re-encryption with the partition key — the output is identical to the original encrypted disc image;
  • full container validation (magic, versions, all SHA-1 integrity checks, structure rules).

Usage

Library

dotnet add package RVZSharp

1. Open any disc image — the format is auto-detected from the magic bytes (RVZ, WIA, GCZ, CISO/WBI, WBFS, TGC, NFS, plain ISO):

using RVZSharp.Blobs;

// From a file path:
using var blob = Blob.Open(@"C:\games\game.rvz");

// From a stream (same result for any supported format):
using var stream = File.OpenRead(@"C:\games\game.gcz");
using var blob2 = Blob.Open(stream);

// NFS images carry their AES key outside the file (Dolphin convention):
using var blob3 = Blob.Open(nfsStream, nfsKey, leaveOpen: true);

2. Decode — the whole image, or random-access ranges:

using var file = File.OpenRead(@"C:\games\game.rvz");
using var reader = RvzReader.Open(file);

Console.WriteLine($"ISO size: {reader.Length} bytes");             // 1459978240
Console.WriteLine($"Disc: {reader.Disc.DiscType}");                // Wii
Console.WriteLine($"Compression: {reader.Disc.Compression}");      // Zstd

// Decode everything (the full disc image, byte-for-byte):
var iso = reader.ReadFully();

// ...or stream any range without decoding the whole file:
var buffer = new byte[0x80000];
long read = reader.ReadAt(partitionStart, buffer);

RvzReader.Open parses and validates the whole container (magic, versions, every SHA-1, structure rules) and throws RvzHashMismatchException / RvzFormatException on damage.

3. Write an RVZ from any supported image (mirrors Dolphin's converter):

using RVZSharp;
using RVZSharp.Blobs;

using var input = Blob.Open(@"C:\games\game.wia");
using var output = File.Create(@"C:\games\game.rvz");

var options = new RvzWriteOptions
{
    Compression = CompressionType.Zstd,   // None, Bzip2, Lzma, Lzma2, Zstd
    CompressionLevel = 5,                 // Zstd: -131072..22 (negative = fast), others 1-9
    ChunkSize = 131072,
    Packing = true                        // PRNG-junk packing (smaller files)
};

RvzWriter.Write(input: input, output: output, options: options);

Wii partitions are stored decrypted with hash exceptions, exactly like Dolphin produces. options defaults to the Dolphin-compatible settings (Zstd / level 5 / 2 MiB chunks, packing on). To get a plain ISO back, use the CLI's convert -f iso (or a reader + copy).

4. Progress and cancellation for long conversions:

using var cts = new CancellationTokenSource();
var progress = new Progress<double>(f => Console.Error.Write($"\r{f,6:P1}"));

RvzWriter.Write(input: input, output: output, options: options,
    progress: progress, cancellationToken: cts.Token);

5. Handling errors — every format problem raises RvzException subclasses:

try
{
    using var reader = RvzReader.Open(file);
    _ = reader.ReadFully();
}
catch (RvzHashMismatchException) { /* a SHA-1 failed (corrupt container) */ }
catch (RvzFormatException)       { /* structural damage / unsupported feature */ }

CLI

dotnet run --project RVZSharp.Cli -- header -i <file.rvz|.wia|.gcz|.ciso|.wbfs|.tgc|.nfs|.iso>
dotnet run --project RVZSharp.Cli -- verify -i <file> [-a crc32|md5|sha1]
dotnet run --project RVZSharp.Cli -- convert -i <file> -o <out> -f iso|rvz \
    [-b <block_size>] [-c none|zstd|bzip2|lzma|lzma2] [-l <level>] [-s]

The CLI accepts the same command arguments as Dolphin's dolphin-tool (convert, verify, header; extract is recognized but not implemented). convert accepts any readable blob (a plain ISO or one of the legacy formats, including split WBFS .wbfs+.wbf1… parts) and writes an RVZ file, mirroring Dolphin's converter: Wii partitions are stored decrypted with hash exceptions, raw data as-is, PRNG junk is packed with a recovered seed (Lagged Fibonacci GetSeed), and the tables carry all SHA-1 checksums. --scrub zeroes the data of non-game Wii partitions (update/channel) before converting. -f iso decodes back to a plain ISO.

Documentation

The full documentation lives in docs/ — a multi-page wiki covering the CLI, the library API, architecture, the RVZ container format, compression & packing, Wii partitions, the legacy formats, testing, packaging & distribution, roadmap and a FAQ.

Project layout

  • RVZSharp — the library: Models (container structs), Interfaces (IBlobReader, codec contracts), IO (big-endian reading, section streams), Compression (codecs + factories), Chunks (group decoding, exception lists), Packing (RVZ packing + PRNG, encoder and decoder), Wii (hash tree + region rebuild, partition extraction for the writer), RvzReader, RvzWriter. Every public and internal type and member carries XML documentation (shipped in the package as RVZSharp.xml for IntelliSense).
  • RVZSharp.Cli — the header/verify/convert tool (DolphinTool-compatible surface, plus the legacy info/decode commands).
  • RVZSharp.Tests — 313 synthetic tests (net8.0 + net9.0 + net10.0): unit (headers, tables, codecs, PRNG, packing, exceptions, region rebuild) and end-to-end round-trips of synthetic RVZ files built by TestRvzBuilder, plus writer round trips (every codec × packing, GC + Wii, legacy → RVZ, split WBFS, scrubbing), package-facing API tests (path open, ReadFully, progress, cancellation).
  • RVZSharp.Slow.Tests — 97 real-file tests (RealRvzFileTests) that decode real GameCube/Wii RVZ images byte-for-byte against their official No-Intro DAT SHA-1s. Kept out of the solution, so a plain dotnet test never runs them (~12 min); run explicitly with dotnet test RVZSharp.Slow.Tests (details in docs/testing.md).

Real-world validation

The slow suite validates the decoder and writer against actual game images on a local drive (F:\Nintendo GameCube / F:\Nintendo Wii):

  • 60 decode tests — 30 full-decode SHA-1 checks (15 GameCube + 15 Wii) plus an expected-ISO-size check per file, each compared byte-for-byte against its official No-Intro DAT entry (the canonical hash of the original disc image, from References/rvz-1.0.3/testdata/*.dat);
  • 30 structural tests — RVZ magic/version, legal chunk size, compression method and group-table sanity on every file;
  • 3 region/random-access tests — full-read hashing, ReadAt vs ReadFully across chunk boundaries, out-of-range clamping;
  • 2 writer round-trips — a real GameCube and a real Wii RVZ are re-encoded to RVZ with default options and decoded back to the same SHA-1.

The tests no-op when the files are not mounted, so the suite stays green on machines without the games. The real Wii round-trip exposed and pinned a writer bug (see Status below).

Status

RVZ and the legacy disc formats (WIA, GCZ, CISO/WBI, WBFS incl. split files, TGC, NFS) are decoded byte-for-byte and covered by tests; the CLI info/decode commands accept any of them (auto-detected by magic). The RVZ writer (rvzsharp convert) encodes any of them back to RVZ (Zstd/Bzip2/LZMA1/LZMA2/None with Dolphin's level rules — including negative Zstd "fast" levels — optional packing, chunks of 32 KiB–2 MiB powers of two or multiples of 2 MiB), with the same SHA-1s Dolphin produces. The codebase was audited against the reference implementations (Dolphin WIABlob/WIACompression and the Go rvz-1.0.3 tool) and every finding was fixed or explicitly documented.

Real-world validation is done: 30 real GameCube/Wii RVZ files decode byte-for-byte to their official No-Intro SHA-1s, and real GC/Wii images re-encode to RVZ and decode back to the same hash. That work also found and fixed a production writer bug: when re-encoding a real Wii game with the default 2 MiB chunk size, the writer used the ISO ticket key instead of the RVZ partition-table key (No-Intro dumps carry re-signed tickets whose key differs), producing files the reader rejected. RvzWriter now prefers the container's partition-table key and falls back to the ticket key for plain ISO inputs.

License

RVZSharp is copyright (c) 2025-2026 by Peterson Fernandes (github.com/drpetersonfernandes) and Pure Logic Code (github.com/purelogiccode).

The RVZ/WIA format logic in this library is derived from Dolphin, which is licensed under the GNU General Public License, version 2 or later. To stay fully compliant, RVZSharp is distributed under the same license (GPL-2.0-or-later) — see LICENSE.

All third-party code and dependencies are listed in THIRD-PARTY-NOTICES.md (MIT SharpCompress LZMA decoder port, MIT/public-domain runtime dependencies, GPL Dolphin as the format source, BSD Go reader as validation reference).

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on RVZSharp:

Package Downloads
RetroAchievementsSharp

A native C# port of the RetroAchievements hashing engine (rcheevos/RAHasher, MIT) that produces 100% identical hashes to the original for every supported console. Supports cartridge, disc (.cue/.bin/.iso/.gdi/.chd/.rvz/.wia), zip, m3u, Arcade, DOS and 3DS inputs.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 38 8/15/2026

1.0.0 release: fully documented API (XML docs), RVZ/WIA reader, legacy format
     decoders, RVZ writer with packing and hash exceptions, real-game validation suite.