From a7b410666bfef1d22e8f155ec5488572b4fb8ead Mon Sep 17 00:00:00 2001 From: Souryo Date: Sat, 13 May 2017 21:18:55 -0400 Subject: [PATCH] Rewind: Fixed some edge cases --- Core/EmulationSettings.cpp | 11 +++++ Core/EmulationSettings.h | 5 +-- Core/RewindData.cpp | 12 +++--- Core/RewindData.h | 2 +- Core/RewindManager.cpp | 88 ++++++++++++++++++++++---------------- Core/RewindManager.h | 2 + 6 files changed, 74 insertions(+), 46 deletions(-) diff --git a/Core/EmulationSettings.cpp b/Core/EmulationSettings.cpp index 47c21580..434b4ce1 100644 --- a/Core/EmulationSettings.cpp +++ b/Core/EmulationSettings.cpp @@ -2,6 +2,7 @@ #include "EmulationSettings.h" #include "Console.h" #include "VsControlManager.h" +#include "RewindManager.h" //Version 0.8.1 uint16_t EmulationSettings::_versionMajor = 0; @@ -103,3 +104,13 @@ void EmulationSettings::SetEqualizerBands(double *bands, uint32_t bandCount) } Console::Resume(); } + +void EmulationSettings::SetRewindBufferSize(uint32_t seconds) +{ + if(seconds == 0 || _rewindBufferSize == 0) { + Console::Pause(); + RewindManager::ClearBuffer(); + Console::Resume(); + } + _rewindBufferSize = seconds; +} \ No newline at end of file diff --git a/Core/EmulationSettings.h b/Core/EmulationSettings.h index f4166d11..2b0df6e8 100644 --- a/Core/EmulationSettings.h +++ b/Core/EmulationSettings.h @@ -665,10 +665,7 @@ public: return _rewindSpeed; } - static void SetRewindBufferSize(uint32_t seconds) - { - _rewindBufferSize = seconds; - } + static void SetRewindBufferSize(uint32_t seconds); static uint32_t GetRewindBufferSize() { diff --git a/Core/RewindData.cpp b/Core/RewindData.cpp index 3152a837..a847ffd8 100644 --- a/Core/RewindData.cpp +++ b/Core/RewindData.cpp @@ -5,11 +5,13 @@ void RewindData::LoadState() { - unsigned long length = OriginalSaveStateSize; - uint8_t* buffer = new uint8_t[length]; - uncompress(buffer, &length, SaveStateData.data(), (unsigned long)SaveStateData.size()); - Console::LoadState(buffer, length); - delete[] buffer; + if(SaveStateData.size() > 0 && OriginalSaveStateSize > 0) { + unsigned long length = OriginalSaveStateSize; + uint8_t* buffer = new uint8_t[length]; + uncompress(buffer, &length, SaveStateData.data(), (unsigned long)SaveStateData.size()); + Console::LoadState(buffer, length); + delete[] buffer; + } } void RewindData::CompressState(string stateData, vector& compressedState) diff --git a/Core/RewindData.h b/Core/RewindData.h index e372c863..a7fda34f 100644 --- a/Core/RewindData.h +++ b/Core/RewindData.h @@ -6,7 +6,7 @@ class RewindData { private: vector SaveStateData; - uint32_t OriginalSaveStateSize; + uint32_t OriginalSaveStateSize = 0; void CompressState(string stateData, vector &compressedState); diff --git a/Core/RewindManager.cpp b/Core/RewindManager.cpp index 39a7a621..e4b6bcdb 100644 --- a/Core/RewindManager.cpp +++ b/Core/RewindManager.cpp @@ -25,28 +25,46 @@ RewindManager::~RewindManager() MessageManager::UnregisterNotificationListener(this); } +void RewindManager::ClearBuffer() +{ + if(_instance) { + _instance->_history.clear(); + _instance->_historyBackup.clear(); + _instance->_currentHistory = RewindData(); + _instance->_framesToFastForward = 0; + _instance->_videoHistory.clear(); + _instance->_videoHistoryBuilder.clear(); + _instance->_audioHistory.clear(); + _instance->_audioHistoryBuilder.clear(); + _instance->_rewindState = RewindState::Stopped; + _instance->AddHistoryBlock(); + } +} + void RewindManager::ProcessNotification(ConsoleNotificationType type, void * parameter) { if(type == ConsoleNotificationType::PpuFrameDone) { - if(_rewindState >= RewindState::Starting) { - _currentHistory.FrameCount--; - } else if(_rewindState == RewindState::Stopping) { - _framesToFastForward--; - _currentHistory.FrameCount++; - if(_framesToFastForward == 0) { - for(int i = 0; i < 4; i++) { - size_t numberToRemove = _currentHistory.InputLogs[i].size(); - _currentHistory.InputLogs[i] = _historyBackup.front().InputLogs[i]; - for(size_t j = 0; j < numberToRemove; j++) { - _currentHistory.InputLogs[i].pop_back(); + if(EmulationSettings::GetRewindBufferSize() > 0) { + if(_rewindState >= RewindState::Starting) { + _currentHistory.FrameCount--; + } else if(_rewindState == RewindState::Stopping) { + _framesToFastForward--; + _currentHistory.FrameCount++; + if(_framesToFastForward == 0) { + for(int i = 0; i < 4; i++) { + size_t numberToRemove = _currentHistory.InputLogs[i].size(); + _currentHistory.InputLogs[i] = _historyBackup.front().InputLogs[i]; + for(size_t j = 0; j < numberToRemove; j++) { + _currentHistory.InputLogs[i].pop_back(); + } } + _historyBackup.clear(); + _rewindState = RewindState::Stopped; + EmulationSettings::SetEmulationSpeed(100); } - _historyBackup.clear(); - _rewindState = RewindState::Stopped; - EmulationSettings::SetEmulationSpeed(100); + } else { + _currentHistory.FrameCount++; } - } else { - _currentHistory.FrameCount++; } } } @@ -54,19 +72,15 @@ void RewindManager::ProcessNotification(ConsoleNotificationType type, void * par void RewindManager::AddHistoryBlock() { uint32_t maxHistorySize = EmulationSettings::GetRewindBufferSize() * 120; - if(maxHistorySize == 0) { - _history.clear(); - } else { - while(_history.size() > maxHistorySize) { - _history.pop_front(); - } - - if(_currentHistory.FrameCount > 0) { - _history.push_back(_currentHistory); - } - _currentHistory = RewindData(); - _currentHistory.SaveState(); + while(_history.size() > maxHistorySize) { + _history.pop_front(); } + + if(_currentHistory.FrameCount > 0) { + _history.push_back(_currentHistory); + } + _currentHistory = RewindData(); + _currentHistory.SaveState(); } void RewindManager::PopHistory() @@ -114,15 +128,17 @@ void RewindManager::Stop() Console::Pause(); if(_rewindState == RewindState::Started) { //Move back to the save state containing the frame currently shown on the screen - _framesToFastForward = (uint32_t)_videoHistory.size() + _historyBackup.front().FrameCount; - do { - _history.push_back(_historyBackup.front()); - _framesToFastForward -= _historyBackup.front().FrameCount; - _historyBackup.pop_front(); + if(_historyBackup.size() > 1) { + _framesToFastForward = (uint32_t)_videoHistory.size() + _historyBackup.front().FrameCount; + do { + _history.push_back(_historyBackup.front()); + _framesToFastForward -= _historyBackup.front().FrameCount; + _historyBackup.pop_front(); - _currentHistory = _historyBackup.front(); + _currentHistory = _historyBackup.front(); + } + while(_framesToFastForward > RewindManager::BufferSize && _historyBackup.size() > 1); } - while(_framesToFastForward > RewindManager::BufferSize); } else { //We started rewinding, but didn't actually visually rewind anything yet //Move back to the save state containing the frame currently shown on the screen @@ -218,7 +234,7 @@ bool RewindManager::ProcessAudio(int16_t * soundBuffer, uint32_t sampleCount, ui void RewindManager::RecordInput(uint8_t port, uint8_t input) { - if(_instance && _instance->_rewindState == RewindState::Stopped) { + if(EmulationSettings::GetRewindBufferSize() > 0 && _instance && _instance->_rewindState == RewindState::Stopped) { _instance->_currentHistory.InputLogs[port].push_back(input); } } diff --git a/Core/RewindManager.h b/Core/RewindManager.h index b773710c..45148392 100644 --- a/Core/RewindManager.h +++ b/Core/RewindManager.h @@ -45,6 +45,8 @@ public: void ProcessNotification(ConsoleNotificationType type, void* parameter) override; void ProcessEndOfFrame(); + static void ClearBuffer(); + static void RecordInput(uint8_t port, uint8_t input); static uint8_t GetInput(uint8_t port);