Merge branch 'develop' into cpak-management

This commit is contained in:
Robin Jones 2024-11-05 09:28:23 +00:00 committed by GitHub
commit 4f060865a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 104 additions and 40 deletions

View File

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

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

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

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),
.align = align,
.valign = valign,
.wrap = WRAP_ELLIPSES,
.wrap = WRAP_WORD,
.line_spacing = TEXT_LINE_SPACING_ADJUST,
},
FNT_DEFAULT,

View File

@ -105,6 +105,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;

View File

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

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

@ -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,11 +30,11 @@ 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) {
sound_play_effect(SFX_EXIT);
@ -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);
}

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_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,7 +33,7 @@ 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) {
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);
}
}

View File

@ -3,12 +3,12 @@
#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 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";
@ -145,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) },
@ -187,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,
}};
@ -196,7 +208,7 @@ static void process (menu_t *menu) {
}
if (menu->actions.enter) {
load_pending = true;
menu->boot_pending.rom_file = true;
} else if (menu->actions.back) {
sound_play_effect(SFX_EXIT);
menu->next_mode = MENU_MODE_BROWSER;
@ -218,7 +230,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();
@ -342,14 +354,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);
@ -358,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) {
@ -368,8 +381,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);
}

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

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