Changed setting generation syntax, added commands to encrypt/decrypt setting file

This commit is contained in:
Campbell 2024-10-10 14:42:12 -04:00
parent 676dbab4f1
commit 0a9733a8d3
Signed by: NinjaCheetah
GPG Key ID: 670C282B3291D63D
3 changed files with 123 additions and 59 deletions

57
modules/nand/emunand.py Normal file
View File

@ -0,0 +1,57 @@
# "modules/nand/emunand.py" from WiiPy by NinjaCheetah
# https://github.com/NinjaCheetah/WiiPy
import pathlib
import libWiiPy
def handle_emunand_title(args):
emunand = libWiiPy.nand.EmuNAND(args.emunand)
if args.skip_hash:
skip_hash = True
else:
skip_hash = False
# Code for if the --install argument was passed.
if args.install:
input_path = pathlib.Path(args.install)
if not input_path.exists():
raise FileNotFoundError(input_path)
if input_path.is_dir():
wad_files = list(input_path.glob("*.[wW][aA][dD]"))
if not wad_files:
raise FileNotFoundError("No WAD files were found in the provided input directory!")
wad_count = 0
for wad in wad_files:
title = libWiiPy.title.Title()
title.load_wad(open(wad, "rb").read())
try:
emunand.install_title(title, skip_hash=skip_hash)
wad_count += 1
except ValueError:
print(f"WAD {wad} could not be installed!")
print(f"Successfully installed {wad_count} WAD(s) to EmuNAND!")
else:
title = libWiiPy.title.Title()
title.load_wad(open(input_path, "rb").read())
emunand.install_title(title, skip_hash=skip_hash)
print("Successfully installed WAD to EmuNAND!")
# Code for if the --uninstall argument was passed.
elif args.uninstall:
input_str = args.uninstall
if pathlib.Path(input_str).exists():
title = libWiiPy.title.Title()
title.load_wad(open(pathlib.Path(input_str), "rb").read())
target_tid = title.tmd.title_id
else:
target_tid = input_str
if len(target_tid) != 16:
raise ValueError("Invalid Title ID! Title IDs must be 16 characters long.")
emunand.uninstall_title(target_tid)
print("Title uninstalled from EmuNAND!")

View File

@ -1,63 +1,47 @@
# "modules/title/emunand.py" from WiiPy by NinjaCheetah
# "modules/nand/setting.py" from WiiPy by NinjaCheetah
# https://github.com/NinjaCheetah/WiiPy
import pathlib
import libWiiPy
def handle_emunand_title(args):
emunand = libWiiPy.nand.EmuNAND(args.emunand)
if args.skip_hash:
skip_hash = True
def handle_setting_decrypt(args):
input_path = pathlib.Path(args.input)
if args.output is not None:
output_path = pathlib.Path(args.output)
else:
skip_hash = False
output_path = pathlib.Path(input_path.stem + "_dec" + input_path.suffix)
# Code for if the --install argument was passed.
if args.install:
input_path = pathlib.Path(args.install)
if not input_path.exists():
raise FileNotFoundError(input_path)
if not input_path.exists():
raise FileNotFoundError(input_path)
if input_path.is_dir():
wad_files = list(input_path.glob("*.[wW][aA][dD]"))
if not wad_files:
raise FileNotFoundError("No WAD files were found in the provided input directory!")
wad_count = 0
for wad in wad_files:
title = libWiiPy.title.Title()
title.load_wad(open(wad, "rb").read())
try:
emunand.install_title(title, skip_hash=skip_hash)
wad_count += 1
except ValueError:
print(f"WAD {wad} could not be installed!")
print(f"Successfully installed {wad_count} WAD(s) to EmuNAND!")
else:
title = libWiiPy.title.Title()
title.load_wad(open(input_path, "rb").read())
emunand.install_title(title, skip_hash=skip_hash)
print("Successfully installed WAD to EmuNAND!")
# Code for if the --uninstall argument was passed.
elif args.uninstall:
input_str = args.uninstall
if pathlib.Path(input_str).exists():
title = libWiiPy.title.Title()
title.load_wad(open(pathlib.Path(input_str), "rb").read())
target_tid = title.tmd.title_id
else:
target_tid = input_str
if len(target_tid) != 16:
raise ValueError("Invalid Title ID! Title IDs must be 16 characters long.")
emunand.uninstall_title(target_tid)
print("Title uninstalled from EmuNAND!")
# Load and decrypt the provided file.
setting = libWiiPy.nand.SettingTxt()
setting.load(open(input_path, "rb").read())
# Write out the decrypted data.
open(output_path, "w").write(setting.dump_decrypted())
print("Successfully decrypted setting.txt!")
def handle_emunand_gensetting(args):
def handle_setting_encrypt(args):
input_path = pathlib.Path(args.input)
if args.output is not None:
output_path = pathlib.Path(args.output)
else:
output_path = pathlib.Path("setting.txt")
if not input_path.exists():
raise FileNotFoundError(input_path)
# Load and encrypt the provided file.
setting = libWiiPy.nand.SettingTxt()
setting.load_decrypted(open(input_path, "r").read())
# Write out the encrypted data.
open(output_path, "wb").write(setting.dump())
print("Successfully encrypted setting.txt!")
def handle_setting_gen(args):
# Validate the provided SN. It should be 2 or 3 letters followed by 9 numbers.
if len(args.serno) != 11 and len(args.serno) != 12:
raise ValueError("The provided Serial Number is not valid!")
@ -113,3 +97,4 @@ def handle_emunand_gensetting(args):
setting.game = game
# Write out the setting.txt file.
open("setting.txt", "wb").write(setting.dump())
print(f"Successfully created setting.txt for console with serial number {args.serno}!")

