diff --git a/src/menu/actions.c b/src/menu/actions.c index 79791b4a..8bb58587 100644 --- a/src/menu/actions.c +++ b/src/menu/actions.c @@ -20,9 +20,7 @@ static void actions_clear (menu_t *menu) { menu->actions.enter = false; menu->actions.back = false; menu->actions.options = false; - menu->actions.system_info = false; menu->actions.settings = false; - menu->actions.credits = false; } static void actions_update_direction (menu_t *menu) { @@ -91,11 +89,7 @@ static void actions_update_buttons (menu_t *menu) { menu->actions.back = true; } else if (pressed.r) { menu->actions.options = true; - } else if (pressed.z) { - menu->actions.system_info = true; } else if (pressed.start) { - menu->actions.credits = true; - } else if (pressed.l) { menu->actions.settings = true; } } diff --git a/src/menu/cart_load.c b/src/menu/cart_load.c index 2986d9a2..32bf4a28 100644 --- a/src/menu/cart_load.c +++ b/src/menu/cart_load.c @@ -34,8 +34,8 @@ static bool create_saves_subdirectory (path_t *path) { return error; } -static flashcart_save_type_t convert_save_type (rom_info_t *info) { - switch (info->save_type) { +static flashcart_save_type_t convert_save_type (rom_save_type_t save_type) { + switch (save_type) { case SAVE_TYPE_EEPROM_4K: return FLASHCART_SAVE_TYPE_EEPROM_4K; case SAVE_TYPE_EEPROM_16K: return FLASHCART_SAVE_TYPE_EEPROM_16K; case SAVE_TYPE_SRAM: return FLASHCART_SAVE_TYPE_SRAM; @@ -71,7 +71,7 @@ cart_load_err_t cart_load_n64_rom_and_save (menu_t *menu, flashcart_progress_cal path_t *path = path_clone(menu->load.rom_path); bool byte_swap = (menu->load.rom_info.endianness == ENDIANNESS_BYTE_SWAP); - flashcart_save_type_t save_type = convert_save_type(&menu->load.rom_info); + flashcart_save_type_t save_type = convert_save_type(rom_info_get_save_type(&menu->load.rom_info)); menu->flashcart_err = flashcart_load_rom(path_get(path), byte_swap, progress); if (menu->flashcart_err != FLASHCART_OK) { diff --git a/src/menu/components.h b/src/menu/components.h index 2a442f44..127c1d7b 100644 --- a/src/menu/components.h +++ b/src/menu/components.h @@ -37,13 +37,16 @@ void component_background_draw (void); void component_file_list_draw (entry_t *list, int entries, int selected); -typedef struct { +typedef struct component_context_menu { int count; int selected; bool hide_pending; + struct component_context_menu *parent; + struct component_context_menu *submenu; struct { const char *text; void (*action) (menu_t *menu); + struct component_context_menu *submenu; } list[]; } component_context_menu_t; diff --git a/src/menu/components/context_menu.c b/src/menu/components/context_menu.c index 10663509..82b3daa0 100644 --- a/src/menu/components/context_menu.c +++ b/src/menu/components/context_menu.c @@ -3,10 +3,19 @@ #include "constants.h" +static component_context_menu_t *get_current_submenu (component_context_menu_t *cm) { + while (cm->submenu != NULL) { + cm = cm->submenu; + } + return cm; +} + + void component_context_menu_init (component_context_menu_t *cm) { cm->selected = -1; cm->count = 0; cm->hide_pending = false; + cm->parent = NULL; for (int i = 0; (cm->list[i].text) != NULL; i++) { cm->count += 1; } @@ -14,6 +23,7 @@ void component_context_menu_init (component_context_menu_t *cm) { void component_context_menu_show (component_context_menu_t *cm) { cm->selected = 0; + cm->submenu = NULL; } bool component_context_menu_process (menu_t *menu, component_context_menu_t *cm) { @@ -21,13 +31,26 @@ bool component_context_menu_process (menu_t *menu, component_context_menu_t *cm) return false; } + component_context_menu_t *top = cm; + + cm = get_current_submenu(cm); + if (menu->actions.back) { - cm->hide_pending = true; - } else if (menu->actions.enter) { - if (cm->list[cm->selected].action) { - cm->list[cm->selected].action(menu); + if (cm->parent) { + cm->parent->submenu = NULL; + } else { cm->hide_pending = true; } + } else if (menu->actions.enter) { + if (cm->list[cm->selected].submenu) { + cm->submenu = cm->list[cm->selected].submenu; + component_context_menu_init(cm->submenu); + cm->submenu->selected = 0; + cm->submenu->parent = cm; + } else if (cm->list[cm->selected].action) { + cm->list[cm->selected].action(menu); + top->hide_pending = true; + } } else if (menu->actions.go_up) { cm->selected -= 1; if (cm->selected < 0) { @@ -48,6 +71,10 @@ void component_context_menu_draw (component_context_menu_t *cm) { return; } + component_context_menu_t *top = cm; + + cm = get_current_submenu(cm); + rdpq_paragraph_builder_begin( &(rdpq_textparms_t) { .width = VISIBLE_AREA_WIDTH, @@ -91,8 +118,8 @@ void component_context_menu_draw (component_context_menu_t *cm) { rdpq_paragraph_free(layout); - if (cm->hide_pending) { - cm->hide_pending = false; - cm->selected = -1; + if (top->hide_pending) { + top->hide_pending = false; + top->selected = -1; } } diff --git a/src/menu/menu.c b/src/menu/menu.c index 020fdc33..5f555831 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -89,6 +89,7 @@ static void menu_init (boot_params_t *boot_params) { char *init_directory = default_directory_exists ? menu->settings.default_directory : ""; menu->browser.valid = false; + menu->browser.reload = false; menu->browser.directory = path_init("sd:/", init_directory); menu->load.rom_path = NULL; diff --git a/src/menu/menu_state.h b/src/menu/menu_state.h index 7db9ca00..7c0c5f10 100644 --- a/src/menu/menu_state.h +++ b/src/menu/menu_state.h @@ -83,13 +83,12 @@ typedef struct { bool enter; bool back; bool options; - bool system_info; bool settings; - bool credits; } actions; struct { bool valid; + bool reload; path_t *directory; entry_t list[BROWSER_LIST_SIZE]; int entries; diff --git a/src/menu/rom_info.c b/src/menu/rom_info.c index 0910cf22..8d8f1f49 100644 --- a/src/menu/rom_info.c +++ b/src/menu/rom_info.c @@ -1,6 +1,7 @@ #include #include +#include #include "rom_info.h" #include "utils/fs.h" @@ -121,7 +122,7 @@ typedef struct { // Matched game metadata struct { // Save type (only cartridge save types) - save_type_t save; + rom_save_type_t save; // Supported features feat_t feat; @@ -659,6 +660,40 @@ static uint32_t fix_boot_address (cic_type_t cic_type, uint32_t boot_address) { } } +static rom_tv_type_t determine_tv_type (destination_type_t rom_destination_code) { + // check the market type from the ROM destination_code and return best guess! + switch (rom_destination_code) { + case MARKET_NORTH_AMERICA: + case MARKET_JAPANESE: + case MARKET_JAPANESE_MULTI: + case MARKET_GATEWAY64_NTSC: + return ROM_TV_TYPE_NTSC; + case MARKET_BRAZILIAN: + return ROM_TV_TYPE_MPAL; + case MARKET_GERMAN: + case MARKET_FRENCH: + case MARKET_DUTCH: + case MARKET_ITALIAN: + case MARKET_SPANISH: + case MARKET_AUSTRALIAN: + case MARKET_SCANDINAVIAN: + case MARKET_GATEWAY64_PAL: + case MARKET_EUROPEAN_BASIC: + // FIXME: There might be some interesting errors with OTHER_X and OTHER_Y (e.g. TGR Asia). + // But they are mainly PAL regions. + case MARKET_OTHER_X: + case MARKET_OTHER_Y: + return ROM_TV_TYPE_PAL; + // FIXME: We cannot be sure on these markets, so just return the default for the moment! + case MARKET_CHINESE: + case MARKET_CANADIAN: + case MARKET_KOREAN: + case MARKET_OTHER_Z: + default: + return ROM_TV_TYPE_UNKNOWN; + } +} + static void extract_rom_info (match_t *match, rom_header_t *rom_header, rom_info_t *rom_info) { rom_info->cic_type = cic_detect(rom_header->ipl3); @@ -688,6 +723,7 @@ static void extract_rom_info (match_t *match, rom_header_t *rom_header, rom_info rom_info->version = rom_header->version; rom_info->save_type = match->data.save; + rom_info->tv_type = determine_tv_type(rom_info->destination_code); rom_info->features.controller_pak = (match->data.feat & FEAT_CPAK); rom_info->features.rumble_pak = (match->data.feat & FEAT_RPAK); @@ -709,13 +745,127 @@ static void extract_rom_info (match_t *match, rom_header_t *rom_header, rom_info } } +static void load_overrides (path_t *path, rom_info_t *rom_info) { + rom_info->override.save = false; + rom_info->override.tv = false; -rom_err_t rom_info_load (char *path, rom_info_t *rom_info) { + path_t *overrides_path = path_clone(path); + + path_ext_replace(overrides_path, "ini"); + + if (!file_exists(path_get(overrides_path))) { + path_free(overrides_path); + return; + } + + mini_t *ini = mini_try_load(path_get(overrides_path)); + + rom_info->override.save_type = mini_get_int(ini, NULL, "save_type", SAVE_TYPE_AUTOMATIC); + if (rom_info->override.save_type != SAVE_TYPE_AUTOMATIC) { + rom_info->override.save = true; + } + + rom_info->override.tv_type = mini_get_int(ini, NULL, "tv_type", ROM_TV_TYPE_AUTOMATIC); + if (rom_info->override.tv_type != ROM_TV_TYPE_AUTOMATIC) { + rom_info->override.tv = true; + } + + mini_free(ini); + + path_free(overrides_path); +} + + +rom_err_t rom_info_override_save_type (path_t *path, rom_info_t *rom_info, rom_save_type_t save_type) { + path_t *overrides_path = path_clone(path); + + path_ext_replace(overrides_path, "ini"); + + mini_t *ini = mini_try_load(path_get(overrides_path)); + + rom_info->override.save_type = save_type; + + if (rom_info->override.save_type == SAVE_TYPE_AUTOMATIC) { + rom_info->override.save = false; + mini_delete_value(ini, NULL, "save_type"); + } else { + rom_info->override.save = true; + mini_set_int(ini, NULL, "save_type", rom_info->override.save_type); + } + + bool empty_override_file = mini_empty(ini); + + if (!empty_override_file) { + mini_save(ini, MINI_FLAGS_NONE); + } + + mini_free(ini); + + if (empty_override_file) { + file_delete(path_get(overrides_path)); + } + + path_free(overrides_path); + + return ROM_OK; +} + +rom_err_t rom_info_override_tv_type (path_t *path, rom_info_t *rom_info, rom_tv_type_t tv_type) { + path_t *overrides_path = path_clone(path); + + path_ext_replace(overrides_path, "ini"); + + mini_t *ini = mini_try_load(path_get(overrides_path)); + + rom_info->override.tv_type = tv_type; + + if (rom_info->override.tv_type == ROM_TV_TYPE_AUTOMATIC) { + rom_info->override.tv = false; + mini_delete_value(ini, NULL, "tv_type"); + } else { + rom_info->override.tv = true; + mini_set_int(ini, NULL, "tv_type", rom_info->override.tv_type); + } + + bool empty_override_file = mini_empty(ini); + + if (!empty_override_file) { + mini_save(ini, MINI_FLAGS_NONE); + } + + mini_free(ini); + + if (empty_override_file) { + file_delete(path_get(overrides_path)); + } + + path_free(overrides_path); + + return ROM_OK; +} + +rom_save_type_t rom_info_get_save_type (rom_info_t *rom_info) { + if (rom_info->override.save) { + return rom_info->override.save_type; + } else { + return rom_info->save_type; + } +} + +rom_tv_type_t rom_info_get_tv_type (rom_info_t *rom_info) { + if (rom_info->override.tv) { + return rom_info->override.tv_type; + } else { + return rom_info->tv_type; + } +} + +rom_err_t rom_info_load (path_t *path, rom_info_t *rom_info) { FIL fil; UINT br; rom_header_t rom_header; - if (f_open(&fil, strip_sd_prefix(path), FA_READ) != FR_OK) { + if (f_open(&fil, strip_sd_prefix(path_get(path)), FA_READ) != FR_OK) { return ROM_ERR_NO_FILE; } if (f_read(&fil, &rom_header, sizeof(rom_header), &br) != FR_OK) { @@ -735,5 +885,7 @@ rom_err_t rom_info_load (char *path, rom_info_t *rom_info) { extract_rom_info(&match, &rom_header, rom_info); + load_overrides(path, rom_info); + return ROM_OK; } diff --git a/src/menu/rom_info.h b/src/menu/rom_info.h index c9aed539..a4088c64 100644 --- a/src/menu/rom_info.h +++ b/src/menu/rom_info.h @@ -13,6 +13,8 @@ #include #include "boot/cic.h" +#include "path.h" + /** @brief ROM error enumeration. */ typedef enum { @@ -100,7 +102,16 @@ typedef enum { SAVE_TYPE_SRAM_128K, SAVE_TYPE_FLASHRAM, SAVE_TYPE_FLASHRAM_PKST2, -} save_type_t; + SAVE_TYPE_AUTOMATIC = -1, +} rom_save_type_t; + +typedef enum { + ROM_TV_TYPE_PAL, + ROM_TV_TYPE_NTSC, + ROM_TV_TYPE_MPAL, + ROM_TV_TYPE_UNKNOWN, + ROM_TV_TYPE_AUTOMATIC = -1, +} rom_tv_type_t; /** @brief ROM memory requirements enumeration. */ typedef enum { @@ -156,7 +167,17 @@ typedef struct { cic_type_t cic_type; /** @brief The save type required by the ROM. */ - save_type_t save_type; + rom_save_type_t save_type; + + rom_tv_type_t tv_type; + + struct { + bool save; + rom_save_type_t save_type; + + bool tv; + rom_tv_type_t tv_type; + } override; /** @brief The supported ROM accessories. */ struct { @@ -172,7 +193,11 @@ typedef struct { } rom_info_t; -rom_err_t rom_info_load (char *path, rom_info_t *rom_info); +rom_err_t rom_info_override_save_type (path_t *path, rom_info_t *rom_info, rom_save_type_t save_type); +rom_err_t rom_info_override_tv_type (path_t *path, rom_info_t *rom_info, rom_tv_type_t tv_type); +rom_save_type_t rom_info_get_save_type (rom_info_t *rom_info); +rom_tv_type_t rom_info_get_tv_type (rom_info_t *rom_info); +rom_err_t rom_info_load (path_t *path, rom_info_t *rom_info); #endif diff --git a/src/menu/settings.c b/src/menu/settings.c index 569f32d2..6f8dba03 100644 --- a/src/menu/settings.c +++ b/src/menu/settings.c @@ -4,16 +4,17 @@ #include "settings.h" #include "utils/fs.h" + #ifndef SETTINGS_FILE_PATH #define SETTINGS_FILE_PATH "sd:/menu/config.ini" #endif + static settings_t init = { .pal60_enabled = false, .hidden_files_enabled = false, .default_directory = "/", .use_saves_folder = true, - .autodetect_rom_region = true, /* Beta feature flags (should always init to off) */ .bgm_enabled = false, @@ -33,14 +34,12 @@ void settings_load (settings_t *settings) { settings->hidden_files_enabled = mini_get_bool(ini, "menu", "show_hidden_files", init.hidden_files_enabled); settings->default_directory = strdup(mini_get_string(ini, "menu", "default_directory", init.default_directory)); settings->use_saves_folder = mini_get_bool(ini, "menu", "use_saves_folder", init.use_saves_folder); - settings->autodetect_rom_region = mini_get_bool(ini, "menu", "autodetect_rom_region", init.autodetect_rom_region); /* 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->sound_enabled = mini_get_bool(ini, "menu_beta_flag", "sound_enabled", init.sound_enabled); settings->rumble_enabled = mini_get_bool(ini, "menu_beta_flag", "rumble_enabled", init.rumble_enabled); - mini_free(ini); } @@ -51,7 +50,6 @@ void settings_save (settings_t *settings) { mini_set_bool(ini, "menu", "show_hidden_files", settings->hidden_files_enabled); 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", "autodetect_rom_region", settings->autodetect_rom_region); /* 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 61ecf919..d2529998 100644 --- a/src/menu/settings.h +++ b/src/menu/settings.h @@ -22,9 +22,6 @@ typedef struct { /** @brief Put saves into separate directory */ bool use_saves_folder; - /** @brief Enable forcing the (N64 system region) tv type to align with game region when booting the ROM. */ - bool autodetect_rom_region; - /** @brief Enable Background music */ bool bgm_enabled; @@ -33,9 +30,9 @@ typedef struct { /** @brief Enable rumble feedback */ bool rumble_enabled; - } settings_t; + /** @brief The settings to load */ void settings_load (settings_t *settings); /** @brief The settings to save */ diff --git a/src/menu/views/browser.c b/src/menu/views/browser.c index 27c170ed..ecc3ac2b 100644 --- a/src/menu/views/browser.c +++ b/src/menu/views/browser.c @@ -228,11 +228,36 @@ static component_context_menu_t entry_context_menu = { } }; +static void edit_settings (menu_t *menu) { + menu->next_mode = MENU_MODE_SETTINGS_EDITOR; +} + +static void show_system_info (menu_t *menu) { + menu->next_mode = MENU_MODE_SYSTEM_INFO; +} + +static void show_credits (menu_t *menu) { + menu->next_mode = MENU_MODE_CREDITS; +} + +static component_context_menu_t settings_context_menu = { + .list = { + { .text = "Edit settings", .action = edit_settings }, + { .text = "Show system info", .action = show_system_info }, + { .text = "Show credits", .action = show_credits }, + COMPONENT_CONTEXT_MENU_LIST_END, + } +}; + static void process (menu_t *menu) { if (component_context_menu_process(menu, &entry_context_menu)) { return; } + if (component_context_menu_process(menu, &settings_context_menu)) { + return; + } + int scroll_speed = menu->actions.go_fast ? 10 : 1; if (menu->browser.entries > 1) { @@ -284,12 +309,8 @@ static void process (menu_t *menu) { } } else if (menu->actions.options && menu->browser.entry) { component_context_menu_show(&entry_context_menu); - } else if (menu->actions.system_info) { - menu->next_mode = MENU_MODE_SYSTEM_INFO; - } else if (menu->actions.credits) { - menu->next_mode = MENU_MODE_CREDITS; } else if (menu->actions.settings) { - menu->next_mode = MENU_MODE_SETTINGS_EDITOR; + component_context_menu_show(&settings_context_menu); } } @@ -326,15 +347,15 @@ static void draw (menu_t *menu, surface_t *d) { component_actions_bar_text_draw( ALIGN_RIGHT, VALIGN_TOP, - "%s\n" - "L: Settings", - menu->browser.entries == 0 ? "" : "R: Options" + "Start: Settings\n" + "^%02XR: Options^00", + menu->browser.entries == 0 ? STL_UNKNOWN : STL_DEFAULT ); if (menu->current_time >= 0) { component_actions_bar_text_draw( ALIGN_CENTER, VALIGN_TOP, - "Z: System Info | Start: Credits\n" + "\n" "%s", ctime(&menu->current_time) ); @@ -342,6 +363,8 @@ static void draw (menu_t *menu, surface_t *d) { component_context_menu_draw(&entry_context_menu); + component_context_menu_draw(&settings_context_menu); + rdpq_detach_show(); } @@ -349,6 +372,7 @@ static void draw (menu_t *menu, surface_t *d) { void view_browser_init (menu_t *menu) { if (!menu->browser.valid) { component_context_menu_init(&entry_context_menu); + component_context_menu_init(&settings_context_menu); if (load_directory(menu)) { path_free(menu->browser.directory); menu->browser.directory = path_init("sd:/", ""); @@ -357,6 +381,20 @@ void view_browser_init (menu_t *menu) { menu->browser.valid = true; } } + if (menu->browser.reload) { + menu->browser.reload = false; + int selected = menu->browser.selected; + if (load_directory(menu)) { + menu_show_error(menu, "Error while reloading current directory"); + menu->browser.valid = false; + } else { + menu->browser.selected = selected; + if (menu->browser.selected >= menu->browser.entries) { + menu->browser.selected = menu->browser.entries - 1; + } + menu->browser.entry = menu->browser.selected >= 0 ? &menu->browser.list[menu->browser.selected] : NULL; + } + } } void view_browser_display (menu_t *menu, surface_t *display) { diff --git a/src/menu/views/load_rom.c b/src/menu/views/load_rom.c index 1e072497..6beeaa0f 100644 --- a/src/menu/views/load_rom.c +++ b/src/menu/views/load_rom.c @@ -64,7 +64,7 @@ static const char *format_rom_destination_market (destination_type_t market_type } } -static const char *format_rom_save_type (save_type_t save_type) { +static const char *format_rom_save_type (rom_save_type_t save_type) { switch (save_type) { case SAVE_TYPE_NONE: return "None"; case SAVE_TYPE_EEPROM_4K: return "EEPROM 4K"; @@ -78,6 +78,15 @@ static const char *format_rom_save_type (save_type_t save_type) { } } +static const char *format_rom_tv_type (rom_tv_type_t tv_type) { + switch (tv_type) { + case ROM_TV_TYPE_PAL: return "PAL"; + case ROM_TV_TYPE_NTSC: return "NTSC"; + case ROM_TV_TYPE_MPAL: return "MPAL"; + default: return "Unknown"; + } +} + static char *format_rom_expansion_pak_info (expansion_pak_t expansion_pak_info) { switch (expansion_pak_info) { case EXPANSION_PAK_REQUIRED: return "Required"; @@ -107,46 +116,67 @@ static const char *format_cic_type (cic_type_t cic_type) { } } -static boot_tv_type_t determine_tv_boot_type (destination_type_t rom_destination_code) { - // check the market type from the ROM destination_code and return best guess! - switch (rom_destination_code) { - case MARKET_NORTH_AMERICA: - case MARKET_JAPANESE: - case MARKET_JAPANESE_MULTI: - case MARKET_GATEWAY64_NTSC: - return BOOT_TV_TYPE_NTSC; - case MARKET_BRAZILIAN: - return BOOT_TV_TYPE_MPAL; - case MARKET_GERMAN: - case MARKET_FRENCH: - case MARKET_DUTCH: - case MARKET_ITALIAN: - case MARKET_SPANISH: - case MARKET_AUSTRALIAN: - case MARKET_SCANDINAVIAN: - case MARKET_GATEWAY64_PAL: - case MARKET_EUROPEAN_BASIC: - // FIXME: There might be some interesting errors with OTHER_X and OTHER_Y (e.g. TGR Asia). - // But they are mainly PAL regions. - case MARKET_OTHER_X: - case MARKET_OTHER_Y: - return BOOT_TV_TYPE_PAL; - // FIXME: We cannot be sure on these markets, so just return the default for the moment! - case MARKET_CHINESE: - case MARKET_CANADIAN: - case MARKET_KOREAN: - case MARKET_OTHER_Z: - default: - return BOOT_TV_TYPE_PASSTHROUGH; - } +static void set_save_type (menu_t *menu, rom_save_type_t save_type) { + rom_info_override_save_type(menu->load.rom_path, &menu->load.rom_info, save_type); + menu->browser.reload = true; } +static void set_save_type_automatic (menu_t *menu) { set_save_type(menu, SAVE_TYPE_AUTOMATIC); } +static void set_save_type_none (menu_t *menu) { set_save_type(menu, SAVE_TYPE_NONE); } +static void set_save_type_eeprom_4kbit (menu_t *menu) { set_save_type(menu, SAVE_TYPE_EEPROM_4K); } +static void set_save_type_eeprom_16kbit (menu_t *menu) { set_save_type(menu, SAVE_TYPE_EEPROM_16K); } +static void set_save_type_sram_256kbit (menu_t *menu) { set_save_type(menu, SAVE_TYPE_SRAM); } +static void set_save_type_sram_768kbit (menu_t *menu) { set_save_type(menu, SAVE_TYPE_SRAM_BANKED); } +static void set_save_type_sram_1mbit (menu_t *menu) { set_save_type(menu, SAVE_TYPE_SRAM_128K); } +static void set_save_type_flash_ram_1mbit (menu_t *menu) { set_save_type(menu, SAVE_TYPE_FLASHRAM); } + +static component_context_menu_t set_save_type_context_menu = { .list = { + { .text = "Automatic", .action = set_save_type_automatic }, + { .text = "None", .action = set_save_type_none }, + { .text = "EEPROM 4kbit", .action = set_save_type_eeprom_4kbit }, + { .text = "EEPROM 16kbit", .action = set_save_type_eeprom_16kbit }, + { .text = "SRAM 256kbit", .action = set_save_type_sram_256kbit }, + { .text = "SRAM 768kbit", .action = set_save_type_sram_768kbit }, + { .text = "SRAM 1Mbit", .action = set_save_type_sram_1mbit }, + { .text = "FlashRAM 1Mbit", .action = set_save_type_flash_ram_1mbit }, + COMPONENT_CONTEXT_MENU_LIST_END, +}}; + +static void set_tv_type (menu_t *menu, rom_tv_type_t tv_type) { + rom_info_override_tv_type(menu->load.rom_path, &menu->load.rom_info, tv_type); + menu->browser.reload = true; +} + +static void set_tv_type_automatic (menu_t *menu) { set_tv_type(menu, ROM_TV_TYPE_AUTOMATIC); } +static void set_tv_type_pal (menu_t *menu) { set_tv_type(menu, ROM_TV_TYPE_PAL); } +static void set_tv_type_ntsc (menu_t *menu) { set_tv_type(menu, ROM_TV_TYPE_NTSC); } +static void set_tv_type_mpal (menu_t *menu) { set_tv_type(menu, ROM_TV_TYPE_MPAL); } + +static component_context_menu_t set_tv_type_context_menu = { .list = { + { .text = "Automatic", .action = set_tv_type_automatic }, + { .text = "PAL", .action = set_tv_type_pal }, + { .text = "NTSC", .action = set_tv_type_ntsc }, + { .text = "MPAL", .action = set_tv_type_mpal }, + COMPONENT_CONTEXT_MENU_LIST_END, +}}; + +static component_context_menu_t options_context_menu = { .list = { + { .text = "Set save type", .submenu = &set_save_type_context_menu }, + { .text = "Set TV type", .submenu = &set_tv_type_context_menu }, + COMPONENT_CONTEXT_MENU_LIST_END, +}}; static void process (menu_t *menu) { + if (component_context_menu_process(menu, &options_context_menu)) { + return; + } + if (menu->actions.enter) { load_pending = true; } else if (menu->actions.back) { menu->next_mode = MENU_MODE_BROWSER; + } else if (menu->actions.options) { + component_context_menu_show(&options_context_menu); } } @@ -182,6 +212,7 @@ static void draw (menu_t *menu, surface_t *d) { " Version: %hhu\n" " Check code: 0x%016llX\n" " Save type: %s\n" + " TV type: %s\n" " Expansion PAK: %s\n" "\n" " Extra information:\n" @@ -196,7 +227,8 @@ static void draw (menu_t *menu, surface_t *d) { format_rom_destination_market(menu->load.rom_info.destination_code), menu->load.rom_info.version, menu->load.rom_info.check_code, - format_rom_save_type(menu->load.rom_info.save_type), + format_rom_save_type(rom_info_get_save_type(&menu->load.rom_info)), + format_rom_tv_type(rom_info_get_tv_type(&menu->load.rom_info)), format_rom_expansion_pak_info(menu->load.rom_info.features.expansion_pak), format_cic_type(menu->load.rom_info.cic_type), menu->load.rom_info.boot_address, @@ -210,7 +242,15 @@ static void draw (menu_t *menu, surface_t *d) { "B: Exit" ); + component_actions_bar_text_draw( + ALIGN_RIGHT, VALIGN_TOP, + "\n" + "R: Options" + ); + component_boxart_draw(boxart); + + component_context_menu_draw(&options_context_menu); } rdpq_detach_show(); @@ -239,14 +279,14 @@ static void load (menu_t *menu) { } menu->next_mode = MENU_MODE_BOOT; + menu->boot_params->device_type = BOOT_DEVICE_TYPE_ROM; menu->boot_params->detect_cic_seed = true; - - if (menu->settings.autodetect_rom_region) { - menu->boot_params->tv_type = determine_tv_boot_type(menu->load.rom_info.destination_code); - } - else { - menu->boot_params->tv_type = BOOT_TV_TYPE_PASSTHROUGH; + switch(rom_info_get_tv_type(&menu->load.rom_info)) { + case ROM_TV_TYPE_PAL: menu->boot_params->tv_type = BOOT_TV_TYPE_PAL; break; + case ROM_TV_TYPE_NTSC: menu->boot_params->tv_type = BOOT_TV_TYPE_NTSC; break; + case ROM_TV_TYPE_MPAL: menu->boot_params->tv_type = BOOT_TV_TYPE_MPAL; break; + default: menu->boot_params->tv_type = BOOT_TV_TYPE_PASSTHROUGH; break; } } @@ -265,12 +305,14 @@ void view_load_rom_init (menu_t *menu) { menu->load.rom_path = path_clone_push(menu->browser.directory, menu->browser.entry->name); - rom_err_t err = rom_info_load(path_get(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) { menu_show_error(menu, convert_error_message(err)); } boxart = component_boxart_init(menu->load.rom_info.game_code); + + component_context_menu_init(&options_context_menu); } void view_load_rom_display (menu_t *menu, surface_t *display) { diff --git a/src/menu/views/settings_editor.c b/src/menu/views/settings_editor.c index 2df8fe30..39801f99 100644 --- a/src/menu/views/settings_editor.c +++ b/src/menu/views/settings_editor.c @@ -35,7 +35,6 @@ static void draw (menu_t *menu, surface_t *d) { "hidden_files_enabled: %s\n" "default_directory: %s\n" "use_saves_folder: %s\n" - "autodetect_rom_region: %s\n" "bgm_enabled: %s\n" "sound_enabled: %s\n" "rumble_enabled: %s\n", @@ -43,7 +42,6 @@ static void draw (menu_t *menu, surface_t *d) { convert_boolean(menu->settings.hidden_files_enabled), menu->settings.default_directory, convert_boolean(menu->settings.use_saves_folder), - convert_boolean(menu->settings.autodetect_rom_region), convert_boolean(menu->settings.bgm_enabled), convert_boolean(menu->settings.sound_enabled), convert_boolean(menu->settings.rumble_enabled)