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);