mirror of
https://github.com/NinjaCheetah/libWiiPy.git
synced 2025-04-26 13:21:01 -04:00
Created title.py to handle titles as a whole and allow for changing parts of them more easily
This commit is contained in:
parent
c2b7724fdd
commit
7b6703cf36
@ -1,7 +1,9 @@
|
|||||||
# "__init__.py" from libWiiPy by NinjaCheetah & Contributors
|
# "__init__.py" from libWiiPy by NinjaCheetah & Contributors
|
||||||
# https://github.com/NinjaCheetah/libWiiPy
|
# https://github.com/NinjaCheetah/libWiiPy
|
||||||
|
|
||||||
from .wad import *
|
from .commonkeys import *
|
||||||
from .tmd import *
|
|
||||||
from .ticket import *
|
|
||||||
from .content import *
|
from .content import *
|
||||||
|
from .ticket import *
|
||||||
|
from .title import *
|
||||||
|
from .tmd import *
|
||||||
|
from .wad import *
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
# See https://wiibrew.org/wiki/Ticket for details about the ticket format
|
# See https://wiibrew.org/wiki/Ticket for details about the ticket format
|
||||||
|
|
||||||
import io
|
import io
|
||||||
|
import binascii
|
||||||
from .crypto import decrypt_title_key
|
from .crypto import decrypt_title_key
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import List
|
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.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.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: 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.title_version: int # Version of the ticket's associated title.
|
||||||
self.permitted_titles: bytes # Permitted titles mask
|
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."
|
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
|
# Title ID
|
||||||
ticket_data.seek(0x1DC)
|
ticket_data.seek(0x1DC)
|
||||||
self.title_id = ticket_data.read(8)
|
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
|
# Title version
|
||||||
ticket_data.seek(0x1E6)
|
ticket_data.seek(0x1E6)
|
||||||
title_version_high = int.from_bytes(ticket_data.read(1)) * 256
|
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)
|
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):
|
||||||
|
"""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
58
src/libWiiPy/title.py
Normal 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)
|
@ -235,3 +235,15 @@ class TMD:
|
|||||||
else:
|
else:
|
||||||
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):
|
||||||
|
"""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
|
||||||
|
@ -47,7 +47,7 @@ class WAD:
|
|||||||
wad_magic = str(wad_magic_hex.decode())
|
wad_magic = str(wad_magic_hex.decode())
|
||||||
if wad_magic != "0000002049730000":
|
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"
|
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.
|
# Get the sizes of each data region contained within the WAD.
|
||||||
# ====================================================================================
|
# ====================================================================================
|
||||||
|
Loading…
x
Reference in New Issue
Block a user