Metadata-Version: 2.4
Name: wiithon
Version: 0.1.1
Summary: Wii ISO reading, patching and rebuilding library
Project-URL: Homepage, https://github.com/Demorck/wiithon
Project-URL: Issues, https://github.com/Demorck/wiithon/issues
Project-URL: Documentation, https://demorck.github.io/wiithon/
Author: demorck
License-Expression: MIT
License-File: LICENSE.md
Keywords: bcsv,bnr,dol,iso,lz77,nintendo,patching,rarc,reverse-engineering,rom-hacking,u8,wii
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: File Formats
Classifier: Topic :: Games/Entertainment
Classifier: Topic :: Software Development :: Disassemblers
Classifier: Topic :: System :: Archiving
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: pycryptodome>=3.0
Requires-Dist: rich>=13.0
Requires-Dist: typer>=0.9
Provides-Extra: dev
Requires-Dist: build; extra == 'dev'
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Description-Content-Type: text/markdown

# Wiithon

A Python library for reading, patching and rebuilding Nintendo Wii disc images.

[![PyPI](https://img.shields.io/pypi/v/wiithon)](https://pypi.org/project/wiithon/)
[![Python](https://img.shields.io/pypi/pyversions/wiithon)](https://pypi.org/project/wiithon/)
[![License](https://img.shields.io/pypi/l/wiithon)](https://github.com/Demorck/wiithon/blob/master/LICENSE.md)

## Installation

```bash
pip install wiithon
```

Requires Python 3.11 or later. Type annotations are shipped (PEP 561).

## Quick start

Read a disc image:

```python
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:

```python
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:

```python
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:

```python
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

```bash
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`:

```python
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

- [Guides and internals](https://demorck.github.io/wiithon/)
- [Examples](https://github.com/Demorck/wiithon/tree/master/examples)

## License

MIT see [LICENSE.md](https://github.com/Demorck/wiithon/blob/master/LICENSE.md).
