diff --git a/src/libWiiPy/shared.py b/src/libWiiPy/shared.py index 6b28cbc..706d0ed 100644 --- a/src/libWiiPy/shared.py +++ b/src/libWiiPy/shared.py @@ -49,6 +49,10 @@ def _pad_bytes(data, alignment=64) -> bytes: return data +def _bitmask(x: int) -> int: + return 1 << x + + _wii_menu_versions = { "Prelaunch": [0, 1, 2], "1.0J": 64, diff --git a/src/libWiiPy/title/ticket.py b/src/libWiiPy/title/ticket.py index 7f8ce13..8266bb7 100644 --- a/src/libWiiPy/title/ticket.py +++ b/src/libWiiPy/title/ticket.py @@ -252,6 +252,27 @@ class Ticket: except OverflowError: raise Exception("An error occurred during fakesigning. Ticket could not be fakesigned!") + def get_is_fakesigned(self) -> bool: + """ + Checks the Ticket object to see if it is currently fakesigned. For a description of fakesigning, refer to the + fakesign() method. + + Returns + ------- + bool: + True if the Ticket is fakesigned, False otherwise. + + See Also + -------- + libWiiPy.title.ticket.Ticket.fakesign() + """ + if self.signature != b'\x00' * 256: + return False + test_hash = hashlib.sha1(self.dump()[320:]).hexdigest() + if test_hash[:2] != '00': + return False + return True + def get_title_id(self) -> str: """ Gets the Title ID of the ticket's associated title. @@ -275,7 +296,7 @@ class Ticket: See Also -------- - commonkeys.get_common_key + libWiiPy.title.commonkeys.get_common_key """ match self.common_key_index: case 0: diff --git a/src/libWiiPy/title/title.py b/src/libWiiPy/title/title.py index a058592..9f5b5e6 100644 --- a/src/libWiiPy/title/title.py +++ b/src/libWiiPy/title/title.py @@ -316,3 +316,22 @@ class Title: """ self.tmd.fakesign() self.ticket.fakesign() + + def get_is_fakesigned(self): + """ + Checks the Title object to see if it is currently fakesigned. This ensures that both the TMD and Ticket are + fakesigned. For a description of fakesigning, refer to the fakesign() method. + + Returns + ------- + bool: + True if the Title is fakesigned, False otherwise. + + See Also + -------- + libWiiPy.title.title.Title.fakesign() + """ + if self.tmd.get_is_fakesigned and self.ticket.get_is_fakesigned(): + return True + else: + return False diff --git a/src/libWiiPy/title/tmd.py b/src/libWiiPy/title/tmd.py index 62c542d..65b4a47 100644 --- a/src/libWiiPy/title/tmd.py +++ b/src/libWiiPy/title/tmd.py @@ -8,7 +8,9 @@ import binascii import hashlib import struct from typing import List +from enum import IntEnum from ..types import _ContentRecord +from ..shared import _bitmask from .util import title_ver_dec_to_standard, title_ver_standard_to_dec @@ -50,7 +52,7 @@ class TMD: self.reserved1: bytes = b'' # Unknown data labeled "Reserved" on WiiBrew. self.ipc_mask: bytes = b'' self.reserved2: bytes = b'' # Other "Reserved" data from WiiBrew. - self.access_rights: bytes = b'' + self.access_rights: int = 0 self.title_version: int = 0 # The version of the associated title. self.title_version_converted: int = 0 # The title version in vX.X format. self.num_contents: int = 0 # The number of contents contained in the associated title. @@ -131,7 +133,7 @@ class TMD: self.reserved2 = tmd_data.read(18) # Access rights of the title; DVD-video and AHB access. tmd_data.seek(0x1D8) - self.access_rights = tmd_data.read(4) + self.access_rights = int.from_bytes(tmd_data.read(4)) # Version number straight from the TMD. tmd_data.seek(0x1DC) self.title_version = int.from_bytes(tmd_data.read(2)) @@ -203,7 +205,7 @@ class TMD: # "Reserved" 2. tmd_data += self.reserved2 # Access rights. - tmd_data += self.access_rights + tmd_data += int.to_bytes(self.access_rights, 4) # Title version. tmd_data += int.to_bytes(self.title_version, 2) # Number of contents. @@ -255,6 +257,27 @@ class TMD: except OverflowError: raise Exception("An error occurred during fakesigning. TMD could not be fakesigned!") + def get_is_fakesigned(self) -> bool: + """ + Checks the TMD object to see if it is currently fakesigned. For a description of fakesigning, refer to the + fakesign() method. + + Returns + ------- + bool: + True if the TMD is fakesigned, False otherwise. + + See Also + -------- + libWiiPy.title.tmd.TMD.fakesign() + """ + if self.signature != b'\x00' * 256: + return False + test_hash = hashlib.sha1(self.dump()[320:]).hexdigest() + if test_hash[:2] != '00': + return False + return True + def get_title_region(self) -> str: """ Gets the region of the TMD's associated title. @@ -367,6 +390,27 @@ class TMD: raise IndexError("Invalid content record! TMD lists '" + str(self.num_contents - 1) + "' contents but index was '" + str(record) + "'!") + class AccessFlags(IntEnum): + AHB = 0 + DVD_VIDEO = 1 + + def get_access_right(self, flag: int) -> bool: + """ + Gets whether an access rights flag is enabled or not. This is done by checking the specified bit. Possible flags + and their corresponding bits are defined in the AccessFlags enum. + + Parameters + ---------- + flag : int + The flag to check. + + Returns + ------- + bool + True if the flag is enabled, False otherwise. + """ + return bool(self.access_rights & _bitmask(flag)) + def set_title_id(self, title_id) -> None: """ Sets the Title ID property of the TMD. Recommended over setting the property directly because of input