From 1a5569bef573af78a6b723d052e0631329f82f6c Mon Sep 17 00:00:00 2001 From: petrie911 <69443847+petrie911@users.noreply.github.com> Date: Wed, 15 May 2024 13:41:15 -0500 Subject: [PATCH] Comptool support for byteswapped ROMs (#249) * comptool update * further updates * lodgenet * comptool and main split * one last thing --- .gitignore | 2 + Makefile | 2 +- include/sf64mesg.h | 192 +++++++++++++-------------- src/engine/fox_hud.c | 10 +- src/overlays/ovl_menu/fox_map.c | 4 +- tools/comptool.py | 223 +++++++++++++++++++++++++------- yamls/jp/rev0/main.yaml | 39 +++++- yamls/jp/rev0/overlays.yaml | 42 +++--- yamls/us/rev1/main.yaml | 2 +- yamls/us/rev1/overlays.yaml | 22 ++-- 10 files changed, 351 insertions(+), 187 deletions(-) diff --git a/.gitignore b/.gitignore index aa907133..d4735450 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,8 @@ ctx.c.m2c *_auto.ld *.n64 *.z64 +*.v64 +*.u64 *.bin *.otr *.eeprom diff --git a/Makefile b/Makefile index af00a638..e1e65dfa 100644 --- a/Makefile +++ b/Makefile @@ -444,7 +444,7 @@ endif decompress: $(BASEROM) @echo "Decompressing ROM..." - @$(PYTHON) $(COMPTOOL) $(DECOMPRESS_OPT) -de $(COMPTOOL_DIR) -m $(MIO0) $(BASEROM) $(BASEROM_UNCOMPRESSED) + @$(PYTHON) $(COMPTOOL) $(DECOMPRESS_OPT) -dse $(COMPTOOL_DIR) -m $(MIO0) $(BASEROM) $(BASEROM_UNCOMPRESSED) compress: $(BASEROM) @echo "Compressing ROM..." diff --git a/include/sf64mesg.h b/include/sf64mesg.h index d116b71c..3f7ded2c 100644 --- a/include/sf64mesg.h +++ b/include/sf64mesg.h @@ -68,104 +68,104 @@ void Radio_Draw(void); typedef enum MsgCharCode { // Non-printing and whitespace - MSGCHAR_END, // End message - MSGCHAR_NWL, // New line - MSGCHAR_NP2, // No effect - MSGCHAR_NP3, // No effect - MSGCHAR_NP4, // No effect - MSGCHAR_NP5, // No effect - MSGCHAR_NP6, // No effect - MSGCHAR_NP7, // No effect - MSGCHAR_PRI0, // Set message priority - MSGCHAR_PRI1, // Set message priority - MSGCHAR_PRI2, // Set message priority - MSGCHAR_PRI3, // Set message priority - MSGCHAR_SPC, // Space - MSGCHAR_QSP, // Quarter space - MSGCHAR_HSP, // Half Space - MSGCHAR_NXT, // Next text box + /* 0 */ MSGCHAR_END, // End message + /* 1 */ MSGCHAR_NWL, // New line + /* 2 */ MSGCHAR_NP2, // No effect + /* 3 */ MSGCHAR_NP3, // No effect + /* 4 */ MSGCHAR_NP4, // No effect + /* 5 */ MSGCHAR_NP5, // No effect + /* 6 */ MSGCHAR_NP6, // No effect + /* 7 */ MSGCHAR_NP7, // No effect + /* 8 */ MSGCHAR_PRI0, // Set message priority + /* 9 */ MSGCHAR_PRI1, // Set message priority + /* 10 */ MSGCHAR_PRI2, // Set message priority + /* 11 */ MSGCHAR_PRI3, // Set message priority + /* 12 */ MSGCHAR_SPC, // Space + /* 13 */ MSGCHAR_QSP, // Quarter space + /* 14 */ MSGCHAR_HSP, // Half Space + /* 15 */ MSGCHAR_NXT, // Next text box // printing characters - MSGCHAR_CLF, // C-Left - MSGCHAR_CUP, // C-Up - MSGCHAR_CRT, // C-Right - MSGCHAR_CDN, // C-Down - MSGCHAR_AUP, // Up arrow - MSGCHAR_ALF, // Left arrow - MSGCHAR_ADN, // Down arrow - MSGCHAR_ART, // Right arrow - MSGCHAR_A, // A - MSGCHAR_B, // B - MSGCHAR_C, // C - MSGCHAR_D, // D - MSGCHAR_E, // E - MSGCHAR_F, // F - MSGCHAR_G, // G - MSGCHAR_H, // H - MSGCHAR_I, // I - MSGCHAR_J, // J - MSGCHAR_K, // K - MSGCHAR_L, // L - MSGCHAR_M, // M - MSGCHAR_N, // N - MSGCHAR_O, // O - MSGCHAR_P, // P - MSGCHAR_Q, // Q - MSGCHAR_R, // R - MSGCHAR_S, // S - MSGCHAR_T, // T - MSGCHAR_U, // U - MSGCHAR_V, // V - MSGCHAR_W, // W - MSGCHAR_X, // X - MSGCHAR_Y, // Y - MSGCHAR_Z, // Z - MSGCHAR_a, // a - MSGCHAR_b, // b - MSGCHAR_c, // c - MSGCHAR_d, // d - MSGCHAR_e, // e - MSGCHAR_f, // f - MSGCHAR_g, // g - MSGCHAR_h, // h - MSGCHAR_i, // i - MSGCHAR_j, // j - MSGCHAR_k, // k - MSGCHAR_l, // l - MSGCHAR_m, // m - MSGCHAR_n, // n - MSGCHAR_o, // o - MSGCHAR_p, // p - MSGCHAR_q, // q - MSGCHAR_r, // r - MSGCHAR_s, // s - MSGCHAR_t, // t - MSGCHAR_u, // u - MSGCHAR_v, // v - MSGCHAR_w, // w - MSGCHAR_x, // x - MSGCHAR_y, // y - MSGCHAR_z, // z - MSGCHAR_EXM, // ! - MSGCHAR_QST, // ? - MSGCHAR_DSH, // - - MSGCHAR_CMA, // , - MSGCHAR_PRD, // . - MSGCHAR_0, // 0 - MSGCHAR_1, // 1 - MSGCHAR_2, // 2 - MSGCHAR_3, // 3 - MSGCHAR_4, // 4 - MSGCHAR_5, // 5 - MSGCHAR_6, // 6 - MSGCHAR_7, // 7 - MSGCHAR_8, // 8 - MSGCHAR_9, // 9 - MSGCHAR_APS, // ' - MSGCHAR_LPR, // ( - MSGCHAR_RPR, // ) - MSGCHAR_CLN, // : - MSGCHAR_PIP, // | + /* 16 */ MSGCHAR_CLF, // C-Left + /* 17 */ MSGCHAR_CUP, // C-Up + /* 18 */ MSGCHAR_CRT, // C-Right + /* 19 */ MSGCHAR_CDN, // C-Down + /* 20 */ MSGCHAR_AUP, // Up arrow + /* 21 */ MSGCHAR_ALF, // Left arrow + /* 22 */ MSGCHAR_ADN, // Down arrow + /* 23 */ MSGCHAR_ART, // Right arrow + /* 24 */ MSGCHAR_A, // A + /* 25 */ MSGCHAR_B, // B + /* 26 */ MSGCHAR_C, // C + /* 27 */ MSGCHAR_D, // D + /* 28 */ MSGCHAR_E, // E + /* 29 */ MSGCHAR_F, // F + /* 30 */ MSGCHAR_G, // G + /* 31 */ MSGCHAR_H, // H + /* 32 */ MSGCHAR_I, // I + /* 33 */ MSGCHAR_J, // J + /* 34 */ MSGCHAR_K, // K + /* 35 */ MSGCHAR_L, // L + /* 36 */ MSGCHAR_M, // M + /* 37 */ MSGCHAR_N, // N + /* 38 */ MSGCHAR_O, // O + /* 39 */ MSGCHAR_P, // P + /* 40 */ MSGCHAR_Q, // Q + /* 41 */ MSGCHAR_R, // R + /* 42 */ MSGCHAR_S, // S + /* 43 */ MSGCHAR_T, // T + /* 44 */ MSGCHAR_U, // U + /* 45 */ MSGCHAR_V, // V + /* 46 */ MSGCHAR_W, // W + /* 47 */ MSGCHAR_X, // X + /* 48 */ MSGCHAR_Y, // Y + /* 49 */ MSGCHAR_Z, // Z + /* 50 */ MSGCHAR_a, // a + /* 51 */ MSGCHAR_b, // b + /* 52 */ MSGCHAR_c, // c + /* 53 */ MSGCHAR_d, // d + /* 54 */ MSGCHAR_e, // e + /* 55 */ MSGCHAR_f, // f + /* 56 */ MSGCHAR_g, // g + /* 57 */ MSGCHAR_h, // h + /* 58 */ MSGCHAR_i, // i + /* 59 */ MSGCHAR_j, // j + /* 60 */ MSGCHAR_k, // k + /* 61 */ MSGCHAR_l, // l + /* 62 */ MSGCHAR_m, // m + /* 63 */ MSGCHAR_n, // n + /* 64 */ MSGCHAR_o, // o + /* 65 */ MSGCHAR_p, // p + /* 66 */ MSGCHAR_q, // q + /* 67 */ MSGCHAR_r, // r + /* 68 */ MSGCHAR_s, // s + /* 69 */ MSGCHAR_t, // t + /* 70 */ MSGCHAR_u, // u + /* 71 */ MSGCHAR_v, // v + /* 72 */ MSGCHAR_w, // w + /* 73 */ MSGCHAR_x, // x + /* 74 */ MSGCHAR_y, // y + /* 75 */ MSGCHAR_z, // z + /* 76 */ MSGCHAR_EXM, // ! + /* 77 */ MSGCHAR_QST, // ? + /* 78 */ MSGCHAR_DSH, // - + /* 79 */ MSGCHAR_CMA, // , + /* 80 */ MSGCHAR_PRD, // . + /* 81 */ MSGCHAR_0, // 0 + /* 82 */ MSGCHAR_1, // 1 + /* 83 */ MSGCHAR_2, // 2 + /* 84 */ MSGCHAR_3, // 3 + /* 85 */ MSGCHAR_4, // 4 + /* 86 */ MSGCHAR_5, // 5 + /* 87 */ MSGCHAR_6, // 6 + /* 88 */ MSGCHAR_7, // 7 + /* 89 */ MSGCHAR_8, // 8 + /* 90 */ MSGCHAR_9, // 9 + /* 91 */ MSGCHAR_APS, // ' + /* 92 */ MSGCHAR_LPR, // ( + /* 93 */ MSGCHAR_RPR, // ) + /* 94 */ MSGCHAR_CLN, // : + /* 95 */ MSGCHAR_PIP, // | } MsgCharCode; #endif diff --git a/src/engine/fox_hud.c b/src/engine/fox_hud.c index 29467f71..818a08fd 100644 --- a/src/engine/fox_hud.c +++ b/src/engine/fox_hud.c @@ -756,7 +756,7 @@ void HUD_DrawLevelClearScreen(void) { f32 x; f32 y; - if ((gPlayState != PLAY_PAUSE) && (gLevelClearScreenTimer)) { + if ((gPlayState != PLAY_PAUSE) && (gLevelClearScreenTimer != 0)) { gLevelClearScreenTimer--; } @@ -1057,7 +1057,7 @@ void HUD_DrawLevelClearStatusScreen(void) { D_801617C0[0] = 0; } - if ((gPlayState != PLAY_PAUSE) && (gShowLevelClearStatusScreen == 1) && (!D_801617E8[0])) { + if ((gPlayState != PLAY_PAUSE) && (gShowLevelClearStatusScreen == 1) && (D_801617E8[0] == 0)) { switch (D_801617C0[0]) { case 0: D_801617C0[5] = gHitCount; @@ -1415,7 +1415,7 @@ void func_hud_80088970(void) { player = &gPlayer[gPlayerNum]; - if ((gPlayState == PLAY_PAUSE) && !gLevelStartStatusScreenTimer && !gVersusMode) { + if ((gPlayState == PLAY_PAUSE) && (gLevelStartStatusScreenTimer == 0) && !gVersusMode) { switch (D_80161810[0]) { case 0: D_80161838[0] = 0; @@ -2014,7 +2014,7 @@ s32 func_hud_8008A4DC(void) { return 0; } - if (gLevelStartStatusScreenTimer) { + if (gLevelStartStatusScreenTimer != 0) { D_800D1E10 = 60.0f; } else { Math_SmoothStepToF(&D_800D1E10, 0.0f, 0.3f, 10.0f, 0.1f); @@ -2478,7 +2478,7 @@ s32 func_hud_8008B774(void) { switch (i) { case 0: - if (gPlayer[0].radioDamageTimer) { + if (gPlayer[0].radioDamageTimer != 0) { ret = 1; } break; diff --git a/src/overlays/ovl_menu/fox_map.c b/src/overlays/ovl_menu/fox_map.c index 32cb4948..2d22e6a0 100644 --- a/src/overlays/ovl_menu/fox_map.c +++ b/src/overlays/ovl_menu/fox_map.c @@ -5812,7 +5812,7 @@ void Map_801AB300(void) { break; case 210: - if (gRadioStateTimer) { + if (gRadioStateTimer != 0) { break; } @@ -5886,7 +5886,7 @@ void Map_801AB300(void) { break; case 41: - if (gRadioStateTimer) { + if (gRadioStateTimer != 0) { break; } diff --git a/tools/comptool.py b/tools/comptool.py index 8d324876..4bb3ff2a 100644 --- a/tools/comptool.py +++ b/tools/comptool.py @@ -6,18 +6,7 @@ import struct import argparse import sys -file_table_dict = {0xDE480:"US 1.1", 0xD9A90:"US 1.0", 0xE93C0:"JP 1.0"} - -file_names_us = [ - "makerom", "main", "dma_table", "audio_seq", "audio_bank", "audio_table", "ast_common", "ast_bg_space", "ast_bg_planet", - "ast_arwing", "ast_landmaster", "ast_blue_marine", "ast_versus", "ast_enmy_planet", "ast_enmy_space", "ast_great_fox", - "ast_star_wolf", "ast_allies", "ast_corneria", "ast_meteo", "ast_titania", "ast_7_ti_2", "ast_8_ti", "ast_9_ti", "ast_A_ti", - "ast_7_ti_1", "ast_sector_x", "ast_sector_z", "ast_aquas", "ast_area_6", "ast_venom_1", "ast_venom_2", "ast_ve1_boss", - "ast_bolse", "ast_fortuna", "ast_sector_y", "ast_solar", "ast_zoness", "ast_katina", "ast_macbeth", "ast_warp_zone", - "ast_title", "ast_map", "ast_option", "ast_vs_menu", "ast_text", "ast_font_3d", "ast_andross", "ast_logo", "ast_ending", - "ast_ending_award_front", "ast_ending_award_back", "ast_ending_expert", "ast_training", "ast_radio", "ovl_i1", "ovl_i2", - "ovl_i3", "ovl_i4", "ovl_i5", "ovl_i6", "ovl_menu", "ovl_ending", "ovl_unused" - ] +file_table_dict = {"US 1.1":0xDE480, "US 1.0":0xD9A90, "JP 1.0":0xE93C0, "JP 1.1":0xF2A10, "EU 1.0":0xE0570, "AU 1.0":0xE0470, "LN 1.0":0xE44F0} file_names_jp = [ "makerom", "main", "dma_table", "audio_seq", "audio_bank", "audio_table", "ast_common", "ast_bg_space", "ast_bg_planet", @@ -30,7 +19,63 @@ file_names_jp = [ "ovl_i3", "ovl_i4", "ovl_i5", "ovl_i6", "ovl_menu", "ovl_ending", "ovl_unused" ] -file_names_critical = {"makerom", "main", "dma_table", "audio_seq", "audio_bank", "audio_table"} +file_names_us = [ + "makerom", "main", "dma_table", "audio_seq", "audio_bank", "audio_table", "ast_common", "ast_bg_space", "ast_bg_planet", + "ast_arwing", "ast_landmaster", "ast_blue_marine", "ast_versus", "ast_enmy_planet", "ast_enmy_space", "ast_great_fox", + "ast_star_wolf", "ast_allies", "ast_corneria", "ast_meteo", "ast_titania", "ast_7_ti_2", "ast_8_ti", "ast_9_ti", "ast_A_ti", + "ast_7_ti_1", "ast_sector_x", "ast_sector_z", "ast_aquas", "ast_area_6", "ast_venom_1", "ast_venom_2", "ast_ve1_boss", + "ast_bolse", "ast_fortuna", "ast_sector_y", "ast_solar", "ast_zoness", "ast_katina", "ast_macbeth", "ast_warp_zone", + "ast_title", "ast_map", "ast_option", "ast_vs_menu", "ast_text", "ast_font_3d", "ast_andross", "ast_logo", "ast_ending", + "ast_ending_award_front", "ast_ending_award_back", "ast_ending_expert", "ast_training", "ast_radio", "ovl_i1", "ovl_i2", + "ovl_i3", "ovl_i4", "ovl_i5", "ovl_i6", "ovl_menu", "ovl_ending", "ovl_unused" + ] + +file_names_pal = [ + "makerom", "main", "dma_table", "audio_seq", "audio_bank", "audio_table", "ast_common", "ast_bg_space", "ast_bg_planet", + "ast_arwing", "ast_landmaster", "ast_blue_marine", "ast_versus", "ast_enmy_planet", "ast_enmy_space", "ast_great_fox", + "ast_star_wolf", "ast_allies", "ast_corneria", "ast_meteo", "ast_titania", "ast_7_ti_2", "ast_8_ti", "ast_9_ti", "ast_A_ti", + "ast_7_ti_1", "ast_sector_x", "ast_sector_z", "ast_aquas", "ast_area_6", "ast_venom_1", "ast_venom_2", "ast_ve1_boss", + "ast_bolse", "ast_fortuna", "ast_sector_y", "ast_solar", "ast_zoness", "ast_katina", "ast_macbeth", "ast_warp_zone", + "ast_title", "ast_map", "ast_option", "ast_vs_menu", "ast_text", "ast_unk_1", "ast_unk_2", "ast_unk_3", + "ast_unk_4", "ast_unk_5", "ast_unk_6", "ast_unk_7", "ast_unk_8", "ast_unk_9", "ast_font_3d", "ast_andross","ast_logo", "ast_ending", + "ast_ending_award_front", "ast_ending_award_back", "ast_ending_expert", "ast_training", "ast_radio_de", "ovl_i1", "ovl_i2", "ovl_i3", + "ovl_i4", "ovl_i5", "ovl_i6", "ovl_menu", "ovl_ending", "ovl_unused", "ast_radio_en", "ast_radio_fr" + ] + +file_names_critical = ["makerom", "main", "dma_table", "audio_seq", "audio_bank", "audio_table"] + +decomp_inds_ntsc = [0, 1, 2, 3, 4, 5, 15, 16, 21, 22, 23, 24, 48] +decomp_inds_pal = [0, 1, 2, 3, 4, 5, 15, 16, 21, 22, 23, 24, 57] + +def get_version_info(ROM): + with open(ROM, "rb") as ROMfile: + ROMfile.seek(0x3E, 0) + region = ROMfile.read(1).decode() + rev =" 1.%d" % int.from_bytes(ROMfile.read(1), 'big') + + + if region == "J": + file_names = file_names_jp + decomp_inds = decomp_inds_ntsc + version = "JP" + elif region == "E" or region == "G": + file_names = file_names_us + decomp_inds = decomp_inds_ntsc + version = "LN" if region == "G" else "US" + elif region == "P" or region == "U": + print("Warning: PAL menu assets are not fully documented.") + file_names = file_names_pal + decomp_inds = decomp_inds_pal + version = "AU" if region == "U" else "EU" + else: + file_names = "file_%d_%X" + decomp_inds = None + version = "Unknown" + + if version != "Unknown": + version += rev + + return (version, file_names, decomp_inds) def int32(x): return x & 0xFFFFFFFF @@ -101,35 +146,102 @@ def mio0_dec_bytes(comp_bytes, mio0): return decomp_bytes +swap_backup = False + +def fix_byte_swap(ROM, outROM): + with open(ROM, 'rb') as ROMfile: + ROMfile.seek(0x20,0) + + game_str = ROMfile.read(4).decode() + + if game_str == "STAR": + print("Provided ROM is big endian.") + return ROM + + ROMfile.seek(0,0) + + ROM_bytes = ROMfile.read() + + s = game_str.find("S") + t = game_str.find("T") + a = game_str.find("A") + r = game_str.find("R") + + if(s == -1 or t == -1 or a == -1 or r==-1): + print('Name string absent. There may be a problem with your ROM.') + sys.exit(2) + + if game_str == "RATS": + print("Provided ROM is little endian.") + byte_order = "LE" + suffix = ".LE.n64" + elif game_str == "TSRA": + print("Provided ROM is byteswapped.") + byte_order = "BS" + suffix = ".BS.v64" + else: + byte_order = "%d%d%d%d" % (s, t, a, r) + suffix = "." + byte_order + ".u64" + print("Provided ROM has unusual byte order " + byte_order) + if swap_backup: + backup = os.path.splitext(ROM)[0] + suffix + with open(backup, "wb") as bakfile: + print("Writing backup file " + backup) + bakfile.write(ROM_bytes) + outROM = ROM + + ROM_array = [bytearray([ROM_bytes[4*x + s], ROM_bytes[4*x + t], ROM_bytes[4*x + a], ROM_bytes[4*x + r]]) + for x in range(len(ROM_bytes) // 4) + ] + + with open(outROM, 'wb') as tempROMfile: + tempROMfile.write(b''.join(ROM_array)) + + return outROM + + def find_file_table(ROM): with open(ROM, 'rb') as ROMfile: ROMfile.seek(0,0) - main_area = ROMfile.read(0x100000) + main_area = ROMfile.read() file_table_start = main_area.find(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x50\x00\x00\x00\x00') + if file_table_start == -1: + file_table_start = main_area.find(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x60\x00\x00\x00\x00') - if(file_table_start == -1): + if file_table_start == -1: print('File table not found.') sys.exit(2) - elif(file_table_start > 0x100000): + elif file_table_start > 0x100000: print("Warning: Detected file table offset 0x%X is larger than expected." % file_table_start) # print(file_table_start) return file_table_start -decomp_inds = [0, 1, 2, 3, 4, 5, 15, 16, 21, 22, 23, 24, 48] def compress(baserom, comprom, mio0, dma_table=None, verbose=False): if dma_table: file_table = int(dma_table, 0) - print("Using provided DMA table offset 0x%X" % file_table) + if verbose: + print("Using provided DMA table offset 0x%X" % file_table) else: file_table = find_file_table(baserom) - print("DMA table found at 0x%X" % file_table) + if verbose: + print("DMA table found at 0x%X" % file_table) - print("Detected ROM version is " + file_table_dict.get(file_table, "Unknown")) + + (version, file_names, decomp_inds) = get_version_info(baserom) + ft_version = file_table_dict.get(version) + + if version == "Unknown": + print("Unknown version. Unable to determine compression scheme.") + sys.exit(2) + elif ft_version and ft_version != file_table: + print("Warning: No record of DMA table at 0x%X for %s" % (file_table, version)) + elif verbose: + print("Detected ROM version is " + version) # comp_const = 0xFFFEFFFFFE1E7FC0 @@ -137,7 +249,6 @@ def compress(baserom, comprom, mio0, dma_table=None, verbose=False): file_count = 0 p_file_begin = 0 - while True: file_entry = file_table + 0x10 * file_count basefile.seek(file_entry + 4) @@ -147,7 +258,7 @@ def compress(baserom, comprom, mio0, dma_table=None, verbose=False): v_file_size = v_file_end - v_file_begin - if(v_file_begin == 0 and v_file_end == 0): + if v_file_begin == 0 and v_file_end == 0: break basefile.seek(v_file_begin) @@ -155,10 +266,7 @@ def compress(baserom, comprom, mio0, dma_table=None, verbose=False): file_bytes = basefile.read(v_file_size) - if file_table_dict.get(file_table).startswith("JP"): - file_name = file_names_jp[file_count] - else: - file_name = file_names_us[file_count] + file_name = file_names[file_count] if (file_count in decomp_inds) or (file_name in file_names_critical): # if (1 << file_count) & comp_flags: @@ -210,20 +318,26 @@ def compress(baserom, comprom, mio0, dma_table=None, verbose=False): return def decompress(baserom, decomprom, mio0, extract_dest=None, dma_table=None, print_inds=False, verbose=False): + baserom = fix_byte_swap(baserom, baserom + "zxqj") + if dma_table: file_table = int(dma_table, 0) print("Using provided DMA table offset 0x%X" % file_table) else: file_table = find_file_table(baserom) print("DMA table found at 0x%X" % file_table) + + (version, file_names, decomp_inds) = get_version_info(baserom) + ft_version = file_table_dict.get(version) + - if file_table_dict.get(file_table): - version = file_table_dict.get(file_table) - print("Detected ROM version is " + version) + if version == "Unknown": + print("Could not detect version") + elif ft_version and ft_version != file_table: + print("Warning: No record of DMA table at 0x%X for %s" % (file_table, version)) else: - print("Could not detect version.") - version = "Unknown" - + print("Detected ROM version is " + version) + with open(decomprom, 'w+b') as decompfile, open(baserom, 'rb') as basefile: file_count = 0 decomp_file_inds = [] @@ -241,7 +355,7 @@ def decompress(baserom, decomprom, mio0, extract_dest=None, dma_table=None, prin #print(v_file_begin, p_file_begin, p_file_end, comp_flag) - if(v_file_begin == 0 and p_file_end == 0): + if v_file_begin == 0 and p_file_end == 0: break decompfile.truncate(v_file_begin) @@ -254,6 +368,7 @@ def decompress(baserom, decomprom, mio0, extract_dest=None, dma_table=None, prin v_file_size = p_file_size decomp_file_inds += [file_count] dec_msg = 'uncompressed' + elif comp_flag == 1: file_bytes = mio0_dec_bytes(file_bytes, mio0) dec_msg = 'compressed' @@ -268,14 +383,15 @@ def decompress(baserom, decomprom, mio0, extract_dest=None, dma_table=None, prin v_file_end = v_file_begin + v_file_size - if file_table_dict.get(file_table).startswith("JP"): - file_name = file_names_jp[file_count] + if decomp_inds: + file_name = file_names[file_count] else: - file_name = file_names_us[file_count] - - if(verbose): + file_name = file_names % (file_count, v_file_begin) + + if verbose: print("name: " + file_name) print("start: 0x%X" % v_file_begin) + # print("index", file_count, dec_msg, "; size: 0x%X" % v_file_size) if extract_dest is not None: if not os.path.exists(extract_dest): @@ -284,7 +400,7 @@ def decompress(baserom, decomprom, mio0, extract_dest=None, dma_table=None, prin if version == "Unknown": suffix = "%X" % file_table else: - suffix = version.replace("1.", ".rev").lower() + suffix = version.replace(" 1.", ".rev").lower() out_file_name = file_name + "." + suffix + ".bin" with open(extract_dest + os.sep + out_file_name, 'wb') as extract_file: @@ -312,21 +428,25 @@ def decompress(baserom, decomprom, mio0, extract_dest=None, dma_table=None, prin elif decomp_file_inds != decomp_inds: print("Warning: Unusual compression scheme. These files were uncompressed:") print(decomp_file_inds) + + if baserom.endswith("zxqj"): + run(["rm", baserom]) + return parser = argparse.ArgumentParser(description='Compress or decompress a Star Fox 64 ROM') -parser.add_argument('inROM', help="ROM file to compress or decompress") -parser.add_argument('outROM', help="output file for processed ROM.") -parser.add_argument('-c', action='store_true',help='compress provided ROM') -parser.add_argument('-d', action='store_true',help='decompress provided ROM') -parser.add_argument('-e', metavar='extract',dest='extract',help='directory for extracted decompressed files. Use with -d') -parser.add_argument('-r', action="store_true",help='Fix crc without compressing or decompressing') -parser.add_argument('-m', metavar='mio0',dest='mio0',help='Path to mio0 tool if not in same directory') +parser.add_argument('inROM', help="ROM file to process") +parser.add_argument('outROM', help="Output file for processed ROM.") +parser.add_argument('-c', action='store_true',help='Compress a big endian uncompressed Star Fox 64 ROM') +parser.add_argument('-d', action='store_true',help='Decompress a Star Fox 64 ROM. Use with -s to also make a big endian compressed ROM.') +parser.add_argument('-e', metavar='extract',dest='extract',help='Directory for extracted decompressed files. Use with -d') +parser.add_argument('-r', action="store_true",help='Fix crc of Star Fox 64 ROM without compressing or decompressing') +parser.add_argument('-s', action='store_true',help='Swap a Star Fox 64 ROM to big endian (.z64). Use . as second argument to swap in-place or .b to also make a backup') +parser.add_argument('-m', metavar='mio0',dest='mio0',help='Path to mio0 tool if not named "mio0" and in same directory') parser.add_argument('-i', action='store_true',help='Print indices of uncompressed files during decompression.') parser.add_argument('-v', action='store_true',help='Print details about the ROM files.') parser.add_argument('-t', metavar='dma_table', dest='dma_table',help='Provide DMA table explicitly instead of autodetecting') - if __name__ == '__main__': args = parser.parse_args() @@ -340,7 +460,14 @@ if __name__ == '__main__': elif args.c: compress(args.inROM, args.outROM, mio0, dma_table=args.dma_table, verbose=args.v) elif args.d or args.extract: + swap_backup = args.s decompress(args.inROM, args.outROM, mio0, extract_dest=args.extract, dma_table=args.dma_table, print_inds=args.i, verbose=args.v) + elif args.s: + if args.outROM[0] == ".": + args.outRom = args.inRom + if args.outROM == ".b": + swap_backup = True + fix_byte_swap(args.inROM, args.outROM) else: - print("Something went wrong.") + print("No action specified. Use -c, -d, -e, -r, or -s to specify an action") diff --git a/yamls/jp/rev0/main.yaml b/yamls/jp/rev0/main.yaml index 754a6248..9bbb4b9f 100644 --- a/yamls/jp/rev0/main.yaml +++ b/yamls/jp/rev0/main.yaml @@ -260,8 +260,43 @@ - [0xE7650, data, wave_samples] - [0xE8270, data, note_data] - # bss - - { start: 0xE93C0, type: bss, vram: 0x800E87C0, name: main } + # Nintendo Library bss + - { type: bss, vram: 0x800E87C0, name: sys_joybus } + - { type: bss, vram: 0x800E89E0, name: sys_main } + - { type: bss, vram: 0x801462E0, name: sys_math } + - { type: bss, vram: 0x80146300, name: sys_matrix } + - { type: bss, vram: 0x80147310, name: sys_memory } + - { type: bss, vram: 0x8014FB20, name: sys_timer } + - { type: bss, vram: 0x8014FEA0, name: sys_save } + - { type: bss, vram: 0x801502A0, name: sys_fault } + - { type: bss, vram: 0x80150C80, name: audio/audio_synthesis } + - { type: bss, vram: 0x80151CC0, name: audio/audio_load } + - { type: bss, vram: 0x80151DA0, name: audio/audio_general } + - { type: bss, vram: 0x80156980, name: audio/audio_context } + - { type: bss, vram: 0x80160CE0, name: audio/audio_thread } + + # Libultra bss + - { type: bss, vram: 0x80161560, name: libultra } + + # Game engine bss + - { type: .bss, vram: 0x801650A0, name: engine/fox_360 } + - { type: .bss, vram: 0x801650F0, name: engine/fox_beam } + - { type: .bss, vram: 0x80165100, name: engine/fox_bg } + - { type: .bss, vram: 0x80166B40, name: engine/fox_boss } + - { type: .bss, vram: 0x80166B50, name: engine/fox_display } + - { type: .bss, vram: 0x80166D70, name: engine/fox_edisplay } + - { type: .bss, vram: 0x80166E10, name: engine/fox_enmy } + - { type: .bss, vram: 0x80166E30, name: engine/fox_enmy2 } + - { type: .bss, vram: 0x80166E40, name: engine/fox_hud } + - { type: .bss, vram: 0x801670F0, name: engine/fox_col1 } + - { type: .bss, vram: 0x80167140, name: engine/fox_std_lib } + - { type: .bss, vram: 0x801671B0, name: engine/fox_game } + - { type: .bss, vram: 0x801671F0, name: engine/fox_play } + - { type: .bss, vram: 0x80167210, name: engine/fox_context} + - { type: .bss, vram: 0x8017DD20, name: engine/fox_rcp } + - { type: .bss, vram: 0x8017DEC0, name: engine/fox_radio } + - { type: .bss, vram: 0x8017DEF0, name: engine/fox_versus } + - { type: .bss, vram: 0x8017E010, name: engine/fox_save } - name: dma_table type: code diff --git a/yamls/jp/rev0/overlays.yaml b/yamls/jp/rev0/overlays.yaml index 0ba6e18d..8f59011c 100644 --- a/yamls/jp/rev0/overlays.yaml +++ b/yamls/jp/rev0/overlays.yaml @@ -21,9 +21,9 @@ - [0xDBD410, .rodata, fox_ve1] - [0xDBD7A0, .rodata, fox_tr] - [0xDBD7E0, .rodata, fox_tr360] - - { start: 0xDBD820, type: bss, vram: 0x80192940, name: fox_i1 } - - { start: 0xDBD820, type: bss, vram: 0x80192950, name: fox_co } - - { start: 0xDBD820, type: bss, vram: 0x80192A70, name: fox_ve1 } + - { type: bss, vram: 0x80192940, name: fox_i1 } + - { type: bss, vram: 0x80192950, name: fox_co } + - { type: bss, vram: 0x80192A70, name: fox_ve1 } - name: ovl_i2 exclusive_ram_id: overlay @@ -43,8 +43,8 @@ - [0xDCB8F0, data, fox_sx] - [0xDCBA40, .rodata, fox_me] - [0xDCBD00, .rodata, fox_sx] - - { start: 0xDCC020, type: bss, vram: 0x8018CFA0, name: fox_i2 } - - { start: 0xDCC020, type: bss, vram: 0x8018CFB0, name: fox_sx } + - { type: bss, vram: 0x8018CFA0, name: fox_i2 } + - { type: bss, vram: 0x8018CFB0, name: fox_sx } - name: ovl_i3 exclusive_ram_id: overlay @@ -70,11 +70,11 @@ - [0xE058E0, .rodata, fox_zo] - [0xE06000, .rodata, fox_so] - [0xE06560, .rodata, fox_aq] - - { start: 0xE06D70, type: bss, vram: 0x801B94F0, name: fox_i3 } - - { start: 0xE06D70, type: bss, vram: 0x801B9500, name: fox_a6 } - - { start: 0xE06D70, type: bss, vram: 0x801B95E0, name: fox_zo } - - { start: 0xE06D70, type: bss, vram: 0x801B99F0, name: fox_so } - - { start: 0xE06D70, type: bss, vram: 0x801B9A70, name: fox_aq } + - { type: bss, vram: 0x801B94F0, name: fox_i3 } + - { type: bss, vram: 0x801B9500, name: fox_a6 } + - { type: bss, vram: 0x801B95E0, name: fox_zo } + - { type: bss, vram: 0x801B99F0, name: fox_so } + - { type: bss, vram: 0x801B9A70, name: fox_aq } - name: ovl_i4 @@ -102,10 +102,10 @@ - [0xE1EDE0, .rodata, fox_bo] - [0xE1F1E0, .rodata, fox_ka] - [0xE1F570, .rodata, fox_sz] - - { start: 0xE1F870, type: bss, vram: 0x801972A0, name: fox_i4 } - - { start: 0xE1F870, type: bss, vram: 0x801972B0, name: fox_bo } - - { start: 0xE1F870, type: bss, vram: 0x80197420, name: fox_ka } - - { start: 0xE1F870, type: bss, vram: 0x80197440, name: fox_sz } + - { type: bss, vram: 0x801972A0, name: fox_i4 } + - { type: bss, vram: 0x801972B0, name: fox_bo } + - { type: bss, vram: 0x80197420, name: fox_ka } + - { type: bss, vram: 0x80197440, name: fox_sz } - name: ovl_i5 @@ -133,10 +133,10 @@ - [0xE52E30, .rodata, fox_ti] - [0xE53690, .rodata, fox_ma] - [0xE541D0, .rodata, fox_ground] - - { start: 0xE542C0, type: bss, vram: 0x801B31F0, name: fox_i5 } - - { start: 0xE542C0, type: bss, vram: 0x801B3200, name: fox_ti } - - { start: 0xE542C0, type: bss, vram: 0x801B5540, name: fox_ma } - - { start: 0xE542C0, type: bss, vram: 0x801B5A40, name: fox_ground } + - { type: bss, vram: 0x801B31F0, name: fox_i5 } + - { type: bss, vram: 0x801B3200, name: fox_ti } + - { type: bss, vram: 0x801B5540, name: fox_ma } + - { type: bss, vram: 0x801B5A40, name: fox_ground } - name: ovl_i6 @@ -164,9 +164,9 @@ - [0xE74210, .rodata, fox_ve2] - [0xE74250, .rodata, fox_sy] - [0xE74CA0, .rodata, fox_turret] - - { start: 0xE74D00, type: bss, vram: 0x8019F1E0, name: fox_i6 } - - { start: 0xE74D00, type: bss, vram: 0x8019F1F0, name: fox_andross } - - { start: 0xE74D00, type: bss, vram: 0x8019F6E0, name: fox_sy } + - { type: bss, vram: 0x8019F1E0, name: fox_i6 } + - { type: bss, vram: 0x8019F1F0, name: fox_andross } + - { type: bss, vram: 0x8019F6E0, name: fox_sy } - name: ovl_menu diff --git a/yamls/us/rev1/main.yaml b/yamls/us/rev1/main.yaml index d570589c..bd7b919c 100644 --- a/yamls/us/rev1/main.yaml +++ b/yamls/us/rev1/main.yaml @@ -340,7 +340,7 @@ - [0xDD330, .data, audio/note_data] # Nintendo Library bss - - { start: 0xDE480, type: .bss, vram: 0x800DD880, name: sys/sys_joybus } + - { type: .bss, vram: 0x800DD880, name: sys/sys_joybus } - { type: .bss, vram: 0x800DDAA0, name: sys/sys_main } - { type: .bss, vram: 0x8013B3A0, name: sys/sys_math } - { type: .bss, vram: 0x8013B3C0, name: sys/sys_matrix } diff --git a/yamls/us/rev1/overlays.yaml b/yamls/us/rev1/overlays.yaml index 3c868211..c4947cd6 100644 --- a/yamls/us/rev1/overlays.yaml +++ b/yamls/us/rev1/overlays.yaml @@ -21,7 +21,7 @@ - [0xE07FF0, .rodata, fox_ve1] - [0xE08380, .rodata, fox_tr] - [0xE083C0, .rodata, fox_tr360] - - { start: 0xE08400, type: .bss, vram: 0x8019B6C0, name: fox_i1 } + - { type: .bss, vram: 0x8019B6C0, name: fox_i1 } - { type: .bss, vram: 0x8019B6D0, name: fox_co } - { type: .bss, vram: 0x8019B7F0, name: fox_ve1 } @@ -43,7 +43,7 @@ - [0xE16520, .data, fox_sx] - [0xE16670, .rodata, fox_me] - [0xE16930, .rodata, fox_sx] - - { start: 0xE16C50, type: .bss, vram: 0x80195D70, name: fox_i2 } + - { type: .bss, vram: 0x80195D70, name: fox_i2 } - { type: .bss, vram: 0x80195D80, name: fox_sx } - name: ovl_i3 @@ -70,7 +70,7 @@ - [0xE504E0, .rodata, fox_zo] - [0xE50C00, .rodata, fox_so] - [0xE51160, .rodata, fox_aq] - - { start: 0xE51970, type: .bss, vram: 0x801C2240, name: fox_i3 } + - { type: .bss, vram: 0x801C2240, name: fox_i3 } - { type: .bss, vram: 0x801C2250, name: fox_a6 } - { type: .bss, vram: 0x801C2330, name: fox_zo } - { type: .bss, vram: 0x801C2740, name: fox_so } @@ -101,7 +101,7 @@ - [0xE69D70, .rodata, fox_bo] - [0xE6A170, .rodata, fox_ka] - [0xE6A510, .rodata, fox_sz] - - { start: 0xE6A810, type: .bss, vram: 0x801A03C0, name: fox_i4 } + - { type: .bss, vram: 0x801A03C0, name: fox_i4 } - { type: .bss, vram: 0x801A03D0, name: fox_bo } - { type: .bss, vram: 0x801A0540, name: fox_ka } - { type: .bss, vram: 0x801A0560, name: fox_sz } @@ -112,7 +112,7 @@ dir: overlays/ovl_i5 start: 0xE6A810 vram: 0x80187520 - follows_vram: ast_radio + # follows_vram: ast_radio bss_size: 0xAF80 symbol_name_format: i5_$VRAM subsegments: @@ -131,7 +131,7 @@ - [0xE9DD40, .rodata, fox_ti] - [0xE9E5A0, .rodata, fox_ma] - [0xE9F0E0, .rodata, fox_ground] - - { start: 0xE9F1D0, type: .bss, vram: 0x801BBEE0, name: fox_i5 } + - { type: .bss, vram: 0x801BBEE0, name: fox_i5 } - { type: .bss, vram: 0x801BBEF0, name: fox_ti } - { type: .bss, vram: 0x801BE240, name: fox_ma } - { type: .bss, vram: 0x801BE740, name: fox_ground } @@ -161,7 +161,7 @@ - [0xEBF0F0, .rodata, fox_ve2] - [0xEBF130, .rodata, fox_sy] - [0xEBFB80, .rodata, fox_turret] - - { start: 0xEBFBE0, type: .bss, vram: 0x801A7F30, name: fox_i6 } + - { type: .bss, vram: 0x801A7F30, name: fox_i6 } - { type: .bss, vram: 0x801A7F40, name: fox_andross } - { type: .bss, vram: 0x801A8440, name: fox_sy } @@ -187,7 +187,7 @@ - [0xEEF430, .rodata, fox_title] - [0xEEF7D0, .rodata, fox_option] - [0xEEFB80, .rodata, fox_map] - - { start: 0xEF0260, type: .bss, vram: 0x801B7BA0, name: fox_i_menu } + - { type: .bss, vram: 0x801B7BA0, name: fox_i_menu } - { type: .bss, vram: 0x801B7BB0, name: fox_title } - { type: .bss, vram: 0x801B9090, name: fox_option } - { type: .bss, vram: 0x801B9410, name: fox_map } @@ -208,7 +208,7 @@ - [0xEFBBB0, .data, fox_end2] - [0xEFEF80, .rodata, fox_end1] - [0xEFF380, .rodata, fox_end2] - - { start: 0xEFFA40, type: .bss, vram: 0x80196D00, name: fox_end1 } + - { type: .bss, vram: 0x80196D00, name: fox_end1 } - { type: .bss, vram: 0x80198590, name: fox_end2 } - name: ovl_unused @@ -223,7 +223,7 @@ subsegments: - [0xEFFA40, c, fox_unused] - [0xEFFA50, .data, fox_unused] - - { start: 0xEFFAE0, type: .bss, vram: 0x801875C0, name: fox_unused } + - { type: .bss, vram: 0x801875C0, name: fox_unused } - name: buffers exclusive_ram_id: buffer @@ -232,6 +232,6 @@ vram: 0x80281000 bss_size: 0x17F000 subsegments: - - { start: 0xEFFAE0, type: .bss, vram: 0x80281000, name: buffers } + - { type: .bss, vram: 0x80281000, name: buffers } - [0xEFFAE0] \ No newline at end of file