Added wad retail2dev and wad dev2retail to convert dev and retail WADs back and forth

This commit is contained in:
Campbell 2024-10-13 22:07:02 -04:00
parent 079c7f9109
commit 4636deeb0a
Signed by: NinjaCheetah
GPG Key ID: B547958AF96ED344
2 changed files with 62 additions and 0 deletions

View File

@ -332,3 +332,53 @@ def handle_wad_unpack(args):
content_out.close()
print("WAD file unpacked!")
def handle_wad_d2r(args):
input_path = pathlib.Path(args.input)
output_path = pathlib.Path(input_path.stem + "_retail" + input_path.suffix)
if not input_path.exists():
raise FileNotFoundError(input_path)
title = libWiiPy.title.Title()
title.load_wad(input_path.read_bytes())
# First, verify that this IS actually a dev WAD.
if not title.ticket.is_dev:
raise ValueError("This is not a development WAD!")
# Now, extract the Title Key, change the certs in the TMD/tik, and set the new retail-encrypted Title Key. The certs
# need to be changed so that this WAD can be identified as retail later. The WAD will also be fakesigned, since
# making this change invalidates the signature, so there's no downside.
title_key = title.ticket.get_title_key()
title.ticket.signature_issuer = "Root-CA00000001-XS00000003" + title.ticket.signature_issuer[26:]
title_key_retail = libWiiPy.title.encrypt_title_key(title_key, 0, title.ticket.title_id, False)
title.ticket.title_key_enc = title_key_retail
title.tmd.signature_issuer = "Root-CA00000001-CP00000004" + title.tmd.signature_issuer[26:]
title.fakesign()
open(output_path, "wb").write(title.dump_wad())
print(f"Successfully converted development WAD to retail WAD \"{output_path.name}\"!")
def handle_wad_r2d(args):
input_path = pathlib.Path(args.input)
output_path = pathlib.Path(input_path.stem + "_dev" + input_path.suffix)
if not input_path.exists():
raise FileNotFoundError(input_path)
title = libWiiPy.title.Title()
title.load_wad(input_path.read_bytes())
# First, verify that this IS actually a retail WAD.
if title.ticket.is_dev:
raise ValueError("This is not a retail WAD!")
# Now, extract the Title Key, change the certs in the TMD/tik, and set the new dev-encrypted Title Key. The certs
# need to be changed so that this WAD can be identified as dev later. The WAD will also be fakesigned, since making
# this change invalidates the signature, so there's no downside.
title_key = title.ticket.get_title_key()
title.ticket.signature_issuer = "Root-CA00000002-XS00000006" + title.ticket.signature_issuer[26:]
title_key_dev = libWiiPy.title.encrypt_title_key(title_key, 0, title.ticket.title_id, True)
title.ticket.title_key_enc = title_key_dev
title.tmd.signature_issuer = "Root-CA00000002-CP00000007" + title.tmd.signature_issuer[26:]
title.fakesign()
open(output_path, "wb").write(title.dump_wad())
print(f"Successfully converted retail WAD to development WAD \"{output_path.name}\"!")

View File

@ -207,6 +207,12 @@ if __name__ == "__main__":
"(optional, will default to \"Normal\" if not specified)")
wad_add_parser.add_argument("-o", "--output", metavar="OUT", type=str,
help="file to output the updated WAD to (optional)")
# dev2retail WAD subcommand.
wad_d2r_parser = wad_subparsers.add_parser("dev2retail", help="re-encrypt a dev WAD for retail consoles",
description="re-encrypt a dev WAD for retail consoles, and update"
"the certs to match; this also fakesigns the WAD")
wad_d2r_parser.set_defaults(func=handle_wad_d2r)
wad_d2r_parser.add_argument("input", metavar="IN", type=str, help="dev WAD file to re-encrypt")
# Pack WAD subcommand.
wad_pack_parser = wad_subparsers.add_parser("pack", help="pack a directory to a WAD file",
description="pack a directory to a WAD file")
@ -229,6 +235,12 @@ if __name__ == "__main__":
help="Content ID of the content to remove")
wad_remove_parser.add_argument("-o", "--output", metavar="OUT", type=str,
help="file to output the updated WAD to (optional)")
# retail2dev WAD subcommand.
wad_r2d_parser = wad_subparsers.add_parser("retail2dev", help="re-encrypt a retail WAD for development consoles",
description="re-encrypt a retail WAD for development consoles, and "
"update the certs to match; this also fakesigns the WAD")
wad_r2d_parser.set_defaults(func=handle_wad_r2d)
wad_r2d_parser.add_argument("input", metavar="IN", type=str, help="retail WAD file to re-encrypt")
# Set WAD subcommand.
wad_set_parser = wad_subparsers.add_parser("set", help="set content in a WAD file",
description="replace existing content in a WAD file with new decrypted "