-
Notifications
You must be signed in to change notification settings - Fork 0
legacy
All legacy formats are decoded to the canonical ISO view through IBlobReader. Detection
is by magic bytes (see CLI reference). Layout
details below follow Dolphin's DiscIO sources.
A compressed GameCube image, invented by GCZTool and supported by Dolphin. The header is 32 bytes; all integers little-endian.
0x00 magic u32 — 0xB10BC001 (bytes 01 C0 0B B1)
0x08 compressed_data_size u64 — size of the data area after the tables
0x10 disc_size u64 — uncompressed ISO size
0x18 block_size u32 — 0x4000 for standard images
0x1C num_blocks u32
0x20 block pointer table: 8 bytes per block
{ u64 LE offset | bit 63 = uncompressed flag }
(offset relative to the start of the compressed data; bit 63 set = block stored
uncompressed, clear = deflate-compressed)
then the hash table: u32 LE Adler-32 per block
Header area total = 0x20 + 12 · num_blocks; the size fields are validated in ulong so a
header with the top bit set cannot wrap past the bounds check. Each 0x4000-byte block of
ISO data is deflate-compressed independently; blocks with size 0 decode as zeroes.
RVZSharp decompresses with the BCL ZLibStream.
A simple block-compressed format used by old homebrew tools.
0x0000 magic "CISO"
0x0004 block_size u32 LE — 0x8000 for standard images
0x0008 block map 0x7FF8 bytes — 1 byte per block: 1 = block present, 0 = zero-fill
0x8000 present blocks, concatenated in order
The decoded length is always 0x7FF8 × block_size (the map covers 0x7FF8 blocks,
regardless of the file_size other tools write). Present blocks are served sequentially;
absent blocks decode as zeroes.
The Wii Backup File System container (a FAT-like structure in the file). Header is 512 bytes; multi-byte integers big-endian.
0x000 magic "WBFS"
0x004 hd_sector_count u32 BE — total sectors of the raw device image
0x008 hd_sector_shift u8 — raw sector size = 1 << shift
0x009 cluster_shift u8 — cluster size = 1 << shift (≥ 0x8000; 2 MiB for standard files)
0x00A disc_table[0] u8 — slot 0 present?
0x00C disc_table… disc offsets in raw sectors
0x100 disc info table (DiscHeaderSize = 256 bytes)
… disc tables: the wlba table at `raw_sector_size + 0x100`:
u16 BE cluster index per 2 MiB cluster of the disc
-
WiiDataSizeis fixed at 9,399,549,952 bytes (~9.4 GiB), so a WBFS blob always reports that logical size; clusters beyond the file are served as zeroes. - The file length must equal
hd_sector_count × hd_sector_size. - Cluster indices are u16 big-endian; the wlba table holds one entry per 2 MiB cluster
of the disc, starting at
hd_sector_size + 0x100. - RVZSharp opens the disc in slot 0.
"Tiny GameCube" images: the disc without its empty tail, plus a header. RVZSharp follows
Dolphin: the virtual image is the file minus the TGC header
(Length = file.Length − tgc_header_size), and reads are served with three on-the-fly
patches. Header fields are u32 big-endian, except the magic — the one field Dolphin reads
without byte-swapping (the on-disk bytes are the little-endian form of 0xA2380FAE):
0x000 magic AE 0F 38 A2
0x008 tgc_header_size (removed from the front when decoding)
0x010 fst_real_offset offset of the FST within the file
0x014 fst_size
0x01C dol_real_offset
0x024 file_area_real_offset
0x034 file_area_virtual_offset
Read patches:
-
Disc header rewrite — the DOL and FST offset fields at
0x420/0x424of the virtual image are rewritten toreal_offset − tgc_header_size, so the virtual disc header points into the decoded image. -
FST relocation — the FST is replaced by a relocated copy: every file entry (12 bytes,
first byte 0 = file rather than directory) has its offset field shifted by
file_area_real_offset − file_area_virtual_offset − tgc_header_sizewith u32-wrapping arithmetic (Dolphin relies on the wrap cancelling out). Entry count is clamped to the FST's actual size; a missing/unreadable FST is tolerated as empty, like Dolphin.
No decompression is involved — reads are served straight from the file with the patches applied, and hostile header values are clamped before any allocation.
Wii U–era encrypted images (the "EGGS" container). The whole image is AES-128-CBC encrypted with a console key; data is organised in LBA ranges. Header is 0x200 bytes; multi-byte integers big-endian.
0x000 magic "EGGS"
0x010 range count u32 BE (capped at 61)
0x014 LBA ranges: { start u32 BE, num u32 BE } × count,
each unit = one 0x8000-byte block
Decoding:
- The AES key comes from the sibling file
code/htk.bin(16 bytes) next to thecontentdirectory — NFS only opens when the file's directory is namedcontent(Dolphin's convention).Blob.Open(stream, nfsKey, …)bypasses the lookup. - The logical size is
0x200 + total_blocks × 0x8000; each 0x8000-byte block is decrypted with IV = 8 zero bytes + 8-byte big-endian block index (index counted over the whole image), except block 0 which uses the "0x61 hack" (the IV is derived from the header byte at 0x61, matching the real disc data). - Images larger than one file continue in
hif_000000.nfs,hif_000001.nfs, …; each file holds 0xFA00000 bytes (0x1F40 blocks), and the last 0x200 bytes of every full file belong to the next file's header region (the original disc layout has no gap there). - Reads beyond the last range (or beyond the files) decode as zeroes.