all repos — mgba @ f50f98416bc9e5455b71732a6727eda9bf8d6064

mGBA Game Boy Advance Emulator

Qt: Add savestate load undo
Jeffrey Pfau jeffrey@endrift.com
Mon, 13 Jul 2015 21:56:05 -0700
commit

f50f98416bc9e5455b71732a6727eda9bf8d6064

parent

5ed05dc66f3cff5e065a70ea79e857ddcec0570e

M CHANGESCHANGES

@@ -24,6 +24,7 @@ - Ability to boot directly into the BIOS

- Preliminary support for yanking out the game pak while a game is running - Thumb-drive mode by putting a file called portable.ini in the same folder - Configurable display driver, between software and OpenGL + - Undo-able savestate loading Bugfixes: - ARM7: Fix SWI and IRQ timings - GBA Audio: Force audio FIFOs to 32-bit
M src/platform/qt/GameController.cppsrc/platform/qt/GameController.cpp

@@ -51,6 +51,8 @@ , m_wasPaused(false)

, m_inputController(nullptr) , m_multiplayer(nullptr) , m_stateSlot(1) + , m_backupLoadState(nullptr) + , m_backupSaveState(nullptr) { m_renderer = new GBAVideoSoftwareRenderer; GBAVideoSoftwareRendererCreate(m_renderer);

@@ -162,6 +164,7 @@ closeGame();

GBACheatDeviceDestroy(&m_cheatDevice); delete m_renderer; delete[] m_drawContext; + delete m_backupLoadState; } void GameController::setMultiplayerController(MultiplayerController* controller) {

@@ -561,6 +564,10 @@ m_stateSlot = slot;

} GBARunOnThread(&m_threadContext, [](GBAThread* context) { GameController* controller = static_cast<GameController*>(context->userData); + if (!controller->m_backupLoadState) { + controller->m_backupLoadState = new GBASerializedState; + } + GBASerialize(context->gba, controller->m_backupLoadState); if (GBALoadState(context, context->stateDir, controller->m_stateSlot)) { controller->frameAvailable(controller->m_drawContext); controller->stateLoaded(context);

@@ -575,6 +582,23 @@ }

GBARunOnThread(&m_threadContext, [](GBAThread* context) { GameController* controller = static_cast<GameController*>(context->userData); GBASaveState(context, context->stateDir, controller->m_stateSlot, true); + }); +} + +void GameController::loadBackupState() { + if (!m_backupLoadState) { + return; + } + + GBARunOnThread(&m_threadContext, [](GBAThread* context) { + GameController* controller = static_cast<GameController*>(context->userData); + if (GBADeserialize(context->gba, controller->m_backupLoadState)) { + GBALog(context->gba, GBA_LOG_STATUS, "Undid state load"); + controller->frameAvailable(controller->m_drawContext); + controller->stateLoaded(context); + } + delete controller->m_backupLoadState; + controller->m_backupLoadState = nullptr; }); }
M src/platform/qt/GameController.hsrc/platform/qt/GameController.h

@@ -120,6 +120,7 @@ void setAudioBufferSamples(int samples);

void setFPSTarget(float fps); void loadState(int slot = 0); void saveState(int slot = 0); + void loadBackupState(); void setVideoSync(bool); void setAudioSync(bool); void setFrameskip(int);

@@ -192,6 +193,8 @@ QTimer m_rewindTimer;

bool m_wasPaused; int m_stateSlot; + GBASerializedState* m_backupLoadState; + GBASerializedState* m_backupSaveState; // TODO: Use this InputController* m_inputController; MultiplayerController* m_multiplayer;
M src/platform/qt/Window.cppsrc/platform/qt/Window.cpp

@@ -698,6 +698,14 @@ m_gameActions.append(quickSave);

addControlledAction(quickSaveMenu, quickSave, "quickSave"); quickLoadMenu->addSeparator(); + + QAction* undoLoadState = new QAction(tr("Undo load state"), quickLoadMenu); + undoLoadState->setShortcut(tr("F11")); + connect(undoLoadState, SIGNAL(triggered()), m_controller, SLOT(loadBackupState())); + m_gameActions.append(undoLoadState); + addControlledAction(quickLoadMenu, undoLoadState, "undoLoadState"); + + quickLoadMenu->addSeparator(); quickSaveMenu->addSeparator(); int i;

@@ -961,14 +969,12 @@ #endif

#ifdef USE_FFMPEG QAction* recordOutput = new QAction(tr("Record output..."), avMenu); - recordOutput->setShortcut(tr("F11")); connect(recordOutput, SIGNAL(triggered()), this, SLOT(openVideoWindow())); addControlledAction(avMenu, recordOutput, "recordOutput"); #endif #ifdef USE_MAGICK QAction* recordGIF = new QAction(tr("Record GIF..."), avMenu); - recordGIF->setShortcut(tr("Shift+F11")); connect(recordGIF, SIGNAL(triggered()), this, SLOT(openGIFWindow())); addControlledAction(avMenu, recordGIF, "recordGIF"); #endif