From e3ab616137074b103517d3ee057ff883f12855c4 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Thu, 11 Jan 2024 00:38:07 +0000 Subject: [PATCH 01/24] Add initial work towards patch support --- Makefile | 2 + src/menu/menu.c | 1 + src/menu/menu_state.h | 5 ++ src/menu/rom_patcher.c | 0 src/menu/rom_patcher.h | 24 ++++++ src/menu/views/browser.c | 8 ++ src/menu/views/load_patch.c | 141 ++++++++++++++++++++++++++++++++++++ src/menu/views/views.h | 3 + 8 files changed, 184 insertions(+) create mode 100644 src/menu/rom_patcher.c create mode 100644 src/menu/rom_patcher.h create mode 100644 src/menu/views/load_patch.c diff --git a/Makefile b/Makefile index 2cc28f62..0fbda6aa 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,7 @@ SRCS = \ menu/path.c \ menu/png_decoder.c \ menu/rom_info.c \ + menu/rom_patcher.c \ menu/settings.c \ menu/sound.c \ menu/usb_comm.c \ @@ -58,6 +59,7 @@ SRCS = \ menu/views/load_disk.c \ menu/views/load_emulator.c \ menu/views/load_rom.c \ + menu/views/load_patch.c \ menu/views/music_player.c \ menu/views/startup.c \ menu/views/system_info.c \ diff --git a/src/menu/menu.c b/src/menu/menu.c index 7cd3758a..7a201e86 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -151,6 +151,7 @@ static struct views_s { { view_rtc_init, view_rtc_display }, // MENU_MODE_RTC { view_load_rom_init, view_load_rom_display }, // MENU_MODE_LOAD_ROM { view_load_disk_init, view_load_disk_display }, // MENU_MODE_LOAD_DISK + { view_load_rom_patch_init, view_load_rom_patch_display }, // MENU_MODE_LOAD_PATCH { view_load_emulator_init, view_load_emulator_display }, // MENU_MODE_LOAD_EMULATOR { view_error_init, view_error_display }, // MENU_MODE_ERROR { view_fault_init, view_fault_display }, // MENU_MODE_FAULT diff --git a/src/menu/menu_state.h b/src/menu/menu_state.h index d29573d4..17c91efc 100644 --- a/src/menu/menu_state.h +++ b/src/menu/menu_state.h @@ -12,6 +12,7 @@ #include "boot/boot.h" #include "disk_info.h" +#include "rom_patcher.h" #include "flashcart/flashcart.h" #include "path.h" #include "rom_info.h" @@ -35,6 +36,7 @@ typedef enum { MENU_MODE_RTC, MENU_MODE_LOAD_ROM, MENU_MODE_LOAD_DISK, + MENU_MODE_LOAD_PATCH, MENU_MODE_LOAD_EMULATOR, MENU_MODE_ERROR, MENU_MODE_FAULT, @@ -47,6 +49,7 @@ typedef enum { ENTRY_TYPE_DIR, ENTRY_TYPE_ROM, ENTRY_TYPE_DISK, + ENTRY_TYPE_PATCH, ENTRY_TYPE_EMULATOR, ENTRY_TYPE_SAVE, ENTRY_TYPE_IMAGE, @@ -102,6 +105,8 @@ typedef struct { rom_info_t rom_info; path_t *disk_path; disk_info_t disk_info; + path_t *patch_path; + //patch_info_t patch_info; } load; } menu_t; diff --git a/src/menu/rom_patcher.c b/src/menu/rom_patcher.c new file mode 100644 index 00000000..e69de29b diff --git a/src/menu/rom_patcher.h b/src/menu/rom_patcher.h new file mode 100644 index 00000000..27c71d1c --- /dev/null +++ b/src/menu/rom_patcher.h @@ -0,0 +1,24 @@ +/** + * @file patcher.h + * @brief N64 ROM patcher + * @ingroup menu + */ + +#ifndef ROM_PATCHER_H__ +#define ROM_PATCHER_H__ + + +#include +#include + +/** @brief Patch state enumeration. */ +typedef enum { + PATCH_OK, + PATCH_ERR_IO, + PATCH_ERR_NO_FILE, + PATCH_ERR_INVALID, +} rom_patcher_err_t; + +rom_patcher_err_t rom_patcher_load (char *path); + +#endif diff --git a/src/menu/views/browser.c b/src/menu/views/browser.c index 75ab0a4a..8612b311 100644 --- a/src/menu/views/browser.c +++ b/src/menu/views/browser.c @@ -34,6 +34,10 @@ static int compare_entry (const void *pa, const void *pb) { return -1; } else if (b->type == ENTRY_TYPE_DISK) { return 1; + } else if (a->type == ENTRY_TYPE_PATCH) { + return -1; + } else if (b->type == ENTRY_TYPE_PATCH) { + return 1; } else if (a->type == ENTRY_TYPE_EMULATOR) { return -1; } else if (b->type == ENTRY_TYPE_EMULATOR) { @@ -294,6 +298,9 @@ static void process (menu_t *menu) { case ENTRY_TYPE_DISK: menu->next_mode = MENU_MODE_LOAD_DISK; break; + case ENTRY_TYPE_PATCH: + menu->next_mode = MENU_MODE_LOAD_PATCH; + break; case ENTRY_TYPE_EMULATOR: menu->next_mode = MENU_MODE_LOAD_EMULATOR; break; @@ -336,6 +343,7 @@ static void draw (menu_t *menu, surface_t *d) { case ENTRY_TYPE_DIR: action = "A: Enter"; break; case ENTRY_TYPE_ROM: action = "A: Load"; break; case ENTRY_TYPE_DISK: action = "A: Load"; break; + case ENTRY_TYPE_PATCH: action = "A: Load"; break; case ENTRY_TYPE_IMAGE: action = "A: Show"; break; case ENTRY_TYPE_MUSIC: action = "A: Play"; break; default: action = "A: Info"; break; diff --git a/src/menu/views/load_patch.c b/src/menu/views/load_patch.c new file mode 100644 index 00000000..64f05496 --- /dev/null +++ b/src/menu/views/load_patch.c @@ -0,0 +1,141 @@ +#include "../cart_load.h" +#include "../rom_patcher.h" +#include "boot/boot.h" +#include "views.h" + + +static bool load_pending; +static bool load_rom; + + +// static char *convert_error_message (rom_patcher_err_t err) { +// switch (err) { +// case PATCH_ERR_IO: return "I/O error during loading patch file information"; +// case PATCH_ERR_NO_FILE: return "Couldn't open patch file"; +// case PATCH_ERR_INVALID: return "Invalid patch file"; +// default: return "Unknown patch info load error"; +// } +// } + + +static void process (menu_t *menu) { + if (menu->actions.enter) { + load_pending = true; + load_rom = false; + } else if (menu->actions.options && menu->load.rom_path) { + load_pending = true; + load_rom = true; + } else if (menu->actions.back) { + menu->next_mode = MENU_MODE_BROWSER; + } +} + +static void draw (menu_t *menu, surface_t *d) { + rdpq_attach(d, NULL); + + component_background_draw(); + + if (load_pending) { + component_loader_draw(0.0f); + } else { + component_layout_draw(); + + component_main_text_draw( + ALIGN_CENTER, VALIGN_TOP, + "Patch information\n" + "\n" + "%s", + menu->browser.entry->name + ); + + component_main_text_draw( + ALIGN_LEFT, VALIGN_TOP, + "\n" + "\n" + "\n" + " %s%s", + menu->load.rom_path ? "ROM: " : "", + menu->load.rom_path ? path_last_get(menu->load.rom_path) : "" + ); + + component_actions_bar_text_draw( + ALIGN_LEFT, VALIGN_TOP, + "A: Load ROM\n" + "B: Exit" + ); + + if (menu->load.rom_path) { + component_actions_bar_text_draw( + ALIGN_RIGHT, VALIGN_TOP, + "R: Load patched ROM" + ); + } + } + + rdpq_detach_show(); +} + +static void draw_progress (float progress) { + surface_t *d = (progress >= 1.0f) ? display_get() : display_try_get(); + + if (d) { + rdpq_attach(d, NULL); + + component_background_draw(); + + component_loader_draw(progress); + + rdpq_detach_show(); + } +} + +static void load (menu_t *menu) { + cart_load_err_t err; + + if (menu->load.rom_path && load_rom) { + err = cart_load_n64_rom_and_save(menu, draw_progress); + if (err != CART_LOAD_OK) { + menu_show_error(menu, cart_load_convert_error_message(err)); + return; + } + } + + // err = cart_load_rom_and_patch(menu, draw_progress); + // if (err != CART_LOAD_OK) { + // menu_show_error(menu, cart_load_convert_error_message(err)); + // return; + // } + + menu->next_mode = MENU_MODE_BOOT; + menu->boot_params->device_type = BOOT_DEVICE_TYPE_ROM; + menu->boot_params->tv_type = BOOT_TV_TYPE_PASSTHROUGH; + menu->boot_params->detect_cic_seed = true; +} + + +void view_load_rom_patch_init (menu_t *menu) { + if (menu->load.patch_path) { + path_free(menu->load.patch_path); + menu->load.patch_path = NULL; + } + + load_pending = false; + + menu->load.patch_path = path_clone_push(menu->browser.directory, menu->browser.entry->name); + + // rom_patcher_err_t err = patch_info_load(path_get(menu->load.patch_path), &menu->load.patch_info); + // if (err != PATCH_OK) { + // menu_show_error(menu, convert_error_message(err)); + // } +} + +void view_load_rom_patch_display (menu_t *menu, surface_t *display) { + process(menu); + + draw(menu, display); + + if (load_pending) { + load_pending = false; + load(menu); + } +} diff --git a/src/menu/views/views.h b/src/menu/views/views.h index 2b7e0660..b30f6418 100644 --- a/src/menu/views/views.h +++ b/src/menu/views/views.h @@ -44,6 +44,9 @@ void view_load_rom_display (menu_t *menu, surface_t *display); void view_load_disk_init (menu_t *menu); void view_load_disk_display (menu_t *menu, surface_t *display); +void view_load_rom_patch_init (menu_t *menu); +void view_load_rom_patch_display (menu_t *menu, surface_t *display); + void view_settings_init (menu_t *menu); void view_settings_display (menu_t *menu, surface_t *display); From 52561a9c7d469dbd0ecd2c1993c563dbfa8989f8 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Thu, 11 Jan 2024 00:38:07 +0000 Subject: [PATCH 02/24] Add initial work towards patch support --- Makefile | 2 + libdragon | 2 +- src/menu/menu.c | 1 + src/menu/menu_state.h | 5 ++ src/menu/rom_patcher.c | 0 src/menu/rom_patcher.h | 24 ++++++ src/menu/views/browser.c | 8 ++ src/menu/views/load_patch.c | 141 ++++++++++++++++++++++++++++++++++++ src/menu/views/views.h | 3 + 9 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 src/menu/rom_patcher.c create mode 100644 src/menu/rom_patcher.h create mode 100644 src/menu/views/load_patch.c diff --git a/Makefile b/Makefile index 7c0ec049..10b241e8 100644 --- a/Makefile +++ b/Makefile @@ -47,6 +47,7 @@ SRCS = \ menu/path.c \ menu/png_decoder.c \ menu/rom_info.c \ + menu/rom_patcher.c \ menu/settings.c \ menu/sound.c \ menu/usb_comm.c \ @@ -60,6 +61,7 @@ SRCS = \ menu/views/load_disk.c \ menu/views/load_emulator.c \ menu/views/load_rom.c \ + menu/views/load_patch.c \ menu/views/music_player.c \ menu/views/startup.c \ menu/views/system_info.c \ diff --git a/libdragon b/libdragon index 185c4a34..6323128d 160000 --- a/libdragon +++ b/libdragon @@ -1 +1 @@ -Subproject commit 185c4a34f265c90d027f4054024cff1675529d7f +Subproject commit 6323128d72fdf32dfaa134f40191ba72e5527076 diff --git a/src/menu/menu.c b/src/menu/menu.c index 1b8832cb..b904acd3 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -157,6 +157,7 @@ static view_t menu_views[] = { { MENU_MODE_LOAD_ROM, view_load_rom_init, view_load_rom_display }, { MENU_MODE_LOAD_DISK, view_load_disk_init, view_load_disk_display }, { MENU_MODE_LOAD_EMULATOR, view_load_emulator_init, view_load_emulator_display }, + { MENU_MODE_LOAD_PATCH, view_load_rom_patch_display }, { MENU_MODE_ERROR, view_error_init, view_error_display }, { MENU_MODE_FAULT, view_fault_init, view_fault_display }, }; diff --git a/src/menu/menu_state.h b/src/menu/menu_state.h index 265443fe..ae528cf2 100644 --- a/src/menu/menu_state.h +++ b/src/menu/menu_state.h @@ -12,6 +12,7 @@ #include "boot/boot.h" #include "disk_info.h" +#include "rom_patcher.h" #include "flashcart/flashcart.h" #include "path.h" #include "rom_info.h" @@ -37,6 +38,7 @@ typedef enum { MENU_MODE_FLASHCART, MENU_MODE_LOAD_ROM, MENU_MODE_LOAD_DISK, + MENU_MODE_LOAD_PATCH, MENU_MODE_LOAD_EMULATOR, MENU_MODE_ERROR, MENU_MODE_FAULT, @@ -48,6 +50,7 @@ typedef enum { ENTRY_TYPE_DIR, ENTRY_TYPE_ROM, ENTRY_TYPE_DISK, + ENTRY_TYPE_PATCH, ENTRY_TYPE_EMULATOR, ENTRY_TYPE_SAVE, ENTRY_TYPE_IMAGE, @@ -104,6 +107,8 @@ typedef struct { rom_info_t rom_info; path_t *disk_path; disk_info_t disk_info; + path_t *patch_path; + //patch_info_t patch_info; } load; } menu_t; diff --git a/src/menu/rom_patcher.c b/src/menu/rom_patcher.c new file mode 100644 index 00000000..e69de29b diff --git a/src/menu/rom_patcher.h b/src/menu/rom_patcher.h new file mode 100644 index 00000000..27c71d1c --- /dev/null +++ b/src/menu/rom_patcher.h @@ -0,0 +1,24 @@ +/** + * @file patcher.h + * @brief N64 ROM patcher + * @ingroup menu + */ + +#ifndef ROM_PATCHER_H__ +#define ROM_PATCHER_H__ + + +#include +#include + +/** @brief Patch state enumeration. */ +typedef enum { + PATCH_OK, + PATCH_ERR_IO, + PATCH_ERR_NO_FILE, + PATCH_ERR_INVALID, +} rom_patcher_err_t; + +rom_patcher_err_t rom_patcher_load (char *path); + +#endif diff --git a/src/menu/views/browser.c b/src/menu/views/browser.c index 00061d67..e317fe08 100644 --- a/src/menu/views/browser.c +++ b/src/menu/views/browser.c @@ -35,6 +35,10 @@ static int compare_entry (const void *pa, const void *pb) { return -1; } else if (b->type == ENTRY_TYPE_DISK) { return 1; + } else if (a->type == ENTRY_TYPE_PATCH) { + return -1; + } else if (b->type == ENTRY_TYPE_PATCH) { + return 1; } else if (a->type == ENTRY_TYPE_EMULATOR) { return -1; } else if (b->type == ENTRY_TYPE_EMULATOR) { @@ -298,6 +302,9 @@ static void process (menu_t *menu) { case ENTRY_TYPE_DISK: menu->next_mode = MENU_MODE_LOAD_DISK; break; + case ENTRY_TYPE_PATCH: + menu->next_mode = MENU_MODE_LOAD_PATCH; + break; case ENTRY_TYPE_EMULATOR: menu->next_mode = MENU_MODE_LOAD_EMULATOR; break; @@ -343,6 +350,7 @@ static void draw (menu_t *menu, surface_t *d) { case ENTRY_TYPE_DIR: action = "A: Enter"; break; case ENTRY_TYPE_ROM: action = "A: Load"; break; case ENTRY_TYPE_DISK: action = "A: Load"; break; + case ENTRY_TYPE_PATCH: action = "A: Load"; break; case ENTRY_TYPE_IMAGE: action = "A: Show"; break; case ENTRY_TYPE_TEXT: action = "A: View"; break; case ENTRY_TYPE_MUSIC: action = "A: Play"; break; diff --git a/src/menu/views/load_patch.c b/src/menu/views/load_patch.c new file mode 100644 index 00000000..64f05496 --- /dev/null +++ b/src/menu/views/load_patch.c @@ -0,0 +1,141 @@ +#include "../cart_load.h" +#include "../rom_patcher.h" +#include "boot/boot.h" +#include "views.h" + + +static bool load_pending; +static bool load_rom; + + +// static char *convert_error_message (rom_patcher_err_t err) { +// switch (err) { +// case PATCH_ERR_IO: return "I/O error during loading patch file information"; +// case PATCH_ERR_NO_FILE: return "Couldn't open patch file"; +// case PATCH_ERR_INVALID: return "Invalid patch file"; +// default: return "Unknown patch info load error"; +// } +// } + + +static void process (menu_t *menu) { + if (menu->actions.enter) { + load_pending = true; + load_rom = false; + } else if (menu->actions.options && menu->load.rom_path) { + load_pending = true; + load_rom = true; + } else if (menu->actions.back) { + menu->next_mode = MENU_MODE_BROWSER; + } +} + +static void draw (menu_t *menu, surface_t *d) { + rdpq_attach(d, NULL); + + component_background_draw(); + + if (load_pending) { + component_loader_draw(0.0f); + } else { + component_layout_draw(); + + component_main_text_draw( + ALIGN_CENTER, VALIGN_TOP, + "Patch information\n" + "\n" + "%s", + menu->browser.entry->name + ); + + component_main_text_draw( + ALIGN_LEFT, VALIGN_TOP, + "\n" + "\n" + "\n" + " %s%s", + menu->load.rom_path ? "ROM: " : "", + menu->load.rom_path ? path_last_get(menu->load.rom_path) : "" + ); + + component_actions_bar_text_draw( + ALIGN_LEFT, VALIGN_TOP, + "A: Load ROM\n" + "B: Exit" + ); + + if (menu->load.rom_path) { + component_actions_bar_text_draw( + ALIGN_RIGHT, VALIGN_TOP, + "R: Load patched ROM" + ); + } + } + + rdpq_detach_show(); +} + +static void draw_progress (float progress) { + surface_t *d = (progress >= 1.0f) ? display_get() : display_try_get(); + + if (d) { + rdpq_attach(d, NULL); + + component_background_draw(); + + component_loader_draw(progress); + + rdpq_detach_show(); + } +} + +static void load (menu_t *menu) { + cart_load_err_t err; + + if (menu->load.rom_path && load_rom) { + err = cart_load_n64_rom_and_save(menu, draw_progress); + if (err != CART_LOAD_OK) { + menu_show_error(menu, cart_load_convert_error_message(err)); + return; + } + } + + // err = cart_load_rom_and_patch(menu, draw_progress); + // if (err != CART_LOAD_OK) { + // menu_show_error(menu, cart_load_convert_error_message(err)); + // return; + // } + + menu->next_mode = MENU_MODE_BOOT; + menu->boot_params->device_type = BOOT_DEVICE_TYPE_ROM; + menu->boot_params->tv_type = BOOT_TV_TYPE_PASSTHROUGH; + menu->boot_params->detect_cic_seed = true; +} + + +void view_load_rom_patch_init (menu_t *menu) { + if (menu->load.patch_path) { + path_free(menu->load.patch_path); + menu->load.patch_path = NULL; + } + + load_pending = false; + + menu->load.patch_path = path_clone_push(menu->browser.directory, menu->browser.entry->name); + + // rom_patcher_err_t err = patch_info_load(path_get(menu->load.patch_path), &menu->load.patch_info); + // if (err != PATCH_OK) { + // menu_show_error(menu, convert_error_message(err)); + // } +} + +void view_load_rom_patch_display (menu_t *menu, surface_t *display) { + process(menu); + + draw(menu, display); + + if (load_pending) { + load_pending = false; + load(menu); + } +} diff --git a/src/menu/views/views.h b/src/menu/views/views.h index 8da900dc..678de8fa 100644 --- a/src/menu/views/views.h +++ b/src/menu/views/views.h @@ -56,6 +56,9 @@ void view_load_rom_display (menu_t *menu, surface_t *display); void view_load_disk_init (menu_t *menu); void view_load_disk_display (menu_t *menu, surface_t *display); +void view_load_rom_patch_init (menu_t *menu); +void view_load_rom_patch_display (menu_t *menu, surface_t *display); + void view_load_emulator_init (menu_t *menu); void view_load_emulator_display (menu_t *menu, surface_t *display); From d20dc881b0e948f04b2d2e1c84646b171a3d82a1 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Thu, 7 Mar 2024 21:17:03 +0000 Subject: [PATCH 03/24] Fixes after rebase. --- src/menu/menu.c | 2 +- src/menu/menu_state.h | 2 +- src/menu/views/browser.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/menu/menu.c b/src/menu/menu.c index b904acd3..071463bc 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -157,7 +157,7 @@ static view_t menu_views[] = { { MENU_MODE_LOAD_ROM, view_load_rom_init, view_load_rom_display }, { MENU_MODE_LOAD_DISK, view_load_disk_init, view_load_disk_display }, { MENU_MODE_LOAD_EMULATOR, view_load_emulator_init, view_load_emulator_display }, - { MENU_MODE_LOAD_PATCH, view_load_rom_patch_display }, + { MENU_MODE_LOAD_PATCH, view_load_rom_patch_init, view_load_rom_patch_display }, { MENU_MODE_ERROR, view_error_init, view_error_display }, { MENU_MODE_FAULT, view_fault_init, view_fault_display }, }; diff --git a/src/menu/menu_state.h b/src/menu/menu_state.h index ae528cf2..7a7b551b 100644 --- a/src/menu/menu_state.h +++ b/src/menu/menu_state.h @@ -38,8 +38,8 @@ typedef enum { MENU_MODE_FLASHCART, MENU_MODE_LOAD_ROM, MENU_MODE_LOAD_DISK, - MENU_MODE_LOAD_PATCH, MENU_MODE_LOAD_EMULATOR, + MENU_MODE_LOAD_PATCH, MENU_MODE_ERROR, MENU_MODE_FAULT, MENU_MODE_BOOT, diff --git a/src/menu/views/browser.c b/src/menu/views/browser.c index e317fe08..f1b0ebd5 100644 --- a/src/menu/views/browser.c +++ b/src/menu/views/browser.c @@ -302,12 +302,12 @@ static void process (menu_t *menu) { case ENTRY_TYPE_DISK: menu->next_mode = MENU_MODE_LOAD_DISK; break; - case ENTRY_TYPE_PATCH: - menu->next_mode = MENU_MODE_LOAD_PATCH; - break; case ENTRY_TYPE_EMULATOR: menu->next_mode = MENU_MODE_LOAD_EMULATOR; break; + case ENTRY_TYPE_PATCH: + menu->next_mode = MENU_MODE_LOAD_PATCH; + break; case ENTRY_TYPE_IMAGE: menu->next_mode = MENU_MODE_IMAGE_VIEWER; break; From d9ad29d285b7e4c2b853023756c19509af7a2588 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Thu, 7 Mar 2024 21:25:48 +0000 Subject: [PATCH 04/24] Fixups after merge. --- src/menu/menu_state.h | 1 - src/menu/views/browser.c | 3 --- 2 files changed, 4 deletions(-) diff --git a/src/menu/menu_state.h b/src/menu/menu_state.h index 93d903f7..7a7b551b 100644 --- a/src/menu/menu_state.h +++ b/src/menu/menu_state.h @@ -38,7 +38,6 @@ typedef enum { MENU_MODE_FLASHCART, MENU_MODE_LOAD_ROM, MENU_MODE_LOAD_DISK, - MENU_MODE_LOAD_PATCH, MENU_MODE_LOAD_EMULATOR, MENU_MODE_LOAD_PATCH, MENU_MODE_ERROR, diff --git a/src/menu/views/browser.c b/src/menu/views/browser.c index 36f33dc2..f1b0ebd5 100644 --- a/src/menu/views/browser.c +++ b/src/menu/views/browser.c @@ -302,9 +302,6 @@ static void process (menu_t *menu) { case ENTRY_TYPE_DISK: menu->next_mode = MENU_MODE_LOAD_DISK; break; - case ENTRY_TYPE_PATCH: - menu->next_mode = MENU_MODE_LOAD_PATCH; - break; case ENTRY_TYPE_EMULATOR: menu->next_mode = MENU_MODE_LOAD_EMULATOR; break; From 010221d610c1b029c9e6baaec3cccb28205c1086 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Thu, 7 Mar 2024 21:33:23 +0000 Subject: [PATCH 05/24] Move menu mode for patch --- src/menu/menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/menu/menu.c b/src/menu/menu.c index 071463bc..c6a185db 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -156,8 +156,8 @@ static view_t menu_views[] = { { MENU_MODE_FLASHCART, view_flashcart_info_init, view_flashcart_info_display }, { MENU_MODE_LOAD_ROM, view_load_rom_init, view_load_rom_display }, { MENU_MODE_LOAD_DISK, view_load_disk_init, view_load_disk_display }, - { MENU_MODE_LOAD_EMULATOR, view_load_emulator_init, view_load_emulator_display }, { MENU_MODE_LOAD_PATCH, view_load_rom_patch_init, view_load_rom_patch_display }, + { MENU_MODE_LOAD_EMULATOR, view_load_emulator_init, view_load_emulator_display }, { MENU_MODE_ERROR, view_error_init, view_error_display }, { MENU_MODE_FAULT, view_fault_init, view_fault_display }, }; From 0847b4d6642fa1b38a644e217c8b570000a54f90 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Thu, 7 Mar 2024 21:44:44 +0000 Subject: [PATCH 06/24] Add flips submodule --- .gitmodules | 4 ++++ src/libs/Flips | 1 + 2 files changed, 5 insertions(+) create mode 160000 src/libs/Flips diff --git a/.gitmodules b/.gitmodules index f830561a..0dc8a638 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,7 @@ path = src/libs/miniz url = https://github.com/richgel999/miniz.git ignore = dirty +[submodule "src/libs/Flips"] + path = src/libs/Flips + url = https://github.com/Alcaro/Flips.git + ignore = dirty diff --git a/src/libs/Flips b/src/libs/Flips new file mode 160000 index 00000000..fdd5c6e3 --- /dev/null +++ b/src/libs/Flips @@ -0,0 +1 @@ +Subproject commit fdd5c6e34285beef5b9be759c9b91390df486c66 From dfe4a2064375aa6f873d2275271a4cdb3d58f340 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Thu, 7 Mar 2024 21:51:04 +0000 Subject: [PATCH 07/24] Revert "Add flips submodule" This reverts commit 0847b4d6642fa1b38a644e217c8b570000a54f90. --- .gitmodules | 4 ---- src/libs/Flips | 1 - 2 files changed, 5 deletions(-) delete mode 160000 src/libs/Flips diff --git a/.gitmodules b/.gitmodules index 0dc8a638..f830561a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,7 +19,3 @@ path = src/libs/miniz url = https://github.com/richgel999/miniz.git ignore = dirty -[submodule "src/libs/Flips"] - path = src/libs/Flips - url = https://github.com/Alcaro/Flips.git - ignore = dirty diff --git a/src/libs/Flips b/src/libs/Flips deleted file mode 160000 index fdd5c6e3..00000000 --- a/src/libs/Flips +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fdd5c6e34285beef5b9be759c9b91390df486c66 From 682669c9781b089fb71f7aaf3c67ba39db7585d4 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Thu, 7 Mar 2024 22:40:35 +0000 Subject: [PATCH 08/24] Improvements --- src/menu/rom_patcher.c | 36 ++++++++++++++++++++++++++++++++++++ src/menu/rom_patcher.h | 3 ++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/menu/rom_patcher.c b/src/menu/rom_patcher.c index e69de29b..46e8147c 100644 --- a/src/menu/rom_patcher.c +++ b/src/menu/rom_patcher.c @@ -0,0 +1,36 @@ +#include +#include + +#include "rom_patcher.h" + + +rom_patcher_err_t rom_patcher_load_file (char *path) +{ + // ROM file should be loaded befoe patch is applied. + // apply patch dependent on extension. + //return apply_patch_type_ips(path); + //return apply_patch_type_bps(path); + //return apply_patch_type_aps(path); + //return apply_patch_type_xdelta(path); + return PATCH_ERR_IO; +} + +rom_patcher_err_t apply_patch_type_ips(char *path) +{ + return PATCH_ERR_INVALID; +} + +rom_patcher_err_t apply_patch_type_bps(char *path) +{ + return PATCH_ERR_INVALID; +} + +rom_patcher_err_t apply_patch_type_aps(char *path) +{ + return PATCH_ERR_INVALID; +} + +rom_patcher_err_t apply_patch_type_xdelta(char *path) +{ + return PATCH_ERR_UNSUPPORTED; +} diff --git a/src/menu/rom_patcher.h b/src/menu/rom_patcher.h index 27c71d1c..25c80d26 100644 --- a/src/menu/rom_patcher.h +++ b/src/menu/rom_patcher.h @@ -17,8 +17,9 @@ typedef enum { PATCH_ERR_IO, PATCH_ERR_NO_FILE, PATCH_ERR_INVALID, + PATCH_ERR_UNSUPPORTED, } rom_patcher_err_t; -rom_patcher_err_t rom_patcher_load (char *path); +rom_patcher_err_t rom_patcher_load_file (char *path); #endif From ded3e3e96b44182db34eed1e89e48089dde6f6a0 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Thu, 7 Mar 2024 22:47:01 +0000 Subject: [PATCH 09/24] Add patch extensions to browser --- src/menu/views/browser.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/menu/views/browser.c b/src/menu/views/browser.c index f1b0ebd5..14bc482e 100644 --- a/src/menu/views/browser.c +++ b/src/menu/views/browser.c @@ -11,6 +11,7 @@ static const char *rom_extensions[] = { "z64", "n64", "v64", "rom", NULL }; static const char *disk_extensions[] = { "ndd", NULL }; +static const char *patch_extensions[] = { "bps", "ips", "aps", "xdelta", NULL }; static const char *emulator_extensions[] = { "nes", "sfc", "smc", "gb", "gbc", "sms", "gg", "sg", NULL }; static const char *save_extensions[] = { "sav", NULL }; // TODO: "eep", "sra", "srm", "fla" could be used if transfered from different flashcarts. static const char *image_extensions[] = { "png", NULL }; @@ -113,6 +114,8 @@ static bool load_directory (menu_t *menu) { entry->type = ENTRY_TYPE_ROM; } else if (file_has_extensions(info.fname, disk_extensions)) { entry->type = ENTRY_TYPE_DISK; + } else if (file_has_extensions(info.fname, patch_extensions)) { + entry->type = ENTRY_TYPE_PATCH; }else if (file_has_extensions(info.fname, emulator_extensions)) { entry->type = ENTRY_TYPE_EMULATOR; } else if (file_has_extensions(info.fname, save_extensions)) { From 71c93c516972aec4a2dafd88a7675d228f99d6a6 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Thu, 7 Mar 2024 23:17:39 +0000 Subject: [PATCH 10/24] minor improvements --- src/menu/rom_patcher.c | 12 +++++++----- src/menu/views/browser.c | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/menu/rom_patcher.c b/src/menu/rom_patcher.c index 46e8147c..3117d901 100644 --- a/src/menu/rom_patcher.c +++ b/src/menu/rom_patcher.c @@ -8,24 +8,26 @@ rom_patcher_err_t rom_patcher_load_file (char *path) { // ROM file should be loaded befoe patch is applied. // apply patch dependent on extension. - //return apply_patch_type_ips(path); //return apply_patch_type_bps(path); - //return apply_patch_type_aps(path); + //return apply_patch_type_ips(path); + //return apply_patch_type_ups(path); //return apply_patch_type_xdelta(path); + // aps should be PATCH_ERR_UNSUPPORTED; as not really a thing?! return PATCH_ERR_IO; } -rom_patcher_err_t apply_patch_type_ips(char *path) +rom_patcher_err_t apply_patch_type_bps(char *path) { + // https://github.com/Alcaro/Flips/blob/master/bps_spec.md return PATCH_ERR_INVALID; } -rom_patcher_err_t apply_patch_type_bps(char *path) +rom_patcher_err_t apply_patch_type_ips(char *path) { return PATCH_ERR_INVALID; } -rom_patcher_err_t apply_patch_type_aps(char *path) +rom_patcher_err_t apply_patch_type_ups(char *path) { return PATCH_ERR_INVALID; } diff --git a/src/menu/views/browser.c b/src/menu/views/browser.c index 14bc482e..f6dbc5c4 100644 --- a/src/menu/views/browser.c +++ b/src/menu/views/browser.c @@ -11,7 +11,7 @@ static const char *rom_extensions[] = { "z64", "n64", "v64", "rom", NULL }; static const char *disk_extensions[] = { "ndd", NULL }; -static const char *patch_extensions[] = { "bps", "ips", "aps", "xdelta", NULL }; +static const char *patch_extensions[] = { "bps", "ips", "ups", "xdelta", NULL }; static const char *emulator_extensions[] = { "nes", "sfc", "smc", "gb", "gbc", "sms", "gg", "sg", NULL }; static const char *save_extensions[] = { "sav", NULL }; // TODO: "eep", "sra", "srm", "fla" could be used if transfered from different flashcarts. static const char *image_extensions[] = { "png", NULL }; From 2258df3c1f40484db46a415df5fb13a2c4042c26 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Sat, 9 Mar 2024 12:48:44 +0000 Subject: [PATCH 11/24] Improve comments --- src/menu/rom_patcher.c | 255 ++++++++++++++++++++++++++++++++++++++- src/menu/views/browser.c | 2 +- 2 files changed, 253 insertions(+), 4 deletions(-) diff --git a/src/menu/rom_patcher.c b/src/menu/rom_patcher.c index 3117d901..77425c18 100644 --- a/src/menu/rom_patcher.c +++ b/src/menu/rom_patcher.c @@ -6,10 +6,13 @@ rom_patcher_err_t rom_patcher_load_file (char *path) { - // ROM file should be loaded befoe patch is applied. + // ROM file should be loaded before patch is applied. + // See https://github.com/marcrobledo/RomPatcher.js/ for an example lib. + // Though needs conversion from JS to C // apply patch dependent on extension. //return apply_patch_type_bps(path); //return apply_patch_type_ips(path); + //return apply_patch_type_aps(path); //return apply_patch_type_ups(path); //return apply_patch_type_xdelta(path); // aps should be PATCH_ERR_UNSUPPORTED; as not really a thing?! @@ -19,20 +22,266 @@ rom_patcher_err_t rom_patcher_load_file (char *path) rom_patcher_err_t apply_patch_type_bps(char *path) { // https://github.com/Alcaro/Flips/blob/master/bps_spec.md - return PATCH_ERR_INVALID; + // https://www.romhacking.net/documents/746/ + return PATCH_ERR_UNSUPPORTED; } rom_patcher_err_t apply_patch_type_ips(char *path) { + // http://www.smwiki.net/wiki/IPS_file_format return PATCH_ERR_INVALID; } -rom_patcher_err_t apply_patch_type_ups(char *path) +rom_patcher_err_t apply_patch_type_aps(char *path) { + // https://github.com/btimofeev/UniPatcher/wiki/APS-(N64) return PATCH_ERR_INVALID; } +rom_patcher_err_t apply_patch_type_ups(char *path) +{ + // http://www.romhacking.net/documents/392/ + return PATCH_ERR_UNSUPPORTED; +} + rom_patcher_err_t apply_patch_type_xdelta(char *path) { return PATCH_ERR_UNSUPPORTED; } + + + +// Krikzz implementation: +// #define APS_BUFF_SIZE 32768 + +// static uint8_t aps_buff[APS_BUFF_SIZE]; +// static uint8_t rom_buff[512]; +// static uint8_t aps_byte; +// static uint8_t aps_resp; +// static uint32_t aps_addr; +// static uint32_t rom_addr; +// static uint32_t current_rom_sector; +// static uint8_t asp_swap; + +// uint8_t apsGetNextByte(); +// void apsSetRomByte(); +// void apsSetRomByteRLE(uint8_t val); + +// uint8_t ips_patch_apply(uint8_t *filename) { + +// uint32_t block_len; +// uint8_t resp; +// uint32_t len; +// uint32_t i; +// uint8_t rle_val; + +// rom_addr = 0; +// aps_addr = 0; +// current_rom_sector = 0; +// // read the ROM memory +// bi_dma_read_rom(rom_buff, current_rom_sector, 1); + +// // open the patch +// resp = fatOpenFileByName(filename, 0); +// if (resp)return resp; + +// len = file.size - 3; + +// // check the header content +// for (i = 0; i < 5; i++) { +// if (apsGetNextByte() != "PATCH"[i])return ERR_WRONG_IPS; +// } + + +// // if (aps_header[5] != 0 || aps_header[6] != 0 || aps_header[7] != 16 || aps_header[8] != 0 || aps_header[9] != 8)return ERR_WRONG_IPS2; + +// asp_swap = 0; + + +// // for (i = 0; i < 5; i++)apsGetNextByte(); +// // gSetXY(4, 4); + +// while (aps_addr < len) { + + + +// rom_addr = apsGetNextByte() << 16; +// rom_addr |= apsGetNextByte() << 8; +// rom_addr |= apsGetNextByte(); + +// block_len = apsGetNextByte() << 8; +// block_len |= apsGetNextByte(); +// if (aps_resp)return aps_resp; + +// if (block_len == 0) { +// block_len = apsGetNextByte() << 8; +// block_len |= apsGetNextByte(); +// rle_val = apsGetNextByte(); +// if (aps_resp)return aps_resp; + +// while (block_len--) { +// apsSetRomByteRLE(rle_val); +// } +// continue; +// } + + +// while (block_len--) { + +// apsSetRomByte(); +// if (aps_resp)return aps_resp; +// } + + +// } + +// // write to the ROM memory +// bi_dma_write_rom(rom_buff, current_rom_sector, 1); + +// return 0; +// } + +// uint8_t aps_patch_apply(uint8_t *filename) { + +// uint16_t block_len; +// uint8_t resp; +// uint32_t len; +// uint32_t i; +// uint8_t aps_header[78]; +// uint8_t rle_val; + + +// rom_addr = 0; +// aps_addr = 0; +// current_rom_sector = 0; +// bi_dma_read_rom(rom_buff, current_rom_sector, 1); + +// resp = fatOpenFileByName(filename, 0); +// if (resp)return resp; + +// len = file.size; + + + + +// for (i = 0; i < 78; i++) { +// resp = apsGetNextByte(); +// if (aps_resp)return aps_resp; +// aps_header[i] = aps_byte; +// } + +// for (i = 0; i < 5; i++) { +// if (aps_header[i] != "APS10"[i])return ERR_WRONG_APS; +// } + +// for (i = 0; i < 8; i++) { +// if (rom_buff[i + 0x10] != aps_header[i + 0x3d])return ERR_APS_CRC; +// } + +// asp_swap = aps_header[57] == 0 ? 1 : 0; + +// while (aps_addr < len) { + +// rom_addr = apsGetNextByte(); +// rom_addr |= apsGetNextByte() << 8; +// rom_addr |= apsGetNextByte() << 16; +// rom_addr |= apsGetNextByte() << 24; +// block_len = apsGetNextByte(); +// if (aps_resp)return aps_resp; + +// if (block_len == 0) { +// block_len = apsGetNextByte(); +// rle_val = apsGetNextByte(); +// if (aps_resp)return aps_resp; + +// while (block_len--) { +// apsSetRomByteRLE(rle_val); +// } +// continue; +// } + + +// while (block_len--) { + +// apsSetRomByte(); +// if (aps_resp)return aps_resp; +// } + + +// } + +// bi_dma_write_rom(rom_buff, current_rom_sector, 1); + +// return 0; +// } + +// inline uint8_t apsGetNextByte() { + +// static uint32_t in_buff_addr; +// in_buff_addr = aps_addr & (APS_BUFF_SIZE - 1); + +// if (in_buff_addr == 0) { + +// if (file.sec_available < APS_BUFF_SIZE / 512) { +// aps_resp = fatReadFile(aps_buff, file.sec_available); +// } else { +// aps_resp = fatReadFile(aps_buff, APS_BUFF_SIZE / 512); +// } + +// if (aps_resp)return 0; +// } + + +// aps_byte = aps_buff[in_buff_addr]; +// aps_addr++; + +// return aps_byte; +// } + +// inline void apsSetRomByte() { + + +// if (rom_addr / 512 != current_rom_sector) { +// bi_dma_write_rom(rom_buff, current_rom_sector, 1); +// current_rom_sector = rom_addr / 512; +// bi_dma_read_rom(rom_buff, current_rom_sector, 1); +// } + + +// if (asp_swap) { +// rom_buff[(rom_addr & 511) ^ 1] = apsGetNextByte(); +// } else { +// rom_buff[rom_addr & 511] = apsGetNextByte(); +// } +// rom_addr++; +// } + +// inline void apsSetRomByteRLE(uint8_t val) { + +// if (rom_addr / 512 != current_rom_sector) { +// bi_dma_write_rom(rom_buff, current_rom_sector, 1); +// current_rom_sector = rom_addr / 512; +// bi_dma_read_rom(rom_buff, current_rom_sector, 1); +// } + +// if (asp_swap) { +// rom_buff[(rom_addr & 511) ^ 1] = val; +// } else { +// rom_buff[rom_addr & 511] = val; +// } +// rom_addr++; +// } + + + +// uint8_t patch_apply(uint8_t *filename) { + + +// if (osExtension(".ips", filename)) { +// return ips_patch_apply(filename); +// } else if (osExtension(".aps", filename)) { +// return aps_patch_apply(filename); +// } + +// return 0; +// } diff --git a/src/menu/views/browser.c b/src/menu/views/browser.c index f6dbc5c4..b8934b77 100644 --- a/src/menu/views/browser.c +++ b/src/menu/views/browser.c @@ -11,7 +11,7 @@ static const char *rom_extensions[] = { "z64", "n64", "v64", "rom", NULL }; static const char *disk_extensions[] = { "ndd", NULL }; -static const char *patch_extensions[] = { "bps", "ips", "ups", "xdelta", NULL }; +static const char *patch_extensions[] = { "bps", "ips", "aps", "ups", "xdelta", NULL }; static const char *emulator_extensions[] = { "nes", "sfc", "smc", "gb", "gbc", "sms", "gg", "sg", NULL }; static const char *save_extensions[] = { "sav", NULL }; // TODO: "eep", "sra", "srm", "fla" could be used if transfered from different flashcarts. static const char *image_extensions[] = { "png", NULL }; From 9fb88b60227b16b63f0b360e23aa63d878a6e0e0 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Fri, 15 Mar 2024 21:14:28 +0000 Subject: [PATCH 12/24] Improvements --- src/menu/rom_patcher.c | 81 ++++++++++++++++++++++++++----------- src/menu/rom_patcher.h | 11 ++++- src/menu/views/load_patch.c | 22 +++++++--- 3 files changed, 85 insertions(+), 29 deletions(-) diff --git a/src/menu/rom_patcher.c b/src/menu/rom_patcher.c index 77425c18..07068661 100644 --- a/src/menu/rom_patcher.c +++ b/src/menu/rom_patcher.c @@ -1,57 +1,93 @@ #include #include - +#include "utils/fs.h" #include "rom_patcher.h" -rom_patcher_err_t rom_patcher_load_file (char *path) -{ - // ROM file should be loaded before patch is applied. - // See https://github.com/marcrobledo/RomPatcher.js/ for an example lib. - // Though needs conversion from JS to C - // apply patch dependent on extension. - //return apply_patch_type_bps(path); - //return apply_patch_type_ips(path); - //return apply_patch_type_aps(path); - //return apply_patch_type_ups(path); - //return apply_patch_type_xdelta(path); - // aps should be PATCH_ERR_UNSUPPORTED; as not really a thing?! - return PATCH_ERR_IO; -} - -rom_patcher_err_t apply_patch_type_bps(char *path) +rom_patcher_err_t apply_patch_type_bps(FIL *fil) { // https://github.com/Alcaro/Flips/blob/master/bps_spec.md // https://www.romhacking.net/documents/746/ return PATCH_ERR_UNSUPPORTED; } -rom_patcher_err_t apply_patch_type_ips(char *path) +rom_patcher_err_t apply_patch_type_ips(FIL *fil) { // http://www.smwiki.net/wiki/IPS_file_format return PATCH_ERR_INVALID; } -rom_patcher_err_t apply_patch_type_aps(char *path) +rom_patcher_err_t apply_patch_type_aps(FIL *fil) { // https://github.com/btimofeev/UniPatcher/wiki/APS-(N64) return PATCH_ERR_INVALID; } -rom_patcher_err_t apply_patch_type_ups(char *path) +rom_patcher_err_t apply_patch_type_ups(FIL *fil) { // http://www.romhacking.net/documents/392/ return PATCH_ERR_UNSUPPORTED; } -rom_patcher_err_t apply_patch_type_xdelta(char *path) +rom_patcher_err_t apply_patch_type_xdelta(FIL *fil) { return PATCH_ERR_UNSUPPORTED; } +rom_patcher_err_t rom_patcher_load_file (char *path) +{ + FIL fil; + rom_patcher_err_t err; + + if (f_open(&fil, strip_sd_prefix(path), FA_READ) != FR_OK) { + return PATCH_ERR_NO_FILE; + } + + + // ROM file should be loaded before patch is applied. + // See https://github.com/marcrobledo/RomPatcher.js/ for an example lib. + // Though needs conversion from JS to C + // apply patch dependent on extension. + + rom_patch_type_t patch_ext_type = PATCH_TYPE_IPS; // FIXME: should be the extension of the file! + + switch (patch_ext_type) + { + case PATCH_TYPE_BPS: + err = apply_patch_type_bps(&fil); + break; + case PATCH_TYPE_IPS: + err = apply_patch_type_ips(&fil); + break; + case PATCH_TYPE_APS: + err = apply_patch_type_aps(&fil); + break; + case PATCH_TYPE_UPS: + err = apply_patch_type_ups(&fil); + break; + case PATCH_TYPE_XDELTA: + err = apply_patch_type_xdelta(&fil); + break; + default: + return PATCH_ERR_UNSUPPORTED; + } + + + if (f_close(&fil) != FR_OK) { + return PATCH_ERR_IO; + } + + if (err != PATCH_OK) { + return err; + } + + return PATCH_OK; +} + + -// Krikzz implementation: +// Krikzz implementation for ref: // #define APS_BUFF_SIZE 32768 // static uint8_t aps_buff[APS_BUFF_SIZE]; @@ -99,7 +135,6 @@ rom_patcher_err_t apply_patch_type_xdelta(char *path) // // for (i = 0; i < 5; i++)apsGetNextByte(); -// // gSetXY(4, 4); // while (aps_addr < len) { diff --git a/src/menu/rom_patcher.h b/src/menu/rom_patcher.h index 25c80d26..50091175 100644 --- a/src/menu/rom_patcher.h +++ b/src/menu/rom_patcher.h @@ -1,5 +1,5 @@ /** - * @file patcher.h + * @file rom_patcher.h * @brief N64 ROM patcher * @ingroup menu */ @@ -20,6 +20,15 @@ typedef enum { PATCH_ERR_UNSUPPORTED, } rom_patcher_err_t; +/** @brief Patch type enumeration. */ +typedef enum { + PATCH_TYPE_BPS, + PATCH_TYPE_APS, + PATCH_TYPE_IPS, + PATCH_TYPE_UPS, + PATCH_TYPE_XDELTA, +} rom_patch_type_t; + rom_patcher_err_t rom_patcher_load_file (char *path); #endif diff --git a/src/menu/views/load_patch.c b/src/menu/views/load_patch.c index 64f05496..85ce186a 100644 --- a/src/menu/views/load_patch.c +++ b/src/menu/views/load_patch.c @@ -60,14 +60,14 @@ static void draw (menu_t *menu, surface_t *d) { component_actions_bar_text_draw( ALIGN_LEFT, VALIGN_TOP, - "A: Load ROM\n" + "A: Load and run patched ROM\n" "B: Exit" ); if (menu->load.rom_path) { component_actions_bar_text_draw( ALIGN_RIGHT, VALIGN_TOP, - "R: Load patched ROM" + "R: Load with ROM" ); } } @@ -107,9 +107,21 @@ static void load (menu_t *menu) { // } menu->next_mode = MENU_MODE_BOOT; - menu->boot_params->device_type = BOOT_DEVICE_TYPE_ROM; - menu->boot_params->tv_type = BOOT_TV_TYPE_PASSTHROUGH; - menu->boot_params->detect_cic_seed = true; + + if (load_rom) { + menu->boot_params->device_type = BOOT_DEVICE_TYPE_ROM; + menu->boot_params->detect_cic_seed = rom_info_get_cic_seed(&menu->load.rom_info, &menu->boot_params->cic_seed); + switch (rom_info_get_tv_type(&menu->load.rom_info)) { + case ROM_TV_TYPE_PAL: menu->boot_params->tv_type = BOOT_TV_TYPE_PAL; break; + case ROM_TV_TYPE_NTSC: menu->boot_params->tv_type = BOOT_TV_TYPE_NTSC; break; + case ROM_TV_TYPE_MPAL: menu->boot_params->tv_type = BOOT_TV_TYPE_MPAL; break; + default: menu->boot_params->tv_type = BOOT_TV_TYPE_PASSTHROUGH; break; + } + } else { + menu->boot_params->device_type = BOOT_DEVICE_TYPE_ROM; + menu->boot_params->tv_type = BOOT_TV_TYPE_NTSC; + menu->boot_params->detect_cic_seed = true; + } } From 277a4cf20a29a095ed8d25d28ffe431976b33562 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Fri, 15 Mar 2024 23:17:27 +0000 Subject: [PATCH 13/24] IPS hints --- src/menu/rom_patcher.c | 48 +++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/src/menu/rom_patcher.c b/src/menu/rom_patcher.c index 07068661..b2225cfc 100644 --- a/src/menu/rom_patcher.c +++ b/src/menu/rom_patcher.c @@ -4,6 +4,22 @@ #include "rom_patcher.h" +typedef struct +{ + uint32_t address; // The start address of the data to modify as big endian. NOTE: this is only 3 bytes. + uint16_t length; // The length of the following data (greater than zero) as big endian. + uint8_t *data; // The data to be written to "Address" (using length). +} ips_patch_record_t; + +typedef struct +{ + uint32_t address; // The start address of the data to modify as big endian. NOTE: this is only 3 bytes. + uint16_t zero_bytes; // The record length was zero, this determines the difference between ips_patch_record_t length. + uint16_t rle_byte_count; // Number of times to repeat the following byte as big endian. + uint8_t rle_byte; // The repeatitive byte to be written to "Address". +} ips_patch_record_rle_t; + + rom_patcher_err_t apply_patch_type_bps(FIL *fil) { // https://github.com/Alcaro/Flips/blob/master/bps_spec.md @@ -13,8 +29,21 @@ rom_patcher_err_t apply_patch_type_bps(FIL *fil) rom_patcher_err_t apply_patch_type_ips(FIL *fil) { - // http://www.smwiki.net/wiki/IPS_file_format - return PATCH_ERR_INVALID; + // https://web.archive.org/web/20170624071240/http://www.smwiki.net:80/wiki/IPS_file_format + + // Check the header is valid. + // UINT bytes_read = 0; + // UINT *buff = 0; + // f_read(fil, &buff, 1024, &bytes_read); + // if (&header != "PATCH") { + // return PATCH_ERR_INVALID; + // } + + //ips_patch_record_t records; + //ips_patch_record_rle_t records_rle; + + // FIXME: we are not yet doing the patch write! + return PATCH_OK; } rom_patcher_err_t apply_patch_type_aps(FIL *fil) @@ -128,32 +157,31 @@ rom_patcher_err_t rom_patcher_load_file (char *path) // if (apsGetNextByte() != "PATCH"[i])return ERR_WRONG_IPS; // } - -// // if (aps_header[5] != 0 || aps_header[6] != 0 || aps_header[7] != 16 || aps_header[8] != 0 || aps_header[9] != 8)return ERR_WRONG_IPS2; - // asp_swap = 0; - -// // for (i = 0; i < 5; i++)apsGetNextByte(); - // while (aps_addr < len) { - - +// Get Address // rom_addr = apsGetNextByte() << 16; // rom_addr |= apsGetNextByte() << 8; // rom_addr |= apsGetNextByte(); +// get length // block_len = apsGetNextByte() << 8; // block_len |= apsGetNextByte(); + // if (aps_resp)return aps_resp; +// if the length is zero // if (block_len == 0) { +// get the rle length // block_len = apsGetNextByte() << 8; // block_len |= apsGetNextByte(); +// get the rle value // rle_val = apsGetNextByte(); // if (aps_resp)return aps_resp; +// apply the rle value while the rle length is valid // while (block_len--) { // apsSetRomByteRLE(rle_val); // } From 8da4ffd18137d89c916fd6f64add3ff499212753 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Sat, 16 Mar 2024 00:48:10 +0000 Subject: [PATCH 14/24] add aps header struct and some comments --- src/menu/rom_patcher.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/src/menu/rom_patcher.c b/src/menu/rom_patcher.c index b2225cfc..8588eb85 100644 --- a/src/menu/rom_patcher.c +++ b/src/menu/rom_patcher.c @@ -3,17 +3,31 @@ #include "utils/fs.h" #include "rom_patcher.h" +typedef struct +{ + char *header_magic[5]; // The header type, should always be "APS10" for N64. + uint8_t type; // The patch type, 0 for a Simple Patch, 1 for a N64 Specific Patch. + uint8_t encoding_method; // Encoding Method, 0 for Simple Encoding. + char *description[49]; // Patch description. + bool endian; // image file format 0 = Doctor V64, 1 = CD64/Z64/Wc/SP. + uint16_t rom_id; // This is the two bytes of Cart ID taken directly from the original image. + uint8_t country_code; // The original image's country code. + uint64_t crc; // The original image's CRC taken directly out of the original image. + char *pad[6]; // For future expansion. + uint32_t size; // Size of destination image. +} aps_patch_header_t; + typedef struct { - uint32_t address; // The start address of the data to modify as big endian. NOTE: this is only 3 bytes. - uint16_t length; // The length of the following data (greater than zero) as big endian. + uint32_t address; // The start address of the data to modify as big endian. NOTE: this is only 3 bytes for IPS. + uint16_t length; // The length of the following data (greater than zero) as big endian. If zero, use ips_patch_record_rle_t uint8_t *data; // The data to be written to "Address" (using length). } ips_patch_record_t; typedef struct { - uint32_t address; // The start address of the data to modify as big endian. NOTE: this is only 3 bytes. + uint32_t address_offset; // The start address of the data to modify as big endian. NOTE: this is only 3 bytes for IPS. uint16_t zero_bytes; // The record length was zero, this determines the difference between ips_patch_record_t length. uint16_t rle_byte_count; // Number of times to repeat the following byte as big endian. uint8_t rle_byte; // The repeatitive byte to be written to "Address". @@ -31,11 +45,12 @@ rom_patcher_err_t apply_patch_type_ips(FIL *fil) { // https://web.archive.org/web/20170624071240/http://www.smwiki.net:80/wiki/IPS_file_format - // Check the header is valid. // UINT bytes_read = 0; // UINT *buff = 0; // f_read(fil, &buff, 1024, &bytes_read); - // if (&header != "PATCH") { + + // Check the header is valid. + // if (header != "PATCH") { // return PATCH_ERR_INVALID; // } @@ -49,6 +64,11 @@ rom_patcher_err_t apply_patch_type_ips(FIL *fil) rom_patcher_err_t apply_patch_type_aps(FIL *fil) { // https://github.com/btimofeev/UniPatcher/wiki/APS-(N64) + + // Check the header is valid. + // if (header != "APS10") { + // return PATCH_ERR_INVALID; + // } return PATCH_ERR_INVALID; } @@ -226,29 +246,35 @@ rom_patcher_err_t rom_patcher_load_file (char *path) - +// get the patch header // for (i = 0; i < 78; i++) { // resp = apsGetNextByte(); // if (aps_resp)return aps_resp; // aps_header[i] = aps_byte; // } +// check the magic in the header, for N64, first 5 bytes should be "APS10" // for (i = 0; i < 5; i++) { // if (aps_header[i] != "APS10"[i])return ERR_WRONG_APS; // } +// check the rom header CRC against the expected patch CRC // for (i = 0; i < 8; i++) { // if (rom_buff[i + 0x10] != aps_header[i + 0x3d])return ERR_APS_CRC; // } +// determine patch endian // asp_swap = aps_header[57] == 0 ? 1 : 0; // while (aps_addr < len) { +// the address // rom_addr = apsGetNextByte(); // rom_addr |= apsGetNextByte() << 8; // rom_addr |= apsGetNextByte() << 16; // rom_addr |= apsGetNextByte() << 24; + +// the number of bytes to be changed // block_len = apsGetNextByte(); // if (aps_resp)return aps_resp; From b1188102c734030fedf07946069f33e7923907fd Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Sat, 16 Mar 2024 01:25:35 +0000 Subject: [PATCH 15/24] minor changes --- src/menu/rom_patcher.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/menu/rom_patcher.c b/src/menu/rom_patcher.c index 8588eb85..393dd03d 100644 --- a/src/menu/rom_patcher.c +++ b/src/menu/rom_patcher.c @@ -8,12 +8,11 @@ typedef struct char *header_magic[5]; // The header type, should always be "APS10" for N64. uint8_t type; // The patch type, 0 for a Simple Patch, 1 for a N64 Specific Patch. uint8_t encoding_method; // Encoding Method, 0 for Simple Encoding. - char *description[49]; // Patch description. + char *description[50]; // Patch description. bool endian; // image file format 0 = Doctor V64, 1 = CD64/Z64/Wc/SP. uint16_t rom_id; // This is the two bytes of Cart ID taken directly from the original image. uint8_t country_code; // The original image's country code. uint64_t crc; // The original image's CRC taken directly out of the original image. - char *pad[6]; // For future expansion. uint32_t size; // Size of destination image. } aps_patch_header_t; @@ -278,6 +277,7 @@ rom_patcher_err_t rom_patcher_load_file (char *path) // block_len = apsGetNextByte(); // if (aps_resp)return aps_resp; +// If paramter block_len is set to zero (0) then the write will be a two (2) byte field // if (block_len == 0) { // block_len = apsGetNextByte(); // rle_val = apsGetNextByte(); @@ -290,6 +290,7 @@ rom_patcher_err_t rom_patcher_load_file (char *path) // } +// Else, the write is a 4 byte field // while (block_len--) { // apsSetRomByte(); From 38a1d11729e2317dd5c1b1e7734edeecb9bfb459 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Sat, 16 Mar 2024 01:57:46 +0000 Subject: [PATCH 16/24] add strcomp --- src/menu/rom_patcher.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/menu/rom_patcher.c b/src/menu/rom_patcher.c index 393dd03d..fcaa8ad4 100644 --- a/src/menu/rom_patcher.c +++ b/src/menu/rom_patcher.c @@ -5,10 +5,10 @@ typedef struct { - char *header_magic[5]; // The header type, should always be "APS10" for N64. + char header_magic[5]; // The header type, should always be "APS10" for N64. uint8_t type; // The patch type, 0 for a Simple Patch, 1 for a N64 Specific Patch. uint8_t encoding_method; // Encoding Method, 0 for Simple Encoding. - char *description[50]; // Patch description. + char description[50]; // Patch description. bool endian; // image file format 0 = Doctor V64, 1 = CD64/Z64/Wc/SP. uint16_t rom_id; // This is the two bytes of Cart ID taken directly from the original image. uint8_t country_code; // The original image's country code. @@ -44,14 +44,14 @@ rom_patcher_err_t apply_patch_type_ips(FIL *fil) { // https://web.archive.org/web/20170624071240/http://www.smwiki.net:80/wiki/IPS_file_format - // UINT bytes_read = 0; - // UINT *buff = 0; - // f_read(fil, &buff, 1024, &bytes_read); + UINT bytes_read = 0; + char header_magic[5]; + f_read(fil, header_magic, 5, &bytes_read); // Check the header is valid. - // if (header != "PATCH") { - // return PATCH_ERR_INVALID; - // } + if (strcmp(header_magic, "PATCH") != 0) { + return PATCH_ERR_INVALID; + } //ips_patch_record_t records; //ips_patch_record_rle_t records_rle; @@ -64,10 +64,15 @@ rom_patcher_err_t apply_patch_type_aps(FIL *fil) { // https://github.com/btimofeev/UniPatcher/wiki/APS-(N64) + UINT bytes_read = 0; + aps_patch_header_t aps_patch_header; + f_read(fil, &aps_patch_header, sizeof(aps_patch_header_t), &bytes_read); + // Check the header is valid. - // if (header != "APS10") { - // return PATCH_ERR_INVALID; - // } + if (strcmp(aps_patch_header.header_magic, "APS10") != 0) { + return PATCH_ERR_INVALID; + } + return PATCH_ERR_INVALID; } From 3f6fc7966c2ce9e031b222569333e9840ea3b122 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Sat, 16 Mar 2024 02:24:00 +0000 Subject: [PATCH 17/24] use defines for magic though would be better as an enum?! --- src/menu/rom_patcher.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/menu/rom_patcher.c b/src/menu/rom_patcher.c index fcaa8ad4..745e4212 100644 --- a/src/menu/rom_patcher.c +++ b/src/menu/rom_patcher.c @@ -3,6 +3,12 @@ #include "utils/fs.h" #include "rom_patcher.h" +#define PATCH_APS_MAGIC_GBA "APS1" +#define PATCH_APS_MAGIC_N64 "APS10" +#define PATCH_IPS_MAGIC "PATCH" +#define PATCH_BPS_MAGIC "BPS1" +#define PATCH_UPS_MAGIC "UPS1" + typedef struct { char header_magic[5]; // The header type, should always be "APS10" for N64. @@ -49,7 +55,7 @@ rom_patcher_err_t apply_patch_type_ips(FIL *fil) f_read(fil, header_magic, 5, &bytes_read); // Check the header is valid. - if (strcmp(header_magic, "PATCH") != 0) { + if (strcmp(header_magic, PATCH_IPS_MAGIC) != 0) { return PATCH_ERR_INVALID; } @@ -69,7 +75,7 @@ rom_patcher_err_t apply_patch_type_aps(FIL *fil) f_read(fil, &aps_patch_header, sizeof(aps_patch_header_t), &bytes_read); // Check the header is valid. - if (strcmp(aps_patch_header.header_magic, "APS10") != 0) { + if (strcmp(aps_patch_header.header_magic, PATCH_APS_MAGIC_N64) != 0) { return PATCH_ERR_INVALID; } From d9fd168a1cb97dfc9bb444c3e923000d9abbb6e9 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Sun, 17 Mar 2024 19:10:20 +0000 Subject: [PATCH 18/24] Rename files Start adding info --- Makefile | 2 +- src/menu/menu.c | 2 +- src/menu/menu_state.h | 8 +- src/menu/{rom_patcher.c => rom_patch_info.c} | 82 +++++++++++--------- src/menu/rom_patch_info.h | 67 ++++++++++++++++ src/menu/rom_patcher.h | 34 -------- src/menu/views/browser.c | 2 +- src/menu/views/load_patch.c | 29 +++---- 8 files changed, 136 insertions(+), 90 deletions(-) rename src/menu/{rom_patcher.c => rom_patch_info.c} (80%) create mode 100644 src/menu/rom_patch_info.h delete mode 100644 src/menu/rom_patcher.h diff --git a/Makefile b/Makefile index 10b241e8..8a96a52d 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,7 @@ SRCS = \ menu/path.c \ menu/png_decoder.c \ menu/rom_info.c \ - menu/rom_patcher.c \ + menu/rom_patch_info.c \ menu/settings.c \ menu/sound.c \ menu/usb_comm.c \ diff --git a/src/menu/menu.c b/src/menu/menu.c index c6a185db..57c01e3e 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -156,7 +156,7 @@ static view_t menu_views[] = { { MENU_MODE_FLASHCART, view_flashcart_info_init, view_flashcart_info_display }, { MENU_MODE_LOAD_ROM, view_load_rom_init, view_load_rom_display }, { MENU_MODE_LOAD_DISK, view_load_disk_init, view_load_disk_display }, - { MENU_MODE_LOAD_PATCH, view_load_rom_patch_init, view_load_rom_patch_display }, + { MENU_MODE_LOAD_ROM_PATCH, view_load_rom_patch_init, view_load_rom_patch_display }, { MENU_MODE_LOAD_EMULATOR, view_load_emulator_init, view_load_emulator_display }, { MENU_MODE_ERROR, view_error_init, view_error_display }, { MENU_MODE_FAULT, view_fault_init, view_fault_display }, diff --git a/src/menu/menu_state.h b/src/menu/menu_state.h index 7a7b551b..a704153a 100644 --- a/src/menu/menu_state.h +++ b/src/menu/menu_state.h @@ -12,7 +12,7 @@ #include "boot/boot.h" #include "disk_info.h" -#include "rom_patcher.h" +#include "rom_patch_info.h" #include "flashcart/flashcart.h" #include "path.h" #include "rom_info.h" @@ -39,7 +39,7 @@ typedef enum { MENU_MODE_LOAD_ROM, MENU_MODE_LOAD_DISK, MENU_MODE_LOAD_EMULATOR, - MENU_MODE_LOAD_PATCH, + MENU_MODE_LOAD_ROM_PATCH, MENU_MODE_ERROR, MENU_MODE_FAULT, MENU_MODE_BOOT, @@ -107,8 +107,8 @@ typedef struct { rom_info_t rom_info; path_t *disk_path; disk_info_t disk_info; - path_t *patch_path; - //patch_info_t patch_info; + path_t *rom_patch_path; + rom_patch_info_t rom_patch_info; } load; } menu_t; diff --git a/src/menu/rom_patcher.c b/src/menu/rom_patch_info.c similarity index 80% rename from src/menu/rom_patcher.c rename to src/menu/rom_patch_info.c index 745e4212..ebbd491f 100644 --- a/src/menu/rom_patcher.c +++ b/src/menu/rom_patch_info.c @@ -1,23 +1,19 @@ #include #include #include "utils/fs.h" -#include "rom_patcher.h" +#include "rom_patch_info.h" +#include "rom_info.h" -#define PATCH_APS_MAGIC_GBA "APS1" -#define PATCH_APS_MAGIC_N64 "APS10" -#define PATCH_IPS_MAGIC "PATCH" -#define PATCH_BPS_MAGIC "BPS1" -#define PATCH_UPS_MAGIC "UPS1" typedef struct { - char header_magic[5]; // The header type, should always be "APS10" for N64. - uint8_t type; // The patch type, 0 for a Simple Patch, 1 for a N64 Specific Patch. - uint8_t encoding_method; // Encoding Method, 0 for Simple Encoding. - char description[50]; // Patch description. + char header_magic[6]; // The header type, should always be "APS10" for N64. (plus null char) + aps_patch_type_t type; // The patch type, 0 for a Simple Patch, 1 for a N64 Specific Patch. + aps_patch_encoding_t encoding_method; // Encoding Method, 0 for Simple Encoding. + char description[50]; // Patch description. (plus null char) bool endian; // image file format 0 = Doctor V64, 1 = CD64/Z64/Wc/SP. uint16_t rom_id; // This is the two bytes of Cart ID taken directly from the original image. - uint8_t country_code; // The original image's country code. + rom_destination_type_t destination_code; // The original rom image's market code. uint64_t crc; // The original image's CRC taken directly out of the original image. uint32_t size; // Size of destination image. } aps_patch_header_t; @@ -39,14 +35,30 @@ typedef struct } ips_patch_record_rle_t; -rom_patcher_err_t apply_patch_type_bps(FIL *fil) +typedef struct +{ + uint32_t file_offset; // The start address of the data to modify as big endian. NOTE: this is only 3 bytes for IPS. + uint8_t byte_count; // Number of times to repeat the following byte as big endian. + uint8_t byte; // The repeatitive byte to be written to "Address". + uint8_t repetitions; // The repeatitive byte to be written to "Address". +} aps_patch_record_t; + +typedef struct +{ + uint32_t file_offset; // The start address of the data to modify as big endian. NOTE: this is only 3 bytes for IPS. + uint8_t byte_count; // Number of times to repeat the following byte as big endian. + uint8_t *bytes; // The repeatitive byte to be written to "Address". +} aps_patch_record_rle_t; + + +rom_patch_load_err_t apply_patch_type_bps(FIL *fil) { // https://github.com/Alcaro/Flips/blob/master/bps_spec.md // https://www.romhacking.net/documents/746/ return PATCH_ERR_UNSUPPORTED; } -rom_patcher_err_t apply_patch_type_ips(FIL *fil) +rom_patch_load_err_t apply_patch_type_ips(FIL *fil) { // https://web.archive.org/web/20170624071240/http://www.smwiki.net:80/wiki/IPS_file_format @@ -66,7 +78,7 @@ rom_patcher_err_t apply_patch_type_ips(FIL *fil) return PATCH_OK; } -rom_patcher_err_t apply_patch_type_aps(FIL *fil) +rom_patch_load_err_t apply_patch_type_aps(FIL *fil) { // https://github.com/btimofeev/UniPatcher/wiki/APS-(N64) @@ -82,22 +94,22 @@ rom_patcher_err_t apply_patch_type_aps(FIL *fil) return PATCH_ERR_INVALID; } -rom_patcher_err_t apply_patch_type_ups(FIL *fil) +rom_patch_load_err_t apply_patch_type_ups(FIL *fil) { // http://www.romhacking.net/documents/392/ return PATCH_ERR_UNSUPPORTED; } -rom_patcher_err_t apply_patch_type_xdelta(FIL *fil) +rom_patch_load_err_t apply_patch_type_xdelta(FIL *fil) { return PATCH_ERR_UNSUPPORTED; } -rom_patcher_err_t rom_patcher_load_file (char *path) +rom_patch_load_err_t rom_patch_info_load (char *path) { FIL fil; - rom_patcher_err_t err; + rom_patch_load_err_t err; if (f_open(&fil, strip_sd_prefix(path), FA_READ) != FR_OK) { return PATCH_ERR_NO_FILE; @@ -113,23 +125,23 @@ rom_patcher_err_t rom_patcher_load_file (char *path) switch (patch_ext_type) { - case PATCH_TYPE_BPS: - err = apply_patch_type_bps(&fil); - break; - case PATCH_TYPE_IPS: - err = apply_patch_type_ips(&fil); - break; - case PATCH_TYPE_APS: - err = apply_patch_type_aps(&fil); - break; - case PATCH_TYPE_UPS: - err = apply_patch_type_ups(&fil); - break; - case PATCH_TYPE_XDELTA: - err = apply_patch_type_xdelta(&fil); - break; - default: - return PATCH_ERR_UNSUPPORTED; + case PATCH_TYPE_BPS: + err = apply_patch_type_bps(&fil); + break; + case PATCH_TYPE_IPS: + err = apply_patch_type_ips(&fil); + break; + case PATCH_TYPE_APS: + err = apply_patch_type_aps(&fil); + break; + case PATCH_TYPE_UPS: + err = apply_patch_type_ups(&fil); + break; + case PATCH_TYPE_XDELTA: + err = apply_patch_type_xdelta(&fil); + break; + default: + return PATCH_ERR_UNSUPPORTED; } diff --git a/src/menu/rom_patch_info.h b/src/menu/rom_patch_info.h new file mode 100644 index 00000000..04f388b5 --- /dev/null +++ b/src/menu/rom_patch_info.h @@ -0,0 +1,67 @@ +/** + * @file rom_patcher.h + * @brief N64 ROM patcher + * @ingroup menu + */ + +#ifndef ROM_PATCH_INFO_H__ +#define ROM_PATCH_INFO_H__ + + +#include +#include + +#include "path.h" + +/** @brief Patch state enumeration. */ +typedef enum { + PATCH_OK, + PATCH_ERR_IO, + PATCH_ERR_NO_FILE, + PATCH_ERR_INVALID, + PATCH_ERR_UNSUPPORTED, +} rom_patch_load_err_t; + +/** @brief Patch type enumeration. */ +typedef enum { + PATCH_TYPE_BPS, + PATCH_TYPE_APS, + PATCH_TYPE_IPS, + PATCH_TYPE_UPS, + PATCH_TYPE_XDELTA, +} rom_patch_type_t; + + +#define PATCH_BPS_MAGIC "BPS1" +#define PATCH_APS_MAGIC_GBA "APS1" +#define PATCH_APS_MAGIC_N64 "APS10" +#define PATCH_IPS_MAGIC "PATCH" +#define PATCH_UPS_MAGIC "UPS1" + + +/** @brief APS patch type enumeration. */ +typedef enum { + /** @brief Is a simple patch. */ + APS_PATCH_TYPE_SIMPLE, + /** @brief Is an N64 specific patch. */ + APS_PATCH_TYPE_N64_SPECIFIC, +} aps_patch_type_t; + +/** @brief APS patch type enumeration. */ +typedef enum { + /** @brief Is a simple patch encoding. */ + PATCH_ENCODING_SIMPLE, +} aps_patch_encoding_t; + + +/** @brief ROM Patch Information Structure. */ +typedef struct { + rom_patch_type_t patch_type; + // patch description + +} rom_patch_info_t; + +//rom_patch_load_err_t rom_patch_info_load (path_t *path, rom_patch_info_t *rom_patch_info); +rom_patch_load_err_t rom_patch_info_load_file (char *path); + +#endif diff --git a/src/menu/rom_patcher.h b/src/menu/rom_patcher.h deleted file mode 100644 index 50091175..00000000 --- a/src/menu/rom_patcher.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @file rom_patcher.h - * @brief N64 ROM patcher - * @ingroup menu - */ - -#ifndef ROM_PATCHER_H__ -#define ROM_PATCHER_H__ - - -#include -#include - -/** @brief Patch state enumeration. */ -typedef enum { - PATCH_OK, - PATCH_ERR_IO, - PATCH_ERR_NO_FILE, - PATCH_ERR_INVALID, - PATCH_ERR_UNSUPPORTED, -} rom_patcher_err_t; - -/** @brief Patch type enumeration. */ -typedef enum { - PATCH_TYPE_BPS, - PATCH_TYPE_APS, - PATCH_TYPE_IPS, - PATCH_TYPE_UPS, - PATCH_TYPE_XDELTA, -} rom_patch_type_t; - -rom_patcher_err_t rom_patcher_load_file (char *path); - -#endif diff --git a/src/menu/views/browser.c b/src/menu/views/browser.c index b8934b77..ae56fb82 100644 --- a/src/menu/views/browser.c +++ b/src/menu/views/browser.c @@ -309,7 +309,7 @@ static void process (menu_t *menu) { menu->next_mode = MENU_MODE_LOAD_EMULATOR; break; case ENTRY_TYPE_PATCH: - menu->next_mode = MENU_MODE_LOAD_PATCH; + menu->next_mode = MENU_MODE_LOAD_ROM_PATCH; break; case ENTRY_TYPE_IMAGE: menu->next_mode = MENU_MODE_IMAGE_VIEWER; diff --git a/src/menu/views/load_patch.c b/src/menu/views/load_patch.c index 85ce186a..1ee15b11 100644 --- a/src/menu/views/load_patch.c +++ b/src/menu/views/load_patch.c @@ -1,5 +1,5 @@ #include "../cart_load.h" -#include "../rom_patcher.h" +#include "../rom_patch_info.h" #include "boot/boot.h" #include "views.h" @@ -8,14 +8,15 @@ static bool load_pending; static bool load_rom; -// static char *convert_error_message (rom_patcher_err_t err) { -// switch (err) { -// case PATCH_ERR_IO: return "I/O error during loading patch file information"; -// case PATCH_ERR_NO_FILE: return "Couldn't open patch file"; -// case PATCH_ERR_INVALID: return "Invalid patch file"; -// default: return "Unknown patch info load error"; -// } -// } +static char *convert_error_message (rom_patch_load_err_t err) { + switch (err) { + case PATCH_ERR_IO: return "I/O error during loading patch file information"; + case PATCH_ERR_NO_FILE: return "Couldn't open patch file"; + case PATCH_ERR_INVALID: return "Invalid patch file"; + case PATCH_ERR_UNSUPPORTED: return "The patch type is not (yet) supported"; + default: return "Unknown patch info load error"; + } +} static void process (menu_t *menu) { @@ -126,16 +127,16 @@ static void load (menu_t *menu) { void view_load_rom_patch_init (menu_t *menu) { - if (menu->load.patch_path) { - path_free(menu->load.patch_path); - menu->load.patch_path = NULL; + if (menu->load.rom_patch_path) { + path_free(menu->load.rom_patch_path); + menu->load.rom_patch_path = NULL; } load_pending = false; - menu->load.patch_path = path_clone_push(menu->browser.directory, menu->browser.entry->name); + menu->load.rom_patch_path = path_clone_push(menu->browser.directory, menu->browser.entry->name); - // rom_patcher_err_t err = patch_info_load(path_get(menu->load.patch_path), &menu->load.patch_info); + // rom_patch_load_err_t err = patch_info_load(path_get(menu->load.rom_patch_path), &menu->load.patch_info); // if (err != PATCH_OK) { // menu_show_error(menu, convert_error_message(err)); // } From 0533df899cf7fc912fb750ab7a3f21866bbe5a0b Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Sun, 17 Mar 2024 19:17:46 +0000 Subject: [PATCH 19/24] Change patch entry type --- src/menu/menu_state.h | 2 +- src/menu/views/browser.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/menu/menu_state.h b/src/menu/menu_state.h index a704153a..42806363 100644 --- a/src/menu/menu_state.h +++ b/src/menu/menu_state.h @@ -50,7 +50,7 @@ typedef enum { ENTRY_TYPE_DIR, ENTRY_TYPE_ROM, ENTRY_TYPE_DISK, - ENTRY_TYPE_PATCH, + ENTRY_TYPE_ROM_PATCH, ENTRY_TYPE_EMULATOR, ENTRY_TYPE_SAVE, ENTRY_TYPE_IMAGE, diff --git a/src/menu/views/browser.c b/src/menu/views/browser.c index ae56fb82..b06819c6 100644 --- a/src/menu/views/browser.c +++ b/src/menu/views/browser.c @@ -36,9 +36,9 @@ static int compare_entry (const void *pa, const void *pb) { return -1; } else if (b->type == ENTRY_TYPE_DISK) { return 1; - } else if (a->type == ENTRY_TYPE_PATCH) { + } else if (a->type == ENTRY_TYPE_ROM_PATCH) { return -1; - } else if (b->type == ENTRY_TYPE_PATCH) { + } else if (b->type == ENTRY_TYPE_ROM_PATCH) { return 1; } else if (a->type == ENTRY_TYPE_EMULATOR) { return -1; @@ -115,7 +115,7 @@ static bool load_directory (menu_t *menu) { } else if (file_has_extensions(info.fname, disk_extensions)) { entry->type = ENTRY_TYPE_DISK; } else if (file_has_extensions(info.fname, patch_extensions)) { - entry->type = ENTRY_TYPE_PATCH; + entry->type = ENTRY_TYPE_ROM_PATCH; }else if (file_has_extensions(info.fname, emulator_extensions)) { entry->type = ENTRY_TYPE_EMULATOR; } else if (file_has_extensions(info.fname, save_extensions)) { @@ -308,7 +308,7 @@ static void process (menu_t *menu) { case ENTRY_TYPE_EMULATOR: menu->next_mode = MENU_MODE_LOAD_EMULATOR; break; - case ENTRY_TYPE_PATCH: + case ENTRY_TYPE_ROM_PATCH: menu->next_mode = MENU_MODE_LOAD_ROM_PATCH; break; case ENTRY_TYPE_IMAGE: @@ -353,7 +353,7 @@ static void draw (menu_t *menu, surface_t *d) { case ENTRY_TYPE_DIR: action = "A: Enter"; break; case ENTRY_TYPE_ROM: action = "A: Load"; break; case ENTRY_TYPE_DISK: action = "A: Load"; break; - case ENTRY_TYPE_PATCH: action = "A: Load"; break; + case ENTRY_TYPE_ROM_PATCH: action = "A: Load"; break; case ENTRY_TYPE_IMAGE: action = "A: Show"; break; case ENTRY_TYPE_TEXT: action = "A: View"; break; case ENTRY_TYPE_MUSIC: action = "A: Play"; break; From 8077f06702c015ac6765628eb2001a55c46a9b7d Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Sun, 17 Mar 2024 19:37:02 +0000 Subject: [PATCH 20/24] update libgragon submodule --- libdragon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdragon b/libdragon index 6323128d..596490a9 160000 --- a/libdragon +++ b/libdragon @@ -1 +1 @@ -Subproject commit 6323128d72fdf32dfaa134f40191ba72e5527076 +Subproject commit 596490a9b650d52463b79c9356774bf3c65623f3 From 657651ae14f86a0f03f255bfc345f9ee4d1d2bd4 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Sun, 19 May 2024 17:54:50 +0100 Subject: [PATCH 21/24] Fix merge --- src/menu/rom_patch_info.c | 2 +- src/menu/views/browser.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/menu/rom_patch_info.c b/src/menu/rom_patch_info.c index ebbd491f..cdb2430f 100644 --- a/src/menu/rom_patch_info.c +++ b/src/menu/rom_patch_info.c @@ -111,7 +111,7 @@ rom_patch_load_err_t rom_patch_info_load (char *path) FIL fil; rom_patch_load_err_t err; - if (f_open(&fil, strip_sd_prefix(path), FA_READ) != FR_OK) { + if (f_open(&fil, strip_fs_prefix(path), FA_READ) != FR_OK) { return PATCH_ERR_NO_FILE; } diff --git a/src/menu/views/browser.c b/src/menu/views/browser.c index b9df2bc8..e7459661 100644 --- a/src/menu/views/browser.c +++ b/src/menu/views/browser.c @@ -136,6 +136,8 @@ static bool load_directory (menu_t *menu) { entry->type = ENTRY_TYPE_DISK; }else if (file_has_extensions(entry->name, emulator_extensions)) { entry->type = ENTRY_TYPE_EMULATOR; + } else if (file_has_extensions(entry->name, patch_extensions)) { + entry->type = ENTRY_TYPE_ROM_PATCH; } else if (file_has_extensions(entry->name, save_extensions)) { entry->type = ENTRY_TYPE_SAVE; } else if (file_has_extensions(entry->name, image_extensions)) { From c68e72bb949e56d6d6bfa691bda71c38b2560f77 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Tue, 6 Aug 2024 23:23:43 +0100 Subject: [PATCH 22/24] Update src/menu/rom_patch_info.c test Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- src/menu/rom_patch_info.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/menu/rom_patch_info.c b/src/menu/rom_patch_info.c index cdb2430f..24940580 100644 --- a/src/menu/rom_patch_info.c +++ b/src/menu/rom_patch_info.c @@ -121,7 +121,21 @@ rom_patch_load_err_t rom_patch_info_load (char *path) // Though needs conversion from JS to C // apply patch dependent on extension. - rom_patch_type_t patch_ext_type = PATCH_TYPE_IPS; // FIXME: should be the extension of the file! + rom_patch_type_t patch_ext_type; + // Determine patch type based on file extension + if (file_has_extension(path, "bps")) { + patch_ext_type = PATCH_TYPE_BPS; + } else if (file_has_extension(path, "ips")) { + patch_ext_type = PATCH_TYPE_IPS; + } else if (file_has_extension(path, "aps")) { + patch_ext_type = PATCH_TYPE_APS; + } else if (file_has_extension(path, "ups")) { + patch_ext_type = PATCH_TYPE_UPS; + } else if (file_has_extension(path, "xdelta")) { + patch_ext_type = PATCH_TYPE_XDELTA; + } else { + return PATCH_ERR_UNSUPPORTED; + } switch (patch_ext_type) { From 1cfb7747f869f17659d15408d6f3b883725794f4 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Thu, 8 Aug 2024 15:57:08 +0100 Subject: [PATCH 23/24] Use libdragon file api Rather than fatfs --- src/menu/rom_patch_info.c | 72 ++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 43 deletions(-) diff --git a/src/menu/rom_patch_info.c b/src/menu/rom_patch_info.c index 24940580..f583b4f5 100644 --- a/src/menu/rom_patch_info.c +++ b/src/menu/rom_patch_info.c @@ -1,10 +1,16 @@ -#include #include #include "utils/fs.h" #include "rom_patch_info.h" #include "rom_info.h" +static const char *patch_rom_bps_extensions[] = { "aps", NULL }; +static const char *patch_rom_ips_extensions[] = { "ips", NULL }; +static const char *patch_rom_aps_extensions[] = { "aps", NULL }; +static const char *patch_rom_ups_extensions[] = { "ups", NULL }; +static const char *patch_rom_xdelta_extensions[] = { "xdelta", NULL }; + + typedef struct { char header_magic[6]; // The header type, should always be "APS10" for N64. (plus null char) @@ -51,67 +57,47 @@ typedef struct } aps_patch_record_rle_t; -rom_patch_load_err_t apply_patch_type_bps(FIL *fil) +rom_patch_load_err_t apply_patch_type_bps(FILE *f) { // https://github.com/Alcaro/Flips/blob/master/bps_spec.md // https://www.romhacking.net/documents/746/ return PATCH_ERR_UNSUPPORTED; } -rom_patch_load_err_t apply_patch_type_ips(FIL *fil) +rom_patch_load_err_t apply_patch_type_ips(FILE *f) { // https://web.archive.org/web/20170624071240/http://www.smwiki.net:80/wiki/IPS_file_format - UINT bytes_read = 0; - char header_magic[5]; - f_read(fil, header_magic, 5, &bytes_read); - - // Check the header is valid. - if (strcmp(header_magic, PATCH_IPS_MAGIC) != 0) { - return PATCH_ERR_INVALID; - } - - //ips_patch_record_t records; - //ips_patch_record_rle_t records_rle; - // FIXME: we are not yet doing the patch write! - return PATCH_OK; + // FIXME: we are not yet implementing it, but should be the first one! + return PATCH_ERR_INVALID; } -rom_patch_load_err_t apply_patch_type_aps(FIL *fil) +rom_patch_load_err_t apply_patch_type_aps(FILE *f) { // https://github.com/btimofeev/UniPatcher/wiki/APS-(N64) - UINT bytes_read = 0; - aps_patch_header_t aps_patch_header; - f_read(fil, &aps_patch_header, sizeof(aps_patch_header_t), &bytes_read); - - // Check the header is valid. - if (strcmp(aps_patch_header.header_magic, PATCH_APS_MAGIC_N64) != 0) { - return PATCH_ERR_INVALID; - } - - return PATCH_ERR_INVALID; + return PATCH_ERR_UNSUPPORTED; } -rom_patch_load_err_t apply_patch_type_ups(FIL *fil) +rom_patch_load_err_t apply_patch_type_ups(FILE *f) { // http://www.romhacking.net/documents/392/ return PATCH_ERR_UNSUPPORTED; } -rom_patch_load_err_t apply_patch_type_xdelta(FIL *fil) +rom_patch_load_err_t apply_patch_type_xdelta(FILE *f) { return PATCH_ERR_UNSUPPORTED; } -rom_patch_load_err_t rom_patch_info_load (char *path) +rom_patch_load_err_t rom_patch_info_load (path_t *path) { - FIL fil; + FILE *f; rom_patch_load_err_t err; - if (f_open(&fil, strip_fs_prefix(path), FA_READ) != FR_OK) { + if ((f = fopen(path_get(path), "rb")) == NULL) { return PATCH_ERR_NO_FILE; } @@ -123,15 +109,15 @@ rom_patch_load_err_t rom_patch_info_load (char *path) rom_patch_type_t patch_ext_type; // Determine patch type based on file extension - if (file_has_extension(path, "bps")) { + if (file_has_extensions(path_get(path), patch_rom_bps_extensions)) { patch_ext_type = PATCH_TYPE_BPS; - } else if (file_has_extension(path, "ips")) { + } else if (file_has_extensions(path_get(path), patch_rom_ips_extensions)) { patch_ext_type = PATCH_TYPE_IPS; - } else if (file_has_extension(path, "aps")) { + } else if (file_has_extensions(path_get(path), patch_rom_aps_extensions)) { patch_ext_type = PATCH_TYPE_APS; - } else if (file_has_extension(path, "ups")) { + } else if (file_has_extensions(path_get(path), patch_rom_ups_extensions)) { patch_ext_type = PATCH_TYPE_UPS; - } else if (file_has_extension(path, "xdelta")) { + } else if (file_has_extensions(path_get(path), patch_rom_xdelta_extensions)) { patch_ext_type = PATCH_TYPE_XDELTA; } else { return PATCH_ERR_UNSUPPORTED; @@ -140,26 +126,26 @@ rom_patch_load_err_t rom_patch_info_load (char *path) switch (patch_ext_type) { case PATCH_TYPE_BPS: - err = apply_patch_type_bps(&fil); + err = apply_patch_type_bps(f); break; case PATCH_TYPE_IPS: - err = apply_patch_type_ips(&fil); + err = apply_patch_type_ips(f); break; case PATCH_TYPE_APS: - err = apply_patch_type_aps(&fil); + err = apply_patch_type_aps(f); break; case PATCH_TYPE_UPS: - err = apply_patch_type_ups(&fil); + err = apply_patch_type_ups(f); break; case PATCH_TYPE_XDELTA: - err = apply_patch_type_xdelta(&fil); + err = apply_patch_type_xdelta(f); break; default: return PATCH_ERR_UNSUPPORTED; } - if (f_close(&fil) != FR_OK) { + if (fclose(f)) { return PATCH_ERR_IO; } From 01e2ec31333fc271c6c3a5cedf5a8e7c21b8e330 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Thu, 8 Aug 2024 16:47:46 +0100 Subject: [PATCH 24/24] Attempt towards IPS mostly commented out. --- src/menu/rom_patch_info.c | 56 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/src/menu/rom_patch_info.c b/src/menu/rom_patch_info.c index f583b4f5..992e822b 100644 --- a/src/menu/rom_patch_info.c +++ b/src/menu/rom_patch_info.c @@ -1,4 +1,5 @@ #include +#include #include "utils/fs.h" #include "rom_patch_info.h" #include "rom_info.h" @@ -68,9 +69,60 @@ rom_patch_load_err_t apply_patch_type_ips(FILE *f) { // https://web.archive.org/web/20170624071240/http://www.smwiki.net:80/wiki/IPS_file_format + char header_magic[5]; + fread(header_magic, 5, 1, f); - // FIXME: we are not yet implementing it, but should be the first one! - return PATCH_ERR_INVALID; + // Check the header is valid. + if (strcmp(header_magic, PATCH_IPS_MAGIC) != 0) { + return PATCH_ERR_INVALID; + } + + // while (true) { + // uint8_t offset_bytes[3]; + // fread(offset_bytes, 3, 1, f); + // uint32_t offset = (offset_bytes[0] << 16) | (offset_bytes[1] << 8) | offset_bytes[2]; + + // // Check for end-of-file marker. + // if (offset == 0x454F46) { // "EOF" in ASCII (big endian?) + // break; + // } + + // uint16_t size; + // fread(&size, 2, 1, f); + // size = (size >> 8) | (size << 8); // Convert to big-endian + + // if (size == 0) { + // // RLE record + // uint16_t rle_size; + // uint8_t rle_byte; + // fread(&rle_size, 2, 1, f); + // fread(&rle_byte, 1, 1, f); + // rle_size = (rle_size >> 8) | (rle_size << 8); // Convert to big-endian + + // // Apply RLE patch + // for (int i = 0; i < rle_size; i++) { + // // Write rle_byte to the ROM at the given offset + // // (Assuming a function write_byte_to_rom exists) + // //write_byte_to_rom(offset + i, rle_byte); + // } + // } else { + // // Normal record + // uint8_t *data = malloc(size); + // fread(data, size, 1, f); + + // // Apply patch + // for (int i = 0; i < size; i++) { + // // Write data[i] to the ROM at the given offset + // // (Assuming a function write_byte_to_rom exists) + // //write_byte_to_rom(offset + i, data[i]); + // } + + // free(data); + // } + // } + + // FIXME: we are not yet applying it! + return PATCH_OK; } rom_patch_load_err_t apply_patch_type_aps(FILE *f)