From 64ea1c47d2415b9881e150fd0f9e57e7bed8c4cd Mon Sep 17 00:00:00 2001 From: r2dliu Date: Thu, 26 Nov 2020 21:26:23 -0500 Subject: [PATCH] update --- Externals/SlippiLib/SlippiGame.cpp | 25 ++++++++++++++++++++ Externals/SlippiLib/SlippiGame.h | 4 ++++ Source/Core/Core/HW/EXI/EXI_DeviceSlippi.cpp | 16 ++++++++++--- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/Externals/SlippiLib/SlippiGame.cpp b/Externals/SlippiLib/SlippiGame.cpp index b76d004970..4aec1a6ea5 100644 --- a/Externals/SlippiLib/SlippiGame.cpp +++ b/Externals/SlippiLib/SlippiGame.cpp @@ -270,6 +270,15 @@ namespace Slippi { } } + void handleFrameEnd(Game* game, uint32_t maxSize) { + int idx = 0; + + int32_t frameCount = readWord(data, idx, maxSize, 0); + int32_t lastFinalizedFrame = readWord(data, idx, maxSize, frameCount); + + game->lastFinalizedFrame = lastFinalizedFrame; + } + void handleGameEnd(Game* game, uint32_t maxSize) { int idx = 0; @@ -459,6 +468,9 @@ namespace Slippi { case EVENT_POST_FRAME_UPDATE: handlePostFrameUpdate(game.get(), payloadSize); break; + case EVENT_FRAME_END: + handleFrameEnd(game.get(), payloadSize); + break; case EVENT_GAME_END: handleGameEnd(game.get(), payloadSize); isProcessingComplete = true; @@ -530,6 +542,14 @@ namespace Slippi { return game->version; } + std::string SlippiGame::GetVersionString() + { + char version[30]; + sprintf(version, "%d.%d.%d", game->version[0], game->version[1], game->version[2]); + + return std::string(version); + } + FrameData* SlippiGame::GetFrame(int32_t frame) { // Get the frame we want return game->framesByIndex.at(frame); @@ -544,6 +564,11 @@ namespace Slippi { return game->frames[pos].get(); } + int32_t SlippiGame::GetLastFinalizedFrame() { + processData(); + return game->lastFinalizedFrame; + } + int32_t SlippiGame::GetLatestIndex() { processData(); return game->frameCount; diff --git a/Externals/SlippiLib/SlippiGame.h b/Externals/SlippiLib/SlippiGame.h index de76ea75c7..464fc1655f 100644 --- a/Externals/SlippiLib/SlippiGame.h +++ b/Externals/SlippiLib/SlippiGame.h @@ -16,6 +16,7 @@ namespace Slippi { const uint8_t EVENT_POST_FRAME_UPDATE = 0x38; const uint8_t EVENT_GAME_END = 0x39; const uint8_t EVENT_FRAME_START = 0x3A; + const uint8_t EVENT_FRAME_END = 0x3C; const uint8_t EVENT_GECKO_LIST = 0x3D; const uint8_t GAME_INFO_HEADER_SIZE = 78; @@ -100,6 +101,7 @@ namespace Slippi { bool areSettingsLoaded = false; int32_t frameCount; // Current/last frame count + int32_t lastFinalizedFrame = -124; //From OnGameEnd event uint8_t winCondition; @@ -122,8 +124,10 @@ namespace Slippi { bool AreSettingsLoaded(); bool DoesFrameExist(int32_t frame); std::array GetVersion(); + std::string GetVersionString(); FrameData* GetFrame(int32_t frame); FrameData* GetFrameAt(uint32_t pos); + int32_t GetLastFinalizedFrame(); int32_t GetLatestIndex(); GameSettings* GetSettings(); bool DoesPlayerExist(int8_t port); diff --git a/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.cpp b/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.cpp index 1579385891..773137d44b 100644 --- a/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.cpp +++ b/Source/Core/Core/HW/EXI/EXI_DeviceSlippi.cpp @@ -1132,9 +1132,20 @@ bool CEXISlippi::checkFrameFullyFetched(s32 frameIndex) Slippi::FrameData* frame = m_current_game->GetFrame(frameIndex); + version::Semver200_version lastFinalizedVersion("3.7.0"); + version::Semver200_version currentVersion(m_current_game->GetVersionString()); + + bool frameIsFinalized = true; + if (currentVersion >= lastFinalizedVersion) + { + // If latest finalized frame should exist, check it as well. This will prevent us + // from loading a non-committed frame when mirroring a rollback game + frameIsFinalized = m_current_game->GetLastFinalizedFrame() >= frameIndex; + } + // This flag is set to true after a post frame update has been received. At that point // we know we have received all of the input data for the frame - return frame->inputsFullyFetched; + return frame->inputsFullyFetched && frameIsFinalized; } void CEXISlippi::prepareFrameData(u8* payload) @@ -1175,9 +1186,8 @@ void CEXISlippi::prepareFrameData(u8* payload) // (this is the last frame, in that case) auto isFrameFound = m_current_game->DoesFrameExist(frameIndex); g_playbackStatus->lastFrame = m_current_game->GetLatestIndex(); - auto isNextFrameFound = g_playbackStatus->lastFrame > frameIndex; auto isFrameComplete = checkFrameFullyFetched(frameIndex); - auto isFrameReady = isFrameFound && (isProcessingComplete || isNextFrameFound || isFrameComplete); + auto isFrameReady = isFrameFound && (isProcessingComplete || isFrameComplete); // If there is a startFrame configured, manage the fast-forward flag if (watchSettings.startFrame > Slippi::GAME_FIRST_FRAME)