View File

@ -6,8 +6,9 @@ from importlib.metadata import version
from modules.archive.ash import *
from modules.archive.u8 import *
from modules.nand.emunand import *
from modules.nand.setting import *
from modules.title.ciosbuild import *
from modules.title.emunand import *
from modules.title.fakesign import *
from modules.title.info import *
from modules.title.iospatcher import *
@ -71,15 +72,6 @@ if __name__ == "__main__":
"accepts a WAD file to read the TID from)")
emunand_title_parser.add_argument("-s", "--skip-hash", help="skips validating the hashes of decrypted "
"content (install only)", action="store_true")
# Setting generation EmuNAND command.
emunand_gensetting_parser = emunand_subparsers.add_parser("gen-setting",
help="generate a new setting.txt based on the provided values",
description="generate a new setting.txt based on the provided values")
emunand_gensetting_parser.set_defaults(func=handle_emunand_gensetting)
emunand_gensetting_parser.add_argument("serno", metavar="SERNO", type=str,
help="serial number of the console these settings are for")
emunand_gensetting_parser.add_argument("region", metavar="REGION", type=str,
help="region of the console these settings are for (USA, EUR, JPN, or KOR)")
# Argument parser for the fakesign subcommand.
fakesign_parser = subparsers.add_parser("fakesign", help="fakesign a TMD, Ticket, or WAD (trucha bug)",
@ -156,6 +148,36 @@ if __name__ == "__main__":
nus_tmd_parser.add_argument("-o", "--output", metavar="OUT", type=str,
help="path to download the TMD to (optional)")
# Argument parser for the setting subcommand.
setting_parser = subparsers.add_parser("setting", help="manage setting.txt",
description="manage setting.txt")
setting_subparsers = setting_parser.add_subparsers(dest="subcommand", required=True)
# Decrypt setting.txt subcommand.
setting_dec_parser = setting_subparsers.add_parser("decrypt", help="decrypt setting.txt",
description="decrypt setting.txt; by default, this will output "
"to setting_dec.txt")
setting_dec_parser.set_defaults(func=handle_setting_decrypt)
setting_dec_parser.add_argument("input", metavar="IN", type=str, help="encrypted setting.txt file to decrypt")
setting_dec_parser.add_argument("-o", "--output", metavar="OUT", type=str,
help="path to output the decrypted file to (optional)")
# Encrypt setting.txt subcommand.
setting_enc_parser = setting_subparsers.add_parser("encrypt", help="encrypt setting.txt",
description="encrypt setting.txt; by default, this will output "
"to setting.txt")
setting_enc_parser.set_defaults(func=handle_setting_encrypt)
setting_enc_parser.add_argument("input", metavar="IN", type=str, help="decrypted setting.txt file to encrypt")
setting_enc_parser.add_argument("-o", "--output", metavar="OUT", type=str,
help="path to output the encrypted file to (optional)")
# Generate setting.txt subcommand.
setting_gen_parser = setting_subparsers.add_parser("gen",
help="generate a new setting.txt based on the provided values",
description="generate a new setting.txt based on the provided values")
setting_gen_parser.set_defaults(func=handle_setting_gen)
setting_gen_parser.add_argument("serno", metavar="SERNO", type=str,
help="serial number of the console these settings are for")
setting_gen_parser.add_argument("region", metavar="REGION", type=str,
help="region of the console these settings are for (USA, EUR, JPN, or KOR)")
# Argument parser for the U8 subcommand.
u8_parser = subparsers.add_parser("u8", help="pack/unpack a U8 archive",
description="pack/unpack a U8 archive")