Added work in progress command for getting info about files, currently only supports TMDs

This commit is contained in:
Campbell 2024-08-03 14:06:33 -04:00
parent fc8bef61a7
commit 1b7c9afb53
Signed by: NinjaCheetah
GPG Key ID: B547958AF96ED344
4 changed files with 85 additions and 19 deletions

View File

@ -62,18 +62,20 @@ def handle_emunand_title(args):
title_dir = title_dir.joinpath(tid_lower)
if not title_dir.exists():
title_dir.mkdir()
title_dir = title_dir.joinpath("content")
if not title_dir.exists():
title_dir.mkdir()
tmd_out = open(title_dir.joinpath("title.tmd"), "wb")
content_dir = title_dir.joinpath("content")
if not content_dir.exists():
content_dir.mkdir()
tmd_out = open(content_dir.joinpath("title.tmd"), "wb")
tmd_out.write(title.wad.get_tmd_data())
tmd_out.close()
for content_file in range(0, title.tmd.num_contents):
if title.tmd.content_records[content_file].content_type == 1:
content_file_name = f"{title.tmd.content_records[content_file].content_id:08X}".lower()
content_out = open(title_dir.joinpath(content_file_name + ".app"), "wb")
content_out = open(content_dir.joinpath(content_file_name + ".app"), "wb")
content_out.write(title.get_content_by_index(content_file))
content_out.close()
if not title_dir.joinpath("data").exists():
title_dir.joinpath("data").mkdir() # Empty directory used for save data for the title.
# Shared contents need to be installed to /shared1/, with incremental names determined by /shared1/content.map.
content_map_path = shared_dir.joinpath("content.map")

55
modules/title/info.py Normal file
View File

@ -0,0 +1,55 @@
# "modules/title/info.py" from WiiPy by NinjaCheetah
# https://github.com/NinjaCheetah/WiiPy
import pathlib
import libWiiPy
def _print_tmd_info(tmd: libWiiPy.title.TMD):
# Get all important keys from the TMD and print them out nicely.
print("Title Info")
print(f" Title ID: {tmd.title_id}")
# This type of version number really only applies to the System Menu and IOS.
if tmd.title_id[:8] == "00000001":
print(f" Title Version: {tmd.title_version} ({tmd.title_version_converted})")
else:
print(f" Title Version: {tmd.title_version}")
if tmd.ios_tid == "0000000000000000":
print(f" IOS Version: N/A")
else:
print(f" Required IOS: IOS{int(tmd.ios_tid[-2:], 16)} ({tmd.ios_tid})")
print(f" Region: {tmd.get_title_region()}")
print(f" Title Type: {tmd.get_title_type()}")
print(f" vWii Title: {bool(tmd.vwii)}")
print(f" DVD Video Access: {tmd.get_access_right(tmd.AccessFlags.DVD_VIDEO)}")
print(f" AHB Access: {tmd.get_access_right(tmd.AccessFlags.AHB)}")
print(f" Fakesigned: {tmd.get_is_fakesigned()}")
# Iterate over the content and print their details.
print("\nContent Info")
print(f"Total Contents: {tmd.num_contents}")
for content in tmd.content_records:
print(f" Content Index: {content.index}")
print(f" Content ID: " + f"{content.content_id:08X}".lower())
print(f" Content Type: {tmd.get_content_type(content.index)}")
print(f" Content Size: {content.content_size} bytes")
print(f" Content Hash: {content.content_hash.decode()}")
def handle_info(args):
input_path = pathlib.Path(args.input)
if not input_path.exists():
raise FileNotFoundError(input_path)
if input_path.suffix.lower() == ".tmd":
tmd = libWiiPy.title.TMD()
tmd.load(open(input_path, "rb").read())
_print_tmd_info(tmd)
#elif input_path.suffix.lower() == ".tik":
# tik = libWiiPy.title.Ticket()
# tik.load(open(input_path, "rb").read())
#elif input_path.suffix.lower() == ".wad":
# title = libWiiPy.title.Title()
# title.load_wad(open(input_path, "rb").read())
else:
raise TypeError("This does not appear to be a TMD, Ticket, or WAD! No info can be provided.")

View File

