From 72b7c9491c16079491cd0b2e78591a2c549ab43a Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Mon, 10 Mar 2025 19:44:29 +0000 Subject: [PATCH] [develop] Add Fast Reboot mode for ROMs (#215) ## Description In this PR I have added the global setting, flashcart feature support and implementation of extra bootmodes (specifically fast reboot). Although technically supported, the 64drive implementation is currently commented out. ## Motivation and Context #75 ## How Has This Been Tested? On a summercart64. Having the USB cable inserted, the hard power ON/OFF contines to use the fast reboot ROM (expected). Having no USB cable inserted , the hard power ON/OFF loads the menu (expected). ## Screenshots ## Types of changes - [x] Improvement (non-breaking change that adds a new feature) - [ ] Bug fix (fixes an issue) - [ ] Breaking change (breaking change) - [ ] Documentation Improvement - [ ] Config and build (change in the configuration and build system, has no impact on code or features) ## Checklist: - [ ] My code follows the code style of this project. - [ ] My change requires a change to the documentation. - [ ] I have updated the documentation accordingly. - [ ] I have added tests to cover my changes. - [ ] All new and existing tests passed. Signed-off-by: GITHUB_USER --- CHANGELOG.md | 3 ++- docs/22_autoload_roms.md | 3 ++- docs/32_menu_settings.md | 5 +++++ src/flashcart/64drive/64drive.c | 11 +++++++++++ src/flashcart/ed64/ed64_vseries.c | 1 + src/flashcart/ed64/ed64_xseries.c | 1 + src/flashcart/flashcart.c | 9 +++++++++ src/flashcart/flashcart.h | 11 +++++++++++ src/flashcart/sc64/sc64.c | 20 ++++++++++++++++++++ src/menu/cart_load.c | 16 ++++++++++++++-- src/menu/cart_load.h | 2 ++ src/menu/views/settings_editor.c | 16 ++++++++++++++-- 12 files changed, 92 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ddb6703c..2930b56b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,8 @@ built from latest commit on main branch. - **New Features** - Introduced tabs in main menu for ROM favorites and recently played ROM history. - BETA_FEATURE: Introduces ROM descriptions from files. - - Ignore macOS metadata. + - BETA_FEATURE: Enabled setting for fast ROM reboots on the SC64. + - Add macOS metadata to hidden files. - **Bug Fixes** diff --git a/docs/22_autoload_roms.md b/docs/22_autoload_roms.md index 4ffa3862..e6ae7c2d 100644 --- a/docs/22_autoload_roms.md +++ b/docs/22_autoload_roms.md @@ -1,6 +1,7 @@ [Return to the index](./00_index.md) ## Autoloading N64 ROMs -You can set up N64FlashcartMenu to load a specific ROM directly instead of booting up the menu's graphical user interface. **NOTE:** byteswapped ROMs will slow down the ROM load process. +You can set up N64FlashcartMenu to load a specific ROM directly instead of booting up the menu's graphical user interface. **NOTE:** byteswapped ROMs will slow down the ROM load process. +If you only want to continously reload a ROM for a single gaming session, you should consider the setting for [Fast ROM reboots](./32_menu_settings.md) instead. ### How to enable autoloading To use the autoload function, open the `N64 ROM information` screen on any ROM, then press the `R` Button on your Controller and select the `Set ROM to autoload` option. When you restart the console, N64FlashcartMenu will now only load the selected ROM, rather than the menu itself. diff --git a/docs/32_menu_settings.md b/docs/32_menu_settings.md index e17710c5..82d639d8 100644 --- a/docs/32_menu_settings.md +++ b/docs/32_menu_settings.md @@ -13,3 +13,8 @@ OFF: ROM saves are saved alongside the ROM file. ### Sound Effects The menu has default sound effects to improve the user experience. This setting is OFF by default. + +### Fast ROM reboots +Certain flashcarts support the ability to use the N64 `RESET` button for re-loading the last game, rather than returning to the menu. When enabled (and if supported by your flashcart), the power switch must be toggled to return to the menu. +NOTE: if a USB cable is connected, the last game may continue to be re-loaded. +This setting is OFF by default. diff --git a/src/flashcart/64drive/64drive.c b/src/flashcart/64drive/64drive.c index 272f4869..91787d39 100644 --- a/src/flashcart/64drive/64drive.c +++ b/src/flashcart/64drive/64drive.c @@ -350,6 +350,16 @@ static flashcart_err_t d64_set_save_writeback (char *save_path) { return FLASHCART_OK; } +// static flashcart_err_t d64_set_bootmode (flashcart_reboot_mode_t boot_mode) { + +// if (d64_ll_set_persistent_variable_storage(true, 0, 0)) { +// return FLASHCART_ERR_INT; +// } + +// return FLASHCART_OK; +// } + + /** @brief Flashcart structure for 64drive. */ static flashcart_t flashcart_d64 = { .init = d64_init, @@ -363,6 +373,7 @@ static flashcart_t flashcart_d64 = { .load_64dd_disk = NULL, .set_save_type = d64_set_save_type, .set_save_writeback = d64_set_save_writeback, + .set_next_boot_mode = NULL, // d64_set_bootmode, }; /** diff --git a/src/flashcart/ed64/ed64_vseries.c b/src/flashcart/ed64/ed64_vseries.c index 3eca82f1..ea07b5d1 100644 --- a/src/flashcart/ed64/ed64_vseries.c +++ b/src/flashcart/ed64/ed64_vseries.c @@ -161,6 +161,7 @@ static flashcart_t flashcart_ed64_vseries = { .load_64dd_disk = NULL, .set_save_type = ed64_vseries_set_save_type, .set_save_writeback = NULL, + .set_next_boot_mode = NULL, }; diff --git a/src/flashcart/ed64/ed64_xseries.c b/src/flashcart/ed64/ed64_xseries.c index 1f1f4e07..52b599d3 100644 --- a/src/flashcart/ed64/ed64_xseries.c +++ b/src/flashcart/ed64/ed64_xseries.c @@ -167,6 +167,7 @@ static flashcart_t flashcart_ed64_xseries = { .load_64dd_disk = NULL, .set_save_type = ed64_xseries_set_save_type, .set_save_writeback = NULL, + .set_next_boot_mode = NULL, }; diff --git a/src/flashcart/flashcart.c b/src/flashcart/flashcart.c index b65c347f..48d0b2fe 100644 --- a/src/flashcart/flashcart.c +++ b/src/flashcart/flashcart.c @@ -107,6 +107,7 @@ static flashcart_t *flashcart = &((flashcart_t) { .load_64dd_disk = NULL, .set_save_type = dummy_set_save_type, .set_save_writeback = NULL, + .set_next_boot_mode = NULL, }); #ifdef NDEBUG @@ -349,3 +350,11 @@ flashcart_err_t flashcart_load_64dd_disk (char *disk_path, flashcart_disk_parame return flashcart->load_64dd_disk(disk_path, disk_parameters); } + +flashcart_err_t flashcart_set_next_boot_mode (flashcart_reboot_mode_t boot_mode) { + if (!flashcart->set_next_boot_mode) { + return FLASHCART_ERR_FUNCTION_NOT_SUPPORTED; + } + + return flashcart->set_next_boot_mode(boot_mode); +} diff --git a/src/flashcart/flashcart.h b/src/flashcart/flashcart.h index ff9a61d7..65812414 100644 --- a/src/flashcart/flashcart.h +++ b/src/flashcart/flashcart.h @@ -48,6 +48,14 @@ typedef enum { __FLASHCART_SAVE_TYPE_END /**< End of save types */ } flashcart_save_type_t; +/** @brief Flashcart save type enumeration */ +typedef enum { + /** @brief The flashcart will reboot into the menu on soft reboot (using the RESET button) */ + FLASHCART_REBOOT_MODE_MENU, + /** @brief The flashcart will reboot into the previous ROM on soft reboot (using the RESET button) */ + FLASHCART_REBOOT_MODE_ROM, +} flashcart_reboot_mode_t; + /** @brief Flashcart Disk Parameter Structure. */ typedef struct { bool development_drive; /**< Development drive flag */ @@ -90,6 +98,8 @@ typedef struct { flashcart_err_t (*set_save_type) (flashcart_save_type_t save_type); /** @brief The flashcart set save writeback function */ flashcart_err_t (*set_save_writeback) (char *save_path); + /** @brief The flashcart set boot mode function */ + flashcart_err_t (*set_next_boot_mode) (flashcart_reboot_mode_t boot_mode); } flashcart_t; /** @@ -176,5 +186,6 @@ flashcart_err_t flashcart_load_64dd_ipl (char *ipl_path, flashcart_progress_call * @return flashcart_err_t Error code. */ flashcart_err_t flashcart_load_64dd_disk (char *disk_path, flashcart_disk_parameters_t *disk_parameters); +flashcart_err_t flashcart_set_next_boot_mode (flashcart_reboot_mode_t boot_mode); #endif /* FLASHCART_H__ */ diff --git a/src/flashcart/sc64/sc64.c b/src/flashcart/sc64/sc64.c index 2c098993..66261c75 100644 --- a/src/flashcart/sc64/sc64.c +++ b/src/flashcart/sc64/sc64.c @@ -666,6 +666,25 @@ static flashcart_err_t sc64_set_save_writeback (char *save_path) { return FLASHCART_OK; } +static flashcart_err_t sc64_set_bootmode (flashcart_reboot_mode_t boot_mode) { + + sc64_boot_mode_t type = BOOT_MODE_MENU; + + switch (boot_mode) { + case FLASHCART_REBOOT_MODE_ROM: + type = BOOT_MODE_ROM; + break; + default: + type = BOOT_MODE_MENU; + break; + } + if (sc64_ll_set_config(CFG_ID_BOOT_MODE, type) != SC64_OK) { + return FLASHCART_ERR_INT; + } + + return FLASHCART_OK; +} + static flashcart_t flashcart_sc64 = { .init = sc64_init, @@ -679,6 +698,7 @@ static flashcart_t flashcart_sc64 = { .load_64dd_disk = sc64_load_64dd_disk, .set_save_type = sc64_set_save_type, .set_save_writeback = sc64_set_save_writeback, + .set_next_boot_mode = sc64_set_bootmode, }; diff --git a/src/menu/cart_load.c b/src/menu/cart_load.c index 0158b61d..2fa52b2b 100644 --- a/src/menu/cart_load.c +++ b/src/menu/cart_load.c @@ -75,8 +75,9 @@ static flashcart_save_type_t convert_save_type (rom_save_type_t save_type) { char *cart_load_convert_error_message (cart_load_err_t err) { switch (err) { case CART_LOAD_OK: return "Cart load OK"; - case CART_LOAD_ERR_ROM_LOAD_FAIL: return "Error occurred during ROM loading"; - case CART_LOAD_ERR_SAVE_LOAD_FAIL: return "Error occurred during save loading"; + case CART_LOAD_ERR_ROM_LOAD_FAIL: return "Error occured during ROM loading"; + case CART_LOAD_ERR_SAVE_LOAD_FAIL: return "Error occured during save loading"; + case CART_LOAD_ERR_BOOT_MODE_FAIL: return "Error occured during boot mode setting"; case CART_LOAD_ERR_64DD_PRESENT: return "64DD accessory is connected to the N64"; case CART_LOAD_ERR_64DD_IPL_NOT_FOUND: return "Required 64DD IPL file was not found"; case CART_LOAD_ERR_64DD_IPL_LOAD_FAIL: return "Error occurred during 64DD IPL loading"; @@ -125,6 +126,17 @@ cart_load_err_t cart_load_n64_rom_and_save (menu_t *menu, flashcart_progress_cal return CART_LOAD_ERR_SAVE_LOAD_FAIL; } + if (menu->settings.rom_fast_reboot_enabled) { + if (!flashcart_has_feature(FLASHCART_FEATURE_ROM_REBOOT_FAST)) { + return CART_LOAD_ERR_FUNCTION_NOT_SUPPORTED; + } + menu->flashcart_err = flashcart_set_next_boot_mode(FLASHCART_REBOOT_MODE_ROM); + if (menu->flashcart_err != FLASHCART_OK) { + path_free(path); + return CART_LOAD_ERR_BOOT_MODE_FAIL; + } + } + path_free(path); return CART_LOAD_OK; diff --git a/src/menu/cart_load.h b/src/menu/cart_load.h index 49f4194d..ec37cd0f 100644 --- a/src/menu/cart_load.h +++ b/src/menu/cart_load.h @@ -20,6 +20,8 @@ typedef enum { CART_LOAD_ERR_ROM_LOAD_FAIL, /** @brief Failed to load the save correctly. */ CART_LOAD_ERR_SAVE_LOAD_FAIL, + /** @brief Failed to set the next boot mode. */ + CART_LOAD_ERR_BOOT_MODE_FAIL, /** @brief The 64DD is available for use. */ CART_LOAD_ERR_64DD_PRESENT, /** @brief Failed to find the 64DD IPL (BIOS) file. */ diff --git a/src/menu/views/settings_editor.c b/src/menu/views/settings_editor.c index c861ad71..4779cf28 100644 --- a/src/menu/views/settings_editor.c +++ b/src/menu/views/settings_editor.c @@ -29,6 +29,11 @@ static void set_soundfx_enabled_type (menu_t *menu, void *arg) { settings_save(&menu->settings); } +static void set_use_rom_fast_reboot_enabled_type (menu_t *menu, void *arg) { + menu->settings.rom_fast_reboot_enabled = (bool)(uintptr_t)(arg); + settings_save(&menu->settings); +} + #ifdef BETA_SETTINGS static void set_pal60_type (menu_t *menu, void *arg) { menu->settings.pal60_enabled = (bool)(uintptr_t)(arg); @@ -74,6 +79,12 @@ static component_context_menu_t set_use_saves_folder_type_context_menu = { .list COMPONENT_CONTEXT_MENU_LIST_END, }}; +static component_context_menu_t set_use_rom_fast_reboot_context_menu = { .list = { + {.text = "On", .action = set_use_rom_fast_reboot_enabled_type, .arg = (void *)(uintptr_t)(true) }, + {.text = "Off", .action = set_use_rom_fast_reboot_enabled_type, .arg = (void *)(uintptr_t)(false) }, + COMPONENT_CONTEXT_MENU_LIST_END, +}}; + #ifdef BETA_SETTINGS static component_context_menu_t set_pal60_type_context_menu = { .list = { {.text = "On", .action = set_pal60_type, .arg = (void *)(uintptr_t)(true) }, @@ -104,6 +115,7 @@ static component_context_menu_t options_context_menu = { .list = { { .text = "Show Hidden Files", .submenu = &set_protected_entries_type_context_menu }, { .text = "Sound Effects", .submenu = &set_soundfx_enabled_type_context_menu }, { .text = "Use Saves Folder", .submenu = &set_use_saves_folder_type_context_menu }, + { .text = "Fast Reboot ROM", .submenu = &set_use_rom_fast_reboot_context_menu }, #ifdef BETA_SETTINGS { .text = "PAL60 Mode", .submenu = &set_pal60_type_context_menu }, { .text = "PAL60 Compatibility", .submenu = &set_pal60_mod_compatibility_type_context_menu }, @@ -148,9 +160,9 @@ static void draw (menu_t *menu, surface_t *d) { "\n\n" " Default Directory : %s\n\n" " Autoload ROM : %s\n" - " Fast Reboot ROM : %s\n" " ROM Loading Bar : %s\n\n" "To change the following menu settings, press 'A':\n" + " Fast Reboot ROM : %s\n" " Show Hidden Files : %s\n" " Use Saves folder : %s\n" " Sound Effects : %s\n" @@ -166,8 +178,8 @@ static void draw (menu_t *menu, surface_t *d) { , menu->settings.default_directory, format_switch(menu->settings.rom_autoload_enabled), - format_switch(menu->settings.rom_fast_reboot_enabled), format_switch(menu->settings.loading_progress_bar_enabled), + format_switch(menu->settings.rom_fast_reboot_enabled), format_switch(menu->settings.show_protected_entries), format_switch(menu->settings.use_saves_folder), format_switch(menu->settings.soundfx_enabled)