[develop] Add Fast Reboot mode for ROMs (#215)

<!--- Provide a general summary of your changes in the Title above -->

## Description
<!--- Describe your changes in detail -->
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
<!--- What does this sample do? What problem does it solve? -->
<!--- If it fixes/closes/resolves an open issue, please link to the
issue here -->
#75 

## How Has This Been Tested?
<!-- (if applicable) -->
<!--- Please describe in detail how you tested your sample/changes. -->
<!--- Include details of your testing environment, and the tests you ran
to -->
<!--- see how your change affects other areas of the code, etc. -->
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
<!-- (if appropriate): -->

## Types of changes
<!--- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [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:
<!--- Go over all the following points, and put an `x` in all the boxes
that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
- [ ] 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.

<!--- It would be nice if you could sign off your contribution by
replacing the name with your GitHub user name and GitHub email contact.
-->
Signed-off-by: GITHUB_USER <GITHUB_USER_EMAIL>
This commit is contained in:
Robin Jones 2025-03-10 19:44:29 +00:00 committed by GitHub
parent 9b69b84f1d
commit 72b7c9491c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 92 additions and 6 deletions

View File

@ -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**

View File

@ -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.

View File

@ -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.

View File

@ -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,
};
/**

View File

@ -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,
};

View File

@ -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,
};

View File

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

View File

@ -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__ */

View File

@ -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,
};

View File

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

View File

@ -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. */

View File

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