Optional file disasm (#664)

* Add optional file disasm

* Fix for full
This commit is contained in:
Maide 2022-03-05 13:49:01 +00:00 committed by GitHub
parent 77cfd399d0
commit cf98c4e7e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 205 additions and 175 deletions

View File

@ -18,6 +18,14 @@ parser.add_argument(
default=False,
help="Decompile all files regardless of whether they are used or not",
)
parser.add_argument(
"-files",
"--files",
dest="files",
nargs="+",
required=False,
help="Optional list of files to diassemble separated by a space. This is a whitelist, all files will be skipped besides the ones listed here if used.",
)
args = parser.parse_args()
jobs = args.jobs
@ -26,7 +34,7 @@ ASM_OUT = "asm/"
DATA_OUT = "data/"
def discard_decomped_files(files_spec):
def discard_decomped_files(files_spec, include_files):
root_path = Path(__file__).parent.parent.parent
with open(root_path / "spec", "r") as f:
@ -38,6 +46,12 @@ def discard_decomped_files(files_spec):
for f in files_spec:
name, _, type, _, file_list = f
force_include = False
if include_files:
if not any([x in name for x in include_files]):
continue
force_include = True
# Find the beginseg for this file
i = 0
while i < len(spec):
@ -92,6 +106,7 @@ def discard_decomped_files(files_spec):
if "GLOBAL_ASM" in f2.read():
include = True
include |= force_include
if include:
new_files[offset] = file
included = True
@ -2191,16 +2206,23 @@ for segment in files_spec:
full_file_list[segment[0]] = new
if args.full:
new_spec = []
for segment in files_spec:
if args.files and not any(
[file_name in segment[0] for file_name in args.files]
):
continue
for offset, name in segment[4].items():
if name == "":
name = f"{segment[2]}_{offset:08X}"
segment[4][offset] = name
new_spec.append(segment)
files_spec = new_spec
else:
# Prune
old_file_count = sum([len(f[4].keys()) for f in files_spec])
files_spec = discard_decomped_files(files_spec)
files_spec = discard_decomped_files(files_spec, args.files)
new_file_count = sum([len(f[4].keys()) for f in files_spec])
@ -2413,11 +2435,20 @@ rodata_symbols_regex = re.compile(r"(?<=\n)glabel (.+)(?=\n)")
asm_symbols_regex = re.compile(r"%(?:lo|hi)\((.+?)\)")
# Split files and migrate rodata that should be migrated
for root, dirs, files in os.walk(ASM_OUT):
for f in files:
if "non_matchings" in root:
for file in Path(ASM_OUT).glob("**/*.s"):
asm_path = str(file)
if "non_matchings" in asm_path:
continue
asm_path = os.path.join(root, f)
if file.parts[1] == "overlays":
name = file.parts[2]
else:
name = file.parts[1]
if not any([name == section[-1]["name"] for section in all_sections]):
continue
rodata_path = (
asm_path.replace(ASM_OUT + "overlays/", DATA_OUT)
.replace(ASM_OUT, DATA_OUT)
@ -2533,9 +2564,9 @@ for root, dirs, files in os.walk(ASM_OUT):
# TODO hack: getting the address from a comment
first_block_split = late_rodata[0][1].split(" */ .")
vaddr = None
if first_block_split[1].startswith(
"float"
) or first_block_split[1].startswith("double"):
if first_block_split[1].startswith("float") or first_block_split[
1
].startswith("double"):
vaddr = first_block_split[0].split(" ")[-2]
else:
vaddr = first_block_split[0].split(" ")[-1]
@ -2562,7 +2593,9 @@ for root, dirs, files in os.walk(ASM_OUT):
]:
# hacks for especially badly behaved rodata, TODO these are ALL jumptables associated with
# comparatively tiny functions, can we swat these programmatically?
late_rodata_alignment = f".late_rodata_alignment {'8' if vaddr % 8 == 0 else '4'}\n"
late_rodata_alignment = (
f".late_rodata_alignment {'8' if vaddr % 8 == 0 else '4'}\n"
)
rdata_out = ""
if rdata is not None:
@ -2592,14 +2625,11 @@ for root, dirs, files in os.walk(ASM_OUT):
all_out = rodata_out + text_out
# write it out
out_path = (
root.replace(ASM_OUT, f"{ASM_OUT}/non_matchings/")
+ "/"
+ ((f.replace(".text.s", "") + "/") if "overlays" not in root else "")
)
os.makedirs(out_path, exist_ok=True)
with open(out_path + label + ".s", "w") as outfile:
outfile.write(all_out.strip() + "\n")
out_path = Path(asm_path.replace(ASM_OUT, f"{ASM_OUT}non_matchings/")).parent
if out_path.parts[2] not in ("overlays", "makerom"):
out_path /= file.name.split(".")[0]
out_path.mkdir(parents=True, exist_ok=True)
# remove rodata and unsplit file
# TODO
out_path /= label + ".s"
with open(out_path, "w") as outfile:
outfile.write(all_out.strip() + "\n")