Qt: Port autosave to Qt interface

This commit is contained in:
Vicki Pfau 2018-01-23 20:43:55 -08:00
parent 5973433aa0
commit 8ec934c58d
6 changed files with 71 additions and 13 deletions

View File

@ -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

View File

@ -28,8 +28,9 @@
#include <mgba-util/math.h>
#include <mgba-util/vfs.h>
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<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);
@ -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<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 @@ CoreController::CoreController(mCore* core, QObject* parent)
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 @@ 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());
if (hasStarted()) {
updateFastForward();
mCoreThreadRewindParamsChanged(&m_threadContext);
}
}
#ifdef USE_DEBUGGERS

View File

@ -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;

View File

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

View File

@ -512,7 +512,14 @@
</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,7 +529,7 @@
</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>
@ -532,6 +539,26 @@
</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>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="emulation">

View File

@ -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)