Improved docstrings and made them all much more consistent across the project

This commit is contained in:
Campbell 2024-04-03 18:05:12 -04:00
parent 7c631454a1
commit e85eae567a
Signed by: NinjaCheetah
GPG Key ID: B547958AF96ED344
10 changed files with 179 additions and 82 deletions

View File

@ -1,5 +1,7 @@
# "__init__.py" from libWiiPy by NinjaCheetah & Contributors # "__init__.py" from libWiiPy by NinjaCheetah & Contributors
# https://github.com/NinjaCheetah/libWiiPy # https://github.com/NinjaCheetah/libWiiPy
#
# These are the essential modules from libWiiPy that you'd probably want imported by default.
from .commonkeys import * from .commonkeys import *
from .content import * from .content import *

View File

@ -8,8 +8,9 @@ korean_key = '63b82bb4f4614e2e13f2fefbba4c9b7e'
vwii_key = '30bfc76e7c19afbb23163330ced7c28d' vwii_key = '30bfc76e7c19afbb23163330ced7c28d'
def get_common_key(common_key_index): def get_common_key(common_key_index) -> bytes:
"""Gets the specified Wii Common Key based on the index provided. """
Gets the specified Wii Common Key based on the index provided.
Possible values for common_key_index: 0: Common Key, 1: Korean Key, 2: vWii Key Possible values for common_key_index: 0: Common Key, 1: Korean Key, 2: vWii Key

View File

