From 4d071e190fc1341c4ad812a0bc873b5d65d04d26 Mon Sep 17 00:00:00 2001 From: Faraphel Date: Fri, 15 Jul 2022 00:28:04 +0200 Subject: [PATCH] extracted szs directory will now be repacked into szs files --- source/mkw/ExtractedGame.py | 30 ++++++++++++++++++++++++++---- source/mkw/Game.py | 12 +++++++----- source/mkw/Patch/Patch.py | 3 +++ source/wt/szs.py | 23 +++++++++++++++++++++-- 4 files changed, 57 insertions(+), 11 deletions(-) diff --git a/source/mkw/ExtractedGame.py b/source/mkw/ExtractedGame.py index 487ad07..a46dcac 100644 --- a/source/mkw/ExtractedGame.py +++ b/source/mkw/ExtractedGame.py @@ -1,3 +1,4 @@ +import shutil from io import BytesIO from pathlib import Path from typing import Generator, IO @@ -5,6 +6,7 @@ from typing import Generator, IO from source.mkw.ModConfig import ModConfig from source.mkw.Patch.Patch import Patch from source.wt import szs +from source.wt.wstrt import StrPath class ExtractedGame: @@ -12,12 +14,12 @@ class ExtractedGame: Class that represents an extracted game """ - def __init__(self, path: Path | str, original_game: "Game" = None): + def __init__(self, path: "Path | str", original_game: "Game" = None): self.path = Path(path) self.original_game = original_game self._special_file: dict[str, IO] = {} - def extract_autoadd(self, destination_path: Path | str) -> Generator[dict, None, None]: + def extract_autoadd(self, destination_path: "Path | str") -> Generator[dict, None, None]: """ Extract all the autoadd files from the game to destination_path :param destination_path: directory where the autoadd files will be extracted @@ -45,12 +47,31 @@ class ExtractedGame: ct_icons.seek(0) self._special_file["ct_icon"] = ct_icons + def prepare_dol(self) -> Generator[dict, None, None]: + """ + Prepare main.dol and StaticR.rel files (clean them and add lecode) + """ + yield {"description": "Preparing main.dol...", "determinate": False} + StrPath(self.path / "sys/main.dol").patch(clean_dol=True, add_lecode=True) + + def recreate_all_szs(self) -> Generator[dict, None, None]: + """ + Repack all the .d directory into .szs files. + :param extracted_game: the extracted game + """ + yield {"description": f"Repacking all szs", "determinate": False} + + for extracted_szs in filter(lambda path: path.is_dir(), self.path.rglob("*.d")): + # for every directory that end with a .d in the extracted game, recreate the szs + yield {"description": f"Repacking {extracted_szs} to szs", "determinate": False} + + szs.create(extracted_szs, extracted_szs.with_suffix(".szs"), overwrite=True) + shutil.rmtree(str(extracted_szs.resolve())) + def install_all_patch(self, mod_config: ModConfig) -> Generator[dict, None, None]: """ Install all patchs of the mod_config into the game - :param special_file: special file that can be used to patch the game :param mod_config: the mod to install - :return: """ yield {"description": "Installing all Patch...", "determinate": False} @@ -62,3 +83,4 @@ class ExtractedGame: for part_directory in mod_config.get_mod_directory().glob("[!_]*"): for patch_directory in part_directory.glob("_PATCH/"): yield from Patch(patch_directory, mod_config, self._special_file).install(self) + diff --git a/source/mkw/Game.py b/source/mkw/Game.py index 9d4a3a9..74efe9e 100644 --- a/source/mkw/Game.py +++ b/source/mkw/Game.py @@ -7,19 +7,19 @@ from source.wt.wit import WITPath, Region, Extension class NotMKWGameError(Exception): - def __init__(self, path: Path | str): + def __init__(self, path: "Path | str"): path = Path(path) super().__init__(f'Not a Mario Kart Wii game : "{path.name}"') class NotVanillaError(Exception): - def __init__(self, path: Path | str): + def __init__(self, path: "Path | str"): path = Path(path) super().__init__(f'This game is already modded : "{path.name}"') class Game: - def __init__(self, path: Path | str): + def __init__(self, path: "Path | str"): self.wit_path = WITPath(path) def is_mkw(self) -> bool: @@ -36,7 +36,7 @@ class Game: """ return not any(self.wit_path[f"./files/rel/lecode-{region.value}.bin"].exists() for region in Region) - def extract(self, dest: Path | str) -> Generator[dict, None, Path]: + def extract(self, dest: "Path | str") -> Generator[dict, None, Path]: """ Extract the game to the destination directory. If the game is a FST, just copy to the destination :param dest: destination directory @@ -67,7 +67,7 @@ class Game: return e.value @staticmethod - def get_output_directory(dest: Path | str, mod_config: ModConfig) -> Path: + def get_output_directory(dest: "Path | str", mod_config: ModConfig) -> Path: """ Return the directory where the game will be installed :param dest: destination directory @@ -107,5 +107,7 @@ class Game: yield from self.extract(extracted_game.path) yield from extracted_game.extract_autoadd(cache_directory / "autoadd/") yield from extracted_game.install_mystuff() + yield from extracted_game.prepare_dol() yield from extracted_game.install_all_patch(mod_config) + yield from extracted_game.recreate_all_szs() diff --git a/source/mkw/Patch/Patch.py b/source/mkw/Patch/Patch.py index ee1382c..d8c2390 100644 --- a/source/mkw/Patch/Patch.py +++ b/source/mkw/Patch/Patch.py @@ -2,6 +2,7 @@ from typing import Generator, IO from source.mkw.Patch import * from source.safe_eval import safe_eval, multiple_safe_eval +from source.wt import szs class Patch: @@ -34,8 +35,10 @@ class Patch: def install(self, extracted_game: "ExtractedGame") -> Generator[dict, None, None]: """ patch a game with this Patch + :param extracted_game: the extracted game """ from source.mkw.Patch.PatchDirectory import PatchDirectory + yield {"description": f"Installing the patch", "determinate": False} # take all the files in the root directory, and patch them into the game. # Patch is not directly applied to the root to avoid custom configuration diff --git a/source/wt/szs.py b/source/wt/szs.py index 700f40f..9561f6b 100644 --- a/source/wt/szs.py +++ b/source/wt/szs.py @@ -21,6 +21,25 @@ def autoadd(course_directory: Path | str, destination_path: Path | str) -> Path: return destination_path +@better_wt_error(tools_path) +def create(extracted_szs: Path | str, dest: Path | str, overwrite: bool = False) -> "SZSPath": + """ + Convert extracted_szs into a szs archive + :param overwrite: should the destination be overwritten + :param dest: destination where to create the szs file + :param extracted_szs: the extracted szs directory + :return: a SZSPath + """ + extracted_szs = Path(extracted_szs) + dest = Path(dest) + + args = [] + if overwrite: args.append("--overwrite") + + _tools_run("CREATE", extracted_szs, "--DEST", dest, *args) + return SZSPath(dest) + + class SZSPath: __slots__ = ("path", "_analyze") @@ -40,7 +59,7 @@ class SZSPath: :param subfile: subfile name :return: the content of the subfile """ - return _tools_run("cat", self.path / subfile) + return _tools_run("cat", (self.path / subfile)) def extract(self, subfile: str, dest: Path | str) -> Path: """ @@ -60,7 +79,7 @@ class SZSPath: dest: Path = Path(dest) if dest.is_dir(): dest /= self.path.name - _tools_run("EXTRACT", self.path, "-D", dest) + _tools_run("EXTRACT", self.path, "--DEST", dest) return dest def analyze(self) -> dict: