Skip to content
This repository has been archived by the owner on Oct 4, 2020. It is now read-only.

Commit

Permalink
Rewind: Fixed some edge cases
Browse files Browse the repository at this point in the history
  • Loading branch information
SourMesen committed May 14, 2017
1 parent 1852f87 commit a7b4106
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 46 deletions.
11 changes: 11 additions & 0 deletions Core/EmulationSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
5 changes: 1 addition & 4 deletions Core/EmulationSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -665,10 +665,7 @@ class EmulationSettings
return _rewindSpeed;
}

static void SetRewindBufferSize(uint32_t seconds)
{
_rewindBufferSize = seconds;
}
static void SetRewindBufferSize(uint32_t seconds);

static uint32_t GetRewindBufferSize()
{
Expand Down
12 changes: 7 additions & 5 deletions Core/RewindData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion Core/RewindData.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
88 changes: 52 additions & 36 deletions Core/RewindManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,48 +25,62 @@ 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++;
}
}
}

void RewindManager::AddHistoryBlock()
{
uint32_t maxHistorySize = EmulationSettings::GetRewindBufferSize() * 120;
if(maxHistorySize == 0) {
_history.clear();
} else {
while(_history.size() > maxHistorySize) {
_history.pop_front();
}
while(_history.size() > maxHistorySize) {
_history.pop_front();
}

if(_currentHistory.FrameCount > 0) {
_history.push_back(_currentHistory);
}
_currentHistory = RewindData();
_currentHistory.SaveState();
if(_currentHistory.FrameCount > 0) {
_history.push_back(_currentHistory);
}
_currentHistory = RewindData();
_currentHistory.SaveState();
}

void RewindManager::PopHistory()
Expand Down Expand Up @@ -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();

_currentHistory = _historyBackup.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();
}
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
Expand Down Expand Up @@ -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);
}
}
Expand Down
2 changes: 2 additions & 0 deletions Core/RewindManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class RewindManager : public INotificationListener
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);

Expand Down

0 comments on commit a7b4106

Please sign in to comment.