From 8ec934c58d12e70d2e5748ca7285be6c0d380630 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 23 Jan 2018 20:43:55 -0800 Subject: [PATCH] Qt: Port autosave to Qt interface --- CHANGES | 1 + src/platform/qt/CoreController.cpp | 42 +++++++++++++++++++++++------- src/platform/qt/CoreController.h | 4 +++ src/platform/qt/SettingsView.cpp | 4 +++ src/platform/qt/SettingsView.ui | 31 ++++++++++++++++++++-- src/platform/qt/Window.cpp | 2 +- 6 files changed, 71 insertions(+), 13 deletions(-) diff --git a/CHANGES b/CHANGES index eaee274ad..0338d6e9a 100644 --- a/CHANGES +++ b/CHANGES @@ -13,6 +13,7 @@ Features: - AGBPrint support - Debugger: Conditional breakpoints and watchpoints - Ability to select GB/GBC/SGB BIOS on console ports + - Optional automatic state saving/loading Bugfixes: - GB Audio: Make audio unsigned with bias (fixes mgba.io/i/749) - GB Serialize: Fix audio state loading diff --git a/src/platform/qt/CoreController.cpp b/src/platform/qt/CoreController.cpp index 8cf21da00..a6d60b99c 100644 --- a/src/platform/qt/CoreController.cpp +++ b/src/platform/qt/CoreController.cpp @@ -28,8 +28,9 @@ #include #include -using namespace QGBA; +#define AUTOSAVE_GRANULARITY 600 +using namespace QGBA; CoreController::CoreController(mCore* core, QObject* parent) : QObject(parent) @@ -48,6 +49,12 @@ CoreController::CoreController(mCore* core, QObject* parent) m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast(m_activeBuffer->data()), size.width()); + m_resetActions.append([this]() { + if (m_autoload) { + mCoreLoadState(m_threadContext.core, 0, m_loadStateFlags); + } + }); + m_threadContext.startCallback = [](mCoreThread* context) { CoreController* controller = static_cast(context->userData); @@ -61,6 +68,8 @@ CoreController::CoreController(mCore* core, QObject* parent) break; } + controller->updateFastForward(); + if (controller->m_multiplayer) { controller->m_multiplayer->attachGame(controller); } @@ -79,10 +88,6 @@ CoreController::CoreController(mCore* core, QObject* parent) controller->m_override->apply(context->core); } - if (mCoreLoadState(context->core, 0, controller->m_loadStateFlags)) { - mCoreDeleteState(context->core, 0); - } - controller->m_resetActions.clear(); QSize size = controller->screenDimensions(); @@ -100,12 +105,24 @@ CoreController::CoreController(mCore* core, QObject* parent) m_threadContext.frameCallback = [](mCoreThread* context) { CoreController* controller = static_cast(context->userData); + if (controller->m_autosaveCounter == AUTOSAVE_GRANULARITY) { + if (controller->m_autosave) { + mCoreSaveState(context->core, 0, controller->m_saveStateFlags); + } + controller->m_autosaveCounter = 0; + } + ++controller->m_autosaveCounter; + controller->finishFrame(); }; m_threadContext.cleanCallback = [](mCoreThread* context) { CoreController* controller = static_cast(context->userData); + if (controller->m_autosave) { + mCoreSaveState(context->core, 0, controller->m_saveStateFlags); + } + controller->clearMultiplayerController(); QMetaObject::invokeMethod(controller, "stopping"); }; @@ -126,7 +143,8 @@ CoreController::CoreController(mCore* core, QObject* parent) mThreadLogger* logContext = reinterpret_cast(logger); mCoreThread* context = logContext->p; - static const char* savestateMessage = "State %i loaded"; + static const char* savestateMessage = "State %i saved"; + static const char* loadstateMessage = "State %i loaded"; static const char* savestateFailedMessage = "State %i failed to load"; static int biosCat = -1; static int statusCat = -1; @@ -152,7 +170,7 @@ CoreController::CoreController(mCore* core, QObject* parent) #endif if (category == statusCat) { // Slot 0 is reserved for suspend points - if (strncmp(savestateMessage, format, strlen(savestateMessage)) == 0) { + if (strncmp(loadstateMessage, format, strlen(loadstateMessage)) == 0) { va_list argc; va_copy(argc, args); int slot = va_arg(argc, int); @@ -160,7 +178,7 @@ CoreController::CoreController(mCore* core, QObject* parent) if (slot == 0) { format = "Loaded suspend state"; } - } else if (strncmp(savestateFailedMessage, format, strlen(savestateFailedMessage)) == 0) { + } else if (strncmp(savestateFailedMessage, format, strlen(savestateFailedMessage)) == 0 || strncmp(savestateMessage, format, strlen(savestateMessage)) == 0) { va_list argc; va_copy(argc, args); int slot = va_arg(argc, int); @@ -232,10 +250,14 @@ void CoreController::loadConfig(ConfigController* config) { m_videoSync = config->getOption("videoSync", m_videoSync).toInt(); m_audioSync = config->getOption("audioSync", m_audioSync).toInt(); m_fpsTarget = config->getOption("fpsTarget").toFloat(); + m_autosave = config->getOption("autosave", false).toInt(); + m_autoload = config->getOption("autoload", true).toInt(); m_autofireThreshold = config->getOption("autofireThreshold", m_autofireThreshold).toInt(); - updateFastForward(); mCoreLoadForeignConfig(m_threadContext.core, config->config()); - mCoreThreadRewindParamsChanged(&m_threadContext); + if (hasStarted()) { + updateFastForward(); + mCoreThreadRewindParamsChanged(&m_threadContext); + } } #ifdef USE_DEBUGGERS diff --git a/src/platform/qt/CoreController.h b/src/platform/qt/CoreController.h index c2fb9a9e8..9022d6812 100644 --- a/src/platform/qt/CoreController.h +++ b/src/platform/qt/CoreController.h @@ -195,6 +195,10 @@ private: bool m_audioSync = AUDIO_SYNC; bool m_videoSync = VIDEO_SYNC; + bool m_autosave; + bool m_autoload; + int m_autosaveCounter; + int m_fastForward = false; int m_fastForwardForced = false; float m_fastForwardRatio = -1.f; diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index 8e44dc025..a36b8b324 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -357,6 +357,8 @@ void SettingsView::updateConfig() { saveSetting("showFps", m_ui.showFps); saveSetting("cheatAutoload", m_ui.cheatAutoload); saveSetting("cheatAutosave", m_ui.cheatAutosave); + saveSetting("autoload", m_ui.autoload); + saveSetting("autosave", m_ui.autosave); if (m_ui.fastForwardUnbounded->isChecked()) { saveSetting("fastForwardRatio", "-1"); @@ -478,6 +480,8 @@ void SettingsView::reloadConfig() { loadSetting("showFps", m_ui.showFps, true); loadSetting("cheatAutoload", m_ui.cheatAutoload, true); loadSetting("cheatAutosave", m_ui.cheatAutosave, true); + loadSetting("autoload", m_ui.autoload, true); + loadSetting("autosave", m_ui.autosave, false); m_ui.libraryStyle->setCurrentIndex(loadSetting("libraryStyle").toInt()); diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 26172ad3e..81a572011 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -512,7 +512,14 @@ - + + + + Qt::Horizontal + + + + Automatically save cheats @@ -522,7 +529,7 @@ - + Automatically load cheats @@ -532,6 +539,26 @@ + + + + Automatically save state + + + true + + + + + + + Automatically load state + + + true + + + diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index b79f0d2ed..c6aab3531 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -1858,8 +1858,8 @@ void Window::setController(CoreController* controller, const QString& fname) { m_pendingPatch = QString(); } - m_controller->start(); m_controller->loadConfig(m_config); + m_controller->start(); } WindowBackground::WindowBackground(QWidget* parent)