From ab2987045d6bd9c7141a324ee447f1157058c900 Mon Sep 17 00:00:00 2001 From: Mc-muffin <8714476+Mc-muffin@users.noreply.github.com> Date: Wed, 6 Sep 2023 03:32:21 -0500 Subject: [PATCH] Formatting changes plus cleaning of tales_exe.py, functionality can be restored if needed when NDX and DC are implemented --- Tales_Exe.py | 171 ++------------------- pythonlib/formats/FileIO.py | 16 +- pythonlib/formats/scpk.py | 6 +- pythonlib/formats/theirsce.py | 24 +-- pythonlib/formats/theirsce_instructions.py | 4 +- pythonlib/games/ToolsTOR.py | 23 +-- 6 files changed, 58 insertions(+), 186 deletions(-) diff --git a/Tales_Exe.py b/Tales_Exe.py index ac3ec47..cbc0a71 100644 --- a/Tales_Exe.py +++ b/Tales_Exe.py @@ -1,57 +1,11 @@ import argparse -import io -import os -import subprocess from pathlib import Path -import GoogleAPI -import RepoFunctions from pythonlib.games import ToolsNDX, ToolsTOR -repos_infos ={ - "TOR": - { - "Org": "SymphoniaLauren", - "Repo": "Tales-Of-Rebirth" - }, - "NDX": - { - "Org": "Lifebottle", - "Repo": "Narikiri-Dungeon-X" - } -} - - SCRIPT_VERSION = "0.0.3" -def generate_xdelta_patch(repo_name, xdelta_name="Tales-Of-Rebirth_Patch_New.xdelta"): - - print("Create xdelta patch") - original_path = "../Data/{}/Disc/Original/{}.iso".format(repo_name, repo_name) - new_path = "../Data/{}/Disc/New/{}.iso".format(repo_name, repo_name) - subprocess.run(["xdelta", "-f", "-s", original_path, new_path, xdelta_name]) - - -def get_directory_path(path): - return os.path.dirname(os.path.abspath(path)) - - -def check_arguments(parser, args): - if hasattr(args, "elf_path") and not args.elf_path: - args.elf_path = get_directory_path(args.input) + "/SLPS_254.50" - - if hasattr(args, "elf_out") and not args.elf_out: - args.elf_out = get_directory_path(args.input) + "/NEW_SLPS_254.50" - - if not args.output: - if not os.path.isdir(args.input): - args.output = get_directory_path(args.input) - args.output += "/" + args.input.split("/")[-1] - else: - args.output = args.input - - def get_arguments(argv=None): # Init argument parser parser = argparse.ArgumentParser() @@ -76,30 +30,6 @@ def get_arguments(argv=None): sp = parser.add_subparsers(title="Available actions", required=False, dest="action") - # # Utility commands - # sp_utility = sp.add_parser( - # "utility", - # description="Usefull functions to be called from Translation App" - # ) - # - # - # - # sp_utility.add_argument( - # "function", - # choices=["hex2bytes", "dumptext"], - # metavar="function_name", - # help="Options: hex2bytes, dumptext", - # ) - # - # sp_utility.add_argument( - # "param1", - # help="First parameter of a function", - # ) - # - # sp_utility.add_argument( - # "param2", - # help="Second parameter of a function", - # ) # Extract commands sp_extract = sp.add_parser( "extract", @@ -123,7 +53,7 @@ def get_arguments(argv=None): required=False, default="../b-topndxj.iso", metavar="iso", - help="(Optional) - Only for extract Iso command" + help="(Optional) - Only for extract Iso command", ) sp_extract.add_argument( @@ -132,18 +62,18 @@ def get_arguments(argv=None): required=False, metavar="replace", default=False, - help="(Optional) - Boolean to uses translations from the Repo to overwrite the one in the Data folder" + help="(Optional) - Boolean to uses translations from the Repo to overwrite the one in the Data folder", ) sp_insert = sp.add_parser( "insert", - help="Take the new texts and recreate the files" + help="Take the new texts and recreate the files", ) sp_insert.add_argument( "-ft", "--file_type", - choices=["Iso", "Main", "Menu", "Story", "Skits", "All", "Asm"], + choices=["Iso", "Main", "Menu", "Story", "Skits", "All", "Asm"], required=True, metavar="file_type", help="(Required) - Options: Iso, Init, Main, Elf, Story, Skits, All, Asm", @@ -162,7 +92,7 @@ def get_arguments(argv=None): "--with-proofreading", required=False, action="store_const", - const="Proofreading", + const="Proofreading", default="", help="(Optional) - Insert lines in 'Proofreading' status", ) @@ -171,7 +101,7 @@ def get_arguments(argv=None): "--with-editing", required=False, action="store_const", - const="Editing", + const="Editing", default="", help="(Optional) - Insert lines in 'Editing' status", ) @@ -180,11 +110,11 @@ def get_arguments(argv=None): "--with-problematic", required=False, action="store_const", - const="Problematic", + const="Problematic", default="", help="(Optional) - Insert lines in 'Problematic' status", ) - + sp_insert.add_argument( "--only-changed", required=False, @@ -192,81 +122,25 @@ def get_arguments(argv=None): help="(Optional) - Insert only changed files not yet commited", ) - # Debug commands - sp_debug = sp.add_parser( - "debug", - description="Used to debug some files", - help="Used to debug some files", - formatter_class=argparse.RawTextHelpFormatter, - ) - - sp_debug.add_argument( - "-ft", - "--file_type", - choices=["Menu", "Story", "Skits"], - metavar="file_type", - help="Options: Menu, Story, Skits", - ) - - sp_debug.add_argument( - "-f", - "--file_name", - required=False, - help="File name to debug" - ) - - sp_debug.add_argument( - "-t", - "--text", - required=False, - help="Boolean to also extract the Japanese text" - ) - - # Export commands - sp_export = sp.add_parser("export", help="Exports, I guess.") - sp_export.add_argument( - "file", choices=["table"], metavar="file type", help="Exports data." - ) - args = parser.parse_args() - #check_arguments(parser, args) return args -def send_xdelta(): - file_link = GoogleAPI.upload_xdelta(xdelta_name, "Stewie") #Need to add user for the folder - - message_text = """ -Hi {}, - -here is your xdelta patch : -{} -""".format('fortiersteven1@gmail.com', file_link) - - message_text = message_text + "
" + RepoFunctions.get_pull_requests_message(org, repo_name) - GoogleAPI.send_message('fortiersteven1@gmail.com', 'fortiersteven1@gmail.com', game_name + " Patch", file_link, message_text) - -def hex2bytes(tales_instance, hex_value): - - bytes_value = bytes.fromhex(hex_value + " 00") - #print(bytes_value) - f = io.BytesIO(bytes_value) - f.seek(0) - txt, offset = tales_instance.bytesToText(f, -1, b'') - txt = "\n\n".join([ele for ele in txt.split("{00}") if ele != ""]) - with open("text_dump.txt", "w",encoding="utf-8") as f: - f.write(txt) - - def getTalesInstance(args, game_name): if game_name == "TOR": if args.action == "insert": - insert_mask = [args.with_proofreading, args.with_editing, args.with_problematic] + insert_mask = [ + args.with_proofreading, + args.with_editing, + args.with_problematic, + ] else: insert_mask = [] - talesInstance = ToolsTOR.ToolsTOR(args.project.resolve(), insert_mask, args.only_changed) + talesInstance = ToolsTOR.ToolsTOR( + args.project.resolve(), insert_mask, args.only_changed + ) elif game_name == "NDX": talesInstance = ToolsNDX.ToolsNDX("TBL_All.json") else: @@ -280,8 +154,6 @@ if __name__ == "__main__": args = get_arguments() game_name = args.game tales_instance = getTalesInstance(args, game_name) - org = repos_infos[game_name]["Org"] - repo_name = repos_infos[game_name]["Repo"] if args.action == "insert": @@ -296,7 +168,7 @@ if __name__ == "__main__": elif args.file_type == "Menu": tales_instance.pack_all_menu() - + elif args.file_type == "Asm": tales_instance.patch_binaries() @@ -307,10 +179,6 @@ if __name__ == "__main__": tales_instance.patch_binaries() tales_instance.make_iso() - # Generate Iso - not yet - # xdelta_name = "../Data/Tales-Of-Rebirth/Disc/New/{}.xdelta".format(args.iso.replace(".iso","")) - # generate_xdelta_patch(repo_name, xdelta_name) - if args.action == "extract": if args.file_type == "Iso": @@ -328,8 +196,3 @@ if __name__ == "__main__": if args.file_type == "Skits": tales_instance.extract_all_skits(args.replace) - - if args.action == "debug": - - if args.file_type in ["Story", "Skits"]: - tales_instance.debug_Story_Skits(args.file_type, args.file_name, args.text) diff --git a/pythonlib/formats/FileIO.py b/pythonlib/formats/FileIO.py index 380c0ac..3eaff52 100644 --- a/pythonlib/formats/FileIO.py +++ b/pythonlib/formats/FileIO.py @@ -1,13 +1,17 @@ -from io import BytesIO +import io import struct +from io import BytesIO +from pathlib import Path +from typing import Union + class FileIO(object): - def __init__(self, path, mode="r+b", endian="little"): - self.mode = mode + def __init__(self, path: Union[Path, str, BytesIO, bytes], mode="r+b", endian="little"): + self.mode: str = mode self._isBitesIO = False if type(path) is bytes: self.path = None - self.f = path + self.f = path # type: ignore self.is_memory_file = True elif type(path) is BytesIO: self.path = None @@ -21,9 +25,9 @@ class FileIO(object): def __enter__(self): if self.is_memory_file: - self.f = self.f if self._isBitesIO else BytesIO(self.f) + self.f: io.BufferedIOBase = self.f if self._isBitesIO else BytesIO(self.f) # type: ignore else: - self.f = open(self.path, self.mode) + self.f:io.BufferedIOBase = open(self.path, self.mode) # type: ignore self.f.seek(0) return self diff --git a/pythonlib/formats/scpk.py b/pythonlib/formats/scpk.py index cbfe675..b8214bc 100644 --- a/pythonlib/formats/scpk.py +++ b/pythonlib/formats/scpk.py @@ -1,5 +1,7 @@ -from dataclasses import dataclass import struct +from dataclasses import dataclass +from pathlib import Path + from ..formats.FileIO import FileIO from ..utils import comptolib @@ -23,7 +25,7 @@ class Scpk(): @staticmethod - def from_path(path="") -> 'Scpk': + def from_path(path: Path) -> 'Scpk': with FileIO(path) as f: if f.read(4) != MAGIC: raise ValueError("Not an SCPK file!") diff --git a/pythonlib/formats/theirsce.py b/pythonlib/formats/theirsce.py index 3e1a0cf..3abc1e4 100644 --- a/pythonlib/formats/theirsce.py +++ b/pythonlib/formats/theirsce.py @@ -1,4 +1,6 @@ -from typing import Generator +from io import BytesIO +from pathlib import Path +from typing import Generator, Union from .FileIO import FileIO from .theirsce_funcs import * @@ -17,7 +19,7 @@ class subsection: class Theirsce(FileIO): - def __init__(self, path=""): + def __init__(self, path: Union[Path, str, BytesIO, bytes] ="") -> None: super().__init__(path, "r+b", "<") super().__enter__() self.magic = self.read(8) @@ -32,7 +34,7 @@ class Theirsce(FileIO): self.frame_offset = self.read_uint16() self.entry_offset = self.read_uint16() - self.sections: list[subsection] = [] + self.sections: list[list[subsection]] = [] # section_stop = self.readUShort(); self.seek(-2, 1) #section_amount = (section_stop - 0x18) // 2 @@ -40,7 +42,7 @@ class Theirsce(FileIO): pos = self.tell() + 2 self.seek(self.read_uint16()) - subsections = [] + subsections: list[subsection] = [] for _ in range(self.read_uint16()): sub = subsection(self.read_uint16(), self.read_uint16(), self.read_uint16() + self.code_offset) subsections.append(sub) @@ -53,7 +55,7 @@ class Theirsce(FileIO): def __exit__(self, exc_type, exc_value, traceback): return super().__exit__(exc_type, exc_value, traceback) - def walk_code(self, start=None, end=None) -> Generator[None, TheirsceBaseInstruction, None]: + def walk_code(self, start=None, end=None) -> Generator[TheirsceBaseInstruction, None, None]: start = self.code_offset if start is None else start end = self.strings_offset if end is None else end @@ -120,7 +122,7 @@ class Theirsce(FileIO): return data - def read_opcode(self): + def read_opcode(self) -> TheirsceBaseInstruction: pos = self.tell() opcode = self.read_uint8() @@ -179,7 +181,7 @@ class Theirsce(FileIO): elif size_mask == 2: value = top << 16 | self.read_uint16() value = value | 0xFF000000 | 0xF80000 if signed else value - elif size_mask == 3: + else: #if size_mask == 3: value = self.read_uint32() # to signed @@ -221,7 +223,7 @@ class Theirsce(FileIO): return TheirsceAcquireInstruction(params=params,variables=variables, position=pos) - elif opcode == 0xF7: + else: # if opcode == 0xF7: param = self.read_uint16() # Type? return TheirsceBreakInstruction(param=param, position=pos) @@ -231,12 +233,12 @@ class Theirsce(FileIO): return TheirsceStringInstruction(offset=value,text="", position=pos) # ? - elif opcode == 0xFE: + else: # if opcode == 0xFE: return TheirsceSpecialReferenceInstruction(position=pos) # Impossible - else: - raise ValueError(f"INVALID OPCODE 0x{opcode:2X}") + # else: + # raise ValueError(f"INVALID OPCODE 0x{opcode:2X}") # if __name__ == "__main__": # with Theirsce("./10233d.theirsce") as f: diff --git a/pythonlib/formats/theirsce_instructions.py b/pythonlib/formats/theirsce_instructions.py index beb3408..3e8e0fd 100644 --- a/pythonlib/formats/theirsce_instructions.py +++ b/pythonlib/formats/theirsce_instructions.py @@ -83,8 +83,8 @@ class AluOperation(Enum): @dataclass class TheirsceBaseInstruction: - mnemonic: str = field(default=False, init=False) - type: InstructionType = field(default=False, init=False) + mnemonic: str = field(default=False, init=False) # type: ignore + type: InstructionType = field(default=False, init=False) # type: ignore #size: int diff --git a/pythonlib/games/ToolsTOR.py b/pythonlib/games/ToolsTOR.py index fb0ed40..1ac45bb 100644 --- a/pythonlib/games/ToolsTOR.py +++ b/pythonlib/games/ToolsTOR.py @@ -1,30 +1,31 @@ -import io -import pyjson5 as json +import datetime import re import shutil import struct +import subprocess +from collections.abc import Iterable from dataclasses import dataclass from itertools import tee from pathlib import Path -import datetime -from collections.abc import Iterable import lxml.etree as etree -import pandas as pd import pycdlib +import pyjson5 as json +from git import Repo from tqdm import tqdm + +import pythonlib.formats.pak2 as pak2lib +import pythonlib.utils.comptolib as comptolib from pythonlib.formats.FileIO import FileIO from pythonlib.formats.pak import Pak from pythonlib.formats.scpk import Scpk - -import pythonlib.utils.comptolib as comptolib -import pythonlib.formats.pak2 as pak2lib from pythonlib.formats.theirsce import Theirsce -from pythonlib.formats.theirsce_instructions import (AluOperation, InstructionType, +from pythonlib.formats.theirsce_instructions import (AluOperation, + InstructionType, TheirsceBaseInstruction) + from .ToolsTales import ToolsTales -import subprocess -from git import Repo + @dataclass class LineEntry: