From 2d1c238c1d4e01cbbf63db0b8fd5781f7e99fb45 Mon Sep 17 00:00:00 2001 From: Cthulhu-throwaway <96153783+Cthulhu-throwaway@users.noreply.github.com> Date: Fri, 12 Aug 2022 21:24:28 -0300 Subject: [PATCH] Special functions for core serialization (#14317) --- core.h | 3 + network/netplay/netplay_frontend.c | 112 ++++++++-------------- runloop.c | 148 +++++++++++++++++++---------- runloop.h | 4 +- 4 files changed, 142 insertions(+), 125 deletions(-) diff --git a/core.h b/core.h index 9aba12461c..d32d552eb1 100644 --- a/core.h +++ b/core.h @@ -41,12 +41,15 @@ bool core_run(void); bool core_reset(void); bool core_serialize_size(retro_ctx_size_info_t *info); +bool core_serialize_size_special(retro_ctx_size_info_t *info); uint64_t core_serialization_quirks(void); bool core_serialize(retro_ctx_serialize_info_t *info); +bool core_serialize_special(retro_ctx_serialize_info_t *info); bool core_unserialize(retro_ctx_serialize_info_t *info); +bool core_unserialize_special(retro_ctx_serialize_info_t *info); bool core_set_cheat(retro_ctx_cheat_info_t *info); diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index bcb60b5ed4..27a9d05a56 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -3578,17 +3578,11 @@ static bool netplay_sync_pre_frame(netplay_t *netplay) if (!(netplay->quirks & NETPLAY_QUIRK_INITIALIZATION)) { retro_ctx_serialize_info_t serial_info = {0}; - bool okay = false; - runloop_state_t *runloop_st = runloop_state_get_ptr(); serial_info.data = netplay->buffer[netplay->run_ptr].state; serial_info.size = netplay->state_size; memset(serial_info.data, 0, serial_info.size); - - runloop_st->request_fast_savestate = true; - okay = core_serialize(&serial_info); - runloop_st->request_fast_savestate = false; - if (okay) + if (core_serialize_special(&serial_info)) { if (netplay->force_send_savestate && !netplay->stall && !netplay->remote_paused) @@ -3604,7 +3598,7 @@ static bool netplay_sync_pre_frame(netplay_t *netplay) netplay->run_frame_count = netplay->self_frame_count; } - /* Send this along to the other side */ + /* Send this along to the other side. */ serial_info.data_const = netplay->buffer[netplay->run_ptr].state; @@ -3789,8 +3783,6 @@ static void netplay_sync_post_frame(netplay_t *netplay, bool stalled) netplay->replay_frame_count < netplay->run_frame_count) { retro_ctx_serialize_info_t serial_info; - bool okay = false; - runloop_state_t *runloop_st = runloop_state_get_ptr(); /* Replay frames. */ netplay->is_replay = true; @@ -3820,31 +3812,24 @@ static void netplay_sync_post_frame(netplay_t *netplay, bool stalled) serial_info.data = NULL; serial_info.data_const = netplay->buffer[netplay->replay_ptr].state; serial_info.size = netplay->state_size; - - runloop_st->request_fast_savestate = true; - okay = core_unserialize(&serial_info); - runloop_st->request_fast_savestate = false; - if (!okay) - { + if (!core_unserialize_special(&serial_info)) RARCH_ERR("[Netplay] Netplay savestate loading failed: Prepare for desync!\n"); - } while (netplay->replay_frame_count < netplay->run_frame_count) { retro_time_t start, tm; struct delta_frame *ptr = &netplay->buffer[netplay->replay_ptr]; + serial_info.data_const = NULL; serial_info.data = ptr->state; serial_info.size = netplay->state_size; - serial_info.data_const = NULL; start = cpu_features_get_time_usec(); /* Remember the current state */ memset(serial_info.data, 0, serial_info.size); - runloop_st->request_fast_savestate = true; - core_serialize(&serial_info); - runloop_st->request_fast_savestate = false; + core_serialize_special(&serial_info); + if (netplay->replay_frame_count < netplay->unread_frame_count) netplay_handle_frame_hash(netplay, ptr); @@ -3869,12 +3854,12 @@ static void netplay_sync_post_frame(netplay_t *netplay, bool stalled) RARCH_LOG("INP %X %X\n", ptr->real_input_state[0], ptr->self_state[0]); else RARCH_LOG("INP %X %X\n", ptr->self_state[0], ptr->real_input_state[0]); - ptr = &netplay->buffer[netplay->replay_ptr]; + + ptr = &netplay->buffer[netplay->replay_ptr]; serial_info.data = ptr->state; memset(serial_info.data, 0, serial_info.size); - runloop_st->request_fast_savestate = true; - core_serialize(&serial_info); - runloop_st->request_fast_savestate = false; + core_serialize_special(&serial_info); + RARCH_LOG("POST %u: %X\n", netplay->replay_frame_count-1, netplay->state_size ? netplay_delta_frame_crc(netplay, ptr) : 0); } #endif @@ -6779,18 +6764,14 @@ static bool netplay_init_socket_buffers(netplay_t *netplay) static bool netplay_init_serialization(netplay_t *netplay) { size_t i; - retro_ctx_size_info_t info = {0}; - runloop_state_t *runloop_st = runloop_state_get_ptr(); + retro_ctx_size_info_t info = {0}; if (netplay->state_size) return true; - runloop_st->request_fast_savestate = true; - core_serialize_size(&info); - runloop_st->request_fast_savestate = false; + core_serialize_size_special(&info); if (!info.size) return false; - netplay->state_size = info.size; for (i = 0; i < netplay->buffer_size; i++) @@ -6822,8 +6803,6 @@ static bool netplay_init_serialization(netplay_t *netplay) static bool netplay_try_init_serialization(netplay_t *netplay) { retro_ctx_serialize_info_t serial_info; - bool okay = false; - runloop_state_t *runloop_st = runloop_state_get_ptr(); if (netplay->state_size) return true; @@ -6831,19 +6810,15 @@ static bool netplay_try_init_serialization(netplay_t *netplay) if (!netplay_init_serialization(netplay)) return false; - /* Check if we can actually save */ + /* Check if we can actually save. */ serial_info.data_const = NULL; serial_info.data = netplay->buffer[netplay->run_ptr].state; serial_info.size = netplay->state_size; - - runloop_st->request_fast_savestate = true; - okay = core_serialize(&serial_info); - runloop_st->request_fast_savestate = false; - if (!okay) + if (!core_serialize_special(&serial_info)) return false; - /* Once initialized, we no longer exhibit this quirk */ - netplay->quirks &= ~((uint32_t)NETPLAY_QUIRK_INITIALIZATION); + /* Once initialized, we no longer exhibit this quirk. */ + netplay->quirks &= ~NETPLAY_QUIRK_INITIALIZATION; return netplay_init_socket_buffers(netplay); } @@ -7302,51 +7277,46 @@ static void netplay_core_reset(netplay_t *netplay) void netplay_load_savestate(netplay_t *netplay, retro_ctx_serialize_info_t *serial_info, bool save) { - retro_ctx_serialize_info_t tmp_serial_info; - bool okay = false; - runloop_state_t *runloop_st = runloop_state_get_ptr(); + retro_ctx_serialize_info_t tmp_serial_info = {0}; + + if (!serial_info) + save = true; netplay_force_future(netplay); - /* Record it in our own buffer */ - if (save || !serial_info) + /* Record it in our own buffer. */ + if (save) { /* TODO/FIXME: This is a critical failure! */ if (!netplay_delta_frame_ready(netplay, - &netplay->buffer[netplay->run_ptr], netplay->run_frame_count)) + &netplay->buffer[netplay->run_ptr], netplay->run_frame_count)) return; if (!serial_info) { - tmp_serial_info.size = netplay->state_size; - tmp_serial_info.data = netplay->buffer[netplay->run_ptr].state; - - runloop_st->request_fast_savestate = true; - okay = core_serialize(&tmp_serial_info); - runloop_st->request_fast_savestate = false; - if (!okay) + tmp_serial_info.data = netplay->buffer[netplay->run_ptr].state; + tmp_serial_info.size = netplay->state_size; + if (!core_serialize_special(&tmp_serial_info)) return; tmp_serial_info.data_const = tmp_serial_info.data; - serial_info = &tmp_serial_info; - } - else - { - if (serial_info->size <= netplay->state_size) - memcpy(netplay->buffer[netplay->run_ptr].state, - serial_info->data_const, serial_info->size); + serial_info = &tmp_serial_info; } + else if (serial_info->size <= netplay->state_size) + memcpy(netplay->buffer[netplay->run_ptr].state, + serial_info->data_const, serial_info->size); } - /* Don't send it if we're expected to be desynced */ - if (netplay->desync) - return; - - /* Send this to every peer */ - if (netplay->compress_nil.compression_backend) - netplay_send_savestate(netplay, serial_info, 0, &netplay->compress_nil); - if (netplay->compress_zlib.compression_backend) - netplay_send_savestate(netplay, serial_info, NETPLAY_COMPRESSION_ZLIB, - &netplay->compress_zlib); + /* Don't send it if we're expected to be desynced. */ + if (!netplay->desync) + { + /* Send this to every peer. */ + if (netplay->compress_nil.compression_backend) + netplay_send_savestate(netplay, serial_info, 0, + &netplay->compress_nil); + if (netplay->compress_zlib.compression_backend) + netplay_send_savestate(netplay, serial_info, NETPLAY_COMPRESSION_ZLIB, + &netplay->compress_zlib); + } } /** diff --git a/runloop.c b/runloop.c index b5789da92e..456b62c959 100644 --- a/runloop.c +++ b/runloop.c @@ -3021,7 +3021,10 @@ bool runloop_environment_cb(unsigned cmd, void *data) result &= ~(1|2); #endif #if defined(HAVE_RUNAHEAD) || defined(HAVE_NETWORKING) - if (runloop_st->request_fast_savestate) + /* Deprecated. + Use RETRO_ENVIRONMENT_GET_SAVESTATE_CONTEXT instead. */ + /* TODO/FIXME: Get rid of this ugly hack. */ + if (runloop_st->request_special_savestate) result |= 4; #endif if (data) @@ -3034,32 +3037,36 @@ bool runloop_environment_cb(unsigned cmd, void *data) case RETRO_ENVIRONMENT_GET_SAVESTATE_CONTEXT: { - int result = RETRO_SAVESTATE_CONTEXT_NORMAL; + int result = RETRO_SAVESTATE_CONTEXT_NORMAL; + #if defined(HAVE_RUNAHEAD) || defined(HAVE_NETWORKING) - if (runloop_st->request_fast_savestate) + if (runloop_st->request_special_savestate) { -#ifdef HAVE_RUNAHEAD -#if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB) - settings_t - *settings = config_get_ptr(); - result = (settings->bools.run_ahead_secondary_instance - && runloop_st->runahead_secondary_core_available - && secondary_core_ensure_exists(settings) ? RETRO_SAVESTATE_CONTEXT_RUNAHEAD_SAME_BINARY : RETRO_SAVESTATE_CONTEXT_RUNAHEAD_SAME_INSTANCE); -#else - result = RETRO_SAVESTATE_CONTEXT_RUNAHEAD_SAME_INSTANCE; -#endif -#endif #ifdef HAVE_NETWORKING if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_ENABLED, NULL)) result = RETRO_SAVESTATE_CONTEXT_ROLLBACK_NETPLAY; + else #endif + { +#ifdef HAVE_RUNAHEAD +#if defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB) + settings_t *settings = config_get_ptr(); + + if (settings->bools.run_ahead_secondary_instance && + runloop_st->runahead_secondary_core_available && + secondary_core_ensure_exists(settings)) + result = RETRO_SAVESTATE_CONTEXT_RUNAHEAD_SAME_BINARY; + else +#endif + result = RETRO_SAVESTATE_CONTEXT_RUNAHEAD_SAME_INSTANCE; +#endif + } } #endif + if (data) - { - int* result_p = (int*)data; - *result_p = result; - } + *(int*)data = result; + break; } @@ -4132,13 +4139,22 @@ bool secondary_core_ensure_exists(settings_t *settings) #if defined(HAVE_RUNAHEAD) && defined(HAVE_DYNAMIC) static bool secondary_core_deserialize(settings_t *settings, - const void *buffer, int size) + const void *data, size_t size) { - runloop_state_t *runloop_st = &runloop_state; + bool ret = false; + if (secondary_core_ensure_exists(settings)) - return runloop_st->secondary_core.retro_unserialize(buffer, size); - runloop_secondary_core_destroy(); - return false; + { + runloop_state_t *runloop_st = &runloop_state; + + runloop_st->request_special_savestate = true; + ret = runloop_st->secondary_core.retro_unserialize(data, size); + runloop_st->request_special_savestate = false; + } + else + runloop_secondary_core_destroy(); + + return ret; } #endif @@ -4614,9 +4630,7 @@ static bool runahead_create(runloop_state_t *runloop_st) retro_ctx_size_info_t info; video_driver_state_t *video_st = video_state_get_ptr(); - runloop_st->request_fast_savestate = true; - core_serialize_size(&info); - runloop_st->request_fast_savestate = false; + core_serialize_size_special(&info); runahead_save_state_list_init(runloop_st, info.size); video_st->runahead_is_active = video_st->active; @@ -4638,7 +4652,6 @@ static bool runahead_create(runloop_state_t *runloop_st) static bool runahead_save_state(runloop_state_t *runloop_st) { retro_ctx_serialize_info_t *serialize_info; - bool okay = false; if (!runloop_st->runahead_save_state_list) return false; @@ -4646,11 +4659,7 @@ static bool runahead_save_state(runloop_state_t *runloop_st) serialize_info = (retro_ctx_serialize_info_t*)runloop_st->runahead_save_state_list->data[0]; - runloop_st->request_fast_savestate = true; - okay = core_serialize(serialize_info); - runloop_st->request_fast_savestate = false; - - if (okay) + if (core_serialize_special(serialize_info)) return true; runahead_error(runloop_st); @@ -4659,47 +4668,35 @@ static bool runahead_save_state(runloop_state_t *runloop_st) static bool runahead_load_state(runloop_state_t *runloop_st) { - bool okay = false; retro_ctx_serialize_info_t *serialize_info = (retro_ctx_serialize_info_t*) runloop_st->runahead_save_state_list->data[0]; bool last_dirty = runloop_st->input_is_dirty; + bool ret = + core_unserialize_special(serialize_info); - runloop_st->request_fast_savestate = true; - /* calling core_unserialize has side effects with - * netplay (it triggers transmitting your save state) - call retro_unserialize directly from the core instead */ - okay = runloop_st->current_core.retro_unserialize( - serialize_info->data_const, serialize_info->size); - - runloop_st->request_fast_savestate = false; runloop_st->input_is_dirty = last_dirty; - if (!okay) + if (!ret) runahead_error(runloop_st); - return okay; + return ret; } #if HAVE_DYNAMIC static bool runahead_load_state_secondary(void) { - bool okay = false; runloop_state_t *runloop_st = &runloop_state; settings_t *settings = config_get_ptr(); retro_ctx_serialize_info_t *serialize_info = (retro_ctx_serialize_info_t*)runloop_st->runahead_save_state_list->data[0]; - runloop_st->request_fast_savestate = true; - okay = - secondary_core_deserialize(settings, - serialize_info->data_const, (int)serialize_info->size); - runloop_st->request_fast_savestate = false; - - if (!okay) + if (!secondary_core_deserialize(settings, serialize_info->data_const, + serialize_info->size)) { runloop_st->runahead_secondary_core_available = false; runahead_error(runloop_st); + return false; } @@ -8391,6 +8388,26 @@ bool core_unserialize(retro_ctx_serialize_info_t *info) return true; } +bool core_unserialize_special(retro_ctx_serialize_info_t *info) +{ + bool ret; + runloop_state_t *runloop_st = &runloop_state; + + if (!info) + return false; + + runloop_st->request_special_savestate = true; + ret = runloop_st->current_core.retro_unserialize(info->data_const, info->size); + runloop_st->request_special_savestate = false; + +#ifdef HAVE_NETWORKING + if (ret) + netplay_driver_ctl(RARCH_NETPLAY_CTL_LOAD_SAVESTATE, info); +#endif + + return ret; +} + bool core_serialize(retro_ctx_serialize_info_t *info) { runloop_state_t *runloop_st = &runloop_state; @@ -8399,6 +8416,21 @@ bool core_serialize(retro_ctx_serialize_info_t *info) return true; } +bool core_serialize_special(retro_ctx_serialize_info_t *info) +{ + bool ret; + runloop_state_t *runloop_st = &runloop_state; + + if (!info) + return false; + + runloop_st->request_special_savestate = true; + ret = runloop_st->current_core.retro_serialize(info->data, info->size); + runloop_st->request_special_savestate = false; + + return ret; +} + bool core_serialize_size(retro_ctx_size_info_t *info) { runloop_state_t *runloop_st = &runloop_state; @@ -8408,6 +8440,20 @@ bool core_serialize_size(retro_ctx_size_info_t *info) return true; } +bool core_serialize_size_special(retro_ctx_size_info_t *info) +{ + runloop_state_t *runloop_st = &runloop_state; + + if (!info) + return false; + + runloop_st->request_special_savestate = true; + info->size = runloop_st->current_core.retro_serialize_size(); + runloop_st->request_special_savestate = false; + + return true; +} + uint64_t core_serialization_quirks(void) { runloop_state_t *runloop_st = &runloop_state; diff --git a/runloop.h b/runloop.h index 41792ce33a..627fbc8f02 100644 --- a/runloop.h +++ b/runloop.h @@ -292,9 +292,7 @@ struct runloop bool runahead_secondary_core_available; bool runahead_force_input_dirty; #endif -#if defined(HAVE_RUNAHEAD) || defined(HAVE_NETWORKING) - bool request_fast_savestate; -#endif + bool request_special_savestate; #ifdef HAVE_PATCH bool patch_blocked; #endif