diff options
| author | octorock <79596758+octorock@users.noreply.github.com> | 2021-03-06 15:53:39 +0100 |
|---|---|---|
| committer | octorock <79596758+octorock@users.noreply.github.com> | 2021-03-06 17:47:56 +0100 |
| commit | 15f480dc0f99437a5ff08c5a8c5c037107b89663 (patch) | |
| tree | ddfc7ddcd37496aa52d7ab0dd266f70222716d5e /tools/script_disassembler | |
| parent | 33b1445debb8b08a2cba349732d615b0a201cfd4 (diff) | |
Add labels for relative jumps
Diffstat (limited to 'tools/script_disassembler')
| -rw-r--r-- | tools/script_disassembler/.gitignore | 1 | ||||
| -rw-r--r-- | tools/script_disassembler/definitions.py | 326 | ||||
| -rw-r--r-- | tools/script_disassembler/incbin_parser.py | 70 | ||||
| -rw-r--r-- | tools/script_disassembler/script_disassembler.py | 338 | ||||
| -rw-r--r-- | tools/script_disassembler/utils.py | 21 |
5 files changed, 415 insertions, 341 deletions
diff --git a/tools/script_disassembler/.gitignore b/tools/script_disassembler/.gitignore new file mode 100644 index 00000000..9289883f --- /dev/null +++ b/tools/script_disassembler/.gitignore @@ -0,0 +1 @@ +labels.txt
\ No newline at end of file diff --git a/tools/script_disassembler/definitions.py b/tools/script_disassembler/definitions.py new file mode 100644 index 00000000..f12ce493 --- /dev/null +++ b/tools/script_disassembler/definitions.py @@ -0,0 +1,326 @@ +from utils import barray_to_u16_hex, barray_to_u32_hex, barray_to_s16 +import struct + +commands = [ + {'fun': 'ScriptCommandNop', 'params': ''}, + {'fun': 'ScriptCommand_StartScript', 'params': '', 'name': 'start executing scripts'}, + {'fun': 'ScriptCommand_StopScript', 'params': '', 'name': 'stop executing scripts'}, + {'fun': 'ScriptCommand_Jump', 'params': 'j', 'name': 'jump by offset'}, + {'fun': 'ScriptCommand_JumpIf', 'params': 'j', 'name': 'jump if'}, + {'fun': 'ScriptCommand_JumpIfNot', 'params': 'j', 'name': 'jump if not'}, + {'fun': 'ScriptCommand_JumpSwitch', 'params': ['jj', 'jjj', 'jjjj', 'jjjjjjj', 'jjjjjjjjj']}, + {'fun': 'ScriptCommand_JumpAbsolute', 'params': 'x','name': 'abs jump' }, + {'fun': 'ScriptCommand_JumpAbsoluteIf', 'params': 'x', 'name': 'abs jump if'}, + {'fun': 'ScriptCommand_JumpAbsoluteIfNot', 'params': 'x', 'name': 'abs jump if not'}, + {'fun': 'ScriptCommand_JumpAbsoluteSwitch', 'params': 'xx'}, + {'fun': 'ScriptCommand_Call', 'params':'p', 'name': 'Execute function via pointer'},# 'exec': ScriptCommand_Call}, + {'fun': 'ScriptCommand_CallWithArg', 'params': ['pw', 'p']}, + {'fun': 'ScriptCommand_LoadRoomEntityList', 'params': 'd'}, + {'fun': 'ScriptCommand_TestBit', 'params': 'w'}, + {'fun': 'ScriptCommand_CheckInventory1', 'params': 's'}, + {'fun': 'ScriptCommand_CheckInventory2', 'params': 's'}, + {'fun': 'ScriptCommand_HasRoomItemForSale', 'params': ''}, + {'fun': 'ScriptCommand_CheckLocalFlag', 'params': 's'}, + {'fun': 'ScriptCommand_CheckLocalFlagByOffset', 'params': 'ss'}, + {'fun': 'ScriptCommand_CheckGlobalFlag', 'params': 's'}, + {'fun': 'ScriptCommand_CheckRoomFlag', 'params': 's'}, + {'fun': 'ScriptCommand_CheckPlayerInRegion', 'params': 'sss'}, + {'fun': 'ScriptCommand_CheckPlayerInRegion2', 'params': 's'}, + {'fun': 'ScriptCommand_CheckEntityInteractType', 'params': ''}, + {'fun': 'ScriptCommand_0807E30C', 'params': ''}, + {'fun': 'ScriptCommand_HasRupees', 'params': 's'}, + {'fun': 'ScriptCommand_0807E3BC', 'params': 's'}, + {'fun': 'ScriptCommand_0807E3E8', 'params': ''}, + {'fun': 'ScriptCommand_CheckKinstoneFused', 'params': 's'}, + {'fun': 'ScriptCommand_BuyItem', 'params': 'ss'}, + {'fun': 'ScriptCommand_0807E48C', 'params': 's'}, + {'fun': 'ScriptCommand_0807E4CC', 'params': 'w'}, + {'fun': 'ScriptCommand_0807E4EC', 'params': 'w'}, + {'fun': 'ScriptCommand_0807E514', 'params': 'w'}, + {'fun': 'ScriptCommand_CheckPlayerFlags', 'params':'w'}, + {'fun': 'ScriptCommand_0807E564', 'params': ''}, + {'fun': 'ScriptCommand_EntityHasHeight', 'params': ''}, + {'fun': 'ScriptCommand_ComparePlayerAction', 'params': 's'}, + {'fun': 'ScriptCommand_ComparePlayerAnimationState', 'params': 's'}, + {'fun': 'ScriptCommand_0807E5F8', 'params': 'w'},# 'exec': ScriptCommand_0807E5F8}, + {'fun': 'ScriptCommand_0807E610', 'params': 'w'}, + {'fun': 'ScriptCommand_SetLocalFlag', 'params': 's'}, + {'fun': 'ScriptCommand_SetLocalFlagByOffset', 'params': 'ss'}, + {'fun': 'ScriptCommand_ClearLocalFlag', 'params': 's'}, + {'fun': 'ScriptCommand_SetGlobalFlag', 'params': 's'}, + {'fun': 'ScriptCommand_ClearGlobalFlag', 'params': 's'}, + {'fun': 'ScriptCommand_SetRoomFlag', 'params': 's'}, + {'fun': 'ScriptCommand_ClearRoomFlag', 'params': 's'}, + {'fun': 'ScriptCommand_Wait', 'params': 's'}, + {'fun': 'ScriptCommand_WaitForSomething', 'params': 'w'}, + {'fun': 'ScriptCommand_WaitForSomething2', 'params': 'w'}, + {'fun': 'ScriptCommand_WaitPlayerAction8', 'params': ''}, + {'fun': 'ScriptCommand_WaitForPlayerAction0x17', 'params': ''}, + {'fun': 'ScriptCommand_WaitFor_1', 'params': ''}, + {'fun': 'ScriptCommand_WaitFor_2', 'params': ''}, + {'fun': 'ScriptCommand_0807E778', 'params': 's'}, + {'fun': 'ScriptCommand_0807E788', 'params': 'w'}, + {'fun': 'ScriptCommand_0807E79C', 'params': ''}, + {'fun': 'ScriptCommandNop2', 'params': 's'}, + {'fun': 'ScriptCommand_DoFade4', 'params': ''}, + {'fun': 'ScriptCommand_DoFade5', 'params': ''}, + {'fun': 'ScriptCommand_DoFade6', 'params': ''}, + {'fun': 'ScriptCommand_DoFade7', 'params': ''}, + {'fun': 'ScriptCommand_0807E800', 'params': 'w'}, + {'fun': 'ScriptCommand_0807E80C', 'params': 'w'}, + {'fun': 'ScriptCommand_0807E858', 'params': ['s', '']}, + {'fun': 'ScriptCommand_0807E864', 'params': ''}, + {'fun': 'ScriptCommand_0807E878', 'params': ''}, + {'fun': 'ScriptCommand_0807E888', 'params': ''}, + {'fun': 'ScriptCommand_SetPlayerAction', 'params': 'w'}, + {'fun': 'ScriptCommand_StartPlayerScript', 'params': 'x'}, + {'fun': 'ScriptCommand_0807E8D4', 'params': 's'}, + {'fun': 'ScriptCommand_0807E8E4_0', 'params': ''}, # duplicate + {'fun': 'ScriptCommand_0807E8E4_1', 'params': ''}, # duplicate + {'fun': 'ScriptCommand_0807E8E4_2', 'params': ''}, # duplicate + {'fun': 'ScriptCommand_0807E8E4_3', 'params': ''}, # duplicate + {'fun': 'ScriptCommand_0807E908', 'params': 's'}, + {'fun': 'ScriptCommand_0807E914', 'params': 'w'}, + {'fun': 'ScriptCommand_0807E924', 'params': ''}, + {'fun': 'ScriptCommand_0807E930', 'params': 's'}, + {'fun': 'ScriptCommand_0807E944', 'params': ''}, + {'fun': 'ScriptCommand_0807E974', 'params': 's'}, + {'fun': 'ScriptCommand_0807E9D4', 'params': ''}, + {'fun': 'ScriptCommand_0807E9DC', 'params': ''}, + {'fun': 'ScriptCommand_0807E9E4', 'params': 's'}, + {'fun': 'ScriptCommand_0807E9F0', 'params': ''}, + {'fun': 'ScriptCommand_0807EA4C', 'params': ''}, + {'fun': 'ScriptCommand_0807EA88', 'params': 's'}, + {'fun': 'ScriptCommand_0807EA94', 'params': ''}, + {'fun': 'ScriptCommand_TextboxNoOverlapFollow', 'params': 's'}, + {'fun': 'ScriptCommand_TextboxNoOverlap', 'params': 's'}, + {'fun': 'ScriptCommand_TextboxNoOverlapFollowPos', 'params': ['w', 's']}, # TODO w or ss? + {'fun': 'ScriptCommand_0807EAF0', 'params': ['ss', 'sss', 'ssss']}, + {'fun': 'ScriptCommand_TextboxNoOverlapVar', 'params': ''}, + {'fun': 'ScriptCommand_0807EB28', 'params': 's'}, + {'fun': 'ScriptCommand_0807EB38', 'params': ''}, + {'fun': 'ScriptCommand_0807EB44', 'params': 's'}, + {'fun': 'ScriptCommand_0807EB4C', 'params': 'ss'}, + {'fun': 'ScriptCommand_0807EB74', 'params': ''}, + {'fun': 'ScriptCommand_0807EB8C', 'params': ''}, + {'fun': 'ScriptCommand_SetEntityDirection', 'params': 's'}, + {'fun': 'ScriptCommand_SetEntityDirectionWithAnimationState', 'params': 's'}, + {'fun': 'ScriptCommand_SetEntityNonPlanarMovement', 'params': 's'}, + {'fun': 'ScriptCommand_SetEntity0x20', 'params': 'w'}, + {'fun': 'ScriptCommand_SetEntityPositionRelative', 'params': 'w'}, + {'fun': 'ScriptCommand_SetEntityPosition', 'params': 'ss'}, + {'fun': 'ScriptCommand_MoveEntityToPlayer', 'params': ''}, + {'fun': 'ScriptCommandNop3', 'params': ''}, + {'fun': 'ScriptCommand_0807EC1C', 'params': 's'}, + {'fun': 'ScriptCommand_0807EC64', 'params': 's'}, + {'fun': 'ScriptCommand_0807EC94', 'params': 's'}, + {'fun': 'ScriptCommand_0807ECC4', 'params': 's'}, + {'fun': 'ScriptCommand_0807ECF4', 'params': 's'}, + {'fun': 'ScriptCommand_0807ED24', 'params': 'sss'}, + {'fun': 'ScriptCommand_0807EDD4', 'params': 'ss'}, + {'fun': 'ScriptCommand_0807EE04', 'params': 'ss'}, + {'fun': 'ScriptCommand_0807EE30', 'params': ''}, + {'fun': 'ScriptCommand_0807EEB4', 'params': ''}, + {'fun': 'ScriptCommand_0807EEF4', 'params': 'ss'}, + {'fun': 'ScriptCommand_0807EF3C', 'params': 'ss'}, + {'fun': 'ScriptCommand_0807EF80', 'params': 's'}, + {'fun': 'ScriptCommand_0807EF90', 'params': 's'}, + {'fun': 'ScriptCommand_SoundReq', 'params': 's'}, + {'fun': 'ScriptCommand_SoundReq2', 'params': 's'}, + {'fun': 'ScriptCommand_SoundReq3', 'params': 'w'}, + {'fun': 'ScriptCommand_SoundReq0x80100000', 'params': ''}, + {'fun': 'ScriptCommand_ModRupees', 'params': 's'}, + {'fun': 'ScriptCommand_ModHealth', 'params': 's'}, + {'fun': 'ScriptCommand_IncreaseMaxHealth', 'params': 's'}, + {'fun': 'ScriptCommand_0807F034', 'params': 's'}, + {'fun': 'ScriptCommand_0807F050', 'params': 's'}, + {'fun': 'ScriptCommand_GetInventoryValue', 'params': 's'}, + {'fun': 'ScriptCommand_0807F078', 'params': 'ss'}, + {'fun': 'ScriptCommand_0807F088', 'params': 's'}, + {'fun': 'ScriptCommand_CameraTargetEntity', 'params': ''}, + {'fun': 'ScriptCommand_CameraTargetPlayer', 'params': ''}, + {'fun': 'ScriptCommand_0807F0B4', 'params': 's'}, + {'fun': 'ScriptCommand_0807F0C8', 'params': 'ss'} +] + + + + +# Functions that have already been renamed +POINTER_MAP = { + 'sub_08095458': 'nullsub_527', + 'sub_0805EBCC': 'DeleteAllEnemies', + 'sub_0806C23C': 'Simon_CreateChest', + 'sub_0801637C': 'script_0801637C+1', + 'sub_08016383': 'script_08016384', + 'sub_0806C598': 'FUN_0806c598', + 'sub_080A2138': 'Windcrest_Unlock', + 'sub_080A29BC': 'CreateDust' +} +# tries to directly reference the function this is pointing to +def get_pointer(barray): + integers = struct.unpack('I', barray) + pointer = 'sub_' + (struct.pack('>I', integers[0]-1).hex()).upper() + if pointer in POINTER_MAP: + return POINTER_MAP[pointer] + return pointer + +# Data pointers that actually point to a script location +DATA_MAP = { + 'gUnk_08016384': 'script_08016384' +} +def get_data_pointer(barray): + integers = struct.unpack('I', barray) + pointer = 'gUnk_' + (struct.pack('>I', integers[0]).hex()).upper() + if pointer in DATA_MAP: + return DATA_MAP[pointer] + return pointer + +def get_script_pointer(barray): + integers = struct.unpack('I', barray) + return 'script_' + (struct.pack('>I', integers[0]).hex()).upper() + + +def get_script_label(u32): + return hex(u32).upper().replace('0X', 'script_0') + + +used_labels = set() +def use_script_label(u32): + global used_labels + used_labels.add(u32) + label = get_script_label(u32) + return label + + + + +# definitions for parameter types +parameters = { + '': { + 'length':0, + 'param': '', + 'expr': '', + 'read': lambda ctx: '' + }, + 's': { + 'length': 1, + 'param': 's', + 'expr': ' .short \s', + 'read': lambda ctx: barray_to_u16_hex(ctx.data[ctx.ptr+2:ctx.ptr+4])[0] + }, + 'ss': { + 'length': 2, + 'param': 'a,b', + 'expr': ' .short \\a\n .short \\b', + 'read': lambda ctx: ', '.join(barray_to_u16_hex(ctx.data[ctx.ptr+2:ctx.ptr+6])) + }, + 'sss': { + 'length': 3, + 'param': 'a,b,c', + 'expr': ' .short \\a\n .short \\b\n .short \\c', + 'read': lambda ctx: ', '.join(barray_to_u16_hex(ctx.data[ctx.ptr+2:ctx.ptr+8])) + }, + 'ssss': { + 'length': 4, + 'param': 'a,b,c,d', + 'expr': ' .short \\a\n .short \\b\n .short \\c\n .short \\d', + 'read': lambda ctx: ', '.join(barray_to_u16_hex(ctx.data[ctx.ptr+2:ctx.ptr+10])) + }, + + 'w': { + 'length': 2, + 'param': 'w', + 'expr': ' .word \w', + 'read': lambda ctx: barray_to_u32_hex(ctx.data[ctx.ptr+2:ctx.ptr+6])[0] + }, + 'ww': { + 'length': 4, + 'param': 'a,b', + 'expr': ' .word \\a\n .word \\b', + 'read': lambda ctx: ', '.join(barray_to_u32_hex(ctx.data[ctx.ptr+2:ctx.ptr+10])) + }, + + + 'j': { # Relative jump target + 'length': 1, + 'param': 's', + 'expr': '1: .short \s - 1b', + 'read': lambda ctx: use_script_label(ctx.script_addr+ctx.ptr+ 2 +barray_to_s16(ctx.data[ctx.ptr+2:ctx.ptr+4])) + # hex(ctx.script_addr + barray_to_s16(ctx.data[ctx.ptr+2:ctx.ptr+4])).upper().replace('0X', 'script_0') + }, + 'jj': { + 'length': 2, + 'param': 'a,b', + 'expr': '1: .short \\a - 1b\n .short \\b - 1b - 2', + 'read': lambda ctx: ', '.join([use_script_label(ctx.script_addr+ctx.ptr+ 2 +barray_to_s16(ctx.data[ctx.ptr+x*2+2:ctx.ptr+x*2+4]) + x*2) for x in range(0,2)]) + }, + 'jjj': { + 'length': 3, + 'param': 'a,b,c', + 'expr': '1: .short \\a - 1b\n .short \\b - 1b - 2\n .short \\c - 1b - 4', + 'read': lambda ctx: ', '.join([use_script_label(ctx.script_addr+ctx.ptr+ 2 +barray_to_s16(ctx.data[ctx.ptr+x*2+2:ctx.ptr+x*2+4]) + x*2) for x in range(0,3)]) + }, + 'jjjj': { + 'length': 4, + 'param': 'a,b,c,d', + 'expr': '1: .short \\a - 1b\n .short \\b - 1b - 2\n .short \\c - 1b - 4\n .short \\d - 1b - 6', + 'read': lambda ctx: ', '.join([use_script_label(ctx.script_addr+ctx.ptr+ 2 +barray_to_s16(ctx.data[ctx.ptr+x*2+2:ctx.ptr+x*2+4]) + x*2) for x in range(0,4)]) + }, + 'jjjjjjj': { + 'length': 7, + 'param': 'a,b,c,d,e,f,g', + 'expr': '1: .short \\a - 1b\n .short \\b - 1b - 2\n .short \\c - 1b - 4\n .short \\d - 1b - 6\n .short \\e - 1b - 8\n .short \\f - 1b - 10\n .short \\g - 1b - 12', + 'read': lambda ctx: ', '.join([use_script_label(ctx.script_addr+ctx.ptr+ 2 +barray_to_s16(ctx.data[ctx.ptr+x*2+2:ctx.ptr+x*2+4]) + x*2) for x in range(0,7)]) + }, + 'jjjjjjjjj': { + 'length': 9, + 'param': 'a,b,c,d,e,f,g,h,i', + 'expr': '1: .short \\a - 1b\n .short \\b - 1b - 2\n .short \\c - 1b - 4\n .short \\d - 1b - 6\n .short \\e - 1b - 8\n .short \\f - 1b - 10\n .short \\g - 1b - 12\n .short \\h - 1b - 14\n .short \\i - 1b - 16', + 'read': lambda ctx: ', '.join([use_script_label(ctx.script_addr+ctx.ptr+ 2 +barray_to_s16(ctx.data[ctx.ptr+x*2+2:ctx.ptr+x*2+4]) + x*2) for x in range(0,9)]) + }, + 'p': { + 'length': 2, + 'param': 'w', + 'expr': ' .word \w', + 'read': lambda ctx: get_pointer(ctx.data[ctx.ptr+2:ctx.ptr+6]) + }, + + 'pw': { + 'length': 4, + 'param': 'a,b', + 'expr': ' .word \\a\n .word \\b', + 'read': lambda ctx: get_pointer(ctx.data[ctx.ptr+2:ctx.ptr+6]) + ', ' + barray_to_u32_hex(ctx.data[ctx.ptr+6:ctx.ptr+14])[0] + }, + 'd': { # Data pointer + 'length': 2, + 'param': 'w', + 'expr': ' .word \w', + 'read': lambda ctx: get_data_pointer(ctx.data[ctx.ptr+2:ctx.ptr+6]) + }, + 'x': { # Script pointer + 'length': 2, + 'param': 'w', + 'expr': ' .word \w', + 'read': lambda ctx: get_script_pointer(ctx.data[ctx.ptr+2:ctx.ptr+6]) + }, + 'xx': { + 'length': 4, + 'param': 'a, b', + 'expr': ' .word \\a\n .word \\b', + 'read': lambda ctx: get_script_pointer(ctx.data[ctx.ptr+2:ctx.ptr+6]) + ', ' + get_script_pointer(ctx.data[ctx.ptr+6:ctx.ptr+10]) + }, + # Commands with variable parameter count are now handled by explicitely defining all used parameter configurations + # 'v': { + # 'length': -1, + # 'param': '', + # 'expr': '', + # 'read': lambda ctx: '' + # }, + # 'pv': { + # 'length': -2, + # 'param': 'w', + # 'expr': ' .word \w', + # 'read': lambda ctx: '' + # }, +}
\ No newline at end of file diff --git a/tools/script_disassembler/incbin_parser.py b/tools/script_disassembler/incbin_parser.py index 0416892e..70fe3da9 100644 --- a/tools/script_disassembler/incbin_parser.py +++ b/tools/script_disassembler/incbin_parser.py @@ -14,8 +14,8 @@ SCRIPTS_END=0x08016984 # Currently done by splitting the script at that point LABEL_BREAKS=[0x0800A088, 0x0800ACE0, 0x0800AD54, 0x0800B41C, 0x0800B7C4, 0x0800C8C8, 0x0800D190, 0x800D3EC, 0x0800E9F4, 0x0800FD80, 0x08012AC8, 0x08012F0C, 0x080130E4, 0x08013B70, 0x080142B0, 0x080147DC, 0x08014A80, 0x08014B10,0x0801635C, 0x08016384, 0x080165D8] -# Generate a version of the script that is annotated with the byte offset to the beginning of the script -GENERATE_REF=False +# Whether to output a label for every line +PRINT_ALL_LABELS=False def read_baserom(): # read baserom data @@ -25,9 +25,8 @@ def read_baserom(): def get_label(addr): return hex(addr).upper().replace('0X', 'script_0') -def main(): - baserom_data = read_baserom() +def disassemble_scripts(baserom_data): script_start = SCRIPTS_START-ROM_OFFSET scripts = ''' .include "asm/macros.inc" @@ -40,11 +39,11 @@ def main(): .text ''' + label_break = 0 while script_start < SCRIPTS_END-ROM_OFFSET: - if len(LABEL_BREAKS) > 0 and script_start+ROM_OFFSET >=LABEL_BREAKS[0]: - print(f'{hex(script_start+ROM_OFFSET)} > {LABEL_BREAKS[0]}') - LABEL_BREAKS.pop(0) + if label_break < len(LABEL_BREAKS) and script_start+ROM_OFFSET >=LABEL_BREAKS[label_break]: + label_break += 1 label = get_label(script_start+ROM_OFFSET) print(f"Disassembling \033[1;34m{label}\033[0m ({script_start} / { SCRIPTS_END-ROM_OFFSET} bytes converted)...") @@ -54,41 +53,62 @@ def main(): if script_end > SCRIPTS_END-ROM_OFFSET: script_end = SCRIPTS_END-ROM_OFFSET - if len(LABEL_BREAKS) > 0 and script_end+ROM_OFFSET > LABEL_BREAKS[0]: - print(f'break at {hex(LABEL_BREAKS[0])} instead of {hex(script_end)}') - script_end = LABEL_BREAKS[0]-ROM_OFFSET + if label_break < len(LABEL_BREAKS) and script_end+ROM_OFFSET > LABEL_BREAKS[label_break]: + #print(f'break at {hex(LABEL_BREAKS[label_break])} instead of {hex(script_end)}') + script_end = LABEL_BREAKS[label_break]-ROM_OFFSET # read data from rom data = baserom_data[script_start:script_end] + scripts += f' .include "data/scripts/{label}.inc"\n' stdout = sys.stdout - with open(f'{TMC_FOLDER}/data/scripts/{label}.ref' if GENERATE_REF else f'{TMC_FOLDER}/data/scripts/{label}.inc','w') as out: + with open(f'{TMC_FOLDER}/data/scripts/{label}.inc','w') as out: sys.stdout = out + + if script_start == 0x1637C: # This function is actually assembly + print ('''thumb_func_start script_0801637C +script_0801637C: + push {lr} + bl CreateDust + pop {pc}''') + sys.stdout = stdout + script_start = script_end + continue + print(f'SCRIPT_START {label}') - if GENERATE_REF: - res = disassemble_script(data, True) - else: - res = disassemble_script(data) + res = disassemble_script(data, script_start+ROM_OFFSET, PRINT_ALL_LABELS) if res != 0: # Script ended in the middle, need to create a new file script_end = script_start + res sys.stdout = stdout script_start = script_end + return scripts + +def main(): + baserom_data = read_baserom() + + # Do two passes, in the first pass not all labels that are jumped to are known, so those labels are recorded in the first pass + # This is not necessary when all labels are printed + if not PRINT_ALL_LABELS: + print('Collecting labels...') + disassemble_scripts(baserom_data) + print('Writing scripts with labels...') + scripts = disassemble_scripts(baserom_data) + + print('Writing scripts.s file...') + with open(f'{TMC_FOLDER}/data/scripts.s', 'w') as out: + out.write(scripts) + print('Generating asm macros...') + stdout = sys.stdout + with open(f'{TMC_FOLDER}/asm/macros/scripts.inc', 'w') as out: + sys.stdout = out + generate_macros() + sys.stdout = stdout - if not GENERATE_REF: - print('Writing scripts.s file...') - with open(f'{TMC_FOLDER}/data/scripts.s', 'w') as out: - out.write(scripts) - print('Generating asm macros...') - stdout = sys.stdout - with open(f'{TMC_FOLDER}/asm/macros/scripts.inc', 'w') as out: - sys.stdout = out - generate_macros() - sys.stdout = stdout print('\033[1;92mDone\033[0m\n') if __name__ == '__main__': diff --git a/tools/script_disassembler/script_disassembler.py b/tools/script_disassembler/script_disassembler.py index 2cf3524d..fe35bcd1 100644 --- a/tools/script_disassembler/script_disassembler.py +++ b/tools/script_disassembler/script_disassembler.py @@ -1,5 +1,8 @@ from dataclasses import dataclass import struct +from utils import barray_to_u16_hex, barray_to_u32_hex, u16_to_hex, u32_to_hex +from definitions import get_pointer, get_data_pointer, get_script_pointer, commands, parameters, get_script_label, used_labels + # Disassembler for tmc scripts # Input 'macros' to generate the macros for the script commands @@ -11,302 +14,8 @@ import struct class Context: ptr: int data: bytes + script_addr: int -def u16_to_hex(value): - return '0x' + (struct.pack('>H', value).hex()) - -def barray_to_u16_hex(barray): - count = len(barray)//2 - integers = struct.unpack('H'*count, barray) - return [u16_to_hex(x) for x in integers] - -def u32_to_hex(value): - return '0x' + (struct.pack('>I', value).hex()) - -def barray_to_u32_hex(barray): - count = len(barray)//4 - integers = struct.unpack('I'*count, barray) - return [u32_to_hex(x) for x in integers] - - -# Functions that have already been renamed -POINTER_MAP = { - 'sub_08095458': 'nullsub_527', - 'sub_0805EBCC': 'DeleteAllEnemies', - 'sub_0806C23C': 'Simon_CreateChest', - 'sub_0801637C': 'script_0801637C+1', - 'sub_08016383': 'script_08016384', - 'sub_0806C598': 'FUN_0806c598', - 'sub_080A2138': 'Windcrest_Unlock', - 'sub_080A29BC': 'CreateDust' -} -# tries to directly reference the function this is pointing to -def get_pointer(barray): - integers = struct.unpack('I', barray) - pointer = 'sub_' + (struct.pack('>I', integers[0]-1).hex()).upper() - if pointer in POINTER_MAP: - return POINTER_MAP[pointer] - return pointer - -# Data pointers that actually point to a script location -DATA_MAP = { - 'gUnk_08016384': 'script_08016384' -} -def get_data_pointer(barray): - integers = struct.unpack('I', barray) - pointer = 'gUnk_' + (struct.pack('>I', integers[0]).hex()).upper() - if pointer in DATA_MAP: - return DATA_MAP[pointer] - return pointer - -def get_script_pointer(barray): - integers = struct.unpack('I', barray) - return 'script_' + (struct.pack('>I', integers[0]).hex()).upper() - - -commands = [ - {'fun': 'ScriptCommandNop', 'params': ''}, - {'fun': 'ScriptCommand_StartScript', 'params': '', 'name': 'start executing scripts'}, - {'fun': 'ScriptCommand_StopScript', 'params': '', 'name': 'stop executing scripts'}, - {'fun': 'ScriptCommand_Jump', 'params': 's', 'name': 'jump by offset'}, - {'fun': 'ScriptCommand_JumpIf', 'params': 's', 'name': 'jump if'}, - {'fun': 'ScriptCommand_JumpIfNot', 'params': 's', 'name': 'jump if not'}, - {'fun': 'ScriptCommand_0807E078', 'params': ['ss', 'sss', 'ssss', 'sssssss', 'sssssssss']}, - {'fun': 'ScriptCommand_JumpAbsolute', 'params': 'x','name': 'abs jump' }, - {'fun': 'ScriptCommand_JumpAbsoluteIf', 'params': 'x', 'name': 'abs jump if'}, - {'fun': 'ScriptCommand_JumpAbsoluteIfNot', 'params': 'x', 'name': 'abs jump if not'}, - {'fun': 'ScriptCommand_0807E0E0', 'params': 'xx'}, - {'fun': 'ScriptCommand_Call', 'params':'p', 'name': 'Execute function via pointer'},# 'exec': ScriptCommand_Call}, - {'fun': 'ScriptCommand_CallWithArg', 'params': ['pw', 'p']}, - {'fun': 'ScriptCommand_LoadRoomEntityList', 'params': 'd'}, - {'fun': 'ScriptCommand_TestBit', 'params': 'w'}, - {'fun': 'ScriptCommand_CheckInventory1', 'params': 's'}, - {'fun': 'ScriptCommand_CheckInventory2', 'params': 's'}, - {'fun': 'ScriptCommand_HasRoomItemForSale', 'params': ''}, - {'fun': 'ScriptCommand_CheckLocalFlag', 'params': 's'}, - {'fun': 'ScriptCommand_CheckLocalFlagByOffset', 'params': 'ss'}, - {'fun': 'ScriptCommand_CheckGlobalFlag', 'params': 's'}, - {'fun': 'ScriptCommand_CheckRoomFlag', 'params': 's'}, - {'fun': 'ScriptCommand_CheckPlayerInRegion', 'params': 'sss'}, - {'fun': 'ScriptCommand_CheckPlayerInRegion2', 'params': 's'}, - {'fun': 'ScriptCommand_CheckEntityInteractType', 'params': ''}, - {'fun': 'ScriptCommand_0807E30C', 'params': ''}, - {'fun': 'ScriptCommand_HasRupees', 'params': 's'}, - {'fun': 'ScriptCommand_0807E3BC', 'params': 's'}, - {'fun': 'ScriptCommand_0807E3E8', 'params': ''}, - {'fun': 'ScriptCommand_CheckKinstoneFused', 'params': 's'}, - {'fun': 'ScriptCommand_BuyItem', 'params': 'ss'}, - {'fun': 'ScriptCommand_0807E48C', 'params': 's'}, - {'fun': 'ScriptCommand_0807E4CC', 'params': 'w'}, - {'fun': 'ScriptCommand_0807E4EC', 'params': 'w'}, - {'fun': 'ScriptCommand_0807E514', 'params': 'w'}, - {'fun': 'ScriptCommand_CheckPlayerFlags', 'params':'w'}, - {'fun': 'ScriptCommand_0807E564', 'params': ''}, - {'fun': 'ScriptCommand_EntityHasHeight', 'params': ''}, - {'fun': 'ScriptCommand_ComparePlayerAction', 'params': 's'}, - {'fun': 'ScriptCommand_ComparePlayerAnimationState', 'params': 's'}, - {'fun': 'ScriptCommand_0807E5F8', 'params': 'w'},# 'exec': ScriptCommand_0807E5F8}, - {'fun': 'ScriptCommand_0807E610', 'params': 'w'}, - {'fun': 'ScriptCommand_SetLocalFlag', 'params': 's'}, - {'fun': 'ScriptCommand_SetLocalFlagByOffset', 'params': 'ss'}, - {'fun': 'ScriptCommand_ClearLocalFlag', 'params': 's'}, - {'fun': 'ScriptCommand_SetGlobalFlag', 'params': 's'}, - {'fun': 'ScriptCommand_ClearGlobalFlag', 'params': 's'}, - {'fun': 'ScriptCommand_SetRoomFlag', 'params': 's'}, - {'fun': 'ScriptCommand_ClearRoomFlag', 'params': 's'}, - {'fun': 'ScriptCommand_Wait', 'params': 's'}, - {'fun': 'ScriptCommand_WaitForSomething', 'params': 'w'}, - {'fun': 'ScriptCommand_WaitForSomething2', 'params': 'w'}, - {'fun': 'ScriptCommand_WaitPlayerAction8', 'params': ''}, - {'fun': 'ScriptCommand_WaitForPlayerAction0x17', 'params': ''}, - {'fun': 'ScriptCommand_WaitFor_1', 'params': ''}, - {'fun': 'ScriptCommand_WaitFor_2', 'params': ''}, - {'fun': 'ScriptCommand_0807E778', 'params': 's'}, - {'fun': 'ScriptCommand_0807E788', 'params': 'w'}, - {'fun': 'ScriptCommand_0807E79C', 'params': ''}, - {'fun': 'ScriptCommandNop2', 'params': 's'}, - {'fun': 'ScriptCommand_DoFade4', 'params': ''}, - {'fun': 'ScriptCommand_DoFade5', 'params': ''}, - {'fun': 'ScriptCommand_DoFade6', 'params': ''}, - {'fun': 'ScriptCommand_DoFade7', 'params': ''}, - {'fun': 'ScriptCommand_0807E800', 'params': 'w'}, - {'fun': 'ScriptCommand_0807E80C', 'params': 'w'}, - {'fun': 'ScriptCommand_0807E858', 'params': ['s', '']}, - {'fun': 'ScriptCommand_0807E864', 'params': ''}, - {'fun': 'ScriptCommand_0807E878', 'params': ''}, - {'fun': 'ScriptCommand_0807E888', 'params': ''}, - {'fun': 'ScriptCommand_SetPlayerAction', 'params': 'w'}, - {'fun': 'ScriptCommand_StartPlayerScript', 'params': 'x'}, - {'fun': 'ScriptCommand_0807E8D4', 'params': 's'}, - {'fun': 'ScriptCommand_0807E8E4_0', 'params': ''}, # duplicate - {'fun': 'ScriptCommand_0807E8E4_1', 'params': ''}, # duplicate - {'fun': 'ScriptCommand_0807E8E4_2', 'params': ''}, # duplicate - {'fun': 'ScriptCommand_0807E8E4_3', 'params': ''}, # duplicate - {'fun': 'ScriptCommand_0807E908', 'params': 's'}, - {'fun': 'ScriptCommand_0807E914', 'params': 'w'}, - {'fun': 'ScriptCommand_0807E924', 'params': ''}, - {'fun': 'ScriptCommand_0807E930', 'params': 's'}, - {'fun': 'ScriptCommand_0807E944', 'params': ''}, - {'fun': 'ScriptCommand_0807E974', 'params': 's'}, - {'fun': 'ScriptCommand_0807E9D4', 'params': ''}, - {'fun': 'ScriptCommand_0807E9DC', 'params': ''}, - {'fun': 'ScriptCommand_0807E9E4', 'params': 's'}, - {'fun': 'ScriptCommand_0807E9F0', 'params': ''}, - {'fun': 'ScriptCommand_0807EA4C', 'params': ''}, - {'fun': 'ScriptCommand_0807EA88', 'params': 's'}, - {'fun': 'ScriptCommand_0807EA94', 'params': ''}, - {'fun': 'ScriptCommand_TextboxNoOverlapFollow', 'params': 's'}, - {'fun': 'ScriptCommand_TextboxNoOverlap', 'params': 's'}, - {'fun': 'ScriptCommand_TextboxNoOverlapFollowPos', 'params': ['w', 's']}, # TODO w or ss? - {'fun': 'ScriptCommand_0807EAF0', 'params': ['ss', 'sss', 'ssss']}, - {'fun': 'ScriptCommand_TextboxNoOverlapVar', 'params': ''}, - {'fun': 'ScriptCommand_0807EB28', 'params': 's'}, - {'fun': 'ScriptCommand_0807EB38', 'params': ''}, - {'fun': 'ScriptCommand_0807EB44', 'params': 's'}, - {'fun': 'ScriptCommand_0807EB4C', 'params': 'ss'}, - {'fun': 'ScriptCommand_0807EB74', 'params': ''}, - {'fun': 'ScriptCommand_0807EB8C', 'params': ''}, - {'fun': 'ScriptCommand_SetEntityDirection', 'params': 's'}, - {'fun': 'ScriptCommand_SetEntityDirectionWithAnimationState', 'params': 's'}, - {'fun': 'ScriptCommand_SetEntityNonPlanarMovement', 'params': 's'}, - {'fun': 'ScriptCommand_SetEntity0x20', 'params': 'w'}, - {'fun': 'ScriptCommand_SetEntityPositionRelative', 'params': 'w'}, - {'fun': 'ScriptCommand_SetEntityPosition', 'params': 'ss'}, - {'fun': 'ScriptCommand_MoveEntityToPlayer', 'params': ''}, - {'fun': 'ScriptCommandNop3', 'params': ''}, - {'fun': 'ScriptCommand_0807EC1C', 'params': 's'}, - {'fun': 'ScriptCommand_0807EC64', 'params': 's'}, - {'fun': 'ScriptCommand_0807EC94', 'params': 's'}, - {'fun': 'ScriptCommand_0807ECC4', 'params': 's'}, - {'fun': 'ScriptCommand_0807ECF4', 'params': 's'}, - {'fun': 'ScriptCommand_0807ED24', 'params': 'sss'}, - {'fun': 'ScriptCommand_0807EDD4', 'params': 'ss'}, - {'fun': 'ScriptCommand_0807EE04', 'params': 'ss'}, - {'fun': 'ScriptCommand_0807EE30', 'params': ''}, - {'fun': 'ScriptCommand_0807EEB4', 'params': ''}, - {'fun': 'ScriptCommand_0807EEF4', 'params': 'ss'}, - {'fun': 'ScriptCommand_0807EF3C', 'params': 'ss'}, - {'fun': 'ScriptCommand_0807EF80', 'params': 's'}, - {'fun': 'ScriptCommand_0807EF90', 'params': 's'}, - {'fun': 'ScriptCommand_SoundReq', 'params': 's'}, - {'fun': 'ScriptCommand_SoundReq2', 'params': 's'}, - {'fun': 'ScriptCommand_SoundReq3', 'params': 'w'}, - {'fun': 'ScriptCommand_SoundReq0x80100000', 'params': ''}, - {'fun': 'ScriptCommand_ModRupees', 'params': 's'}, - {'fun': 'ScriptCommand_ModHealth', 'params': 's'}, - {'fun': 'ScriptCommand_IncreaseMaxHealth', 'params': 's'}, - {'fun': 'ScriptCommand_0807F034', 'params': 's'}, - {'fun': 'ScriptCommand_0807F050', 'params': 's'}, - {'fun': 'ScriptCommand_GetInventoryValue', 'params': 's'}, - {'fun': 'ScriptCommand_0807F078', 'params': 'ss'}, - {'fun': 'ScriptCommand_0807F088', 'params': 's'}, - {'fun': 'ScriptCommand_CameraTargetEntity', 'params': ''}, - {'fun': 'ScriptCommand_CameraTargetPlayer', 'params': ''}, - {'fun': 'ScriptCommand_0807F0B4', 'params': 's'}, - {'fun': 'ScriptCommand_0807F0C8', 'params': 'ss'} -] - -# definitions for parameters -parameters = { - '': { - 'length':0, - 'param': '', - 'expr': '', - 'read': lambda ctx: '' - }, - 's': { - 'length': 1, - 'param': 's', - 'expr': ' .short \s', - 'read': lambda ctx: barray_to_u16_hex(ctx.data[ctx.ptr+2:ctx.ptr+4])[0] - }, - 'w': { - 'length': 2, - 'param': 'w', - 'expr': ' .word \w', - 'read': lambda ctx: barray_to_u32_hex(ctx.data[ctx.ptr+2:ctx.ptr+6])[0] - }, - 'ss': { - 'length': 2, - 'param': 'a,b', - 'expr': ' .short \\a\n .short \\b', - 'read': lambda ctx: ', '.join(barray_to_u16_hex(ctx.data[ctx.ptr+2:ctx.ptr+6])) - }, - 'ww': { - 'length': 4, - 'param': 'a,b', - 'expr': ' .word \\a\n .word \\b', - 'read': lambda ctx: ', '.join(barray_to_u32_hex(ctx.data[ctx.ptr+2:ctx.ptr+10])) - }, - 'sss': { - 'length': 3, - 'param': 'a,b,c', - 'expr': ' .short \\a\n .short \\b\n .short \\c', - 'read': lambda ctx: ', '.join(barray_to_u16_hex(ctx.data[ctx.ptr+2:ctx.ptr+8])) - }, - 'ssss': { - 'length': 4, - 'param': 'a,b,c,d', - 'expr': ' .short \\a\n .short \\b\n .short \\c\n .short \\d', - 'read': lambda ctx: ', '.join(barray_to_u16_hex(ctx.data[ctx.ptr+2:ctx.ptr+10])) - }, - 'sssssss': { - 'length': 7, - 'param': 'a,b,c,d,e,f,g', - 'expr': ' .short \\a\n .short \\b\n .short \\c\n .short \\d\n .short \\e\n .short \\f\n .short \\g', - 'read': lambda ctx: ', '.join(barray_to_u16_hex(ctx.data[ctx.ptr+2:ctx.ptr+16])) - }, - 'sssssssss': { - 'length': 9, - 'param': 'a,b,c,d,e,f,g,h,i', - 'expr': ' .short \\a\n .short \\b\n .short \\c\n .short \\d\n .short \\e\n .short \\f\n .short \\g\n .short \\h\n .short \\i', - 'read': lambda ctx: ', '.join(barray_to_u16_hex(ctx.data[ctx.ptr+2:ctx.ptr+20])) - }, - 'p': { - 'length': 2, - 'param': 'w', - 'expr': ' .word \w', - 'read': lambda ctx: get_pointer(ctx.data[ctx.ptr+2:ctx.ptr+6]) - }, - 'd': { # Data pointer - 'length': 2, - 'param': 'w', - 'expr': ' .word \w', - 'read': lambda ctx: get_data_pointer(ctx.data[ctx.ptr+2:ctx.ptr+6]) - }, - 'x': { # Script pointer - 'length': 2, - 'param': 'w', - 'expr': ' .word \w', - 'read': lambda ctx: get_script_pointer(ctx.data[ctx.ptr+2:ctx.ptr+6]) - }, - - 'pw': { - 'length': 4, - 'param': 'a,b', - 'expr': ' .word \\a\n .word \\b', - 'read': lambda ctx: get_pointer(ctx.data[ctx.ptr+2:ctx.ptr+6]) + ', ' + barray_to_u32_hex(ctx.data[ctx.ptr+6:ctx.ptr+14])[0] - }, - 'xx': { - 'length': 4, - 'param': 'a, b', - 'expr': ' .word \\a\n .word \\b', - 'read': lambda ctx: get_script_pointer(ctx.data[ctx.ptr+2:ctx.ptr+6]) + ', ' + get_script_pointer(ctx.data[ctx.ptr+6:ctx.ptr+10]) - }, - # Commands with variable parameter count are now handled by explicitely defining all used parameter configurations - # 'v': { - # 'length': -1, - # 'param': '', - # 'expr': '', - # 'read': lambda ctx: '' - # }, - # 'pv': { - # 'length': -2, - # 'param': 'w', - # 'expr': ' .word \w', - # 'read': lambda ctx: '' - # }, -} # Remove the ScriptCommand_ prefix for the asm macros def build_script_command(name: str): @@ -318,13 +27,14 @@ def build_script_command(name: str): def print_rest_bytes(ctx): print('\n'.join(['.byte ' + hex(x) for x in ctx.data[ctx.ptr:]])) -def ExecuteScriptCommandSet(ctx: Context, add_annotations=False): - if add_annotations: - print(f'@{ctx.ptr}') # print offsets to debug when manually inserting labels +def disassemble_command(ctx: Context, add_all_annotations=False): + global used_labels + if add_all_annotations or ctx.script_addr + ctx.ptr in used_labels: + print(f'{get_script_label(ctx.script_addr + ctx.ptr)}:') # print offsets to debug when manually inserting labels cmd = struct.unpack('H', ctx.data[ctx.ptr:ctx.ptr+2])[0] if cmd == 0: # this does not need to be the end of the script - print('.short 0x0000') + print('\t.short 0x0000') ctx.ptr += 2 return 1 @@ -334,7 +44,7 @@ def ExecuteScriptCommandSet(ctx: Context, add_annotations=False): cmd = struct.unpack('H', ctx.data[ctx.ptr:ctx.ptr+2])[0] if cmd == 0x0000: # This is actually the end of the script - print('.short 0x0000') + print('\t.short 0x0000') ctx.ptr += 2 return 2 return 3 # There is a SCRIPT_END without 0x0000 afterwards, but still split into a new file, please @@ -347,7 +57,7 @@ def ExecuteScriptCommandSet(ctx: Context, add_annotations=False): commandId = cmd & 0x3FF if commandId >= len(commands): #print_rest_bytes(ctx) - print(f'.short {u16_to_hex(cmd)}') + print(f'\t.short {u16_to_hex(cmd)}') ctx.ptr += 2 #raise Exception(f'Invalid commandId {commandId} / {len(commands)} {cmd}') # TODO error @@ -377,7 +87,7 @@ def ExecuteScriptCommandSet(ctx: Context, add_annotations=False): if candidate['length'] == commandSize -1: params = candidate if i != 0: - suffix = f'_{param}'# We need to add a suffix to distinguish the correct parameter variant + suffix = f'_{params["length"]}'# We need to add a suffix to distinguish the correct parameter variant break if params is None: raise Exception(f'No suitable parameter configuration with length {commandSize-1} found for {command["fun"]}') @@ -389,18 +99,18 @@ def ExecuteScriptCommandSet(ctx: Context, add_annotations=False): command_name = f'{command["fun"]}{suffix}' if params['length'] == -1: # variable parameter length - print(f'.short {u16_to_hex(cmd)} @ {build_script_command(command_name)} with {commandSize-1} parameters') + print(f'\t.short {u16_to_hex(cmd)} @ {build_script_command(command_name)} with {commandSize-1} parameters') if commandSize > 1: - print('\n'.join(['.short ' + x for x in barray_to_u16_hex(ctx.data[ctx.ptr+2:ctx.ptr+commandSize*2])])) + print('\n'.join(['\t.short ' + x for x in barray_to_u16_hex(ctx.data[ctx.ptr+2:ctx.ptr+commandSize*2])])) print(f'@ End of parameters') ctx.ptr += commandSize*2 return 1 elif params['length'] == -2: # point and var - print(f'.short {u16_to_hex(cmd)} @ {build_script_command(command_name)} with {commandSize-3} parameters') + print(f'\t.short {u16_to_hex(cmd)} @ {build_script_command(command_name)} with {commandSize-3} parameters') - print('.word '+ get_pointer(ctx.data[ctx.ptr+2:ctx.ptr+6])) + print('\t.word '+ get_pointer(ctx.data[ctx.ptr+2:ctx.ptr+6])) if commandSize > 3: - print('\n'.join(['.short ' + x for x in barray_to_u16_hex(ctx.data[ctx.ptr+6:ctx.ptr+commandSize*2])])) + print('\n'.join(['\t.short ' + x for x in barray_to_u16_hex(ctx.data[ctx.ptr+6:ctx.ptr+commandSize*2])])) print(f'@ End of parameters') ctx.ptr += commandSize*2 return 1 @@ -408,28 +118,24 @@ def ExecuteScriptCommandSet(ctx: Context, add_annotations=False): if commandSize-1 != params['length']: raise Exception(f'Call {command_name} with ' + str(commandSize-1) +' length, while length of ' + str(params['length'])+' defined') - print(build_script_command(command_name) + ' ' + params['read'](ctx)) + print(f'\t{build_script_command(command_name)} {params["read"](ctx)}') # Execute script ctx.ptr += commandSize*2 return 1 -# TODO -# JumpAbsolute 0x08016384 -# JumpAbsoluteIf 0x08016384 -# JumpAbsoluteIfNot 0x08016384 -def disassemble_script(input_bytes, add_annotations=False): +def disassemble_script(input_bytes, script_addr, add_all_annotations=False): - ctx = Context(0, input_bytes) + ctx = Context(0, input_bytes, script_addr) foundEnd = False while True: if ctx.ptr >= len(ctx.data) - 1: # End of file (there need to be at least two bytes remaining for the next operation id) break - res = ExecuteScriptCommandSet(ctx, add_annotations) + res = disassemble_command(ctx, add_all_annotations) if res == 0: break elif res == 2: @@ -495,7 +201,7 @@ def generate_macros(): id = ((params['length']+1) << 0xA) + num suffix = '' if i != 0: - suffix = f'_{variant}' + suffix = f'_{params["length"]}' emit_macro(f'{build_script_command(command["fun"])}{suffix}', id, params) else: if not command['params'] in parameters: diff --git a/tools/script_disassembler/utils.py b/tools/script_disassembler/utils.py new file mode 100644 index 00000000..b0501e5a --- /dev/null +++ b/tools/script_disassembler/utils.py @@ -0,0 +1,21 @@ +import struct + +def barray_to_s16(barray): + integers = struct.unpack('h', barray) + return integers[0] + +def u16_to_hex(value): + return '0x' + (struct.pack('>H', value).hex()) + +def barray_to_u16_hex(barray): + count = len(barray)//2 + integers = struct.unpack('H'*count, barray) + return [u16_to_hex(x) for x in integers] + +def u32_to_hex(value): + return '0x' + (struct.pack('>I', value).hex()) + +def barray_to_u32_hex(barray): + count = len(barray)//4 + integers = struct.unpack('I'*count, barray) + return [u32_to_hex(x) for x in integers]
\ No newline at end of file |
