1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2024-11-13 04:39:36 +00:00

Delete old bootstrap tools (#1590)

* Delete old bootstrap tools

* Restore find_unused_asm.sh
This commit is contained in:
cadmic 2023-12-10 16:05:37 -08:00 committed by GitHub
parent 0ed57f61b7
commit b2f596faca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 0 additions and 1872 deletions

View file

@ -1,69 +0,0 @@
import os
class FileEntry:
def __init__(self, nFuncName):
self.funcName = nFuncName
self.lines = list()
def ReadAllLines(filename):
with open(filename) as f:
lines = f.read().splitlines()
return lines;
def WriteAllLines(filename, lines):
with open(filename, 'w') as f:
for item in lines:
f.write("%s\n" % item)
return lines;
if not os.path.exists("asm"):
os.makedirs("asm")
if not os.path.exists("c"):
os.makedirs("c")
dirs = os.listdir("asm")
for directory in dirs:
if (os.path.isdir("asm//" + directory)):
continue
print("Processing asm//" + directory)
folderName = os.path.splitext(directory)[0]
lines = ReadAllLines("asm//" + directory)
functions = list()
currentFunction = None
for line in lines:
if (line.startswith("glabel")):
if (currentFunction != None):
functions.insert(len(functions), currentFunction)
currentFunction = FileEntry(line.split("glabel ")[1])
if (currentFunction != None):
currentFunction.lines.insert(len(currentFunction.lines), line)
if (currentFunction != None):
functions.insert(len(functions), currentFunction)
if not os.path.exists("asm//" + folderName):
os.makedirs("asm//" + folderName)
for func in functions:
WriteAllLines("asm//" + folderName + "//" + func.funcName + ".s", func.lines)
cLines = list()
cLines.insert(len(cLines), "#include <ultra64.h>")
cLines.insert(len(cLines), "#include <global.h>\n")
for func in functions:
cLines.insert(len(cLines), "#pragma GLOBAL_ASM(\"asm/non_matchings/code/" + folderName + "/" + func.funcName + ".s\")\n")
WriteAllLines("c//" + folderName + ".c", cLines)
print("Done!")

View file

@ -1,218 +0,0 @@
#!/usr/bin/python3
import os
import sys
import re
from disassemble import get_z_name
script_dir = os.path.dirname(os.path.realpath(__file__))
root_dir = script_dir + "/../"
data_dir = root_dir + "data/overlays/actors"
asm_dir = root_dir + "asm/non_matchings/overlays/actors"
src_dir = root_dir + "src/overlays/actors"
include_dir = root_dir + "include"
indent = " "
to_rename = []
with open(os.path.join(include_dir, "z64actor.h")) as f:
z64actor_text = f.read()
with open(os.path.join(include_dir, "z64object.h")) as f:
z64object_text = f.read()
def get_actor_id_name(actor_id):
matches = re.findall(actor_id + " .*\n", z64actor_text)
if len(matches) == 0:
return "0x" + actor_id
match = matches[-1]
match = match.replace(",", "").strip().split(" ")[-1]
return match
def get_actor_type_name(actor_type):
matches = re.findall(actor_type + " .*\n", z64actor_text)
for m in matches:
if "ACTORCAT" in m:
match = m.replace(",", "").strip().split(" ")[-1]
return match
return "0x" + actor_type
def get_object_id_name(object_id):
matches = re.findall(object_id + " .*\n", z64object_text)
if len(matches) == 0:
return "0x" + object_id
match = matches[-1]
match = match.replace(",", "").strip().split(" ")[-1]
return match
def create_struct(name, size):
ret = "typedef struct\n{\n" + indent + "/* 0x0000 */ Actor actor;\n"
leftover = int(size, 16) - int("0x14C", 16)
if leftover > 0:
ret += indent + "/* 0x014C */ char unk_14C[0x" + hex(leftover).upper()[2:] + "];\n"
ret += "} " + name + "; // size = 0x" + size + "\n"
return ret
def rename():
# Filenames first
for root, dirs, files in os.walk(root_dir):
for file in files:
for elem in to_rename:
if elem[0] in file:
new_file = file.replace(elem[0], elem[1])
file_path = os.path.join(root, file)
new_file_path = os.path.join(root, new_file)
os.rename(file_path, new_file_path)
# File contents
for root, dirs, files in os.walk(root_dir):
for file in files:
if file.endswith(".c") or file.endswith(".s"):
file_path = os.path.join(root, file)
with open(file_path) as f:
file_text = f.read()
new_file_text = file_text
for elem in to_rename:
# if "func_" in elem[0]:
# new_file_text = new_file_text.replace("glabel " + elem[0], elem[1] + ":")
new_file_text = new_file_text.replace(elem[0], elem[1])
if new_file_text != file_text:
with open(file_path, "w", newline="\n") as f:
f.write(new_file_text)
def bootstrap(ovl_path, ovl_text):
path_split = ovl_path.split(os.path.sep)
z_name = path_split[-1][:-2]
ovl_name = path_split[-2]
init_vars_name = ovl_name[4:] + "_InitVars"
with open(os.path.join(data_dir, z_name + ".data.s")) as f:
data_text = f.read()
pattern = re.compile("glabel D_........\n .word 0x........, 0x........, 0x........, 0x........\n(\.word func_........\n|\.word 0x00000000\n|\.word Actor_Noop\n){4}")
init_data = pattern.search(data_text)
if init_data is None or len(init_data.regs) == 0:
return ""
init_data = data_text[init_data.regs[0][0]:init_data.regs[0][1]]
lines = init_data.split("\n")
init_var_label = lines[0][7:]
init_func = lines[2][6:]
destroy_func = lines[3][6:]
update_func = lines[4][6:]
draw_func = lines[5][6:]
ovl_shortened = ovl_name.replace("ovl", "").replace("_", "")
init_func_name = ovl_shortened + "_Init"
destroy_func_name = ovl_shortened + "_Destroy"
update_func_name = ovl_shortened + "_Update"
draw_func_name = ovl_shortened + "_Draw"
to_rename.append((init_var_label, init_vars_name))
if init_func != "0x00000000" and init_func != "Actor_Noop":
to_rename.append((init_func, init_func_name))
if destroy_func != "0x00000000" and destroy_func != "Actor_Noop":
to_rename.append((destroy_func, destroy_func_name))
if update_func != "0x00000000" and update_func != "Actor_Noop":
to_rename.append((update_func, update_func_name))
if draw_func != "0x00000000" and draw_func != "Actor_Noop":
to_rename.append((draw_func, draw_func_name))
init_var_data = lines[1]
init_data = init_var_data[7:53].replace("0x", "").split(", ")
actor_id = init_data[0][0:4]
actor_type = init_data[0][4:6]
room = init_data[0][6:8]
flags = init_data[1]
object_id = init_data[2][0:4]
struct_size = init_data[3][4:8]
actor_id_name = get_actor_id_name(actor_id)
actor_type_name = get_actor_type_name(actor_type)
object_id_name = get_object_id_name(object_id)
struct_name = ovl_shortened
struct_text = create_struct(struct_name, struct_size)
defines = "#define ROOM 0x" + room + "\n#define FLAGS 0x" + flags + "\n"
decs = ""
if init_func != "0x00000000" and init_func != "Actor_Noop":
decs += "void " + init_func_name + "(" + struct_name + "* this, PlayState* play);\n"
if destroy_func != "0x00000000" and destroy_func != "Actor_Noop":
decs += "void " + destroy_func_name + "(" + struct_name + "* this, PlayState* play);\n"
if update_func != "0x00000000" and update_func != "Actor_Noop":
decs += "void " + update_func_name + "(" + struct_name + "* this, PlayState* play);\n"
if draw_func != "0x00000000" and draw_func != "Actor_Noop":
decs += "void " + draw_func_name + "(" + struct_name + "* this, PlayState* play);\n"
init_vars = "ActorInit " + init_vars_name + " =\n{\n"
init_vars += indent + actor_id_name + ",\n"
init_vars += indent + actor_type_name + ",\n"
init_vars += indent + "ROOM,\n" + indent + "FLAGS,\n"
init_vars += indent + object_id_name + ",\n"
init_vars += indent + "sizeof(" + struct_name + "),\n"
if init_func == "0x00000000":
init_vars += indent + "NULL,\n"
elif init_func == "Actor_Noop":
init_vars += indent + "(ActorFunc)Actor_Noop,\n"
else:
init_vars += indent + "(ActorFunc)" + init_func_name + ",\n"
if destroy_func == "0x00000000":
init_vars += indent + "NULL,\n"
elif destroy_func == "Actor_Noop":
init_vars += indent + "(ActorFunc)Actor_Noop,\n"
else:
init_vars += indent + "(ActorFunc)" + destroy_func_name + ",\n"
if update_func == "0x00000000":
init_vars += indent + "NULL,\n"
elif update_func == "Actor_Noop":
init_vars += indent + "(ActorFunc)Actor_Noop,\n"
else:
init_vars += indent + "(ActorFunc)" + update_func_name + ",\n"
if draw_func == "0x00000000":
init_vars += indent + "NULL,\n"
elif draw_func == "Actor_Noop":
init_vars += indent + "(ActorFunc)Actor_Noop,\n"
else:
init_vars += indent + "(ActorFunc)" + draw_func_name + ",\n"
init_vars += "};\n"
return struct_text + "\n" + defines + "\n" + decs + "\n/*\n" + init_vars + "*/"
def main():
for root, dirs, files in os.walk(src_dir):
for file in files:
if file.endswith(".c"):
file_path = os.path.join(root, file)
with open(file_path) as f:
file_text = f.read()
brace_count = file_text.count("{")
if brace_count == 0:
bootstrap_text = bootstrap(file_path, file_text)
if bootstrap_text != "":
newline_spot = file_text.find("\n\n") + 1
newfile_text = file_text[:newline_spot] + "\n" + bootstrap_text + file_text[newline_spot:]
newfile_text = newfile_text.replace("\n\n\n\n\n", "\n")
with open(file_path, "w", newline="\n") as f:
f.write(newfile_text)
else:
dog = 5
rename()
main()

View file

@ -1,196 +0,0 @@
#!/usr/bin/python3
import os
import sys
import re
script_dir = os.path.dirname(os.path.realpath(__file__))
root_dir = script_dir + "/../"
data_dir = root_dir + "data/overlays/effects"
asm_dir = root_dir + "asm/non_matchings/overlays/effects"
src_dir = root_dir + "src/overlays/effects"
include_dir = root_dir + "include"
indent = " "
effect_enum = [
"EFFECT_SS_DUST",
"EFFECT_SS_KIRAKIRA",
"EFFECT_SS_BOMB",
"EFFECT_SS_BOMB2",
"EFFECT_SS_BLAST",
"EFFECT_SS_G_SPK",
"EFFECT_SS_D_FIRE",
"EFFECT_SS_BUBBLE",
"EFFECT_SS_UNSET",
"EFFECT_SS_G_RIPPLE",
"EFFECT_SS_G_SPLASH",
"EFFECT_SS_G_MAGMA",
"EFFECT_SS_G_FIRE",
"EFFECT_SS_LIGHTNING",
"EFFECT_SS_DT_BUBBLE",
"EFFECT_SS_HAHEN",
"EFFECT_SS_STICK",
"EFFECT_SS_SIBUKI",
"EFFECT_SS_SIBUKI2",
"EFFECT_SS_G_MAGMA2",
"EFFECT_SS_STONE1",
"EFFECT_SS_HITMARK",
"EFFECT_SS_FHG_FLASH",
"EFFECT_SS_K_FIRE",
"EFFECT_SS_SOLDER_SRCH_BALL",
"EFFECT_SS_KAKERA",
"EFFECT_SS_ICE_PIECE",
"EFFECT_SS_EN_ICE",
"EFFECT_SS_FIRE_TAIL",
"EFFECT_SS_EN_FIRE",
"EFFECT_SS_EXTRA",
"EFFECT_SS_FCIRCLE",
"EFFECT_SS_DEAD_DB",
"EFFECT_SS_DEAD_DD",
"EFFECT_SS_DEAD_DS",
"EFFECT_SS_DEAD_SOUND",
"EFFECT_SS_ICE_SMOKE",
]
to_rename = []
def get_regs_enum(short_name):
upper_name = short_name.upper()
return \
"typedef enum {\n" + \
indent + "/* 0x00 */ SS_" + upper_name + "_0,\n" + \
indent + "/* 0x01 */ SS_" + upper_name + "_1,\n" + \
indent + "/* 0x02 */ SS_" + upper_name + "_2,\n" + \
indent + "/* 0x03 */ SS_" + upper_name + "_3,\n" + \
indent + "/* 0x04 */ SS_" + upper_name + "_4,\n" + \
indent + "/* 0x05 */ SS_" + upper_name + "_5,\n" + \
indent + "/* 0x06 */ SS_" + upper_name + "_6,\n" + \
indent + "/* 0x07 */ SS_" + upper_name + "_7,\n" + \
indent + "/* 0x08 */ SS_" + upper_name + "_8,\n" + \
indent + "/* 0x09 */ SS_" + upper_name + "_9,\n" + \
indent + "/* 0x0A */ SS_" + upper_name + "_A,\n" + \
indent + "/* 0x0B */ SS_" + upper_name + "_B,\n" + \
indent + "/* 0x0C */ SS_" + upper_name + "_C,\n" + \
"} " + "EffectSs" + short_name + "Regs;\n"
def bootstrap(ovl_path, ovl_text):
path_split = ovl_path.split(os.path.sep)
z_name = path_split[-1][:-2]
ovl_name = path_split[-2]
short_name = ovl_name[14:]
init_vars_name = ovl_name[4:] + "_InitVars"
top_comment = "/*\n * File: " + z_name + ".c" \
"\n * Overlay: " + ovl_name + "\n * Description:\n */\n"
header_include = "#include \"" + z_name + ".h\"\n"
regs_enum = get_regs_enum(short_name)
with open(os.path.join(data_dir, z_name + ".data.s")) as f:
data_text = f.read()
pattern = re.compile("glabel " + init_vars_name +
"\n.word 0x........\n\.word func_........\n")
init_data = pattern.search(data_text)
if init_data is None or len(init_data.regs) == 0:
return ""
init_data = data_text[init_data.regs[0][0]:init_data.regs[0][1]]
lines = init_data.split("\n")
effect_id = int(lines[1][6:], 16)
init_func = lines[2][6:]
ovl_shortened = ovl_name.replace("ovl", "").replace("_", "")
init_func_name = ovl_shortened + "_Init"
ovl_text = ovl_text.replace(init_func, init_func_name)
to_rename.append((init_func, init_func_name))
effect_id_name = effect_enum[effect_id]
struct_text = "/*\nEffectSsInit " + init_vars_name + \
" = {\n" + indent + effect_id_name + \
",\n" + indent + init_func_name + ",\n};\n*/"
decs = "u32 " + init_func_name + \
"(PlayState* play, u32 index, EffectSs* this, void* initParamsx);\n"
decs += "void " + \
init_func_name[:-4] + \
"Draw(PlayState* play, u32 index, EffectSs* this);\n"
decs += "void " + \
init_func_name[:-4] + \
"Update(PlayState* play, u32 index, EffectSs* this);\n"
insert_pos = ovl_text.find("global.h>\n")
return top_comment + "\n" + header_include + "\n" + regs_enum + "\n" + decs + "\n" + struct_text + "\n" + ovl_text[insert_pos + 10:]
def get_header(header_path):
path_split = header_path.split(os.path.sep)
ovl_name = path_split[-2]
short_name = ovl_name[14:]
init_vars_name = "".join(ovl_name[4:].split("_")) + "InitParams"
ifndef = "#ifndef _Z_EFF_SS_" + short_name.upper() + "_H_\n" + \
"#define _Z_EFF_SS_" + short_name.upper() + "_H_\n\n"
includes = "#include <ultra64.h>\n#include <global.h>\n\n"
struct = "typedef struct {\n" + \
indent + "/* 0x00 */ Vec3f pos;\n" + \
indent + "/* 0x0C */ Vec3f velocity;\n" + \
indent + "/* 0x18 */ Vec3f accel;\n" + \
"} " + init_vars_name + "; // size = 0x\n\n#endif\n"
return ifndef + includes + struct
def rename():
# Filenames first
for root, dirs, files in os.walk(root_dir):
for file in files:
for elem in to_rename:
if elem[0] in file:
new_file = file.replace(elem[0], elem[1])
file_path = os.path.join(root, file)
new_file_path = os.path.join(root, new_file)
os.rename(file_path, new_file_path)
# File contents
for root, dirs, files in os.walk(root_dir):
for file in files:
if file.endswith(".c") or file.endswith(".s"):
file_path = os.path.join(root, file)
with open(file_path) as f:
file_text = f.read()
new_file_text = file_text
for elem in to_rename:
# if "func_" in elem[0]:
# new_file_text = new_file_text.replace("glabel " + elem[0], elem[1] + ":")
new_file_text = new_file_text.replace(elem[0], elem[1])
if new_file_text != file_text:
with open(file_path, "w", newline="\n") as f:
f.write(new_file_text)
def main():
for root, dirs, files in os.walk(src_dir):
for file in files:
if file.endswith(".c"):
file_path = os.path.join(root, file)
with open(file_path) as f:
file_text = f.read()
brace_count = file_text.count("{")
if brace_count == 0:
if "dead" in file_path:
dog = 5
header_path = file_path[:-1] + "h"
c_text = bootstrap(file_path, file_text)
header_text = get_header(header_path)
with open(file_path, "w", newline="\n") as f:
f.write(c_text)
with open(header_path, "w", newline="\n") as f:
f.write(header_text)
rename()
main()

View file

@ -1,114 +0,0 @@
#!/usr/bin/python3
import re
import os
from disassemble import get_ovl_dir, get_z_name
script_dir = os.path.dirname(os.path.realpath(__file__))
root_dir = script_dir + "/../"
src_dir = root_dir + "src/overlays/"
asm_dir = root_dir + "asm/non_matchings/overlays/"
def get_overlays_to_bootstrap():
non_decomped_ovls = []
# traverse root directory, and list directories as dirs and files as files
for root, dirs, files in os.walk(asm_dir):
for ovl_name in dirs:
if ovl_name.startswith("ovl_"):
non_decomped_ovls.append(ovl_name)
for root, dirs, files in os.walk(src_dir):
for ovl_name in dirs:
if ovl_name in non_decomped_ovls:
non_decomped_ovls.remove(ovl_name)
return non_decomped_ovls
def create_source_dir(overlay):
overlay_dir = get_ovl_dir(overlay)
full_dir = src_dir + overlay_dir
os.mkdir(full_dir)
c_name = get_z_name(overlay) + ".c"
s_name = get_z_name(overlay) + ".s"
with open(full_dir + c_name, "w", newline="\n") as c_file:
pragma_line = "#pragma GLOBAL_ASM(\"asm/non_matchings/overlays/" + get_ovl_dir(overlay) + s_name + "\")\n"
c_file.write("#include <ultra64.h>\n#include <global.h>\n\n")
c_file.write(pragma_line)
with open(full_dir + "overlay.cfg", "w", newline="\n") as cfg_file:
cfg_file.write(overlay + "\n" + c_name)
def strip_header_from_s(overlay):
s_file_path = asm_dir + get_ovl_dir(overlay) + get_z_name(overlay) + ".s"
beginning_line = -1
with open(s_file_path, "r") as s_file:
s_lines = s_file.readlines()
for i in range(len(s_lines)):
if s_lines[i].startswith("glabel") or s_lines[i].startswith("func_"):
beginning_line = i
break
if beginning_line > -1:
if beginning_line > 10:
for i in range(0, beginning_line):
if s_lines[i].startswith("/*"):
func_name = s_lines[i].split(" ")[2]
func_line = "glabel func_" + func_name + "\n"
s_lines.insert(i, func_line)
beginning_line = i
for i in range(len(s_lines)):
if s_lines[i].startswith("func"):
s_lines[i] = "glabel " + s_lines[i]
s_lines[i] = s_lines[i].replace(":", "")
with open(s_file_path, "w", newline="\n") as s_file:
s_file.writelines(s_lines[beginning_line:])
def manage_overlays_mk(overlay):
with open(root_dir + "overlays.mk", "a", newline="\n") as overlays_file:
overlays_file.write(" src/overlays/" + get_ovl_dir(overlay) + " \\\n")
with open(root_dir + "overlays_asm.mk", "r") as overlays_asm_file:
lines = overlays_asm_file.readlines()
to_remove = " asm/non_matchings/overlays/" + get_ovl_dir(overlay)[:-1] + " \\\n"
lines.remove(to_remove)
with open(root_dir + "overlays_asm.mk", "w", newline="\n") as overlays_asm_file:
overlays_asm_file.writelines(lines)
def manage_spec(overlay):
with open(root_dir + "spec", "r") as spec_file:
spec_text = spec_file.read()
spec_text = spec_text.replace("asm/non_matchings/overlays/" + get_ovl_dir(overlay), "src/overlays/"
+ get_ovl_dir(overlay))
with open(root_dir + "spec", "w", newline="\n") as spec_file:
spec_file.write(spec_text)
def main():
num = 100
i = 0
overlays = get_overlays_to_bootstrap()
for overlay in overlays:
print("Setting up " + overlay)
create_source_dir(overlay)
strip_header_from_s(overlay)
#manage_overlays_mk(overlay)
#manage_spec(overlay)
i += 1
if i >= num:
break
main()

View file

@ -1,71 +0,0 @@
#!/usr/bin/python3
import os
import sys
import re
from disassemble import get_z_name
script_dir = os.path.dirname(os.path.realpath(__file__))
root_dir = script_dir + "/../"
asm_dir = root_dir + "asm/non_matchings/overlays/actors"
src_dir = root_dir + "src/overlays/actors"
include_dir = root_dir + "include"
indent = " "
includes = "#include <ultra64.h>\n#include <global.h>\n\n"
def remove_struct(root, filename):
with open(os.path.join(root, filename)) as f:
c_text = f.read()
struct_start = c_text.find("typedef")
struct_end = c_text.find("#define")
struct = c_text[struct_start:struct_end]
newfile_text = "#include \"" + filename[:-2] + ".h\"" + "\n\n" + c_text[struct_end:]
with open(os.path.join(root, filename), "w", newline="\n") as f:
f.write(newfile_text)
return struct
def handle_file(root, filename):
guard_name = "_" + filename[:-2].upper() + "_H_"
top_guard = "#ifndef " + guard_name + "\n#define " + guard_name + "\n\n"
header_text = top_guard
header_text += includes
struct = remove_struct(root, filename)
header_text += struct
u_split = filename[:-2].split("_")
init_vars_name = ""
for part in u_split[1:]:
init_vars_name += part[0].upper()
if len(part) > 1:
init_vars_name += part[1:]
init_vars_name += "_"
init_vars_name += "InitVars"
header_text += "extern ActorInit " + init_vars_name + ";\n\n"
header_text += "#endif\n"
with open(os.path.join(root, filename[:-2] + ".h"), "w", newline="\n") as f:
f.write(header_text)
def main():
for root, dirs, files in os.walk(src_dir):
for filename in files:
if filename.endswith(".c"):
file_path = os.path.join(root, filename)
with open(file_path) as f:
file_text = f.read()
brace_count = file_text.count("{")
if brace_count == 2:
handle_file(root, filename)
dog = 5
main()

View file

@ -1,136 +0,0 @@
#!/usr/bin/python3
import os
import re
import shutil
import subprocess
atom_path = "/mnt/c/Users/Ethan/Documents/GitHub/MasterOcarina/Atom/bin/Release/netcoreapp3.0"
atom_cmd = "Atom df oot DBGMQ baserom.z64 --mips-to-c -f"
script_dir = os.path.dirname(os.path.realpath(__file__))
def load_symbols():
ret = {}
with open(script_dir + "/overlayhelpers/batchdisasm/symbols.txt") as f:
symbol_text = f.readlines()
for line in symbol_text:
if len(line.strip()) > 0:
line_split = line.split(" ")
ret[line_split[0]] = line_split[1]
return ret
symbols = load_symbols()
def get_overlays_to_disassemble():
all_overlays = {}
# traverse root directory, and list directories as dirs and files as files
for root, dirs, files in os.walk("baserom"):
for file in files:
if file.startswith("ovl_"):
all_overlays[file] = os.path.getsize(os.path.join(root, file))
non_disassembled_ovls = all_overlays.copy()
for root, dirs, files in os.walk("asm/overlays"):
for ovl_name in dirs:
if ovl_name in non_disassembled_ovls:
non_disassembled_ovls.pop(ovl_name)
for root, dirs, files in os.walk("src/overlays"):
for ovl_name in dirs:
if ovl_name in non_disassembled_ovls:
non_disassembled_ovls.pop(ovl_name)
print("Found " + str(len(non_disassembled_ovls)) + " non-disassembled overlays out of " + str(len(all_overlays))
+ " total")
return {k: v for k, v in sorted(non_disassembled_ovls.items(), key=lambda item: item[1])}
def disassemble(overlay):
args = atom_cmd.split(" ")
args.append(overlay)
# subprocess.run(args, cwd=atom_path, shell=True)
with open(atom_path + "/O/DBGMQ/" + overlay + ".txt") as f:
return f.read()
def fix_symbols(assembly):
for symbol in symbols:
assembly = assembly.replace(symbol, symbols[symbol])
return assembly
def get_ovl_dir(overlay):
actors_overrides = ['ovl_player_actor']
ovl_part = "/" + overlay + "/"
category = "actors"
if overlay.startswith("ovl_Effect"):
category = "effects"
if overlay[4:5].islower():
category = "gamestates"
if 'data' in overlay:
category = "data"
if overlay in actors_overrides:
category = "actors"
return category + ovl_part
def create_asm_dir(overlay, assembly):
asm_dir = "asm/non_matchings/overlays/" + get_ovl_dir(overlay)
shutil.rmtree(asm_dir)
os.mkdir(asm_dir)
with open(asm_dir + get_z_name(overlay) + ".s", "w", newline="\n") as f:
f.write(assembly)
def get_z_name(overlay):
# Annoying edge case
if overlay == 'ovl_Effect_Ss_Solder_Srch_Ball':
return 'z_eff_ss_solder_srch_ball'
if overlay == "ovl_player_actor":
return "z_player"
ret = overlay.lower()
ret = "z_" + ret[4:]
return ret
def patch_spec(overlay):
with open("spec", "r+", newline="\n") as f:
spec = f.read()
spec = re.sub("build/baserom/" + overlay + ".o",
"build/asm/overlays/" + get_ovl_dir(overlay) + get_z_name(overlay) + ".o",
spec)
f.seek(0)
f.write(spec)
f.truncate()
def patch_overlays_asm_mk(overlay):
with open("overlays_asm.mk", "a", newline="\n") as f:
f.write(" asm/overlays/" + get_ovl_dir(overlay)[:-1] + " \\\n")
def main():
print("Beginning disassembly in the order of filesize, ascending")
overlays = get_overlays_to_disassemble()
for overlay in overlays:
print("\t" + overlay)
assembly = disassemble(overlay)
assembly = fix_symbols(assembly)
create_asm_dir(overlay, assembly)
patch_spec(overlay)
patch_overlays_asm_mk(overlay)

View file

@ -1,53 +0,0 @@
#!/usr/bin/python3
import os
import sys
import re
from disassemble import get_z_name
script_dir = os.path.dirname(os.path.realpath(__file__))
root_dir = script_dir + "/../"
src_dir = root_dir + "src/overlays/"
asm_dir = root_dir + "asm/non_matchings/overlays/"
def handle_actor_line(match):
match = match.group()
base_portion = match[23:-4]
base_portion_split = base_portion.split("/")
if len(base_portion_split) < 3:
return match
ret = match
base_name = "build/data/overlays/" + base_portion_split[1] + "/" + base_portion_split[3]
data_path = base_name + ".data.o"
rodata_path = base_name + ".rodata.o"
bss_path = base_name + ".bss.o"
reloc_path = base_name + ".reloc.o"
if os.path.exists(root_dir + data_path):
ret += " include \"" + data_path + "\"\n"
if os.path.exists(root_dir + rodata_path):
ret += " include \"" + rodata_path + "\"\n"
if os.path.exists(root_dir + bss_path):
ret += " include \"" + bss_path + "\"\n"
if os.path.exists(root_dir + reloc_path):
ret += " include \"" + reloc_path + "\"\n"
return ret
def main():
with open(root_dir + "spec") as spec_file:
spec_text = spec_file.read()
spec_text_replaced = re.sub(".*ovl_.*\.o.*\n", handle_actor_line, spec_text)
with open(root_dir + "spec", "w", newline="\n") as spec_file:
spec_file.write(spec_text_replaced)
main()

View file

@ -1,86 +0,0 @@
#!/usr/bin/python3
import os
import sys
import re
from disassemble import get_z_name
script_dir = os.path.dirname(os.path.realpath(__file__))
root_dir = script_dir + "/../"
src_dir = root_dir + "src/overlays/"
asm_dir = root_dir + "asm/non_matchings/overlays/"
def remove_empty_lines_after_glabel(file_text):
file_lines = file_text.splitlines()
last_glabel = False
to_remove = []
for i, line in enumerate(file_lines):
if "glabel" in line:
last_glabel = True
continue
if last_glabel and not line.strip():
to_remove.append(i)
last_glabel = False
if len(to_remove) > 0:
for line_num in reversed(to_remove):
del file_lines[line_num]
file_text = "\n".join(file_lines)
return file_text
def remove_balign_after_float(file_text):
file_lines = file_text.splitlines()
last_float = False
to_remove = []
for i, line in enumerate(file_lines):
if ".float" in line:
last_float = True
continue
if last_float and line == " .balign 4":
to_remove.append(i)
last_float = False
if len(to_remove) > 0:
for line_num in reversed(to_remove):
del file_lines[line_num]
file_text = "\n".join(file_lines)
return file_text
def format_file(file_path):
with open(file_path) as f:
orig_file_text = f.read()
file_text = orig_file_text
# Condense 2+ empty lines to 1
file_text = file_text.replace("\n\n\n+", "\n\n")
# Remove empty lines after section declarations
file_text = file_text.replace(".rdata\n\n", ".rdata\n")
file_text = file_text.replace(".late_rodata\n\n", ".late_rodata\n")
file_text = file_text.replace(".text\n\n", ".text\n")
# Remove dumb empty lines after glabel
file_text = remove_empty_lines_after_glabel(file_text)
# Remove dumb balign 4 lines after float
file_text = remove_balign_after_float(file_text)
# Make sure there's only one empty line at the end
file_text = file_text.rstrip("\n") + "\n"
if file_text != orig_file_text:
with open(file_path, "w", newline="\n") as f:
f.write(file_text)
return True
return False
def main():
for root, dirs, files in os.walk(asm_dir):
for f in files:
if f.endswith(".s"):
format_file(os.path.join(root, f))
main()

View file

@ -1,203 +0,0 @@
#!/usr/bin/python3
import os
#import pprint
import re
import argparse
import math
script_dir = os.path.dirname(os.path.realpath(__file__))
root_dir = script_dir + "/../"
asm_dir = root_dir + "asm/non_matchings/overlays/actors"
build_dir = root_dir + "build/src/overlays/actors"
def get_num_instructions(f_path):
with open(f_path) as f:
f_lines = f.readlines()
sum = 0
for line in f_lines:
if line.startswith("/* "):
sum += 1
return sum
def count_non_matching():
overlays = {}
for root, dirs, _ in os.walk(asm_dir):
for actor_dir in dirs:
total_size = 0
max_size = -1
ovl_path = os.path.join(root, actor_dir)
num_files = 0
actor_funcs = {}
for f_name in os.listdir(ovl_path):
file_path = os.path.join(ovl_path, f_name)
file_size = get_num_instructions(file_path)
num_files += 1
total_size += file_size
if file_size > max_size:
max_size = file_size
actor_funcs[f_name] = file_size
overlays[actor_dir] = {
"summary": (num_files, max_size, total_size,
total_size / num_files),
"funcs": actor_funcs
}
return overlays
pattern_function = re.compile("^[0-9a-fA-F]+ <(.+)>:")
pattern_switchcase = re.compile("L[0-9a-fA-F]{8}")
def count_builded_funcs_and_instructions(f_path):
f_lines = ""
with open(f_path) as f:
f_lines = f.readlines()
current = ""
funcs = {}
for line in f_lines:
if line.strip() == "":
continue
match_function = pattern_function.match(line)
if match_function:
func_name = match_function.group(1)
if pattern_switchcase.match(func_name):
# this is not a real function tag.
# probably a case from a switch
# for example: <L80979A80>
continue
current = func_name
funcs[current] = 0
elif current != "":
funcs[current] += 1
return funcs
def count_build():
overlays = {}
for root, dirs, _ in os.walk(build_dir):
for actor_dir in dirs:
total_size = 0
max_size = -1
ovl_path = os.path.join(root, actor_dir)
num_files = 0
actor_funcs = {}
for f_name in os.listdir(ovl_path):
if not f_name.endswith(".s"):
continue
if f_name.endswith("_reloc.s"):
continue
file_path = os.path.join(ovl_path, f_name)
funcs = count_builded_funcs_and_instructions(file_path)
if len(funcs) > 0:
num_files += len(funcs)
# round up the file size to a multiple of four.
total_size += math.ceil(sum(funcs.values())/4)*4
max_size = max(max_size, max(funcs.values()))
# merges both dictionaries
actor_funcs = {**actor_funcs, **funcs}
overlays[actor_dir] = {
"summary": (num_files, max_size, total_size,
total_size / num_files),
"funcs": actor_funcs
}
return overlays
def get_list_from_file(filename):
actor_list = []
if filename is not None:
with open(filename) as f:
actor_list = list(map(lambda x: x.strip().split(",")[0], f.readlines()))
return actor_list
def print_csv(overlays, ignored, include_only):
sorted_actors = [(k, v["summary"]) for k, v in overlays.items()]
sorted_actors.sort()
row = "{},{},{},{},{}"
print(row.format("Overlay", "Num files", "Max size", "Total size", "Average size"))
for actor_data in sorted_actors:
name = actor_data[0]
other = actor_data[1]
if name in ignored:
continue
if include_only and name not in include_only:
continue
print(row.format(name, *other))
def print_function_lines(overlays, ignored, include_only):
sorted_actors = []
for k, v in overlays.items():
func_data = []
for func_name, lines in v["funcs"].items():
func_data.append((func_name, lines))
#func_data.sort(key=lambda x: x[1], reverse=True)
sorted_actors.append((k, func_data))
sorted_actors.sort()
row = "{},{},{}"
print(row.format("actor_name", "function_name", "lines"))
for actor_data in sorted_actors:
name = actor_data[0]
func_data = actor_data[1]
if name in ignored:
continue
if include_only and name not in include_only:
continue
for func_name, lines in func_data:
print(row.format(name, func_name, lines))
def main():
description = "Collects actor's functions sizes, and print them in csv format."
epilog = """\
To make a .csv with the data, simply redirect the output. For example:
./tools/get_actor_sizes.py > results.csv
Flags can be mixed to produce a customized result:
./tools/get_actor_sizes.py --function-lines --non-matching > status.csv
./tools/get_actor_sizes.py --non-matching --ignore pull_request.csv > non_matching.csv
./tools/get_actor_sizes.py --non-matching --function-lines --include-only my_reserved.csv > my_status.csv
"""
parser = argparse.ArgumentParser(description=description, epilog=epilog, formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument("--non-matching", help="Collect data of the non-matching actors instead.", action="store_true")
parser.add_argument("--function-lines", help="Prints the size of every function instead of a summary.", action="store_true")
parser.add_argument("--ignore", help="Path to a file containing actor's names. The data of actors in this list will be ignored.")
parser.add_argument("--include-only", help="Path to a file containing actor's names. Only data of actors in this list will be printed.")
args = parser.parse_args()
if args.non_matching:
overlays = count_non_matching()
else:
overlays = count_build()
ignored = get_list_from_file(args.ignore)
include_only = get_list_from_file(args.include_only)
if args.function_lines:
print_function_lines(overlays, ignored, include_only)
else:
print_csv(overlays, ignored, include_only)
main()

View file

@ -1,296 +0,0 @@
"""
Given a code file name (excluding the file extension, e.g. z_view) this script
will attempt to build rodata and late_rodata sections for all of its functions.
Supports overlays and other files as long as the rodata file is formatted
correctly(see files in code for examples of properly formatted rodata sections)
This supports automatically commenting or deleting the rodata file from the
spec and automatic deletion of the rodata file itself (only use if you are sure
it will build afterwards)
Has trouble with rodata that goes unused, and .incbin placement
"""
import re
import os
from os import system, listdir, remove, walk
from os.path import exists, isdir, sep
# FUNCTIONS -----------------------------------------------------------------
"""
Extracts rodata symbols from asm
"""
def asm_syms(asm):
split = re.split("jtbl_|D_",asm)
return [s.partition(")")[0] for s in split[1:len(split)]]
"""
Extracts rodata symbols from rodata
"""
def rodata_syms(rodata):
split = re.split("glabel jtbl_|glabel D_",rodata)
return [s.partition("\n")[0] for s in split[1:len(split)]]
"""
Extracts the symbol from a single rodata block
"""
def rodata_sym(rodata_block):
return (re.split("glabel jtbl_|glabel D_",rodata_block)[1]).split("\n")[0]
"""
Splits rodata into blocks
"""
def rodata_blocks(rodata):
split = rodata.split("glabel")
return ["glabel" + b for b in split[1:len(split)]]
"""
Gets the block size
"""
def rodata_block_size(rodata):
split = rodata.split(" .")
elements = split[1:len(split)]
size = 0
for e in elements:
element_type = e.split(" ")[0]
if element_type == "double":
size += 8
if element_type == "float":
size += 4
if element_type == "word":
size += 4
if element_type == "incbin":
size += int(e.rpartition(", ")[2].split("\n")[0],16)
if element_type == "ascii":
size += len(e.split("\"")[1].split("\"")[0])
if element_type == "asciz":
size += len(e.split("\"")[1].split("\"")[0])
if element_type == "balign":
size += size % int(e.split(" ")[1])
return size
"""
Gets the text size
"""
def text_size(asm):
instructions = [l for l in asm.split("\n") if l.startswith("/* ")]
return 4*(len(instructions)-1)
"""
Gets the rodata-to-text ratio
"""
def late_rodata_ratio(asm,late_rodata_blocks):
total_rodata_size = 0
for b in late_rodata_blocks:
total_rodata_size += rodata_block_size(b)
return total_rodata_size/text_size(asm)
"""
Accepts a single block of rodata and extracts the type
"""
def rodata_type(rodata_block):
first_split = re.split("\s+\.", rodata_block)
return first_split[1].split(" ")[0]
"""
Checks if a block should go in .rdata or .late_rodata
"""
def is_rodata(r):
return (rodata_type(r)=="asciz" or rodata_type=="ascii")
"""
For given asm and rodata files, build a rodata section for the asm file
"""
def build_rodata(asm, rodata):
contained_syms = [s for s in asm_syms(asm) if s in rodata_syms(rodata)]
contained_blocks = [b for b in rodata_blocks(rodata) if rodata_sym(b) in contained_syms]
# TODO include arrays in rodata_list
rodata_list = [r for r in contained_blocks if is_rodata(r)]
return_str = ""
if (len(rodata_list)!=0):
return_str += ".rdata\n"
for r in rodata_list:
return_str += r
late_rodata_list = [r for r in contained_blocks if r not in rodata_list]
if (len(late_rodata_list)!=0):
if late_rodata_ratio(asm,late_rodata_list) > (1/3):
top_sym = rodata_sym(late_rodata_list[0])
if top_sym.endswith("0") or top_sym.endswith("8"):
return_str += ".late_rodata\n.late_rodata_alignment 8\n"
elif top_sym.endswith("4") or top_sym.endswith("C"):
return_str += ".late_rodata\n.late_rodata_alignment 4\n"
else:
return_str += ".late_rodata\n"
for r in late_rodata_list:
return_str += r
return None if return_str=="" else return_str + ("" if return_str.endswith("\n\n") else "\n") + ".text\n"
"""
Gets all file paths contained in a given folder, does not enter subfolders
"""
def get_file_paths(folder_path):
return next(walk(folder_path),(None,None,[]))[2]
"""
Given a path, reads the asm .s file into a single string
"""
def file_read(path):
with open(path, 'r', encoding="utf-8") as infile:
return infile.read()
"""
Writes the rodata section to the start of the file specified by path
"""
def rodata_write(path, section):
with open(path, 'r+', encoding="utf-8", newline="\n") as outfile:
original = outfile.read()
outfile.seek(0,0)
outfile.write(str(section) + original)
"""
Comments out the line in spec associated with the given filenames
"""
def modify_spec(filenames, identifier, delete):
lines = ""
with open("spec", 'r+', encoding="utf-8", newline="\n") as spec:
lines = spec.read().split("\n")
changed = False
files = filenames.split(",")
for filename in files:
eff_filename = filename.lower().replace("effect_", "eff_")
if identifier == "code" and " include \"build/data/" + filename + ".rodata.o\"" in lines:
e = lines.index(" include \"build/data/" + filename + ".rodata.o\"")
if delete:
del lines[e]
else:
lines[e] = " //include \"build/data/" + filename + ".rodata.o\""
changed = True
elif " include \"build/data/overlays/" + identifier + "/z_" + eff_filename + ".rodata.o\"" in lines:
e = lines.index(" include \"build/data/overlays/" + identifier + "/z_" + eff_filename + ".rodata.o\"")
if delete:
del lines[e]
else:
lines[e] = " //include \"build/data/overlays/" + identifier + "/z_" + eff_filename + ".rodata.o\""
changed = True
if changed:
modified = "\n".join(lines)
with open("spec", 'w', encoding="utf-8", newline="\n") as spec:
#spec.seek(0,0)
spec.write(modified)
"""
Processes each individual file
asm\non_matchings\overlays\<identifier>
data\overlays\<identifier>
asm\non_matchings\code\
data\code\
"""
def process_file(filename, identifier, delete_rodata):
folder_path = "asm" + sep + "non_matchings" + sep + ("code" + sep if identifier=="code" else "overlays" + sep + identifier.lower() + sep + "ovl_") + filename + sep
rodata_path = "data" + sep + (sep if identifier=="code" else "overlays" + sep + identifier.lower() + sep + "z_") + filename.lower() + ".rodata.s"
if filename == "player":
folder_path = "asm" + sep + "non_matchings" + sep + "overlays" + sep + "actors" + sep + "ovl_player_actor" + sep
rodata_path = rodata_path.replace("effect_", "eff_")
print("ASM at: " + folder_path)
print("Data at: " + rodata_path)
if not exists(folder_path):
print("Aborting: ASM does not exist")
return
if not exists(rodata_path):
print("Aborting: Data does not exist")
return
files = [folder_path + f for f in get_file_paths(folder_path)]
for asm_file in files:
asm = file_read(asm_file)
print("Found asm file " + asm_file)
if ".rdata" in asm:
print("Skipping: it already has a rodata section")
continue
print("Processing asm file " + asm_file)
section = build_rodata(asm, file_read(rodata_path))
if section is not None:
print("Writing asm file " + asm_file)
rodata_write(asm_file, section)
else: print("Skipping: no rodata to write")
print("Built rodata sections for " + identifier + " file " + filename)
if delete_rodata:
remove(rodata_path)
print("Deleted rodata at " + rodata_path)
"""
Allows files to be provided as comma-separated filenames for batch migration
"""
def process_files(filenames, identifier, spechandle, delete_rodata):
if "," in filenames:
files = filenames.split(",")
for f in files:
process_file(f, identifier, delete_rodata)
else:
process_file(filenames, identifier, delete_rodata)
if spechandle.lower() == "delete":
modify_spec(filenames, identifier, True)
print("Deleted rodata for files in spec")
elif spechandle.lower() == "comment":
result = modify_spec(filenames, identifier, False)
if result:
print("Commented out rodata for files in spec")
"""
Asks what to do about spec and rodata, converts 'all' to comma-separated filenames
"""
def check_spec_rodata(filenames, identifier):
spechandle = input("Delete, Comment or Leave spec? ")
delete_rodata = input("Delete rodata file(s)? (Y/N) ")
if filenames == "all" or "all|" in filenames:
to_remove_list = []
if "all|" in filenames:
print("all| in filenames")
to_remove_list = filenames.split("|")[1]
basedir = "asm" + sep + "non_matchings" + sep + ("code" if identifier=="code" else "overlays" + sep + identifier.lower()) + sep
folder_names = [name.replace("ovl_","") for name in listdir(basedir) if isdir(basedir + name) and name not in to_remove_list]
filenames = ",".join(map(str, folder_names))
print(filenames)
process_files(filenames, identifier, spechandle, delete_rodata == "Y")
"""
Main execution
"""
def run(show_help):
if(show_help):
print("""Usage: Enter 'Code' or 'Overlay' and follow the instructions.
Batch migrate files by entering comma-separated filenames instead of a single filename.
Migrate all files by entering 'all' for filenames. Exclude files from all with all| followed by comma-separated filenames Use at your own risk.
Enter 'q' to the code or overlay question to quit.""")
code_or_overlay = input("Code or Overlay? ")
if(code_or_overlay == "q"):
return
if(code_or_overlay == "Code"):
filename = input("Enter the code file name(s) (excluding .c) or all: ")
check_spec_rodata(filename, "code")
elif(code_or_overlay == "Overlay"):
overlay_type = input("Actor, Effect or Gamestate? ")
if(overlay_type == "Actor"):
filename = input("Enter the actor name(s) (excluding ovl_ or z_, ex. obj_bombiwa) or all: ")
check_spec_rodata(filename, "actors")
elif(overlay_type == "Effect"):
filename = input("Enter the effect name(s) (excluding ovl_ or z_, ex. effect_ss_bomb) or all: ")
check_spec_rodata(filename, "effects")
elif(overlay_type == "Gamestate"):
filename = input("Enter the gamestate name(s) (excluding ovl_ or z_, ex. kaleido_scope) or all: ")
check_spec_rodata(filename, "gamestates")
run(True)
# PROGRAM -------------------------------------------------------------------
run(False)
#bigs = ["Boss_Ganon", "Boss_Ganondrof","En_Wf", "Door_Warp1",]
#ovls = ["En_Elf"]
#effects = [x[0] for x in os.walk("src/overlays/effects")][1:]
#for i, ovl in enumerate(effects):
# process_files(ovl.split("/")[-1][4:], "effects", "Delete", True)
# command = "echo >> src/overlays/effects/ovl_" + effects[i] + "/z_" + effects[i].lower() + ".c"
# os.system(command) # purpose of this is to "modify" each C file in order to prevent undefined symbol errors.
# # the new line will be removed by format.sh

View file

@ -1,84 +0,0 @@
#!/usr/bin/python3
import os
import sys
import re
from disassemble import get_z_name
script_dir = os.path.dirname(os.path.realpath(__file__))
root_dir = script_dir + "/../"
data_dir = root_dir + "data/overlays"
asm_dir = root_dir + "asm/non_matchings/overlays"
def rename(old_name, new_name):
for root, dirs, files in os.walk(asm_dir):
for file in files:
file_path = os.path.join(root, file)
with open(file_path) as f:
file_text = f.read()
new_file_text = file_text.replace(old_name, new_name)
if file_text != new_file_text:
with open(file_path, "w", newline="\n") as f:
f.write(new_file_text)
def rename_l(old_name, new_name):
for root, dirs, files in os.walk(asm_dir):
for file in files:
file_path = os.path.join(root, file)
with open(file_path) as f:
file_text = f.read()
new_file_text = file_text.replace(old_name + ":", "glabel " + new_name)
new_file_text = new_file_text.replace(old_name, new_name)
if file_text != new_file_text:
with open(file_path, "w", newline="\n") as f:
f.write(new_file_text)
def handle_jtbl(match):
match = match.group()
split = match.replace(":", "").split(" ")
lbl_name = split[0]
new_lbl_name = "jtbl_" + lbl_name[2:]
rename(lbl_name, new_lbl_name)
ret = "glabel " + new_lbl_name + "\n.word .L"
return ret
def handle_data_line(match):
match = match.group()
ret = "glabel " + match[:-1] + "\n"
return ret
def handle_word_l(match):
match = match.group()
split = match.split(" ")
lbl_name = split[1]
new_lbl_name = split[1][1:]
rename_l(lbl_name, new_lbl_name)
ret = ".word " + new_lbl_name
return ret
def main():
preamble = ".include \"macro.inc\"\n\n # assembler directives\n .set noat # allow manual use of $at\n .set noreorder # don't insert nops after branches\n .set gp=64 # allow use of 64-bit general purpose registers\n\n"
for root, dirs, files in os.walk(data_dir):
for file in files:
file_path = os.path.join(root, file)
with open(file_path) as f:
file_text = f.read()
file_text = preamble + file_text
file_text = re.sub("D_.*: .word .L", handle_jtbl, file_text)
file_text = re.sub("D_.*:", handle_data_line, file_text)
file_text = re.sub(".word .L........", handle_word_l, file_text)
file_text = re.sub("\n\n ", "\n ", file_text)
with open(file_path, "w", newline="\n") as f:
f.write(file_text)
main()

View file

@ -1,55 +0,0 @@
import os
import sys
specFile = open("spec", "r");
specText = specFile.read();
specFile.close()
specLines = specText.split("\n");
# TODO: CLEAN THIS UP!
for i in range(0, len(specLines)):
line = specLines[i]
if (line.startswith("INCLUDE_SEG_SCENE")):
params = line.split("(")[1].split(")")[0].split(",")
for j in range(0, len(params)):
while (params[j].startswith(" ")):
params[j] = params[j][1 : len(params[j])]
line = "beginseg\r\n";
line += "\tname " + params[0] + "\r\n";
line += "\tromalign 0x1000\r\n";
line += "\tinclude " + params[1] + "\r\n";
line += "\taddress SEGMENT_SCENE\r\n";
line += "endseg\r\n";
elif (line.startswith("INCLUDE_SEG_ROOM")):
params = line.split("(")[1].split(")")[0].split(",")
for j in range(0, len(params)):
while (params[j].startswith(" ")):
params[j] = params[j][1 : len(params[j])]
line = "beginseg\r\n";
line += "\tname " + params[0] + "\r\n";
line += "\tromalign 0x1000\r\n";
line += "\tinclude " + params[1] + "\r\n";
line += "\taddress SEGMENT_ROOM\r\n";
line += "endseg\r\n";
elif (line.startswith("INCLUDE_SEG_OBJECT")):
params = line.split("(")[1].split(")")[0].split(",")
for j in range(0, len(params)):
while (params[j].startswith(" ")):
params[j] = params[j][1 : len(params[j])]
line = "beginseg\r\n";
line += "\tname " + params[0] + "\r\n";
line += "\tromalign 0x1000\r\n";
line += "\tinclude " + params[1] + "\r\n";
line += "\taddress SEGMENT_OBJECT\r\n";
line += "endseg\r\n";
line += "\r\n";
specLines[i] = line;
specOut = open("build/spec_preproc", "w");
specOut.writelines(specLines);
specOut.close();

View file

@ -1,78 +0,0 @@
#!/usr/bin/python3
import os
import sys
import re
from disassemble import get_z_name
script_dir = os.path.dirname(os.path.realpath(__file__))
root_dir = script_dir + "/../"
src_dir = root_dir + "src/overlays/"
asm_dir = root_dir + "asm/non_matchings/overlays/"
def get_c_file_path(file):
c_file = get_z_name(file) + ".c"
for root, dirs, files in os.walk(src_dir):
if c_file in files:
return os.path.join(root, c_file)
return None
def handle_file(asm_root, asm_file, c_file_path):
file_path = os.path.join(asm_root, asm_file)
with open(file_path) as f:
file_lines = f.readlines()
new_files = []
num_rodata = 0
for i, line in enumerate(file_lines):
asm_basename = asm_file.split(".")[0]
if line.startswith("glabel func"):
new_files.append((i, line.split(" ")[1].strip() + ".s", "func"))
elif line.startswith(".section .data"):
new_files.append((i, asm_basename + ".data.s", "data"))
elif line.startswith(".section .rodata"):
type = "rodata"
ext = ".rodata.s"
if num_rodata > 0:
type = "reloc"
ext = ".reloc.s"
num_rodata += 1
new_files.append((i, asm_basename + ext, type))
elif line.startswith(".bss"):
new_files.append((i, asm_basename + ".bss.s", "bss"))
if len(new_files) == 1:
return
os.remove(file_path)
for i, new_file in enumerate(new_files):
if i < len(new_files) - 1:
new_file_lines = file_lines[new_file[0]:new_files[i+1][0]]
else:
new_file_lines = file_lines[new_file[0]:]
with open(os.path.join(asm_root, new_file[1]), mode="w", newline="\n") as out_file:
out_file.writelines(new_file_lines)
os.remove(c_file_path)
pragma_begin = "#pragma GLOBAL_ASM(\"" + asm_root.split("../")[1] + "/"
pragma_end = "\")"
with open(c_file_path, mode="w", newline="\n") as c_file:
for new_file in new_files:
c_file.write(pragma_begin + new_file[1] + pragma_end + "\n\n")
def main():
for root, dirs, files in os.walk(asm_dir):
for file in files:
if file.startswith("z_"):
c_file_path = get_c_file_path(root.split("/")[-1])
if c_file_path is not None:
handle_file(root, file, c_file_path)
main()

View file

@ -1,213 +0,0 @@
#!/usr/bin/python3
import os
import argparse
offsets = set()
replacements = {}
global_name = ''
name_fmt = 'g{0}{1}_{2}'
spec_fmt = ' include "build/assets/objects/{0}/{0}.o"\n number 6\n'
dlist_xml = '<DList Name="{0}" Offset="0x{1}"/>'
collision_xml = '<Collision Name="{0}" Offset="0x{1}"/>'
animation_xml = '<Animation Name="{0}" Offset="0x{1}"/>'
skeleton_xml = '<Skeleton Name="{0}" Type="{2}" LimbType="{3}" Offset="0x{1}"/>'
unknown_xml = '<!-- <{2} Name="{0}" Offset="0x{1}"/> -->'
def set_globals(new_name):
global offsets
global global_name
global replacements
offsets = set()
replacements = {}
global_name = new_name
return 0
def dlist_to_xml(var_name,offset):
return dlist_xml.format(var_name,offset.lstrip('0'))
def collision_to_xml(var_name,offset):
return collision_xml.format(var_name,offset.lstrip('0'))
def animation_to_xml(var_name,offset):
return animation_xml.format(var_name,offset.lstrip('0'))
def skeleton_to_xml(var_name,offset, type):
skel_type = "Flex" if "Flex" in type else "Normal"
limb_type = "Standard"
return skeleton_xml.format(var_name, offset.lstrip('0'), skel_type, limb_type)
def unknown_to_xml(var_name,offset, type):
return unknown_xml.format(var_name,offset.lstrip('0'),type)
def make_xml_line(offset, type):
if 'Gfx' in type:
var_name = name_fmt.format(global_name,'DL',offset)
xml_line = dlist_to_xml(var_name, offset)
elif 'Col' in type:
var_name = name_fmt.format(global_name,'Col',offset)
xml_line = collision_to_xml(var_name, offset)
elif 'Animation' in type:
var_name = name_fmt.format(global_name,'Anim',offset)
xml_line = animation_to_xml(var_name, offset)
elif 'Skeleton' in type:
var_name = name_fmt.format(global_name,'Skel',offset)
xml_line = skeleton_to_xml(var_name, offset, type)
else:
var_name = name_fmt.format(global_name,'Unknown',offset)
xml_line = unknown_to_xml(var_name, offset, type)
print('Unknown type at offset', offset)
replacements['06'+offset] = var_name
return xml_line
def extern_to_xml(line):
global offsets
type = line.split()[1]
sym = line.split()[2]
offset = sym[4:10]
if(offset in offsets):
return ''
else:
offsets.add(offset)
xml_line = ' ' * 8
xml_line += make_xml_line(offset, type)
# make_replace(offset, type)
return xml_line + '\n'
def find_type(srcdata, i):
j = i
while(j >= 0 and ' = {' not in srcdata[j]):
j -= 1
if(j < 0):
return 'UNKNOWN'
else:
return srcdata[j].split(' = {')[0].split()[-2]
def other_to_xml(srcdata, i):
xml_data = ''
line = srcdata[i]
index = line.find('0x060')
while(index < len(line) and '0x060' in line[index:]):
offset = line[index+4:index+10]
type = find_type(srcdata, i)
if(offset not in offsets):
offsets.add(offset)
xml_data += ' ' * 8 + make_xml_line(offset, type) + '\n'
# make_replace(offset, type)
index += line[index+10:].find('0x060') + 10
return xml_data
def find_object(src):
with open(src,'r',encoding='utf-8') as srcfile:
srcdata = srcfile.readlines()
for i, line in enumerate(srcdata):
if 'OBJECT_' in line and ' FLAGS,' in srcdata[i-1]:
object = line.strip().strip(',')
return object.lower()
print('Object not found in', src)
object = ''
return object
def create_xml(src, name):
set_globals(name)
with open(src,'r',encoding='utf-8') as srcfile:
srcdata = srcfile.readlines()
object = find_object(src)
xml = '<Root>\n <File Name="' + object + '" Segment="6">\n'
symbols = {}
for i, line in enumerate(srcdata):
if '0x060' in line or 'D_060' in line:
if 'extern' in line:
xml += extern_to_xml(line)
elif '0x060' in line:
xml += other_to_xml(srcdata, i)
xml += ' </File>\n</Root>\n'
return xml
def add_header(src):
object = find_object(src)
if(object == ''):
return 0
with open(src,'r', encoding='utf-8') as srcfile:
srcdata = srcfile.readlines()
for i, line in enumerate(srcdata):
if('#include' in line):
break
srcdata = srcdata[0:i+1] + ['#include "objects/' + object + '/' + object + '.h"\n'] + srcdata[i+1:]
with open(src,'w',encoding='utf-8', newline = '\n') as outfile:
outfile.writelines(srcdata)
return 1
def replace_src(src):
global replacements
global global_name
add_header(src)
with open(src,'r', encoding='utf-8') as srcfile:
srcdata = srcfile.read()
for key in list(replacements.keys()):
srcdata = srcdata.replace(key, replacements.get(key))
srcdata = srcdata.replace('D_g' + global_name, 'g' + global_name)
if('Gfx' in replacements.get(key)):
srcdata = srcdata.replace('0xg' + global_name, 'g' + global_name)
else:
srcdata = srcdata.replace('0xg' + global_name, '&g' + global_name)
with open(src,'w',encoding='utf-8', newline = '\n') as outfile:
outfile.write(srcdata)
return 1
def fix_spec(src, spec):
object = find_object(src)
fix = False
old = False
with open(spec, 'r') as specfile:
specdata = specfile.readlines()
for i, line in enumerate(specdata):
if ('"' + object + '"') in line:
if 'number' in specdata[i+3]:
old = True
else:
specdata[i+2] = spec_fmt.format(object)
fix = True
break
if old:
print('Already fixed', object, 'in', spec)
return 0
if not fix:
print('Could not find',object,'in', spec)
return -1
with open(spec, 'w', newline='\n') as outfile:
outfile.writelines(specdata)
return 1
parser = argparse.ArgumentParser(description="Generate an xml object file from a source file")
parser.add_argument('file', help="overlay file to generate xml from")
parser.add_argument('name', help='name to use for xml variables')
parser.add_argument('-r',action='store_true', help="replace variables in overlay with the new names")
parser.add_argument('-s',metavar = 'spec', dest = 'spec', help="spec file to update", default=None)
parser.add_argument('-o', metavar = 'outfile', dest = 'outfile', help = 'file to write xml to', default = None)
if __name__ == "__main__":
args = parser.parse_args()
if args.outfile is None:
print(create_xml(args.file, args.name))
else:
with open(args.outfile, 'w', encoding='utf-8',newline='\n') as outfile:
outfile.write(create_xml(args.file, args.name))
if(args.r):
replace_src(args.file)
if(args.spec is not None):
fix_spec(args.file, args.spec)