WiiPy/wiipy.py
NinjaCheetah a863da98c7
Major updates to info and emunand commands
Info command now displays more info for TMDs, as well as info for Tickets or entire WADs.
EmuNAND command now allows for bulk installing a folder of WADs, and will create/update uid.sys during installation.
2024-08-04 00:00:38 -04:00

159 lines
11 KiB
Python

# "wiipy.py" from WiiPy by NinjaCheetah
# https://github.com/NinjaCheetah/WiiPy
import argparse
from importlib.metadata import version
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 *
if __name__ == "__main__":
# Main argument parser.
parser = argparse.ArgumentParser(
description="A simple command line tool to manage file formats used by the Wii.")
parser.add_argument("--version", action="version",
version=f"WiiPy v1.3.0, based on libWiiPy v{version('libWiiPy')} (from branch \'main\')")
subparsers = parser.add_subparsers(title="subcommands", dest="subcommand", required=True)
# Argument parser for the ASH subcommand.
ash_parser = subparsers.add_parser("ash", help="compress/decompress an ASH file",
description="compress/decompress an ASH file")
ash_parser.set_defaults(func=handle_ash)
ash_group = ash_parser.add_mutually_exclusive_group(required=True)
ash_group.add_argument("-c", "--compress", help="compress a file into an ASH file", action="store_true")
ash_group.add_argument("-d", "--decompress", help="decompress an ASH file", action="store_true")
ash_parser.add_argument("input", metavar="IN", type=str, help="input file")
ash_parser.add_argument("output", metavar="OUT", type=str, help="output file")
ash_parser.add_argument("--sym-bits", metavar="SYM_BITS", type=int,
help="number of bits in each symbol tree leaf (default: 9)", default=9)
ash_parser.add_argument("--dist-bits", metavar="DIST_BITS", type=int,
help="number of bits in each distance tree leaf (default: 11)", default=11)
# Argument parser for the EmuNAND subcommand.
emunand_parser = subparsers.add_parser("emunand", help="manage Wii EmuNAND directories",
description="manage Wii EmuNAND directories")
emunand_subparsers = emunand_parser.add_subparsers(title="emunand", dest="emunand", required=True)
# Title EmuNAND subcommand.
emunand_title_parser = emunand_subparsers.add_parser("title", help="manage titles on an EmuNAND",
description="manage titles on an EmuNAND")
emunand_title_parser.set_defaults(func=handle_emunand_title)
emunand_title_parser.add_argument("emunand", metavar="EMUNAND", type=str,
help="path to the target EmuNAND directory")
emunand_title_install_group = emunand_title_parser.add_mutually_exclusive_group(required=True)
emunand_title_install_group.add_argument("--install", metavar="WAD", type=str,
help="install the target WAD(s) to an EmuNAND (can be a single file or a "
"folder of WADs)")
emunand_title_install_group.add_argument("--uninstall", metavar="TID", type=str,
help="uninstall a title with the provided Title ID from an EmuNAND")
# Argument parser for the fakesign subcommand.
fakesign_parser = subparsers.add_parser("fakesign", help="fakesign a TMD, Ticket, or WAD (trucha bug)",
description="fakesign a TMD, Ticket, or WAD (trucha bug); by default, this "
"will overwrite the input file if no output file is specified")
fakesign_parser.set_defaults(func=handle_fakesign)
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"
"overwrite the input file in place unless you use -o/--output")
iospatch_parser.set_defaults(func=handle_iospatch)
iospatch_parser.add_argument("input", metavar="IN", type=str, help="input file")
iospatch_parser.add_argument("-o", "--output", metavar="OUT", type=str, help="output file (optional)")
iospatch_parser.add_argument("-fs", "--fakesigning", action="store_true", help="patch in fakesigning support")
iospatch_parser.add_argument("-ei", "--es-identify", action="store_true", help="patch in ES_Identify access")
iospatch_parser.add_argument("-na", "--nand-access", action="store_true", help="patch in /dev/flash access")
iospatch_parser.add_argument("-vd", "--version-downgrading", action="store_true",
help="patch in version downgrading support")
iospatch_parser.add_argument("-di", "--drive-inquiry", action="store_true",
help="patches out the drive inquiry check")
iospatch_parser.add_argument("-v", "--version", metavar="VERSION", type=int, help="set the IOS version")
iospatch_parser.add_argument("-s", "--slot", metavar="SLOT", type=int,
help="set the slot that this IOS will install to")
iospatch_parser.add_argument("-a", "--all", action="store_true", help="apply all patches (overrides other options)")
iospatch_parser.add_argument("-ns", "--no-shared", action="store_true",
help="set all patched content to be non-shared")
# Argument parser for the NUS subcommand.
nus_parser = subparsers.add_parser("nus", help="download data from the NUS",
description="download from the NUS")
nus_subparsers = nus_parser.add_subparsers(dest="subcommand", required=True)
# Title NUS subcommand.
nus_title_parser = nus_subparsers.add_parser("title", help="download a title from the NUS",
description="download a title from the NUS")
nus_title_parser.set_defaults(func=handle_nus_title)
nus_title_parser.add_argument("tid", metavar="TID", type=str, help="Title ID to download")
nus_title_parser.add_argument("-v", "--version", metavar="VERSION", type=int,
help="version to download (optional)")
nus_title_out_group_label = nus_title_parser.add_argument_group(title="output types (required)")
nus_title_out_group = nus_title_out_group_label.add_mutually_exclusive_group(required=True)
nus_title_out_group.add_argument("-o", "--output", metavar="OUT", type=str,
help="download the title to a folder")
nus_title_out_group.add_argument("-w", "--wad", metavar="WAD", type=str,
help="pack a wad with the provided name")
nus_title_parser.add_argument("--wii", help="use original Wii NUS instead of the Wii U servers",
action="store_true")
# Content NUS subcommand.
nus_content_parser = nus_subparsers.add_parser("content", help="download a specific content from the NUS",
description="download a specific content from the NUS")
nus_content_parser.set_defaults(func=handle_nus_content)
nus_content_parser.add_argument("tid", metavar="TID", type=str, help="Title ID the content belongs to")
nus_content_parser.add_argument("cid", metavar="CID", type=str,
help="Content ID to download (in \"000000xx\" format)")
nus_content_parser.add_argument("-v", "--version", metavar="VERSION", type=int,
help="version this content belongs to (required for decryption)")
nus_content_parser.add_argument("-o", "--output", metavar="OUT", type=str,
help="path to download the content to (optional)")
nus_content_parser.add_argument("-d", "--decrypt", action="store_true", help="decrypt this content")
# TMD NUS subcommand.
nus_tmd_parser = nus_subparsers.add_parser("tmd", help="download a tmd from the NUS",
description="download a tmd from the NUS")
nus_tmd_parser.set_defaults(func=handle_nus_tmd)
nus_tmd_parser.add_argument("tid", metavar="TID", type=str, help="Title ID the TMD is for")
nus_tmd_parser.add_argument("-v", "--version", metavar="VERSION", type=int, help="version of the TMD to download")
nus_tmd_parser.add_argument("-o", "--output", metavar="OUT", type=str,
help="path to download the TMD to (optional)")
# Argument parser for the U8 subcommand.
u8_parser = subparsers.add_parser("u8", help="pack/unpack a U8 archive",
description="pack/unpack a U8 archive")
u8_parser.set_defaults(func=handle_u8)
u8_group = u8_parser.add_mutually_exclusive_group(required=True)
u8_group.add_argument("-p", "--pack", help="pack a directory to a U8 archive", action="store_true")
u8_group.add_argument("-u", "--unpack", help="unpack a U8 archive to a directory", action="store_true")
u8_parser.add_argument("input", metavar="IN", type=str, help="input file")
u8_parser.add_argument("output", metavar="OUT", type=str, help="output file")
# Argument parser for the WAD subcommand.
wad_parser = subparsers.add_parser("wad", help="pack/unpack a WAD file",
description="pack/unpack a WAD file")
wad_parser.set_defaults(func=handle_wad)
wad_group = wad_parser.add_mutually_exclusive_group(required=True)
wad_group.add_argument("-p", "--pack", help="pack a directory to a WAD file", 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("output", metavar="OUT", type=str, help="output file")
wad_pack_group = wad_parser.add_argument_group(title="packing options")
wad_pack_group.add_argument("-f", "--fakesign", help="fakesign the TMD and Ticket (trucha bug)",
action="store_true")
wad_unpack_group = wad_parser.add_argument_group(title="unpacking options")
wad_unpack_group.add_argument("-s", "--skip-hash", help="skips validating the hashes of decrypted "
"content", action="store_true")
# Parse all the args, and call the appropriate function with all of those args if a valid subcommand was passed.
args = parser.parse_args()
args.func(args)