diff --git a/intl/msg_hash_lbl.h b/intl/msg_hash_lbl.h index df6a0e149e..2f4086e86a 100644 --- a/intl/msg_hash_lbl.h +++ b/intl/msg_hash_lbl.h @@ -693,7 +693,7 @@ MSG_HASH( ) MSG_HASH( MENU_ENUM_LABEL_CLOSE_CONTENT, - "unload_core" + "close_content" ) MSG_HASH( MENU_ENUM_LABEL_COLLECTION, @@ -827,6 +827,10 @@ MSG_HASH( MENU_ENUM_LABEL_CORE_LIST, "load_core" ) +MSG_HASH( + MENU_ENUM_LABEL_CORE_LIST_UNLOAD, + "unload_core" + ) MSG_HASH( MENU_ENUM_LABEL_SIDELOAD_CORE_LIST, "sideload_core" diff --git a/intl/msg_hash_us.h b/intl/msg_hash_us.h index 9639f05802..97244ed523 100644 --- a/intl/msg_hash_us.h +++ b/intl/msg_hash_us.h @@ -71,6 +71,14 @@ MSG_HASH( MENU_ENUM_SUBLABEL_CORE_LIST, "Select which core to use." ) +MSG_HASH( + MENU_ENUM_LABEL_VALUE_CORE_LIST_UNLOAD, + "Unload Core" + ) +MSG_HASH( + MENU_ENUM_SUBLABEL_CORE_LIST_UNLOAD, + "Release the loaded core." + ) MSG_HASH( MENU_ENUM_LABEL_HELP_CORE_LIST, "Browse for a libretro core implementation. Where the browser starts depends on your Core Directory path. If blank, it will start in root.\nIf Core Directory is a directory, the menu will use that as top folder. If Core Directory is a full path, it will start in the folder where the file is." diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index 60d7f6c306..da6a1ff307 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -5717,6 +5717,9 @@ int action_ok_close_content(const char *path, const char *label, unsigned type, menu_st->flags &= ~MENU_ST_FLAG_PREVENT_POPULATE; } + /* Try to reload last core if loaded manually */ + menu_state_get_ptr()->flags |= MENU_ST_FLAG_PENDING_RELOAD_CORE; + return ret; } diff --git a/menu/cbs/menu_cbs_start.c b/menu/cbs/menu_cbs_start.c index cf6126514d..97f50ce12e 100644 --- a/menu/cbs/menu_cbs_start.c +++ b/menu/cbs/menu_cbs_start.c @@ -798,6 +798,7 @@ static int menu_cbs_init_bind_start_compare_label(menu_file_list_cbs_t *cbs) switch (cbs->enum_idx) { case MENU_ENUM_LABEL_CORE_LIST: + case MENU_ENUM_LABEL_CORE_LIST_UNLOAD: BIND_ACTION_START(cbs, action_start_load_core); break; case MENU_ENUM_LABEL_VIDEO_SHADER_PRESET: diff --git a/menu/cbs/menu_cbs_sublabel.c b/menu/cbs/menu_cbs_sublabel.c index 162a14c852..64bb82f668 100644 --- a/menu/cbs/menu_cbs_sublabel.c +++ b/menu/cbs/menu_cbs_sublabel.c @@ -620,6 +620,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_cheevos_password, MENU_ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_video_post_filter_record, MENU_ENUM_SUBLABEL_VIDEO_POST_FILTER_RECORD) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_start_core, MENU_ENUM_SUBLABEL_START_CORE) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_core_list, MENU_ENUM_SUBLABEL_CORE_LIST) +DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_core_list_unload, MENU_ENUM_SUBLABEL_CORE_LIST_UNLOAD) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_download_core, MENU_ENUM_SUBLABEL_DOWNLOAD_CORE) DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_update_installed_cores, MENU_ENUM_SUBLABEL_UPDATE_INSTALLED_CORES) #if defined(ANDROID) @@ -4464,6 +4465,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_CORE_LIST: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_core_list); break; + case MENU_ENUM_LABEL_CORE_LIST_UNLOAD: + BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_core_list_unload); + break; case MENU_ENUM_LABEL_SIDELOAD_CORE_LIST: BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_sideload_core_list); break; diff --git a/menu/drivers/materialui.c b/menu/drivers/materialui.c index e3d4119de7..c932eef42d 100644 --- a/menu/drivers/materialui.c +++ b/menu/drivers/materialui.c @@ -11713,9 +11713,9 @@ static void materialui_list_insert(void *userdata, node->icon_texture_index = MUI_TEXTURE_HALT_REPLAY; node->icon_type = MUI_ICON_TYPE_INTERNAL; } - else if ( - string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DISK_TRAY_EJECT)) + else if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DISK_TRAY_EJECT)) || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DISK_TRAY_INSERT)) + || string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_CORE_LIST_UNLOAD)) ) { node->icon_texture_index = MUI_TEXTURE_EJECT; diff --git a/menu/drivers/ozone.c b/menu/drivers/ozone.c index 9beacf90c1..e732e36ff5 100644 --- a/menu/drivers/ozone.c +++ b/menu/drivers/ozone.c @@ -1889,6 +1889,7 @@ static uintptr_t ozone_entries_icon_get_texture( case MENU_ENUM_LABEL_TAKE_SCREENSHOT: case MENU_ENUM_LABEL_QUICK_MENU_SHOW_TAKE_SCREENSHOT: return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_SCREENSHOT]; + case MENU_ENUM_LABEL_CORE_LIST_UNLOAD: case MENU_ENUM_LABEL_DELETE_ENTRY: case MENU_ENUM_LABEL_QUICK_MENU_SHOW_CLOSE_CONTENT: return ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_CLOSE]; diff --git a/menu/drivers/xmb.c b/menu/drivers/xmb.c index 63c24d687a..07f0ac700a 100644 --- a/menu/drivers/xmb.c +++ b/menu/drivers/xmb.c @@ -3322,6 +3322,7 @@ static uintptr_t xmb_icon_get_id(xmb_handle_t *xmb, case MENU_ENUM_LABEL_TAKE_SCREENSHOT: case MENU_ENUM_LABEL_QUICK_MENU_SHOW_TAKE_SCREENSHOT: return xmb->textures.list[XMB_TEXTURE_SCREENSHOT]; + case MENU_ENUM_LABEL_CORE_LIST_UNLOAD: case MENU_ENUM_LABEL_DELETE_ENTRY: case MENU_ENUM_LABEL_QUICK_MENU_SHOW_CLOSE_CONTENT: return xmb->textures.list[XMB_TEXTURE_CLOSE]; diff --git a/menu/menu_defines.h b/menu/menu_defines.h index 33f12ad599..5bff359c2e 100644 --- a/menu/menu_defines.h +++ b/menu/menu_defines.h @@ -48,7 +48,8 @@ enum menu_state_flags * - Does menu driver support screensaver functionality? * - Is screensaver currently active? */ MENU_ST_FLAG_SCREENSAVER_SUPPORTED = (1 << 10), - MENU_ST_FLAG_SCREENSAVER_ACTIVE = (1 << 11) + MENU_ST_FLAG_SCREENSAVER_ACTIVE = (1 << 11), + MENU_ST_FLAG_PENDING_RELOAD_CORE = (1 << 12) }; enum menu_scroll_mode diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 58fa628db9..cfb8bfb5f0 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -15075,9 +15075,18 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, { if (settings->bools.menu_show_load_core) { - if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, - MENU_ENUM_LABEL_CORE_LIST, PARSE_ACTION, false) == 0) - count++; + if (!string_is_empty(sys_info->info.library_name)) + { + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, + MENU_ENUM_LABEL_CORE_LIST_UNLOAD, PARSE_ACTION, false) == 0) + count++; + } + else + { + if (MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(info->list, + MENU_ENUM_LABEL_CORE_LIST, PARSE_ACTION, false) == 0) + count++; + } } } } diff --git a/menu/menu_driver.c b/menu/menu_driver.c index 2d145269de..b610b31238 100644 --- a/menu/menu_driver.c +++ b/menu/menu_driver.c @@ -49,6 +49,7 @@ #include "../driver.h" #include "../list_special.h" #include "../paths.h" +#include "../tasks/task_content.h" #include "../tasks/task_powerstate.h" #include "../tasks/tasks_internal.h" #include "../verbosity.h" @@ -6417,6 +6418,7 @@ void retroarch_menu_running(void) struct menu_state *menu_st = &menu_driver_state; menu_handle_t *menu = menu_st->driver_data; menu_input_t *menu_input = &menu_st->input_state; + if (menu) { if (menu->driver_ctx && menu->driver_ctx->toggle) @@ -6485,6 +6487,11 @@ void retroarch_menu_running_finished(bool quit) struct menu_state *menu_st = &menu_driver_state; menu_handle_t *menu = menu_st->driver_data; menu_input_t *menu_input = &menu_st->input_state; + + /* Only allow toggling menu off with a proper core */ + if (runloop_st->current_core_type == CORE_TYPE_DUMMY && !quit) + return; + if (menu) { if (menu->driver_ctx && menu->driver_ctx->toggle) @@ -7839,6 +7846,25 @@ int generic_menu_entry_action( | MENU_ST_FLAG_PENDING_ENV_SHUTDOWN_FLUSH); menu_st->pending_env_shutdown_content_path[0] = '\0'; } + else if (menu_st->flags & MENU_ST_FLAG_PENDING_RELOAD_CORE) + { + menu_st->flags &= ~MENU_ST_FLAG_PENDING_RELOAD_CORE; + + if (!string_is_empty(path_get(RARCH_PATH_CORE_LAST))) + { + content_ctx_info_t content_info = {0}; + if (task_push_load_new_core( + path_get(RARCH_PATH_CORE_LAST), + NULL, + &content_info, + CORE_TYPE_PLAIN, + NULL, NULL)) + { + menu_st->flags |= MENU_ST_FLAG_ENTRIES_NEED_REFRESH + | MENU_ST_FLAG_PREVENT_POPULATE; + } + } + } return ret; } diff --git a/menu/menu_setting.c b/menu/menu_setting.c index 3696fd7e24..0228a91711 100644 --- a/menu/menu_setting.c +++ b/menu/menu_setting.c @@ -9948,6 +9948,15 @@ static bool setting_append_list( (*list)[list_info->index - 1].values = ext_name; MENU_SETTINGS_LIST_CURRENT_ADD_CMD(list, list_info, CMD_EVENT_LOAD_CORE); SETTINGS_DATA_LIST_CURRENT_ADD_FLAGS(list, list_info, SD_FLAG_BROWSER_ACTION); + + CONFIG_ACTION( + list, list_info, + MENU_ENUM_LABEL_CORE_LIST_UNLOAD, + MENU_ENUM_LABEL_VALUE_CORE_LIST_UNLOAD, + &group_info, + &subgroup_info, + parent_group); + MENU_SETTINGS_LIST_CURRENT_ADD_CMD(list, list_info, CMD_EVENT_UNLOAD_CORE); } } diff --git a/msg_hash.h b/msg_hash.h index e4be9553e0..642b9886f6 100644 --- a/msg_hash.h +++ b/msg_hash.h @@ -3074,6 +3074,7 @@ enum msg_hash_enums MENU_LABEL(SUBSYSTEM_ADD), MENU_LABEL(SUBSYSTEM_LOAD), MENU_LBL_H(CORE_LIST), + MENU_LABEL(CORE_LIST_UNLOAD), MENU_LABEL(DOWNLOAD_CORE), MENU_LABEL(SIDELOAD_CORE_LIST), MENU_LABEL(SIDELOAD_CORE_ERROR), diff --git a/paths.h b/paths.h index cd223641db..eb5abafcc5 100644 --- a/paths.h +++ b/paths.h @@ -46,13 +46,14 @@ enum rarch_content_type enum rarch_path_type { RARCH_PATH_NONE = 0, - RARCH_PATH_CORE, RARCH_PATH_NAMES, - RARCH_PATH_CONFIG, RARCH_PATH_CONTENT, + RARCH_PATH_CORE, + RARCH_PATH_CORE_LAST, + RARCH_PATH_CORE_OPTIONS, + RARCH_PATH_CONFIG, RARCH_PATH_CONFIG_APPEND, RARCH_PATH_CONFIG_OVERRIDE, - RARCH_PATH_CORE_OPTIONS, RARCH_PATH_DEFAULT_SHADER_PRESET, RARCH_PATH_BASENAME, RARCH_PATH_SUBSYSTEM diff --git a/retroarch.c b/retroarch.c index ff225e2415..03329823b2 100644 --- a/retroarch.c +++ b/retroarch.c @@ -321,6 +321,7 @@ struct rarch_state char path_default_shader_preset[PATH_MAX_LENGTH]; char path_content[PATH_MAX_LENGTH]; char path_libretro[PATH_MAX_LENGTH]; + char path_libretro_last[PATH_MAX_LENGTH]; char path_config_file[PATH_MAX_LENGTH]; char path_config_append_file[PATH_MAX_LENGTH]; char path_config_override_file[PATH_MAX_LENGTH]; @@ -2429,6 +2430,8 @@ char *path_get_ptr(enum rarch_path_type type) break; case RARCH_PATH_CORE: return p_rarch->path_libretro; + case RARCH_PATH_CORE_LAST: + return p_rarch->path_libretro_last; case RARCH_PATH_NONE: case RARCH_PATH_NAMES: break; @@ -2465,6 +2468,8 @@ const char *path_get(enum rarch_path_type type) break; case RARCH_PATH_CORE: return p_rarch->path_libretro; + case RARCH_PATH_CORE_LAST: + return p_rarch->path_libretro_last; case RARCH_PATH_NONE: case RARCH_PATH_NAMES: break; @@ -2497,6 +2502,8 @@ size_t path_get_realsize(enum rarch_path_type type) return sizeof(p_rarch->path_config_override_file); case RARCH_PATH_CORE: return sizeof(p_rarch->path_libretro); + case RARCH_PATH_CORE_LAST: + return sizeof(p_rarch->path_libretro_last); case RARCH_PATH_NONE: case RARCH_PATH_NAMES: break; @@ -2529,6 +2536,10 @@ bool path_set(enum rarch_path_type type, const char *path) strlcpy(p_rarch->path_libretro, path, sizeof(p_rarch->path_libretro)); break; + case RARCH_PATH_CORE_LAST: + strlcpy(p_rarch->path_libretro_last, path, + sizeof(p_rarch->path_libretro_last)); + break; case RARCH_PATH_DEFAULT_SHADER_PRESET: strlcpy(p_rarch->path_default_shader_preset, path, sizeof(p_rarch->path_default_shader_preset)); @@ -2604,6 +2615,10 @@ bool path_is_empty(enum rarch_path_type type) if (string_is_empty(p_rarch->path_libretro)) return true; break; + case RARCH_PATH_CORE_LAST: + if (string_is_empty(p_rarch->path_libretro_last)) + return true; + break; case RARCH_PATH_BASENAME: if (string_is_empty(runloop_state_get_ptr()->runtime_content_path_basename)) return true; @@ -2627,20 +2642,20 @@ void path_clear(enum rarch_path_type type) switch (type) { + case RARCH_PATH_CONTENT: + *p_rarch->path_content = '\0'; + break; case RARCH_PATH_CORE: *p_rarch->path_libretro = '\0'; break; - case RARCH_PATH_CONFIG: - *p_rarch->path_config_file = '\0'; - break; - case RARCH_PATH_CONTENT: - *p_rarch->path_content = '\0'; + case RARCH_PATH_CORE_LAST: + *p_rarch->path_libretro_last = '\0'; break; case RARCH_PATH_CORE_OPTIONS: *p_rarch->path_core_options_file = '\0'; break; - case RARCH_PATH_DEFAULT_SHADER_PRESET: - *p_rarch->path_default_shader_preset = '\0'; + case RARCH_PATH_CONFIG: + *p_rarch->path_config_file = '\0'; break; case RARCH_PATH_CONFIG_APPEND: *p_rarch->path_config_append_file = '\0'; @@ -2648,6 +2663,9 @@ void path_clear(enum rarch_path_type type) case RARCH_PATH_CONFIG_OVERRIDE: *p_rarch->path_config_override_file = '\0'; break; + case RARCH_PATH_DEFAULT_SHADER_PRESET: + *p_rarch->path_default_shader_preset = '\0'; + break; case RARCH_PATH_NONE: case RARCH_PATH_NAMES: break; @@ -2665,11 +2683,15 @@ void path_clear(enum rarch_path_type type) static void path_clear_all(void) { path_clear(RARCH_PATH_CONTENT); + path_clear(RARCH_PATH_CORE); + path_clear(RARCH_PATH_CORE_LAST); + path_clear(RARCH_PATH_CORE_OPTIONS); path_clear(RARCH_PATH_CONFIG); path_clear(RARCH_PATH_CONFIG_APPEND); path_clear(RARCH_PATH_CONFIG_OVERRIDE); - path_clear(RARCH_PATH_CORE_OPTIONS); + path_clear(RARCH_PATH_DEFAULT_SHADER_PRESET); path_clear(RARCH_PATH_BASENAME); + path_clear(RARCH_PATH_SUBSYSTEM); } static void ram_state_to_file(void) @@ -3655,6 +3677,15 @@ bool command_event(enum event_command cmd, void *data) content_clear_subsystem(); } } + +#ifdef HAVE_MENU + menu_st->flags |= MENU_ST_FLAG_ENTRIES_NEED_REFRESH + | MENU_ST_FLAG_PREVENT_POPULATE; + { + bool pending_push = false; + menu_driver_ctl(MENU_NAVIGATION_CTL_CLEAR, &pending_push); + } +#endif break; case CMD_EVENT_CLOSE_CONTENT: #ifdef HAVE_MENU @@ -3671,6 +3702,7 @@ bool command_event(enum event_command cmd, void *data) if (!(menu_state_get_ptr()->flags & MENU_ST_FLAG_ALIVE)) { menu_state_get_ptr()->flags |= MENU_ST_FLAG_PENDING_CLOSE_CONTENT; + menu_state_get_ptr()->flags |= MENU_ST_FLAG_PENDING_RELOAD_CORE; command_event(CMD_EVENT_MENU_TOGGLE, NULL); } #else diff --git a/runloop.c b/runloop.c index 9f86e1c214..846a5ccc9a 100644 --- a/runloop.c +++ b/runloop.c @@ -5808,22 +5808,25 @@ static enum runloop_state_enum runloop_check_state( /* Check menu hotkey */ { static bool old_pressed = false; - char *menu_driver = settings->arrays.menu_driver; bool pressed = BIT256_GET(current_bits, RARCH_MENU_TOGGLE) - && !string_is_equal(menu_driver, "null"); + && !string_is_equal(settings->arrays.menu_driver, "null"); bool core_type_is_dummy = runloop_st->current_core_type == CORE_TYPE_DUMMY; - if ( (pressed && !old_pressed) - || core_type_is_dummy) + if (pressed && !old_pressed) { + bool core_is_running = runloop_st->flags & RUNLOOP_FLAG_CORE_RUNNING; + if (menu_st->flags & MENU_ST_FLAG_ALIVE) { - if (rarch_is_initialized && !core_type_is_dummy) + if (rarch_is_initialized && !core_type_is_dummy && core_is_running) retroarch_menu_running_finished(false); } else retroarch_menu_running(); } + /* Initial menu toggle on startup */ + else if (core_type_is_dummy && !(menu_st->flags & MENU_ST_FLAG_ALIVE)) + retroarch_menu_running(); old_pressed = pressed; } diff --git a/tasks/task_content.c b/tasks/task_content.c index 7005217f3c..0d6017c251 100644 --- a/tasks/task_content.c +++ b/tasks/task_content.c @@ -2109,8 +2109,10 @@ bool task_push_load_content_from_playlist_from_menu( #endif /* Specified core is not loaded - * > Load it */ + * > Load it + * > Forget manually loaded core */ path_set(RARCH_PATH_CORE, core_path); + path_clear(RARCH_PATH_CORE_LAST); #ifdef HAVE_DYNAMIC command_event(CMD_EVENT_LOAD_CORE, NULL); #else @@ -2275,8 +2277,12 @@ bool task_push_load_new_core( retro_task_callback_t cb, void *user_data) { + /* Set core path */ path_set(RARCH_PATH_CORE, core_path); + /* Remember core path for reloading */ + path_set(RARCH_PATH_CORE_LAST, core_path); + /* Load core */ command_event(CMD_EVENT_LOAD_CORE, NULL);