Skip to main content
The WIA (Wii Archive) and RVZ formats are compressed disc image formats for GameCube and Wii games. These formats offer superior compression compared to older formats like GCZ by supporting modern compression algorithms and storing Wii partition data decrypted without hashes.

Format Overview

WIA Features

  • Support for compression algorithms: bzip2, LZMA, and LZMA2
  • Wii partition data stored decrypted and without hashes for better compression
  • Chunk-based compression enabling random access
  • Version 1.00 as implemented in wit v2.40a

RVZ Enhancements

RVZ is based on WIA with the following improvements:
  • Zstandard compression support
  • Removed PURGE compression method
  • Support for chunk sizes smaller than 2 MiB (minimum 32 KiB, must be power of two)
  • Enhanced wia_group_t struct with per-group compression flags
  • Lossless storage of pseudorandom padding data

Data Format Conventions

All integers are big endian unless otherwise noted. Data in WIA/RVZ files can be stored in any order unless explicitly specified.
The type sha1_hash_t refers to an array of 20 bytes.

File Structures

wia_file_head_t

Stored at offset 0x0, size 0x48 bytes. This format will never be changed according to wit source code.

wia_disc_t

Stored at offset 0x48, immediately after wia_file_head_t.
NONE, PURGE, BZIP2: compr_data_len is 0LZMA (5 bytes, 7-Zip SDK format):
  • Byte 0: Encodes lc, pb, lp parameters
  • Bytes 1-4: Dictionary size (little endian)
Decoding byte 0:
LZMA2 (1 byte, 7-Zip SDK format):
  • Single byte encoding dictionary size
Zstandard (RVZ): No compressor-specific dataPreset dictionaries are not used for any compression method.

wia_part_data_t

wia_part_t

Tracks Wii partition data that is encrypted and hashed on actual discs. Does not include the unencrypted partition header (ticket, TMD, certificate chain, H3 table).
For a typical game partition, pd[0].first_sector * 0x8000 would be 0x0F820000, not 0x0F800000.
Wii partition data is stored decrypted with hashes removed. For each 0x8000 bytes on disc, 0x7C00 bytes are stored in the WIA file (before compression).

wia_raw_data_t

Tracks disc data not stored as wia_part_t. Data is stored as-is (with compression applied).
The first wia_raw_data_t has raw_data_off = 0x80 and raw_data_size = 0x4FF80, but actually contains 0x50000 bytes. Handle this by rounding offset down to previous multiple of 0x8000 and adjusting size accordingly.

wia_group_t (WIA)

Points directly to compressed disc data. Interpretation differs based on whether referenced by wia_part_data_t or wia_raw_data_t. A group normally contains chunk_size bytes of decompressed data (or chunk_size / 0x8000 * 0x7C00 for Wii partition data excluding hashes). The last group may contain less data.

rvz_group_t (RVZ)

Expanded version of wia_group_t with per-group compression control.

wia_exception_t

Represents a 20-byte difference between recalculated hash data and original hash data.
  • When recalculating hashes for a group not evenly divisible by 2 MiB, treat missing bytes as zeroes
  • wit: Only outputs exceptions for actual hash data, not padding
  • Dolphin: Outputs exceptions for both hash data and padding. For 32-byte padding areas, writes two overlapping exceptions (first 20 bytes, last 20 bytes = 12 bytes overlap)

wia_except_list_t

Each wia_group_t of Wii partition data contains one or more exception lists before the actual data. Number of lists per group: Always chunk_size / 0x200000, even for undersized groups at partition end.
Implementation limits:
  • Dolphin reading: 52×64 = 3328 exceptions max (unlimited for NONE/PURGE)
  • wit reading: Appears to support ~3008+ exceptions
  • Safe assumption: Reading code can handle at least 3328 exceptions per list
Storage:
  • PURGE: Exception lists stored uncompressed (before first wia_segment_t)
  • BZIP2, LZMA, LZMA2, Zstandard: Compressed with the rest of the data
Padding:
  • NONE, PURGE: Padding inserted after last exception list if end offset not divisible by 4
  • Other methods: No padding inserted

wia_segment_t

Used by the PURGE compression method to efficiently store runs of zeroes.
PURGE is only available in WIA, not in RVZ.
Each PURGE chunk contains:
  1. Zero or more wia_segment_t structs in ascending offset order
  2. SHA-1 hash (0x14 bytes) of exception lists (if any) and segment structs
  3. Bytes not covered by any segment are set to 0x00

RVZ Packing

RVZ introduces a packing encoding scheme for pseudorandom padding data, applied before bzip2/LZMA/Zstandard compression.

Decoding Algorithm

  1. Read 4 bytes as 32-bit unsigned big endian integer (size)
  2. If bit 31 is clear: Read size bytes and output unchanged
  3. If bit 31 is set: Clear bit 31 of size, read 68 bytes of PRNG seed data, output size bytes using PRNG
  4. Repeat until all input consumed

PRNG Algorithm

Lagged Fibonacci generator with parameters: f = xor, j = 32, k = 521
Before outputting data, check if offset (relative to disc start for wia_raw_data_t, partition data start for wia_part_t) is evenly divisible by 32 KiB.If not, advance PRNG state by offset % 0x8000 bytes first.
For wia_part_t, hashes are not counted in offset calculation, but the number is still 32 KiB (not 31 KiB).

Output Generation

Implementation Notes

Dolphin vs wit Differences

Where Dolphin’s implementation differs from wit:
  • Hash exception handling for padding areas
  • Special handling of first wia_raw_data_t offset rounding
  • Group size calculations for non-aligned partition ends
Both implementations are compatible for reading, but may produce slightly different files when writing.