mirror of https://github.com/mgba-emu/mgba.git
Qt: Port autosave to Qt interface
This commit is contained in:
parent
5973433aa0
commit
8ec934c58d
1
CHANGES
1
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
|
||||
|
|
|
@ -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,11 +250,15 @@ 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
|
||||
void CoreController::setDebugger(mDebugger* debugger) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue