diff --git a/FileIO.py b/FileIO.py new file mode 100644 index 0000000..4e2bd74 --- /dev/null +++ b/FileIO.py @@ -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) diff --git a/ToolsTOR.py b/ToolsTOR.py index ae366ca..1bcfafa 100644 --- a/ToolsTOR.py +++ b/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(" 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) \ No newline at end of file diff --git a/theirsce_funcs.py b/theirsce_funcs.py new file mode 100644 index 0000000..03d57e8 --- /dev/null +++ b/theirsce_funcs.py @@ -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 +) \ No newline at end of file diff --git a/theirsce_instructions.py b/theirsce_instructions.py new file mode 100644 index 0000000..ba1b569 --- /dev/null +++ b/theirsce_instructions.py @@ -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 \ No newline at end of file