Wiithon
A Python library for reading, patching and rebuilding Nintendo Wii disc images.
Installation
pip install wiithon
Requires Python 3.11 or later. Type annotations are shipped (PEP 561).
Quick start
Read a disc image:
from wiithon import WiiIsoReader
with WiiIsoReader("game.iso") as reader:
print(reader.disc_header.game_title)
partition = reader.open_partition(reader.get_data_partition())
for path in partition.list_files():
print(path)
data = partition.read_file("opening.bnr")
Patch it and write a new image:
from wiithon import WiiIsoPatcher
with WiiIsoPatcher("game.iso") as patcher:
patcher.modify_banner_title("My Hack")
patcher.replace_file("StageData/Foo.arc", new_bytes)
patcher.add_file("custom/data.bin", b"...")
patcher.build("patched.iso")
Edit a file inside an archive, without unpacking anything by hand:
from wiithon import WiiIsoPatcher, BCSV
with WiiIsoPatcher("game.iso") as patcher:
path = "StageData/CannonFleetGalaxy/CannonFleetGalaxyScenario.arc/scenariodata.bcsv"
with patcher.edit_as(path, BCSV, str_fmt="shift_jis") as bcsv:
for entry in bcsv.entries:
entry["LuigiModeTimer"] = 0
patcher.build("patched.iso")
Patch the executable:
from wiithon import WiiIsoPatcher, DOL
def patch(dol: DOL) -> None:
dol.write_at(0x80123456, b"\x60\x00\x00\x00") # nop
print(dol.read_until_null_at(0x805A1234).decode("shift_jis"))
with WiiIsoPatcher("game.iso") as patcher:
patcher.patch_dol(patch)
patcher.build("patched.iso")
What it does
Discs parses the disc header, partition table and File System Table. Partition data is decrypted on the fly, so reading one file does not mean decrypting the whole partition. Rebuilding handles re-encryption, the full H0–H3 Merkle tree and TMD fakesigning, so the result boots in Dolphin.
Building master a new image by copying an existing one, or from an
extracted sys/ + files/ directory tree. The PartitionSource interface
lets you plug in your own.
File formats DOL, BCSV, RARC, U8, Yaz0, LZ77, BNR with IMET titles. Compressed archives are resolved transparently: a path may cross into an archive, and into a Yaz0 layer wrapping it.
DOL patching read and write at virtual addresses, add text or data
sections, find code caves, locate and patch the arenaLo setter, inject
code above the arena. A PowerPC instruction encoder is included.
Command line
wiithon iso info game.iso
wiithon iso list game.iso
wiithon iso extract game.iso ./out
wiithon iso cat game.iso opening.bnr
wiithon rarc info archive.arc
wiithon rarc extract archive.arc ./out
wiithon dol caves main.dol
Errors
Anything raised because of malformed data derives from WiithonError:
from wiithon import WiiIsoReader, InvalidDiscError, FstFileNotFoundError
try:
with WiiIsoReader("maybe.iso") as reader:
...
except InvalidDiscError:
print("not a Wii disc image")
The "not found" variants also inherit from the matching builtin, so
except FileNotFoundError keeps working. Invalid arguments still raise
the usual ValueError and TypeError.
Documentation
License
MIT see LICENSE.md.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wiithon-0.1.1.tar.gz.
File metadata
- Download URL: wiithon-0.1.1.tar.gz
- Upload date:
- Size: 2.4 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
725a9b14f0ae07b68c26a0064ff9f702049c435361b4cd97d05b53b95b7a87d3
|
|
| MD5 |
1783803a3434ebd36dc23ed3192ceb8c
|
|
| BLAKE2b-256 |
54ec4f15477c4970d62ffbf122d06e9618b1af864314d451adffee7da0849e97
|
Provenance
The following attestation bundles were made for wiithon-0.1.1.tar.gz:
Publisher:
python-publish.yml on Demorck/wiithon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wiithon-0.1.1.tar.gz -
Subject digest:
725a9b14f0ae07b68c26a0064ff9f702049c435361b4cd97d05b53b95b7a87d3 - Sigstore transparency entry: 2364679157
- Sigstore integration time:
-
Permalink:
Demorck/wiithon@a021ca50cbd9b7d5fc8f8baf01518d132d9d4e9a -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Demorck
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@a021ca50cbd9b7d5fc8f8baf01518d132d9d4e9a -
Trigger Event:
release
-
Statement type:
File details
Details for the file wiithon-0.1.1-py3-none-any.whl.
File metadata
- Download URL: wiithon-0.1.1-py3-none-any.whl
- Upload date:
- Size: 77.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aeb284d16f129721f4f5b06e7940b34e7e31a6df81ae63fad101f64284aba172
|
|
| MD5 |
8c4df529c30f41218c0a980287d62979
|
|
| BLAKE2b-256 |
fbb5e56c33de60ae3490b6309b0892fce7bd3bf310439de81c3f04735b1d1e36
|
Provenance
The following attestation bundles were made for wiithon-0.1.1-py3-none-any.whl:
Publisher:
python-publish.yml on Demorck/wiithon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wiithon-0.1.1-py3-none-any.whl -
Subject digest:
aeb284d16f129721f4f5b06e7940b34e7e31a6df81ae63fad101f64284aba172 - Sigstore transparency entry: 2364679238
- Sigstore integration time:
-
Permalink:
Demorck/wiithon@a021ca50cbd9b7d5fc8f8baf01518d132d9d4e9a -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/Demorck
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@a021ca50cbd9b7d5fc8f8baf01518d132d9d4e9a -
Trigger Event:
release
-
Statement type: