diff --git a/src/core/config.c b/src/core/config.c
index 17de20d46..6dfb6ea8c 100644
--- a/src/core/config.c
+++ b/src/core/config.c
@@ -307,7 +307,6 @@ void mCoreConfigMap(const struct mCoreConfig* config, struct mCoreOptions* opts)
_lookupIntValue(config, "frameskip", &opts->frameskip);
_lookupIntValue(config, "volume", &opts->volume);
_lookupIntValue(config, "rewindBufferCapacity", &opts->rewindBufferCapacity);
- _lookupIntValue(config, "rewindBufferInterval", &opts->rewindBufferInterval);
_lookupFloatValue(config, "fpsTarget", &opts->fpsTarget);
unsigned audioBuffers;
if (_lookupUIntValue(config, "audioBuffers", &audioBuffers)) {
@@ -363,7 +362,6 @@ void mCoreConfigLoadDefaults(struct mCoreConfig* config, const struct mCoreOptio
ConfigurationSetIntValue(&config->defaultsTable, 0, "frameskip", opts->frameskip);
ConfigurationSetIntValue(&config->defaultsTable, 0, "rewindEnable", opts->rewindEnable);
ConfigurationSetIntValue(&config->defaultsTable, 0, "rewindBufferCapacity", opts->rewindBufferCapacity);
- ConfigurationSetIntValue(&config->defaultsTable, 0, "rewindBufferInterval", opts->rewindBufferInterval);
ConfigurationSetFloatValue(&config->defaultsTable, 0, "fpsTarget", opts->fpsTarget);
ConfigurationSetUIntValue(&config->defaultsTable, 0, "audioBuffers", opts->audioBuffers);
ConfigurationSetUIntValue(&config->defaultsTable, 0, "sampleRate", opts->sampleRate);
diff --git a/src/core/config.h b/src/core/config.h
index 27d12ca5e..806fadde3 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -25,7 +25,6 @@ struct mCoreOptions {
int frameskip;
bool rewindEnable;
int rewindBufferCapacity;
- int rewindBufferInterval;
float fpsTarget;
size_t audioBuffers;
unsigned sampleRate;
diff --git a/src/core/core.h b/src/core/core.h
index 78dc2ae6a..38655362c 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -145,6 +145,9 @@ void mCoreTakeScreenshot(struct mCore* core);
struct mCore* mCoreFindVF(struct VFile* vf);
enum mPlatform mCoreIsCompatible(struct VFile* vf);
+bool mCoreSaveStateNamed(struct mCore* core, struct VFile* vf, int flags);
+bool mCoreLoadStateNamed(struct mCore* core, struct VFile* vf, int flags);
+
void mCoreInitConfig(struct mCore* core, const char* port);
void mCoreLoadConfig(struct mCore* core);
void mCoreLoadForeignConfig(struct mCore* core, const struct mCoreConfig* config);
diff --git a/src/core/rewind.c b/src/core/rewind.c
new file mode 100644
index 000000000..e48b2eb8b
--- /dev/null
+++ b/src/core/rewind.c
@@ -0,0 +1,88 @@
+/* Copyright (c) 2013-2016 Jeffrey Pfau
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#include "rewind.h"
+
+#include "core/core.h"
+#include "util/patch-fast.h"
+#include "util/vfs.h"
+
+DEFINE_VECTOR(mCoreRewindPatches, struct PatchFast);
+
+void mCoreRewindContextInit(struct mCoreRewindContext* context, size_t entries) {
+ mCoreRewindPatchesInit(&context->patchMemory, entries);
+ size_t e;
+ for (e = 0; e < entries; ++e) {
+ initPatchFast(mCoreRewindPatchesAppend(&context->patchMemory));
+ }
+ context->previousState = VFileMemChunk(0, 0);
+ context->currentState = VFileMemChunk(0, 0);
+ context->size = 0;
+}
+
+void mCoreRewindContextDeinit(struct mCoreRewindContext* context) {
+ context->previousState->close(context->previousState);
+ context->currentState->close(context->currentState);
+ size_t s;
+ for (s = 0; s < mCoreRewindPatchesSize(&context->patchMemory); ++s) {
+ deinitPatchFast(mCoreRewindPatchesGetPointer(&context->patchMemory, s));
+ }
+ mCoreRewindPatchesDeinit(&context->patchMemory);
+}
+
+void mCoreRewindAppend(struct mCoreRewindContext* context, struct mCore* core) {
+ struct VFile* nextState = context->previousState;
+ ++context->current;
+ if (context->size < mCoreRewindPatchesSize(&context->patchMemory)) {
+ ++context->size;
+ }
+ if (context->current >= mCoreRewindPatchesSize(&context->patchMemory)) {
+ context->current = 0;
+ }
+ mCoreSaveStateNamed(core, nextState, 0);
+ struct PatchFast* patch = mCoreRewindPatchesGetPointer(&context->patchMemory, context->current);
+ size_t size2 = nextState->size(nextState);
+ size_t size = context->currentState->size(context->currentState);
+ if (size2 > size) {
+ context->currentState->truncate(context->currentState, size2);
+ size = size2;
+ }
+ void* current = context->currentState->map(context->currentState, size, MAP_READ);
+ void* next = nextState->map(nextState, size, MAP_READ);
+ diffPatchFast(patch, current, next, size);
+ context->currentState->unmap(context->currentState, current, size);
+ nextState->unmap(next, nextState, size);
+ context->previousState = context->currentState;
+ context->currentState = nextState;
+}
+
+bool mCoreRewindRestore(struct mCoreRewindContext* context, struct mCore* core) {
+ if (!context->size) {
+ return false;
+ }
+ --context->size;
+
+ struct PatchFast* patch = mCoreRewindPatchesGetPointer(&context->patchMemory, context->current);
+ size_t size2 = context->previousState->size(context->previousState);
+ size_t size = context->currentState->size(context->currentState);
+ if (size2 < size) {
+ size = size2;
+ }
+ void* current = context->currentState->map(context->currentState, size, MAP_READ);
+ void* previous = context->previousState->map(context->previousState, size, MAP_WRITE);
+ patch->d.applyPatch(&patch->d, current, size, previous, size);
+ context->currentState->unmap(context->currentState, current, size);
+ context->previousState->unmap(context->previousState, previous, size);
+ mCoreLoadStateNamed(core, context->previousState, 0);
+ struct VFile* nextState = context->previousState;
+ context->previousState = context->currentState;
+ context->currentState = nextState;
+
+ if (context->current == 0) {
+ context->current = mCoreRewindPatchesSize(&context->patchMemory);
+ }
+ --context->current;
+ return true;
+}
diff --git a/src/core/rewind.h b/src/core/rewind.h
new file mode 100644
index 000000000..50844c545
--- /dev/null
+++ b/src/core/rewind.h
@@ -0,0 +1,31 @@
+/* Copyright (c) 2013-2016 Jeffrey Pfau
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef M_CORE_REWIND_H
+#define M_CORE_REWIND_H
+
+#include "util/common.h"
+
+#include "util/vector.h"
+
+DECLARE_VECTOR(mCoreRewindPatches, struct PatchFast);
+
+struct VFile;
+struct mCoreRewindContext {
+ struct mCoreRewindPatches patchMemory;
+ size_t current;
+ size_t size;
+ struct VFile* previousState;
+ struct VFile* currentState;
+};
+
+void mCoreRewindContextInit(struct mCoreRewindContext*, size_t entries);
+void mCoreRewindContextDeinit(struct mCoreRewindContext*);
+
+struct mCore;
+void mCoreRewindAppend(struct mCoreRewindContext*, struct mCore*);
+bool mCoreRewindRestore(struct mCoreRewindContext*, struct mCore*);
+
+#endif
diff --git a/src/core/thread.c b/src/core/thread.c
index 177d94eed..27d5f835c 100644
--- a/src/core/thread.c
+++ b/src/core/thread.c
@@ -109,6 +109,10 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
core->setSync(core, &threadContext->sync);
core->reset(core);
+ if (core->opts.rewindEnable) {
+ mCoreRewindContextInit(&threadContext->rewind, core->opts.rewindBufferCapacity);
+ }
+
_changeState(threadContext, THREAD_RUNNING, true);
if (threadContext->startCallback) {
@@ -126,14 +130,14 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
_changeState(threadContext, THREAD_EXITING, false);
}
} else {
- while (threadContext->state == THREAD_RUNNING) {
+ while (threadContext->state <= THREAD_MAX_RUNNING) {
core->runLoop(core);
}
}
int resetScheduled = 0;
MutexLock(&threadContext->stateMutex);
- while (threadContext->state > THREAD_RUNNING && threadContext->state < THREAD_EXITING) {
+ while (threadContext->state > THREAD_MAX_RUNNING && threadContext->state < THREAD_EXITING) {
if (threadContext->state == THREAD_PAUSING) {
threadContext->state = THREAD_PAUSED;
ConditionWake(&threadContext->stateCond);
@@ -170,6 +174,10 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) {
_changeState(threadContext, THREAD_SHUTDOWN, false);
}
+ if (core->opts.rewindEnable) {
+ mCoreRewindContextDeinit(&threadContext->rewind);
+ }
+
if (threadContext->cleanCallback) {
threadContext->cleanCallback(threadContext);
}
@@ -422,6 +430,18 @@ void mCoreThreadPauseFromThread(struct mCoreThread* threadContext) {
mCoreSyncSetVideoSync(&threadContext->sync, frameOn);
}
+void mCoreThreadSetRewinding(struct mCoreThread* threadContext, bool rewinding) {
+ MutexLock(&threadContext->stateMutex);
+ _waitOnInterrupt(threadContext);
+ if (rewinding && threadContext->state == THREAD_RUNNING) {
+ threadContext->state = THREAD_REWINDING;
+ }
+ if (!rewinding && threadContext->state == THREAD_REWINDING) {
+ threadContext->state = THREAD_RUNNING;
+ }
+ MutexUnlock(&threadContext->stateMutex);
+}
+
#ifdef USE_PTHREADS
struct mCoreThread* mCoreThreadGet(void) {
pthread_once(&_contextOnce, _createTLS);
@@ -438,10 +458,41 @@ struct mCoreThread* mCoreThreadGet(void) {
}
#endif
+void mCoreThreadFrameStarted(struct mCoreThread* thread) {
+ if (!thread) {
+ return;
+ }
+ if (thread->core->opts.rewindEnable && thread->state != THREAD_REWINDING) {
+ mCoreRewindAppend(&thread->rewind, thread->core);
+ } else if (thread->state == THREAD_REWINDING) {
+ if (!mCoreRewindRestore(&thread->rewind, thread->core)) {
+ mCoreRewindAppend(&thread->rewind, thread->core);
+ }
+ }
+}
+
+void mCoreThreadFrameEnded(struct mCoreThread* thread) {
+ if (!thread) {
+ return;
+ }
+ if (thread->frameCallback) {
+ thread->frameCallback(thread);
+ }
+}
+
#else
struct mCoreThread* mCoreThreadGet(void) {
return NULL;
}
+
+void mCoreThreadFrameStarted(struct mCoreThread* thread) {
+ UNUSED(thread);
+}
+
+void mCoreThreadFrameEnded(struct mCoreThread* thread) {
+ UNUSED(thread);
+}
+
#endif
static void _mCoreLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) {
diff --git a/src/core/thread.h b/src/core/thread.h
index 9540c841b..c965ab8d2 100644
--- a/src/core/thread.h
+++ b/src/core/thread.h
@@ -9,6 +9,7 @@
#include "util/common.h"
#include "core/log.h"
+#include "core/rewind.h"
#include "core/sync.h"
#include "util/threading.h"
@@ -20,6 +21,8 @@ typedef void (*ThreadCallback)(struct mCoreThread* threadContext);
enum mCoreThreadState {
THREAD_INITIALIZED = -1,
THREAD_RUNNING = 0,
+ THREAD_REWINDING,
+ THREAD_MAX_RUNNING = THREAD_REWINDING,
THREAD_INTERRUPTED,
THREAD_INTERRUPTING,
THREAD_PAUSED,
@@ -61,6 +64,7 @@ struct mCoreThread {
void (*run)(struct mCoreThread*);
struct mCoreSync sync;
+ struct mCoreRewindContext rewind;
};
bool mCoreThreadStart(struct mCoreThread* threadContext);
@@ -84,7 +88,13 @@ bool mCoreThreadIsPaused(struct mCoreThread* threadContext);
void mCoreThreadTogglePause(struct mCoreThread* threadContext);
void mCoreThreadPauseFromThread(struct mCoreThread* threadContext);
+void mCoreThreadSetRewinding(struct mCoreThread* threadContext, bool);
+
struct mCoreThread* mCoreThreadGet(void);
+
+void mCoreThreadFrameStarted(struct mCoreThread*);
+void mCoreThreadFrameEnded(struct mCoreThread*);
+
struct mLogger* mCoreThreadLogger(void);
#endif
diff --git a/src/gb/video.c b/src/gb/video.c
index a38efce4d..91b857e22 100644
--- a/src/gb/video.c
+++ b/src/gb/video.c
@@ -175,6 +175,8 @@ int32_t GBVideoProcessEvents(struct GBVideo* video, int32_t cycles) {
if (video->p->memory.mbcType == GB_MBC7 && video->p->memory.rotation && video->p->memory.rotation->sample) {
video->p->memory.rotation->sample(video->p->memory.rotation);
}
+ struct mCoreThread* thread = mCoreThreadGet();
+ mCoreThreadFrameStarted(thread);
break;
case 2:
_cleanOAM(video, video->ly);
@@ -204,9 +206,7 @@ int32_t GBVideoProcessEvents(struct GBVideo* video, int32_t cycles) {
if (video->p->cpu->executionState == LR35902_CORE_FETCH) {
GBFrameEnded(video->p);
struct mCoreThread* thread = mCoreThreadGet();
- if (thread && thread->frameCallback) {
- thread->frameCallback(thread);
- }
+ mCoreThreadFrameEnded(thread);
video->nextFrame = GB_VIDEO_TOTAL_LENGTH;
} else {
video->nextFrame = 4 - ((video->p->cpu->executionState + 1) & 3);
diff --git a/src/gba/gba.c b/src/gba/gba.c
index ccdf28dd6..458f722f9 100644
--- a/src/gba/gba.c
+++ b/src/gba/gba.c
@@ -800,7 +800,8 @@ void GBABreakpoint(struct ARMCore* cpu, int immediate) {
void GBAFrameStarted(struct GBA* gba) {
UNUSED(gba);
- // TODO: Put back rewind
+ struct mCoreThread* thread = mCoreThreadGet();
+ mCoreThreadFrameStarted(thread);
}
void GBAFrameEnded(struct GBA* gba) {
@@ -831,13 +832,7 @@ void GBAFrameEnded(struct GBA* gba) {
}
struct mCoreThread* thread = mCoreThreadGet();
- if (!thread) {
- return;
- }
-
- if (thread->frameCallback) {
- thread->frameCallback(thread);
- }
+ mCoreThreadFrameEnded(thread);
// TODO: Put back RR
}
diff --git a/src/gba/serialize.c b/src/gba/serialize.c
index a2dd3e0de..8130fd00c 100644
--- a/src/gba/serialize.c
+++ b/src/gba/serialize.c
@@ -225,5 +225,3 @@ struct GBASerializedState* GBAAllocateState(void) {
void GBADeallocateState(struct GBASerializedState* state) {
mappedMemoryFree(state, sizeof(struct GBASerializedState));
}
-
-// TODO: Put back rewind
diff --git a/src/platform/qt/ConfigController.cpp b/src/platform/qt/ConfigController.cpp
index ee7beb890..62b209bfc 100644
--- a/src/platform/qt/ConfigController.cpp
+++ b/src/platform/qt/ConfigController.cpp
@@ -112,8 +112,7 @@ ConfigController::ConfigController(QObject* parent)
m_opts.volume = 0x100;
m_opts.logLevel = mLOG_WARN | mLOG_ERROR | mLOG_FATAL;
m_opts.rewindEnable = false;
- m_opts.rewindBufferInterval = 0;
- m_opts.rewindBufferCapacity = 0;
+ m_opts.rewindBufferCapacity = 60;
m_opts.useBios = true;
m_opts.suspendScreensaver = true;
mCoreConfigLoad(&m_config);
diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp
index 4fc8764b4..7b48a84a9 100644
--- a/src/platform/qt/GameController.cpp
+++ b/src/platform/qt/GameController.cpp
@@ -234,13 +234,6 @@ GameController::GameController(QObject* parent)
m_threadContext.userData = this;
- connect(&m_rewindTimer, &QTimer::timeout, [this]() {
- // TODO: Put rewind back
- emit frameAvailable(m_drawContext);
- emit rewound(&m_threadContext);
- });
- m_rewindTimer.setInterval(100);
-
m_audioThread->setObjectName("Audio Thread");
m_audioThread->start(QThread::TimeCriticalPriority);
m_audioProcessor->moveToThread(m_audioThread);
@@ -529,7 +522,6 @@ void GameController::closeGame() {
}
m_gameOpen = false;
- m_rewindTimer.stop();
if (mCoreThreadIsPaused(&m_threadContext)) {
mCoreThreadUnpause(&m_threadContext);
}
@@ -578,7 +570,7 @@ QSize GameController::screenDimensions() const {
}
void GameController::setPaused(bool paused) {
- if (!isLoaded() || m_rewindTimer.isActive() || paused == mCoreThreadIsPaused(&m_threadContext)) {
+ if (!isLoaded() || paused == mCoreThreadIsPaused(&m_threadContext)) {
return;
}
if (paused) {
@@ -617,15 +609,12 @@ void GameController::threadContinue() {
}
void GameController::frameAdvance() {
- if (m_rewindTimer.isActive()) {
- return;
- }
if (m_pauseAfterFrame.testAndSetRelaxed(false, true)) {
setPaused(false);
}
}
-void GameController::setRewind(bool enable, int capacity, int interval) {
+void GameController::setRewind(bool enable, int capacity) {
if (m_gameOpen) {
threadInterrupt();
// TODO: Put back rewind
@@ -638,9 +627,12 @@ void GameController::setRewind(bool enable, int capacity, int interval) {
void GameController::rewind(int states) {
threadInterrupt();
if (!states) {
- // TODO: Put back rewind
- } else {
- // TODO: Put back rewind
+ states = INT_MAX;
+ }
+ for (int i = 0; i < states; ++i) {
+ if (!mCoreRewindRestore(&m_threadContext.rewind, m_threadContext.core)) {
+ break;
+ }
}
threadContinue();
emit frameAvailable(m_drawContext);
@@ -648,24 +640,21 @@ void GameController::rewind(int states) {
}
void GameController::startRewinding() {
- if (!m_gameOpen || m_rewindTimer.isActive()) {
+ if (!m_gameOpen) {
return;
}
if (m_multiplayer && m_multiplayer->attached() > 1) {
return;
}
- m_wasPaused = isPaused();
- if (!mCoreThreadIsPaused(&m_threadContext)) {
- mCoreThreadPause(&m_threadContext);
+ m_wasPaused = mCoreThreadIsPaused(&m_threadContext);
+ if (m_wasPaused) {
+ mCoreThreadUnpause(&m_threadContext);
}
- m_rewindTimer.start();
+ mCoreThreadSetRewinding(&m_threadContext, true);
}
void GameController::stopRewinding() {
- if (!m_rewindTimer.isActive()) {
- return;
- }
- m_rewindTimer.stop();
+ mCoreThreadSetRewinding(&m_threadContext, false);
bool signalsBlocked = blockSignals(true);
setPaused(m_wasPaused);
blockSignals(signalsBlocked);
diff --git a/src/platform/qt/GameController.h b/src/platform/qt/GameController.h
index 3747fa895..e7a0638ef 100644
--- a/src/platform/qt/GameController.h
+++ b/src/platform/qt/GameController.h
@@ -116,7 +116,7 @@ public slots:
void setPaused(bool paused);
void reset();
void frameAdvance();
- void setRewind(bool enable, int capacity, int interval);
+ void setRewind(bool enable, int capacity);
void rewind(int states = 0);
void startRewinding();
void stopRewinding();
@@ -202,7 +202,6 @@ private:
bool m_turbo;
bool m_turboForced;
float m_turboSpeed;
- QTimer m_rewindTimer;
bool m_wasPaused;
bool m_audioChannels[6];
diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp
index 488e09bbc..ae5167512 100644
--- a/src/platform/qt/SettingsView.cpp
+++ b/src/platform/qt/SettingsView.cpp
@@ -165,14 +165,6 @@ void SettingsView::selectBios() {
}
}
-void SettingsView::recalculateRewind() {
- int interval = m_ui.rewindInterval->value();
- int capacity = m_ui.rewindCapacity->value();
- double duration = m_ui.fpsTarget->value();
- m_ui.rewindDuration->setValue(interval * capacity / duration);
-
-}
-
void SettingsView::updateConfig() {
saveSetting("bios", m_ui.bios);
saveSetting("useBios", m_ui.useBios);
@@ -187,7 +179,6 @@ void SettingsView::updateConfig() {
saveSetting("volume", m_ui.volume);
saveSetting("mute", m_ui.mute);
saveSetting("rewindEnable", m_ui.rewind);
- saveSetting("rewindBufferInterval", m_ui.rewindInterval);
saveSetting("rewindBufferCapacity", m_ui.rewindCapacity);
saveSetting("resampleVideo", m_ui.resampleVideo);
saveSetting("allowOpposingDirections", m_ui.allowOpposingDirections);
@@ -262,7 +253,6 @@ void SettingsView::reloadConfig() {
loadSetting("volume", m_ui.volume);
loadSetting("mute", m_ui.mute);
loadSetting("rewindEnable", m_ui.rewind);
- loadSetting("rewindBufferInterval", m_ui.rewindInterval);
loadSetting("rewindBufferCapacity", m_ui.rewindCapacity);
loadSetting("resampleVideo", m_ui.resampleVideo);
loadSetting("allowOpposingDirections", m_ui.allowOpposingDirections);
@@ -283,10 +273,6 @@ void SettingsView::reloadConfig() {
m_ui.fastForwardRatio->setValue(fastForwardRatio);
}
- connect(m_ui.rewindInterval, SIGNAL(valueChanged(int)), this, SLOT(recalculateRewind()));
- connect(m_ui.rewindCapacity, SIGNAL(valueChanged(int)), this, SLOT(recalculateRewind()));
- connect(m_ui.fpsTarget, SIGNAL(valueChanged(double)), this, SLOT(recalculateRewind()));
-
QString idleOptimization = loadSetting("idleOptimization");
if (idleOptimization == "ignore") {
m_ui.idleOptimization->setCurrentIndex(0);
diff --git a/src/platform/qt/SettingsView.h b/src/platform/qt/SettingsView.h
index 77d672bdf..352604b32 100644
--- a/src/platform/qt/SettingsView.h
+++ b/src/platform/qt/SettingsView.h
@@ -30,7 +30,6 @@ signals:
private slots:
void selectBios();
- void recalculateRewind();
void updateConfig();
void reloadConfig();
diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui
index 0b1b45333..804cfffc4 100644
--- a/src/platform/qt/SettingsView.ui
+++ b/src/platform/qt/SettingsView.ui
@@ -6,8 +6,8 @@
0
0
- 544
- 425
+ 548
+ 431
@@ -72,7 +72,7 @@
-
- 0
+ 2
@@ -110,7 +110,7 @@
true
-
+
1536
@@ -176,7 +176,7 @@
true
-
+
44100
@@ -487,13 +487,6 @@
- -
-
-
- Allow opposing input directions
-
-
-
-
@@ -537,6 +530,13 @@
+ -
+
+
+ Allow opposing input directions
+
+
+
@@ -634,70 +634,25 @@
-
-
-
- Create rewind state:
-
-
-
- -
-
-
-
-
-
- Every
-
-
-
- -
-
-
- -
-
-
- frames
-
-
-
-
-
- -
Rewind history:
- -
+
-
-
-
+
+
+ 3600
+
+
-
- states
-
-
-
-
-
- -
-
-
-
-
-
- false
-
-
- 999.990000000000009
-
-
-
- -
-
-
- seconds
+ frames
diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp
index 318f16b68..41ae3ce7e 100644
--- a/src/platform/qt/Window.cpp
+++ b/src/platform/qt/Window.cpp
@@ -1375,17 +1375,12 @@ void Window::setupMenu(QMenuBar* menubar) {
ConfigOption* rewindEnable = m_config->addOption("rewindEnable");
rewindEnable->connect([this](const QVariant& value) {
- m_controller->setRewind(value.toBool(), m_config->getOption("rewindBufferCapacity").toInt(), m_config->getOption("rewindBufferInterval").toInt());
+ m_controller->setRewind(value.toBool(), m_config->getOption("rewindBufferCapacity").toInt());
}, this);
ConfigOption* rewindBufferCapacity = m_config->addOption("rewindBufferCapacity");
rewindBufferCapacity->connect([this](const QVariant& value) {
- m_controller->setRewind(m_config->getOption("rewindEnable").toInt(), value.toInt(), m_config->getOption("rewindBufferInterval").toInt());
- }, this);
-
- ConfigOption* rewindBufferInterval = m_config->addOption("rewindBufferInterval");
- rewindBufferInterval->connect([this](const QVariant& value) {
- m_controller->setRewind(m_config->getOption("rewindEnable").toInt(), m_config->getOption("rewindBufferCapacity").toInt(), value.toInt());
+ m_controller->setRewind(m_config->getOption("rewindEnable").toInt(), value.toInt());
}, this);
ConfigOption* allowOpposingDirections = m_config->addOption("allowOpposingDirections");
diff --git a/src/platform/sdl/main.c b/src/platform/sdl/main.c
index 83a4c51a2..0e89c368f 100644
--- a/src/platform/sdl/main.c
+++ b/src/platform/sdl/main.c
@@ -51,6 +51,7 @@ int main(int argc, char** argv) {
struct mCoreOptions opts = {
.useBios = true,
.rewindEnable = true,
+ .rewindBufferCapacity = 600,
.audioBuffers = 512,
.videoSync = false,
.audioSync = true,
diff --git a/src/platform/sdl/sdl-events.c b/src/platform/sdl/sdl-events.c
index 651ccc885..224ccf5f5 100644
--- a/src/platform/sdl/sdl-events.c
+++ b/src/platform/sdl/sdl-events.c
@@ -406,6 +406,9 @@ static void _mSDLHandleKeypress(struct mCoreThread* context, struct mSDLPlayer*
context->sync.audioWait = event->type != SDL_KEYDOWN;
return;
}
+ if (event->keysym.sym == SDLK_BACKQUOTE) {
+ mCoreThreadSetRewinding(context, event->type == SDL_KEYDOWN);
+ }
if (event->type == SDL_KEYDOWN) {
switch (event->keysym.sym) {
case SDLK_F11:
@@ -423,9 +426,6 @@ static void _mSDLHandleKeypress(struct mCoreThread* context, struct mSDLPlayer*
context->frameCallback = _pauseAfterFrame;
mCoreThreadUnpause(context);
return;
- case SDLK_BACKQUOTE:
- // TODO: Put back rewind
- return;
#ifdef BUILD_PANDORA
case SDLK_ESCAPE:
mCoreThreadEnd(context);