N64 Rom autoload (#150)

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

## Description
<!--- Describe your changes in detail -->
Allows the ability to autoload a specified ROM instead of the menu,
taking into account the ROM database.
If enabled, you can currently fallback to the menu by holding joypad
start on console reset.


## 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 -->
This is a better implementation of #140.

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

## 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 is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

- **New Features**
- Introduced ROM autoloading functionality, allowing users to enable
automatic loading of ROMs with specified paths and filenames.
- Added a settings option for managing ROM autoload preferences in the
menu.

- **User Interface Enhancements**
- Updated settings menu to display the state of the "Autoload ROM"
setting.
  - Improved context menus for toggling various settings.

- **Bug Fixes**
- Enhanced memory management by ensuring proper resource deallocation
for settings.

- **Documentation**
- Added documentation for new functions and settings related to ROM
autoloading.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Robin Jones 2024-11-05 09:27:44 +00:00 committed by GitHub
parent 4eca91798c
commit 36647ebdec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 71 additions and 10 deletions

View File

@ -26,6 +26,7 @@ An open source menu for N64 flashcarts.
* Real Time Clock support.
* Music playback (MP3).
* Menu sound effects.
* N64 ROM autoload.
## Documentation
@ -49,6 +50,9 @@ An open source menu for N64 flashcarts.
## Experimental features
These features are subject to change:
### N64 ROM autoload
To use the autoload function, while on the `N64 ROM information` display, press the `R` button on your joypad and select the `Set ROM to autoload` option. When you restart the console, it will now only load the selected ROM rather than the menu.
NOTE: to return to the menu, hold joypad `start` button whilst powering on the console.
### GamePak sprites
To use N64 `GamePak` sprites, place `PNG` files within the `sd:/menu/boxart/` folder.

View File

@ -14,6 +14,9 @@ static settings_t init = {
.default_directory = "/",
.use_saves_folder = true,
.sound_enabled = true,
.rom_autoload_enabled = false,
.rom_autoload_path = "",
.rom_autoload_filename = "",
/* Beta feature flags (should always init to off) */
.bgm_enabled = false,
@ -41,6 +44,10 @@ void settings_load (settings_t *settings) {
settings->use_saves_folder = mini_get_bool(ini, "menu", "use_saves_folder", init.use_saves_folder);
settings->sound_enabled = mini_get_bool(ini, "menu", "sound_enabled", init.sound_enabled);
settings->rom_autoload_enabled = mini_get_bool(ini, "menu", "autoload_rom_enabled", init.rom_autoload_enabled);
settings->rom_autoload_path = strdup(mini_get_string(ini, "autoload", "rom_path", init.rom_autoload_path));
settings->rom_autoload_filename = strdup(mini_get_string(ini, "autoload", "rom_filename", init.rom_autoload_filename));
/* Beta feature flags, they might not be in the file */
settings->bgm_enabled = mini_get_bool(ini, "menu_beta_flag", "bgm_enabled", init.bgm_enabled);
settings->rumble_enabled = mini_get_bool(ini, "menu_beta_flag", "rumble_enabled", init.rumble_enabled);
@ -56,6 +63,9 @@ void settings_save (settings_t *settings) {
mini_set_string(ini, "menu", "default_directory", settings->default_directory);
mini_set_bool(ini, "menu", "use_saves_folder", settings->use_saves_folder);
mini_set_bool(ini, "menu", "sound_enabled", settings->sound_enabled);
mini_set_bool(ini, "menu", "autoload_rom_enabled", settings->rom_autoload_enabled);
mini_set_string(ini, "autoload", "rom_path", settings->rom_autoload_path);
mini_set_string(ini, "autoload", "rom_filename", settings->rom_autoload_filename);
/* Beta feature flags, they should not save until production ready! */
// mini_set_bool(ini, "menu_beta_flag", "bgm_enabled", settings->bgm_enabled);

View File

@ -30,6 +30,16 @@ typedef struct {
/** @brief Enable rumble feedback */
bool rumble_enabled;
/** @brief Enable the ability to bypass the menu and instantly load a ROM */
bool rom_autoload_enabled;
/** @brief A path to the autoloaded ROM */
char *rom_autoload_path;
/** @brief A filename of the autoloaded ROM */
char *rom_autoload_filename;
} settings_t;
@ -40,5 +50,4 @@ void settings_load (settings_t *settings);
/** @brief The settings to save */
void settings_save (settings_t *settings);
#endif

View File

@ -3,6 +3,8 @@
#include "boot/boot.h"
#include "../sound.h"
#include "views.h"
#include <string.h>
#include "utils/fs.h"
static bool show_extra_info_message = false;
static component_boxart_t *boxart;
@ -143,6 +145,17 @@ static void set_tv_type (menu_t *menu, void *arg) {
menu->browser.reload = true;
}
static void set_autoload_type (menu_t *menu, void *arg) {
free(menu->settings.rom_autoload_path);
menu->settings.rom_autoload_path = strdup(strip_fs_prefix(path_get(menu->browser.directory)));
free(menu->settings.rom_autoload_filename);
menu->settings.rom_autoload_filename = strdup(menu->browser.entry->name);
// FIXME: add a confirmation box here! (press start on reboot)
menu->settings.rom_autoload_enabled = true;
settings_save(&menu->settings);
menu->browser.reload = true;
}
static component_context_menu_t set_cic_type_context_menu = { .list = {
{.text = "Automatic", .action = set_cic_type, .arg = (void *) (ROM_CIC_TYPE_AUTOMATIC) },
{.text = "CIC-6101", .action = set_cic_type, .arg = (void *) (ROM_CIC_TYPE_6101) },
@ -185,6 +198,7 @@ static component_context_menu_t options_context_menu = { .list = {
{ .text = "Set CIC Type", .submenu = &set_cic_type_context_menu },
{ .text = "Set Save Type", .submenu = &set_save_type_context_menu },
{ .text = "Set TV Type", .submenu = &set_tv_type_context_menu },
{ .text = "Set ROM to autoload", .action = set_autoload_type },
COMPONENT_CONTEXT_MENU_LIST_END,
}};
@ -340,14 +354,14 @@ static void deinit (void) {
void view_load_rom_init (menu_t *menu) {
menu->boot_pending.rom_file = false;
if (!menu->settings.rom_autoload_enabled) {
if (menu->load.rom_path) {
path_free(menu->load.rom_path);
}
if (menu->load.rom_path) {
path_free(menu->load.rom_path);
menu->load.rom_path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
}
menu->load.rom_path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
rom_err_t err = rom_info_load(menu->load.rom_path, &menu->load.rom_info);
if (err != ROM_OK) {
path_free(menu->load.rom_path);
@ -356,9 +370,10 @@ void view_load_rom_init (menu_t *menu) {
return;
}
boxart = component_boxart_init(menu->storage_prefix, menu->load.rom_info.game_code, IMAGE_BOXART_FRONT);
component_context_menu_init(&options_context_menu);
if (!menu->settings.rom_autoload_enabled) {
boxart = component_boxart_init(menu->storage_prefix, menu->load.rom_info.game_code, IMAGE_BOXART_FRONT);
component_context_menu_init(&options_context_menu);
}
}
void view_load_rom_display (menu_t *menu, surface_t *display) {

View File

@ -136,6 +136,7 @@ static void draw (menu_t *menu, surface_t *d) {
ALIGN_LEFT, VALIGN_TOP,
"\n\n"
" Default Directory : %s\n\n"
" Autoload ROM : %s\n"
"To change the following menu settings, press 'A':\n"
"* PAL60 Mode : %s\n"
" Show Hidden Files : %s\n"
@ -149,6 +150,7 @@ static void draw (menu_t *menu, surface_t *d) {
"Note: Certain settings have the following caveats:\n"
"* Requires rebooting the N64 Console.\n",
menu->settings.default_directory,
format_switch(menu->settings.rom_autoload_enabled),
format_switch(menu->settings.pal60_enabled),
format_switch(menu->settings.show_protected_entries),
format_switch(menu->settings.use_saves_folder),

View File

@ -9,6 +9,27 @@ static void draw (menu_t *menu, surface_t *d) {
void view_startup_init (menu_t *menu) {
// FIXME: rather than use a controller button, would it be better to use the cart button?
JOYPAD_PORT_FOREACH (port) {
joypad_poll();
joypad_buttons_t b_held = joypad_get_buttons_held(port);
if (menu->settings.rom_autoload_enabled && b_held.start) {
menu->settings.rom_autoload_enabled = false;
menu->settings.rom_autoload_path = "";
menu->settings.rom_autoload_filename = "";
settings_save(&menu->settings);
}
}
if (menu->settings.rom_autoload_enabled) {
menu->browser.directory = path_init(menu->storage_prefix, menu->settings.rom_autoload_path);
menu->load.rom_path = path_clone_push(menu->browser.directory, menu->settings.rom_autoload_filename);
menu->boot_pending.rom_file = true;
menu->next_mode = MENU_MODE_LOAD_ROM;
return;
}
menu->next_mode = MENU_MODE_BROWSER;
}