From a1d20ae36ec0e4a7cd1bcf0accd4522db6229b9c Mon Sep 17 00:00:00 2001 From: Mateusz Faderewski Date: Fri, 18 Aug 2023 22:19:01 +0200 Subject: [PATCH] Added option to put saves in subdirectory + moved ROM loading procedure outside of views --- Makefile | 3 +- src/menu/cart_load.c | 142 ++++++++++++++++++++++++++ src/menu/cart_load.h | 38 +++++++ src/menu/menu.c | 4 +- src/menu/menu_state.h | 4 +- src/menu/settings.c | 3 + src/menu/settings.h | 3 + src/menu/views/browser.c | 4 +- src/menu/views/error.c | 1 + src/menu/views/load_emulator.c | 109 +++++--------------- src/menu/views/{load.c => load_rom.c} | 57 ++--------- src/menu/views/views.h | 4 +- 12 files changed, 232 insertions(+), 140 deletions(-) create mode 100644 src/menu/cart_load.c create mode 100644 src/menu/cart_load.h rename src/menu/views/{load.c => load_rom.c} (82%) diff --git a/Makefile b/Makefile index e2b1742c..f31233df 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,7 @@ SRCS = \ libs/miniz/miniz_zip.c \ libs/miniz/miniz.c \ menu/actions.c \ + menu/cart_load.c \ menu/components/background.c \ menu/components/boxart.c \ menu/components/common.c \ @@ -47,7 +48,7 @@ SRCS = \ menu/views/file_info.c \ menu/views/image_viewer.c \ menu/views/load_emulator.c \ - menu/views/load.c \ + menu/views/load_rom.c \ menu/views/music_player.c \ menu/views/startup.c \ menu/views/system_info.c \ diff --git a/src/menu/cart_load.c b/src/menu/cart_load.c new file mode 100644 index 00000000..a8de2087 --- /dev/null +++ b/src/menu/cart_load.c @@ -0,0 +1,142 @@ +#include "cart_load.h" +#include "path.h" +#include "utils/fs.h" + + +#define SAVES_SUBDIRECTORY "saves" +#define EMU_LOCATION "/emulators" + + +static bool create_saves_subdirectory (menu_t *menu) { + path_t *save_folder_path = path_clone_push(menu->browser.directory, SAVES_SUBDIRECTORY); + bool error = directory_create(path_get(save_folder_path)); + path_free(save_folder_path); + return error; +} + +static flashcart_save_type_t convert_save_type (rom_header_t *header) { + switch (rom_db_match_save_type(*header)) { + case DB_SAVE_TYPE_EEPROM_4K: + return FLASHCART_SAVE_TYPE_EEPROM_4K; + case DB_SAVE_TYPE_EEPROM_16K: + return FLASHCART_SAVE_TYPE_EEPROM_16K; + case DB_SAVE_TYPE_SRAM: + return FLASHCART_SAVE_TYPE_SRAM; + case DB_SAVE_TYPE_SRAM_BANKED: + return FLASHCART_SAVE_TYPE_SRAM_BANKED; + case DB_SAVE_TYPE_SRAM_128K: + return FLASHCART_SAVE_TYPE_SRAM_128K; + case DB_SAVE_TYPE_FLASHRAM: + return FLASHCART_SAVE_TYPE_FLASHRAM; + default: + return FLASHCART_SAVE_TYPE_NONE; + } +} + + +char *cart_load_convert_error_message (cart_load_err_t err) { + switch (err) { + case CART_LOAD_ERR_SAVES_SUBDIR: return "Could not create saves subdirectory"; + case CART_LOAD_ERR_ROM: return "Error during ROM loading"; + case CART_LOAD_ERR_SAVE: return "Error during save creation or loading"; + case CART_LOAD_ERR_EMU_NOT_FOUND: return "Emulator ROM not found"; + case CART_LOAD_ERR_EMU: return "Error during emulator ROM loading"; + case CART_LOAD_ERR_EMU_ROM: return "Error during emulated ROM loading"; + default: return "Unknown cart load error"; + } +} + +cart_load_err_t cart_load_n64_rom_and_save (menu_t *menu, rom_header_t *header, flashcart_progress_callback_t progress) { + if (menu->settings.use_saves_folder) { + if (create_saves_subdirectory(menu)) { + return CART_LOAD_ERR_SAVES_SUBDIR; + } + } + + path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name); + + bool byte_swap = (header->config_flags == ROM_MID_BIG_ENDIAN); + menu->flashcart_error = flashcart_load_rom(path_get(path), byte_swap, progress); + if (menu->flashcart_error != FLASHCART_OK) { + path_free(path); + return CART_LOAD_ERR_ROM; + } + + path_ext_replace(path, "sav"); + if (menu->settings.use_saves_folder) { + path_push_subdir(path, SAVES_SUBDIRECTORY); + } + + menu->flashcart_error = flashcart_load_save(path_get(path), convert_save_type(header)); + if (menu->flashcart_error != FLASHCART_OK) { + path_free(path); + return CART_LOAD_ERR_SAVE; + } + + path_free(path); + + return CART_LOAD_OK; +} + +cart_load_err_t cart_load_emulator (menu_t *menu, cart_load_emu_type_t emu_type, flashcart_progress_callback_t progress) { + if (menu->settings.use_saves_folder) { + if (create_saves_subdirectory(menu)) { + return CART_LOAD_ERR_SAVES_SUBDIR; + } + } + + path_t *path = path_init("sd:/", EMU_LOCATION); + flashcart_save_type_t save_type = FLASHCART_SAVE_TYPE_NONE; + uint32_t emulated_rom_offset = 0x200000; + + switch (emu_type) { + case CART_LOAD_EMU_TYPE_NES: + path_push(path, "emu.nes"); + save_type = FLASHCART_SAVE_TYPE_SRAM_BANKED; + break; + case CART_LOAD_EMU_TYPE_GAMEBOY: + path_push(path, "emu.gb"); + save_type = FLASHCART_SAVE_TYPE_FLASHRAM; + break; + case CART_LOAD_EMU_TYPE_GAMEBOY_COLOR: + path_push(path, "emu.gbc"); + save_type = FLASHCART_SAVE_TYPE_FLASHRAM; + break; + } + + if (!file_exists(path_get(path))) { + path_free(path); + return CART_LOAD_ERR_EMU_NOT_FOUND; + } + + menu->flashcart_error = flashcart_load_rom(path_get(path), false, progress); + if (menu->flashcart_error != FLASHCART_OK) { + path_free(path); + return CART_LOAD_ERR_EMU; + } + + path_free(path); + + path = path_clone_push(menu->browser.directory, menu->browser.entry->name); + + menu->flashcart_error = flashcart_load_file(path_get(path), emulated_rom_offset); + if (menu->flashcart_error != FLASHCART_OK) { + path_free(path); + return CART_LOAD_ERR_EMU_ROM; + } + + path_ext_replace(path, "sav"); + if (menu->settings.use_saves_folder) { + path_push_subdir(path, SAVES_SUBDIRECTORY); + } + + menu->flashcart_error = flashcart_load_save(path_get(path), save_type); + if (menu->flashcart_error != FLASHCART_OK) { + path_free(path); + return CART_LOAD_ERR_SAVE; + } + + path_free(path); + + return CART_LOAD_OK; +} diff --git a/src/menu/cart_load.h b/src/menu/cart_load.h new file mode 100644 index 00000000..5527206b --- /dev/null +++ b/src/menu/cart_load.h @@ -0,0 +1,38 @@ +/** + * @file cart_load.h + * @brief ROM/save loading functions + * @ingroup menu + */ + +#ifndef CART_LOAD_H__ +#define CART_LOAD_H__ + + +#include "flashcart/flashcart.h" +#include "menu_state.h" +#include "rom_database.h" + + +typedef enum { + CART_LOAD_OK, + CART_LOAD_ERR_SAVES_SUBDIR, + CART_LOAD_ERR_ROM, + CART_LOAD_ERR_SAVE, + CART_LOAD_ERR_EMU_NOT_FOUND, + CART_LOAD_ERR_EMU, + CART_LOAD_ERR_EMU_ROM, +} cart_load_err_t; + +typedef enum { + CART_LOAD_EMU_TYPE_NES, + CART_LOAD_EMU_TYPE_GAMEBOY, + CART_LOAD_EMU_TYPE_GAMEBOY_COLOR, +} cart_load_emu_type_t; + + +char *cart_load_convert_error_message (cart_load_err_t err); +cart_load_err_t cart_load_n64_rom_and_save (menu_t *menu, rom_header_t *header, flashcart_progress_callback_t progress); +cart_load_err_t cart_load_emulator (menu_t *menu, cart_load_emu_type_t emu_type, flashcart_progress_callback_t progress); + + +#endif diff --git a/src/menu/menu.c b/src/menu/menu.c index bb552560..f728d12e 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -137,8 +137,8 @@ static struct views_s { { view_image_viewer_init, view_image_viewer_display }, // MENU_MODE_IMAGE_VIEWER { view_music_player_init, view_music_player_display }, // MENU_MODE_MUSIC_PLAYER { view_credits_init, view_credits_display }, // MENU_MODE_CREDITS - { view_load_init, view_load_display }, // MENU_MODE_LOAD - { view_load_emulator_init, view_load_emulator_display }, // MENU_MODE_EMULATOR_LOAD + { view_load_rom_init, view_load_rom_display }, // MENU_MODE_LOAD_ROM + { 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 { NULL, NULL }, // MENU_MODE_BOOT diff --git a/src/menu/menu_state.h b/src/menu/menu_state.h index 97aa8e5a..5e0d07b7 100644 --- a/src/menu/menu_state.h +++ b/src/menu/menu_state.h @@ -28,8 +28,8 @@ typedef enum { MENU_MODE_IMAGE_VIEWER, MENU_MODE_MUSIC_PLAYER, MENU_MODE_CREDITS, - MENU_MODE_LOAD, - MENU_MODE_EMULATOR_LOAD, + MENU_MODE_LOAD_ROM, + MENU_MODE_LOAD_EMULATOR, MENU_MODE_ERROR, MENU_MODE_FAULT, MENU_MODE_BOOT, diff --git a/src/menu/settings.c b/src/menu/settings.c index b8a6b5b4..a4a05f97 100644 --- a/src/menu/settings.c +++ b/src/menu/settings.c @@ -12,6 +12,7 @@ static settings_t init = { .pal60 = false, .show_hidden_files = false, .default_directory = "/", + .use_saves_folder = false, }; @@ -25,6 +26,7 @@ void settings_load (settings_t *settings) { settings->pal60 = mini_get_bool(ini, "menu", "pal60", init.pal60); settings->show_hidden_files = mini_get_bool(ini, "menu", "show_hidden_files", init.show_hidden_files); settings->default_directory = strdup(mini_get_string(ini, "menu", "default_directory", init.default_directory)); + settings->use_saves_folder = mini_get_bool(ini, "menu", "use_saves_folder", init.use_saves_folder); mini_free(ini); } @@ -35,6 +37,7 @@ void settings_save (settings_t *settings) { mini_set_bool(ini, "menu", "pal60", settings->pal60); mini_set_bool(ini, "menu", "show_hidden_files", settings->show_hidden_files); mini_set_string(ini, "menu", "default_directory", settings->default_directory); + mini_set_bool(ini, "menu", "use_saves_folder", settings->use_saves_folder); mini_save(ini); diff --git a/src/menu/settings.h b/src/menu/settings.h index 575059ef..39781a15 100644 --- a/src/menu/settings.h +++ b/src/menu/settings.h @@ -18,6 +18,9 @@ typedef struct { /** @brief Default directory to navigate to when menu loads */ char *default_directory; + + /** @brief Put saves into separate directory */ + bool use_saves_folder; } settings_t; diff --git a/src/menu/views/browser.c b/src/menu/views/browser.c index 15b7adfe..95e43c9a 100644 --- a/src/menu/views/browser.c +++ b/src/menu/views/browser.c @@ -196,10 +196,10 @@ static void process (menu_t *menu) { } break; case ENTRY_TYPE_ROM: - menu->next_mode = MENU_MODE_LOAD; + menu->next_mode = MENU_MODE_LOAD_ROM; break; case ENTRY_TYPE_EMULATOR: - menu->next_mode = MENU_MODE_EMULATOR_LOAD; + menu->next_mode = MENU_MODE_LOAD_EMULATOR; break; case ENTRY_TYPE_IMAGE: menu->next_mode = MENU_MODE_IMAGE_VIEWER; diff --git a/src/menu/views/error.c b/src/menu/views/error.c index 711f166e..120e40cd 100644 --- a/src/menu/views/error.c +++ b/src/menu/views/error.c @@ -43,4 +43,5 @@ void view_error_display (menu_t *menu, surface_t *display) { void menu_show_error (menu_t *menu, char *error_message) { menu->next_mode = MENU_MODE_ERROR; menu->error_message = error_message; + menu->browser.valid = false; } diff --git a/src/menu/views/load_emulator.c b/src/menu/views/load_emulator.c index c96cde80..349d1812 100644 --- a/src/menu/views/load_emulator.c +++ b/src/menu/views/load_emulator.c @@ -1,22 +1,16 @@ -#include - +#include "../cart_load.h" #include "boot/boot.h" -#include "flashcart/flashcart.h" #include "utils/fs.h" #include "views.h" -#ifndef EMULATOR_FOLDER -#define EMULATOR_FOLDER "/emulators/" -#endif static const char *emu_nes_rom_extensions[] = { "nes", NULL }; static const char *emu_gameboy_rom_extensions[] = { "gb", NULL }; static const char *emu_gameboy_color_rom_extensions[] = { "gbc", NULL }; -static const char *emu_sega_rom_extensions[] = {"smc", "gen", "smd", NULL }; - -static const uint32_t eum_rom_start_address = 0x200000; +// static const char *emu_sega_rom_extensions[] = {"smc", "gen", "smd", NULL }; static bool load_pending; +static cart_load_emu_type_t emu_type; static void process (menu_t *menu) { @@ -71,86 +65,15 @@ static void draw_progress (float progress) { } } -static void load_emulator_nes_rom (path_t *path, menu_t *menu) { - if (file_exists(EMULATOR_FOLDER"emu.nes")) { // || neon64bu.rom - menu->flashcart_error = flashcart_load_rom(EMULATOR_FOLDER"emu.nes", false, draw_progress); - /* Combine EMU and ROM before loading. See https://github.com/hcs64/neon64v2/tree/master/pkg */ - menu->flashcart_error = flashcart_load_file(path_get(path), eum_rom_start_address); - if (menu->flashcart_error != FLASHCART_OK) { - menu->next_mode = MENU_MODE_FAULT; - path_free(path); - return; - } - - path_ext_replace(path, "sav"); - menu->flashcart_error = flashcart_load_save(path_get(path), FLASHCART_SAVE_TYPE_SRAM_BANKED); - if (menu->flashcart_error != FLASHCART_OK) { - menu->next_mode = MENU_MODE_FAULT; - path_free(path); - return; - } - } -} - -static void load_emulator_gameboy_rom (path_t *path, menu_t *menu) { - if (file_exists(EMULATOR_FOLDER"emu.gb")) { // || gb.v64 - menu->flashcart_error = flashcart_load_rom(EMULATOR_FOLDER"emu.gb", false, draw_progress); - /* Combine EMU and ROM before loading. */ - menu->flashcart_error = flashcart_load_file(path_get(path), eum_rom_start_address); - if (menu->flashcart_error != FLASHCART_OK) { - menu->next_mode = MENU_MODE_FAULT; - path_free(path); - return; - } - - path_ext_replace(path, "sav"); - menu->flashcart_error = flashcart_load_save(path_get(path), FLASHCART_SAVE_TYPE_FLASHRAM); - if (menu->flashcart_error != FLASHCART_OK) { - menu->next_mode = MENU_MODE_FAULT; - path_free(path); - return; - } - } -} - -static void load_emulator_gameboy_color_rom (path_t *path, menu_t *menu) { - if (file_exists(EMULATOR_FOLDER"emu.gbc")) { // || gbc.v64 - menu->flashcart_error = flashcart_load_rom(EMULATOR_FOLDER"emu.gbc", false, draw_progress); - /* Combine EMU and ROM before loading. */ - menu->flashcart_error = flashcart_load_file(path_get(path), eum_rom_start_address); - if (menu->flashcart_error != FLASHCART_OK) { - menu->next_mode = MENU_MODE_FAULT; - path_free(path); - return; - } - - path_ext_replace(path, "sav"); - menu->flashcart_error = flashcart_load_save(path_get(path), FLASHCART_SAVE_TYPE_FLASHRAM); - if (menu->flashcart_error != FLASHCART_OK) { - menu->next_mode = MENU_MODE_FAULT; - path_free(path); - return; - } - } -} - static void load (menu_t *menu) { - menu->next_mode = MENU_MODE_BOOT; + cart_load_err_t err = cart_load_emulator(menu, emu_type, draw_progress); - path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name); - - if (file_has_extensions(path_get(path), emu_nes_rom_extensions)) { - load_emulator_nes_rom(path, menu); - } else if (file_has_extensions(path_get(path), emu_gameboy_rom_extensions)) { - load_emulator_gameboy_rom(path, menu); - } else if (file_has_extensions(path_get(path), emu_gameboy_color_rom_extensions)) { - load_emulator_gameboy_color_rom(path, menu); - } else if (file_has_extensions(path_get(path), emu_sega_rom_extensions)) { - //load_emulator_sega_rom(path, menu); + if (err != CART_LOAD_OK) { + menu_show_error(menu, cart_load_convert_error_message(err)); + return; } - path_free(path); - + 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; @@ -159,6 +82,22 @@ static void load (menu_t *menu) { void view_load_emulator_init (menu_t *menu) { load_pending = false; + + path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name); + + if (file_has_extensions(path_get(path), emu_nes_rom_extensions)) { + emu_type = CART_LOAD_EMU_TYPE_NES; + } else if (file_has_extensions(path_get(path), emu_gameboy_rom_extensions)) { + emu_type = CART_LOAD_EMU_TYPE_GAMEBOY; + } else if (file_has_extensions(path_get(path), emu_gameboy_color_rom_extensions)) { + emu_type = CART_LOAD_EMU_TYPE_GAMEBOY_COLOR; + // } else if (file_has_extensions(path_get(path), emu_sega_rom_extensions)) { + // emu_type = CART_LOAD_EMU_TYPE_SEGA; + } else { + menu_show_error(menu, "Unsupported ROM"); + } + + path_free(path); } void view_load_emulator_display (menu_t *menu, surface_t *display) { diff --git a/src/menu/views/load.c b/src/menu/views/load_rom.c similarity index 82% rename from src/menu/views/load.c rename to src/menu/views/load_rom.c index 246bc181..d5828c1d 100644 --- a/src/menu/views/load.c +++ b/src/menu/views/load_rom.c @@ -1,6 +1,6 @@ +#include "../cart_load.h" #include "../rom_database.h" #include "boot/boot.h" -#include "flashcart/flashcart.h" #include "views.h" @@ -224,50 +224,15 @@ static void draw_progress (float progress) { } } -static flashcart_save_type_t convert_save_type (db_savetype_t save_type) { - switch (save_type) { - case DB_SAVE_TYPE_EEPROM_4K: - return FLASHCART_SAVE_TYPE_EEPROM_4K; - case DB_SAVE_TYPE_EEPROM_16K: - return FLASHCART_SAVE_TYPE_EEPROM_16K; - case DB_SAVE_TYPE_SRAM: - return FLASHCART_SAVE_TYPE_SRAM; - case DB_SAVE_TYPE_SRAM_BANKED: - return FLASHCART_SAVE_TYPE_SRAM_BANKED; - case DB_SAVE_TYPE_SRAM_128K: - return FLASHCART_SAVE_TYPE_SRAM_128K; - case DB_SAVE_TYPE_FLASHRAM: - return FLASHCART_SAVE_TYPE_FLASHRAM; - default: - return FLASHCART_SAVE_TYPE_NONE; - } -} - static void load (menu_t *menu) { + cart_load_err_t err = cart_load_n64_rom_and_save(menu, &rom_header, draw_progress); + + if (err != CART_LOAD_OK) { + menu_show_error(menu, cart_load_convert_error_message(err)); + return; + } + menu->next_mode = MENU_MODE_BOOT; - - path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name); - - bool byte_swap = (rom_header.config_flags == ROM_MID_BIG_ENDIAN); - menu->flashcart_error = flashcart_load_rom(path_get(path), byte_swap, draw_progress); - if (menu->flashcart_error != FLASHCART_OK) { - menu->next_mode = MENU_MODE_FAULT; - path_free(path); - return; - } - - uint8_t save_type = rom_db_match_save_type(rom_header); - - path_ext_replace(path, "sav"); - menu->flashcart_error = flashcart_load_save(path_get(path), convert_save_type(save_type)); - if (menu->flashcart_error != FLASHCART_OK) { - menu->next_mode = MENU_MODE_FAULT; - path_free(path); - return; - } - - path_free(path); - 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; @@ -278,7 +243,7 @@ static void deinit (void) { } -void view_load_init (menu_t *menu) { +void view_load_rom_init (menu_t *menu) { load_pending = false; path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name); @@ -290,7 +255,7 @@ void view_load_init (menu_t *menu) { path_free(path); } -void view_load_display (menu_t *menu, surface_t *display) { +void view_load_rom_display (menu_t *menu, surface_t *display) { process(menu); draw(menu, display); @@ -300,7 +265,7 @@ void view_load_display (menu_t *menu, surface_t *display) { load(menu); } - if (menu->next_mode != MENU_MODE_LOAD) { + if (menu->next_mode != MENU_MODE_LOAD_ROM) { deinit(); } } diff --git a/src/menu/views/views.h b/src/menu/views/views.h index 0c02ce06..186000d5 100644 --- a/src/menu/views/views.h +++ b/src/menu/views/views.h @@ -38,8 +38,8 @@ void view_music_player_display (menu_t *menu, surface_t *display); void view_credits_init (menu_t *menu); void view_credits_display (menu_t *menu, surface_t *display); -void view_load_init (menu_t *menu); -void view_load_display (menu_t *menu, surface_t *display); +void view_load_rom_init (menu_t *menu); +void view_load_rom_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);