diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index a29e1c2fdb..1b252c29f8 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -20,8 +20,8 @@ "F3DEX_GBI_2", "_LANGUAGE_C", "_MIPS_SZLONG=32", - "VERSION=pal", - "VERSION_PAL" + "VERSION=jp", + "VERSION_JP" ], "cStandard": "c89", "cppStandard": "c++17", diff --git a/first_diff.py b/first_diff.py index e2c7728969..f8a84b4622 100755 --- a/first_diff.py +++ b/first_diff.py @@ -1,255 +1,73 @@ #!/usr/bin/env python3 -import os.path import argparse -from subprocess import check_call +import mapfile_parser +from pathlib import Path +import rabbitizer -parser = argparse.ArgumentParser( - description="Find the first difference(s) between the built ROM and the base ROM." -) -parser.add_argument( - "-c", - "--count", - type=int, - default=5, - help="find up to this many instruction difference(s)", -) -parser.add_argument( - "-d", - "--diff", - dest="diff_args", - nargs="?", - action="store", - default=False, - const="prompt", - help="run diff.py on the result with the provided arguments", -) -parser.add_argument( - "-m", "--make", help="run ninja before finding difference(s)", action="store_true" -) -args = parser.parse_args() - -diff_count = args.count - -if args.make: - check_call(["ninja", "ver/current/build/papermario.z64"]) - -baseimg = f"ver/current/baserom.z64" -basemap = f"ver/current/expected/build/papermario.map" - -myimg = f"ver/current/build/papermario.z64" -mymap = f"ver/current/build/papermario.map" - -if not os.path.isfile(baseimg): - print(f"{baseimg} must exist.") - exit(1) -if not os.path.isfile(myimg) or not os.path.isfile(mymap): - print(f"{myimg} and {mymap} must exist.") - exit(1) - -mybin = open(myimg, "rb").read() -basebin = open(baseimg, "rb").read() - -if len(mybin) != len(basebin): - print("Modified ROM has different size...") - exit(1) - -if mybin == basebin: - print("No differences!") - exit(0) +script_dir = Path(__file__).resolve().parent +root_dir = script_dir +build_dir = root_dir / "ver" / "jp" / "build" +expected_build_dir = root_dir / "ver/jp/expected/ver/jp/build" -def search_rom_address(target_addr): - ram_offset = None - prev_ram = 0 - prev_rom = 0 - prev_sym = "" - cur_file = "" - prev_file = cur_file - prev_line = "" - with open(mymap) as f: - for line in f: - if "load address" in line: - # Ignore .bss sections since we're looking for a ROM address - if ".bss" in line or ".bss" in prev_line: - ram_offset = None - continue - ram = int(line[16 : 16 + 18], 0) - rom = int(line[59 : 59 + 18], 0) - ram_offset = ram - rom - continue - - prev_line = line - - if ( - ram_offset is None - or "=" in line - or "*fill*" in line - or " 0x" not in line - ): - continue - - ram = int(line[16 : 16 + 18], 0) - rom = ram - ram_offset - sym = line.split()[-1] - - if "0x" in sym: - ram_offset = None - continue - if "/" in sym: - cur_file = sym - continue - - if rom > target_addr: - return ( - f"{prev_sym} (RAM 0x{prev_ram:X}, ROM 0x{prev_rom:X}, {prev_file})" - ) - - prev_ram = ram - prev_rom = rom - prev_sym = sym - prev_file = cur_file - - return "at end of rom?" - - -def parse_map(map_fname): - ram_offset = None - cur_file = "" - syms = {} - prev_sym = None - prev_line = "" - with open(map_fname) as f: - for line in f: - if "load address" in line: - ram = int(line[16 : 16 + 18], 0) - rom = int(line[59 : 59 + 18], 0) - ram_offset = ram - rom - continue - - prev_line = line - - if ( - ram_offset is None - or "=" in line - or "*fill*" in line - or " 0x" not in line - ): - continue - - ram = int(line[16 : 16 + 18], 0) - rom = ram - ram_offset - sym = line.split()[-1] - - if "0x" in sym: - ram_offset = None - continue - elif "/" in sym: - cur_file = sym - continue - - syms[sym] = (rom, cur_file, prev_sym, ram) - prev_sym = sym - - return syms - - -def map_diff(): - map1 = parse_map(mymap) - map2 = parse_map(basemap) - min_ram = None - found = None - for sym, addr in map1.items(): - if sym not in map2: - continue - if addr[0] != map2[sym][0]: - if min_ram is None or addr[0] < min_ram: - min_ram = addr[0] - found = (sym, addr[1], addr[2]) - if min_ram is None: - return False - else: - print( - f"Map appears to have shifted just before {found[0]} ({found[1]}) -- in {found[2]}?" - ) - if found[2] is not None and found[2] not in map2: - print( - f"(Base map file {basemap} out of date due to new or renamed symbols, so result may be imprecise.)" - ) - return True - - -def hexbytes(bs): - return ":".join("{:02X}".format(c) for c in bs) - - -found_instr_diff = [] -map_search_diff = [] -diffs = 0 -shift_cap = 1000 -for i in range(24, len(mybin), 4): - # (mybin[i:i+4] != basebin[i:i+4], but that's slightly slower in CPython...) - if diffs <= shift_cap and ( - mybin[i] != basebin[i] - or mybin[i + 1] != basebin[i + 1] - or mybin[i + 2] != basebin[i + 2] - or mybin[i + 3] != basebin[i + 3] - ): - if diffs == 0: - print(f"First difference at ROM addr 0x{i:X}, {search_rom_address(i)}") - print( - f"Bytes: {hexbytes(mybin[i : i + 4])} vs {hexbytes(basebin[i : i + 4])}" - ) - diffs += 1 - if ( - len(found_instr_diff) < diff_count - and mybin[i] >> 2 != basebin[i] >> 2 - and not search_rom_address(i) in map_search_diff - ): - found_instr_diff.append(i) - map_search_diff.append(search_rom_address(i)) - -if diffs == 0: - print("No differences but ROMs differ?") - exit() - -if len(found_instr_diff) > 0: - for i in found_instr_diff: - print(f"Instruction difference at ROM addr 0x{i:X}, {search_rom_address(i)}") - print(f"Bytes: {hexbytes(mybin[i : i + 4])} vs {hexbytes(basebin[i : i + 4])}") -print() - -definite_shift = diffs > shift_cap -if definite_shift: - print(f"Over {shift_cap} differing words, must be a shifted ROM.") -else: - print(f"{diffs} differing word(s).") - -if diffs > 100: - if not os.path.isfile(basemap): - print( - f"To find ROM shifts, copy a clean .map file to {basemap} and rerun this script." - ) - elif not map_diff(): - print(f"No ROM shift{' (!?)' if definite_shift else ''}") - -if args.diff_args: - if len(found_instr_diff) < 1: - print(f"No instruction difference to run diff.py on") - exit() - - diff_sym = search_rom_address(found_instr_diff[0]).split()[0] - if args.diff_args == "prompt": - diff_args = input("Call diff.py with which arguments? ") or "--" - else: - diff_args = args.diff_args - if diff_args[0] != "-": - diff_args = "-" + diff_args - check_call( - [ - "python3", - "diff.py", - diff_args, - diff_sym, - ] +def decode_instruction(bytes_diff: bytes, map_file: mapfile_parser.MapFile) -> str: + word = ( + (bytes_diff[0] << 24) + | (bytes_diff[1] << 16) + | (bytes_diff[2] << 8) + | (bytes_diff[3] << 0) ) + instr = rabbitizer.Instruction(word) + imm_override = None + + if instr.isJumpWithAddress(): + # Instruction is a function call (jal) + + # Get the embedded address of the function call + sym_address = instr.getInstrIndexAsVram() + + # Search for the address in the mapfile + sym_info = map_file.findSymbolByVramOrVrom(sym_address) + if sym_info is not None: + # Use the symbol from the mapfile instead of a raw value + imm_override = sym_info.symbol.name + + return instr.disassemble(immOverride=imm_override, extraLJust=-20) + + +def main(): + parser = argparse.ArgumentParser( + description="Find the first difference(s) between the built ROM and the base ROM." + ) + + parser.add_argument( + "-c", + "--count", + type=int, + default=5, + help="find up to this many instruction difference(s)", + ) + parser.add_argument( + "-v", "--version", help="Which version should be processed", default="us" + ) + parser.add_argument( + "-a", "--add-colons", action="store_true", help="Add colon between bytes" + ) + + args = parser.parse_args() + + mapfile_parser.frontends.first_diff.doFirstDiff( + build_dir / f"papermario.map", + expected_build_dir / f"papermario.map", + build_dir / f"papermario.z64", + expected_build_dir / f"papermario.z64", + args.count, + mismatchSize=True, + addColons=args.add_colons, + bytesConverterCallback=decode_instruction, + ) + + +if __name__ == "__main__": + main() diff --git a/src/filemenu/filemenu_createfile.c b/src/filemenu/filemenu_createfile.c index 6f52f10f15..336f233c4a 100644 --- a/src/filemenu/filemenu_createfile.c +++ b/src/filemenu/filemenu_createfile.c @@ -340,6 +340,16 @@ void filemenu_draw_contents_choose_name( baseX + 2 + menu->col * 19, baseY + 13 + menu->row * FILEMENU_ROW_AMT); } + +#if VERSION_JP // TODO ASDF + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); +#endif } void filemenu_choose_name_init(MenuPanel* menu) { @@ -560,6 +570,7 @@ void filemenu_choose_name_handle_input(MenuPanel* menu) { sfx_play_sound(SOUND_MENU_NEXT); set_window_update(WIN_FILES_CONFIRM_OPTIONS, (s32) filemenu_update_show_name_confirm); +#if !VERSION_JP // TODO ASDF gWindows[WIN_FILES_CONFIRM_OPTIONS].pos.y = 121; gWindows[WIN_FILES_CONFIRM_OPTIONS].width = 69; gWindows[WIN_FILES_CONFIRM_OPTIONS].height = 44; @@ -580,6 +591,16 @@ void filemenu_choose_name_handle_input(MenuPanel* menu) { confirmMenu = filemenu_menus[filemenu_currentMenu]; confirmMenu->state = FM_CONFIRM_CREATE; filemenu_set_selected(confirmMenu, 0, 0); +#else +__asm__("nop"); +__asm__("nop"); +__asm__("nop"); +__asm__("nop"); +__asm__("nop"); +__asm__("nop"); +__asm__("nop"); +__asm__("nop"); +#endif } } diff --git a/src/filemenu/filemenu_info.c b/src/filemenu/filemenu_info.c index 352538474a..1e547a166e 100644 --- a/src/filemenu/filemenu_info.c +++ b/src/filemenu/filemenu_info.c @@ -103,7 +103,9 @@ void filemenu_info_draw_message_contents( switch (menu->state) { case FM_MESSAGE_DELETED: filemenu_draw_message(filemenu_get_menu_message(FILE_MESSAGE_FILE_26), baseX + 10, baseY + 4, 255, 0, 0); +#if !VERSION_JP // TODO ASDF draw_number(filemenu_menus[FILE_MENU_MAIN]->selected + 1, baseX + 48, baseY + 6 + NUMBER_OFFSET_Y, DRAW_NUMBER_CHARSET_NORMAL, MSG_PAL_WHITE, 255, DRAW_NUMBER_STYLE_MONOSPACE | DRAW_NUMBER_STYLE_ALIGN_RIGHT); +#endif filemenu_draw_message(filemenu_get_menu_message(FILE_MESSAGE_HAS_BEEN_DELETED), baseX + 49, baseY + 4, 255, 0, 0); break; case FM_MESSAGE_COPIED: @@ -136,6 +138,18 @@ void filemenu_info_draw_message_contents( } #endif filemenu_set_cursor_alpha(0); + +#if VERSION_JP // TODO ASDF + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); + +#endif } void filemenu_info_init(MenuPanel* tab) { diff --git a/src/filemenu/filemenu_main.c b/src/filemenu/filemenu_main.c index 1d6e7511ac..9949e2b281 100644 --- a/src/filemenu/filemenu_main.c +++ b/src/filemenu/filemenu_main.c @@ -659,6 +659,9 @@ void filemenu_draw_contents_file_title( } } #else +// #if VERSION_JP +// INCLUDE_ASM(s32, "filemenu/filemenu_main", filemenu_draw_contents_file_title); +// #else void filemenu_draw_contents_file_title( s32 fileIdx, MenuPanel* menu, @@ -672,6 +675,13 @@ void filemenu_draw_contents_file_title( filemenu_draw_message(filemenu_get_menu_message(FILE_MESSAGE_FILE_26), baseX + FILE_X, baseY + 1, 255, 0, 1); +#if VERSION_JP // TODO ASDF + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); +#endif if (!gSaveSlotHasData[fileIdx]) { draw_number(fileIdx + 1, baseX + FILE_NUMBER_X, baseY + 1 + NUMBER_OFFSET_Y, DRAW_NUMBER_CHARSET_THIN, MSG_PAL_WHITE, 255, DRAW_NUMBER_STYLE_MONOSPACE); } else { @@ -683,6 +693,7 @@ void filemenu_draw_contents_file_title( } } #endif +//#endif void filemenu_draw_contents_file_0_info( MenuPanel* menu, diff --git a/src/filemenu/filemenu_msg.c b/src/filemenu/filemenu_msg.c index 408faedfeb..318350ca01 100644 --- a/src/filemenu/filemenu_msg.c +++ b/src/filemenu/filemenu_msg.c @@ -686,6 +686,13 @@ s32 filemenu_draw_char(s32 c, s32 x, s32 y, s32 flag1, s32 color, s32 flag2) { } #endif +#if VERSION_JP // TODO ASDF + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); +#endif + if (c == MSG_CHAR_READ_SPACE) { return charWidth - 6; } diff --git a/src/filemenu/filemenu_yesno.c b/src/filemenu/filemenu_yesno.c index f9308c6a7b..e50497c184 100644 --- a/src/filemenu/filemenu_yesno.c +++ b/src/filemenu/filemenu_yesno.c @@ -120,6 +120,7 @@ MenuPanel filemenu_yesno_menuBP = { .fpCleanup = &filemenu_yesno_cleanup }; + void filemenu_yesno_draw_options_contents( MenuPanel* menu, s32 baseX, s32 baseY, @@ -199,7 +200,9 @@ void filemenu_yesno_draw_prompt_contents( xOffset = DELETE_FILE_FILE_X; filemenu_draw_message(filemenu_get_menu_message(FILE_MESSAGE_FILE_22), baseX + xOffset, baseY + 4, 0xFF, 0, 0); xOffset += DELETE_FILE_NUMBER_X; +#if !VERSION_JP // TODO ASDF draw_number(filemenu_menus[FILE_MENU_MAIN]->selected + 1, baseX + xOffset, baseY + 6 + NUMBER_OFFSET_Y, DRAW_NUMBER_CHARSET_NORMAL, MSG_PAL_WHITE, 0xFF, DRAW_NUMBER_STYLE_MONOSPACE | DRAW_NUMBER_STYLE_ALIGN_RIGHT); +#endif xOffset += DELETE_FILE_QMARK_X; filemenu_draw_message(filemenu_get_menu_message(FILE_MESSAGE_QUESTION), baseX + xOffset, baseY + 4, 0xFF, 0, 0); break; @@ -248,7 +251,9 @@ void filemenu_yesno_draw_prompt_contents( } #endif xOffset += START_GAME_FILE_X; +#if !VERSION_JP // TODO ASDF filemenu_draw_message(filemenu_get_menu_message(FILE_MESSAGE_FILE_22), baseX + xOffset, baseY + 4, 0xFF, 0, 0); +#endif xOffset += START_GAME_NUMBER_X; draw_number(filemenu_menus[FILE_MENU_MAIN]->selected + 1, baseX + xOffset, baseY + 6 + NUMBER_OFFSET_Y, DRAW_NUMBER_CHARSET_NORMAL, MSG_PAL_WHITE, 0xFF, DRAW_NUMBER_STYLE_MONOSPACE | DRAW_NUMBER_STYLE_ALIGN_RIGHT); xOffset += START_GAME_QMARK_X; @@ -259,6 +264,11 @@ void filemenu_yesno_draw_prompt_contents( #endif break; } + +#if VERSION_JP // TODO ASDF +__asm__("nop"); +__asm__("nop"); +#endif } void filemenu_yesno_init(MenuPanel* tab) { diff --git a/ver/jp/splat.yaml b/ver/jp/splat.yaml index 8416d5b57e..cd5629490c 100644 --- a/ver/jp/splat.yaml +++ b/ver/jp/splat.yaml @@ -28,6 +28,7 @@ options: symbol_name_format: JP_$VRAM symbol_name_format_no_rom: JP_$VRAM_$SEG hasm_in_src_path: True + use_legacy_include_asm: True asset_stack: - jp segments: @@ -1222,7 +1223,28 @@ segments: - [0x16A010, .data, pause_gfx] - [0x16B3F0] - - [0x16B550, bin] + - type: code + dir: filemenu + start: 0x16B550 + vram: 0x80242370 + subsegments: + - [0x16B550, c, filemenu_common] + - [0x16D5E0, c, filemenu_main] + - [0x16F6C0, c, filemenu_yesno] + - [auto, c, filemenu_info] + - [auto, c, filemenu_createfile] + - [auto, c, filemenu_gfx] + - [auto, c, filemenu_msg] + - [auto, c, filemenu_styles] + - start: 0x172000 + type: .data + name: filemenu_gfx + subsegments: + - [auto, ia4, copyarrow, 64, 16] + - [auto, rgba32, corners_yellow, 16, 64] + - [auto, ia8, corners_gray, 16, 32] + - [auto, .data, filemenu_gfx] ## ?????? this looks kinda borken + - [0x1749F0] - name: battle_code type: code @@ -14743,9 +14765,8 @@ segments: - [0xF19D60, bin] - - start: 0xFC0000 - type: pm_sbn - name: audio + - [0xFC0000, pm_sbn, audio] + - [ 0x1A01AF0, bin ] - start: 0x1A40000 diff --git a/ver/jp/symbol_addrs.txt b/ver/jp/symbol_addrs.txt index 19bf6600fd..236faa2719 100644 --- a/ver/jp/symbol_addrs.txt +++ b/ver/jp/symbol_addrs.txt @@ -5300,3 +5300,6 @@ D_0A000000_E91890 = 0x0A000000; // rom:0xE9A710 charset_peach_letter_png = 0x0000FC10; //rom:0x11EF40 charset_postcard_png = 0x00013B98; //rom:0x122EC8 charset_letter_content_1_png = 0x00015A80; //rom:0x124DB0 + +// the below might be wrong cause it's not disassembling +filemenu_draw_contents_file_title = 0x80242370; // type:func rom:0x16DDFC