You've already forked PythonLib
mirror of
https://github.com/lifebottle/PythonLib.git
synced 2026-02-13 15:25:50 -08:00
Theirsce specific text extraction, part 1
This commit is contained in:
263
FileIO.py
Normal file
263
FileIO.py
Normal file
@@ -0,0 +1,263 @@
|
||||
from io import BytesIO
|
||||
import struct
|
||||
|
||||
class FileIO(object):
|
||||
def __init__(self, path="", mode="r+b", endian="little"):
|
||||
self.f = path
|
||||
self.mode = mode
|
||||
if type(path) is bytes:
|
||||
self.path = None
|
||||
self.is_memory_file = True
|
||||
else:
|
||||
self.path = path
|
||||
self.is_memory_file = False
|
||||
self.endian = "<" if endian == "little" or endian == "<" else ">"
|
||||
|
||||
def __enter__(self):
|
||||
if self.is_memory_file:
|
||||
self.f = BytesIO(self.f)
|
||||
else:
|
||||
self.f = open(self.path, self.mode)
|
||||
self.f.seek(0)
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
self.f.close()
|
||||
|
||||
def close(self):
|
||||
self.f.close()
|
||||
|
||||
def tell(self):
|
||||
return self.f.tell()
|
||||
|
||||
def seek(self, pos, whence=0):
|
||||
self.f.seek(pos, whence)
|
||||
|
||||
def read(self, n=-1):
|
||||
return self.f.read(n)
|
||||
|
||||
def read_at(self, pos, n=-1):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
ret = self.read(n)
|
||||
self.seek(current)
|
||||
return ret
|
||||
|
||||
def write(self, data):
|
||||
self.f.write(data)
|
||||
|
||||
def write_at(self, pos, data):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
self.write(data)
|
||||
self.seek(current)
|
||||
|
||||
def peek(self, n):
|
||||
pos = self.tell()
|
||||
ret = self.read(n)
|
||||
self.seek(pos)
|
||||
return ret
|
||||
|
||||
def write_line(self, data):
|
||||
self.f.write(data + "\n")
|
||||
|
||||
def set_endian(self, endian):
|
||||
self.endian = "<" if endian == "little" or endian == "<" else ">"
|
||||
|
||||
def read_int8(self):
|
||||
return struct.unpack("b", self.read(1))[0]
|
||||
|
||||
def read_int8_at(self, pos):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
ret = self.read_int8()
|
||||
self.seek(current)
|
||||
return ret
|
||||
|
||||
def read_uint8(self):
|
||||
return struct.unpack("B", self.read(1))[0]
|
||||
|
||||
def read_uint8_at(self, pos):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
ret = self.read_uint8()
|
||||
self.seek(current)
|
||||
return ret
|
||||
|
||||
def read_int16(self):
|
||||
return struct.unpack(self.endian + "h", self.read(2))[0]
|
||||
|
||||
def read_int16_at(self, pos):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
ret = self.read_int16()
|
||||
self.seek(current)
|
||||
return ret
|
||||
|
||||
def read_uint16(self):
|
||||
return struct.unpack(self.endian + "H", self.read(2))[0]
|
||||
|
||||
def read_uint16_at(self, pos):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
ret = self.read_uint16()
|
||||
self.seek(current)
|
||||
return ret
|
||||
|
||||
def read_int32(self):
|
||||
return struct.unpack(self.endian + "i", self.read(4))[0]
|
||||
|
||||
def read_int32_at(self, pos):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
ret = self.read_int32()
|
||||
self.seek(current)
|
||||
return ret
|
||||
|
||||
def read_uint32(self):
|
||||
return struct.unpack(self.endian + "I", self.read(4))[0]
|
||||
|
||||
def read_uint32_at(self, pos):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
ret = self.read_uint32()
|
||||
self.seek(current)
|
||||
return ret
|
||||
|
||||
def read_int64(self):
|
||||
return struct.unpack(self.endian + "q", self.read(8))[0]
|
||||
|
||||
def read_int64_at(self, pos):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
ret = self.read_int64()
|
||||
self.seek(current)
|
||||
return ret
|
||||
|
||||
def read_uint64(self):
|
||||
return struct.unpack(self.endian + "Q", self.read(8))[0]
|
||||
|
||||
def read_uint64_at(self, pos):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
ret = self.read_uint64()
|
||||
self.seek(current)
|
||||
return ret
|
||||
|
||||
def read_single(self):
|
||||
return struct.unpack(self.endian + "f", self.read(4))[0]
|
||||
|
||||
def read_single_at(self, pos):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
ret = self.read_single()
|
||||
self.seek(current)
|
||||
return ret
|
||||
|
||||
def read_double(self):
|
||||
return struct.unpack(self.endian + "d", self.read(8))[0]
|
||||
|
||||
def read_double_at(self, pos):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
ret = self.read_double()
|
||||
self.seek(current)
|
||||
return ret
|
||||
|
||||
def skip_padding(self, alignment):
|
||||
while self.tell() % alignment != 0:
|
||||
self.read_uint8()
|
||||
|
||||
def write_int8(self, num):
|
||||
self.f.write(struct.pack("b", num))
|
||||
|
||||
def write_int8_at(self, pos, num):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
self.write_int8(num)
|
||||
self.seek(current)
|
||||
|
||||
def write_uint8(self, num):
|
||||
self.f.write(struct.pack("B", num))
|
||||
|
||||
def write_uint8_at(self, pos, num):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
self.write_uint8(num)
|
||||
self.seek(current)
|
||||
|
||||
def write_int16(self, num):
|
||||
self.f.write(struct.pack(self.endian + "h", num))
|
||||
|
||||
def write_int16_at(self, pos, num):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
self.write_int16(num)
|
||||
self.seek(current)
|
||||
|
||||
def write_uint16(self, num):
|
||||
self.f.write(struct.pack(self.endian + "H", num))
|
||||
|
||||
def write_uint16_at(self, pos, num):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
self.write_uint16(num)
|
||||
self.seek(current)
|
||||
|
||||
def write_int32(self, num):
|
||||
self.f.write(struct.pack(self.endian + "i", num))
|
||||
|
||||
def write_int32_at(self, pos, num):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
self.write_int32(num)
|
||||
self.seek(current)
|
||||
|
||||
def write_uint32(self, num):
|
||||
self.f.write(struct.pack(self.endian + "I", num))
|
||||
|
||||
def write_uint32_at(self, pos, num):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
self.write_uint32(num)
|
||||
self.seek(current)
|
||||
|
||||
def write_int64(self, num):
|
||||
self.f.write(struct.pack(self.endian + "q", num))
|
||||
|
||||
def write_int64_at(self, pos, num):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
self.write_int64(num)
|
||||
self.seek(current)
|
||||
|
||||
def write_uint64(self, num):
|
||||
self.f.write(struct.pack(self.endian + "Q", num))
|
||||
|
||||
def write_uint64_at(self, pos, num):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
self.write_uint64(num)
|
||||
self.seek(current)
|
||||
|
||||
def write_single(self, num):
|
||||
self.f.write(struct.pack(self.endian + "f", num))
|
||||
|
||||
def write_single_at(self, pos, num):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
self.write_single(num)
|
||||
self.seek(current)
|
||||
|
||||
def write_double(self, num):
|
||||
self.f.write(struct.pack(self.endian + "d", num))
|
||||
|
||||
def write_double_at(self, pos, num):
|
||||
current = self.tell()
|
||||
self.seek(pos)
|
||||
self.write_double(num)
|
||||
self.seek(current)
|
||||
|
||||
def write_padding(self, alignment, pad_byte=0x00):
|
||||
while self.tell() % alignment != 0:
|
||||
self.write_uint8(pad_byte)
|
||||
34
ToolsTOR.py
34
ToolsTOR.py
@@ -15,6 +15,8 @@ from pathlib import Path
|
||||
import string
|
||||
import io
|
||||
import pak2 as pak2lib
|
||||
from theirsce import Theirsce
|
||||
from theirsce_instructions import InstructionType, TheirsceStringInstruction
|
||||
|
||||
class ToolsTOR(ToolsTales):
|
||||
|
||||
@@ -56,6 +58,7 @@ class ToolsTOR(ToolsTales):
|
||||
|
||||
#byteCode
|
||||
self.story_byte_code = b"\xF8"
|
||||
self.string_opcode = InstructionType.STRING
|
||||
self.list_status_insertion = ['Done', 'Proofreading']
|
||||
|
||||
self.mkdir('../Data/{}/DAT'.format(self.repo_name))
|
||||
@@ -240,23 +243,10 @@ class ToolsTOR(ToolsTales):
|
||||
#Create the XML file
|
||||
root = etree.Element('SceneText')
|
||||
etree.SubElement(root, "OriginalName").text = file_name
|
||||
stringsNode = etree.SubElement(root, "Strings")
|
||||
theirsce.seek(0)
|
||||
#Validate the header
|
||||
header = theirsce.read(8)
|
||||
if header != b"THEIRSCE":
|
||||
raise ValueError("No THEIRSCE header")
|
||||
|
||||
#Start of the pointer
|
||||
pointer_block = struct.unpack("<L", theirsce.read(4))[0]
|
||||
|
||||
#Start of the text and baseOffset
|
||||
strings_offset = struct.unpack("<L", theirsce.read(4))[0]
|
||||
|
||||
#File size
|
||||
fsize = theirsce.getbuffer().nbytes
|
||||
theirsce.seek(pointer_block, 0) #Go the the start of the pointer section
|
||||
pointers_offset, texts_offset = self.extract_Story_Pointers(theirsce, strings_offset, fsize, self.story_byte_code)
|
||||
stringsNode = etree.SubElement(root, "Strings")
|
||||
|
||||
rsce = Theirsce(path=theirsce)
|
||||
pointers_offset, texts_offset = self.extract_Story_Pointers(rsce)
|
||||
|
||||
text_list = [self.bytes_to_text(theirsce, ele)[0] for ele in texts_offset]
|
||||
|
||||
@@ -281,6 +271,16 @@ class ToolsTOR(ToolsTales):
|
||||
'../Data/{}/{}/XML/{}.xml'.format(self.repo_name, section, self.get_file_name(file_name))
|
||||
)
|
||||
|
||||
def extract_Story_Pointers(self, theirsce: Theirsce):
|
||||
pointers_offset = []; texts_offset = []
|
||||
|
||||
for opcode in theirsce.walk_code():
|
||||
if opcode == self.string_opcode:
|
||||
pointers_offset.append(theirsce.tell() - 2) # Maybe check this later
|
||||
texts_offset.append(opcode.offset + theirsce.strings_offset)
|
||||
|
||||
return pointers_offset, texts_offset
|
||||
|
||||
#Convert a bytes object to text using TAGS and TBL in the json file
|
||||
def bytes_to_text(self, fileRead, offset=-1, end_strings = b"\x00"):
|
||||
|
||||
|
||||
189
theirsce.py
Normal file
189
theirsce.py
Normal file
@@ -0,0 +1,189 @@
|
||||
from typing import Generator
|
||||
from FileIO import FileIO
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from theirsce_instructions import *
|
||||
from theirsce_funcs import *
|
||||
|
||||
# I followed other project when making this class
|
||||
# not sure how if it's the best approach
|
||||
|
||||
SECTION_AMOUNT = 6
|
||||
|
||||
@dataclass
|
||||
class subsection:
|
||||
unk1: int
|
||||
unk2: int
|
||||
off: int
|
||||
|
||||
|
||||
class Theirsce(FileIO):
|
||||
def __init__(self, path=""):
|
||||
super().__init__(path, "r+b", "<")
|
||||
super().__enter__()
|
||||
self.magic = self.read(8)
|
||||
|
||||
if self.magic != b"THEIRSCE":
|
||||
raise ValueError("Not a THEIRSCE file!")
|
||||
|
||||
self.code_offset = self.read_uint32()
|
||||
self.strings_offset = self.read_uint32()
|
||||
self.unk_field = self.read_uint32()
|
||||
|
||||
self.frame_offset = self.read_uint16()
|
||||
self.entry_offset = self.read_uint16()
|
||||
|
||||
self.sections: list[subsection] = []
|
||||
# section_stop = self.readUShort(); self.seek(-2, 1)
|
||||
#section_amount = (section_stop - 0x18) // 2
|
||||
|
||||
for _ in range(SECTION_AMOUNT):
|
||||
pos = self.tell() + 2
|
||||
self.seek(self.read_uint16())
|
||||
|
||||
subsections = []
|
||||
for _ in range(self.read_uint16()):
|
||||
sub = subsection(self.read_uint16(), self.read_uint16(), self.read_uint16() + self.code_offset)
|
||||
subsections.append(sub)
|
||||
self.sections.append(subsections)
|
||||
self.seek(pos)
|
||||
|
||||
def __enter__(self):
|
||||
return super().__enter__()
|
||||
|
||||
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]:
|
||||
start = self.code_offset if start is None else start
|
||||
end = self.strings_offset if end is None else end
|
||||
|
||||
self.seek(start)
|
||||
|
||||
while self.tell() < end:
|
||||
pos = self.tell()
|
||||
yield self.read_opcode()
|
||||
self.seek(pos)
|
||||
|
||||
def read_opcode(self):
|
||||
opcode = self.read_uint8()
|
||||
|
||||
# Reference Block
|
||||
if opcode < 0x80:
|
||||
var_type = (opcode >> 4) & 7
|
||||
shift = 0
|
||||
|
||||
#id = mask
|
||||
if var_type == 0: # bitfields
|
||||
value = self.read_uint8()
|
||||
if opcode & 8 == 0:
|
||||
next_byte = opcode & 3
|
||||
pass
|
||||
else:
|
||||
next_byte = self.read_uint8()
|
||||
pass
|
||||
shift = (value & 7) #<< 3
|
||||
value = ((( value | (next_byte << 8)) >> 3) & 0xFF)
|
||||
else:
|
||||
value = self.read_uint8()
|
||||
top = 1
|
||||
if opcode & 8 != 0:
|
||||
top = 2
|
||||
next_byte = self.read_uint8()
|
||||
value = ( ((next_byte & 0xFF) << 8) | (value & 0xFF))
|
||||
value = ((opcode & 3) << (8 * top)) | value
|
||||
|
||||
# scope
|
||||
if opcode & 4 == 0:
|
||||
if value < 0x400:
|
||||
scope = ReferenceScope.GLOBAL
|
||||
else:
|
||||
scope = ReferenceScope.FILE
|
||||
value -= 0x400
|
||||
else:
|
||||
scope = ReferenceScope.LOCAL
|
||||
|
||||
return TheirsceReferenceInstruction(ref_type=VariableType(var_type), scope=scope, offset=value, shift=shift)
|
||||
|
||||
# ALU operations
|
||||
elif opcode < 0xC0:
|
||||
return TheirsceAluInstruction(operation = AluOperation(opcode & 0x3F))
|
||||
|
||||
# PUSH block, the amount of bytes depend on encoding
|
||||
elif opcode < 0xE0:
|
||||
size_mask = (opcode >> 3) & 3
|
||||
signed = opcode & 4 != 0
|
||||
top = opcode & 7
|
||||
|
||||
if size_mask == 0:
|
||||
value = 0xFFFFFF00 | (top | 0xF8) if signed else top
|
||||
if size_mask == 1:
|
||||
value = top << 8 | self.read_uint8()
|
||||
value = value | 0xFFFF0000 | 0xF800 if signed else value
|
||||
elif size_mask == 2:
|
||||
value = top << 16 | self.read_uint16()
|
||||
value = value | 0xFF000000 | 0xF80000 if signed else value
|
||||
elif size_mask == 3:
|
||||
value = self.read_uint32()
|
||||
|
||||
# to signed
|
||||
value = value | (-(value & 0x80000000))
|
||||
|
||||
return TheirscePushInstruction(value=value)
|
||||
|
||||
# CALL block, available commands are at 0x1e5300
|
||||
# first entry is number of parameters then function
|
||||
elif opcode < 0xF0:
|
||||
index = ((opcode & 0xF) << 8) | self.read_uint8()
|
||||
return TheirsceSyscallInstruction(function_index=index, function_name=SYSCALL_NAMES[index])
|
||||
|
||||
# Flow related block
|
||||
elif opcode < 0xF8:
|
||||
if opcode == 0xF0:
|
||||
return TheirsceReturnInstruction(is_void=True)
|
||||
elif opcode == 0xF1:
|
||||
return TheirsceReturnInstruction(is_void=False)
|
||||
|
||||
# Need to be offsetted to start of code
|
||||
elif opcode >= 0xF2 and opcode < 0xF5:
|
||||
target = self.code_offset + self.read_uint16()
|
||||
return TheirsceBranchInstruction(branch_type=BranchType(opcode - 0xF2), destination=target)
|
||||
elif opcode == 0xF5:
|
||||
target = self.code_offset + self.read_uint16()
|
||||
reserve = self.read_uint16()
|
||||
return TheirsceLocalCallInstruction(destination=target, reserve=reserve)
|
||||
|
||||
# ?
|
||||
elif opcode == 0xF6:
|
||||
variables = self.read_uint8()
|
||||
params = []
|
||||
for _ in range(variables):
|
||||
if self.read_uint8() & 8 != 0:
|
||||
params.append(self.read_uint16())
|
||||
else:
|
||||
params.append(self.read_uint8())
|
||||
|
||||
return TheirsceAcquireInstruction(params=params,variables=variables)
|
||||
|
||||
elif opcode == 0xF7:
|
||||
param = self.read_uint16() # Type?
|
||||
return TheirsceBreakInstruction(param=param)
|
||||
|
||||
# Get string
|
||||
elif opcode < 0xFC:
|
||||
value = ((opcode & 3) << 16) | self.read_uint16()
|
||||
return TheirsceStringInstruction(offset=value,text="")
|
||||
|
||||
# ?
|
||||
elif opcode == 0xFE:
|
||||
return TheirsceSpecialReferenceInstruction()
|
||||
|
||||
# Impossible
|
||||
else:
|
||||
raise ValueError(f"INVALID OPCODE 0x{opcode:2X}")
|
||||
|
||||
# if __name__ == "__main__":
|
||||
# with Theirsce("./10233d.theirsce") as f:
|
||||
# for op in f.walk_code():
|
||||
# if op.type == InstructionType.ACQUIRE:
|
||||
# print(op)
|
||||
371
theirsce_funcs.py
Normal file
371
theirsce_funcs.py
Normal file
@@ -0,0 +1,371 @@
|
||||
SYSCALL_NAMES = (
|
||||
"printf", # 0x0
|
||||
None, # 0x1
|
||||
None, # 0x2
|
||||
None, # 0x3
|
||||
None, # 0x4
|
||||
"set_person", # 0x5
|
||||
"set_person_3d", # 0x6
|
||||
"set_position", # 0x7
|
||||
"set_position_3d", # 0x8
|
||||
"delete_person", # 0x9
|
||||
"animate_person", # 0xA
|
||||
"set_balloon", # 0xB
|
||||
"get_param", # 0xC
|
||||
"set_param", # 0xD
|
||||
"move_position", # 0xE
|
||||
"move_position_3d", # 0xF
|
||||
"na_move_position", # 0x10
|
||||
"na_move_position_3d", # 0x11
|
||||
"move_check", # 0x12
|
||||
"sky_init", # 0x13
|
||||
"cloud_init", # 0x14
|
||||
"cloud_inc_alpha", # 0x15
|
||||
"cloud_dec_alpha", # 0x16
|
||||
"delete_cloud_dec_alpha", # 0x17
|
||||
"trap_line", # 0x18
|
||||
"trap_box", # 0x19
|
||||
"trap_box_stoptimer", # 0x1A
|
||||
"trap_box_stoptimer_pop", # 0x1B
|
||||
"trap_poly4", # 0x1C
|
||||
"trap_poly4_stoptimer", # 0x1D
|
||||
"trap_poly4_stoptimer_pop", # 0x1E
|
||||
"trap_line_3d", # 0x1F
|
||||
"trap_box_3d", # 0x20
|
||||
"trap_box_stoptimer_3d", # 0x21
|
||||
"trap_box_stoptimer_pop_3d", # 0x22
|
||||
"trap_poly4_3d", # 0x23
|
||||
"trap_poly4_stoptimer_3d", # 0x24
|
||||
"trap_poly4_stoptimer_pop_3d",# 0x25
|
||||
"trap_contact_chr", # 0x26
|
||||
"delete_trap", # 0x27
|
||||
"is_trap", # 0x28
|
||||
"event_line", # 0x29
|
||||
"event_box", # 0x2A
|
||||
"event_poly4", # 0x2B
|
||||
"event_line_3d", # 0x2C
|
||||
"event_box_3d", # 0x2D
|
||||
"event_poly4_3d", # 0x2E
|
||||
"delete_event", # 0x2F
|
||||
"is_event", # 0x30
|
||||
"line_hit", # 0x31
|
||||
"line_hit_ply", # 0x32
|
||||
"line_hit_npc", # 0x33
|
||||
"line_hit_3d", # 0x34
|
||||
"line_hit_ply_3d", # 0x35
|
||||
"line_hit_npc_3d", # 0x36
|
||||
"delete_line_hit", # 0x37
|
||||
"is_line_hit", # 0x38
|
||||
"scope", # 0x39
|
||||
"scope_3d", # 0x3A
|
||||
"delete_scope", # 0x3B
|
||||
"is_scope", # 0x3C
|
||||
"scroll_direct", # 0x3D
|
||||
"scroll", # 0x3E
|
||||
"zoom_scroll", # 0x3F
|
||||
"is_scroll", # 0x40
|
||||
"scroll_four", # 0x41
|
||||
None, # 0x42
|
||||
"fst_load", # 0x43
|
||||
"gradation_palet", # 0x44
|
||||
None, # 0x45
|
||||
None, # 0x46
|
||||
None, # 0x47
|
||||
None, # 0x48
|
||||
None, # 0x49
|
||||
None, # 0x4A
|
||||
None, # 0x4B
|
||||
None, # 0x4C
|
||||
None, # 0x4D
|
||||
None, # 0x4E
|
||||
None, # 0x4F
|
||||
None, # 0x50
|
||||
None, # 0x51
|
||||
None, # 0x52
|
||||
None, # 0x53
|
||||
None, # 0x54
|
||||
None, # 0x55
|
||||
None, # 0x56
|
||||
None, # 0x57
|
||||
None, # 0x58
|
||||
None, # 0x59
|
||||
None, # 0x5A
|
||||
None, # 0x5B
|
||||
None, # 0x5C
|
||||
None, # 0x5D
|
||||
None, # 0x5E
|
||||
None, # 0x5F
|
||||
None, # 0x60
|
||||
None, # 0x61
|
||||
None, # 0x62
|
||||
None, # 0x63
|
||||
None, # 0x64
|
||||
"event_line_inf", # 0x65
|
||||
"event_box_inf", # 0x66
|
||||
"event_poly4_inf", # 0x67
|
||||
"event_line_3d_inf", # 0x68
|
||||
"event_box_3d_inf", # 0x69
|
||||
"event_poly4_3d_inf", # 0x6A
|
||||
None, # 0x6B
|
||||
None, # 0x6C
|
||||
None, # 0x6D
|
||||
None, # 0x6E
|
||||
None, # 0x6F
|
||||
"scroll_cnt", # 0x70
|
||||
"zoom_scroll_cnt", # 0x71
|
||||
"map_bright", # 0x72
|
||||
"change_bg_anime", # 0x73
|
||||
"get_bg_anime_param", # 0x74
|
||||
"scope_msg", # 0x75
|
||||
"scope_msg_3d", # 0x76
|
||||
None, # 0x77
|
||||
None, # 0x78
|
||||
None, # 0x79
|
||||
None, # 0x7A
|
||||
None, # 0x7B
|
||||
None, # 0x7C
|
||||
"is_sideview", # 0x7D
|
||||
"get_map_no", # 0x7E
|
||||
"bg_alpha", # 0x7F
|
||||
None, # 0x80
|
||||
None, # 0x81
|
||||
None, # 0x82
|
||||
None, # 0x83
|
||||
None, # 0x84
|
||||
None, # 0x85
|
||||
None, # 0x86
|
||||
None, # 0x87
|
||||
None, # 0x88
|
||||
None, # 0x89
|
||||
None, # 0x8A
|
||||
None, # 0x8B
|
||||
None, # 0x8C
|
||||
None, # 0x8D
|
||||
None, # 0x8E
|
||||
"get_sys_map_rate", # 0x8F
|
||||
None, # 0x90
|
||||
None, # 0x91
|
||||
None, # 0x92
|
||||
None, # 0x93
|
||||
None, # 0x94
|
||||
None, # 0x95
|
||||
None, # 0x96
|
||||
None, # 0x97
|
||||
None, # 0x98
|
||||
None, # 0x99
|
||||
"get_int_no", # 0x9A
|
||||
None, # 0x9B
|
||||
None, # 0x9C
|
||||
None, # 0x9D
|
||||
"special_person", # 0x9E
|
||||
"special_person_3d", # 0x9F
|
||||
None, # 0xA0
|
||||
None, # 0xA1
|
||||
None, # 0xA2
|
||||
None, # 0xA3
|
||||
"walk_se", # 0xA4
|
||||
"get_mapsize_x", # 0xA5
|
||||
"get_mapsize_y", # 0xA6
|
||||
"set_3d_zoom_rate", # 0xA7
|
||||
None, # 0xA8
|
||||
None, # 0xA9
|
||||
"set_cloud_h", # 0xAA
|
||||
"move_stop", # 0xAB
|
||||
None, # 0xAC
|
||||
"set_child_chr", # 0xAD
|
||||
"del_child_chr", # 0xAE
|
||||
"get_child_pos", # 0xAF
|
||||
"get_parent_chr", # 0xB0
|
||||
"is_bg_atari", # 0xB1
|
||||
None, # 0xB2
|
||||
"set_gradation_chr", # 0xB3
|
||||
"set_rot_chr_color", # 0xB4
|
||||
"scroll_offset", # 0xB5
|
||||
None, # 0xB6
|
||||
None, # 0xB7
|
||||
"set_bg_pal_anime", # 0xB8
|
||||
None, # 0xB9
|
||||
"get_pl_move_spd", # 0xBA
|
||||
"get_pl_move_dir", # 0xBB
|
||||
None, # 0xBC
|
||||
None, # 0xBD
|
||||
None, # 0xBE
|
||||
None, # 0xBF
|
||||
None, # 0xC0
|
||||
None, # 0xC1
|
||||
None, # 0xC2
|
||||
None, # 0xC3
|
||||
None, # 0xC4
|
||||
None, # 0xC5
|
||||
"set_force_mode", # 0xC6
|
||||
"trap_force_line", # 0xC7
|
||||
"trap_force_box", # 0xC8
|
||||
"trap_force_poly4", # 0xC9
|
||||
"trap_force_line_3d", # 0xCA
|
||||
"trap_force_box_3d", # 0xCB
|
||||
"trap_force_poly4_3d", # 0xCC
|
||||
"trap_force_rain_point", # 0xCD
|
||||
"trap_force_chr", # 0xCE
|
||||
"line_hit_force", # 0xCF
|
||||
"line_hit_force_3d", # 0xD0
|
||||
"get_force_pow", # 0xD1
|
||||
"get_force_lever", # 0xD2
|
||||
"set_csp_param", # 0xD3
|
||||
"get_csp_param", # 0xD4
|
||||
"calc_csp_param", # 0xD5
|
||||
None, # 0xD6
|
||||
None, # 0xD7
|
||||
None, # 0xD8
|
||||
None, # 0xD9
|
||||
"set_move_pass", # 0xDA
|
||||
"move_pass", # 0xDB
|
||||
None, # 0xDC
|
||||
"scroll_limit", # 0xDD
|
||||
None, # 0xDE
|
||||
None, # 0xDF
|
||||
None, # 0xE0
|
||||
None, # 0xE1
|
||||
"demo_stop_move_pass", # 0xE2
|
||||
None, # 0xE3
|
||||
None, # 0xE4
|
||||
"trap_force_rain_point_3d", # 0xE5
|
||||
"trap_force_rain_chr", # 0xE6
|
||||
"get_force_rain_trap_count", # 0xE7
|
||||
"get_force_rain_trap_no", # 0xE8
|
||||
None, # 0xE9
|
||||
"get_prev_crate", # 0xEA
|
||||
None, # 0xEB
|
||||
None, # 0xEC
|
||||
None, # 0xED
|
||||
None, # 0xEE
|
||||
None, # 0xEF
|
||||
None, # 0xF0
|
||||
"force_obj_delete", # 0xF1
|
||||
"get_force_action", # 0xF2
|
||||
None, # 0xF3
|
||||
None, # 0xF4
|
||||
None, # 0xF5
|
||||
"set_chr_bright", # 0xF6
|
||||
None, # 0xF7
|
||||
"set_fade_chr_color", # 0xF8
|
||||
None, # 0xF9
|
||||
None, # 0xFA
|
||||
"set_line_hit_mode", # 0xFB
|
||||
None, # 0xFC
|
||||
None, # 0xFD
|
||||
None, # 0xFE
|
||||
"trap_force_box_ivy_up", # 0xFF
|
||||
"trap_force_box_ivy_dn", # 0x100
|
||||
"trap_force_poly4_ivy_up", # 0x101
|
||||
"trap_force_poly4_ivy_dn", # 0x102
|
||||
None, # 0x103
|
||||
"set_ladder", # 0x104
|
||||
None, # 0x105
|
||||
None, # 0x106
|
||||
None, # 0x107
|
||||
"print_screen", # 0x108
|
||||
"cross_fade", # 0x109
|
||||
None, # 0x10A
|
||||
None, # 0x10B
|
||||
None, # 0x10C
|
||||
None, # 0x10D
|
||||
None, # 0x10E
|
||||
None, # 0x10F
|
||||
"define_texture", # 0x110
|
||||
"get_ce_arg", # 0x111
|
||||
"set_ce_arg", # 0x112
|
||||
"set4_ce_arg", # 0x113
|
||||
None, # 0x114
|
||||
None, # 0x115
|
||||
None, # 0x116
|
||||
None, # 0x117
|
||||
None, # 0x118
|
||||
None, # 0x119
|
||||
None, # 0x11A
|
||||
None, # 0x11B
|
||||
"set_weather_disp", # 0x11C
|
||||
None, # 0x11D
|
||||
None, # 0x11E
|
||||
"set_keyframe", # 0x11F
|
||||
"set_keyframe_arg", # 0x120
|
||||
"delete_keyframe", # 0x121
|
||||
None, # 0x122
|
||||
None, # 0x123
|
||||
None, # 0x124
|
||||
None, # 0x125
|
||||
None, # 0x126
|
||||
"debug_bp", # 0x127
|
||||
None, # 0x128
|
||||
None, # 0x129
|
||||
None, # 0x12A
|
||||
None, # 0x12B
|
||||
None, # 0x12C
|
||||
None, # 0x12D
|
||||
None, # 0x12E
|
||||
None, # 0x12F
|
||||
None, # 0x130
|
||||
None, # 0x131
|
||||
None, # 0x132
|
||||
None, # 0x133
|
||||
None, # 0x134
|
||||
None, # 0x135
|
||||
None, # 0x136
|
||||
None, # 0x137
|
||||
None, # 0x138
|
||||
None, # 0x139
|
||||
None, # 0x13A
|
||||
None, # 0x13B
|
||||
None, # 0x13C
|
||||
None, # 0x13D
|
||||
None, # 0x13E
|
||||
None, # 0x13F
|
||||
None, # 0x140
|
||||
None, # 0x141
|
||||
# PSP only
|
||||
None, # 0x142
|
||||
None, # 0x143
|
||||
None, # 0x144
|
||||
None, # 0x145
|
||||
None, # 0x146
|
||||
None, # 0x147
|
||||
None, # 0x148
|
||||
None, # 0x149
|
||||
None, # 0x14A
|
||||
None, # 0x14B
|
||||
None, # 0x14C
|
||||
None, # 0x14D
|
||||
None, # 0x14E
|
||||
None, # 0x14F
|
||||
None, # 0x150
|
||||
None, # 0x151
|
||||
None, # 0x152
|
||||
None, # 0x153
|
||||
)
|
||||
|
||||
SYSCALL_ARGUMENT_COUNT = (
|
||||
0x02,0x02,0x01,0x01,0x00,0x06,0x07,0x03,0x04,0x01,0x03,0x05,0x02,0x03,0x04,
|
||||
0x05,0x04,0x05,0x01,0x02,0x06,0x00,0x00,0x00,0x06,0x06,0x07,0x08,0x0A,0x0B,
|
||||
0x0C,0x08,0x08,0x09,0x0A,0x0E,0x0F,0x10,0x02,0x01,0x01,0x06,0x06,0x0A,0x08,
|
||||
0x08,0x0E,0x01,0x01,0x06,0x06,0x06,0x08,0x08,0x08,0x01,0x01,0x05,0x06,0x01,
|
||||
0x01,0x02,0x03,0x04,0x00,0x03,0x06,0x02,0x03,0x08,0x01,0x04,0x02,0x01,0x01,
|
||||
0x01,0x00,0x01,0x01,0x07,0x05,0x01,0x02,0x00,0x00,0x00,0x00,0x02,0x03,0x01,
|
||||
0x01,0x01,0x04,0x00,0x02,0x01,0x02,0x01,0x02,0x01,0x01,0x07,0x07,0x0B,0x09,
|
||||
0x09,0x0F,0x01,0x01,0x01,0x01,0x01,0x03,0x04,0x03,0x05,0x03,0x07,0x08,0x03,
|
||||
0x04,0x07,0x01,0x03,0x02,0x00,0x00,0x02,0x02,0x04,0x09,0x04,0x01,0x01,0x02,
|
||||
0x02,0x05,0x01,0x02,0x02,0x03,0x03,0x02,0x00,0x02,0x01,0x01,0x03,0x03,0x02,
|
||||
0x01,0x01,0x01,0x09,0x00,0x01,0x00,0x01,0x0F,0x10,0x04,0x01,0x04,0x02,0x02,
|
||||
0x01,0x01,0x01,0x01,0x08,0x01,0x01,0x02,0x03,0x01,0x01,0x01,0x04,0x01,0x06,
|
||||
0x08,0x03,0x03,0x00,0x04,0x02,0x00,0x00,0x03,0x00,0x02,0x04,0x03,0x02,0x02,
|
||||
0x01,0x02,0x03,0x01,0x06,0x06,0x0A,0x08,0x08,0x0E,0x04,0x02,0x06,0x08,0x00,
|
||||
0x00,0x05,0x03,0x09,0x00,0x03,0x02,0x04,0x06,0x03,0x02,0x04,0x00,0x01,0x04,
|
||||
0x01,0x03,0x01,0x02,0x05,0x02,0x00,0x01,0x01,0x00,0x01,0x01,0x01,0x01,0x01,
|
||||
0x01,0x00,0x00,0x08,0x01,0x00,0x04,0x04,0x07,0x08,0x02,0x01,0x00,0x00,0x02,
|
||||
0x06,0x06,0x0A,0x0A,0x01,0x09,0x01,0x04,0x02,0x00,0x01,0x00,0x01,0x07,0x00,
|
||||
0x01,0x02,0x09,0x04,0x05,0x08,0x01,0x00,0x01,0x03,0x03,0x0A,0x03,0x01,0x01,
|
||||
0x02,0x01,0x09,0x02,0x03,0x01,0x02,0x01,0x06,0x03,0x01,0x00,0x05,0x01,0x00,
|
||||
0x01,0x01,0x02,0x00,0x01,0x04,0x01,0x01,0x01,0x08,0x01,0x01,0x02,0x00,0x04,
|
||||
0x06,0x00,0x00,0x05,0x02,0x02,0x01,
|
||||
# PSP
|
||||
0x00,0x01,0x01,0x00,0x00,0x01,0x01,0x01,0x01,0x02,0x01,0x02,0x02,0x01,0x01,
|
||||
0x01,0x01,0x04
|
||||
)
|
||||
181
theirsce_instructions.py
Normal file
181
theirsce_instructions.py
Normal file
@@ -0,0 +1,181 @@
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
|
||||
class VariableType(Enum):
|
||||
BIT = 0
|
||||
BYTE = 1
|
||||
SHORT = 2
|
||||
INT = 3
|
||||
PTR = 4
|
||||
|
||||
|
||||
class ReferenceScope(Enum):
|
||||
LOCAL = 0
|
||||
FILE = 1
|
||||
GLOBAL = 2
|
||||
|
||||
|
||||
class BranchType(Enum):
|
||||
UNCONDITIONAL = 0
|
||||
NOT_EQUALS = 1
|
||||
EQUALS = 2
|
||||
|
||||
|
||||
class InstructionType(Enum):
|
||||
ALU = 0
|
||||
PUSH = 1
|
||||
SYSCALL = 2
|
||||
BRANCH = 3
|
||||
LOCAL_CALL = 4
|
||||
RETURN = 5
|
||||
ACQUIRE = 6
|
||||
BREAK = 7
|
||||
STRING = 8
|
||||
REFERENCE = 9
|
||||
SP_REF = 10
|
||||
|
||||
|
||||
class AluOperation(Enum):
|
||||
# UNARY
|
||||
SWITCH_POP = 0
|
||||
POST_INCREMENT = 1
|
||||
POST_DECREMENT = 2
|
||||
PRE_INCREMENT = 3
|
||||
PRE_DECREMENT = 4
|
||||
ARITHMETIC_NEGATION = 5
|
||||
BITWISE_NOT = 6
|
||||
LOGICAL_NOT = 7
|
||||
|
||||
# BINARY
|
||||
INDEX_ARRAY = 8
|
||||
SUBSCRIPT = 8
|
||||
MULTIPLICATION = 9
|
||||
DIVISION = 10
|
||||
MODULO = 11
|
||||
ADDITION = 12
|
||||
SUBTRACTION = 13
|
||||
BITWISE_LEFT_SHIFT = 14
|
||||
BITWISE_RIGHT_SHIFT = 15
|
||||
GREATER_THAN = 16
|
||||
LESS_THAN = 17
|
||||
GREATER_THAN_OR_EQUALS = 18
|
||||
LESS_THAN_OR_EQUALS = 19
|
||||
EQUALS = 20
|
||||
NOT_EQUALS = 21
|
||||
BITWISE_AND = 22
|
||||
BITWISE_XOR = 23
|
||||
BITWISE_OR = 24
|
||||
LOGICAL_AND = 25
|
||||
LOGICAL_OR = 26
|
||||
ASSIGNMENT = 27
|
||||
MULTIPLICATION_ASSIGNMENT = 28
|
||||
DIVISION_ASSIGNMENT = 29
|
||||
MODULO_ASSIGNMENT = 30
|
||||
ADDITION_ASSIGNMENT = 31
|
||||
SUBTRACTION_ASSIGNMENT = 32
|
||||
BITWISE_LEFT_SHIFT_ASSIGNMENT = 33
|
||||
BITWISE_RIGHT_SHIFT_ASSIGNMENT = 34
|
||||
BITWISE_AND_ASSIGNMENT = 35
|
||||
BITWISE_XOR_ASSIGNMENT = 36
|
||||
BITWISE_OR_ASSIGNMENT = 37
|
||||
|
||||
|
||||
@dataclass
|
||||
class TheirsceBaseInstruction:
|
||||
mnemonic: str = field(default=False, init=False)
|
||||
type: InstructionType = field(default=False, init=False)
|
||||
#size: int
|
||||
|
||||
|
||||
@dataclass
|
||||
class TheirsceAluInstruction(TheirsceBaseInstruction):
|
||||
operation: AluOperation
|
||||
mnemonic = "ALU"
|
||||
type = InstructionType.ALU
|
||||
|
||||
def __post_init__(self):
|
||||
self.mnemonic = self.operation.name
|
||||
|
||||
|
||||
@dataclass
|
||||
class TheirscePushInstruction(TheirsceBaseInstruction):
|
||||
value: int
|
||||
mnemonic = "PUSH"
|
||||
type = InstructionType.PUSH
|
||||
|
||||
|
||||
@dataclass
|
||||
class TheirsceSyscallInstruction(TheirsceBaseInstruction):
|
||||
function_index: int
|
||||
function_name: str
|
||||
mnemonic = "SYSCALL"
|
||||
type = InstructionType.SYSCALL
|
||||
|
||||
|
||||
@dataclass
|
||||
class TheirsceLocalCallInstruction(TheirsceBaseInstruction):
|
||||
destination: int
|
||||
reserve: int
|
||||
mnemonic = "CALL"
|
||||
type = InstructionType.LOCAL_CALL
|
||||
|
||||
|
||||
@dataclass
|
||||
class TheirsceAcquireInstruction(TheirsceBaseInstruction):
|
||||
params: list[int]
|
||||
variables: int
|
||||
mnemonic = "ACQUIRE"
|
||||
type = InstructionType.ACQUIRE
|
||||
|
||||
|
||||
@dataclass
|
||||
class TheirsceBreakInstruction(TheirsceBaseInstruction):
|
||||
param: int
|
||||
mnemonic = "BREAK"
|
||||
type = InstructionType.BREAK
|
||||
|
||||
|
||||
@dataclass
|
||||
class TheirsceBranchInstruction(TheirsceBaseInstruction):
|
||||
destination: int
|
||||
branch_type: BranchType
|
||||
mnemonic = ""
|
||||
type = InstructionType.BRANCH
|
||||
|
||||
def __post_init__(self):
|
||||
self.mnemonic = self.branch_type.name
|
||||
|
||||
|
||||
@dataclass
|
||||
class TheirsceReturnInstruction(TheirsceBaseInstruction):
|
||||
is_void: bool
|
||||
mnemonic = "RETURN"
|
||||
type = InstructionType.RETURN
|
||||
|
||||
def __post_init__(self):
|
||||
if self.is_void:
|
||||
self.mnemonic += "_VOID"
|
||||
|
||||
|
||||
@dataclass
|
||||
class TheirsceStringInstruction(TheirsceBaseInstruction):
|
||||
text: str
|
||||
offset: int
|
||||
mnemonic = "STRING"
|
||||
type = InstructionType.STRING
|
||||
|
||||
|
||||
@dataclass
|
||||
class TheirsceReferenceInstruction(TheirsceBaseInstruction):
|
||||
ref_type: VariableType
|
||||
scope: ReferenceScope
|
||||
offset: int
|
||||
shift: int
|
||||
mnemonic = "REF"
|
||||
type = InstructionType.REFERENCE
|
||||
|
||||
|
||||
@dataclass
|
||||
class TheirsceSpecialReferenceInstruction(TheirsceBaseInstruction):
|
||||
mnemonic = "SP_REF"
|
||||
type = InstructionType.SP_REF
|
||||
Reference in New Issue
Block a user