@ -12,7 +12,16 @@ from .crypto import decrypt_content, encrypt_content
class ContentRegion: class ContentRegion:
"""Creates a ContentRegion object to parse the continuous content region of a WAD. """
A ContentRegion object to parse the continuous content region of a WAD. Allows for retrieving content from the
region in both encrypted or decrypted form, and setting new content.
Attributes
----------
content_records : List[ContentRecord]
The content records for the content stored in the region.
num_contents : int
The total number of contents stored in the region.
""" """
def __init__(self): def __init__(self):
@ -23,7 +32,8 @@ class ContentRegion:
self.content_list: List[bytes] = [] self.content_list: List[bytes] = []
def load(self, content_region: bytes, content_records: List[ContentRecord]) -> None: def load(self, content_region: bytes, content_records: List[ContentRecord]) -> None:
"""Loads the raw content region and builds a list of all the contents. """
Loads the raw content region and builds a list of all the contents.
Parameters Parameters
---------- ----------
@ -59,7 +69,8 @@ class ContentRegion:
self.content_list.append(content_enc) self.content_list.append(content_enc)
def dump(self) -> bytes: def dump(self) -> bytes:
"""Takes the list of contents and assembles them back into one content region. Returns this content region as a """
Takes the list of contents and assembles them back into one content region. Returns this content region as a
bytes object and sets the raw content region variable to this result, then calls load() again to make sure the bytes object and sets the raw content region variable to this result, then calls load() again to make sure the
content list matches the raw data. content list matches the raw data.
@ -85,7 +96,8 @@ class ContentRegion:
return content_region_raw return content_region_raw
def get_enc_content_by_index(self, index: int) -> bytes: def get_enc_content_by_index(self, index: int) -> bytes:
"""Gets an individual content from the content region based on the provided index, in encrypted form. """
Gets an individual content from the content region based on the provided index, in encrypted form.
Parameters Parameters
---------- ----------
@ -101,7 +113,8 @@ class ContentRegion:
return content_enc return content_enc
def get_enc_content_by_cid(self, cid: int) -> bytes: def get_enc_content_by_cid(self, cid: int) -> bytes:
"""Gets an individual content from the content region based on the provided Content ID, in encrypted form. """
Gets an individual content from the content region based on the provided Content ID, in encrypted form.
Parameters Parameters
---------- ----------
@ -127,7 +140,8 @@ class ContentRegion:
return content_enc return content_enc
def get_enc_contents(self) -> List[bytes]: def get_enc_contents(self) -> List[bytes]:
"""Gets a list of all encrypted contents from the content region. """
Gets a list of all encrypted contents from the content region.
Returns Returns
------- -------
@ -137,7 +151,8 @@ class ContentRegion:
return self.content_list return self.content_list
def get_content_by_index(self, index: int, title_key: bytes) -> bytes: def get_content_by_index(self, index: int, title_key: bytes) -> bytes:
"""Gets an individual content from the content region based on the provided index, in decrypted form. """
Gets an individual content from the content region based on the provided index, in decrypted form.
Parameters Parameters
---------- ----------
@ -168,7 +183,8 @@ class ContentRegion:
return content_dec return content_dec
def get_content_by_cid(self, cid: int, title_key: bytes) -> bytes: def get_content_by_cid(self, cid: int, title_key: bytes) -> bytes:
"""Gets an individual content from the content region based on the provided Content ID, in decrypted form. """
Gets an individual content from the content region based on the provided Content ID, in decrypted form.
Parameters Parameters
---------- ----------
@ -196,7 +212,8 @@ class ContentRegion:
return content_dec return content_dec
def get_contents(self, title_key: bytes) -> List[bytes]: def get_contents(self, title_key: bytes) -> List[bytes]:
"""Gets a list of all contents from the content region, in decrypted form. """
Gets a list of all contents from the content region, in decrypted form.
Parameters Parameters
---------- ----------
@ -216,7 +233,8 @@ class ContentRegion:
def set_enc_content(self, enc_content: bytes, cid: int, index: int, content_type: int, content_size: int, def set_enc_content(self, enc_content: bytes, cid: int, index: int, content_type: int, content_size: int,
content_hash: bytes) -> None: content_hash: bytes) -> None:
"""Sets the provided index to a new content with the provided Content ID. Hashes and size of the content are """
Sets the provided index to a new content with the provided Content ID. Hashes and size of the content are
set in the content record, with a new record being added if necessary. set in the content record, with a new record being added if necessary.
Parameters Parameters
@ -257,8 +275,9 @@ class ContentRegion:
self.content_list[index] = enc_content self.content_list[index] = enc_content
def set_content(self, dec_content: bytes, cid: int, index: int, content_type: int, title_key: bytes) -> None: def set_content(self, dec_content: bytes, cid: int, index: int, content_type: int, title_key: bytes) -> None:
"""Sets the provided index to a new content with the provided Content ID. Hashes and size of the content are """
set in the content record, with a new record being added if necessary. Sets the provided index to a new content with the provided Content ID. Hashes and size of the content are
set in the content record, with a new record being added if necessary.
Parameters Parameters
---------- ----------
@ -283,7 +302,8 @@ class ContentRegion:
self.set_enc_content(enc_content, cid, index, content_type, dec_content_size, dec_content_hash) self.set_enc_content(enc_content, cid, index, content_type, dec_content_size, dec_content_hash)
def load_enc_content(self, enc_content: bytes, index: int) -> None: def load_enc_content(self, enc_content: bytes, index: int) -> None:
"""Loads the provided encrypted content into the content region at the specified index, with the assumption that """
Loads the provided encrypted content into the content region at the specified index, with the assumption that
it matches the record at that index. Not recommended for most use cases, use decrypted content and it matches the record at that index. Not recommended for most use cases, use decrypted content and
load_content() instead. load_content() instead.
@ -303,7 +323,8 @@ class ContentRegion:
self.content_list[index] = enc_content self.content_list[index] = enc_content
def load_content(self, dec_content: bytes, index: int, title_key: bytes) -> None: def load_content(self, dec_content: bytes, index: int, title_key: bytes) -> None:
"""Loads the provided decrypted content into the content region at the specified index, but first checks to make """
Loads the provided decrypted content into the content region at the specified index, but first checks to make
sure it matches the record at that index before loading. This content will be encrypted when loaded. sure it matches the record at that index before loading. This content will be encrypted when loaded.
Parameters Parameters

View File

