From 76f0895d98eb4243d37595482cafa21cead1e928 Mon Sep 17 00:00:00 2001 From: Nikhil Narayana Date: Mon, 30 May 2022 12:33:51 -0700 Subject: [PATCH] possible desync fixes --- Source/Core/Core/HW/EXI/EXI_DeviceSlippi.cpp | 10 ++-- Source/Core/Core/Slippi/SlippiNetplay.cpp | 52 +++++++------------- 2 files changed, 23 insertions(+), 39 deletions(-) diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.cpp index 209796a6a3..dea9f48a3f 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.cpp +++ b/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.cpp @@ -1662,7 +1662,7 @@ bool CEXISlippi::shouldSkipOnlineFrame(s32 frame, s32 finalizedFrame) isCurrentlySkipping = true; int maxSkipFrames = frame <= 120 ? 5 : 1; // On early frames, support skipping more frames - framesToSkip = ((offsetUs - 10000) / 16683) + 1; + framesToSkip = ((offsetUs - t1) / frameTime) + 1; framesToSkip = framesToSkip > maxSkipFrames ? maxSkipFrames : framesToSkip; // Only skip 5 frames max @@ -1732,9 +1732,7 @@ bool CEXISlippi::shouldAdvanceOnlineFrame(s32 frame) deviation = frameWindowMultiplier * -maxSlowDownAmount; } - // If we are behind (negative offset) we want to go above 100% run speed, so we need to subtract - // the deviation value - auto dynamicEmulationSpeed = 1.0f - deviation; + auto dynamicEmulationSpeed = 1.0f + deviation; SConfig::GetInstance().m_EmulationSpeed = dynamicEmulationSpeed; // SConfig::GetInstance().m_EmulationSpeed = 0.97f; // used for testing @@ -1867,6 +1865,7 @@ void CEXISlippi::prepareOpponentInputs(s32 frame, bool shouldSkip) int32_t latestFrame = results[i]->latestFrame; if (latestFrame > frame) latestFrame = frame; + latestFrameRead[i] = latestFrame; appendWordToBuffer(&m_read_queue, static_cast(latestFrame)); // INFO_LOG(SLIPPI_ONLINE, "Sending frame num %d for pIdx %d (offset: %d)", latestFrame, i, // offset[i]); @@ -1874,6 +1873,7 @@ void CEXISlippi::prepareOpponentInputs(s32 frame, bool shouldSkip) // Send the current frame for any unused player slots. for (int i = remotePlayerCount; i < SLIPPI_REMOTE_PLAYER_MAX; i++) { + latestFrameRead[i] = frame; appendWordToBuffer(&m_read_queue, static_cast(frame)); } @@ -1898,8 +1898,6 @@ void CEXISlippi::prepareOpponentInputs(s32 frame, bool shouldSkip) m_read_queue.insert(m_read_queue.end(), tx.begin(), tx.end()); } - slippi_netplay->DropOldRemoteInputs(frame); - // ERROR_LOG(SLIPPI_ONLINE, "EXI: [%d] %X %X %X %X %X %X %X %X", latestFrame, m_read_queue[5], // m_read_queue[6], m_read_queue[7], m_read_queue[8], m_read_queue[9], m_read_queue[10], // m_read_queue[11], m_read_queue[12]); diff --git a/Source/Core/Core/Slippi/SlippiNetplay.cpp b/Source/Core/Core/Slippi/SlippiNetplay.cpp index 56500c1f41..7f11b23de6 100644 --- a/Source/Core/Core/Slippi/SlippiNetplay.cpp +++ b/Source/Core/Core/Slippi/SlippiNetplay.cpp @@ -281,32 +281,37 @@ unsigned int SlippiNetplayClient::OnData(sf::Packet& packet, ENetPeer* peer) auto packetData = (u8*)packet.getData(); - INFO_LOG_FMT(SLIPPI_ONLINE, "Receiving a packet of inputs [{}]...", frame); + // INFO_LOG_FMT(SLIPPI_ONLINE, "Receiving a packet of inputs [{}]...", frame); - INFO_LOG_FMT(SLIPPI_ONLINE, "Receiving a packet of inputs from player {}({}) [{}]...", - packetPlayerPort, pIdx, frame); + // INFO_LOG_FMT(SLIPPI_ONLINE, "Receiving a packet of inputs from player {}({}) [{}]...", + // packetPlayerPort, pIdx, frame); - int32_t headFrame = remotePadQueue[pIdx].empty() ? 0 : remotePadQueue[pIdx].front()->frame; - int inputsToCopy = frame - headFrame; + s64 frame64 = static_cast(frame); + s32 headFrame = remotePadQueue[pIdx].empty() ? 0 : remotePadQueue[pIdx].front()->frame; + s64 inputsToCopy = frame64 - static_cast(headFrame); - // Not sure what the max is here. If we never ack frames it could get big... - if (inputsToCopy > 128) + // Check that the packet actually contains the data it claims to + if ((6 + inputsToCopy * SLIPPI_PAD_DATA_SIZE) > static_cast(packet.getDataSize())) { ERROR_LOG_FMT( SLIPPI_ONLINE, "Netplay packet too small to read pad buffer. Size: {}, Inputs: {}, MinSize: {}", - (int)packet.getDataSize(), inputsToCopy, 5 + inputsToCopy * SLIPPI_PAD_DATA_SIZE); + static_cast(packet.getDataSize()), inputsToCopy, + 6 + inputsToCopy * SLIPPI_PAD_DATA_SIZE); break; } - for (int i = inputsToCopy - 1; i >= 0; i--) + // Not sure what the max is here. If we never ack frames it could get big... + if (inputsToCopy > 128) { - auto pad = - std::make_unique(frame - i, pIdx, &packetData[6 + i * SLIPPI_PAD_DATA_SIZE]); - INFO_LOG(SLIPPI_ONLINE, "Rcv [%d] -> %02X %02X %02X %02X %02X %02X %02X %02X", pad->frame, - pad->padBuf[0], pad->padBuf[1], pad->padBuf[2], pad->padBuf[3], pad->padBuf[4], - pad->padBuf[5], pad->padBuf[6], pad->padBuf[7]); + ERROR_LOG_FMT(SLIPPI_ONLINE, "Netplay packet contained too many frames: {}", inputsToCopy); + break; + } + for (s64 i = inputsToCopy - 1; i >= 0; i--) + { + auto pad = std::make_unique(static_cast(frame64 - i), pIdx, + &packetData[6 + i * SLIPPI_PAD_DATA_SIZE]); remotePadQueue[pIdx].push_front(std::move(pad)); } } @@ -1199,28 +1204,9 @@ void SlippiNetplayClient::DropOldRemoteInputs(int32_t finalizedFrame) { std::lock_guard lk(pad_mutex); - // Remove pad reports that should no longer be needed, compute the lowest frame recieved by - // all remote players that can be safely dropped. - int lowestCommonFrame = 0; for (int i = 0; i < m_remotePlayerCount; i++) { - int playerFrame = 0; - for (auto it = remotePadQueue[i].begin(); it != remotePadQueue[i].end(); ++it) - { - if (it->get()->frame > playerFrame) - playerFrame = it->get()->frame; - } - - if (lowestCommonFrame == 0 || playerFrame < lowestCommonFrame) - lowestCommonFrame = playerFrame; - } - - for (int i = 0; i < m_remotePlayerCount; i++) - { - // INFO_LOG_FMT(SLIPPI_ONLINE, "remotePadQueue[{}] size: {}", i, remotePadQueue[i].size()); while (remotePadQueue[i].size() > 1 && remotePadQueue[i].back()->frame < finalizedFrame) - /*INFO_LOG_FMT(SLIPPI_ONLINE, "Popping inputs for frame {} from back of player {} queue", - remotePadQueue[i].back()->frame, i);*/ remotePadQueue[i].pop_back(); } }