mirror of
https://github.com/NinjaCheetah/WiiPy.git
synced 2025-04-26 21:31:02 -04:00
116 lines
4.1 KiB
Python
116 lines
4.1 KiB
Python
# "modules/title/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!")
|
|
|
|
|
|
def handle_emunand_gensetting(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!")
|
|
try:
|
|
int(args.serno[-9:])
|
|
except ValueError:
|
|
raise ValueError("The provided Serial Number is not valid!")
|
|
prefix = args.serno[:-9]
|
|
# Detect the console revision based on the SN.
|
|
match prefix[0].upper():
|
|
case "L":
|
|
revision = "RVL-001"
|
|
case "K":
|
|
revision = "RVL-101"
|
|
case "H":
|
|
revision = "RVL-201"
|
|
case _:
|
|
revision = "RVL-001"
|
|
# Validate the region, and then validate the SN based on the region. USA has a two-letter prefix for a total length
|
|
# of 11 characters, while other regions have a three-letter prefix for a total length of 12 characters.
|
|
valid_regions = ["USA", "EUR", "JPN", "KOR"]
|
|
if args.region not in valid_regions:
|
|
raise ValueError("The provided region is not valid!")
|
|
if len(prefix) == 2 and args.region != "USA":
|
|
raise ValueError("The provided region does not match the provided Serial Number!")
|
|
elif len(prefix) == 3 and args.region == "USA":
|
|
raise ValueError("The provided region does not match the provided Serial Number!")
|
|
# Get the values for VIDEO and GAME.
|
|
video = ""
|
|
game = ""
|
|
match args.region:
|
|
case "USA":
|
|
video = "NTSC"
|
|
game = "US"
|
|
case "EUR":
|
|
video = "PAL"
|
|
game = "EU"
|
|
case "JPN":
|
|
video = "NTSC"
|
|
game = "JP"
|
|
case "KOR":
|
|
video = "NTSC"
|
|
game = "KR"
|
|
# Create a new SettingTxt object and load the settings into it.
|
|
setting = libWiiPy.nand.SettingTxt()
|
|
setting.area = args.region
|
|
setting.model = f"{revision}({args.region})"
|
|
setting.dvd = 0
|
|
setting.mpch = "0x7FFE"
|
|
setting.code = prefix
|
|
setting.serial_number = args.serno[-9:]
|
|
setting.video = video
|
|
setting.game = game
|
|
# Write out the setting.txt file.
|
|
open("setting.txt", "wb").write(setting.dump())
|