From 9de4cebb799933e60a70780c5daa6fc68f56f9bb Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Wed, 21 Oct 2020 03:10:13 +0100 Subject: [PATCH 01/22] map disassembly --- tools/disasm_map.py | 182 +++++++++++++++++++++++++++++++++++++++++ tools/disasm_script.py | 21 +++-- 2 files changed, 197 insertions(+), 6 deletions(-) create mode 100755 tools/disasm_map.py diff --git a/tools/disasm_map.py b/tools/disasm_map.py new file mode 100755 index 0000000000..a34d4d6c47 --- /dev/null +++ b/tools/disasm_map.py @@ -0,0 +1,182 @@ +#! /usr/bin/python3 + +import sys +import os +import yaml +from struct import unpack +from disasm_script import disassemble as disassemble_script + +def disassemble(bytes, offset, midx, symbol_map = {}, map_name = "map"): + out = "" + found_data = False + + while len(midx) > 0: + struct = midx.pop(0) + name = struct["name"] + if name == "Script_Main": name = f"{map_name}_Main" + + #print(f"{offset:X} ({name}, start = {struct['start']:X}, len = {struct['length']:X})") + + if struct["start"] == offset: + found_data = True + + if struct["start"] != offset: + # end of data / padding + break + + # format struct + if struct["type"].startswith("Script"): + out += disassemble_script(bytes, name, symbol_map) + elif struct["type"] == "Padding": + # nops at end of file + bytes.seek(offset % 4, 1) + return out + elif struct["type"] == "EntryList": + out += f"EntryList {map_name}_entryList = {{" + for i in range(0, struct["length"], 4 * 4): + x,y,z,yaw = unpack(">ffff", bytes.read(4 * 4)) + out += f"\n {{ {x}f, {y}f, {z}f, {yaw}f }}," + out += f"\n}};\n" + elif struct["type"] == "Header": + out += f"MapConfig {map_name}_config = {{\n" + + bytes.read(0x10) + + main,entry_list,entry_count = unpack(">IIi", bytes.read(4 * 3)) + out += f" .main = {map_name}_Main,\n" + out += f" .entryList = {map_name}_entryList,\n" + out += f" .entryCount = {entry_count},\n" + + bytes.read(0x1C) + + bg,tattle = unpack(">II", bytes.read(4 * 2)) + out += f" .background = {'&gBackgroundImage' if bg == 0x80200000 else 'NULL'},\n" + out += f" .tattle = {tattle:X},\n" + + out += f"}};\n" + else: # unknown type of struct + out += f"s32 {name}[] = {{" + for i in range(0, struct["length"], 4): + if (i % 0x20) == 0: + out += f"\n " + + word = int.from_bytes(bytes.read(4), byteorder="big") + + if word in symbol_map: + out += f" {symbol_map[word]}," + else: + out += f" 0x{word:08X}," + + out += f"\n}};\n" + + out += "\n" + elif found_data: + if struct["type"] != "Padding": + # put struct back on list + midx.insert(0, struct) + + # nops at end of file + bytes.seek(offset % 4, 1) + + return out + + if struct["type"] != "Function" and not struct["type"] == "Padding" and not (struct["type"] == "Missing" and not found_data): + offset += struct["length"] + + # end of data + return out + +def parse_midx(file, prefix = ""): + structs = [] + + for line in file.readlines(): + s = line.split("#") + if len(s) == 5: + if s[0] == "$Start": continue + if s[0] == "$End": continue + structs.append({ + "name": prefix + name_struct(s[0]), + "type": s[1], + "start": int(s[2], 16), + "vaddr": int(s[3], 16), + "length": int(s[4], 16), + "end": int(s[2], 16) + int(s[4], 16), + }) + elif "Missing" in s: + start = int(s[1], 16) + end = int(s[2], 16) + vaddr = start + 0x80240000 + structs.append({ + "name": f"{prefix}unk_missing_{vaddr:X}", + "type": "Missing", + "start": start, + "vaddr": vaddr, + "length": end - start, + "end": end, + }) + elif "Padding" in s: + start = int(s[1], 16) + end = int(s[2], 16) + vaddr = start + 0x80240000 + structs.append({ + "name": f"{prefix}__padding__", + "type": "Padding", + "start": start, + "vaddr": vaddr, + "length": end - start, + "end": end, + }) + + structs.sort(key=lambda s: s["start"]) + return structs + +def name_struct(s): + return s[1:].replace("???", "unk") + +if __name__ == "__main__": + if len(sys.argv) == 1: + print("usage: ./disasm_map.py ") + print("Converts split map data into C files using a .midx file from Star Rod.") + exit() + + map_name = os.path.splitext(os.path.basename(sys.argv[1]))[0] + area_name = "area_" + map_name.split("_")[0] + if len(area_name) > 8: + area_name = area_name[:8] + + with open(sys.argv[1], "r") as f: + midx = parse_midx(f, map_name + "_") + + symbol_map = {} + for struct in midx: + symbol_map[struct["vaddr"]] = struct["name"] + + bin_dir = f"bin/world/{area_name}/{map_name}" + src_dir = f"src/world/{area_name}/{map_name}" + + splits = [] + rom_start = 0 + with open(os.path.join(os.path.dirname(__file__), "splat.yaml")) as splat: + splat = yaml.safe_load(splat) + + for segment in splat["segments"]: + if type(segment) == dict and segment.get("name") == f"world/{area_name}/{map_name}/": + rom_start = segment.get("start", 0) + splits = segment.get("files", []) + continue + if len(splits) == 0: + print(f"unable to find {map_name} in splat.yaml") + exit(1) + + # advance to the EntryList (start of data) + while midx[0]["type"] != "EntryList": + midx.pop(0) + + for split in splits: + rom_addr = split[0] + filetype = split[1] + + if filetype == "bin": + with open(f"{bin_dir}/{rom_addr:X}.bin", "rb") as bytes: + print(f"// {rom_addr:X}") + print(disassemble(bytes, rom_addr - rom_start, midx, symbol_map, map_name)) diff --git a/tools/disasm_script.py b/tools/disasm_script.py index d9699500db..f9e249b877 100755 --- a/tools/disasm_script.py +++ b/tools/disasm_script.py @@ -42,14 +42,11 @@ def star_rod_lib(): return _star_rod_lib -def addr_ref(addr): - return star_rod_lib().get(addr, f"0x{addr:08X}") - -def disassemble(bytes, indent = 0, script_name = "script"): +def disassemble(bytes, script_name = "script", symbol_map = {}): out = "" prefix = "" - indent += 1 + indent = 1 indent_used = False def write_line(line): @@ -65,6 +62,9 @@ def disassemble(bytes, indent = 0, script_name = "script"): prefix += "\n" def var(arg): + if arg in symbol_map: + return symbol_map[arg] + v = arg - 2**32 # convert to s32 if v > -250000000: if v <= -220000000: return f"SI_FIXED({(v + 230000000) / 1024}f)" @@ -86,6 +86,11 @@ def disassemble(bytes, indent = 0, script_name = "script"): else: return f"{arg}" + def addr_ref(addr): + if addr in symbol_map: + return symbol_map[addr] + return star_rod_lib().get(addr, f"0x{addr:08X}") + def trigger(trigger): if trigger == 0x00000080: trigger = "TriggerFlag_FLOOR_TOUCH" if trigger == 0x00800000: trigger = "TriggerFlag_FLOOR_ABOVE" @@ -107,6 +112,10 @@ def disassemble(bytes, indent = 0, script_name = "script"): while True: opcode = read_word() argc = read_word() + + if opcode > 0xFF or argc > 0xFF: + return f"/* malformed script: {script_name} */\n" + argv = [] for i in range(0, argc): argv.append(read_word()) @@ -167,7 +176,7 @@ def disassemble(bytes, indent = 0, script_name = "script"): write_line(f"SI_END_IF(),") elif opcode == 0x14: write_line(f"SI_SWITCH({var(argv[0])}),") - indent += 1 + indent += 2 elif opcode == 0x15: write_line(f"SI_SWITCH_CONST(0x{argv[0]:X}),") indent += 2 From 6474bf4704cee4a2c6bc19b46b219c2ccd153e27 Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Wed, 21 Oct 2020 03:37:42 +0100 Subject: [PATCH 02/22] add map namespace macro M(sym) --- Doxyfile | 2 +- src/world/area_kmr/kmr_12/events.c | 66 ++++++++++++++---------------- src/world/area_kmr/kmr_12/header.c | 14 +++---- src/world/area_kmr/kmr_12/kmr_12.h | 13 ++++-- 4 files changed, 49 insertions(+), 46 deletions(-) diff --git a/Doxyfile b/Doxyfile index 8c73332737..343634104a 100644 --- a/Doxyfile +++ b/Doxyfile @@ -104,7 +104,7 @@ ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES PREDEFINED = DOXYGEN NON_MATCHING __attribute__((x))= -EXPAND_AS_DEFINED = INCLUDE_ASM UNK_TYPE UNK_PTR UNK_RET UNK_FUN_ARG UNK_FUN_PTR UNK_ARGS +EXPAND_AS_DEFINED = INCLUDE_ASM UNK_TYPE UNK_PTR UNK_RET UNK_FUN_ARG UNK_FUN_PTR UNK_ARGS M SKIP_FUNCTION_MACROS = YES SEARCH_INCLUDES = YES diff --git a/src/world/area_kmr/kmr_12/events.c b/src/world/area_kmr/kmr_12/events.c index 70f3923b3d..5d88e76355 100644 --- a/src/world/area_kmr/kmr_12/events.c +++ b/src/world/area_kmr/kmr_12/events.c @@ -1,37 +1,33 @@ #include "kmr_12.h" -static Script make_entities; -static Script read_west_sign; -static NpcGroupList npc_groups; +Script M(ExitWest) = EXIT_WALK_SCRIPT(60, 0, "kmr_07", 1); +Script M(ExitEast) = EXIT_WALK_SCRIPT(60, 1, "kmr_11", 0); -static Script exit_west = EXIT_WALK_SCRIPT(60, 0, "kmr_07", 1); -static Script exit_east = EXIT_WALK_SCRIPT(60, 1, "kmr_11", 0); - -static Script bind_exits = { - SI_BIND(exit_west, TriggerFlag_FLOOR_ABOVE, 0 /* deili1 */, NULL), - SI_BIND(exit_east, TriggerFlag_FLOOR_ABOVE, 3 /* deili2 */, NULL), +Script M(BindExits) = { + SI_BIND(M(ExitWest), TriggerFlag_FLOOR_ABOVE, 0 /* deili1 */, NULL), + SI_BIND(M(ExitEast), TriggerFlag_FLOOR_ABOVE, 3 /* deili2 */, NULL), SI_RETURN(), SI_END(), }; -Script kmr_12_main = { +Script M(Main) = { SI_SET(SI_SAVE_VAR(425), 31), SI_CALL(SetSpriteShading, -1), SI_CALL(SetCamPerspective, 0, 3, 25, 16, 4096), SI_CALL(SetCamBGColor, 0, 0, 0, 0), SI_CALL(SetCamEnabled, 0, 1), - SI_CALL(MakeNpcs, 0, npc_groups), - SI_EXEC_WAIT(make_entities), - SI_EXEC(kmr_12_play_music), - SI_SET(SI_VAR(0), bind_exits), + SI_CALL(MakeNpcs, 0, M(npcGroupList)), + SI_EXEC_WAIT(M(MakeEntities)), + SI_EXEC(M(PlayMusic)), + SI_SET(SI_VAR(0), M(BindExits)), SI_EXEC(EnterWalk), SI_WAIT_FRAMES(1), - SI_BIND(read_west_sign, TriggerFlag_WALL_INTERACT, 10, NULL), + SI_BIND(M(ReadWestSign), TriggerFlag_WALL_INTERACT, 10, NULL), SI_RETURN(), SI_END(), }; -static NpcAISettings goomba_ai_settings = { +NpcAISettings M(goombaAISettings) = { .moveSpeed = 1.5f, .moveTime = 30, .waitTime = 30, @@ -46,16 +42,16 @@ static NpcAISettings goomba_ai_settings = { .unk_2C = TRUE, }; -static Script goomba_ai = { - SI_CALL(DoBasicAI, &goomba_ai_settings), +Script M(GoombaAI) = { + SI_CALL(DoBasicAI, &M(goombaAISettings)), SI_RETURN(), SI_END(), }; -static NpcSettings goomba_npc_settings = { +NpcSettings M(GoombaNpcSettings) = { .height = 20, .radius = 23, - .ai = &goomba_ai, + .ai = &M(GoombaAI), .onHit = EnemyNpcHit, .onDefeat = EnemyNpcDefeat, .level = 5, @@ -63,7 +59,7 @@ static NpcSettings goomba_npc_settings = { // *INDENT-OFF* /// @bug The RETURN command is after the END command, so this script will never terminate. -static Script read_west_sign = { +Script M(ReadWestSign) = { SI_GROUP(0), // "Eat a Mushroom to regain your energy!" @@ -73,7 +69,7 @@ static Script read_west_sign = { SI_RESUME_GROUP(1), SI_SET(SI_FLAG(0), FALSE), - SI_CALL(kmr_12_get_goomba_ref), + SI_CALL(M(GetGoomba)), SI_IF_NE(SI_VAR(0), FALSE), SI_CALL(GetNpcVar, NpcId_GOOMBA, 0, SI_VAR(0)), SI_IF_EQ(SI_VAR(0), FALSE), @@ -92,7 +88,7 @@ static Script read_west_sign = { SI_RETURN(), }; -static Script goomba_idle = { +Script M(GoombaIdle) = { SI_WAIT_FRAMES(1), SI_CALL(SetSelfVar, 0, FALSE), @@ -142,28 +138,28 @@ static Script goomba_idle = { SI_CALL(SetSelfEnemyFlagBits, 0x40000000, TRUE), // We're done jumping off; the player can read the sign again - SI_BIND(read_west_sign, TriggerFlag_WALL_INTERACT, 10, NULL), + SI_BIND(M(ReadWestSign), TriggerFlag_WALL_INTERACT, 10, NULL), // Behave like a normal enemy from now on - SI_CALL(BindNpcAI, NpcId_SELF, &goomba_ai), + SI_CALL(BindNpcAI, NpcId_SELF, &M(GoombaAI)), SI_RETURN(), SI_END(), }; -static Script goomba_init = { - SI_CALL(BindNpcIdle, NpcId_SELF, &goomba_idle), +Script M(GoombaInit) = { + SI_CALL(BindNpcIdle, NpcId_SELF, &M(GoombaIdle)), SI_RETURN(), SI_END(), }; // *INDENT-ON* -static StaticNpc goomba_npc = { +StaticNpc M(GoombaNPC) = { .id = NpcId_GOOMBA, - .settings = &goomba_npc_settings, + .settings = &M(GoombaNpcSettings), .pos = { -33.0f, 30.0f, -25.0f }, .flags = 0x00000C00, - .init = goomba_init, + .init = M(GoombaInit), .yaw = 90, .dropFlags = 0x80, .itemDropChance = 5, @@ -204,13 +200,13 @@ static StaticNpc goomba_npc = { }, }; -static NpcGroupList npc_groups = { - NPC_GROUP(goomba_npc, FORMATION_ID(1, 0, 3)), +NpcGroupList M(npcGroupList) = { + NPC_GROUP(M(GoombaNPC), FORMATION_ID(1, 0, 3)), NPC_GROUP_LIST_END(), }; // *INDENT-OFF* -static Script read_east_sign = { +Script M(ReadEastSign) = { SI_CALL(func_800441F0, SI_VAR(0)), SI_IF_EQ(SI_VAR(0), 1), SI_RETURN(), @@ -228,9 +224,9 @@ static Script read_east_sign = { SI_END(), }; -static Script make_entities = { +Script M(MakeEntities) = { SI_CALL(MakeEntity, 0x802EAFDC, 436, 0, -42, 0, 0x80000000), - SI_CALL(AssignScript, &read_east_sign), + SI_CALL(AssignScript, &M(ReadEastSign)), SI_RETURN(), SI_END(), diff --git a/src/world/area_kmr/kmr_12/header.c b/src/world/area_kmr/kmr_12/header.c index f8b4cba3f5..5d51db0b27 100644 --- a/src/world/area_kmr/kmr_12/header.c +++ b/src/world/area_kmr/kmr_12/header.c @@ -1,25 +1,25 @@ #include "kmr_12.h" -static EntryList entryList = { +EntryList M(entryList) = { { -126.0f, 0.0f, 12.0f, 90.0f }, // west, towards Red/Blue Goomba miniboss room { 471.0f, 0.0f, 12.0f, 270.0f }, // east, towards Goomba King's Fortress }; -MapConfig config = { - .main = kmr_12_main, - .entryList = entryList, - .entryCount = ENTRY_COUNT(entryList), +MapConfig M(config) = { + .main = M(Main), + .entryList = M(entryList), + .entryCount = ENTRY_COUNT(M(entryList)), .background = &gBackgroundImage, .tattle = MessageID_TATTLE_KMR_12, }; -Script kmr_12_play_music = { +Script M(PlayMusic) = { SI_CALL(SetMusicTrack, 0, Song_PLEASANT_PATH, 0, 8), SI_RETURN(), SI_END(), }; -ApiStatus kmr_12_get_goomba_ref(ScriptInstance* script, s32 isInitialCall) { +ApiStatus M(GetGoomba)(ScriptInstance* script, s32 isInitialCall) { script->varTable[0] = get_enemy_safe(NpcId_GOOMBA); return ApiStatus_DONE2; } diff --git a/src/world/area_kmr/kmr_12/kmr_12.h b/src/world/area_kmr/kmr_12/kmr_12.h index 10708cb84c..609ebfd5a3 100644 --- a/src/world/area_kmr/kmr_12/kmr_12.h +++ b/src/world/area_kmr/kmr_12/kmr_12.h @@ -1,8 +1,15 @@ #include "common.h" #include "map.h" +#define M(sym) kmr_12 ## _ ## sym + #define NpcId_GOOMBA 0 -Script kmr_12_main; -Script kmr_12_play_music; -ApiStatus kmr_12_get_goomba_ref(ScriptInstance* script, s32 isInitialCall); +ApiStatus M(GetGoomba)(ScriptInstance* script, s32 isInitialCall); + +Script M(Main); +Script M(PlayMusic); +Script M(MakeEntities); +Script M(ReadWestSign); + +NpcGroupList M(npcGroupList); From a85df352a43989aa50d0e37f110107a964ccc80e Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Wed, 21 Oct 2020 03:54:40 +0100 Subject: [PATCH 03/22] use M(sym) in disasm_map --- tools/disasm_map.py | 28 +++++++++++++++++----------- tools/disasm_script.py | 2 +- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/tools/disasm_map.py b/tools/disasm_map.py index a34d4d6c47..842912d30b 100755 --- a/tools/disasm_map.py +++ b/tools/disasm_map.py @@ -13,7 +13,7 @@ def disassemble(bytes, offset, midx, symbol_map = {}, map_name = "map"): while len(midx) > 0: struct = midx.pop(0) name = struct["name"] - if name == "Script_Main": name = f"{map_name}_Main" + if name == "Script_Main": name = f"M(Main)" #print(f"{offset:X} ({name}, start = {struct['start']:X}, len = {struct['length']:X})") @@ -26,26 +26,26 @@ def disassemble(bytes, offset, midx, symbol_map = {}, map_name = "map"): # format struct if struct["type"].startswith("Script"): - out += disassemble_script(bytes, name, symbol_map) + out += disassemble_script(bytes, f"M({name})", symbol_map) elif struct["type"] == "Padding": # nops at end of file bytes.seek(offset % 4, 1) return out elif struct["type"] == "EntryList": - out += f"EntryList {map_name}_entryList = {{" + out += f"EntryList M(entryList) = {{" for i in range(0, struct["length"], 4 * 4): x,y,z,yaw = unpack(">ffff", bytes.read(4 * 4)) out += f"\n {{ {x}f, {y}f, {z}f, {yaw}f }}," out += f"\n}};\n" elif struct["type"] == "Header": - out += f"MapConfig {map_name}_config = {{\n" + out += f"MapConfig M(config) = {{\n" bytes.read(0x10) main,entry_list,entry_count = unpack(">IIi", bytes.read(4 * 3)) - out += f" .main = {map_name}_Main,\n" - out += f" .entryList = {map_name}_entryList,\n" - out += f" .entryCount = {entry_count},\n" + out += f" .main = M(Main)\n" + out += f" .entryList = M(entryList)\n" + out += f" .entryCount = {entry_count}, // prefer ENTRY_COUNT(M(entryList)) if it matches\n" bytes.read(0x1C) @@ -55,7 +55,7 @@ def disassemble(bytes, offset, midx, symbol_map = {}, map_name = "map"): out += f"}};\n" else: # unknown type of struct - out += f"s32 {name}[] = {{" + out += f"s32 M({name})[] = {{" for i in range(0, struct["length"], 4): if (i % 0x20) == 0: out += f"\n " @@ -63,7 +63,7 @@ def disassemble(bytes, offset, midx, symbol_map = {}, map_name = "map"): word = int.from_bytes(bytes.read(4), byteorder="big") if word in symbol_map: - out += f" {symbol_map[word]}," + out += f" M({symbol_map[word]})," else: out += f" 0x{word:08X}," @@ -131,7 +131,13 @@ def parse_midx(file, prefix = ""): return structs def name_struct(s): - return s[1:].replace("???", "unk") + s = s[1:].replace("???", "unk") + + # use ThisCase for scripts + if s.startswith("$Script"): + return s[0].upper() + s[1:] + + return s[0].lower() + s[1:] if __name__ == "__main__": if len(sys.argv) == 1: @@ -145,7 +151,7 @@ if __name__ == "__main__": area_name = area_name[:8] with open(sys.argv[1], "r") as f: - midx = parse_midx(f, map_name + "_") + midx = parse_midx(f) symbol_map = {} for struct in midx: diff --git a/tools/disasm_script.py b/tools/disasm_script.py index f9e249b877..165553f838 100755 --- a/tools/disasm_script.py +++ b/tools/disasm_script.py @@ -206,7 +206,7 @@ def disassemble(bytes, script_name = "script", symbol_map = {}): indent += 1 elif opcode == 0x1C: indent -= 1 - write_line(f"SI_CASE_DEFAULT({var(argv[0])}),") + write_line(f"SI_CASE_DEFAULT(),") indent += 1 elif opcode == 0x1D: indent -= 1 From d6fdb87a569f35e3545dd03fba066a5092b9fcde Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Wed, 21 Oct 2020 03:59:27 +0100 Subject: [PATCH 04/22] NpcSettings casing --- src/world/area_kmr/kmr_12/events.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/world/area_kmr/kmr_12/events.c b/src/world/area_kmr/kmr_12/events.c index 5d88e76355..ce34959b93 100644 --- a/src/world/area_kmr/kmr_12/events.c +++ b/src/world/area_kmr/kmr_12/events.c @@ -48,7 +48,7 @@ Script M(GoombaAI) = { SI_END(), }; -NpcSettings M(GoombaNpcSettings) = { +NpcSettings M(goombaNpcSettings) = { .height = 20, .radius = 23, .ai = &M(GoombaAI), @@ -156,7 +156,7 @@ Script M(GoombaInit) = { StaticNpc M(GoombaNPC) = { .id = NpcId_GOOMBA, - .settings = &M(GoombaNpcSettings), + .settings = &M(goombaNpcSettings), .pos = { -33.0f, 30.0f, -25.0f }, .flags = 0x00000C00, .init = M(GoombaInit), From 5e8f352090eb22fcbea554bfaaf352ec41523e81 Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Wed, 21 Oct 2020 04:04:41 +0100 Subject: [PATCH 05/22] fix BIND_PADLOCK disasm --- tools/disasm_script.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/disasm_script.py b/tools/disasm_script.py index 165553f838..33c834df2a 100755 --- a/tools/disasm_script.py +++ b/tools/disasm_script.py @@ -274,7 +274,7 @@ def disassemble(bytes, script_name = "script", symbol_map = {}): elif opcode == 0x4E: if argv[4] != 0: raise "BIND_PADLOCK argv[4] != NULL" - if argv[5] != 0: + if argv[5] != 1: raise "BIND_PADLOCK argv[5] != 1" write_line(f"SI_BIND_PADLOCK({addr_ref(argv[0])}, {trigger(argv[1])}, {var(argv[2])}, {var(argv[3])}),") From 48c132c2d212590e301bdddd10fcfdf5c89b92eb Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Wed, 21 Oct 2020 04:06:22 +0100 Subject: [PATCH 06/22] more casing --- src/world/area_kmr/kmr_12/events.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/world/area_kmr/kmr_12/events.c b/src/world/area_kmr/kmr_12/events.c index ce34959b93..b68eeba977 100644 --- a/src/world/area_kmr/kmr_12/events.c +++ b/src/world/area_kmr/kmr_12/events.c @@ -154,7 +154,7 @@ Script M(GoombaInit) = { }; // *INDENT-ON* -StaticNpc M(GoombaNPC) = { +StaticNpc M(goombaNPC) = { .id = NpcId_GOOMBA, .settings = &M(goombaNpcSettings), .pos = { -33.0f, 30.0f, -25.0f }, @@ -201,7 +201,7 @@ StaticNpc M(GoombaNPC) = { }; NpcGroupList M(npcGroupList) = { - NPC_GROUP(M(GoombaNPC), FORMATION_ID(1, 0, 3)), + NPC_GROUP(M(goombaNPC), FORMATION_ID(1, 0, 3)), NPC_GROUP_LIST_END(), }; From ccfe465f3b34a3d7d03229b5047a4b2a965fc3b3 Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Wed, 21 Oct 2020 04:07:38 +0100 Subject: [PATCH 07/22] NPC -> Npc --- src/world/area_kmr/kmr_12/events.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/world/area_kmr/kmr_12/events.c b/src/world/area_kmr/kmr_12/events.c index b68eeba977..adfefe17c4 100644 --- a/src/world/area_kmr/kmr_12/events.c +++ b/src/world/area_kmr/kmr_12/events.c @@ -154,7 +154,7 @@ Script M(GoombaInit) = { }; // *INDENT-ON* -StaticNpc M(goombaNPC) = { +StaticNpc M(goombaNpc) = { .id = NpcId_GOOMBA, .settings = &M(goombaNpcSettings), .pos = { -33.0f, 30.0f, -25.0f }, @@ -201,7 +201,7 @@ StaticNpc M(goombaNPC) = { }; NpcGroupList M(npcGroupList) = { - NPC_GROUP(M(goombaNPC), FORMATION_ID(1, 0, 3)), + NPC_GROUP(M(goombaNpc), FORMATION_ID(1, 0, 3)), NPC_GROUP_LIST_END(), }; From 2a8ecfd904356d594fb8107f599c4cdb4dcbe190 Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Wed, 21 Oct 2020 04:59:28 +0100 Subject: [PATCH 08/22] add clean-code target h --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 68397813df..2791d54bea 100644 --- a/Makefile +++ b/Makefile @@ -65,6 +65,9 @@ all: $(TARGET).ld $(BUILD_DIR) $(TARGET).z64 verify clean: rm -rf $(BUILD_DIR) $(TARGET).z64 +clean-code: + rm -rf $(BUILD_DIR)/src $(TARGET).z64 + submodules: git submodule update --init --recursive From e855c2f5d236f7c448f4ac7ca0e585a2bcb877ed Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Wed, 21 Oct 2020 04:58:03 +0100 Subject: [PATCH 09/22] use -Wimplicit -Wuninitialized -Wshadow --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2791d54bea..08aab13ea2 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,7 @@ TARGET = papermario CPPFLAGS = -Iinclude -Isrc -D _LANGUAGE_C -ffreestanding -DF3DEX_GBI_2 ASFLAGS = -EB -Iinclude -march=vr4300 -mtune=vr4300 OLDASFLAGS = -EB -Iinclude -G 0 -CFLAGS = -O2 -quiet -G 0 -mcpu=vr4300 -mfix4300 -mips3 -mgp32 -mfp32 +CFLAGS = -O2 -quiet -G 0 -mcpu=vr4300 -mfix4300 -mips3 -mgp32 -mfp32 -Wimplicit -Wuninitialized -Wshadow LDFLAGS = -T undefined_syms.txt -T undefined_funcs.txt -T $(LD_SCRIPT) -Map $(BUILD_DIR)/papermario.map --no-check-sections ######################## Targets ############################# From 1dc8a3583d8a49912e3782dfb717d5963b5ebad1 Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Wed, 21 Oct 2020 14:12:24 +0100 Subject: [PATCH 10/22] declare M in map.h --- include/macros.h | 3 +++ include/map.h | 2 ++ src/world/area_kmr/kmr_12/kmr_12.h | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/macros.h b/include/macros.h index e3a3854285..29beb68336 100644 --- a/include/macros.h +++ b/include/macros.h @@ -48,4 +48,7 @@ // Fixed-point short literal #define F16(f) (s16)(f * 327.67f) +#define _NAMESPACE(x, y) x ## _ ## y +#define NAMESPACE(x, y) _NAMESPACE(x, y) + #endif diff --git a/include/map.h b/include/map.h index eda5ad5bf1..956fa203a1 100644 --- a/include/map.h +++ b/include/map.h @@ -7,6 +7,8 @@ // TODO: consider moving Npc here +#define M(sym) NAMESPACE(MAP_NAME, sym) + #define ENTRY_COUNT(entryList) (sizeof(entryList) / sizeof(Vec4f)) typedef Vec4f EntryList[]; diff --git a/src/world/area_kmr/kmr_12/kmr_12.h b/src/world/area_kmr/kmr_12/kmr_12.h index 609ebfd5a3..6cb287685a 100644 --- a/src/world/area_kmr/kmr_12/kmr_12.h +++ b/src/world/area_kmr/kmr_12/kmr_12.h @@ -1,7 +1,7 @@ #include "common.h" #include "map.h" -#define M(sym) kmr_12 ## _ ## sym +#define MAP_NAME kmr_12 #define NpcId_GOOMBA 0 From 010ef82fa2582aed2a89194a2b47fbb9e26c15ab Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Wed, 21 Oct 2020 16:51:58 +0100 Subject: [PATCH 11/22] lint identifier names --- .clang-tidy | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index bbfbd5c7db..5bea913a68 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,2 +1,20 @@ -Checks: '-*,clang-analyzer-core.*,clang-analyzer-deadcode.*,readability-*,-readability-magic-numbers,-readability-else-after-return,-readability-named-parameter,-readability-braces-around-statements,-readability-isolate-declaration,-readability-uppercase-literal-suffix,-readability-function-size,-readability-non-const-parameter' -HeaderFilterRegex: '(src|include)\/.*\.h' +Checks: '-*,clang-analyzer-core.*,clang-analyzer-deadcode.*,readability-*,-readability-magic-numbers,-readability-else-after-return,-readability-named-parameter,-readability-braces-around-statements,-readability-isolate-declaration,-readability-uppercase-literal-suffix,-readability-function-size,-readability-non-const-parameter,readability-identifier-naming' +CheckOptions: + - key: readability-identifier-naming.LocalVariableCase + value: camelBack + - key: readability-identifier-naming.ParameterCase + value: camelBack + + - key: readability-identifier-naming.TypedefCase + value: CamelCase + + # TODO: rename all unk_XXX members + #- key: readability-identifier-naming.MemberCase + # value: camelBack + + # TODO: rename all D_XXXXXXXX symbols + #- key: readability-identifier-naming.GlobalVariableCase + # value: CamelCase + #- key: readability-identifier-naming.GlobalVariablePrefix + # value: g +HeaderFilterRegex: '(src|include)\/[^P].*\.h' # ignore inclue/PR/ From c2ba2ea7c50ea0af392e26437d94cbd1f894c0e1 Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Wed, 21 Oct 2020 17:16:42 +0100 Subject: [PATCH 12/22] add STATIC_ASSERT --- include/macros.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/macros.h b/include/macros.h index 3544d26c7c..bcea849bbc 100644 --- a/include/macros.h +++ b/include/macros.h @@ -15,6 +15,7 @@ #define ASSERT(condition) if (!(condition)) { while (1) {} } #define PANIC() ASSERT(0) +#define STATIC_ASSERT(condition) enum { static_assert_fail = 1/(!!(condition)) } // Causes division by zero ("not integer constant") if false #define GAME_STATUS (*gGameStatusPtr) #define PLAYER_STATUS (&gPlayerStatus) From 3cb526273f86ff4b677cb4e819c18d3a9dad82e7 Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Wed, 21 Oct 2020 17:48:56 +0100 Subject: [PATCH 13/22] typedef Script as zero-size Bytecode array --- include/script_api/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/script_api/common.h b/include/script_api/common.h index 4af0f69b8d..2d51df65ec 100644 --- a/include/script_api/common.h +++ b/include/script_api/common.h @@ -4,7 +4,7 @@ #include "common_structs.h" #include "si.h" -typedef Bytecode Script[]; +typedef Bytecode Script[0]; ApiStatus FadeBackgroundToBlack(ScriptInstance* script, s32 isInitialCall); ApiStatus UnfadeBackgroundFromBlack(ScriptInstance* script, s32 isInitialCall); From 49c7ba0239c2504c6515c0d87fc6972adfea4c9d Mon Sep 17 00:00:00 2001 From: dark-samus Date: Wed, 21 Oct 2020 20:07:00 -0400 Subject: [PATCH 14/22] add list types and fix code that uses them --- include/common_structs.h | 13 +++++++++++++ include/macros.h | 6 ++++++ include/variables.h | 37 +++++++++++++++++++------------------ src/code_a5dd0_len_114e0.c | 16 ++++++++-------- src/code_dbd70_len_700.c | 17 +++++++++-------- 5 files changed, 55 insertions(+), 34 deletions(-) diff --git a/include/common_structs.h b/include/common_structs.h index 4e1d121026..f5b8e5dd1c 100644 --- a/include/common_structs.h +++ b/include/common_structs.h @@ -115,6 +115,8 @@ typedef struct Npc { /* 0x0AB */ char unk_AB[661]; } Npc; // size = 0x340 +typedef Npc* NpcList[MAX_NPCS]; + typedef struct PlayerData { /* 0x000 */ s8 bootsLevel; /* 0x001 */ s8 hammerLevel; @@ -204,6 +206,8 @@ typedef struct Trigger { /* 0x34 */ ScriptID runningScriptID; } Trigger; // size = 0x38 +typedef Trigger* TriggerList[MAX_TRIGGERS]; + typedef struct ScriptInstance { /* 0x000 */ u8 state; /* 0x001 */ u8 currentArgc; @@ -271,6 +275,10 @@ typedef struct Entity { /* 0xB1 */ char unk_B1[71]; } Entity; // size = 0xF8 +typedef Entity* EntityList[MAX_ENTITIES]; + +typedef UNK_TYPE* DynamicEntityList[MAX_DYNAMIC_ENTITIES]; + typedef struct StaticEntityData { /* 0x00 */ s16 flags; /* 0x02 */ s16 argSize; @@ -364,6 +372,7 @@ typedef struct UiStatus { /* 0x68 */ s32 iconIndex13; /* 0x6C */ s8 unk_6C[4]; } UiStatus; // size = 0x70 + typedef struct Collider { /* 0x00 */ s32 flags; /* 0x04 */ s16 nextSibling; @@ -672,6 +681,8 @@ typedef struct Model { /* 0xAA */ char unk_AA[6]; } Model; // size = 0xB0 +typedef Model* ModelList[MAX_MODELS]; + typedef struct AnimatedMesh { /* 0x000 */ s32 flags; /* 0x004 */ u8 renderMode; @@ -921,6 +932,8 @@ typedef struct Shadow { /* 0x28 */ char unk_28[80]; } Shadow; // size = 0x78 +typedef Shadow* ShadowList[MAX_SHADOWS]; + typedef struct PushBlockGrid { /* 0x00 */ s8* cells; /* 0x04 */ u8 numCellsX; diff --git a/include/macros.h b/include/macros.h index bcea849bbc..318da49bcd 100644 --- a/include/macros.h +++ b/include/macros.h @@ -23,7 +23,13 @@ #define MAX_MAPVARS 16 #define MAX_MAPFLAGS 3 +#define MAX_MODELS 256 #define MAX_SCRIPTS 128 +#define MAX_NPCS 64 +#define MAX_TRIGGERS 64 +#define MAX_SHADOWS 60 +#define MAX_ENTITIES 30 +#define MAX_DYNAMIC_ENTITIES 16 //NOTE: SCRIPT_ALLOC is probably not quite correct, but this is the closest thing to matching for the functions its used in. Needs more work. #define SCRIPT_ALLOC(new, index) \ diff --git a/include/variables.h b/include/variables.h index acdf8f3fd4..62b185a0b0 100644 --- a/include/variables.h +++ b/include/variables.h @@ -38,30 +38,31 @@ extern s32 gScriptIndexList[MAX_SCRIPTS]; extern s32 gMoveScriptTable[][4]; -extern Model* gWorldModelList[256]; -extern Model* gBattleModelList[256]; -extern Model** gCurrentModelListPtr[256]; +extern ModelList gWorldModelList; +extern ModelList gBattleModelList; +extern ModelList* gCurrentModelListPtr; +// TODO: potentially a display list, figure this out extern u32* gWorldModelSpecialDls[32]; extern u32* gBattleModelSpecialDls[32]; extern u32** gCurrentModelSpecialDlsPtr[32]; -extern Entity* gWorldEntityList[30]; -extern Entity* gBattleEntityList[30]; -extern Entity** gCurrentEntityListPtr[30]; +extern EntityList gWorldEntityList; +extern EntityList gBattleEntityList; +extern EntityList* gCurrentEntityListPtr; extern s32 gLastCreatedEntityIndex; -extern UNK_TYPE* gWorldDynamicEntityList[16]; -extern UNK_TYPE* gBattleDynamicEntityList[16]; -extern UNK_TYPE*** gCurrentDynamicEntityListPtr; +extern DynamicEntityList gWorldDynamicEntityList; +extern DynamicEntityList gBattleDynamicEntityList; +extern DynamicEntityList* gCurrentDynamicEntityListPtr; -extern Npc* gWorldNpcList[64]; -extern Npc* gBattleNpcList[64]; -extern Npc** gCurrentNpcListPtr[64]; +extern NpcList gWorldNpcList; +extern NpcList gBattleNpcList; +extern NpcList* gCurrentNpcListPtr; -extern Shadow* gWorldShadowList[60]; -extern Shadow* gBattleShadowList[60]; -extern Shadow** gCurrentShadowListPtr[60]; +extern ShadowList gWorldShadowList; +extern ShadowList gBattleShadowList; +extern ShadowList* gCurrentShadowListPtr; extern Camera gCameras[4]; extern s32 gCurrentCameraID; @@ -89,9 +90,9 @@ extern PrintContext* D_802DB268; // Triggers extern s16 gTriggerCount; -extern Trigger* gTriggerList1[64]; -extern Trigger* gTriggerList2[64]; -extern Trigger** gCurrentTriggerListPtr[64]; +extern TriggerList gTriggerList1; +extern TriggerList gTriggerList2; +extern TriggerList* gCurrentTriggerListPtr; // Map transition data. Should probably be a struct extern u16 gMapTransitionAlpha; diff --git a/src/code_a5dd0_len_114e0.c b/src/code_a5dd0_len_114e0.c index 3c67595af5..26d7166ec7 100644 --- a/src/code_a5dd0_len_114e0.c +++ b/src/code_a5dd0_len_114e0.c @@ -34,24 +34,24 @@ Shadow* get_shadow_by_index(s32 index) { return (*gCurrentShadowListPtr)[index & 0xFFF]; } -Entity** get_entity_list(void) { - Entity** ret; +EntityList* get_entity_list(void) { + EntityList* ret; if (!GAME_STATUS->isBattle) { - ret = gWorldEntityList; + ret = &gWorldEntityList; } else { - ret = gBattleEntityList; + ret = &gBattleEntityList; } return ret; } -Shadow** get_shadow_list(void) { - Shadow** ret; +ShadowList* get_shadow_list(void) { + ShadowList* ret; if (!GAME_STATUS->isBattle) { - ret = gWorldShadowList; + ret = &gWorldShadowList; } else { - ret = gBattleShadowList; + ret = &gBattleShadowList; } return ret; } diff --git a/src/code_dbd70_len_700.c b/src/code_dbd70_len_700.c index 9045c95c38..e5c36c58ce 100644 --- a/src/code_dbd70_len_700.c +++ b/src/code_dbd70_len_700.c @@ -8,9 +8,9 @@ INCLUDE_ASM(s32, "code_dbd70_len_700", clear_trigger_data); void init_trigger_list(void) { if (!GAME_STATUS->isBattle) { - *gCurrentTriggerListPtr = gTriggerList1; + gCurrentTriggerListPtr = &gTriggerList1; } else { - *gCurrentTriggerListPtr = gTriggerList2; + gCurrentTriggerListPtr = &gTriggerList2; } gTriggerCount = 0; @@ -22,16 +22,17 @@ INCLUDE_ASM(s32, "code_dbd70_len_700", update_triggers); void delete_trigger(Trigger* toDelete) { s32 i; + TriggerList** currentTriggerListPtr = &gCurrentTriggerListPtr; - for (i = 0; i < ARRAY_COUNT(gCurrentTriggerListPtr); i++) { - if ((*gCurrentTriggerListPtr)[i] == toDelete) { + for (i = 0; i < MAX_TRIGGERS; i++) { + if ((**currentTriggerListPtr)[i] == toDelete) { break; } } - if (i < ARRAY_COUNT(gCurrentTriggerListPtr)) { - heap_free((*gCurrentTriggerListPtr)[i]); - (*gCurrentTriggerListPtr)[i] = NULL; + if (i < MAX_TRIGGERS) { + heap_free((**currentTriggerListPtr)[i]); + (**currentTriggerListPtr)[i] = NULL; } } @@ -48,7 +49,7 @@ s32 func_80145CE8(s32 arg0) { return 0; } - for (i = 0; i < ARRAY_COUNT(gCurrentTriggerListPtr); i++) { + for (i = 0; i < MAX_TRIGGERS; i++) { Trigger* trigger = (*gCurrentTriggerListPtr)[i]; if ((trigger != NULL) && From 7cfd053fb7506da03a034dc7dd09dc0b5e4d8ced Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Thu, 22 Oct 2020 03:09:23 +0100 Subject: [PATCH 15/22] improve make speed --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 159cbb970f..38b35929be 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,8 @@ SHELL=/bin/bash -o pipefail +MAKEFLAGS += --no-builtin-rules +MAKEFLAGS += --no-builtin-variables + ################ Target Executable and Sources ############### # BUILD_DIR is location where all build artifacts are placed @@ -57,8 +60,6 @@ LDFLAGS = -T undefined_syms.txt -T undefined_funcs.txt -T $(LD_SCRIPT) -Map $ ######################## Targets ############################# -$(foreach dir,$(SRC_DIRS) $(ASM_DIRS) $(DATA_DIRS) $(ASSETS_FS_DIRS) ,$(shell mkdir -p build/$(dir))) - default: all LD_SCRIPT = $(TARGET).ld @@ -67,6 +68,7 @@ all: $(TARGET).ld $(BUILD_DIR) $(TARGET).z64 verify clean: rm -rf $(BUILD_DIR) $(TARGET).z64 + mkdir -p $(foreach dir,$(SRC_DIRS) $(ASM_DIRS) $(DATA_DIRS) $(ASSETS_FS_DIRS),build/$(dir) submodules: git submodule update --init --recursive From 14b509830fdcabcaece31a5e6d421f88427a5cfd Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Thu, 22 Oct 2020 03:14:13 +0100 Subject: [PATCH 16/22] #define map-namespaced functions with M --- src/world/area_kmr/kmr_12/events.c | 2 +- src/world/area_kmr/kmr_12/header.c | 2 +- src/world/area_kmr/kmr_12/kmr_12.h | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/world/area_kmr/kmr_12/events.c b/src/world/area_kmr/kmr_12/events.c index adfefe17c4..b56c1e1d21 100644 --- a/src/world/area_kmr/kmr_12/events.c +++ b/src/world/area_kmr/kmr_12/events.c @@ -69,7 +69,7 @@ Script M(ReadWestSign) = { SI_RESUME_GROUP(1), SI_SET(SI_FLAG(0), FALSE), - SI_CALL(M(GetGoomba)), + SI_CALL(GetGoomba), SI_IF_NE(SI_VAR(0), FALSE), SI_CALL(GetNpcVar, NpcId_GOOMBA, 0, SI_VAR(0)), SI_IF_EQ(SI_VAR(0), FALSE), diff --git a/src/world/area_kmr/kmr_12/header.c b/src/world/area_kmr/kmr_12/header.c index 5d51db0b27..5d9a96fdf0 100644 --- a/src/world/area_kmr/kmr_12/header.c +++ b/src/world/area_kmr/kmr_12/header.c @@ -19,7 +19,7 @@ Script M(PlayMusic) = { SI_END(), }; -ApiStatus M(GetGoomba)(ScriptInstance* script, s32 isInitialCall) { +ApiStatus GetGoomba(ScriptInstance* script, s32 isInitialCall) { script->varTable[0] = get_enemy_safe(NpcId_GOOMBA); return ApiStatus_DONE2; } diff --git a/src/world/area_kmr/kmr_12/kmr_12.h b/src/world/area_kmr/kmr_12/kmr_12.h index 6cb287685a..406b7f4299 100644 --- a/src/world/area_kmr/kmr_12/kmr_12.h +++ b/src/world/area_kmr/kmr_12/kmr_12.h @@ -5,7 +5,8 @@ #define NpcId_GOOMBA 0 -ApiStatus M(GetGoomba)(ScriptInstance* script, s32 isInitialCall); +#define GetGoomba M(GetGoomba) +ApiStatus GetGoomba(ScriptInstance* script, s32 isInitialCall); Script M(Main); Script M(PlayMusic); From e2d1de8ffe42552eb2ea4db9d2a5ba242ce549b7 Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Thu, 22 Oct 2020 03:19:25 +0100 Subject: [PATCH 17/22] fix `make setup' when bin/ doesn't exist --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 38b35929be..4153cde5d8 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ WORLD_AREAS := area_dgb area_arn area_dro area_end area_flo area_gv area_hos are SRC_DIRS := $(shell find src -type d) ASM_DIRS := asm asm/os INCLUDE_DIRS := include include/PR src -DATA_DIRS := $(shell find bin -type d -not -name Yay0) +DATA_DIRS := $(shell mkdir -p bin && find bin -type d -not -name Yay0) YAY0_DIRS := bin/Yay0 ASSETS_FS_DIRS := assets/fs From 54c337596b6ed36d2cde3d22f99353f67ee8d019 Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Thu, 22 Oct 2020 03:53:49 +0100 Subject: [PATCH 18/22] reduce makefile lookup Waiting on https://github.com/ethteck/n64splat/pull/6 --- Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 4153cde5d8..5bbe69d645 100644 --- a/Makefile +++ b/Makefile @@ -28,9 +28,9 @@ YAY0_FILES := $(foreach dir,$(YAY0_DIRS),$(wildcard $(dir)/*.bin)) ASSETS_FS_FILES := $(foreach dir,$(ASSETS_FS_DIRS),$(wildcard $(dir)/*.*)) # Object files -O_FILES := $(foreach file,$(C_FILES),$(BUILD_DIR)/$(file:.c=.o)) \ - $(foreach file,$(S_FILES),$(BUILD_DIR)/$(file:.s=.o)) \ - $(foreach file,$(DATA_FILES),$(BUILD_DIR)/$(file:.bin=.o)) \ +O_FILES := $(foreach file,$(C_FILES),$(BUILD_DIR)/$(file:.c=.c.o)) \ + $(foreach file,$(S_FILES),$(BUILD_DIR)/$(file:.s=.s.o)) \ + $(foreach file,$(DATA_FILES),$(BUILD_DIR)/$(file:.bin=.bin.o)) \ $(foreach dir,$(ASSETS_FS_DIRS),$(BUILD_DIR)/$(dir).o) \ YAY0_FILES := $(foreach file,$(YAY0_FILES),$(BUILD_DIR)/$(file:.bin=.Yay0.o)) @@ -68,7 +68,7 @@ all: $(TARGET).ld $(BUILD_DIR) $(TARGET).z64 verify clean: rm -rf $(BUILD_DIR) $(TARGET).z64 - mkdir -p $(foreach dir,$(SRC_DIRS) $(ASM_DIRS) $(DATA_DIRS) $(ASSETS_FS_DIRS),build/$(dir) + mkdir -p $(foreach dir,$(SRC_DIRS) $(ASM_DIRS) $(DATA_DIRS) $(ASSETS_FS_DIRS),build/$(dir)) submodules: git submodule update --init --recursive @@ -93,13 +93,13 @@ $(BUILD_DIR): $(BUILD_DIR)/$(TARGET).elf: $(O_FILES) $(YAY0_FILES) $(LD_SCRIPT) @$(LD) $(LDFLAGS) -o $@ -$(BUILD_DIR)/%.o: %.s +$(BUILD_DIR)/%.s.o: %.s $(AS) $(ASFLAGS) -o $@ $< -$(BUILD_DIR)/%.o: %.c $(H_FILES) +$(BUILD_DIR)/%.c.o: %.c $(H_FILES) cpp $(CPPFLAGS) $< | $(CC) $(CFLAGS) -o - | $(OLD_AS) $(OLDASFLAGS) - -o $@ -$(BUILD_DIR)/%.o: %.bin +$(BUILD_DIR)/%.bin.o: %.bin $(LD) -r -b binary -o $@ $< $(BUILD_DIR)/%.Yay0.o: %.bin From 191be39a039dd5f8625fcc096fa8a38fc7895568 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 22 Oct 2020 06:01:11 +0100 Subject: [PATCH 19/22] document StatDrop (#88) --- docs/doxygen_custom.css | 15 ++++++++------- include/map.h | 23 ++++++++++++++++++----- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/docs/doxygen_custom.css b/docs/doxygen_custom.css index 877606101a..943a4fe917 100644 --- a/docs/doxygen_custom.css +++ b/docs/doxygen_custom.css @@ -2,7 +2,7 @@ body, table, div, p, dl { font: inherit } -body, table, div, p, dl, p.reference, p.definition, .memberdecls .header { +body, table, div, p, dl, p.reference, p.definition, .memberdecls .header, .mdescRight { color: #121212; font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji; } @@ -48,7 +48,7 @@ body { flex-direction: row; width: 100%; - max-width: 1000px; + max-width: 1100px; min-height: 100%; margin: 0 auto; } @@ -92,9 +92,7 @@ table { #details + .groupheader, .definition, -.memtitle, -.contents > p:first-child > a:first-child /* "Go to the source code of this file." */ -{ display: none } +.memtitle { display: none } table.memname * { display: inline; @@ -125,19 +123,22 @@ code { display: block !important; border-left: 1px solid #eee; padding-left: 1em; - margin: 1em 0; + margin: 1.5em 0; width: 100%; box-sizing: border-box; } .memproto { padding: 8px; - margin-bottom: .5em; box-shadow: none; text-shadow: none; display: inline-block; } +.memdoc p:first-child { + margin-top: 0; +} + .memname { margin-left: 0; } diff --git a/include/map.h b/include/map.h index eda5ad5bf1..833a57a350 100644 --- a/include/map.h +++ b/include/map.h @@ -61,12 +61,25 @@ typedef struct ItemDrop { /* 0x04 */ s16 unk_08; } ItemDrop; // size = 0x06 +/// @brief Describes heart/flower drop chances after defeating an Npc in the overworld. +/// +/// The algorithm for calculating the number of hearts/flowers from a StatDrop is: +/// - If current HP/FP > cutoff, drop 0. +/// - Roll generalChance. If it fails, drop 0. +/// - Roll chancePerAttempt attempts times. For each success, drop a heart/flower. +/// +/// StaticNpc holds a table of StatDrops for each stat (hearts, flowers). All are checked together +/// and the number of hearts/flowers to drop is the total number of successful attempts for each stat. +/// +/// Each heart/flower is worth 1 HP and 1 FP respectively, if picked up. +/// +/// cutoff, generalChance, and chancePerAttempt are short fixed-point percentage values. +/// That is, `F16(0)` is a 0% chance and `F16(100)` is a 100% chance. typedef struct StatDrop { - // NOTE: these %s are F16 - /* 0x00 */ s16 hpCutoff; // % of max HP/FP - /* 0x02 */ s16 generalChance; // % - /* 0x04 */ s16 attempts; - /* 0x06 */ s16 chancePerAttempt; // % + /* 0x00 */ s16 cutoff; ///< % of max HP/FP. If current HP/FP > cutoff, no hearts/flowers can be dropped. + /* 0x02 */ s16 generalChance; ///< % chance for any hearts/flowers to be dropped at all from this StatDrop. + /* 0x04 */ s16 attempts; ///< Maximum number of hearts/flowers that can be dropped from this StatDrop. + /* 0x06 */ s16 chancePerAttempt; ///< % chance for a single heart/flower to be dropped from each attempt. } StatDrop; // size = 0x08 #define NO_DROPS { F16(100), F16(0), 0, F16(0) } From 1abd55b4a152f09ab467500b1a9ac01bc1cb0b9f Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Thu, 22 Oct 2020 17:39:14 +0100 Subject: [PATCH 20/22] fix build --- Makefile | 2 +- tools/n64splat | 2 +- tools/splat.yaml | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 4520c20f74..6660e79cc6 100644 --- a/Makefile +++ b/Makefile @@ -88,7 +88,7 @@ print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true $(BUILD_DIR): mkdir -p $(BUILD_DIR) -$(BUILD_DIR)/%.o: %.s +$(BUILD_DIR)/%.s.o: %.s $(AS) $(ASFLAGS) -o $@ $< $(BUILD_DIR)/%.c.o: %.c $(H_FILES) diff --git a/tools/n64splat b/tools/n64splat index b349796f4e..91d14b76cd 160000 --- a/tools/n64splat +++ b/tools/n64splat @@ -1 +1 @@ -Subproject commit b349796f4ef5d7f796ac0796c7a9974f5b735547 +Subproject commit 91d14b76cd4bb956b586d5802c1a86e019ca8029 diff --git a/tools/splat.yaml b/tools/splat.yaml index 9bf1d51de8..aa9b4e5b56 100644 --- a/tools/splat.yaml +++ b/tools/splat.yaml @@ -5,6 +5,7 @@ options: pycparser_flags: ["-Iinclude", "-D_LANGUAGE_C", "-ffreestanding", "-DF3DEX_GBI_2", "-DSPLAT"] compiler: "GCC" mnemonic_ljust: 10 + o_as_suffix: yes segments: - name: header type: header From 61665d1066593e41ff8f0fca02555ee9c9dbb100 Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Thu, 22 Oct 2020 18:12:13 +0100 Subject: [PATCH 21/22] bump splat --- tools/n64splat | 2 +- tools/splat.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/n64splat b/tools/n64splat index 91d14b76cd..895abeff31 160000 --- a/tools/n64splat +++ b/tools/n64splat @@ -1 +1 @@ -Subproject commit 91d14b76cd4bb956b586d5802c1a86e019ca8029 +Subproject commit 895abeff31cc0bd5de3a05a55715d3457f8425eb diff --git a/tools/splat.yaml b/tools/splat.yaml index aa9b4e5b56..8be3d8daf9 100644 --- a/tools/splat.yaml +++ b/tools/splat.yaml @@ -5,7 +5,7 @@ options: pycparser_flags: ["-Iinclude", "-D_LANGUAGE_C", "-ffreestanding", "-DF3DEX_GBI_2", "-DSPLAT"] compiler: "GCC" mnemonic_ljust: 10 - o_as_suffix: yes + ld_o_replace_extension: no segments: - name: header type: header From c9a0f1b7d9379380ddea5cf0b380a91019aacb47 Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Thu, 22 Oct 2020 18:41:52 +0100 Subject: [PATCH 22/22] fix asset_table.o generation --- Makefile | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 6660e79cc6..ae7543bc27 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,7 @@ INCLUDE_DIRS := include include/PR src DATA_DIRS := $(shell mkdir -p bin && find bin -type d -not -name Yay0) YAY0_DIRS := bin/Yay0 ASSETS_FS_DIRS := assets/fs +ASSETS_FS_BIN := $(BUILD_DIR)/assets/fs.bin # Source code files C_FILES := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.c)) @@ -26,10 +27,11 @@ YAY0_FILES := $(foreach dir,$(YAY0_DIRS),$(wildcard $(dir)/*.bin)) ASSETS_FS_FILES := $(foreach dir,$(ASSETS_FS_DIRS),$(wildcard $(dir)/*.*)) # Object files +ASSETS_FS_O := $(ASSETS_FS_BIN:.bin=.o) O_FILES := $(foreach file,$(C_FILES),$(BUILD_DIR)/$(file:.c=.c.o)) \ $(foreach file,$(S_FILES),$(BUILD_DIR)/$(file:.s=.s.o)) \ $(foreach file,$(DATA_FILES),$(BUILD_DIR)/$(file:.bin=.bin.o)) \ - $(foreach dir,$(ASSETS_FS_DIRS),$(BUILD_DIR)/$(dir).o) \ + $(ASSETS_FS_O) \ $(foreach file,$(YAY0_FILES),$(BUILD_DIR)/$(file:.bin=.Yay0.o)) ####################### Tools ######################### @@ -65,11 +67,11 @@ all: $(TARGET).ld $(BUILD_DIR) $(TARGET).z64 verify clean: rm -rf $(BUILD_DIR) $(TARGET).z64 - @mkdir -p $(foreach dir,$(SRC_DIRS) $(ASM_DIRS) $(DATA_DIRS) $(ASSETS_FS_DIRS),build/$(dir)) + make $(BUILD_DIR) clean-code: rm -rf $(BUILD_DIR)/src $(TARGET).z64 - @mkdir -p $(foreach dir,$(SRC_DIRS),build/$(dir)) + make $(BUILD_DIR) submodules: git submodule update --init --recursive @@ -87,6 +89,7 @@ print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true $(BUILD_DIR): mkdir -p $(BUILD_DIR) + @mkdir -p $(foreach dir,$(SRC_DIRS) $(ASM_DIRS) $(DATA_DIRS) $(ASSETS_FS_DIRS),build/$(dir)) $(BUILD_DIR)/%.s.o: %.s $(AS) $(ASFLAGS) -o $@ $< @@ -97,13 +100,14 @@ $(BUILD_DIR)/%.c.o: %.c $(H_FILES) $(BUILD_DIR)/%.bin.o: %.bin $(LD) -r -b binary -o $@ $< -$(BUILD_DIR)/assets/fs/%: $(ASSETS_FS_FILES) +$(BUILD_DIR)/assets/fs/%: assets/fs/% + @rm -f $@ $(TOOLS)/build_assets_fs.py $* $(BUILD_DIR)/assets/fs.bin: assets/fs.json $(TOOLS)/build_assets_fs.py $(foreach file,$(ASSETS_FS_FILES),build/$(file)) $(TOOLS)/build_assets_fs.py -$(BUILD_DIR)/assets/fs.o: $(BUILD_DIR)/assets/fs.bin +$(ASSETS_FS_O): $(ASSETS_FS_BIN) $(LD) -r -b binary -o $@ $< $(BUILD_DIR)/%.Yay0.o: %.bin @@ -128,4 +132,4 @@ $(TARGET).z64: $(BUILD_DIR)/$(TARGET).bin verify: $(TARGET).z64 sha1sum -c checksum.sha1 -.PHONY: all clean default +.PHONY: all clean default $(BUILD_DIR)