Created title.py to handle titles as a whole and allow for changing parts of them more easily

This commit is contained in:
Campbell 2024-03-19 22:48:55 -04:00
parent c2b7724fdd
commit 7b6703cf36
Signed by: NinjaCheetah
GPG Key ID: B547958AF96ED344
5 changed files with 94 additions and 4 deletions

View File

@ -1,7 +1,9 @@
# "__init__.py" from libWiiPy by NinjaCheetah & Contributors
# https://github.com/NinjaCheetah/libWiiPy
from .wad import *
from .tmd import *
from .ticket import *
from .commonkeys import *
from .content import *
from .ticket import *
from .title import *
from .tmd import *
from .wad import *

View File

@ -4,6 +4,7 @@
# See https://wiibrew.org/wiki/Ticket for details about the ticket format
import io
import binascii
from .crypto import decrypt_title_key
from dataclasses import dataclass
from typing import List
@ -66,6 +67,7 @@ class Ticket:
self.ticket_id: bytes # Used as the IV when decrypting the title key for console-specific title installs.
self.console_id: int # ID of the console that the ticket was issued for.
self.title_id: bytes # TID/IV used for AES-CBC encryption.
self.title_id_str: str # TID in string form for comparing against the TMD.
self.title_version: int # Version of the ticket's associated title.
self.permitted_titles: bytes # Permitted titles mask
self.permit_mask: bytes # "Permit mask. The current disc title is ANDed with the inverse of this mask to see if the result matches the Permitted Titles Mask."
@ -106,6 +108,9 @@ class Ticket:
# Title ID
ticket_data.seek(0x1DC)
self.title_id = ticket_data.read(8)
# Title ID (as a string)
title_id_hex = binascii.hexlify(self.title_id)
self.title_id_str = str(title_id_hex.decode())
# Title version
ticket_data.seek(0x1E6)
title_version_high = int.from_bytes(ticket_data.read(1)) * 256
@ -175,3 +180,16 @@ class Ticket:
"""
title_key = decrypt_title_key(self.title_key_enc, self.common_key_index, self.title_id)
return title_key
def set_title_id(self, title_id):
"""Sets the Title ID of the title in the Ticket.
Parameters
----------
title_id : str
The new Title ID of the title.
"""
if len(title_id) != 16:
raise ValueError("Invalid Title ID! Title IDs must be 8 bytes long.")
self.title_id_str = title_id
self.title_id = binascii.unhexlify(title_id)

58
src/libWiiPy/title.py Normal file
View File

@ -0,0 +1,58 @@
# "title.py" from libWiiPy by NinjaCheetah & Contributors
# https://github.com/NinjaCheetah/libWiiPy
#
# See https://wiibrew.org/wiki/Title for details about how titles are formatted
from .content import ContentRegion
from .ticket import Ticket
from .tmd import TMD
from .wad import WAD
class Title:
"""Creates a Title object that contains all components of a title, and allows altering them.
Parameters
----------
wad : WAD
A WAD object to load data from.
Attributes
----------
tmd : TMD
A TMD object of the title's TMD.
ticket : Ticket
A Ticket object of the title's Ticket.
content: ContentRegion
A ContentRegion object containing the title's contents.
"""
def __init__(self, wad: WAD):
self.wad = wad
self.tmd: TMD
self.ticket: Ticket
self.content: ContentRegion
# Load data from the WAD object, and generate all other objects from the data in it.
# Load the TMD.
self.tmd = TMD(self.wad.get_tmd_data())
# Load the ticket.
self.ticket = Ticket(self.wad.get_ticket_data())
# Load the content.
self.content = ContentRegion(self.wad.get_content_data(), self.tmd.content_records)
# Ensure that the Title IDs of the TMD and Ticket match before doing anything else. If they don't, throw an
# error because clearly something strange has gone on with the WAD and editing it probably won't work.
if self.tmd.title_id != self.ticket.title_id_str:
raise ValueError("The Title IDs of the TMD and Ticket in this WAD do not match. This WAD appears to be "
"invalid.")
def set_title_id(self, title_id: str):
"""Sets the Title ID of the title in both the TMD and Ticket.
Parameters
----------
title_id : str
The new Title ID of the title.
"""
if len(title_id) != 16:
raise ValueError("Invalid Title ID! Title IDs must be 8 bytes long.")
self.tmd.set_title_id(title_id)
self.ticket.set_title_id(title_id)

View File

@ -235,3 +235,15 @@ class TMD:
else:
raise IndexError("Invalid content record! TMD lists '" + str(self.num_contents - 1) +
"' contents but index was '" + str(record) + "'!")
def set_title_id(self, title_id):
"""Sets the Title ID of the title in the ticket.
Parameters
----------
title_id : str
The new Title ID of the title.
"""
if len(title_id) != 16:
raise ValueError("Invalid Title ID! Title IDs must be 8 bytes long.")
self.title_id = title_id

View File

@ -47,7 +47,7 @@ class WAD:
wad_magic = str(wad_magic_hex.decode())
if wad_magic != "0000002049730000":
raise TypeError("This does not appear to be a valid WAD file, or is a boot2 WAD, which is not currently"
"supported by this library.")
" supported by this library.")
# ====================================================================================
# Get the sizes of each data region contained within the WAD.
# ====================================================================================