Rewind: Fixed some edge cases

This commit is contained in:
Souryo 2017-05-13 21:18:55 -04:00
parent 1852f87934
commit a7b410666b
6 changed files with 74 additions and 46 deletions

View File

@ -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;
}

View File

@ -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()
{

View File

@ -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<uint8_t>& compressedState)

View File

@ -6,7 +6,7 @@ class RewindData
{
private:
vector<uint8_t> SaveStateData;
uint32_t OriginalSaveStateSize;
uint32_t OriginalSaveStateSize = 0;
void CompressState(string stateData, vector<uint8_t> &compressedState);

View File

@ -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);
}
}

View File

@ -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);