diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b7da2151..7f88be12 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -113,7 +113,7 @@ jobs: - uses: actions/checkout@v4 - name: Run Doxygen - uses: mattnotmitt/doxygen-action@1.9.5 + uses: mattnotmitt/doxygen-action@v1 with: doxyfile-path: './Doxyfile' diff --git a/README.md b/README.md index de3d030c..8fae66a3 100644 --- a/README.md +++ b/README.md @@ -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. @@ -60,7 +64,7 @@ These must be `PNG` files that use the following dimensions: * Japanese N64 GamePak boxart sprites: 112x158 * 64DD boxart sprites: 129x112 -They will be loaded by directories using each character of the full 4 character Game Code (as identified in the menus ROM information). +They will be loaded by directories using each character (case-sensitive) of the full 4 character Game Code (as identified in the menu ROM information). i.e. for GoldenEye NTSC USA (NGEE), this would be `sd:/menu/boxart/N/G/E/E/boxart_front.png`. i.e. for GoldenEye PAL (NGEP), this would be `sd:/menu/boxart/N/G/E/P/boxart_front.png`. diff --git a/libdragon b/libdragon index 9dd99415..e93802ae 160000 --- a/libdragon +++ b/libdragon @@ -1 +1 @@ -Subproject commit 9dd994151ae3f3709f1f80224e6b654aac8be6b4 +Subproject commit e93802aec7e7839710281824ce2e9e4689b3a01d diff --git a/src/flashcart/64drive/64drive.c b/src/flashcart/64drive/64drive.c index 363b3bcf..5b4b5d22 100644 --- a/src/flashcart/64drive/64drive.c +++ b/src/flashcart/64drive/64drive.c @@ -77,6 +77,7 @@ static bool d64_has_feature (flashcart_features_t feature) { case FLASHCART_FEATURE_USB: return true; case FLASHCART_FEATURE_AUTO_CIC: return true; case FLASHCART_FEATURE_AUTO_REGION: return true; + case FLASHCART_FEATURE_SAVE_WRITEBACK: return true; default: return false; } } diff --git a/src/flashcart/flashcart.h b/src/flashcart/flashcart.h index ade09eaa..fcbcf606 100644 --- a/src/flashcart/flashcart.h +++ b/src/flashcart/flashcart.h @@ -31,6 +31,9 @@ typedef enum { FLASHCART_FEATURE_USB, FLASHCART_FEATURE_AUTO_CIC, FLASHCART_FEATURE_AUTO_REGION, + FLASHCART_FEATURE_DIAGNOSTIC_DATA, + FLASHCART_FEATURE_BIOS_UPDATE_FROM_MENU, + FLASHCART_FEATURE_SAVE_WRITEBACK } flashcart_features_t; /** @brief Flashcart save type enumeration */ diff --git a/src/flashcart/sc64/sc64.c b/src/flashcart/sc64/sc64.c index 927843a3..605ae419 100644 --- a/src/flashcart/sc64/sc64.c +++ b/src/flashcart/sc64/sc64.c @@ -256,6 +256,8 @@ static bool sc64_has_feature (flashcart_features_t feature) { case FLASHCART_FEATURE_USB: return true; case FLASHCART_FEATURE_AUTO_CIC: return true; case FLASHCART_FEATURE_AUTO_REGION: return true; + case FLASHCART_FEATURE_DIAGNOSTIC_DATA: return true; + case FLASHCART_FEATURE_SAVE_WRITEBACK: return true; default: return false; } } diff --git a/src/libs/miniz b/src/libs/miniz index 1ff82be7..35528ad7 160000 --- a/src/libs/miniz +++ b/src/libs/miniz @@ -1 +1 @@ -Subproject commit 1ff82be7d67f5c2f8b5497f538eea247861e0717 +Subproject commit 35528ad769143b9ed38a95a22d460b963e39f278 diff --git a/src/menu/components.h b/src/menu/components.h index 67fde2d3..6d31a3d3 100644 --- a/src/menu/components.h +++ b/src/menu/components.h @@ -73,8 +73,8 @@ void component_background_draw (void); void component_file_list_draw (entry_t *list, int entries, int selected); typedef struct component_context_menu { - int count; - int selected; + int row_count; + int row_selected; bool hide_pending; struct component_context_menu *parent; struct component_context_menu *submenu; diff --git a/src/menu/components/common.c b/src/menu/components/common.c index d0fce75f..29a97ada 100644 --- a/src/menu/components/common.c +++ b/src/menu/components/common.c @@ -151,7 +151,7 @@ void component_main_text_draw (rdpq_align_t align, rdpq_valign_t valign, char *f .height = LAYOUT_ACTIONS_SEPARATOR_Y - OVERSCAN_HEIGHT - (TEXT_MARGIN_VERTICAL * 2), .align = align, .valign = valign, - .wrap = WRAP_ELLIPSES, + .wrap = WRAP_WORD, .line_spacing = TEXT_LINE_SPACING_ADJUST, }, FNT_DEFAULT, diff --git a/src/menu/components/context_menu.c b/src/menu/components/context_menu.c index c4d0364a..abf1947e 100644 --- a/src/menu/components/context_menu.c +++ b/src/menu/components/context_menu.c @@ -13,22 +13,22 @@ static component_context_menu_t *get_current_submenu (component_context_menu_t * void component_context_menu_init (component_context_menu_t *cm) { - cm->selected = -1; - cm->count = 0; + cm->row_selected = -1; + cm->row_count = 0; cm->hide_pending = false; cm->parent = NULL; for (int i = 0; (cm->list[i].text) != NULL; i++) { - cm->count += 1; + cm->row_count += 1; } } void component_context_menu_show (component_context_menu_t *cm) { - cm->selected = 0; + cm->row_selected = 0; cm->submenu = NULL; } bool component_context_menu_process (menu_t *menu, component_context_menu_t *cm) { - if (!cm || (cm->selected < 0)) { + if (!cm || (cm->row_selected < 0)) { return false; } @@ -44,26 +44,26 @@ bool component_context_menu_process (menu_t *menu, component_context_menu_t *cm) } sound_play_effect(SFX_EXIT); } else if (menu->actions.enter) { - if (cm->list[cm->selected].submenu) { - cm->submenu = cm->list[cm->selected].submenu; + if (cm->list[cm->row_selected].submenu) { + cm->submenu = cm->list[cm->row_selected].submenu; component_context_menu_init(cm->submenu); - cm->submenu->selected = 0; + cm->submenu->row_selected = 0; cm->submenu->parent = cm; - } else if (cm->list[cm->selected].action) { - cm->list[cm->selected].action(menu, cm->list[cm->selected].arg); + } else if (cm->list[cm->row_selected].action) { + cm->list[cm->row_selected].action(menu, cm->list[cm->row_selected].arg); top->hide_pending = true; } sound_play_effect(SFX_ENTER); } else if (menu->actions.go_up) { - cm->selected -= 1; - if (cm->selected < 0) { - cm->selected = 0; + cm->row_selected -= 1; + if (cm->row_selected < 0) { + cm->row_selected = 0; } sound_play_effect(SFX_CURSOR); } else if (menu->actions.go_down) { - cm->selected += 1; - if (cm->selected >= cm->count) { - cm->selected = (cm->count - 1); + cm->row_selected += 1; + if (cm->row_selected >= cm->row_count) { + cm->row_selected = (cm->row_count - 1); } sound_play_effect(SFX_CURSOR); } @@ -72,7 +72,7 @@ bool component_context_menu_process (menu_t *menu, component_context_menu_t *cm) } void component_context_menu_draw (component_context_menu_t *cm) { - if (!cm || (cm->selected < 0)) { + if (!cm || (cm->row_selected < 0)) { return; } @@ -92,7 +92,7 @@ void component_context_menu_draw (component_context_menu_t *cm) { NULL ); - for (int i = 0; i < cm->count; i++) { + for (int i = 0; i < cm->row_count; i++) { const char *text = cm->list[i].text; rdpq_paragraph_builder_span(text, strlen(text)); if (cm->list[i + 1].text != NULL) { @@ -110,7 +110,7 @@ void component_context_menu_draw (component_context_menu_t *cm) { int highlight_x0 = DISPLAY_CENTER_X - (width / 2); int highlight_x1 = DISPLAY_CENTER_X + (width / 2); int highlight_height = (layout->bbox.y1 - layout->bbox.y0) / layout->nlines; - int highlight_y = VISIBLE_AREA_Y0 + layout->bbox.y0 + ((cm->selected) * highlight_height); + int highlight_y = VISIBLE_AREA_Y0 + layout->bbox.y0 + ((cm->row_selected) * highlight_height); component_box_draw( highlight_x0, @@ -126,6 +126,6 @@ void component_context_menu_draw (component_context_menu_t *cm) { if (top->hide_pending) { top->hide_pending = false; - top->selected = -1; + top->row_selected = -1; } } diff --git a/src/menu/menu_state.h b/src/menu/menu_state.h index 0d6aa459..eaeb83ec 100644 --- a/src/menu/menu_state.h +++ b/src/menu/menu_state.h @@ -104,6 +104,12 @@ typedef struct { path_t *disk_path; disk_info_t disk_info; } load; + + struct { + bool rom_file; + bool disk_file; + bool emulator_file; + } boot_pending; } menu_t; diff --git a/src/menu/settings.c b/src/menu/settings.c index 0b372531..5361f0a6 100644 --- a/src/menu/settings.c +++ b/src/menu/settings.c @@ -14,7 +14,10 @@ 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, .rumble_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); diff --git a/src/menu/settings.h b/src/menu/settings.h index e9931b05..471879eb 100644 --- a/src/menu/settings.h +++ b/src/menu/settings.h @@ -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 diff --git a/src/menu/sound.c b/src/menu/sound.c index c439c4f9..ea088447 100644 --- a/src/menu/sound.c +++ b/src/menu/sound.c @@ -19,7 +19,10 @@ static bool sfx_enabled = false; static void sound_reconfigure (int frequency) { if ((frequency > 0) && (audio_get_frequency() != frequency)) { - sound_deinit(); + if (sound_initialized) { + mixer_close(); + audio_close(); + } audio_init(frequency, NUM_BUFFERS); mixer_init(NUM_CHANNELS); mp3player_mixer_init(); @@ -97,9 +100,7 @@ void sound_deinit (void) { } void sound_poll (void) { - if (sound_initialized && audio_can_write()) { - short *audio_buffer = audio_write_begin(); - mixer_poll(audio_buffer, audio_get_buffer_length()); - audio_write_end(); + if (sound_initialized) { + mixer_try_play(); } } diff --git a/src/menu/views/credits.c b/src/menu/views/credits.c index fb068e6b..1889232a 100644 --- a/src/menu/views/credits.c +++ b/src/menu/views/credits.c @@ -12,8 +12,8 @@ static void process (menu_t *menu) { if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } } diff --git a/src/menu/views/file_info.c b/src/menu/views/file_info.c index 496c07f4..9d45574b 100644 --- a/src/menu/views/file_info.c +++ b/src/menu/views/file_info.c @@ -50,8 +50,8 @@ static char *format_file_type (char *name, bool is_directory) { static void process (menu_t *menu) { if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } } @@ -84,7 +84,7 @@ static void draw (menu_t *menu, surface_t *d) { S_ISDIR(st.st_mode) ? "Directory" : "File", st.st_mode & S_IWUSR ? "" : "(Read only)", format_file_type(menu->browser.entry->name, S_ISDIR(st.st_mode)), - ctime(&st.st_mtim.tv_sec) + ctime(&st.st_mtime) ); component_actions_bar_text_draw( diff --git a/src/menu/views/flashcart_info.c b/src/menu/views/flashcart_info.c index fa1f6eb5..635ef2ca 100644 --- a/src/menu/views/flashcart_info.c +++ b/src/menu/views/flashcart_info.c @@ -1,15 +1,35 @@ #include "views.h" #include "../sound.h" +#include static inline const char *format_boolean_type (bool bool_value) { return bool_value ? "Supported" : "Unsupported"; } +static const char *format_cart_type () { + switch (cart_type) { + case CART_CI: + return "64drive"; + + case CART_EDX: + return "Series X EverDrive-64"; + + case CART_ED: + return "Series V EverDrive-64"; + + case CART_SC: + return "SummerCart64"; + + default: // Probably emulator + return "Emulator?"; + } +} + static void process (menu_t *menu) { if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } } @@ -39,24 +59,25 @@ static void draw (menu_t *menu, surface_t *d) { " Virtual 64DD: %s.\n" " Real Time Clock: %s.\n" " USB Debugging: %s.\n" - " CIC Detection: %s.\n" + " Automatic CIC: %s.\n" " Region Detection: %s.\n" + " Save Writeback: %s.\n" + " Update from menu: %s.\n" "\n\n", - "SummerCart64", - "V?.?.?", - format_boolean_type(true), - format_boolean_type(true), - format_boolean_type(true), - format_boolean_type(true), - format_boolean_type(true) + format_cart_type(), + "Not Available", // TODO get cart firmware version(s). + format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_64DD)), + format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_RTC)), + format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_USB)), + format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_AUTO_CIC)), + format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_AUTO_REGION)), + format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_SAVE_WRITEBACK)), + format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_BIOS_UPDATE_FROM_MENU)) + + //TODO: display the battery and temperature information (if available). + //format_diagnostic_data(flashcart_has_feature(FLASHCART_FEATURE_DIAGNOSTIC_DATA)) ); - // FIXME: Display: - // * cart_type - // * Firmware version - // * supported features (flashcart_features_t) - - component_actions_bar_text_draw( ALIGN_LEFT, VALIGN_TOP, "\n" diff --git a/src/menu/views/load_disk.c b/src/menu/views/load_disk.c index f4140781..781ebe27 100644 --- a/src/menu/views/load_disk.c +++ b/src/menu/views/load_disk.c @@ -5,8 +5,7 @@ #include "views.h" -static bool load_pending; -static bool load_rom; +static bool load_disk_with_rom; static component_boxart_t *boxart; @@ -31,15 +30,15 @@ static char *format_disk_region (disk_region_t region) { static void process (menu_t *menu) { if (menu->actions.enter) { - load_pending = true; - load_rom = false; + menu->boot_pending.disk_file = true; + load_disk_with_rom = false; } else if (menu->actions.options && menu->load.rom_path) { - load_pending = true; - load_rom = true; + menu->boot_pending.disk_file = true; + load_disk_with_rom = true; sound_play_effect(SFX_SETTING); } else if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } } @@ -48,7 +47,7 @@ static void draw (menu_t *menu, surface_t *d) { component_background_draw(); - if (load_pending) { + if (menu->boot_pending.disk_file) { component_loader_draw(0.0f); } else { component_layout_draw(); @@ -119,7 +118,7 @@ static void draw_progress (float progress) { static void load (menu_t *menu) { cart_load_err_t err; - if (menu->load.rom_path && load_rom) { + if (menu->load.rom_path && load_disk_with_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)); @@ -135,7 +134,7 @@ static void load (menu_t *menu) { menu->next_mode = MENU_MODE_BOOT; - if (load_rom) { + if (load_disk_with_rom) { menu->boot_params->device_type = BOOT_DEVICE_TYPE_ROM; menu->boot_params->detect_cic_seed = rom_info_get_cic_seed(&menu->load.rom_info, &menu->boot_params->cic_seed); switch (rom_info_get_tv_type(&menu->load.rom_info)) { @@ -163,7 +162,7 @@ void view_load_disk_init (menu_t *menu) { menu->load.disk_path = NULL; } - load_pending = false; + menu->boot_pending.disk_file = false; menu->load.disk_path = path_clone_push(menu->browser.directory, menu->browser.entry->name); @@ -180,8 +179,8 @@ void view_load_disk_display (menu_t *menu, surface_t *display) { draw(menu, display); - if (load_pending) { - load_pending = false; + if (menu->boot_pending.disk_file) { + menu->boot_pending.disk_file = false; load(menu); } diff --git a/src/menu/views/load_emulator.c b/src/menu/views/load_emulator.c index 589a6a59..3a131722 100644 --- a/src/menu/views/load_emulator.c +++ b/src/menu/views/load_emulator.c @@ -11,7 +11,6 @@ static const char *emu_gameboy_rom_extensions[] = { "gb", NULL }; static const char *emu_gameboy_color_rom_extensions[] = { "gbc", NULL }; static const char *emu_sega_8bit_rom_extensions[] = { "sms", "gg", "sg", NULL }; -static bool load_pending; static cart_load_emu_type_t emu_type; static char *format_emulator_name (cart_load_emu_type_t emulator_info) { @@ -34,10 +33,10 @@ static char *format_emulator_name (cart_load_emu_type_t emulator_info) { static void process (menu_t *menu) { if (menu->actions.enter) { - load_pending = true; + menu->boot_pending.emulator_file = true; } else if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } } @@ -46,7 +45,7 @@ static void draw (menu_t *menu, surface_t *d) { component_background_draw(); - if (load_pending) { + if (menu->boot_pending.emulator_file) { component_loader_draw(0.0f); } else { component_layout_draw(); @@ -107,7 +106,7 @@ static void load (menu_t *menu) { void view_load_emulator_init (menu_t *menu) { - load_pending = false; + menu->boot_pending.emulator_file = false; path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name); @@ -133,8 +132,8 @@ void view_load_emulator_display (menu_t *menu, surface_t *display) { draw(menu, display); - if (load_pending) { - load_pending = false; + if (menu->boot_pending.emulator_file) { + menu->boot_pending.emulator_file = false; load(menu); } } diff --git a/src/menu/views/load_rom.c b/src/menu/views/load_rom.c index 8ddf35b9..228c6956 100644 --- a/src/menu/views/load_rom.c +++ b/src/menu/views/load_rom.c @@ -3,12 +3,12 @@ #include "boot/boot.h" #include "../sound.h" #include "views.h" +#include +#include "utils/fs.h" static bool show_extra_info_message = false; -static bool load_pending; static component_boxart_t *boxart; - static char *convert_error_message (rom_err_t err) { switch (err) { case ROM_ERR_LOAD_IO: return "I/O error during loading ROM information and/or options"; @@ -153,6 +153,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) }, @@ -195,6 +206,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, }}; @@ -204,10 +216,10 @@ static void process (menu_t *menu) { } if (menu->actions.enter) { - load_pending = true; + menu->boot_pending.rom_file = true; } else if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } else if (menu->actions.options) { component_context_menu_show(&options_context_menu); sound_play_effect(SFX_SETTING); @@ -226,7 +238,7 @@ static void draw (menu_t *menu, surface_t *d) { component_background_draw(); - if (load_pending) { + if (menu->boot_pending.rom_file) { component_loader_draw(0.0f); } else { component_layout_draw(); @@ -354,14 +366,14 @@ static void deinit (void) { void view_load_rom_init (menu_t *menu) { - load_pending = 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); @@ -370,9 +382,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) { @@ -380,8 +393,8 @@ void view_load_rom_display (menu_t *menu, surface_t *display) { draw(menu, display); - if (load_pending) { - load_pending = false; + if (menu->boot_pending.rom_file) { + menu->boot_pending.rom_file = false; load(menu); } diff --git a/src/menu/views/music_player.c b/src/menu/views/music_player.c index 4de00756..c540bfab 100644 --- a/src/menu/views/music_player.c +++ b/src/menu/views/music_player.c @@ -41,8 +41,8 @@ static void process (menu_t *menu) { if (err != MP3PLAYER_OK) { menu_show_error(menu, convert_error_message(err)); } else if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } else if (menu->actions.enter) { err = mp3player_toggle(); if (err != MP3PLAYER_OK) { diff --git a/src/menu/views/rtc.c b/src/menu/views/rtc.c index da595f6f..6be481a3 100644 --- a/src/menu/views/rtc.c +++ b/src/menu/views/rtc.c @@ -18,8 +18,8 @@ static void process (menu_t *menu) { if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } } diff --git a/src/menu/views/settings_editor.c b/src/menu/views/settings_editor.c index 41d96407..068b4675 100644 --- a/src/menu/views/settings_editor.c +++ b/src/menu/views/settings_editor.c @@ -114,8 +114,8 @@ static void process (menu_t *menu) { component_context_menu_show(&options_context_menu); sound_play_effect(SFX_SETTING); } else if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } } @@ -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" @@ -145,9 +146,11 @@ static void draw (menu_t *menu, surface_t *d) { " Background Music : %s\n" " Rumble Feedback : %s\n" #endif - "Note: Certain settings have the following caveats:\n\n" - "* Requires a flashcart reboot.\n", + "\n\n" + "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), diff --git a/src/menu/views/startup.c b/src/menu/views/startup.c index 118d20dc..c12a9045 100644 --- a/src/menu/views/startup.c +++ b/src/menu/views/startup.c @@ -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; } diff --git a/src/menu/views/system_info.c b/src/menu/views/system_info.c index 74ed4cbd..2dea476d 100644 --- a/src/menu/views/system_info.c +++ b/src/menu/views/system_info.c @@ -28,8 +28,8 @@ static void process (menu_t *menu) { } if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } } diff --git a/src/menu/views/text_viewer.c b/src/menu/views/text_viewer.c index cf8b505f..0339ba37 100644 --- a/src/menu/views/text_viewer.c +++ b/src/menu/views/text_viewer.c @@ -55,8 +55,8 @@ static void perform_vertical_scroll (int lines) { static void process (menu_t *menu) { if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } else if (text) { if (menu->actions.go_up) { perform_vertical_scroll(menu->actions.go_fast ? -10 : -1);