Merge pull request #9 from NinjaCheetah/full_docs

Docs: Add full NumPy-style documentation to source code
This commit is contained in:
Campbell 2024-03-02 16:36:31 -05:00 committed by GitHub
commit 1d127b09e6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 325 additions and 40 deletions

View File

@ -9,9 +9,19 @@ vwii_key = '30bfc76e7c19afbb23163330ced7c28d'
def get_common_key(common_key_index): def get_common_key(common_key_index):
""" """Gets the specified Wii Common Key based on the index provided.
Returns 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
Parameters
----------
common_key_index : int
The index of the common key to be returned.
Returns
-------
bytes
The specified common key, in binary format.
""" """
match common_key_index: match common_key_index:
case 0: case 0:

View File

@ -8,9 +8,23 @@ from Crypto.Cipher import AES
def decrypt_title_key(title_key_enc, common_key_index, title_id): def decrypt_title_key(title_key_enc, common_key_index, title_id):
""" """Gets the decrypted version of the encrypted Title Key provided.
Returns 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.
Parameters
----------
title_key_enc : bytes
The encrypted Title Key.
common_key_index : int
The index of the common key to be returned.
title_id : bytes
The title ID of the tite that the key is for.
Returns
-------
bytes
The decrypted Title Key.
""" """
# Load the correct common key for the title. # Load the correct common key for the title.
common_key = get_common_key(common_key_index) common_key = get_common_key(common_key_index)

View File