@ -7,7 +7,8 @@ from Crypto.Cipher import AES
def decrypt_title_key(title_key_enc, common_key_index, title_id) -> bytes: def decrypt_title_key(title_key_enc, common_key_index, title_id) -> bytes:
"""Gets the decrypted version of the encrypted Title Key provided. """
Gets the decrypted version of the encrypted Title Key provided.
Requires the index of the common key to use, and the Title ID of the title that the Title Key is for. Requires the index of the common key to use, and the Title ID of the title that the Title Key is for.
@ -37,7 +38,8 @@ def decrypt_title_key(title_key_enc, common_key_index, title_id) -> bytes:
def decrypt_content(content_enc, title_key, content_index, content_length) -> bytes: def decrypt_content(content_enc, title_key, content_index, content_length) -> bytes:
"""Gets the decrypted version of the encrypted content. """
Gets the decrypted version of the encrypted content.
This requires the index of the content to decrypt as it is used as the IV, as well as the content length to adjust This requires the index of the content to decrypt as it is used as the IV, as well as the content length to adjust
padding as necessary. padding as necessary.
@ -76,7 +78,8 @@ def decrypt_content(content_enc, title_key, content_index, content_length) -> by
def encrypt_content(content_dec, title_key, content_index) -> bytes: def encrypt_content(content_dec, title_key, content_index) -> bytes:
"""Gets the encrypted version of the decrypted content. """
Gets the encrypted version of the decrypted content.
This requires the index of the content to encrypt as it is used as the IV, as well as the content length to adjust This requires the index of the content to encrypt as it is used as the IV, as well as the content length to adjust
padding as necessary. padding as necessary.

View File

@ -1,8 +1,12 @@
# "shared.py" from libWiiPy by NinjaCheetah & Contributors # "shared.py" from libWiiPy by NinjaCheetah & Contributors
# https://github.com/NinjaCheetah/libWiiPy # https://github.com/NinjaCheetah/libWiiPy
#
# This file defines general functions that may be useful in other modules of libWiiPy. Putting them here cuts down on
# clutter in other files.
def align_value(value, alignment=64): def align_value(value, alignment=64) -> int:
"""Aligns the provided value to the set alignment (defaults to 64). """
Aligns the provided value to the set alignment (defaults to 64).
Parameters Parameters
---------- ----------
@ -22,8 +26,9 @@ def align_value(value, alignment=64):
return value return value
def pad_bytes_stream(data, alignment=64): def pad_bytes_stream(data, alignment=64) -> bytes:
"""Pads the provided bytes stream to the provided alignment (defaults to 64). """
Pads the provided bytes stream to the provided alignment (defaults to 64).
Parameters Parameters
---------- ----------

View File

