Reading a Wii ISO

WiiIsoReader is the entry point for inspecting a Wii ISO without modifying it.

from wiithon import WiiIsoReader

with WiiIsoReader("game.iso") as reader:
    ...

Tip

Always use it as a context manager. It holds an open file handle, and the with block guarantees it gets closed even if something raises.

Disc information

The unencrypted disc header sits at offset 0x000 and is read as soon as the ISO is opened.

with WiiIsoReader("game.iso") as reader:
    header = reader.disc_header

    print(header.game_id)        # b'RMGE01'
    print(header.game_title)     # 'SUPER MARIO GALAXY'
    print(header.disc_num)       # 0
    print(header.disc_version)   # 0

Note

game_id is raw bytes, not str. It is copied verbatim from the disc. game_title is decoded for you.

See also

Wii ISO Structure and Decryption Process describes every field of the disc header and its offset.

Partitions

A Wii disc holds one or more partitions. Most games have a DATA partition containing the game itself, and an UPDATE partition holding a system update.

with WiiIsoReader("game.iso") as reader:
    data   = reader.get_data_partition()
    update = reader.get_update_partition()
    every  = reader.get_partitions()

Warning

get_data_partition() and get_update_partition() return None when the partition is absent an update partition is optional. Check the result before passing it on.

Warning

CHANNEL partitions are not supported yet. Games that ship virtual channels, like Super Smash Bros. Brawl, expose them through get_partitions() but they cannot be opened.

Opening a partition

Opening a partition decrypts its header, reads the ticket and TMD, and loads the file system table.

with WiiIsoReader("game.iso") as reader:
    partition = reader.open_partition(reader.get_data_partition())

The result is a WiiPartitionInfo, which is what you use for everything file-related.

Listing and reading files

with WiiIsoReader("game.iso") as reader:
    partition = reader.open_partition(reader.get_data_partition())

    for path in partition.list_files():
        print(path)

    print(f"{len(partition.list_files())} files")

    data = partition.read_file("opening.bnr")

For a large disc, list_files() builds the whole list in memory. To walk the tree without materialising it, use a callback:

def show(node):
    print(node.name)

partition.callback_all_files(show)

System files

Some files live outside the file system table and have dedicated accessors.

dol       = partition.read_dol()          # main executable, parsed as DOL
apploader = partition.read_apploader()    # raw bytes
bi2       = partition.read_bi2()          # raw bytes

See also

Patching a Wii ISO to modify what you just read, and File Formats to parse the files you extracted.