@ -11,7 +11,15 @@ from typing import List
@dataclass @dataclass
class TitleLimit: class TitleLimit:
"""Creates a TitleLimit object that contains the type of restriction and the limit.""" """Creates a TitleLimit object that contains the type of restriction and the limit.
Attributes:
----------
limit_type : int
The type of play limit applied.
maximum_usage : int
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. The following types exist:
# 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
@ -105,40 +113,102 @@ class Ticket:
self.title_limits_list.append(TitleLimit(limit_type, limit_value)) self.title_limits_list.append(TitleLimit(limit_type, limit_value))
def get_signature(self): def get_signature(self):
"""Returns the signature of the ticket.""" """Gets the signature of the ticket.
Returns
-------
bytes
The signature.
"""
return self.signature return self.signature
def get_ticket_version(self): def get_ticket_version(self):
"""Returns the version of the ticket.""" """Gets the version of the ticket.
Returns
-------
int
The version.
"""
return self.ticket_version return self.ticket_version
def get_title_key_enc(self): def get_title_key_enc(self):
"""Returns the title key contained in the ticket, in encrypted form.""" """Gets the Title Key contained in the ticket, in encrypted form.
Returns
-------
bytes
The encrypted Title Key.
"""
return self.title_key_enc return self.title_key_enc
def get_ticket_id(self): def get_ticket_id(self):
"""Returns the ID of the ticket.""" """Gets the ID of the ticket.
Returns
-------
bytes
The ID of the ticket.
"""
return self.ticket_id return self.ticket_id
def get_console_id(self): def get_console_id(self):
"""Returns the ID of the console this ticket is designed for, if the ticket is console-specific.""" """Gets the ID of the console this ticket is designed for, if the ticket is console-specific.
Returns
-------
bytes
The ID of the console.
"""
return self.console_id return self.console_id
def get_title_id(self): def get_title_id(self):
"""Returns the Title ID of the ticket's associated title.""" """Gets the Title ID of the ticket's associated title.
Returns
-------
str
The Title ID of the title.
"""
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_title_version(self): def get_title_version(self):
"""Returns the version of the ticket's associated title that this ticket is designed for.""" """Gets the version of the ticket's associated title that this ticket is designed for.
Returns
-------
int
The version of the title.
"""
return self.title_version return self.title_version
def get_common_key_index(self): def get_common_key_index(self):
"""Returns the index of the common key used to encrypt the Title Key contained in the ticket.""" """Gets the index of the common key used to encrypt the Title Key contained in the ticket.
Returns
-------
int
The index of the common key required.
See Also
--------
commonkeys.get_common_key
"""
return self.common_key_index return self.common_key_index
def get_common_key_type(self): def get_common_key_type(self):
"""Returns 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
-------
str
The name of the common key required.
See Also
--------
commonkeys.get_common_key
"""
match self.common_key_index: match self.common_key_index:
case 0: case 0:
return "Common" return "Common"
@ -148,7 +218,13 @@ class Ticket:
return "vWii" return "vWii"
def get_title_key(self): def get_title_key(self):
"""Returns the decrypted title key contained in the ticket.""" """Gets the decrypted title key contained in the ticket.
Returns
-------
bytes
The decrypted title key.
"""
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

View File

@ -12,7 +12,22 @@ from typing import List
@dataclass @dataclass
class ContentRecord: class ContentRecord:
"""Creates a content record object that contains the details of a content contained in a title.""" """
Creates a content record object that contains the details of a content contained in a title.
Attributes:
----------
cid : int
ID of the content.
index : int
Index of the content in the list of contents.
content_type : int
The type of the content.
content_size : int
The size of the content.
content_hash
The SHA-1 hash of the decrypted content.
"""
cid: int # Content ID cid: int # Content ID
index: int # Index in the list of contents index: int # Index in the list of contents
content_type: int # Normal: 0x0001, DLC: 0x4001, Shared: 0x8001 content_type: int # Normal: 0x0001, DLC: 0x4001, Shared: 0x8001
@ -21,7 +36,14 @@ class ContentRecord:
class TMD: class TMD:
"""Creates a TMD object to parse a TMD file to retrieve information about a title.""" """
Creates a TMD object to parse a TMD file to retrieve information about a title.
Attributes:
----------
tmd : bytes
A bytes object containing the contents of a TMD file.
"""
def __init__(self, tmd): def __init__(self, tmd):
self.tmd = tmd self.tmd = tmd
self.sig_type: int self.sig_type: int
@ -115,15 +137,36 @@ class TMD:
binascii.hexlify(content_record_hdr[4]))) binascii.hexlify(content_record_hdr[4])))
def get_title_id(self): def get_title_id(self):
"""Returns the TID of the TMD's associated title.""" """Gets the TID of the TMD's associated title.
Returns
-------
str
The Title ID.
"""
return self.title_id return self.title_id
def get_title_version(self): def get_title_version(self):
"""Returns the version of the TMD's associated title.""" """Gets the version of the TMD's associated title.
Returns
-------
int
The version of the title.
"""
return self.title_version return self.title_version
def get_title_region(self): def get_title_region(self):
"""Returns the region of the TMD's associated title.""" """Gets the region of the TMD's associated title.
Can be one of several possible values:
'JAP', 'USA', 'EUR', 'NONE', or 'KOR'.
Returns
-------
str
The region of the title.
"""
match self.region: match self.region:
case 0: case 0:
return "JAP" return "JAP"
@ -137,26 +180,59 @@ class TMD:
return "KOR" return "KOR"
def get_is_vwii_title(self): def get_is_vwii_title(self):
"""Returns whether the TMD is designed for the vWii or not.""" """Gets whether the TMD is designed for the vWii or not.
Returns
-------
bool
If the title is for vWii.
"""
if self.vwii == 1: if self.vwii == 1:
return True return True
else: else:
return False return False
def get_tmd_version(self): def get_tmd_version(self):
"""Returns the version of the TMD.""" """Gets the version of the TMD.
Returns
-------
int
The version of the TMD.
"""
return self.version return self.version
def get_required_ios_tid(self): def get_required_ios_tid(self):
"""Returns the TID of the required IOS for the title.""" """Gets the TID of the required IOS for the title.
Returns
-------
str
The Title ID of the required IOS version.
"""
return self.ios_tid return self.ios_tid
def get_required_ios(self): def get_required_ios(self):
"""Returns the required IOS version for the title.""" """Gets the required IOS version for the title.
Returns
-------
int
The required IOS version.
"""
return self.ios_version return self.ios_version
def get_title_type(self): def get_title_type(self):
"""Returns the type of the TMD's associated title.""" """Gets the type of the TMD's associated title.
Can be one of several possible values:
'System', 'Game', 'Channel', 'SystemChannel', 'GameWithChannel', or 'HiddenChannel'
Returns
-------
str
The type of the title.
"""
title_id_high = self.title_id[:8] title_id_high = self.title_id[:8]
match title_id_high: match title_id_high:
case '00000001': case '00000001':
@ -177,7 +253,16 @@ class TMD:
return "Unknown" return "Unknown"
def get_content_type(self): def get_content_type(self):
"""Returns 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:
'Normal', 'Development/Unknown', 'Hash Tree', 'DLC', or 'Shared'
Returns
-------
str
The type of content.
"""
match self.content_type: match self.content_type:
case '00000001': case '00000001':
return "Normal" return "Normal"
@ -193,11 +278,28 @@ class TMD:
return "Unknown" return "Unknown"
def get_num_contents(self): def get_num_contents(self):
"""Returns the number of contents listed in the TMD.""" """Gets the number of contents listed in the TMD.
Returns
-------
int
The number of contents.
"""
return self.num_contents return self.num_contents
def get_content_record(self, record): def get_content_record(self, record):
"""Returns the content record at the specified index.""" """Gets the content record at the specified index.
Parameters
----------
record : int
The content record to be retrieved.
Returns
-------
ContentRecord
A ContentRecord object containing the data in the content record.
"""
if record < self.num_contents: if record < self.num_contents:
return self.content_records[record] return self.content_records[record]
else: else:

View File

@ -8,7 +8,14 @@ import binascii
class WAD: class WAD:
"""Creates a WAD object to parse the header of a WAD file and retrieve the data contained in it.""" """
Creates a WAD object to parse the header of a WAD file and retrieve the data contained in it.
Attributes:
----------
wad : bytes
A bytes object containing the contents of a WAD file.
"""
def __init__(self, wad): def __init__(self, wad):
self.wad = wad self.wad = wad
self.wad_hdr_size: int self.wad_hdr_size: int
@ -73,59 +80,135 @@ class WAD:
self.wad_meta_offset = int(64 * round((self.wad_content_offset + self.wad_content_size) / 64)) self.wad_meta_offset = int(64 * round((self.wad_content_offset + self.wad_content_size) / 64))
def get_cert_region(self): def get_cert_region(self):
"""Returns the offset and size for the cert data.""" """Gets the offset and size of the certificate data.
Returns
-------
int
The offset of the certificate data in the WAD.
int
The size of the certificate data in the WAD.
"""
return self.wad_cert_offset, self.wad_cert_size return self.wad_cert_offset, self.wad_cert_size
def get_crl_region(self): def get_crl_region(self):
"""Returns the offset and size for the crl data.""" """Gets the offset and size of the crl data.
Returns
-------
int
The offset of the crl data in the WAD.
int
The size of the crl data in the WAD.
"""
return self.wad_crl_offset, self.wad_crl_size return self.wad_crl_offset, self.wad_crl_size
def get_ticket_region(self): def get_ticket_region(self):
"""Returns the offset and size for the ticket data.""" """Gets the offset and size of the ticket data.
Returns
-------
int
The offset of the ticket data in the WAD.
int
The size of the ticket data in the WAD.
"""
return self.wad_tik_offset, self.wad_tik_size return self.wad_tik_offset, self.wad_tik_size
def get_tmd_region(self): def get_tmd_region(self):
"""Returns the offset and size for the TMD data.""" """Gets the offset and size of the TMD data.
Returns
-------
int
The offset of the TMD data in the WAD.
int
The size of the TMD data in the WAD.
"""
return self.wad_tmd_offset, self.wad_tmd_size return self.wad_tmd_offset, self.wad_tmd_size
def get_content_region(self): def get_content_region(self):
"""Returns the offset and size for the content of the WAD.""" """Gets the offset and size of the content of the WAD.
Returns
-------
int
The offset of the content data in the WAD.
int
The size of the content data in the WAD.
"""
return self.wad_content_offset, self.wad_tmd_size return self.wad_content_offset, self.wad_tmd_size
def get_wad_type(self): def get_wad_type(self):
"""Returns the type of the WAD. This is 'Is' unless the WAD contains boot2 where it is 'ib'.""" """Gets the type of the WAD.
Returns
-------
str
The type of the WAD. This is 'Is', unless the WAD contains boot2, where it is 'ib'.
"""
return self.wad_type return self.wad_type
def get_cert_data(self): def get_cert_data(self):
"""Returns the certificate data from the WAD.""" """Gets the certificate data from the WAD.
Returns
-------
bytes
The certificate data.
"""
waddata = io.BytesIO(self.wad) waddata = io.BytesIO(self.wad)
waddata.seek(self.wad_cert_offset) waddata.seek(self.wad_cert_offset)
cert_data = waddata.read(self.wad_cert_size) cert_data = waddata.read(self.wad_cert_size)
return cert_data return cert_data
def get_crl_data(self): def get_crl_data(self):
"""Returns the crl data from the WAD, if it exists.""" """Gets the crl data from the WAD, if it exists.
Returns
-------
bytes
The crl data.
"""
waddata = io.BytesIO(self.wad) waddata = io.BytesIO(self.wad)
waddata.seek(self.wad_crl_offset) waddata.seek(self.wad_crl_offset)
crl_data = waddata.read(self.wad_crl_size) crl_data = waddata.read(self.wad_crl_size)
return crl_data return crl_data
def get_ticket_data(self): def get_ticket_data(self):
"""Returns the ticket data from the WAD.""" """Gets the ticket data from the WAD.
Returns
-------
bytes
The ticket data.
"""
waddata = io.BytesIO(self.wad) waddata = io.BytesIO(self.wad)
waddata.seek(self.wad_tik_offset) waddata.seek(self.wad_tik_offset)
ticket_data = waddata.read(self.wad_tik_size) ticket_data = waddata.read(self.wad_tik_size)
return ticket_data return ticket_data
def get_tmd_data(self): def get_tmd_data(self):
"""Returns the TMD data from the WAD.""" """Returns the TMD data from the WAD.
Returns
-------
bytes
The TMD data.
"""
waddata = io.BytesIO(self.wad) waddata = io.BytesIO(self.wad)
waddata.seek(self.wad_tmd_offset) waddata.seek(self.wad_tmd_offset)
tmd_data = waddata.read(self.wad_tmd_size) tmd_data = waddata.read(self.wad_tmd_size)
return tmd_data return tmd_data
def get_content_data(self): def get_content_data(self):
"""Returns the content of the WAD.""" """Gets the content of the WAD.
Returns
-------
bytes
The content data.
"""
waddata = io.BytesIO(self.wad) waddata = io.BytesIO(self.wad)
waddata.seek(self.wad_content_offset) waddata.seek(self.wad_content_offset)
content_data = waddata.read(self.wad_content_size) content_data = waddata.read(self.wad_content_size)