@ -12,8 +12,7 @@ from typing import List
class Ticket: class Ticket:
""" """
Creates a Ticket object that allows for either loading and editing an existing Ticket or creating one manually if A Ticket object that allows for either loading and editing an existing Ticket or creating one manually if desired.
desired.
Attributes Attributes
---------- ----------
@ -58,7 +57,8 @@ class Ticket:
# TODO: Write in v1 ticket attributes here. This code can currently only handle v0 tickets, and will reject v1. # TODO: Write in v1 ticket attributes here. This code can currently only handle v0 tickets, and will reject v1.
def load(self, ticket: bytes) -> None: def load(self, ticket: bytes) -> None:
"""Loads raw Ticket data and sets all attributes of the WAD object. This allows for manipulating an already """
Loads raw Ticket data and sets all attributes of the WAD object. This allows for manipulating an already
existing Ticket. existing Ticket.
Parameters Parameters
@ -138,7 +138,8 @@ class Ticket:
self.title_limits_list.append(TitleLimit(limit_type, limit_value)) self.title_limits_list.append(TitleLimit(limit_type, limit_value))
def dump(self) -> bytes: def dump(self) -> bytes:
"""Dumps the Ticket object back into bytes. This also sets the raw Ticket attribute of Ticket object to the """
Dumps the Ticket object back into bytes. This also sets the raw Ticket attribute of Ticket object to the
dumped data, and triggers load() again to ensure that the raw data and object match. dumped data, and triggers load() again to ensure that the raw data and object match.
Returns Returns
@ -209,8 +210,9 @@ class Ticket:
# Return the raw TMD for the data contained in the object. # Return the raw TMD for the data contained in the object.
return ticket_data_raw return ticket_data_raw
def get_title_id(self): def get_title_id(self) -> str:
"""Gets the Title ID of the ticket's associated title. """
Gets the Title ID of the ticket's associated title.
Returns Returns
------- -------
@ -220,8 +222,9 @@ class Ticket:
title_id_str = str(self.title_id.decode()) title_id_str = str(self.title_id.decode())
return title_id_str return title_id_str
def get_common_key_type(self): def get_common_key_type(self) -> str:
"""Gets the name of the common key used to encrypt the Title Key contained in the ticket. """
Gets the name of the common key used to encrypt the Title Key contained in the ticket.
Returns Returns
------- -------
@ -240,8 +243,9 @@ class Ticket:
case 2: case 2:
return "vWii" return "vWii"
def get_title_key(self): def get_title_key(self) -> bytes:
"""Gets the decrypted title key contained in the ticket. """
Gets the decrypted title key contained in the ticket.
Returns Returns
------- -------
@ -251,8 +255,9 @@ class Ticket:
title_key = decrypt_title_key(self.title_key_enc, self.common_key_index, self.title_id) title_key = decrypt_title_key(self.title_key_enc, self.common_key_index, self.title_id)
return title_key return title_key
def set_title_id(self, title_id): def set_title_id(self, title_id) -> None:
"""Sets the Title ID of the title in the Ticket. """
Sets the Title ID of the title in the Ticket.
Parameters Parameters
---------- ----------

View File

