You've already forked PythonLib
mirror of
https://github.com/lifebottle/PythonLib.git
synced 2026-02-13 15:25:50 -08:00
Rework tag acquisition and text conversion
This commit is contained in:
159
ToolsTOR.py
159
ToolsTOR.py
@@ -59,19 +59,13 @@ class ToolsTOR(ToolsTales):
|
||||
super().__init__("TOR", tbl, "Tales-Of-Rebirth")
|
||||
|
||||
with open("../{}/Data/{}/Misc/{}".format(self.repo_name, self.gameName, self.tblFile), encoding="utf-8") as f:
|
||||
|
||||
jsonRaw = json.load(f)
|
||||
self.jsonTblTags ={ k1:{ int(k2,16) if (k1 != "TBL") else k2:v2 for k2,v2 in jsonRaw[k1].items()} for k1,v1 in jsonRaw.items()}
|
||||
|
||||
|
||||
|
||||
self.itable = dict([[i, struct.pack(">H", int(j))] for j, i in self.jsonTblTags['TBL'].items()])
|
||||
self.itags = dict([[i, j] for j, i in self.jsonTblTags['TAGS'].items()])
|
||||
if "NAME" in self.jsonTblTags.keys():
|
||||
self.inames = dict([[i, j] for j, i in self.jsonTblTags['NAME'].items()])
|
||||
jsonRaw = json.load(f)
|
||||
|
||||
for k, v in jsonRaw.items():
|
||||
self.jsonTblTags[k] = {int(k2, 16): v2 for k2, v2 in v.items()}
|
||||
|
||||
if "COLOR" in self.jsonTblTags.keys():
|
||||
self.icolors = dict([[i, j] for j, i in self.jsonTblTags['COLOR'].items()])
|
||||
for k, v in self.jsonTblTags.items():
|
||||
self.ijsonTblTags[k] = {v2: k2 for k2, v2 in v.items()}
|
||||
self.id = 1
|
||||
|
||||
#byteCode
|
||||
@@ -479,100 +473,73 @@ class ToolsTOR(ToolsTales):
|
||||
|
||||
#Convert a bytes object to text using TAGS and TBL in the json file
|
||||
def bytes_to_text(self, theirsce: Theirsce, offset=-1, end_strings = b"\x00"):
|
||||
|
||||
finalText = ''
|
||||
TAGS = self.jsonTblTags['TAGS']
|
||||
|
||||
finalText = ""
|
||||
tags = self.jsonTblTags['TAGS']
|
||||
chars = self.jsonTblTags['TBL']
|
||||
|
||||
if (offset > 0):
|
||||
theirsce.seek(offset, 0)
|
||||
|
||||
pos = theirsce.tell()
|
||||
b = theirsce.read(1)
|
||||
while b != end_strings:
|
||||
#print(hex(fileRead.tell()))
|
||||
b = ord(b)
|
||||
|
||||
if (b >= 0x99 and b <= 0x9F) or (b >= 0xE0 and b <= 0xEB):
|
||||
c = (b << 8) + ord(theirsce.read(1))
|
||||
|
||||
# if str(c) not in json_data.keys():
|
||||
# json_data[str(c)] = char_index[decode(c)]
|
||||
try:
|
||||
finalText += (self.jsonTblTags['TBL'][str(c)])
|
||||
except KeyError:
|
||||
b_u = (c >> 8) & 0xff
|
||||
b_l = c & 0xff
|
||||
finalText += ("{%02X}" % b_u)
|
||||
finalText += ("{%02X}" % b_l)
|
||||
elif b == 0x1:
|
||||
finalText += ("\n")
|
||||
elif b in (0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xB, 0xC, 0xD, 0xE, 0xF):
|
||||
b2 = struct.unpack("<L", theirsce.read(4))[0]
|
||||
if b in TAGS:
|
||||
tag_name = TAGS.get(b)
|
||||
|
||||
tag_param = None
|
||||
tag_search = tag_name.upper()
|
||||
if (tag_search in self.jsonTblTags.keys()):
|
||||
tags2 = self.jsonTblTags[tag_search]
|
||||
tag_param = tags2.get(b2, None)
|
||||
if tag_param != None:
|
||||
finalText += tag_param
|
||||
else:
|
||||
#Pad the tag to be even number of characters
|
||||
hex_value = self.hex2(b2)
|
||||
if len(hex_value) < 4 and tag_name not in ['icon','speed']:
|
||||
hex_value = "0"*(4-len(hex_value)) + hex_value
|
||||
|
||||
finalText += '<{}:{}>'.format(tag_name, hex_value)
|
||||
#finalText += ("<%s:%08X>" % (tag_name, b2))
|
||||
else:
|
||||
finalText += "<%02X:%08X>" % (b, b2)
|
||||
elif chr(b) in self.PRINTABLE_CHARS:
|
||||
finalText += chr(b)
|
||||
elif b >= 0xA1 and b < 0xE0:
|
||||
finalText += struct.pack("B", b).decode("cp932")
|
||||
elif b in (0x13, 0x17, 0x1A):
|
||||
tag_name = f"Unk{b:02X}"
|
||||
hex_value = ""
|
||||
|
||||
while theirsce.read(1) != b"\x80":
|
||||
theirsce.seek(theirsce.tell()-1)
|
||||
mark = theirsce.read(1)
|
||||
hex_value += mark.hex()
|
||||
if mark == "\x38":
|
||||
hex_value += f"{struct.unpack('<H', theirsce.read(2))[0]:04X}"
|
||||
|
||||
finalText += '<{}:{}>'.format(tag_name, hex_value)
|
||||
|
||||
elif b in (0x18, 0x19):
|
||||
tag_name = f"Unk{b:02X}"
|
||||
hex_value = ""
|
||||
|
||||
while theirsce.read(1) != b"\x80":
|
||||
theirsce.seek(theirsce.tell()-1)
|
||||
hex_value += theirsce.read(1).hex()
|
||||
|
||||
finalText += '<{}:{}>'.format(tag_name, hex_value)
|
||||
|
||||
elif b == 0x81:
|
||||
b = theirsce.read(1)
|
||||
while True:
|
||||
b = theirsce.read(1)
|
||||
if b == end_strings: break
|
||||
|
||||
b = ord(b)
|
||||
# Custom Encoded Text
|
||||
if (0x99 <= b <= 0x9F) or (0xE0 <= b <= 0xEB):
|
||||
c = (b << 8) | theirsce.read_uint8()
|
||||
finalText += chars.get(c, "{%02X}{%02X}" % (c >> 8, c & 0xFF))
|
||||
continue
|
||||
|
||||
if b == 0x1:
|
||||
finalText += ("\n")
|
||||
continue
|
||||
|
||||
# ASCII text
|
||||
if chr(b) in self.PRINTABLE_CHARS:
|
||||
finalText += chr(b)
|
||||
continue
|
||||
|
||||
# cp932 text
|
||||
if 0xA0 < b < 0xE0:
|
||||
finalText += struct.pack("B", b).decode("cp932")
|
||||
continue
|
||||
|
||||
if b == 0x81:
|
||||
next_b = theirsce.read(1)
|
||||
if next_b == b"\x40":
|
||||
finalText += " "
|
||||
else:
|
||||
finalText += "{%02X}" % b
|
||||
finalText += "{%02X}" % ord(next_b)
|
||||
else:
|
||||
finalText += "{%02X}" % b
|
||||
b = theirsce.read(1)
|
||||
continue
|
||||
|
||||
# Simple Tags
|
||||
if 0x3 <= b <= 0xF:
|
||||
parameter = theirsce.read_uint32()
|
||||
|
||||
tag_name = tags.get(b, f"{b:02X}")
|
||||
tag_param = self.jsonTblTags.get(tag_name.upper(), {}).get(parameter, None)
|
||||
|
||||
if tag_param is not None:
|
||||
finalText += tag_param
|
||||
else:
|
||||
finalText += f"<{tag_name}:{self.hex2(parameter)}>"
|
||||
|
||||
continue
|
||||
|
||||
# Variable tags (same as above but using rsce bytecode as parameter)
|
||||
if 0x13 <= b <= 0x1A:
|
||||
tag_name = f"unk{b:02X}"
|
||||
parameter = "".join([f"{c:02X}" for c in theirsce.read_tag_bytes()])
|
||||
|
||||
finalText += f"<{tag_name}:{parameter}>"
|
||||
continue
|
||||
|
||||
# None of the above
|
||||
finalText += "{%02X}" % b
|
||||
|
||||
end = theirsce.tell()
|
||||
size = theirsce.tell() - pos - 1
|
||||
theirsce.seek(pos)
|
||||
hex_string = theirsce.read(size).hex()
|
||||
hex_values = ' '.join(a+b for a,b in zip(hex_string[::2], hex_string[1::2]))
|
||||
theirsce.seek(end)
|
||||
#return finalText, hex_values
|
||||
return finalText
|
||||
|
||||
def get_Node_Bytes(self, entry_node):
|
||||
|
||||
105
ToolsTales.py
105
ToolsTales.py
@@ -31,7 +31,8 @@ class ToolsTales:
|
||||
VALID_VOICEID = ['VSM_', 'voice_', 'VCT_']
|
||||
|
||||
def __init__(self, gameName, tblFile, repo_name):
|
||||
|
||||
self.jsonTblTags = {}
|
||||
self.ijsonTblTags = {}
|
||||
self.gameName = gameName
|
||||
self.repo_name = repo_name
|
||||
self.basePath = os.getcwd()
|
||||
@@ -493,67 +494,55 @@ class ToolsTales:
|
||||
|
||||
#Convert text to Bytes object to reinsert text into THEIRSCE and other files
|
||||
def text_to_bytes(self, text):
|
||||
multi_regex = (self.HEX_TAG + "|" + self.COMMON_TAG + r"|(\n)")
|
||||
tokens = [sh for sh in re.split(multi_regex, text) if sh]
|
||||
|
||||
|
||||
|
||||
unames = []
|
||||
|
||||
splitLineBreak = text.split('\x0A')
|
||||
nb = len(splitLineBreak)
|
||||
|
||||
bytesFinal = b''
|
||||
i=0
|
||||
for line in splitLineBreak:
|
||||
string_hex = re.split(self.HEX_TAG, line)
|
||||
string_hex = [sh for sh in string_hex if sh]
|
||||
#print(string_hex)
|
||||
for s in string_hex:
|
||||
if re.match(self.HEX_TAG, s):
|
||||
bytesFinal += struct.pack("B", int(s[1:3], 16))
|
||||
output = b''
|
||||
for t in tokens:
|
||||
# Hex literals
|
||||
if re.match(self.HEX_TAG, t):
|
||||
output += struct.pack("B", int(t[1:3], 16))
|
||||
|
||||
# Tags
|
||||
elif re.match(self.COMMON_TAG, t):
|
||||
tag, param, *_ = t[3][1:-1].split(":") + [None]
|
||||
|
||||
if param is not None:
|
||||
output += struct.pack("B", self.ijsonTblTags["TAGS"].get(tag, int(tag, 16)))
|
||||
# FIXME
|
||||
if tag.lower() in ("unk13", "unk17", "unk1a"):
|
||||
splat = re.findall("..", param)
|
||||
i = 0
|
||||
while i < len(splat):
|
||||
if splat[i] == "38" and i + 2 < len(splat):
|
||||
output += bytes.fromhex(splat[i])
|
||||
output += bytes.fromhex(splat[i + 2])
|
||||
output += bytes.fromhex(splat[i + 1])
|
||||
i += 3
|
||||
else:
|
||||
output += bytes.fromhex(splat[i])
|
||||
i += 1
|
||||
|
||||
output += bytes.fromhex("80")
|
||||
elif "unk" in tag.lower:
|
||||
output += bytes.fromhex(param + "80")
|
||||
else:
|
||||
output += struct.pack("<I", param)
|
||||
else:
|
||||
s_com = re.split(self.COMMON_TAG, s)
|
||||
s_com = [sc for sc in s_com if sc]
|
||||
for c in s_com:
|
||||
|
||||
if re.match(self.COMMON_TAG, c):
|
||||
if ":" in c:
|
||||
split = c.split(":")
|
||||
tag = split[0][1:]
|
||||
print(split)
|
||||
if tag in self.itags.keys():
|
||||
bytesFinal += struct.pack("B", self.itags[tag])
|
||||
for k, v in self.ijsonTblTags:
|
||||
if tag in v:
|
||||
output += struct.pack("B", self.ijsonTblTags["TAGS"][k.lower()])
|
||||
output += struct.pack("<I", v[tag])
|
||||
break
|
||||
|
||||
if tag in ['Unk13', 'Unk17', 'Unk18', 'Unk19', 'Unk1A']:
|
||||
right_part = split[1][0:-1]
|
||||
nb = len(right_part) / 2.0
|
||||
bytesFinal += int(right_part, 16).to_bytes(int(nb), 'big')
|
||||
else:
|
||||
bytesFinal += int(split[1][0:-1], 16).to_bytes(4, 'little')
|
||||
# Actual text
|
||||
elif t == "\n":
|
||||
output += b"\x01"
|
||||
else:
|
||||
for c in t:
|
||||
output += self.ijsonTblTags["TBL"].get(c, c.encode("cp932"))
|
||||
|
||||
else:
|
||||
bytesFinal += struct.pack("B", int(split[0][1:], 16))
|
||||
bytesFinal += struct.pack("<I", int(split[1][:8], 16))
|
||||
if c in self.inames:
|
||||
bytesFinal += struct.pack("B", 0xB)
|
||||
bytesFinal += struct.pack("<I", self.inames[c])
|
||||
if c in self.icolors:
|
||||
bytesFinal += struct.pack("B", 0x5)
|
||||
bytesFinal += struct.pack("<I", self.icolors[c])
|
||||
|
||||
|
||||
else:
|
||||
for c2 in c:
|
||||
if c2 in self.itable.keys():
|
||||
bytesFinal += self.itable[c2]
|
||||
else:
|
||||
|
||||
bytesFinal += c2.encode("cp932")
|
||||
|
||||
i=i+1
|
||||
if (nb >=2 and i<nb):
|
||||
bytesFinal += b'\x01'
|
||||
|
||||
return bytesFinal
|
||||
return output
|
||||
|
||||
def search_all_files(self, japanese_text):
|
||||
|
||||
|
||||
42
theirsce.py
42
theirsce.py
@@ -67,6 +67,48 @@ class Theirsce(FileIO):
|
||||
yield opcode
|
||||
self.seek(pos)
|
||||
|
||||
def read_tag_bytes(self):
|
||||
data = b""
|
||||
|
||||
while self.read_uint8_at(self.tell() + 1) != 0x80:
|
||||
data += self.read(1)
|
||||
opcode = data[-1]
|
||||
|
||||
if opcode < 0x80:
|
||||
if opcode & 8 != 0:
|
||||
data += self.read(2)
|
||||
else:
|
||||
data += self.read(1)
|
||||
|
||||
elif opcode < 0xE0:
|
||||
size_mask = (opcode >> 3) & 3
|
||||
|
||||
if size_mask == 1: data += self.read(1)
|
||||
elif size_mask == 2: data += self.read(2)
|
||||
elif size_mask == 3: data += self.read(4)
|
||||
|
||||
elif opcode < 0xF0:
|
||||
data += self.read(1)
|
||||
|
||||
elif opcode < 0xF8:
|
||||
if (0xF2 <= opcode < 0xF5) or opcode == 0xF7:
|
||||
data += self.read(2)
|
||||
elif opcode == 0xF5:
|
||||
data += self.read(4)
|
||||
elif opcode == 0xF6:
|
||||
data += self.read(1)
|
||||
for _ in range(data[-1]):
|
||||
if ord(data[-1]) & 8 != 0:
|
||||
data += self.read(2)
|
||||
else:
|
||||
data += self.read(3)
|
||||
|
||||
elif opcode < 0xFC:
|
||||
data += self.read(2)
|
||||
|
||||
self.read(1)
|
||||
return data
|
||||
|
||||
def read_opcode(self):
|
||||
pos = self.tell()
|
||||
opcode = self.read_uint8()
|
||||
|
||||
Reference in New Issue
Block a user