diff --git a/network/netplay/netplay_frontend.c b/network/netplay/netplay_frontend.c index 2ab6a61638..489c5cfc6d 100644 --- a/network/netplay/netplay_frontend.c +++ b/network/netplay/netplay_frontend.c @@ -1924,8 +1924,9 @@ static bool netplay_handshake(netplay_t *netplay, return false; } - if (connection->mode >= NETPLAY_CONNECTION_CONNECTED && - !netplay_send_cur_input(netplay, connection)) + if (connection->mode >= NETPLAY_CONNECTION_CONNECTED + && netplay->modus == NETPLAY_MODUS_INPUT_FRAME_SYNC + && !netplay_send_cur_input(netplay, connection)) return false; return ret; @@ -3551,7 +3552,7 @@ static bool netplay_sync_pre_frame(netplay_t *netplay) if (netplay->run_frame_count > 0 && netplay_delta_frame_ready(netplay, &netplay->buffer[netplay->run_ptr], netplay->run_frame_count) - && !networking_driver_st.core_netpacket_interface) + && netplay->modus == NETPLAY_MODUS_INPUT_FRAME_SYNC) { /* Don't serialize until it's safe. */ if (!(netplay->quirks & NETPLAY_QUIRK_INITIALIZATION)) @@ -3663,21 +3664,17 @@ process: } /** - * netplay_sync_post_frame + * netplay_sync_input_post_frame * @netplay : pointer to netplay object * @stalled : true if we're currently stalled * * Post-frame for Netplay synchronization. * We check if we have new input and replay from recorded input. */ -static void netplay_sync_post_frame(netplay_t *netplay, bool stalled) +static void netplay_sync_input_post_frame(netplay_t *netplay, bool stalled) { uint32_t lo_frame_count, hi_frame_count; - /* When a core uses the netpacket interface frames are not synced */ - if (networking_driver_st.core_netpacket_interface) - return; - /* Unless we're stalling, we've just finished running a frame */ if (!stalled) { @@ -3764,7 +3761,7 @@ static void netplay_sync_post_frame(netplay_t *netplay, bool stalled) /* Now replay the real input if we've gotten ahead of it */ if ((netplay->force_rewind || netplay->replay_frame_count < netplay->run_frame_count) - && !networking_driver_st.core_netpacket_interface) + && netplay->modus == NETPLAY_MODUS_INPUT_FRAME_SYNC) { retro_ctx_serialize_info_t serial_info; @@ -4201,10 +4198,6 @@ static bool send_input_frame(netplay_t *netplay, struct delta_frame *dframe, buffer[2] = htonl(dframe->frame); buffer[3] = htonl(client_num); - /* When a core uses the netpacket interface input is not shared */ - if (networking_driver_st.core_netpacket_interface) - return true; - /* Add the device data */ devices = netplay->client_devices[client_num]; for (device = 0; device < MAX_INPUT_DEVICES; device++) @@ -4775,7 +4768,7 @@ static void handle_play_spectate(netplay_t *netplay, if (settings->bools.netplay_allow_slaves) { /* Slave mode unused when core uses netpacket interface */ - if (networking_driver_st.core_netpacket_interface) + if (netplay->modus == NETPLAY_MODUS_CORE_PACKET_INTERFACE) slave = false; else if (settings->bools.netplay_require_slaves) slave = true; @@ -5544,9 +5537,9 @@ static bool netplay_get_cmd(netplay_t *netplay, /* A change to me! */ if (mode & NETPLAY_CMD_MODE_BIT_PLAYING) { - /* When a core uses the netpacket interface this is valid */ + /* When a core uses the netpacket interface this is OK */ if (frame != netplay->server_frame_count - && !networking_driver_st.core_netpacket_interface) + && netplay->modus != NETPLAY_MODUS_CORE_PACKET_INTERFACE) { RARCH_ERR("[Netplay] Received mode change out of order.\n"); return netplay_cmd_nak(netplay, connection); @@ -5575,61 +5568,64 @@ static bool netplay_get_cmd(netplay_t *netplay, netplay->read_ptr[client_num] = netplay->server_ptr; netplay->read_frame_count[client_num] = netplay->server_frame_count; - /* Fix up current frame info */ - if (frame <= netplay->self_frame_count && - netplay->self_mode == NETPLAY_CONNECTION_PLAYING) + if (netplay->modus == NETPLAY_MODUS_INPUT_FRAME_SYNC) { - /* It wanted past frames, better send 'em! */ - START(netplay->server_ptr); - while (dframe->used && dframe->frame <= netplay->self_frame_count) + /* Fix up current frame info */ + if (frame <= netplay->self_frame_count && + netplay->self_mode == NETPLAY_CONNECTION_PLAYING) { - for (device = 0; device < MAX_INPUT_DEVICES; device++) + /* It wanted past frames, better send 'em! */ + START(netplay->server_ptr); + while (dframe->used && dframe->frame <= netplay->self_frame_count) { - uint32_t dsize; - netplay_input_state_t istate; - if (!(devices & (1<real_input[device], client_num, dsize, - false, false); - if (!istate) - continue; - memset(istate->data, 0, dsize*sizeof(uint32_t)); - } - dframe->have_local = true; - dframe->have_real[client_num] = true; - send_input_frame(netplay, dframe, connection, NULL, client_num, false); - if (dframe->frame == netplay->self_frame_count) break; - NEXT(); - } - } - else - { - uint32_t frame_count; - - /* It wants future frames, make sure we don't capture or send intermediate ones */ - START(netplay->self_ptr); - frame_count = netplay->self_frame_count; - - do - { - if (!dframe->used) - { - /* Make sure it's ready */ - if (!netplay_delta_frame_ready(netplay, dframe, frame_count)) + for (device = 0; device < MAX_INPUT_DEVICES; device++) { - RARCH_ERR("[Netplay] Received mode change but delta frame isn't ready!\n"); - return netplay_cmd_nak(netplay, connection); + uint32_t dsize; + netplay_input_state_t istate; + if (!(devices & (1<real_input[device], client_num, dsize, + false, false); + if (!istate) + continue; + memset(istate->data, 0, dsize*sizeof(uint32_t)); } + dframe->have_local = true; + dframe->have_real[client_num] = true; + send_input_frame(netplay, dframe, connection, NULL, client_num, false); + if (dframe->frame == netplay->self_frame_count) break; + NEXT(); } + } + else + { + uint32_t frame_count; - dframe->have_local = true; + /* It wants future frames, make sure we don't capture or send intermediate ones */ + START(netplay->self_ptr); + frame_count = netplay->self_frame_count; - /* Go on to the next delta frame */ - NEXT(); - frame_count++; - } while (frame_count < frame); + do + { + if (!dframe->used) + { + /* Make sure it's ready */ + if (!netplay_delta_frame_ready(netplay, dframe, frame_count)) + { + RARCH_ERR("[Netplay] Received mode change but delta frame isn't ready!\n"); + return netplay_cmd_nak(netplay, connection); + } + } + + dframe->have_local = true; + + /* Go on to the next delta frame */ + NEXT(); + frame_count++; + } while (frame_count < frame); + } } /* Announce it */ @@ -5661,9 +5657,9 @@ static bool netplay_get_cmd(netplay_t *netplay, /* Somebody else is joining or parting */ if (mode & NETPLAY_CMD_MODE_BIT_PLAYING) { - /* When a core uses the netpacket interface this is valid */ + /* When a core uses the netpacket interface this is OK */ if (frame != netplay->server_frame_count - && !networking_driver_st.core_netpacket_interface) + && netplay->modus != NETPLAY_MODUS_CORE_PACKET_INTERFACE) { RARCH_ERR("[Netplay] Received mode change out of order.\n"); return netplay_cmd_nak(netplay, connection); @@ -6810,7 +6806,7 @@ static bool netplay_init_serialization(netplay_t *netplay) if (netplay->state_size) return true; - if (networking_driver_st.core_netpacket_interface) + if (netplay->modus == NETPLAY_MODUS_CORE_PACKET_INTERFACE) { /* max core netpacket size is 64 kb, hold 2 of them */ netplay->state_size = 64*1024*2; @@ -7018,7 +7014,8 @@ static void netplay_free(netplay_t *netplay) static netplay_t *netplay_new(const char *server, const char *mitm, uint16_t port, const char *mitm_session, uint32_t check_frames, const struct retro_callbacks *cb, - bool nat_traversal, const char *nick, uint32_t quirks) + bool nat_traversal, const char *nick, uint32_t quirks, + enum netplay_modus modus) { netplay_t *netplay = (netplay_t*)calloc(1, sizeof(*netplay)); @@ -7029,6 +7026,7 @@ static netplay_t *netplay_new(const char *server, const char *mitm, netplay->check_frames = check_frames; netplay->cbs = *cb; netplay->quirks = quirks; + netplay->modus = modus; netplay->crcs_valid = true; netplay->listen_fd = -1; netplay->next_announce = -1; @@ -7201,7 +7199,7 @@ static void netplay_frontend_paused(netplay_t *netplay, bool paused) /* When a core uses the netpacket interface netplay doesn't control pause. * We need this because even if RARCH_NETPLAY_CTL_ALLOW_PAUSE returns false * on some platforms the frontend may try to force netplay to pause. */ - if (networking_driver_st.core_netpacket_interface) + if (netplay->modus == NETPLAY_MODUS_CORE_PACKET_INTERFACE) return; netplay->local_paused = paused; @@ -7327,10 +7325,6 @@ void netplay_load_savestate(netplay_t *netplay, { retro_ctx_serialize_info_t tmp_serial_info = {0}; - /* When a core uses the netpacket interface save states are not shared */ - if (networking_driver_st.core_netpacket_interface) - return; - if (!serial_info) save = true; @@ -7663,12 +7657,20 @@ static bool netplay_poll(netplay_t *netplay, bool block_libretro_input) size_t i; /* Use simplified polling loop when a core uses the netpacket interface. */ - if (networking_driver_st.core_netpacket_interface) + if (netplay->modus == NETPLAY_MODUS_CORE_PACKET_INTERFACE) { if (netplay->self_mode == NETPLAY_CONNECTION_NONE) return true; + + /* Read netplay input. */ netplay_poll_net_input(netplay); - if (networking_driver_st.core_netpacket_interface->poll + + /* Handle any delayed state changes */ + if (netplay->is_server) + netplay_delayed_state_change(netplay); + + if (networking_driver_st.core_netpacket_interface + && networking_driver_st.core_netpacket_interface->poll && netplay->self_mode == NETPLAY_CONNECTION_PLAYING) networking_driver_st.core_netpacket_interface->poll(); return true; @@ -8468,12 +8470,13 @@ static bool netplay_pre_frame(netplay_t *netplay) } } - if ((netplay->stall || netplay->remote_paused) && - (!netplay->is_server || netplay->connected_players > 1)) + if ((netplay->stall || netplay->remote_paused) + && (!netplay->is_server || netplay->connected_players > 1) + && netplay->modus == NETPLAY_MODUS_INPUT_FRAME_SYNC) { /* We may have received data even if we're stalled, * so run post-frame sync. */ - netplay_sync_post_frame(netplay, true); + netplay_sync_input_post_frame(netplay, true); return false; } @@ -8492,8 +8495,12 @@ static void netplay_post_frame(netplay_t *netplay) { size_t i; - netplay_update_unread_ptr(netplay); - netplay_sync_post_frame(netplay, false); + /* When a core uses the netpacket interface frames are not synced */ + if (netplay->modus == NETPLAY_MODUS_INPUT_FRAME_SYNC) + { + netplay_update_unread_ptr(netplay); + netplay_sync_input_post_frame(netplay, false); + } for (i = 0; i < netplay->connections_size; i++) { @@ -8558,6 +8565,7 @@ bool init_netplay(const char *server, unsigned port, const char *mitm_session) net_driver_state_t *net_st = &networking_driver_st; struct netplay_room *host_room = &net_st->host_room; const char *mitm = NULL; + enum netplay_modus modus = NETPLAY_MODUS_CORE_PACKET_INTERFACE; if (!(net_st->flags & NET_DRIVER_ST_FLAG_NETPLAY_ENABLED)) return false; @@ -8568,10 +8576,13 @@ bool init_netplay(const char *server, unsigned port, const char *mitm_session) serialization_quirks = core_serialization_quirks(); + if (net_st->core_netpacket_interface) + modus = NETPLAY_MODUS_CORE_PACKET_INTERFACE; + if ((!core_info_current_supports_netplay() || serialization_quirks & (RETRO_SERIALIZATION_QUIRK_INCOMPLETE | RETRO_SERIALIZATION_QUIRK_SINGLE_SESSION)) - && !net_st->core_netpacket_interface) + && modus != NETPLAY_MODUS_CORE_PACKET_INTERFACE) { RARCH_ERR("[Netplay] %s\n", msg_hash_to_str(MSG_NETPLAY_UNSUPPORTED)); runloop_msg_queue_push( @@ -8642,7 +8653,7 @@ bool init_netplay(const char *server, unsigned port, const char *mitm_session) : #endif settings->paths.username, - quirks); + quirks, modus); if (!netplay) goto failure; @@ -9030,7 +9041,7 @@ bool netplay_driver_ctl(enum rarch_netplay_ctl_state state, void *data) break; case RARCH_NETPLAY_CTL_GAME_WATCH: - if (netplay && net_st->core_netpacket_interface == NULL) + if (netplay && netplay->modus != NETPLAY_MODUS_CORE_PACKET_INTERFACE) netplay_toggle_play_spectate(netplay); else ret = false; @@ -9044,9 +9055,9 @@ bool netplay_driver_ctl(enum rarch_netplay_ctl_state state, void *data) break; case RARCH_NETPLAY_CTL_ALLOW_PAUSE: - ret = (!netplay || netplay->allow_pausing) && - ((net_st->core_netpacket_interface == NULL) - || !netplay_have_any_active_connection(netplay)); + ret = (!netplay || (netplay->allow_pausing && + (netplay->modus != NETPLAY_MODUS_CORE_PACKET_INTERFACE || + !netplay_have_any_active_connection(netplay)))); break; case RARCH_NETPLAY_CTL_PAUSE: @@ -9061,13 +9072,13 @@ bool netplay_driver_ctl(enum rarch_netplay_ctl_state state, void *data) break; case RARCH_NETPLAY_CTL_LOAD_SAVESTATE: - if (netplay && !net_st->core_netpacket_interface) + if (netplay && netplay->modus != NETPLAY_MODUS_CORE_PACKET_INTERFACE) netplay_load_savestate(netplay, (retro_ctx_serialize_info_t*)data, true); break; case RARCH_NETPLAY_CTL_RESET: - if (netplay && !net_st->core_netpacket_interface) + if (netplay && netplay->modus != NETPLAY_MODUS_CORE_PACKET_INTERFACE) netplay_core_reset(netplay); break; @@ -9084,11 +9095,13 @@ bool netplay_driver_ctl(enum rarch_netplay_ctl_state state, void *data) break; case RARCH_NETPLAY_CTL_DESYNC_PUSH: - if (net_st->core_netpacket_interface - && netplay_have_any_active_connection(netplay)) - ret = false; - else if (netplay) - netplay->desync++; + if (netplay) + { + if (netplay->modus != NETPLAY_MODUS_CORE_PACKET_INTERFACE) + netplay->desync++; + else if (netplay_have_any_active_connection(netplay)) + ret = false; + } break; case RARCH_NETPLAY_CTL_DESYNC_POP: @@ -9148,6 +9161,13 @@ bool netplay_driver_ctl(enum rarch_netplay_ctl_state state, void *data) break; case RARCH_NETPLAY_CTL_SET_CORE_PACKET_INTERFACE: + if (!net_st->core_netpacket_interface && data && netplay) + { + /* it's too late to enable the interface */ + ret = false; + break; + } + if (net_st->core_netpacket_interface) { free(net_st->core_netpacket_interface); @@ -9172,7 +9192,8 @@ bool netplay_driver_ctl(enum rarch_netplay_ctl_state state, void *data) break; case RARCH_NETPLAY_CTL_ALLOW_TIMESKIP: - ret = ((net_st->core_netpacket_interface == NULL) + ret = (!netplay + || netplay->modus != NETPLAY_MODUS_CORE_PACKET_INTERFACE || !netplay_have_any_active_connection(netplay)); break;