From f97ba6517b32f5043a833cd5f8defb30987a7086 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Mon, 5 Jan 2015 23:12:44 -0800 Subject: [PATCH] Qt: Expose rewind (fixes #136) --- CHANGES | 1 + README.md | 1 + src/platform/qt/GameController.cpp | 26 ++++++++++++++++++++++++++ src/platform/qt/GameController.h | 2 ++ src/platform/qt/SettingsView.cpp | 2 ++ src/platform/qt/SettingsView.ui | 3 --- src/platform/qt/Window.cpp | 16 ++++++++++++++++ 7 files changed, 48 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index a4c99812b..1397b8f68 100644 --- a/CHANGES +++ b/CHANGES @@ -13,6 +13,7 @@ Features: - Game Pak overrides dialog for setting savetype and sensor values - Support for games using the tilt sensor - Remappable shortcuts for keyboard and gamepad + - Rewinding of emulation Bugfixes: - Qt: Fix issue with set frame sizes being the wrong height - Qt: Fix emulator crashing when full screen if a game is not running diff --git a/README.md b/README.md index be4dc96e7..f1b11cf00 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ Features - Loading from ZIP files. - IPS and UPS patch support. - Game debugging via a command-line interface (not available with Qt port) and GDB remote support. +- Configurable emulation rewinding. ### Planned features diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index 1394e533b..388943406 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -298,6 +298,32 @@ void GameController::frameAdvance() { m_pauseMutex.unlock(); } +void GameController::setRewind(bool enable, int capacity, int interval) { + if (m_gameOpen) { + threadInterrupt(); + GBARewindSettingsChanged(&m_threadContext, enable ? capacity : 0, enable ? interval : 0); + threadContinue(); + } else { + if (enable) { + m_threadContext.rewindBufferInterval = interval; + m_threadContext.rewindBufferCapacity = capacity; + } else { + m_threadContext.rewindBufferInterval = 0; + m_threadContext.rewindBufferCapacity = 0; + } + } +} + +void GameController::rewind(int states) { + threadInterrupt(); + if (!states) { + GBARewindAll(&m_threadContext); + } else { + GBARewind(&m_threadContext, states); + } + threadContinue(); +} + void GameController::keyPressed(int key) { int mappedKey = 1 << key; m_activeKeys |= mappedKey; diff --git a/src/platform/qt/GameController.h b/src/platform/qt/GameController.h index 4043bfd46..eaa0afce5 100644 --- a/src/platform/qt/GameController.h +++ b/src/platform/qt/GameController.h @@ -80,6 +80,8 @@ public slots: void setPaused(bool paused); void reset(); void frameAdvance(); + void setRewind(bool enable, int capacity, int interval); + void rewind(int states = 0); void keyPressed(int key); void keyReleased(int key); void clearKeys(); diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index b0cf5df4c..f8900385e 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -25,6 +25,7 @@ SettingsView::SettingsView(ConfigController* controller, QWidget* parent) loadSetting("frameskip", m_ui.frameskip); loadSetting("fpsTarget", m_ui.fpsTarget); loadSetting("lockAspectRatio", m_ui.lockAspectRatio); + loadSetting("rewindEnable", m_ui.rewind); loadSetting("rewindBufferInterval", m_ui.rewindInterval); loadSetting("rewindBufferCapacity", m_ui.rewindCapacity); loadSetting("resampleVideo", m_ui.resampleVideo); @@ -49,6 +50,7 @@ void SettingsView::updateConfig() { saveSetting("frameskip", m_ui.frameskip); saveSetting("fpsTarget", m_ui.fpsTarget); saveSetting("lockAspectRatio", m_ui.lockAspectRatio); + saveSetting("rewindEnable", m_ui.rewind); saveSetting("rewindBufferInterval", m_ui.rewindInterval); saveSetting("rewindBufferCapacity", m_ui.rewindCapacity); saveSetting("resampleVideo", m_ui.resampleVideo); diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 96b2ac798..8d2ca1ba6 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -244,9 +244,6 @@ - - false - Enable rewind diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 47508198b..a2f6faaec 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -144,6 +144,7 @@ void Window::loadConfig() { m_controller->setAudioSync(opts->audioSync); m_controller->setVideoSync(opts->videoSync); m_controller->setSkipBIOS(opts->skipBios); + m_controller->setRewind(opts->rewindEnable, opts->rewindBufferCapacity, opts->rewindBufferInterval); m_display->lockAspectRatio(opts->lockAspectRatio); m_display->filter(opts->resampleVideo); @@ -522,6 +523,12 @@ void Window::setupMenu(QMenuBar* menubar) { connect(turbo, SIGNAL(triggered(bool)), m_controller, SLOT(setTurbo(bool))); addControlledAction(emulationMenu, turbo, "fastForward"); + QAction* rewind = new QAction(tr("Re&wind"), emulationMenu); + rewind->setShortcut(tr("`")); + connect(rewind, SIGNAL(triggered()), m_controller, SLOT(rewind())); + m_gameActions.append(rewind); + addControlledAction(emulationMenu, rewind, "rewind"); + ConfigOption* videoSync = m_config->addOption("videoSync"); videoSync->addBoolean(tr("Sync to &video"), emulationMenu); videoSync->connect([this](const QVariant& value) { m_controller->setVideoSync(value.toBool()); }); @@ -649,6 +656,15 @@ void Window::setupMenu(QMenuBar* menubar) { ConfigOption* skipBios = m_config->addOption("skipBios"); skipBios->connect([this](const QVariant& value) { m_controller->setSkipBIOS(value.toBool()); }); + 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()); }); + + 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()); }); + + 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()); }); + QMenu* other = new QMenu(tr("Other"), this); m_shortcutController->addMenu(other); m_shortcutController->addFunctions(other, [this]() {