RETRO_ENVIRONMENT_SHUTDOWN Fixes

- Ensure core is properly unloaded when RETRO_ENVIRONMENT_SHUTDOWN is called
- Ensure menu stack is properly flushed when RETRO_ENVIRONMENT_SHUTDOWN is called
This commit is contained in:
jdgleaver 2022-03-17 17:27:40 +00:00 committed by Autechre
parent 72513e29b2
commit c6e83d23f5
7 changed files with 121 additions and 69 deletions

View File

@ -9239,7 +9239,7 @@ static int materialui_list_push(void *data, void *userdata,
}
else
{
if (system->load_no_content)
if (system && system->load_no_content)
{
MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
info->list,

View File

@ -7899,7 +7899,7 @@ static int ozone_list_push(void *data, void *userdata,
}
else
{
if (system->load_no_content)
if (system && system->load_no_content)
{
MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
info->list,

View File

@ -7107,7 +7107,7 @@ static int xmb_list_push(void *data, void *userdata,
}
else
{
if (system->load_no_content)
if (system && system->load_no_content)
{
MENU_DISPLAYLIST_PARSE_SETTINGS_ENUM(
info->list,

View File

@ -8061,23 +8061,73 @@ int generic_menu_entry_action(
}
#endif
if (menu_st->pending_close_content)
if (menu_st->pending_close_content ||
menu_st->pending_env_shutdown_flush)
{
const char *content_path = path_get(RARCH_PATH_CONTENT);
const char *menu_flush_to = msg_hash_to_str(MENU_ENUM_LABEL_MAIN_MENU);
const char *content_path = menu_st->pending_env_shutdown_flush ?
menu_st->pending_env_shutdown_content_path :
path_get(RARCH_PATH_CONTENT);
const char *deferred_path = menu ? menu->deferred_path : NULL;
const char *flush_target = msg_hash_to_str(MENU_ENUM_LABEL_MAIN_MENU);
size_t stack_offset = 1;
bool reset_navigation = true;
/* Flush to playlist entry menu if launched via playlist */
if (menu &&
!string_is_empty(menu->deferred_path) &&
!string_is_empty(content_path) &&
string_is_equal(menu->deferred_path, content_path))
menu_flush_to = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_RPL_ENTRY_ACTIONS);
/* Loop backwards through the menu stack to
* find a known reference point */
while (menu_stack && (menu_stack->size >= stack_offset))
{
const char *parent_label = NULL;
command_event(CMD_EVENT_UNLOAD_CORE, NULL);
menu_entries_flush_stack(menu_flush_to, 0);
file_list_get_at_offset(menu_stack,
menu_stack->size - stack_offset,
NULL, &parent_label, NULL, NULL);
if (string_is_empty(parent_label))
continue;
/* If core was launched via a playlist, flush
* to playlist entry menu */
if (string_is_equal(parent_label,
msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_RPL_ENTRY_ACTIONS)) &&
(!string_is_empty(deferred_path) &&
!string_is_empty(content_path) &&
string_is_equal(deferred_path, content_path)))
{
flush_target = msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_RPL_ENTRY_ACTIONS);
break;
}
/* If core was launched via standalone cores menu,
* flush to standalone cores menu */
else if (string_is_equal(parent_label,
msg_hash_to_str(MENU_ENUM_LABEL_CONTENTLESS_CORES_TAB)) ||
string_is_equal(parent_label,
msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_CONTENTLESS_CORES_LIST)))
{
flush_target = parent_label;
reset_navigation = false;
break;
}
stack_offset++;
}
if (!menu_st->pending_env_shutdown_flush)
command_event(CMD_EVENT_UNLOAD_CORE, NULL);
menu_entries_flush_stack(flush_target, 0);
/* An annoyance - some menu drivers (Ozone...) call
* RARCH_MENU_CTL_SET_PREVENT_POPULATE in awkward
* places, which can cause breakage here when flushing
* the menu stack. We therefore have to force a
* RARCH_MENU_CTL_UNSET_PREVENT_POPULATE */
menu_driver_ctl(RARCH_MENU_CTL_UNSET_PREVENT_POPULATE, NULL);
menu_st->selection_ptr = 0;
menu_st->pending_close_content = false;
if (reset_navigation)
menu_st->selection_ptr = 0;
menu_st->pending_close_content = false;
menu_st->pending_env_shutdown_flush = false;
menu_st->pending_env_shutdown_content_path[0] = '\0';
}
return ret;

View File

@ -501,6 +501,12 @@ struct menu_state
/* Storage container for current menu datetime
* representation string */
char datetime_cache[255];
/* Filled with current content path when a core calls
* RETRO_ENVIRONMENT_SHUTDOWN. Value is required in
* generic_menu_entry_action(), and must be cached
* since RETRO_ENVIRONMENT_SHUTDOWN will cause
* RARCH_PATH_CONTENT to be cleared */
char pending_env_shutdown_content_path[PATH_MAX_LENGTH];
#ifdef HAVE_MENU
char input_dialog_kb_label_setting[256];
@ -520,6 +526,9 @@ struct menu_state
bool entries_nonblocking_refresh;
/* 'Close Content'-hotkey menu resetting */
bool pending_close_content;
/* Flagged when a core calls RETRO_ENVIRONMENT_SHUTDOWN,
* requiring the menu to be flushed on the next iteration */
bool pending_env_shutdown_flush;
/* Screensaver status
* - Does menu driver support screensaver functionality?
* - Is screensaver currently active? */

View File

@ -1875,6 +1875,7 @@ bool command_event(enum event_command cmd, void *data)
break;
case CMD_EVENT_UNLOAD_CORE:
{
bool load_dummy_core = data ? *(bool*)data : true;
bool contentless = false;
bool is_inited = false;
content_ctx_info_t content_info = {0};
@ -1936,7 +1937,7 @@ bool command_event(enum event_command cmd, void *data)
else
input_remapping_restore_global_config(true);
if (is_inited)
if (is_inited && load_dummy_core)
{
#ifdef HAVE_MENU
if ( (settings->uints.quit_on_close_content == QUIT_ON_CLOSE_CONTENT_CLI && global->launched_from_cli)

View File

@ -1900,48 +1900,34 @@ bool runloop_environment_cb(unsigned cmd, void *data)
}
case RETRO_ENVIRONMENT_SHUTDOWN:
RARCH_LOG("[Environ]: SHUTDOWN.\n");
/* This case occurs when a core (internally) requests
* a shutdown event. Must save runtime log file here,
* since normal command.c CMD_EVENT_CORE_DEINIT event
* will not occur until after the current content has
* been cleared (causing log to be skipped) */
runloop_runtime_log_deinit(runloop_st,
settings->bools.content_runtime_log,
settings->bools.content_runtime_log_aggregate,
settings->paths.directory_runtime_log,
settings->paths.directory_playlist);
/* Similarly, since the CMD_EVENT_CORE_DEINIT will
* be called *after* the runloop state has been
* cleared, must also perform the following actions
* here:
* - Disable any active config overrides
* - Unload any active input remaps */
#ifdef HAVE_CONFIGFILE
if (runloop_st->overrides_active)
{
/* Reload the original config */
config_unload_override();
runloop_st->overrides_active = false;
}
{
#ifdef HAVE_MENU
struct menu_state *menu_st = menu_state_get_ptr();
#endif
if ( runloop_st->remaps_core_active
|| runloop_st->remaps_content_dir_active
|| runloop_st->remaps_game_active
|| !string_is_empty(runloop_st->name.remapfile)
)
{
input_remapping_deinit(true);
input_remapping_set_defaults(true);
}
else
input_remapping_restore_global_config(true);
/* This case occurs when a core (internally)
* requests a shutdown event */
RARCH_LOG("[Environ]: SHUTDOWN.\n");
runloop_st->shutdown_initiated = true;
runloop_st->core_shutdown_initiated = true;
#ifdef HAVE_MENU
/* Ensure that menu stack is flushed appropriately
* after the core has stopped running */
if (menu_st)
{
const char *content_path = path_get(RARCH_PATH_CONTENT);
menu_st->pending_env_shutdown_flush = true;
if (!string_is_empty(content_path))
strlcpy(menu_st->pending_env_shutdown_content_path,
content_path,
sizeof(menu_st->pending_env_shutdown_content_path));
else
menu_st->pending_env_shutdown_content_path[0] = '\0';
}
#endif
break;
}
case RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL:
if (system)
@ -6531,30 +6517,36 @@ static enum runloop_state_enum runloop_check_state(
if (runloop_exec)
runloop_exec = false;
if (runloop_st->core_shutdown_initiated &&
settings->bools.load_dummy_on_core_shutdown)
if (runloop_st->core_shutdown_initiated)
{
content_ctx_info_t content_info;
bool load_dummy_core = false;
content_info.argc = 0;
content_info.argv = NULL;
content_info.args = NULL;
content_info.environ_get = NULL;
runloop_st->core_shutdown_initiated = false;
if (task_push_start_dummy_core(&content_info))
/* Check whether dummy core should be loaded
* instead of exiting RetroArch completely
* (aborts shutdown if invoked) */
if (settings->bools.load_dummy_on_core_shutdown)
{
/* Loads dummy core instead of exiting RetroArch completely.
* Aborts core shutdown if invoked. */
runloop_st->shutdown_initiated = false;
runloop_st->core_shutdown_initiated = false;
load_dummy_core = true;
runloop_st->shutdown_initiated = false;
}
else
quit_runloop = true;
/* Unload current core, and load dummy if
* required */
if (!command_event(CMD_EVENT_UNLOAD_CORE, &load_dummy_core))
{
runloop_st->shutdown_initiated = true;
quit_runloop = true;
}
if (!load_dummy_core)
quit_runloop = true;
}
else
quit_runloop = true;
runloop_st->core_running = false;
runloop_st->core_running = false;
if (quit_runloop)
{