libWiiPy
More actions
| libWiiPy | |
|---|---|
| General | |
| Author | NinjaCheetah |
| Type | Developments |
| Version | 0.6.0 |
| License | MIT License |
| Last Updated | 2025/02/11 |
| Links | |
| Download | |
| Website | |
| Source | |
libWiiPy is a lightweight C library designed to simplify homebrew development on the Nintendo Wii console. It provides a collection of useful utilities and abstractions to make programming for the Wii faster and easier, particularly when working alongside devkitPPC and the libogc development libraries.
Features
This list will expand as libWiiPy is developed, but these features are currently available:
- TMD and Ticket parsing/editing (
.tmd,.tik) - Title parsing/editing, including content encryption/decryption (both retail and development)
- WAD file parsing/editing (
.wad) - Downloading titles and their components from the NUS
- Certificate, TMD, and Ticket signature verification
- Packing and unpacking U8 archives (
.app,.arc) - Decompressing ASH files (
.ash, both the standard variants and the variants found in My Pokémon Ranch) - Compressing/Decompressing LZ77-compressed files
- IOS patching
- NAND-related functionality:
- EmuNAND title management (currently requires an existing EmuNAND)
content.mapparsing/editingsetting.txtparsing/editinguid.sysparsing/editing
- Limited channel banner parsing/editing
- Assorted miscellaneous features used to make the other core features possible
For a more detailed look at what's available in libWiiPy, check out our API docs.
Usage
The easiest way to get libWiiPy for your project is to install the latest version of the library from PyPI, as shown below.
pip install -U libWiiPy
Our PyPI project page can be foundhere.
Because libWiiPy is very early in development, you may want to use the latest version of the package via git instead, so that you have the latest features available. You can do that like this:
pip install -U git+https://github.com/NinjaCheetah/libWiiPy
Please be aware that because libWiiPy is in a very early state right now, many features may be subject to change, and methods and properties available now have the potential to disappear in the future.
For more tips on getting started, see our guide here.
Changelog
v0.6.0
- General Title Changes
- The Title ID of a TMD and Ticket no longer have to match their data to be successfully loaded into a Title. This configuration is still invalid, but loading this data may be required to correct it.
- When downloading anything from the NUS, you can now specify a value for the kwarg
endpoint_override, which will allow using an external endpoint. Setting this value will causewiiu_endpointto be ignored. Note that at this time, there is no validation done for provided override URLs. - Added
get_content_size()andget_content_size_blocks()to the TMD class, allowing you to get the size of the content listed in its content records. Like the related methods for getting a Title's size, these methods accept the kwargabsolutethat determines whether shared content should be included in the totals or not. - The
title_idproperty of a Ticket will now be stored as raw bytes instead of ASCII bytes, which is a more appropriate format. This may cause issues if you read this property directly, however this change will have no effect on library functions.
- EmuNAND
- Added
get_installed_titles()to get an index of all titles currently installed to an EmuNAND. - Added
get_title_tmd()andget_title_ticket()to get the TMD and Ticket of an installed title, respectively. - Title objects passed to
install_title()will now install properly if they were created from individual components rather than directly from a WAD.
- Added
- New Module:
cert- Contains a new Certificate class used to store the various certificates used by the Wii for content validation.
- Contains a new CertificateChain class used to store the entire chain of certificates needed a validate an entire Wii title.
- Adds the function
validate_ca_cert()for validating a retail or development CA certificate. - Adds the function
validate_cert_sig()for validating any TMD or Ticket certificate using a CA certificate. - Adds the functions
validate_tmd_sig()andvalidate_ticket_sig()for validating a TMD or Ticket using the appropriate certificates.
- New Module:
lz77- Adds the function
decompress_lz77()to decompress any file that was compressed using the Wii's flavor of the LZ77 compression algorithm. - Adds the function
compress_lz77()to compress any file using the Wii's flavor of the LZ77 compression algorithm. Supports two levels of compression, labeled as just 1 or 2, with 1 being the default. This function is currently very slow when run on files greater than a couple hundred kilobytes.
- Adds the function
- New Class: IMETHeader
- New class for handling the IMET header that precedes the data of a banner in a Wii channel. This header stores the name of the channel for every applicable region, as well as the sizes of the banner's files.
- This class is mostly just for parsing right now, but in the future when more banner support is added, you'll be able to use it for other banner-creation functionality.
- Provides the methods
get_channel_names()andset_channel_names()to get or set the channel name for the specified region(s).
- New Class: IMD5Header
- New class for storing the information stored in an IMD5 header. This is currently only a data class, as the banner parsing functionality required to extend it doesn't exist yet.
v0.5.2
- Content
- Reverted changes to how content indices were processed. In v0.5.0, all methods for
ContentRegion()s that took an index as a parameter were changed to resolve that index by finding the content record that contained it and then using that, rather than just going to the literal position of that index in order. This change was made to fix support for WADs where the index of the content in the record didn't match the literal index, but introduced issues related to getting/decrypting content as well as setting/encrypting it. - As a replacement for the complicated and ultimately problematic solution referenced above, methods in
ContentRegion()s that take indices will now resolve to the literal index again, but will still resolve to the content index when required for decryption. This fixes the same issue without introducing behavior different from the v0.4.x API.
- Reverted changes to how content indices were processed. In v0.5.0, all methods for
- Title Parsing and Editing
- The
get_common_key()method now accepts the kwargdev, which when set to True will cause the method to return the development Wii Common Key instead of the retail one when key 0 is requested. Keys 1 and 2 are unaffected by this argument. - The crypto methods
encrypt_title_key()anddecrypt_title_key()now accept the kwarddev, which when set to True will cause them to pass that True along toget_common_key(), allowing them to successfully decrypt the Title Key of a development title. - The signature issuer of a Ticket is now parsed during load, and the new
Ticket()propertyis_devwill be set to True if the signature issuer is the one used for development titles. - The
Ticket()methodget_title_key()and theTitle()methodset_title_id()now pass the newTicketpropertyis_devalong todecrypt_title_key()andset_title_id(), respectively, to allow for proper support of development titles across the library. - Combined, these features allow for seamless decryption of content from development titles with no explicit intervention required under typical use.
- The
v0.5.1
- General
- The NAND-related modules
emunandandsyshave been moved under a newnandsubpackage. You will now need to reference them using thelibWiiPy.nandprefix instead oflibWiiPy.title. An overview of this new subpackage can be found in the API documentation.
- The NAND-related modules
- Title Parsing and Editing
- TMD regions have been changed to the more correct region code system, rather than returning the full names of the regions. These codes are as follows:
USA,EUR,JPN, andKOR. - The
Title()class now offersget_title_size()andget_title_size_blocks()to get the size of the entire title in either bytes or blocks, respectively. Both methods accept the kwargabsoluteto determine whether shared content should be included in the total or not. - Title types are now returned correctly from the
TMD()class'get_title_type()method. This previously read an incorrect field in the TMD and would always returnSystemregardless of the actual type. - Adding new content to an existing title now works as expected. Previously, the
num_contentsproperty of the TMD was not updated, so content added beyond the original count would not be saved when dumping a WAD. ContentRegion()now offersremove_content_by_index()andremove_content_by_cid()to remove a specified content from a title.Title()now offersadd_content()andadd_enc_content()so that you do not have to interface with the underlyingContentRegion()directly to add new content to a title.ContentRegion()now offers the methodget_index_from_cid()to resolve a content index from a Content ID.
- TMD regions have been changed to the more correct region code system, rather than returning the full names of the regions. These codes are as follows:
- New Class: SettingTxt
- New class for handling the
setting.txtfile used by the System Menu to store your console's region and serial number. - Allows for parsing
setting.txtby decrypting it and loading the keys, allowing you to edit them, and for re-encrypting the file for use on a console.
- New class for handling the
v0.5.0
- General
- The TMD, Ticket, and Title classes now all offer
get_is_fakesigned()to check whether the loaded TMD and/or Ticket is fakesigned. For a Title, this checks both the TMD and Ticket and only returns True if they are both fakesigned. - Content records with content indices that don't match the literal index of the record are now handled correctly on the dumping side. The loading side was already working as expected.
- The TMD, Ticket, and Title classes now all offer
set_title_version()to correctly set a new version number. For a Title, this sets the version in both the TMD and Ticket. get_common_key()now falls back on key 0 (the normal common key) instead of raising an exception when an invalid key index is supplied. This fixes handling tickets with strange values set as the key index.- Fixed a case where a Title ID formatted in a certain way would not be converted properly to an IV during Title Key decryption.
- The footer is now read from/written to the correct portion of a WAD. Y'know, the foot. Where it always should've been.
- The title version can be converted to a friendlier format (vX.X) for supported titles. This mostly only produces useful results for the System Menu, whose values are hard-coded, IOS, and most first-party downloadable channels.
- U8 archives are now all extracted properly, and packing is much closer to official Nintendo-made U8 archives.
- The TMD, Ticket, and Title classes now all offer
- New Class: SharedContentMap
- New class for handling the
content.mapfile used by the Wii to manage shared content. - Allows for parsing an existing map, initializing a new one, and adding entries.
- New entries return the shared content ID that was assigned to them when added.
- New class for handling the
- New Class: IOSPatcher
- New class for applying patches to loaded IOS Title objects.
- Currently supported stable patches include:
patch_fakesigning(),patch_es_identify(),patch_nand_access(), andpatch_version_downgrading(). More can be read about these patches in the API documentation, though they are the same as patches done by legacy tools. - Experimental patch for disabling querying the disc drive, mostly for vWii users without a drive installed. This patch is still a work in progress and may cause unexpected side effects on some setups. This patch is not included in
patch_all().
- New Class: EmuNAND
- New class for creating and managing EmuNANDs.
- Currently only supports installing titles to an EmuNAND and removing installed titles.
- Not currently complete enough to create a fresh, working EmuNAND, but it can safely modify an existing one, and creates enough data that you can install WADs to a blank folder with it and give it to Dolphin and it can fill in the gaps to boot it.
- New Class: UidSys
- New class for handling the
uid.sysfile used by the Wii to track all titles ever present on the console. - Allows for parsing an existing file, initializing a new one, and adding new entries.
- New entries return the UID assigned to them when added.
- New class for handling the
- Content
- Much of the ContentRegion class was rewritten from scratch, providing much more clarity. This is also represented in the improved docstrings and API documentation generated from them.
- The ContentRegion class now entirely relies on the true content indices specified in the content records. This means that getting or setting a certain index may actually be changing a different index than expected, because the content index of the record there differs from the index of the record. This should not matter in most cases.
- Distinctions between
load_content()/add_content()/set_content()and their encrypted counterparts are now much clearer. - Get methods now support skipping the hash checks for decryption. This will print out a warning if the check failed that it is being ignored. This behavior cannot be changed.
- Title
- A major bug was fixed where edited content records weren't being copied from the ContentRegion (where they were being edited) to the TMD before dumping a WAD.
- The Title Key will now be properly re-encrypted when setting the Title ID in a Title object.
- Added
get_title_size()andget_title_size_blocks()to get the installed size of the title in bytes and blocks, respectively.
- TMD
- A TMD's
access_rightsproperty is now properly stored as an integer. - TMDs now offer the
AccessFlagsenum that defines the bits used to determine and set access rights. Current values areDVD_VIDEOandAHB. - New method
get_access_right()that takes a bit to check and returns True/False based on if that bit is enabled or not. Recommended to be used alongsideAccessFlags. - Title types and content types are now handled properly. This does not impact
get_title_type()as it only changed the backend for it and not the return values. For getting the content type, you now must useget_content_type()and specify the content index that you want the type of.
- A TMD's
v0.4.0
- The tmd and ticket modules now offer a fakesign() method, that will fakesign the object it is being used on in-place. You can then dump the TMD or Ticket back into data after using this method, and the resulting file will be fakesigned.
- The title module now offers fakesign() as well to automatically fakesign the TMD and Ticket of the loaded title. You can then dump the title to a WAD, and it will be fakesigned and installable with any IOS vulnerable to the trucha bug.
- Added code to the tmd module to load/dump the minor version key to or from a TMD, which was previously ignored as it goes totally unused. This was needed for fakesigning support.
- Fixed the way some title versions were handled in the tmd module, namely the Wii Menu. Versions converted to vX.X format would sometimes not convert back to vXXX format correctly.
- Known Issues:
- There are some known issues with the u8 module, meaning that some U8 archives may not extract correctly. This is being looked into and will hopefully be fixed soon.
v0.4.0
- Added new ash module to handle decompressing ASH files (both the common variant in the Wii Menu and games like Animal Crossing: City Folk, and also the other variant found in My Pokémon Ranch)
- New function decompress_ash() to decompress an ASH file, part of the libWiiPy.archive subpackage
- Many functions and classes that were previously public have been made private, as they were not designed for general use and could be confusing when they were automatically imported
- U8 archives can now be extracted to an existing empty directory (as opposed to the previous behavior of requiring the target directory to not already exist)
- The components of a TMD's signature (the type, the signature itself, and the padding afterwards) have all been separated out, which matches how Tickets have always handled these properties
- Fixed a major bug where IOS WADs made using legacy tools (NUS Downloader, Sharpii, etc.) could not be extracted by libWiiPy
- Fixed a bug where the content region size in the WAD header of IOS WADs would be calculated incorrectly, creating WADs that could not be extracted properly (this also guarantees consistency with WADs created using legacy tools)
v0.3.1
- pack_u8() now raises a FileNotFound error if the input path doesn't match the file or directory check. Previously, this function would silently fail and do nothing if the input path was invalid, with no indication that the file or directory was not found.
v0.3.0
- Added new u8 module to handle U8 archive files (files with extensions .app, .arc, .carc, and .szs)
- New classes U8Archive and U8Node to assist in U8 handling, however these are unlikely to be used directly under normal use
- New function pack_u8() to pack a file or folder into a U8 archive
- New function extract_u8() to extract a U8 archive into a folder
- Completely redid package structure! This is breaking!
- All title-related modules have been moved into the subpackage title and can now be accessed with the prefix libWiiPy.title instead of only libWiiPy
- New archive-related modules like the new u8 one are located under the prefix libWiiPy.archive
- Added the basics for writing tests for the library in the future
v0.2.3
- Added the ability to use the Wii U NUS endpoint (http://ccs.cdn.wup.shop.nintendo.net/ccs/download/) to the NUS module, allowing you to get a decent speed increase with downloads by adding wiiu_endpoint=True to any NUS function.
- Added encrypt_title_key() to the Crypto module, allowing you to re-encrypt any decrypted Title Key with any common key you choose.
- Improved IV handling when decrypting Title Keys in the Crypto module, so that you can now pass the Title ID used as the IV in any of three formats (b'0102', b'\x01\x02', "0102").
- Replaced unnecessary uses of BytesIO objects when dumping WAD, TMD, Ticket, and Content objects back into raw data.
- Updated comments in the TMD module that describe various properties stored in a TMD thanks to new information from @rvtr.
- The TMD module now reads and writes two "reserved" regions of a TMD that were previously ignored and written out as all zeroes, because they were found to be critical on the DSi in libTWLPy, and may be important here.
v0.2.2
- Changed the NUS endpoint URL from http://ccs.shop.wii.com/ccs/download to https://nus.cdn.shop.wii.com/ccs/download, which massively improves NUS download speeds. Really should've figured this one out sooner...
- boot2 WADs are now dumped properly as type ib instead of type Is.
- The TMD instance method get_title_type() now returns GameChannel instead of GameWithChannel for a TID high of 00010004, since this ID refers to channels installed by games and not the games themselves.
v0.2.1
- Functions are now available for downloading the TMD, Ticket (for free titles), general WAD certificate (which is obtained by downloading the raw TMD and Ticket of System Menu 4.3U as it never changes), and encrypted contents for a title.
- boot2 WADs are now accepted as valid when loading WAD data into a WAD object, thanks to testing by @rvtr confirming that these files work.
v0.2.0
- Entirely restructured wad.py, tmd.py, ticket.py, content.py
- Added title.py for higher-level access to an entire WAD and all of its components without having to handle each one separately
- Fixed a bug in content.py and removed a mitigation for that bug in crypto.py that also caused issues
- Added support for for re-encryption of content and for that content to be loaded back into a ContentRegion
- Added support for dumping TMD, Ticket, ContentRegion, and WAD objects back into raw data for outputting
- Added support for creating blank objects of each type so that data can be loaded into them after creation, rather than forcing you to have that data beforehand (this allows title.py to actually function for creating a new WAD from loose files)
- Removed unnecessary instance attributes that didn't need to be exposed and would become poisoned upon any changes
- Removed some remaining instance methods that just retrieved instance attributes that you could already access
- Replaced content.py's get_enc_content() and get_content() with get_enc_content_by_id()/get_enc_content_by_cid() and get_content_by_id() and get_content_by_cid() to allow getting content by either its content index or ID
v0.1.0
- First Release.
Special Thanks
This project wouldn't be possible without the amazing people behind its predecessors and all of the people who have contributed to the documentation of the Wii's inner workings over at WiiBrew.
Special Thanks to People Behind Related Projects
- Xuzz, SquidMan, megazig, Matt_P, Omega and The Lemon Man for creating Wii.py
- Leathl for creating libWiiSharp
- TheShadowEevee for maintaining libWiiSharp
Special Thanks to WiiBrew Contributors
Thank you to all of the contributors to the documentation on the WiiBrew pages that make this all understandable! Some of the key articles referenced are as follows:
- Title metadata, for the documentation on how a TMD is structured
- WAD files, for the documentation on how a WAD is structured
- IOS history, for the documentation on IOS TIDs and how IOS is versioned
One additional special thanks to @DamiDoop!
She made the very cool banner you can see at the top of this README, and has also helped greatly with my sanity throughout debugging this library.