@ -10,10 +10,15 @@ from .wad import WAD
class Title: class Title:
"""Creates a Title object that contains all components of a title, and allows altering them. """
A Title object that contains all components of a title, and allows altering them. Provides higher-level access
than manually creating WAD, TMD, Ticket, and ContentRegion objects and ensures that any data that needs to match
between files matches.
Attributes Attributes
---------- ----------
wad : WAD
A WAD object of a WAD containing the title's data.
tmd : TMD tmd : TMD
A TMD object of the title's TMD. A TMD object of the title's TMD.
ticket : Ticket ticket : Ticket
@ -28,7 +33,8 @@ class Title:
self.content: ContentRegion = ContentRegion() self.content: ContentRegion = ContentRegion()
def load_wad(self, wad: bytes) -> None: def load_wad(self, wad: bytes) -> None:
"""Load existing WAD data into the title and create WAD, TMD, Ticket, and ContentRegion objects based off of it """
Load existing WAD data into the title and create WAD, TMD, Ticket, and ContentRegion objects based off of it
to allow you to modify that data. Note that this will overwrite any existing data for this title. to allow you to modify that data. Note that this will overwrite any existing data for this title.
Parameters Parameters
@ -55,7 +61,8 @@ class Title:
"invalid.") "invalid.")
def dump_wad(self) -> bytes: def dump_wad(self) -> bytes:
"""Dumps all title components (TMD, Ticket, and contents) back into the WAD object, and then dumps the WAD back """
Dumps all title components (TMD, Ticket, and contents) back into the WAD object, and then dumps the WAD back
into raw data and returns it. into raw data and returns it.
Returns Returns
@ -74,7 +81,8 @@ class Title:
return wad_data return wad_data
def load_tmd(self, tmd: bytes) -> None: def load_tmd(self, tmd: bytes) -> None:
"""Load existing TMD data into the title. Note that this will overwrite any existing TMD data for this title. """
Load existing TMD data into the title. Note that this will overwrite any existing TMD data for this title.
Parameters Parameters
---------- ----------
@ -85,7 +93,8 @@ class Title:
self.tmd.load(tmd) self.tmd.load(tmd)
def load_ticket(self, ticket: bytes) -> None: def load_ticket(self, ticket: bytes) -> None:
"""Load existing Ticket data into the title. Note that this will overwrite any existing Ticket data for this """
Load existing Ticket data into the title. Note that this will overwrite any existing Ticket data for this
title. title.
Parameters Parameters
@ -97,7 +106,8 @@ class Title:
self.ticket.load(ticket) self.ticket.load(ticket)
def load_content_records(self) -> None: def load_content_records(self) -> None:
"""Load content records from the TMD into the ContentRegion to allow loading content files based on the records. """
Load content records from the TMD into the ContentRegion to allow loading content files based on the records.
This requires that a TMD has already been loaded and will throw an exception if it isn't. This requires that a TMD has already been loaded and will throw an exception if it isn't.
""" """
if not self.tmd.content_records: if not self.tmd.content_records:
@ -106,7 +116,8 @@ class Title:
self.content.content_records = self.tmd.content_records self.content.content_records = self.tmd.content_records
def set_title_id(self, title_id: str) -> None: def set_title_id(self, title_id: str) -> None:
"""Sets the Title ID of the title in both the TMD and Ticket. """
Sets the Title ID of the title in both the TMD and Ticket.
Parameters Parameters
---------- ----------
@ -119,7 +130,8 @@ class Title:
self.ticket.set_title_id(title_id) self.ticket.set_title_id(title_id)
def get_content_by_index(self, index: id) -> bytes: def get_content_by_index(self, index: id) -> bytes:
"""Gets an individual content from the content region based on the provided index, in decrypted form. """
Gets an individual content from the content region based on the provided index, in decrypted form.
Parameters Parameters
---------- ----------
@ -138,7 +150,8 @@ class Title:
return dec_content return dec_content
def get_content_by_cid(self, cid: int) -> bytes: def get_content_by_cid(self, cid: int) -> bytes:
"""Gets an individual content from the content region based on the provided Content ID, in decrypted form. """
Gets an individual content from the content region based on the provided Content ID, in decrypted form.
Parameters Parameters
---------- ----------
@ -158,7 +171,8 @@ class Title:
def set_enc_content(self, enc_content: bytes, cid: int, index: int, content_type: int, content_size: int, def set_enc_content(self, enc_content: bytes, cid: int, index: int, content_type: int, content_size: int,
content_hash: bytes) -> None: content_hash: bytes) -> None:
"""Sets the provided index to a new content with the provided Content ID. Hashes and size of the content are """
Sets the provided index to a new content with the provided Content ID. Hashes and size of the content are
set in the content record, with a new record being added if necessary. The TMD is also updated to match the new set in the content record, with a new record being added if necessary. The TMD is also updated to match the new
records. records.
@ -183,7 +197,8 @@ class Title:
self.tmd.content_records = self.content.content_records self.tmd.content_records = self.content.content_records
def set_content(self, dec_content: bytes, cid: int, index: int, content_type: int) -> None: def set_content(self, dec_content: bytes, cid: int, index: int, content_type: int) -> None:
"""Sets the provided index to a new content with the provided Content ID. Hashes and size of the content are """
Sets the provided index to a new content with the provided Content ID. Hashes and size of the content are
set in the content record, with a new record being added if necessary. The Title Key is sourced from this set in the content record, with a new record being added if necessary. The Title Key is sourced from this
title's loaded ticket. The TMD is also updated to match the new records. title's loaded ticket. The TMD is also updated to match the new records.
@ -204,7 +219,8 @@ class Title:
self.tmd.content_records = self.content.content_records self.tmd.content_records = self.content.content_records
def load_content(self, dec_content: bytes, index: int) -> None: def load_content(self, dec_content: bytes, index: int) -> None:
"""Loads the provided decrypted content into the content region at the specified index, but first checks to make """
Loads the provided decrypted content into the content region at the specified index, but first checks to make
sure it matches the record at that index before loading. This content will be encrypted when loaded. sure it matches the record at that index before loading. This content will be encrypted when loaded.
Parameters Parameters

View File

