From ef022ffe9017bef06d5f82d479e472362a7b8ba7 Mon Sep 17 00:00:00 2001 From: Cthulhu-throwaway <96153783+Cthulhu-throwaway@users.noreply.github.com> Date: Fri, 8 Jul 2022 13:20:01 -0300 Subject: [PATCH] (Netplay) Force a core update when starting netplay (#14157) --- retroarch.c | 66 ++++------ runloop.c | 20 ++++ tasks/task_core_updater.c | 193 +++++++++++++++++++++++++++++- tasks/task_netplay_find_content.c | 58 +++++++-- tasks/tasks_internal.h | 4 + 5 files changed, 286 insertions(+), 55 deletions(-) diff --git a/retroarch.c b/retroarch.c index ec4e36fa17..d4adc6f204 100644 --- a/retroarch.c +++ b/retroarch.c @@ -2883,61 +2883,45 @@ bool command_event(enum event_command cmd, void *data) break; case CMD_EVENT_NETPLAY_ENABLE_HOST: { -#ifdef HAVE_MENU - bool contentless = false; - bool is_inited = false; - - content_get_status(&contentless, &is_inited); - - if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL)) - command_event(CMD_EVENT_NETPLAY_DEINIT, NULL); - netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_SERVER, NULL); - - /* If we haven't yet started, this will load on its own */ - if (!is_inited) + if (!task_push_netplay_content_reload(NULL)) { + command_event(CMD_EVENT_NETPLAY_DEINIT, NULL); + netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_SERVER, NULL); + runloop_msg_queue_push( - msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_START_WHEN_LOADED), - 1, 480, true, - NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_START_WHEN_LOADED), + 1, 480, true, NULL, + MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO); + return false; } - - /* Enable Netplay itself */ - if (!command_event(CMD_EVENT_NETPLAY_INIT, NULL)) - return false; -#endif - break; } + break; case CMD_EVENT_NETPLAY_DISCONNECT: { + bool rewind_enable = settings->bools.rewind_enable; + unsigned autosave_interval = settings->uints.autosave_interval; + netplay_driver_ctl(RARCH_NETPLAY_CTL_DISCONNECT, NULL); netplay_driver_ctl(RARCH_NETPLAY_CTL_DISABLE, NULL); - { - bool rewind_enable = settings->bools.rewind_enable; - unsigned autosave_interval = settings->uints.autosave_interval; - #ifdef HAVE_REWIND - /* Re-enable rewind if it was enabled - * TODO/FIXME: Add a setting for these tweaks */ - if (rewind_enable) - command_event(CMD_EVENT_REWIND_INIT, NULL); + /* Re-enable rewind if it was enabled + * TODO/FIXME: Add a setting for these tweaks */ + if (rewind_enable) + command_event(CMD_EVENT_REWIND_INIT, NULL); #endif - if (autosave_interval != 0) - command_event(CMD_EVENT_AUTOSAVE_INIT, NULL); - } - - break; + if (autosave_interval != 0) + command_event(CMD_EVENT_AUTOSAVE_INIT, NULL); } + break; case CMD_EVENT_NETPLAY_HOST_TOGGLE: - if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_ENABLED, NULL) && - netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_SERVER, NULL)) - command_event(CMD_EVENT_NETPLAY_DISCONNECT, NULL); - else if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_ENABLED, NULL) && - !netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_SERVER, NULL) && - netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_CONNECTED, NULL)) - command_event(CMD_EVENT_NETPLAY_DISCONNECT, NULL); + if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_ENABLED, NULL)) + { + if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_SERVER, NULL) || + netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_CONNECTED, NULL)) + command_event(CMD_EVENT_NETPLAY_DISCONNECT, NULL); + } else command_event(CMD_EVENT_NETPLAY_ENABLE_HOST, NULL); diff --git a/runloop.c b/runloop.c index 07b7bc3277..79fed67d5c 100644 --- a/runloop.c +++ b/runloop.c @@ -5448,6 +5448,26 @@ bool runloop_event_init_core( float fastforward_ratio = 0.0f; rarch_system_info_t *sys_info = &runloop_st->system; +#if defined(HAVE_NETWORKING) && defined(HAVE_UPDATE_CORES) + /* If netplay is enabled, update the core before initializing. */ + if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_ENABLED, NULL)) + { + const char *path_core = path_get(RARCH_PATH_CORE); + + if (!string_is_empty(path_core) && + !string_is_equal(path_core, "builtin")) + { + task_push_update_single_core(path_core, + settings->bools.core_updater_auto_backup, + settings->uints.core_updater_auto_backup_history_size, + settings->paths.directory_libretro, + settings->paths.directory_core_assets); + /* We must wait for the update to finish before starting the core. */ + task_update_installed_cores_wait(); + } + } +#endif + if (!init_libretro_symbols(runloop_st, type, &runloop_st->current_core)) return false; diff --git a/tasks/task_core_updater.c b/tasks/task_core_updater.c index 2481e22315..c25c543322 100644 --- a/tasks/task_core_updater.c +++ b/tasks/task_core_updater.c @@ -3,6 +3,7 @@ * Copyright (C) 2014-2017 - Jean-André Santoni * Copyright (C) 2016-2019 - Brad Parker * Copyright (C) 2019 - James Leaver + * Copyright (C) 2022 - Roberto V. Rampim * * RetroArch is free software: you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Found- @@ -133,6 +134,26 @@ typedef struct update_installed_cores_handle bool auto_backup; } update_installed_cores_handle_t; +enum update_single_core_status +{ + UPDATE_SINGLE_CORE_BEGIN = 0, + UPDATE_SINGLE_CORE_WAIT_LIST, + UPDATE_SINGLE_CORE_UPDATE_CORE, + UPDATE_SINGLE_CORE_WAIT_DOWNLOAD, + UPDATE_SINGLE_CORE_END +}; + +typedef struct update_single_core_handle +{ + core_updater_list_t *core_list; + size_t auto_backup_history_size; + enum update_single_core_status status; + char path_core[PATH_MAX_LENGTH]; + char path_dir_libretro[PATH_MAX_LENGTH]; + char path_dir_core_assets[PATH_MAX_LENGTH]; + bool auto_backup; +} update_single_core_handle_t; + #if defined(ANDROID) /* Play feature delivery core install */ enum play_feature_delivery_install_task_status @@ -1454,17 +1475,128 @@ task_finished: free_update_installed_cores_handle(update_installed_handle); } +static void task_update_single_core_handler(retro_task_t *task) +{ + update_single_core_handle_t *handle = + (update_single_core_handle_t*)task->state; + + switch (handle->status) + { + case UPDATE_SINGLE_CORE_BEGIN: + { + if (task_push_get_core_updater_list(handle->core_list, + true, false)) + handle->status = UPDATE_SINGLE_CORE_WAIT_LIST; + else + handle->status = UPDATE_SINGLE_CORE_END; + } + break; + case UPDATE_SINGLE_CORE_WAIT_LIST: + { + task_finder_data_t find_data; + + find_data.func = task_core_updater_get_list_finder; + find_data.userdata = handle->core_list; + if (!task_queue_find(&find_data)) + handle->status = UPDATE_SINGLE_CORE_UPDATE_CORE; + } + break; + case UPDATE_SINGLE_CORE_UPDATE_CORE: + { + uint32_t crc; + const core_updater_list_entry_t *entry = NULL; + + if (!core_updater_list_get_core(handle->core_list, + handle->path_core, &entry)) + { + handle->status = UPDATE_SINGLE_CORE_END; + break; + } + + if (core_info_get_core_lock(entry->local_core_path, false)) + { + handle->status = UPDATE_SINGLE_CORE_END; + break; + } + + crc = task_core_updater_get_core_crc(entry->local_core_path); + if (!crc || crc == entry->crc) + { + handle->status = UPDATE_SINGLE_CORE_END; + break; + } + + if (task_push_core_updater_download(handle->core_list, + entry->remote_filename, crc, true, + handle->auto_backup, handle->auto_backup_history_size, + handle->path_dir_libretro, handle->path_dir_core_assets)) + handle->status = UPDATE_SINGLE_CORE_WAIT_DOWNLOAD; + else + handle->status = UPDATE_SINGLE_CORE_END; + } + break; + case UPDATE_SINGLE_CORE_WAIT_DOWNLOAD: + { + task_finder_data_t find_data; + const core_updater_list_entry_t *entry = NULL; + + if (!core_updater_list_get_core(handle->core_list, + handle->path_core, &entry)) + { + handle->status = UPDATE_SINGLE_CORE_END; + break; + } + + find_data.func = task_core_updater_download_finder; + find_data.userdata = entry->remote_filename; + if (!task_queue_find(&find_data)) + handle->status = UPDATE_SINGLE_CORE_END; + } + break; + case UPDATE_SINGLE_CORE_END: + default: + task_set_progress(task, 100); + task_set_finished(task, true); + break; + } +} + +static void task_update_single_core_cleanup(retro_task_t *task) +{ + update_single_core_handle_t *handle = + (update_single_core_handle_t*)task->state; + + core_updater_list_free(handle->core_list); + free(handle); +} + static bool task_update_installed_cores_finder(retro_task_t *task, void *user_data) { if (!task) return false; - if (task->handler == task_update_installed_cores_handler) + if (task->handler == task_update_installed_cores_handler || + task->handler == task_update_single_core_handler) return true; return false; } +static bool task_update_installed_cores_waiter(void *data) +{ + task_finder_data_t find_data; + + find_data.func = task_update_installed_cores_finder; + find_data.userdata = NULL; + + return task_queue_find(&find_data); +} + +void task_update_installed_cores_wait(void) +{ + task_queue_wait(task_update_installed_cores_waiter, NULL); +} + void task_push_update_installed_cores( bool auto_backup, size_t auto_backup_history_size, const char *path_dir_libretro, @@ -1545,6 +1677,65 @@ error: free_update_installed_cores_handle(update_installed_handle); } +void task_push_update_single_core( + const char *path_core, bool auto_backup, size_t auto_backup_history_size, + const char *path_dir_libretro, const char *path_dir_core_assets) +{ + task_finder_data_t find_data; + core_updater_list_t *core_list; + update_single_core_handle_t *handle; + retro_task_t *task; + + if (string_is_empty(path_core) || string_is_empty(path_dir_libretro)) + return; + +#ifdef ANDROID + /* Regular core updater is disabled in Play Store builds. */ + if (play_feature_delivery_enabled()) + return; +#endif + + /* Only one instance of this task may run at a time. */ + find_data.func = task_update_installed_cores_finder; + find_data.userdata = NULL; + if (task_queue_find(&find_data)) + return; + + core_list = core_updater_list_init(); + handle = (update_single_core_handle_t*)malloc(sizeof(*handle)); + task = task_init(); + if (!core_list || !handle || !task) + { + core_updater_list_free(core_list); + free(handle); + free(task); + + return; + } + + /* Configure handle */ + handle->status = UPDATE_SINGLE_CORE_BEGIN; + handle->core_list = core_list; + handle->auto_backup = auto_backup; + handle->auto_backup_history_size = auto_backup_history_size; + strlcpy(handle->path_core, path_core, sizeof(handle->path_core)); + strlcpy(handle->path_dir_libretro, path_dir_libretro, + sizeof(handle->path_dir_libretro)); + if (!string_is_empty(path_dir_core_assets)) + strlcpy(handle->path_dir_core_assets, path_dir_core_assets, + sizeof(handle->path_dir_core_assets)); + else + handle->path_dir_core_assets[0] = '\0'; + + /* Configure task */ + task->handler = task_update_single_core_handler; + task->cleanup = task_update_single_core_cleanup; + task->state = handle; + + /* Push task */ + task_queue_push(task); +} + #if defined(ANDROID) /**************************************/ /* Play feature delivery core install */ diff --git a/tasks/task_netplay_find_content.c b/tasks/task_netplay_find_content.c index f368482403..9ae99828d3 100644 --- a/tasks/task_netplay_find_content.c +++ b/tasks/task_netplay_find_content.c @@ -468,9 +468,17 @@ static void task_netplay_crc_scan_callback(retro_task_t *task, data->core, content_path); command_event(CMD_EVENT_NETPLAY_DEINIT, NULL); - netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_CLIENT, NULL); - command_event(CMD_EVENT_NETPLAY_INIT_DIRECT_DEFERRED, - data->hostname); + + if (string_is_empty(data->hostname)) + { + netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_SERVER, NULL); + } + else + { + netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_CLIENT, NULL); + command_event(CMD_EVENT_NETPLAY_INIT_DIRECT_DEFERRED, + data->hostname); + } task_push_load_new_core(data->core, NULL, NULL, CORE_TYPE_PLAIN, NULL, NULL); @@ -502,7 +510,11 @@ static void task_netplay_crc_scan_callback(retro_task_t *task, data->core, subsystem); command_event(CMD_EVENT_NETPLAY_DEINIT, NULL); - netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_CLIENT, NULL); + + if (string_is_empty(data->hostname)) + netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_SERVER, NULL); + else + netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_CLIENT, NULL); task_push_load_new_core(data->core, NULL, NULL, CORE_TYPE_PLAIN, NULL, NULL); @@ -517,8 +529,9 @@ static void task_netplay_crc_scan_callback(retro_task_t *task, for (i = 0; i < subsystem_content->size; i++) content_add_subsystem(subsystem_content->elems[i].data); - command_event(CMD_EVENT_NETPLAY_INIT_DIRECT_DEFERRED, - data->hostname); + if (!string_is_empty(data->hostname)) + command_event(CMD_EVENT_NETPLAY_INIT_DIRECT_DEFERRED, + data->hostname); task_push_load_subsystem_with_core(NULL, &content_info, CORE_TYPE_PLAIN, NULL, NULL); @@ -545,9 +558,17 @@ static void task_netplay_crc_scan_callback(retro_task_t *task, RARCH_LOG("[Lobby] Loading contentless core '%s'.\n", data->core); command_event(CMD_EVENT_NETPLAY_DEINIT, NULL); - netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_CLIENT, NULL); - command_event(CMD_EVENT_NETPLAY_INIT_DIRECT_DEFERRED, - data->hostname); + + if (string_is_empty(data->hostname)) + { + netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_SERVER, NULL); + } + else + { + netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_CLIENT, NULL); + command_event(CMD_EVENT_NETPLAY_INIT_DIRECT_DEFERRED, + data->hostname); + } task_push_load_new_core(data->core, NULL, NULL, CORE_TYPE_PLAIN, NULL, NULL); @@ -562,9 +583,17 @@ static void task_netplay_crc_scan_callback(retro_task_t *task, command_event(CMD_EVENT_UNLOAD_CORE, NULL); command_event(CMD_EVENT_NETPLAY_DEINIT, NULL); - netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_CLIENT, NULL); - command_event(CMD_EVENT_NETPLAY_INIT_DIRECT_DEFERRED, - data->hostname); + + if (string_is_empty(data->hostname)) + { + netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_SERVER, NULL); + } + else + { + netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_CLIENT, NULL); + command_event(CMD_EVENT_NETPLAY_INIT_DIRECT_DEFERRED, + data->hostname); + } task_push_load_new_core(data->core, NULL, NULL, CORE_TYPE_PLAIN, NULL, NULL); @@ -754,7 +783,10 @@ bool task_push_netplay_content_reload(const char *hostname) scan_state.state = STATE_RELOAD; strlcpy(data->core, pcore, sizeof(data->core)); - strlcpy(data->hostname, hostname, sizeof(data->hostname)); + + /* Hostname being NULL indicates this is a host. */ + if (hostname) + strlcpy(data->hostname, hostname, sizeof(data->hostname)); content_get_status(&contentless, &is_inited); if (contentless) diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h index 305dc94caa..f63cac33af 100644 --- a/tasks/tasks_internal.h +++ b/tasks/tasks_internal.h @@ -112,6 +112,10 @@ void task_push_update_installed_cores( bool auto_backup, size_t auto_backup_history_size, const char *path_dir_libretro, const char *path_dir_core_assets); +void task_push_update_single_core( + const char *path_core, bool auto_backup, size_t auto_backup_history_size, + const char *path_dir_libretro, const char *path_dir_core_assets); +void task_update_installed_cores_wait(void); #if defined(ANDROID) void *task_push_play_feature_delivery_core_install( core_updater_list_t* core_list,