diff --git a/CHANGES b/CHANGES index 6c4170f45..b7562b903 100644 --- a/CHANGES +++ b/CHANGES @@ -24,7 +24,7 @@ Features: - 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 + - Undo-able savestate loading and saving Bugfixes: - ARM7: Fix SWI and IRQ timings - GBA Audio: Force audio FIFOs to 32-bit diff --git a/src/platform/qt/GameController.cpp b/src/platform/qt/GameController.cpp index d7dc24c4f..893a5bc02 100644 --- a/src/platform/qt/GameController.cpp +++ b/src/platform/qt/GameController.cpp @@ -581,6 +581,12 @@ void GameController::saveState(int slot) { } GBARunOnThread(&m_threadContext, [](GBAThread* context) { GameController* controller = static_cast(context->userData); + VFile* vf = GBAGetState(context->gba, context->stateDir, controller->m_stateSlot, false); + if (vf) { + controller->m_backupSaveState.resize(vf->size(vf)); + vf->read(vf, controller->m_backupSaveState.data(), controller->m_backupSaveState.size()); + vf->close(vf); + } GBASaveState(context, context->stateDir, controller->m_stateSlot, true); }); } @@ -602,6 +608,23 @@ void GameController::loadBackupState() { }); } +void GameController::saveBackupState() { + if (m_backupSaveState.isEmpty()) { + return; + } + + GBARunOnThread(&m_threadContext, [](GBAThread* context) { + GameController* controller = static_cast(context->userData); + VFile* vf = GBAGetState(context->gba, context->stateDir, controller->m_stateSlot, true); + if (vf) { + vf->write(vf, controller->m_backupSaveState.constData(), controller->m_backupSaveState.size()); + vf->close(vf); + GBALog(context->gba, GBA_LOG_STATUS, "Undid state save"); + } + controller->m_backupSaveState.clear(); + }); +} + void GameController::setVideoSync(bool set) { m_videoSync = set; if (!m_turbo) { diff --git a/src/platform/qt/GameController.h b/src/platform/qt/GameController.h index 6160a6818..0fb82ba14 100644 --- a/src/platform/qt/GameController.h +++ b/src/platform/qt/GameController.h @@ -121,6 +121,7 @@ public slots: void loadState(int slot = 0); void saveState(int slot = 0); void loadBackupState(); + void saveBackupState(); void setVideoSync(bool); void setAudioSync(bool); void setFrameskip(int); @@ -194,7 +195,7 @@ private: int m_stateSlot; GBASerializedState* m_backupLoadState; - GBASerializedState* m_backupSaveState; // TODO: Use this + QByteArray m_backupSaveState; InputController* m_inputController; MultiplayerController* m_multiplayer; diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 472a39163..3c217c861 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -707,6 +707,12 @@ void Window::setupMenu(QMenuBar* menubar) { m_gameActions.append(undoLoadState); addControlledAction(quickLoadMenu, undoLoadState, "undoLoadState"); + QAction* undoSaveState = new QAction(tr("Undo save state"), quickSaveMenu); + undoSaveState->setShortcut(tr("Shift+F11")); + connect(undoSaveState, SIGNAL(triggered()), m_controller, SLOT(saveBackupState())); + m_gameActions.append(undoSaveState); + addControlledAction(quickLoadMenu, undoSaveState, "undoSaveState"); + quickLoadMenu->addSeparator(); quickSaveMenu->addSeparator();