Formatting changes

plus cleaning of tales_exe.py, functionality can be restored if needed when NDX and DC are implemented
This commit is contained in:
Mc-muffin
2023-09-06 03:32:21 -05:00
parent f4f75b85ea
commit ab2987045d
6 changed files with 58 additions and 186 deletions

View File

@@ -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 + "<br>" + 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)

View File

@@ -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

View File

@@ -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!")

View File

@@ -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:

View File

@@ -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

View File

@@ -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: