mirror of
https://github.com/Polprzewodnikowy/N64FlashcartMenu.git
synced 2025-02-18 11:06:25 +01:00
Merge branch 'develop' into cpak-management
This commit is contained in:
commit
4f060865a8
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -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'
|
||||
|
||||
|
@ -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
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user