Fuse symbol_info with disasm_script so you can give it symbols (#552)

This commit is contained in:
Ethan Roseman 2021-12-15 19:27:26 -05:00 committed by GitHub
parent 967427ba97
commit 731d270014
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 55 additions and 43 deletions

View File

@ -1,6 +1,6 @@
#! /usr/bin/python3
import sys
import sym_info
from pathlib import Path
_script_lib = None
@ -1230,7 +1230,7 @@ if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("file", type=str, help="File to dissassemble from")
parser.add_argument("offset", type=lambda x: int(x, 16), default=0, help="Offset to start dissassembling from")
parser.add_argument("offset", help="Offset to start dissassembling from")
parser.add_argument("-end", "-e", "--e", type=lambda x: int(x, 16), default=0, dest="end", required=False, help="End offset to stop dissassembling from.\nOnly used as a way to find valid scripts.")
parser.add_argument("-vram", "-v", "--v", type=lambda x: int(x, 16), default=0, dest="vram", required=False, help="VRAM start will be tracked and used for the script output name")
parser.add_argument("-si", "--si", action="store_true", default=False, dest="si", required=False, help="Force si script output")
@ -1248,14 +1248,23 @@ if __name__ == "__main__":
INCLUDES_NEEDED["npcs"] = {}
INCLUDES_NEEDED["sprites"] = set()
if args.end > args.offset:
try:
offset = int(args.offset, 0)
except ValueError:
info = sym_info.search_symbol(args.offset)
if info is None:
print(f"{args.offset} is not a valid symbol name")
exit(1)
offset = info[0]
if args.end > offset:
# Search the given memory range and report scripts
with open(args.file, "rb") as f:
gap = False
first_print = False
while args.offset < args.end:
f.seek(args.offset)
while offset < args.end:
f.seek(offset)
script = ScriptDSLDisassembler(f, "", {}, 0x978DE0, INCLUDES_NEEDED, INCLUDED)
try:
@ -1264,7 +1273,7 @@ if __name__ == "__main__":
if script.instructions > 1 and "_EVT_CMD" not in script_text:
if gap and first_print:
potential_struct_sizes = { "StaticNpc": 0x1F0, "NpcAISettings":0x30, "NpcSettings":0x2C, "NpcGroupList":0xC }
gap_size = args.offset - gap_start
gap_size = offset - gap_start
potential_struct = "Unknown data"
potential_count = 1
for k,v in potential_struct_sizes.items():
@ -1272,36 +1281,36 @@ if __name__ == "__main__":
potential_struct = k
potential_count = gap_size // v
print(f"========== 0x{gap_size:X} byte gap ({potential_count} {potential_struct}?) 0x{gap_start:X} - 0x{args.offset:X} ==========")
print(f"========== 0x{gap_size:X} byte gap ({potential_count} {potential_struct}?) 0x{gap_start:X} - 0x{offset:X} ==========")
print()
gap = False
#print(f"EvtSource read from 0x{script.start_pos:X} to 0x{script.end_pos:X} "
# f"(0x{script.end_pos - script.start_pos:X} bytes, {script.instructions} instructions)")
#print()
vram = f"{args.vram:X}_" if vram_base > 0 else f""
script_text = script_text.replace("EvtSource script = SCRIPT({", f"EvtSource N(D_{vram}{args.offset:X}) = " + "SCRIPT({")
script_text = script_text.replace("EvtSource script = SCRIPT({", f"EvtSource N(D_{vram}{offset:X}) = " + "SCRIPT({")
print(script_text, end="")
print()
#print(f"Valid script found at 0x{args.offset:X}")
args.vram += script.end_pos - args.offset
args.offset = script.end_pos
#print(f"Valid script found at 0x{offset:X}")
args.vram += script.end_pos - offset
offset = script.end_pos
first_print = True
else:
if not gap:
gap_start = args.offset
gap_start = offset
gap = True
args.offset += 4
offset += 4
args.vram += 4
except Exception:
if not gap:
gap_start = args.offset
gap_start = offset
gap = True
args.offset += 4
offset += 4
args.vram += 4
else:
with open(args.file, "rb") as f:
f.seek(args.offset)
f.seek(offset)
script = ScriptDSLDisassembler(f, "", {}, 0x978DE0, INCLUDES_NEEDED, INCLUDED)
@ -1317,5 +1326,5 @@ if __name__ == "__main__":
print(script_text, end="")
except UnsupportedScript:
f.seek(args.offset)
f.seek(offset)
print(ScriptDisassembler(f).disassemble(), end="")

View File

@ -22,18 +22,14 @@ parser.add_argument(
action="store_true",
help="use the map file in expected/build/ instead of build/"
)
args = parser.parse_args()
mymap = os.path.join(root_dir, "ver", "current", "build", "papermario.map")
if args.use_expected:
def get_map(expected: bool = False):
mymap = os.path.join(root_dir, "ver", "current", "build", "papermario.map")
if expected:
mymap = os.path.join(root_dir, "ver", "current", "expected", "build", "papermario.map")
return mymap
if not os.path.isfile(mymap):
print(f"{mymap} must exist.")
exit(1)
def search_address(target_addr):
def search_address(target_addr, map=get_map()):
is_ram = target_addr & 0x80000000
ram_offset = None
prev_ram = 0
@ -42,7 +38,7 @@ def search_address(target_addr):
cur_file = "<no file>"
prev_file = cur_file
prev_line = ""
with open(mymap) as f:
with open(map) as f:
for line in f:
if "load address" in line:
# Ignore .bss sections if we're looking for a ROM address
@ -88,12 +84,11 @@ def search_address(target_addr):
return "at end of rom?"
def search_symbol(target_sym):
def search_symbol(target_sym, map=get_map()):
ram_offset = None
cur_file = "<no file>"
prev_line = ""
with open(mymap) as f:
with open(map) as f:
for line in f:
if "load address" in line:
ram = int(line[16 : 16 + 18], 0)
@ -127,11 +122,19 @@ def search_symbol(target_sym):
return None
if __name__ == "__main__":
args = parser.parse_args()
try:
map = get_map(args.use_expected)
if not os.path.isfile(map):
print(f"{map} must exist.")
exit(1)
try:
target_addr = int(args.name, 0)
print(args.name, "is", search_address(target_addr))
except ValueError:
except ValueError:
sym_info = search_symbol(args.name)
if sym_info is not None:
sym_rom = sym_info[0]
@ -139,4 +142,4 @@ except ValueError:
sym_ram = sym_info[2]
print(f"Symbol {args.name} (RAM: 0x{sym_ram:08X}, ROM: 0x{sym_rom:06X}, {sym_file})")
else:
print(f"Symbol {args.name} not found in map file {mymap}")
print(f"Symbol {args.name} not found in map file {map}")