@ -12,7 +12,7 @@ from .types import ContentRecord
class TMD: class TMD:
""" """
Creates a TMD object that allows for either loading and editing an existing TMD or creating one manually if desired. A TMD object that allows for either loading and editing an existing TMD or creating one manually if desired.
Attributes Attributes
---------- ----------
@ -53,7 +53,8 @@ class TMD:
self.content_records: List[ContentRecord] = [] self.content_records: List[ContentRecord] = []
def load(self, tmd: bytes) -> None: def load(self, tmd: bytes) -> None:
"""Loads raw TMD data and sets all attributes of the WAD object. This allows for manipulating an already """
Loads raw TMD data and sets all attributes of the WAD object. This allows for manipulating an already
existing TMD. existing TMD.
Parameters Parameters
@ -138,7 +139,8 @@ class TMD:
binascii.hexlify(content_record_hdr[4]))) binascii.hexlify(content_record_hdr[4])))
def dump(self) -> bytes: def dump(self) -> bytes:
"""Dumps the TMD object back into bytes. This also sets the raw TMD attribute of TMD object to the dumped data, """
Dumps the TMD object back into bytes. This also sets the raw TMD attribute of TMD object to the dumped data,
and triggers load() again to ensure that the raw data and object match. and triggers load() again to ensure that the raw data and object match.
Returns Returns
@ -212,8 +214,9 @@ class TMD:
# Return the raw TMD for the data contained in the object. # Return the raw TMD for the data contained in the object.
return tmd_data_raw return tmd_data_raw
def get_title_region(self): def get_title_region(self) -> str:
"""Gets the region of the TMD's associated title. """
Gets the region of the TMD's associated title.
Can be one of several possible values: Can be one of several possible values:
'JAP', 'USA', 'EUR', 'NONE', or 'KOR'. 'JAP', 'USA', 'EUR', 'NONE', or 'KOR'.
@ -235,8 +238,9 @@ class TMD:
case 4: case 4:
return "KOR" return "KOR"
def get_is_vwii_title(self): def get_is_vwii_title(self) -> bool:
"""Gets whether the TMD is designed for the vWii or not. """
Gets whether the TMD is designed for the vWii or not.
Returns Returns
------- -------
@ -248,8 +252,9 @@ class TMD:
else: else:
return False return False
def get_title_type(self): def get_title_type(self) -> str:
"""Gets the type of the TMD's associated title. """
Gets the type of the TMD's associated title.
Can be one of several possible values: Can be one of several possible values:
'System', 'Game', 'Channel', 'SystemChannel', 'GameWithChannel', or 'HiddenChannel' 'System', 'Game', 'Channel', 'SystemChannel', 'GameWithChannel', or 'HiddenChannel'
@ -279,7 +284,8 @@ class TMD:
return "Unknown" return "Unknown"
def get_content_type(self): def get_content_type(self):
"""Gets the type of content contained in the TMD's associated title. """
Gets the type of content contained in the TMD's associated title.
Can be one of several possible values: Can be one of several possible values:
'Normal', 'Development/Unknown', 'Hash Tree', 'DLC', or 'Shared' 'Normal', 'Development/Unknown', 'Hash Tree', 'DLC', or 'Shared'
@ -303,8 +309,9 @@ class TMD:
case _: case _:
return "Unknown" return "Unknown"
def get_content_record(self, record): def get_content_record(self, record) -> ContentRecord:
"""Gets the content record at the specified index. """
Gets the content record at the specified index.
Parameters Parameters
---------- ----------
@ -322,8 +329,9 @@ class TMD:
raise IndexError("Invalid content record! TMD lists '" + str(self.num_contents - 1) + raise IndexError("Invalid content record! TMD lists '" + str(self.num_contents - 1) +
"' contents but index was '" + str(record) + "'!") "' contents but index was '" + str(record) + "'!")
def set_title_id(self, title_id): def set_title_id(self, title_id) -> None:
"""Sets the Title ID of the title in the ticket. """
Sets the Title ID of the title in the ticket.
Parameters Parameters
---------- ----------

View File

