all repos — mgba @ 8ec934c58d12e70d2e5748ca7285be6c0d380630

mGBA Game Boy Advance Emulator

Qt: Port autosave to Qt interface
Vicki Pfau vi@endrift.com
Tue, 23 Jan 2018 20:43:55 -0800
commit

8ec934c58d12e70d2e5748ca7285be6c0d380630

parent

5973433aa06cbe46e0262161aaefbc3df9ca1c63

M CHANGESCHANGES

@@ -13,6 +13,7 @@ - GameShark and Action Replay button support

- 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
M src/platform/qt/CoreController.cppsrc/platform/qt/CoreController.cpp

@@ -28,8 +28,9 @@ #endif

#include <mgba-util/math.h> #include <mgba-util/vfs.h> +#define AUTOSAVE_GRANULARITY 600 + using namespace QGBA; - CoreController::CoreController(mCore* core, QObject* parent) : QObject(parent)

@@ -48,6 +49,12 @@ m_activeBuffer = &m_buffers[0];

m_threadContext.core->setVideoBuffer(m_threadContext.core, reinterpret_cast<color_t*>(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<CoreController*>(context->userData);

@@ -60,6 +67,8 @@ #endif

default: break; } + + controller->updateFastForward(); if (controller->m_multiplayer) { controller->m_multiplayer->attachGame(controller);

@@ -79,10 +88,6 @@ controller->m_override->identify(context->core);

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,11 +105,23 @@

m_threadContext.frameCallback = [](mCoreThread* context) { CoreController* controller = static_cast<CoreController*>(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<CoreController*>(context->userData); + + if (controller->m_autosave) { + mCoreSaveState(context->core, 0, controller->m_saveStateFlags); + } controller->clearMultiplayerController(); QMetaObject::invokeMethod(controller, "stopping");

@@ -126,7 +143,8 @@ m_threadContext.logger.d.log = [](mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) {

mThreadLogger* logContext = reinterpret_cast<mThreadLogger*>(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 @@ } else

#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 @@ va_end(argc);

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 @@ m_fastForwardRatio = config->getOption("fastForwardRatio", m_fastForwardRatio).toFloat();

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
M src/platform/qt/CoreController.hsrc/platform/qt/CoreController.h

@@ -195,6 +195,10 @@

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;
M src/platform/qt/SettingsView.cppsrc/platform/qt/SettingsView.cpp

@@ -357,6 +357,8 @@ saveSetting("preload", m_ui.preload);

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 @@ loadSetting("preload", m_ui.preload);

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());
M src/platform/qt/SettingsView.uisrc/platform/qt/SettingsView.ui

@@ -512,7 +512,14 @@ <enum>Qt::Horizontal</enum>

</property> </widget> </item> - <item row="11" column="1"> + <item row="13" column="0" colspan="2"> + <widget class="Line" name="line_16"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item row="14" column="1"> <widget class="QCheckBox" name="cheatAutosave"> <property name="text"> <string>Automatically save cheats</string>

@@ -522,10 +529,30 @@ <bool>true</bool>

</property> </widget> </item> - <item row="12" column="1"> + <item row="15" column="1"> <widget class="QCheckBox" name="cheatAutoload"> <property name="text"> <string>Automatically load cheats</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="11" column="1"> + <widget class="QCheckBox" name="autosave"> + <property name="text"> + <string>Automatically save state</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="12" column="1"> + <widget class="QCheckBox" name="autoload"> + <property name="text"> + <string>Automatically load state</string> </property> <property name="checked"> <bool>true</bool>
M src/platform/qt/Window.cppsrc/platform/qt/Window.cpp

@@ -1858,8 +1858,8 @@ m_controller->loadPatch(m_pendingPatch);

m_pendingPatch = QString(); } - m_controller->start(); m_controller->loadConfig(m_config); + m_controller->start(); } WindowBackground::WindowBackground(QWidget* parent)