Merge branch 'develop' into improve-rom-info

This commit is contained in:
Robin Jones 2024-11-05 09:34:48 +00:00 committed by GitHub
commit 2e8fdc2e33
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 186 additions and 94 deletions

View File

@ -113,7 +113,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Run Doxygen - name: Run Doxygen
uses: mattnotmitt/doxygen-action@1.9.5 uses: mattnotmitt/doxygen-action@v1
with: with:
doxyfile-path: './Doxyfile' doxyfile-path: './Doxyfile'

View File

@ -26,6 +26,7 @@ An open source menu for N64 flashcarts.
* Real Time Clock support. * Real Time Clock support.
* Music playback (MP3). * Music playback (MP3).
* Menu sound effects. * Menu sound effects.
* N64 ROM autoload.
## Documentation ## Documentation
@ -49,6 +50,9 @@ An open source menu for N64 flashcarts.
## Experimental features ## Experimental features
These features are subject to change: 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 ### GamePak sprites
To use N64 `GamePak` sprites, place `PNG` files within the `sd:/menu/boxart/` folder. 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 * Japanese N64 GamePak boxart sprites: 112x158
* 64DD boxart sprites: 129x112 * 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 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`. i.e. for GoldenEye PAL (NGEP), this would be `sd:/menu/boxart/N/G/E/P/boxart_front.png`.

@ -1 +1 @@
Subproject commit 9dd994151ae3f3709f1f80224e6b654aac8be6b4 Subproject commit e93802aec7e7839710281824ce2e9e4689b3a01d

View File

@ -77,6 +77,7 @@ static bool d64_has_feature (flashcart_features_t feature) {
case FLASHCART_FEATURE_USB: return true; case FLASHCART_FEATURE_USB: return true;
case FLASHCART_FEATURE_AUTO_CIC: return true; case FLASHCART_FEATURE_AUTO_CIC: return true;
case FLASHCART_FEATURE_AUTO_REGION: return true; case FLASHCART_FEATURE_AUTO_REGION: return true;
case FLASHCART_FEATURE_SAVE_WRITEBACK: return true;
default: return false; default: return false;
} }
} }

View File

@ -31,6 +31,9 @@ typedef enum {
FLASHCART_FEATURE_USB, FLASHCART_FEATURE_USB,
FLASHCART_FEATURE_AUTO_CIC, FLASHCART_FEATURE_AUTO_CIC,
FLASHCART_FEATURE_AUTO_REGION, FLASHCART_FEATURE_AUTO_REGION,
FLASHCART_FEATURE_DIAGNOSTIC_DATA,
FLASHCART_FEATURE_BIOS_UPDATE_FROM_MENU,
FLASHCART_FEATURE_SAVE_WRITEBACK
} flashcart_features_t; } flashcart_features_t;
/** @brief Flashcart save type enumeration */ /** @brief Flashcart save type enumeration */

View File

@ -256,6 +256,8 @@ static bool sc64_has_feature (flashcart_features_t feature) {
case FLASHCART_FEATURE_USB: return true; case FLASHCART_FEATURE_USB: return true;
case FLASHCART_FEATURE_AUTO_CIC: return true; case FLASHCART_FEATURE_AUTO_CIC: return true;
case FLASHCART_FEATURE_AUTO_REGION: 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; default: return false;
} }
} }

2
src/libs/miniz vendored

@ -1 +1 @@
Subproject commit 1ff82be7d67f5c2f8b5497f538eea247861e0717 Subproject commit 35528ad769143b9ed38a95a22d460b963e39f278

View File

@ -73,8 +73,8 @@ void component_background_draw (void);
void component_file_list_draw (entry_t *list, int entries, int selected); void component_file_list_draw (entry_t *list, int entries, int selected);
typedef struct component_context_menu { typedef struct component_context_menu {
int count; int row_count;
int selected; int row_selected;
bool hide_pending; bool hide_pending;
struct component_context_menu *parent; struct component_context_menu *parent;
struct component_context_menu *submenu; struct component_context_menu *submenu;

View File

@ -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), .height = LAYOUT_ACTIONS_SEPARATOR_Y - OVERSCAN_HEIGHT - (TEXT_MARGIN_VERTICAL * 2),
.align = align, .align = align,
.valign = valign, .valign = valign,
.wrap = WRAP_ELLIPSES, .wrap = WRAP_WORD,
.line_spacing = TEXT_LINE_SPACING_ADJUST, .line_spacing = TEXT_LINE_SPACING_ADJUST,
}, },
FNT_DEFAULT, FNT_DEFAULT,

View File

@ -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) { void component_context_menu_init (component_context_menu_t *cm) {
cm->selected = -1; cm->row_selected = -1;
cm->count = 0; cm->row_count = 0;
cm->hide_pending = false; cm->hide_pending = false;
cm->parent = NULL; cm->parent = NULL;
for (int i = 0; (cm->list[i].text) != NULL; i++) { 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) { void component_context_menu_show (component_context_menu_t *cm) {
cm->selected = 0; cm->row_selected = 0;
cm->submenu = NULL; cm->submenu = NULL;
} }
bool component_context_menu_process (menu_t *menu, component_context_menu_t *cm) { 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; return false;
} }
@ -44,26 +44,26 @@ bool component_context_menu_process (menu_t *menu, component_context_menu_t *cm)
} }
sound_play_effect(SFX_EXIT); sound_play_effect(SFX_EXIT);
} else if (menu->actions.enter) { } else if (menu->actions.enter) {
if (cm->list[cm->selected].submenu) { if (cm->list[cm->row_selected].submenu) {
cm->submenu = cm->list[cm->selected].submenu; cm->submenu = cm->list[cm->row_selected].submenu;
component_context_menu_init(cm->submenu); component_context_menu_init(cm->submenu);
cm->submenu->selected = 0; cm->submenu->row_selected = 0;
cm->submenu->parent = cm; cm->submenu->parent = cm;
} else if (cm->list[cm->selected].action) { } else if (cm->list[cm->row_selected].action) {
cm->list[cm->selected].action(menu, cm->list[cm->selected].arg); cm->list[cm->row_selected].action(menu, cm->list[cm->row_selected].arg);
top->hide_pending = true; top->hide_pending = true;
} }
sound_play_effect(SFX_ENTER); sound_play_effect(SFX_ENTER);
} else if (menu->actions.go_up) { } else if (menu->actions.go_up) {
cm->selected -= 1; cm->row_selected -= 1;
if (cm->selected < 0) { if (cm->row_selected < 0) {
cm->selected = 0; cm->row_selected = 0;
} }
sound_play_effect(SFX_CURSOR); sound_play_effect(SFX_CURSOR);
} else if (menu->actions.go_down) { } else if (menu->actions.go_down) {
cm->selected += 1; cm->row_selected += 1;
if (cm->selected >= cm->count) { if (cm->row_selected >= cm->row_count) {
cm->selected = (cm->count - 1); cm->row_selected = (cm->row_count - 1);
} }
sound_play_effect(SFX_CURSOR); 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) { void component_context_menu_draw (component_context_menu_t *cm) {
if (!cm || (cm->selected < 0)) { if (!cm || (cm->row_selected < 0)) {
return; return;
} }
@ -92,7 +92,7 @@ void component_context_menu_draw (component_context_menu_t *cm) {
NULL 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; const char *text = cm->list[i].text;
rdpq_paragraph_builder_span(text, strlen(text)); rdpq_paragraph_builder_span(text, strlen(text));
if (cm->list[i + 1].text != NULL) { 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_x0 = DISPLAY_CENTER_X - (width / 2);
int highlight_x1 = 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_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( component_box_draw(
highlight_x0, highlight_x0,
@ -126,6 +126,6 @@ void component_context_menu_draw (component_context_menu_t *cm) {
if (top->hide_pending) { if (top->hide_pending) {
top->hide_pending = false; top->hide_pending = false;
top->selected = -1; top->row_selected = -1;
} }
} }

View File

@ -104,6 +104,12 @@ typedef struct {
path_t *disk_path; path_t *disk_path;
disk_info_t disk_info; disk_info_t disk_info;
} load; } load;
struct {
bool rom_file;
bool disk_file;
bool emulator_file;
} boot_pending;
} menu_t; } menu_t;

View File

@ -14,6 +14,9 @@ static settings_t init = {
.default_directory = "/", .default_directory = "/",
.use_saves_folder = true, .use_saves_folder = true,
.sound_enabled = true, .sound_enabled = true,
.rom_autoload_enabled = false,
.rom_autoload_path = "",
.rom_autoload_filename = "",
/* Beta feature flags (should always init to off) */ /* Beta feature flags (should always init to off) */
.bgm_enabled = false, .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->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->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 */ /* 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->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); 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_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", "use_saves_folder", settings->use_saves_folder);
mini_set_bool(ini, "menu", "sound_enabled", settings->sound_enabled); 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! */ /* Beta feature flags, they should not save until production ready! */
// mini_set_bool(ini, "menu_beta_flag", "bgm_enabled", settings->bgm_enabled); // mini_set_bool(ini, "menu_beta_flag", "bgm_enabled", settings->bgm_enabled);

View File

@ -30,6 +30,16 @@ typedef struct {
/** @brief Enable rumble feedback */ /** @brief Enable rumble feedback */
bool rumble_enabled; 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; } settings_t;
@ -40,5 +50,4 @@ void settings_load (settings_t *settings);
/** @brief The settings to save */ /** @brief The settings to save */
void settings_save (settings_t *settings); void settings_save (settings_t *settings);
#endif #endif

View File

@ -19,7 +19,10 @@ static bool sfx_enabled = false;
static void sound_reconfigure (int frequency) { static void sound_reconfigure (int frequency) {
if ((frequency > 0) && (audio_get_frequency() != frequency)) { if ((frequency > 0) && (audio_get_frequency() != frequency)) {
sound_deinit(); if (sound_initialized) {
mixer_close();
audio_close();
}
audio_init(frequency, NUM_BUFFERS); audio_init(frequency, NUM_BUFFERS);
mixer_init(NUM_CHANNELS); mixer_init(NUM_CHANNELS);
mp3player_mixer_init(); mp3player_mixer_init();
@ -97,9 +100,7 @@ void sound_deinit (void) {
} }
void sound_poll (void) { void sound_poll (void) {
if (sound_initialized && audio_can_write()) { if (sound_initialized) {
short *audio_buffer = audio_write_begin(); mixer_try_play();
mixer_poll(audio_buffer, audio_get_buffer_length());
audio_write_end();
} }
} }

View File

@ -12,8 +12,8 @@
static void process (menu_t *menu) { static void process (menu_t *menu) {
if (menu->actions.back) { if (menu->actions.back) {
menu->next_mode = MENU_MODE_BROWSER;
sound_play_effect(SFX_EXIT); sound_play_effect(SFX_EXIT);
menu->next_mode = MENU_MODE_BROWSER;
} }
} }

View File

@ -50,8 +50,8 @@ static char *format_file_type (char *name, bool is_directory) {
static void process (menu_t *menu) { static void process (menu_t *menu) {
if (menu->actions.back) { if (menu->actions.back) {
menu->next_mode = MENU_MODE_BROWSER;
sound_play_effect(SFX_EXIT); 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", S_ISDIR(st.st_mode) ? "Directory" : "File",
st.st_mode & S_IWUSR ? "" : "(Read only)", st.st_mode & S_IWUSR ? "" : "(Read only)",
format_file_type(menu->browser.entry->name, S_ISDIR(st.st_mode)), 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( component_actions_bar_text_draw(

View File

@ -1,15 +1,35 @@
#include "views.h" #include "views.h"
#include "../sound.h" #include "../sound.h"
#include <libcart/cart.h>
static inline const char *format_boolean_type (bool bool_value) { static inline const char *format_boolean_type (bool bool_value) {
return bool_value ? "Supported" : "Unsupported"; 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) { static void process (menu_t *menu) {
if (menu->actions.back) { if (menu->actions.back) {
menu->next_mode = MENU_MODE_BROWSER;
sound_play_effect(SFX_EXIT); 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" " Virtual 64DD: %s.\n"
" Real Time Clock: %s.\n" " Real Time Clock: %s.\n"
" USB Debugging: %s.\n" " USB Debugging: %s.\n"
" CIC Detection: %s.\n" " Automatic CIC: %s.\n"
" Region Detection: %s.\n" " Region Detection: %s.\n"
" Save Writeback: %s.\n"
" Update from menu: %s.\n"
"\n\n", "\n\n",
"SummerCart64", format_cart_type(),
"V?.?.?", "Not Available", // TODO get cart firmware version(s).
format_boolean_type(true), format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_64DD)),
format_boolean_type(true), format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_RTC)),
format_boolean_type(true), format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_USB)),
format_boolean_type(true), format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_AUTO_CIC)),
format_boolean_type(true) 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( component_actions_bar_text_draw(
ALIGN_LEFT, VALIGN_TOP, ALIGN_LEFT, VALIGN_TOP,
"\n" "\n"

View File

@ -5,8 +5,7 @@
#include "views.h" #include "views.h"
static bool load_pending; static bool load_disk_with_rom;
static bool load_rom;
static component_boxart_t *boxart; static component_boxart_t *boxart;
@ -31,15 +30,15 @@ static char *format_disk_region (disk_region_t region) {
static void process (menu_t *menu) { static void process (menu_t *menu) {
if (menu->actions.enter) { if (menu->actions.enter) {
load_pending = true; menu->boot_pending.disk_file = true;
load_rom = false; load_disk_with_rom = false;
} else if (menu->actions.options && menu->load.rom_path) { } else if (menu->actions.options && menu->load.rom_path) {
load_pending = true; menu->boot_pending.disk_file = true;
load_rom = true; load_disk_with_rom = true;
sound_play_effect(SFX_SETTING); sound_play_effect(SFX_SETTING);
} else if (menu->actions.back) { } else if (menu->actions.back) {
menu->next_mode = MENU_MODE_BROWSER;
sound_play_effect(SFX_EXIT); 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(); component_background_draw();
if (load_pending) { if (menu->boot_pending.disk_file) {
component_loader_draw(0.0f); component_loader_draw(0.0f);
} else { } else {
component_layout_draw(); component_layout_draw();
@ -119,7 +118,7 @@ static void draw_progress (float progress) {
static void load (menu_t *menu) { static void load (menu_t *menu) {
cart_load_err_t err; 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); err = cart_load_n64_rom_and_save(menu, draw_progress);
if (err != CART_LOAD_OK) { if (err != CART_LOAD_OK) {
menu_show_error(menu, cart_load_convert_error_message(err)); 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; 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->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); 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)) { 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; 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); 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); draw(menu, display);
if (load_pending) { if (menu->boot_pending.disk_file) {
load_pending = false; menu->boot_pending.disk_file = false;
load(menu); load(menu);
} }

View File

@ -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_gameboy_color_rom_extensions[] = { "gbc", NULL };
static const char *emu_sega_8bit_rom_extensions[] = { "sms", "gg", "sg", 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 cart_load_emu_type_t emu_type;
static char *format_emulator_name (cart_load_emu_type_t emulator_info) { 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) { static void process (menu_t *menu) {
if (menu->actions.enter) { if (menu->actions.enter) {
load_pending = true; menu->boot_pending.emulator_file = true;
} else if (menu->actions.back) { } else if (menu->actions.back) {
menu->next_mode = MENU_MODE_BROWSER;
sound_play_effect(SFX_EXIT); 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(); component_background_draw();
if (load_pending) { if (menu->boot_pending.emulator_file) {
component_loader_draw(0.0f); component_loader_draw(0.0f);
} else { } else {
component_layout_draw(); component_layout_draw();
@ -107,7 +106,7 @@ static void load (menu_t *menu) {
void view_load_emulator_init (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); 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); draw(menu, display);
if (load_pending) { if (menu->boot_pending.emulator_file) {
load_pending = false; menu->boot_pending.emulator_file = false;
load(menu); load(menu);
} }
} }

View File

@ -3,12 +3,12 @@
#include "boot/boot.h" #include "boot/boot.h"
#include "../sound.h" #include "../sound.h"
#include "views.h" #include "views.h"
#include <string.h>
#include "utils/fs.h"
static bool show_extra_info_message = false; static bool show_extra_info_message = false;
static bool load_pending;
static component_boxart_t *boxart; static component_boxart_t *boxart;
static char *convert_error_message (rom_err_t err) { static char *convert_error_message (rom_err_t err) {
switch (err) { switch (err) {
case ROM_ERR_LOAD_IO: return "I/O error during loading ROM information and/or options"; 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; 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 = { static component_context_menu_t set_cic_type_context_menu = { .list = {
{.text = "Automatic", .action = set_cic_type, .arg = (void *) (ROM_CIC_TYPE_AUTOMATIC) }, {.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) }, {.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 CIC Type", .submenu = &set_cic_type_context_menu },
{ .text = "Set Save Type", .submenu = &set_save_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 TV Type", .submenu = &set_tv_type_context_menu },
{ .text = "Set ROM to autoload", .action = set_autoload_type },
COMPONENT_CONTEXT_MENU_LIST_END, COMPONENT_CONTEXT_MENU_LIST_END,
}}; }};
@ -204,10 +216,10 @@ static void process (menu_t *menu) {
} }
if (menu->actions.enter) { if (menu->actions.enter) {
load_pending = true; menu->boot_pending.rom_file = true;
} else if (menu->actions.back) { } else if (menu->actions.back) {
menu->next_mode = MENU_MODE_BROWSER;
sound_play_effect(SFX_EXIT); sound_play_effect(SFX_EXIT);
menu->next_mode = MENU_MODE_BROWSER;
} else if (menu->actions.options) { } else if (menu->actions.options) {
component_context_menu_show(&options_context_menu); component_context_menu_show(&options_context_menu);
sound_play_effect(SFX_SETTING); sound_play_effect(SFX_SETTING);
@ -226,7 +238,7 @@ static void draw (menu_t *menu, surface_t *d) {
component_background_draw(); component_background_draw();
if (load_pending) { if (menu->boot_pending.rom_file) {
component_loader_draw(0.0f); component_loader_draw(0.0f);
} else { } else {
component_layout_draw(); component_layout_draw();
@ -354,13 +366,13 @@ static void deinit (void) {
void view_load_rom_init (menu_t *menu) { void view_load_rom_init (menu_t *menu) {
load_pending = false; if (!menu->settings.rom_autoload_enabled) {
if (menu->load.rom_path) { if (menu->load.rom_path) {
path_free(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); rom_err_t err = rom_info_load(menu->load.rom_path, &menu->load.rom_info);
if (err != ROM_OK) { if (err != ROM_OK) {
@ -370,9 +382,10 @@ void view_load_rom_init (menu_t *menu) {
return; return;
} }
if (!menu->settings.rom_autoload_enabled) {
boxart = component_boxart_init(menu->storage_prefix, menu->load.rom_info.game_code, IMAGE_BOXART_FRONT); boxart = component_boxart_init(menu->storage_prefix, menu->load.rom_info.game_code, IMAGE_BOXART_FRONT);
component_context_menu_init(&options_context_menu); component_context_menu_init(&options_context_menu);
}
} }
void view_load_rom_display (menu_t *menu, surface_t *display) { 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); draw(menu, display);
if (load_pending) { if (menu->boot_pending.rom_file) {
load_pending = false; menu->boot_pending.rom_file = false;
load(menu); load(menu);
} }

View File

@ -41,8 +41,8 @@ static void process (menu_t *menu) {
if (err != MP3PLAYER_OK) { if (err != MP3PLAYER_OK) {
menu_show_error(menu, convert_error_message(err)); menu_show_error(menu, convert_error_message(err));
} else if (menu->actions.back) { } else if (menu->actions.back) {
menu->next_mode = MENU_MODE_BROWSER;
sound_play_effect(SFX_EXIT); sound_play_effect(SFX_EXIT);
menu->next_mode = MENU_MODE_BROWSER;
} else if (menu->actions.enter) { } else if (menu->actions.enter) {
err = mp3player_toggle(); err = mp3player_toggle();
if (err != MP3PLAYER_OK) { if (err != MP3PLAYER_OK) {

View File

@ -18,8 +18,8 @@
static void process (menu_t *menu) { static void process (menu_t *menu) {
if (menu->actions.back) { if (menu->actions.back) {
menu->next_mode = MENU_MODE_BROWSER;
sound_play_effect(SFX_EXIT); sound_play_effect(SFX_EXIT);
menu->next_mode = MENU_MODE_BROWSER;
} }
} }

View File

@ -114,8 +114,8 @@ static void process (menu_t *menu) {
component_context_menu_show(&options_context_menu); component_context_menu_show(&options_context_menu);
sound_play_effect(SFX_SETTING); sound_play_effect(SFX_SETTING);
} else if (menu->actions.back) { } else if (menu->actions.back) {
menu->next_mode = MENU_MODE_BROWSER;
sound_play_effect(SFX_EXIT); 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, ALIGN_LEFT, VALIGN_TOP,
"\n\n" "\n\n"
" Default Directory : %s\n\n" " Default Directory : %s\n\n"
" Autoload ROM : %s\n"
"To change the following menu settings, press 'A':\n" "To change the following menu settings, press 'A':\n"
"* PAL60 Mode : %s\n" "* PAL60 Mode : %s\n"
" Show Hidden Files : %s\n" " Show Hidden Files : %s\n"
@ -145,9 +146,11 @@ static void draw (menu_t *menu, surface_t *d) {
" Background Music : %s\n" " Background Music : %s\n"
" Rumble Feedback : %s\n" " Rumble Feedback : %s\n"
#endif #endif
"Note: Certain settings have the following caveats:\n\n" "\n\n"
"* Requires a flashcart reboot.\n", "Note: Certain settings have the following caveats:\n"
"* Requires rebooting the N64 Console.\n",
menu->settings.default_directory, menu->settings.default_directory,
format_switch(menu->settings.rom_autoload_enabled),
format_switch(menu->settings.pal60_enabled), format_switch(menu->settings.pal60_enabled),
format_switch(menu->settings.show_protected_entries), format_switch(menu->settings.show_protected_entries),
format_switch(menu->settings.use_saves_folder), 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) { 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; menu->next_mode = MENU_MODE_BROWSER;
} }

View File

@ -28,8 +28,8 @@ static void process (menu_t *menu) {
} }
if (menu->actions.back) { if (menu->actions.back) {
menu->next_mode = MENU_MODE_BROWSER;
sound_play_effect(SFX_EXIT); sound_play_effect(SFX_EXIT);
menu->next_mode = MENU_MODE_BROWSER;
} }
} }

View File

@ -55,8 +55,8 @@ static void perform_vertical_scroll (int lines) {
static void process (menu_t *menu) { static void process (menu_t *menu) {
if (menu->actions.back) { if (menu->actions.back) {
menu->next_mode = MENU_MODE_BROWSER;
sound_play_effect(SFX_EXIT); sound_play_effect(SFX_EXIT);
menu->next_mode = MENU_MODE_BROWSER;
} else if (text) { } else if (text) {
if (menu->actions.go_up) { if (menu->actions.go_up) {
perform_vertical_scroll(menu->actions.go_fast ? -10 : -1); perform_vertical_scroll(menu->actions.go_fast ? -10 : -1);