@ -7,7 +7,9 @@ from dataclasses import dataclass
@dataclass @dataclass
class ContentRecord: class ContentRecord:
""" """
Creates a content record object that contains the details of a content contained in a title. A content record object that contains the details of a content contained in a title. This information must match
the content stored at the index in the record, or else the content will not decrypt properly, as the hash of the
decrypted data will not match the hash in the content record.
Attributes Attributes
---------- ----------
@ -31,7 +33,10 @@ class ContentRecord:
@dataclass @dataclass
class TitleLimit: class TitleLimit:
"""Creates a TitleLimit object that contains the type of restriction and the limit. """
A TitleLimit object that contains the type of restriction and the limit. The limit type can be one of the following:
0 = None, 1 = Time Limit, 3 = None, or 4 = Launch Count. The maximum usage is then either the time in minutes the
title can be played or the maximum number of launches allowed for that title, based on the type of limit applied.
Attributes Attributes
---------- ----------
@ -40,9 +45,8 @@ class TitleLimit:
maximum_usage : int maximum_usage : int
The maximum value for the type of play limit applied. The maximum value for the type of play limit applied.
""" """
# The type of play limit applied. The following types exist: # The type of play limit applied.
# 0 = None, 1 = Time Limit, 3 = None, 4 = Launch Count # 0 = None, 1 = Time Limit, 3 = None, 4 = Launch Count
limit_type: int limit_type: int
# The maximum value of the limit applied. # The maximum value of the limit applied.
# This is either the number of minutes for a time limit, or the number of launches for a launch limit.
maximum_usage: int maximum_usage: int

View File

