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.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/dolphin-emu/dolphin/llms.txt
Use this file to discover all available pages before exploring further.
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_tstruct 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.
sha1_hash_t refers to an array of 20 bytes.
File Structures
wia_file_head_t
Stored at offset0x0, size 0x48 bytes. This format will never be changed according to wit source code.
Version Number Format
Version Number Format
| Type and Name | Description |
|---|---|
char magic[4] | Always contains "WIA\x1" |
u32 version | The WIA format version |
u32 version_compatible | Minimum version required to read this file. Can be lower than version (wit v2.40a: version=0x01000000, compatible=0x00090000) |
u32 disc_size | Size of the wia_disc_t struct. wit v2.40a always includes the full 7 bytes of compr_data |
sha1_hash_t disc_hash | SHA-1 hash of the wia_disc_t struct. Number of bytes to hash is determined by disc_size |
u64 iso_file_size | Original size of the disc (equivalent ISO file size) |
u64 wia_file_size | Size of this WIA/RVZ file |
sha1_hash_t file_head_hash | SHA-1 hash of this struct, up to but not including file_head_hash itself |
wia_disc_t
Stored at offset0x48, immediately after wia_file_head_t.
| Type and Name | Description |
|---|---|
u32 disc_type | 0 = unknown, 1 = GameCube, 2 = Wii |
u32 compression | 0 = NONE, 1 = PURGE, 2 = BZIP2, 3 = LZMA, 4 = LZMA2, 5 = Zstandard (RVZ only) |
u32 compr_level | Compression level used (compressor-specific, informational only). Treat as signed for RVZ due to negative Zstandard levels |
u32 chunk_size | Size of data chunks. WIA: must be multiple of 2 MiB. RVZ: minimum 32 KiB, must be power of two if <2 MiB |
u8 dhead[0x80] | First 0x80 bytes of the disc image |
u32 n_part | Number of wia_part_t structs |
u32 part_t_size | Size of one wia_part_t struct. If smaller than expected, fill missing bytes with 0x00 |
u64 part_off | File offset where wia_part_t structs are stored (uncompressed) |
sha1_hash_t part_hash | SHA-1 hash of the wia_part_t structs (n_part * part_t_size bytes) |
u32 n_raw_data | Number of wia_raw_data_t structs |
u64 raw_data_off | File offset where wia_raw_data_t structs are stored (compressed) |
u32 raw_data_size | Total compressed size of wia_raw_data_t structs |
u32 n_groups | Number of wia_group_t structs |
u64 group_off | File offset where wia_group_t structs are stored (compressed) |
u32 group_size | Total compressed size of wia_group_t structs |
u8 compr_data_len | Number of used bytes in compr_data array |
u8 compr_data[7] | Compressor-specific data |
Compression-Specific Data
Compression-Specific Data
NONE, PURGE, BZIP2: LZMA2 (1 byte, 7-Zip SDK format):Zstandard (RVZ): No compressor-specific dataPreset dictionaries are not used for any compression method.
compr_data_len is 0LZMA (5 bytes, 7-Zip SDK format):- Byte 0: Encodes
lc,pb,lpparameters - Bytes 1-4: Dictionary size (little endian)
- Single byte encoding dictionary size
wia_part_data_t
| Type and Name | Description |
|---|---|
u32 first_sector | Starting sector on disc for this data (1 sector = 32 KiB or 31 KiB excluding hashes) |
u32 n_sectors | Number of sectors covered by this struct |
u32 group_index | Index of first wia_group_t struct. Other indices follow sequentially |
u32 n_groups | Number of wia_group_t structs used for this data |
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.0x8000 bytes on disc, 0x7C00 bytes are stored in the WIA file (before compression).
| Type and Name | Description |
|---|---|
u8 part_key[16] | Title key for this partition (128-bit AES). Already decrypted, can be used directly without Wii common key |
wia_part_data_t pd[2] | Segment 0: Small segment for management data (boot to FST). Segment 1: Remaining data. Split point is FST end offset rounded up to next 2 MiB |
wia_raw_data_t
Tracks disc data not stored aswia_part_t. Data is stored as-is (with compression applied).
| Type and Name | Description |
|---|---|
u64 raw_data_off | Offset on disc where this data starts |
u64 raw_data_size | Number of bytes on disc covered by this struct |
u32 group_index | Index of first wia_group_t struct. Other indices follow sequentially |
u32 n_groups | Number of wia_group_t structs used for this data |
wia_group_t (WIA)
Points directly to compressed disc data. Interpretation differs based on whether referenced bywia_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.
| Type and Name | Description |
|---|---|
u32 data_off4 | File offset where compressed data is stored, divided by 4 |
u32 data_size | Size of compressed data, including wia_except_list_t structs and required padding. 0 = special case: all decompressed data is 0x00 and exception lists (if any) contain 0 exceptions |
rvz_group_t (RVZ)
Expanded version ofwia_group_t with per-group compression control.
| Type and Name | Description |
|---|---|
u32 data_off4 | File offset where compressed data is stored, divided by 4 |
u32 data_size | Bit 31: 1 if using compression method from wia_disc_t, 0 if using NONE. Bits 0-30: Size of compressed data including exception lists and padding. 0 = special case: all data is 0x00 with 0 exceptions |
u32 rvz_packed_size | Size after decompression but before RVZ unpacking. 0 = RVZ packing not used for this group |
wia_exception_t
Represents a 20-byte difference between recalculated hash data and original hash data.Implementation Notes
Implementation Notes
- 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)
| Type and Name | Description |
|---|---|
u16 offset | Offset among the hashes. Offsets 0x0000-0x0400 map to 0x0000-0x0400 in full 2 MiB; offsets 0x0400-0x0800 map to 0x8000-0x8400, etc. Resets to 0 for each new wia_except_list_t |
sha1_hash_t hash | Hash to replace the automatically generated hash. Apply after calculating all hashes for current 2 MiB but before encrypting |
wia_except_list_t
Eachwia_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.
| Type and Name | Description |
|---|---|
u16 n_exceptions | Number of wia_exception_t structs |
wia_exception_t exception[n_exceptions] | Each entry describes one hash difference |
Compression Method Exceptions
Compression Method Exceptions
Storage:
- PURGE: Exception lists stored uncompressed (before first
wia_segment_t) - BZIP2, LZMA, LZMA2, Zstandard: Compressed with the rest of the data
- 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.
| Type and Name | Description |
|---|---|
u32 offset | Offset of data within decompressed data (exception lists not counted) |
u32 size | Number of bytes in data |
u8 data[size] | Data bytes |
- Zero or more
wia_segment_tstructs in ascendingoffsetorder - SHA-1 hash (0x14 bytes) of exception lists (if any) and segment structs
- 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
- Read 4 bytes as 32-bit unsigned big endian integer (
size) - If bit 31 is clear: Read
sizebytes and output unchanged - If bit 31 is set: Clear bit 31 of
size, read 68 bytes of PRNG seed data, outputsizebytes using PRNG - Repeat until all input consumed
PRNG Algorithm
Lagged Fibonacci generator with parameters: f = xor, j = 32, k = 521Offset Alignment
Offset Alignment
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_toffset rounding - Group size calculations for non-aligned partition ends
Both implementations are compatible for reading, but may produce slightly different files when writing.