diff --git a/Tales_Exe.py b/Tales_Exe.py index 300d677..40135ca 100644 --- a/Tales_Exe.py +++ b/Tales_Exe.py @@ -268,6 +268,7 @@ if __name__ == "__main__": tales_instance.pack_all_menu() tales_instance.patch_binaries() tales_instance.pack_main_archive() + tales_instance.make_iso(Path(args.iso)) # Generate Iso - not yet # xdelta_name = "../Data/Tales-Of-Rebirth/Disc/New/{}.xdelta".format(args.iso.replace(".iso","")) diff --git a/pythonlib/games/ToolsTOR.py b/pythonlib/games/ToolsTOR.py index 5d348e0..948f528 100644 --- a/pythonlib/games/ToolsTOR.py +++ b/pythonlib/games/ToolsTOR.py @@ -6,6 +6,7 @@ import struct from dataclasses import dataclass from itertools import tee from pathlib import Path +from time import time import lxml.etree as etree import pandas as pd @@ -910,6 +911,90 @@ class ToolsTOR(ToolsTales): pbar.update(len(data)) iso.close() + + + def make_iso(self, umd_iso: Path) -> None: + + print("Creating new iso...") + + # We now pack the iso using every shortcut imaginable + # because realistically we won't really touch anything + # apart from the DAT.BIN and SLPS files + # The logic was basically taken from PS2 Iso Rebuilder + + # Let's clean old build (if they exists) + self.clean_builds(self.paths["game_builds"]) + + # Set up new iso name + new_iso = self.paths["game_builds"] / f"TalesOfRebirth_{int(time())}.iso" + + with FileIO(new_iso, "wb+") as new: + + # 1st copy the relevant contents from the original iso + # as we don't touch anything before the DAT.BIN that means + # copying the first 847549 LBAs from the original iso + with open(umd_iso, "rb") as og: + og_sz = 847549 * 0x800 + with tqdm(total=og_sz, desc=f"Copying unchanged data", unit="B", unit_divisor=1024, unit_scale=True) as pbar: + for _ in range(og_sz // 0xCEEBD): + new.write(og.read(0xCEEBD)) + pbar.update(0xCEEBD) + + # Now we grab the 2nd Anchor from the original iso too + # it's at the end of the image, so just grab the last LBA + og.seek(-0x800, 2) + anchor_save = og.read(0x800) + + # Now we plop the new DAT.BIN in its legitimate spot + with open(self.paths["final_files"] / "DAT.BIN", "rb") as dt: + dt.seek(0, 2) + dat_sz = dt.tell() + dt.seek(0) + with tqdm(total=dat_sz, desc=f"Inserting DAT.BIN", unit="B", unit_divisor=1024, unit_scale=True) as pbar: + while data := dt.read(0x8000): + new.write(data) + pbar.update(len(data)) + + # Align to nearest LBA + new.write_padding(0x800) + # get FIELD.BIN LBA + fld_lba = new.tell() // 0x800 + + # Now we plop FIELD.BIN in its legitimate spot + with open(self.paths["original_files"] / "FLD.BIN", "rb") as dt: + dt.seek(0, 2) + fld_sz = dt.tell() + dt.seek(0) + with tqdm(total=fld_sz, desc=f"Inserting FLD.BIN", unit="B", unit_divisor=1024, unit_scale=True) as pbar: + while data := dt.read(0x8000): + new.write(data) + pbar.update(len(data)) + + # Align + new.write_padding(0x8000) + # get end of volume spot + end_lba = new.tell() // 0x800 + + # Put the Anchor in place + new.write(anchor_save) + + # Now we update the file entries, DAT.BIN only need updated + # size, FLD.BIN size and LBA, also update the PVD size + new.write_int32_at(dat_sz, 0x82992) + new.write_int32_at(fld_lba, 0x829C2) + new.write_int32_at(end_lba, 0x8050) + new.write_int32_at(end_lba - 1, end_lba - 0x7F4) + new.set_endian("big") + new.write_int32_at(dat_sz, 0x82996) + new.write_int32_at(fld_lba, 0x829C6) + new.write_int32_at(end_lba, 0x8054) + new.set_endian("little") + + # Finally, the SLPS, it's at the same location and size + # so no problems for us + with open(self.paths["final_files"] / "SLPS_254.50", "rb") as sl: + new.seek(0x89000) + new.write(sl.read()) def clean_folder(self, path: Path) -> None: @@ -920,4 +1005,13 @@ class ToolsTOR(ToolsTales): if file.is_dir(): shutil.rmtree(file) elif file.name.lower() != ".gitignore": - file.unlink(missing_ok=False) \ No newline at end of file + file.unlink(missing_ok=False) + + + def clean_builds(self, path: Path) -> None: + target_files = sorted(list(path.glob("*.iso")))[5:] + if len(target_files) != 0: + print("Cleaning builds folder...") + for file in target_files: + print(f"deleting {str(file)}...") + file.unlink() \ No newline at end of file