@ -10,7 +10,24 @@ from .shared import align_value, pad_bytes_stream
class WAD: class WAD:
""" """
Creates a WAD object that allows for either loading and editing an existing WAD or creating a new WAD from raw data. A WAD object that allows for either loading and editing an existing WAD or creating a new WAD from raw data.
Attributes
----------
wad_type : str
The type of WAD, either ib for boot2 or Is for normal installable WADs. libWiiPy only supports Is currently.
wad_cert_size : int
The size of the WAD's certificate.
wad_crl_size : int
The size of the WAD's crl.
wad_tik_size : int
The size of the WAD's Ticket.
wad_tmd_size : int
The size of the WAD's TMD.
wad_content_size : int
The size of WAD's total content region.
wad_meta_size : int
The size of the WAD's meta/footer.
""" """
def __init__(self): def __init__(self):
self.wad_hdr_size: int = 64 self.wad_hdr_size: int = 64
@ -33,7 +50,8 @@ class WAD:
self.wad_meta_data: bytes = b'' self.wad_meta_data: bytes = b''
def load(self, wad_data) -> None: def load(self, wad_data) -> None:
"""Loads raw WAD data and sets all attributes of the WAD object. This allows for manipulating an already """
Loads raw WAD data and sets all attributes of the WAD object. This allows for manipulating an already
existing WAD file. existing WAD file.
Parameters Parameters
@ -114,7 +132,8 @@ class WAD:
self.wad_meta_data = wad_data.read(self.wad_meta_size) self.wad_meta_data = wad_data.read(self.wad_meta_size)
def dump(self) -> bytes: def dump(self) -> bytes:
"""Dumps the WAD object into the raw WAD file. This allows for creating a WAD file from the data contained in """
Dumps the WAD object into the raw WAD file. This allows for creating a WAD file from the data contained in
the WAD object. the WAD object.
Returns Returns
@ -167,8 +186,9 @@ class WAD:
# Return the raw WAD file for the data contained in the object. # Return the raw WAD file for the data contained in the object.
return wad_data_raw return wad_data_raw
def get_wad_type(self): def get_wad_type(self) -> str:
"""Gets the type of the WAD. """
Gets the type of the WAD.
Returns Returns
------- -------
@ -178,7 +198,8 @@ class WAD:
return self.wad_type return self.wad_type
def get_cert_data(self) -> bytes: def get_cert_data(self) -> bytes:
"""Gets the certificate data from the WAD. """
Gets the certificate data from the WAD.
Returns Returns
------- -------
@ -188,7 +209,8 @@ class WAD:
return self.wad_cert_data return self.wad_cert_data
def get_crl_data(self) -> bytes: def get_crl_data(self) -> bytes:
"""Gets the crl data from the WAD, if it exists. """
Gets the crl data from the WAD, if it exists.
Returns Returns
------- -------
@ -198,7 +220,8 @@ class WAD:
return self.wad_crl_data return self.wad_crl_data
def get_ticket_data(self) -> bytes: def get_ticket_data(self) -> bytes:
"""Gets the ticket data from the WAD. """
Gets the ticket data from the WAD.
Returns Returns
------- -------
@ -208,7 +231,8 @@ class WAD:
return self.wad_tik_data return self.wad_tik_data
def get_tmd_data(self) -> bytes: def get_tmd_data(self) -> bytes:
"""Returns the TMD data from the WAD. """
Returns the TMD data from the WAD.
Returns Returns
------- -------
@ -218,7 +242,8 @@ class WAD:
return self.wad_tmd_data return self.wad_tmd_data
def get_content_data(self) -> bytes: def get_content_data(self) -> bytes:
"""Gets the content of the WAD. """
Gets the content of the WAD.
Returns Returns
------- -------
@ -228,7 +253,8 @@ class WAD:
return self.wad_content_data return self.wad_content_data
def get_meta_data(self) -> bytes: def get_meta_data(self) -> bytes:
"""Gets the meta region of the WAD, which is typically unused. """
Gets the meta region of the WAD, which is typically unused.
Returns Returns
------- -------
@ -238,7 +264,8 @@ class WAD:
return self.wad_meta_data return self.wad_meta_data
def set_cert_data(self, cert_data) -> None: def set_cert_data(self, cert_data) -> None:
"""Sets the certificate data of the WAD. Also calculates the new size. """
Sets the certificate data of the WAD. Also calculates the new size.
Parameters Parameters
---------- ----------
@ -250,7 +277,8 @@ class WAD:
self.wad_cert_size = len(cert_data) self.wad_cert_size = len(cert_data)
def set_crl_data(self, crl_data) -> None: def set_crl_data(self, crl_data) -> None:
"""Sets the crl data of the WAD. Also calculates the new size. """
Sets the crl data of the WAD. Also calculates the new size.
Parameters Parameters
---------- ----------
@ -262,7 +290,8 @@ class WAD:
self.wad_crl_size = len(crl_data) self.wad_crl_size = len(crl_data)
def set_tmd_data(self, tmd_data) -> None: def set_tmd_data(self, tmd_data) -> None:
"""Sets the TMD data of the WAD. Also calculates the new size. """
Sets the TMD data of the WAD. Also calculates the new size.
Parameters Parameters
---------- ----------
@ -274,7 +303,8 @@ class WAD:
self.wad_tmd_size = len(tmd_data) self.wad_tmd_size = len(tmd_data)
def set_ticket_data(self, tik_data) -> None: def set_ticket_data(self, tik_data) -> None:
"""Sets the Ticket data of the WAD. Also calculates the new size. """
Sets the Ticket data of the WAD. Also calculates the new size.
Parameters Parameters
---------- ----------
@ -286,7 +316,8 @@ class WAD:
self.wad_tik_size = len(tik_data) self.wad_tik_size = len(tik_data)
def set_content_data(self, content_data) -> None: def set_content_data(self, content_data) -> None:
"""Sets the content data of the WAD. Also calculates the new size. """
Sets the content data of the WAD. Also calculates the new size.
Parameters Parameters
---------- ----------
@ -298,7 +329,8 @@ class WAD:
self.wad_content_size = len(content_data) self.wad_content_size = len(content_data)
def set_meta_data(self, meta_data) -> None: def set_meta_data(self, meta_data) -> None:
"""Sets the meta data of the WAD. Also calculates the new size. """
Sets the meta data of the WAD. Also calculates the new size.
Parameters Parameters
---------- ----------