@ -5,7 +5,7 @@ import pathlib
import libWiiPy
def patch_fakesigning(ios_patcher: libWiiPy.title.IOSPatcher) -> int:
def _patch_fakesigning(ios_patcher: libWiiPy.title.IOSPatcher) -> int:
print("Applying fakesigning patch... ", end="", flush=True)
count = ios_patcher.patch_fakesigning()
if count == 1:
@ -15,7 +15,7 @@ def patch_fakesigning(ios_patcher: libWiiPy.title.IOSPatcher) -> int:
return count
def patch_es_identify(ios_patcher: libWiiPy.title.IOSPatcher) -> int:
def _patch_es_identify(ios_patcher: libWiiPy.title.IOSPatcher) -> int:
print("Applying ES_Identify access patch... ", end="", flush=True)
count = ios_patcher.patch_es_identify()
if count == 1:
@ -25,7 +25,7 @@ def patch_es_identify(ios_patcher: libWiiPy.title.IOSPatcher) -> int:
return count
def patch_nand_access(ios_patcher: libWiiPy.title.IOSPatcher) -> int:
def _patch_nand_access(ios_patcher: libWiiPy.title.IOSPatcher) -> int:
print("Applying /dev/flash access patch... ", end="", flush=True)
count = ios_patcher.patch_nand_access()
if count == 1:
@ -35,7 +35,7 @@ def patch_nand_access(ios_patcher: libWiiPy.title.IOSPatcher) -> int:
return count
def patch_version_downgrading(ios_patcher: libWiiPy.title.IOSPatcher) -> int:
def _patch_version_downgrading(ios_patcher: libWiiPy.title.IOSPatcher) -> int:
print("Applying version downgrading patch... ", end="", flush=True)
count = ios_patcher.patch_version_downgrading()
if count == 1:
@ -45,7 +45,9 @@ def patch_version_downgrading(ios_patcher: libWiiPy.title.IOSPatcher) -> int:
return count
def patch_drive_inquiry(ios_patcher: libWiiPy.title.IOSPatcher) -> int:
def _patch_drive_inquiry(ios_patcher: libWiiPy.title.IOSPatcher) -> int:
print("\n/!\\ WARNING! /!\\\n"
"This drive inquiry patch is experimental, and may introduce unexpected side effects on some consoles.\n")
print("Applying drive inquiry patch... ", end="", flush=True)
count = ios_patcher.patch_drive_inquiry()
if count == 1:
@ -82,21 +84,21 @@ def handle_iospatch(args):
ios_patcher.load(title)
if args.all is True:
patch_count += patch_fakesigning(ios_patcher)
patch_count += patch_es_identify(ios_patcher)
patch_count += patch_nand_access(ios_patcher)
patch_count += patch_version_downgrading(ios_patcher)
patch_count += _patch_fakesigning(ios_patcher)
patch_count += _patch_es_identify(ios_patcher)
patch_count += _patch_nand_access(ios_patcher)
patch_count += _patch_version_downgrading(ios_patcher)
else:
if args.fakesigning is True:
patch_count += patch_fakesigning(ios_patcher)
patch_count += _patch_fakesigning(ios_patcher)
if args.es_identify is True:
patch_count += patch_es_identify(ios_patcher)
patch_count += _patch_es_identify(ios_patcher)
if args.nand_access is True:
patch_count += patch_nand_access(ios_patcher)
patch_count += _patch_nand_access(ios_patcher)
if args.version_downgrading is True:
patch_count += patch_version_downgrading(ios_patcher)
patch_count += _patch_version_downgrading(ios_patcher)
if args.drive_inquiry is True:
patch_count += patch_drive_inquiry(ios_patcher)
patch_count += _patch_drive_inquiry(ios_patcher)
print(f"\nTotal patches applied: {patch_count}")

View File

@ -8,6 +8,7 @@ from modules.archive.ash import *
from modules.archive.u8 import *
from modules.title.emunand import *
from modules.title.fakesign import *
from modules.title.info import *
from modules.title.iospatcher import *
from modules.title.nus import *
from modules.title.wad import *
@ -58,6 +59,12 @@ if __name__ == "__main__":
fakesign_parser.add_argument("input", metavar="IN", type=str, help="input file")
fakesign_parser.add_argument("-o", "--output", metavar="OUT", type=str, help="output file (optional)")
# Argument parser for the info command.
info_parser = subparsers.add_parser("info", help="get information about a TMD, Ticket, or WAD",
description="get information about a TMD, Ticket, or WAD")
info_parser.set_defaults(func=handle_info)
info_parser.add_argument("input", metavar="IN", type=str, help="input file")
# Argument parser for the iospatch command.
iospatch_parser = subparsers.add_parser("iospatch", help="patch IOS WADs to re-enable exploits",
description="patch IOS WADs to re-enable exploits; by default, this will"