mirror of
https://github.com/NinjaCheetah/WiiPy.git
synced 2026-02-16 18:15:40 -05:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
436189659d
|
|||
|
5cff545921
|
|||
|
dcafda4b71
|
@@ -8,6 +8,15 @@ import libWiiPy
|
|||||||
def handle_nus(args):
|
def handle_nus(args):
|
||||||
title_version = None
|
title_version = None
|
||||||
file_path = None
|
file_path = None
|
||||||
|
tid = args.tid
|
||||||
|
if args.wii:
|
||||||
|
use_wiiu_servers = False
|
||||||
|
else:
|
||||||
|
use_wiiu_servers = True
|
||||||
|
if args.verbose:
|
||||||
|
verbose = True
|
||||||
|
else:
|
||||||
|
verbose = False
|
||||||
|
|
||||||
# Check if --version was passed, because it'll be None if it wasn't.
|
# Check if --version was passed, because it'll be None if it wasn't.
|
||||||
if args.version is not None:
|
if args.version is not None:
|
||||||
@@ -26,8 +35,54 @@ def handle_nus(args):
|
|||||||
if file_path.suffix != ".wad":
|
if file_path.suffix != ".wad":
|
||||||
file_path = file_path.with_suffix(".wad")
|
file_path = file_path.with_suffix(".wad")
|
||||||
|
|
||||||
# libWiiPy accepts a title version of "None" and will just use the latest available version if it gets it.
|
# Download the title from the NUS. This is done "manually" (as opposed to using download_title()) so that we can
|
||||||
title = libWiiPy.title.download_title(args.tid, title_version)
|
# provide verbose output if desired.
|
||||||
|
title = libWiiPy.title.Title()
|
||||||
|
|
||||||
|
# Announce the title being downloaded, and the version if applicable.
|
||||||
|
if verbose:
|
||||||
|
if title_version is not None:
|
||||||
|
print("Downloading title " + tid + " v" + str(title_version) + ", please wait...")
|
||||||
|
else:
|
||||||
|
print("Downloading title " + tid + " vLatest, please wait...")
|
||||||
|
|
||||||
|
# Download a specific TMD version if a version was specified, otherwise just download the latest TMD.
|
||||||
|
if verbose:
|
||||||
|
print(" - Downloading and parsing TMD...")
|
||||||
|
if title_version is not None:
|
||||||
|
title.load_tmd(libWiiPy.title.download_tmd(tid, title_version, wiiu_endpoint=use_wiiu_servers))
|
||||||
|
else:
|
||||||
|
title.load_tmd(libWiiPy.title.download_tmd(tid, wiiu_endpoint=use_wiiu_servers))
|
||||||
|
|
||||||
|
# Download and parse the Ticket.
|
||||||
|
if verbose:
|
||||||
|
print(" - Downloading and parsing Ticket...")
|
||||||
|
try:
|
||||||
|
title.load_ticket(libWiiPy.title.download_ticket(tid, wiiu_endpoint=use_wiiu_servers))
|
||||||
|
except ValueError:
|
||||||
|
# If libWiiPy returns an error, then no ticket is available, so we can't continue.
|
||||||
|
print("No Ticket is available for this title! Exiting...")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Load the content records from the TMD, and begin iterating over the records.
|
||||||
|
title.load_content_records()
|
||||||
|
content_list = []
|
||||||
|
for content in range(len(title.tmd.content_records)):
|
||||||
|
if verbose:
|
||||||
|
print(" - Downloading content " + str(content + 1) + " of " +
|
||||||
|
str(len(title.tmd.content_records)) + " (Content ID: " +
|
||||||
|
str(title.tmd.content_records[content].content_id) + ", Size: " +
|
||||||
|
str(title.tmd.content_records[content].content_size) + " bytes)...")
|
||||||
|
content_list.append(libWiiPy.title.download_content(tid, title.tmd.content_records[content].content_id,
|
||||||
|
wiiu_endpoint=use_wiiu_servers))
|
||||||
|
if verbose:
|
||||||
|
print(" - Done!")
|
||||||
|
title.content.content_list = content_list
|
||||||
|
|
||||||
|
# Get the WAD certificate chain.
|
||||||
|
if verbose:
|
||||||
|
print(" - Building certificate...")
|
||||||
|
title.wad.set_cert_data(libWiiPy.title.download_cert(wiiu_endpoint=use_wiiu_servers))
|
||||||
|
|
||||||
# If we haven't gotten a name yet, make one from the TID and version.
|
# If we haven't gotten a name yet, make one from the TID and version.
|
||||||
if file_path is None:
|
if file_path is None:
|
||||||
|
|||||||
@@ -30,12 +30,8 @@ def handle_u8(args):
|
|||||||
|
|
||||||
u8_data = open(input_path, "rb").read()
|
u8_data = open(input_path, "rb").read()
|
||||||
|
|
||||||
# Ensure the output directory doesn't already exist, because libWiiPy wants to create a new one to ensure that
|
# Output path is deliberately not checked in any way because libWiiPy already has those checks, and it's easier
|
||||||
# the contents of the U8 archive are extracted correctly.
|
# and cleaner to only have one component doing all the checks.
|
||||||
if output_path.exists():
|
|
||||||
print("Error: Specified output directory already exists!")
|
|
||||||
return
|
|
||||||
|
|
||||||
libWiiPy.archive.extract_u8(u8_data, str(output_path))
|
libWiiPy.archive.extract_u8(u8_data, str(output_path))
|
||||||
|
|
||||||
print("U8 archive unpacked!")
|
print("U8 archive unpacked!")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
# "wad.py" from WiiPy by NinjaCheetah
|
# "wad.py" from WiiPy by NinjaCheetah
|
||||||
# https://github.com/NinjaCheetah/WiiPy
|
# https://github.com/NinjaCheetah/WiiPy
|
||||||
|
|
||||||
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
import binascii
|
import binascii
|
||||||
import libWiiPy
|
import libWiiPy
|
||||||
@@ -69,6 +70,11 @@ def handle_wad(args):
|
|||||||
# Method to ensure that the title's content records match between the TMD() and ContentRegion() objects.
|
# Method to ensure that the title's content records match between the TMD() and ContentRegion() objects.
|
||||||
title.load_content_records()
|
title.load_content_records()
|
||||||
|
|
||||||
|
# Nullify TMD/Ticket signatures here if the argument was passed.
|
||||||
|
if args.null_sigs:
|
||||||
|
title.tmd.signature = b'\x00' * 256
|
||||||
|
title.ticket.signature = b'\x00' * 256
|
||||||
|
|
||||||
# Iterate over every file in the content_files list, and attempt to load it into the Title().
|
# Iterate over every file in the content_files list, and attempt to load it into the Title().
|
||||||
for index in range(len(title.content.content_records)):
|
for index in range(len(title.content.content_records)):
|
||||||
for content in range(len(content_files)):
|
for content in range(len(content_files)):
|
||||||
@@ -89,8 +95,14 @@ def handle_wad(args):
|
|||||||
elif args.unpack:
|
elif args.unpack:
|
||||||
if not input_path.exists():
|
if not input_path.exists():
|
||||||
raise FileNotFoundError(input_path)
|
raise FileNotFoundError(input_path)
|
||||||
if not output_path.is_dir():
|
# Check if the output path already exists, and if it does, ensure that it is both a directory and empty.
|
||||||
output_path.mkdir()
|
if output_path.exists():
|
||||||
|
if output_path.is_dir() and next(os.scandir(output_path), None):
|
||||||
|
raise ValueError("Output folder is not empty!")
|
||||||
|
elif output_path.is_file():
|
||||||
|
raise ValueError("A file already exists with the provided name!")
|
||||||
|
else:
|
||||||
|
os.mkdir(output_path)
|
||||||
|
|
||||||
# Step through each component of a WAD and dump it to a file.
|
# Step through each component of a WAD and dump it to a file.
|
||||||
with open(args.input, "rb") as wad_file:
|
with open(args.input, "rb") as wad_file:
|
||||||
|
|||||||
8
wiipy.py
8
wiipy.py
@@ -14,7 +14,7 @@ if __name__ == "__main__":
|
|||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description="WiiPy is a simple command line tool to manage file formats used by the Wii.")
|
description="WiiPy is a simple command line tool to manage file formats used by the Wii.")
|
||||||
parser.add_argument("--version", action="version",
|
parser.add_argument("--version", action="version",
|
||||||
version=f"WiiPy v1.0.0, based on libWiiPy v{version('libWiiPy')} (from branch \'main\')")
|
version=f"WiiPy v1.1.0, based on libWiiPy v{version('libWiiPy')} (from branch \'main\')")
|
||||||
subparsers = parser.add_subparsers(dest="subcommand", required=True)
|
subparsers = parser.add_subparsers(dest="subcommand", required=True)
|
||||||
|
|
||||||
# Argument parser for the WAD subcommand.
|
# Argument parser for the WAD subcommand.
|
||||||
@@ -26,6 +26,8 @@ if __name__ == "__main__":
|
|||||||
wad_group.add_argument("-u", "--unpack", help="unpack a WAD file to a directory", action="store_true")
|
wad_group.add_argument("-u", "--unpack", help="unpack a WAD file to a directory", action="store_true")
|
||||||
wad_parser.add_argument("input", metavar="IN", type=str, help="input file")
|
wad_parser.add_argument("input", metavar="IN", type=str, help="input file")
|
||||||
wad_parser.add_argument("output", metavar="OUT", type=str, help="output file")
|
wad_parser.add_argument("output", metavar="OUT", type=str, help="output file")
|
||||||
|
wad_parser.add_argument("--null-sigs", help="nullify signatures in the TMD and Ticket (packing only)",
|
||||||
|
action="store_true")
|
||||||
|
|
||||||
# Argument parser for the NUS subcommand.
|
# Argument parser for the NUS subcommand.
|
||||||
nus_parser = subparsers.add_parser("nus", help="download a title from the NUS",
|
nus_parser = subparsers.add_parser("nus", help="download a title from the NUS",
|
||||||
@@ -35,6 +37,10 @@ if __name__ == "__main__":
|
|||||||
nus_parser.add_argument("-v", "--version", metavar="VERSION", type=int,
|
nus_parser.add_argument("-v", "--version", metavar="VERSION", type=int,
|
||||||
help="version to download (optional)")
|
help="version to download (optional)")
|
||||||
nus_parser.add_argument("-o", "--output", metavar="OUT", type=str, help="output file (optional)")
|
nus_parser.add_argument("-o", "--output", metavar="OUT", type=str, help="output file (optional)")
|
||||||
|
nus_parser.add_argument("--verbose", help="output more information about the current download",
|
||||||
|
action="store_true")
|
||||||
|
nus_parser.add_argument("-w", "--wii", help="use original Wii NUS instead of the Wii U servers",
|
||||||
|
action="store_true")
|
||||||
|
|
||||||
# Argument parser for the U8 subcommand.
|
# Argument parser for the U8 subcommand.
|
||||||
u8_parser = subparsers.add_parser("u8", help="pack/unpack a U8 archive",
|
u8_parser = subparsers.add_parser("u8", help="pack/unpack a U8 archive",
|
||||||
|
|||||||
Reference in New Issue
Block a user