Qt: Add savestate load undo

This commit is contained in:
Jeffrey Pfau 2015-07-13 21:56:05 -07:00
parent 5ed05dc66f
commit f50f98416b
4 changed files with 36 additions and 2 deletions

View File

@ -24,6 +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
Bugfixes:
- ARM7: Fix SWI and IRQ timings
- GBA Audio: Force audio FIFOs to 32-bit

View File

@ -51,6 +51,8 @@ GameController::GameController(QObject* parent)
, 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 @@ GameController::~GameController() {
GBACheatDeviceDestroy(&m_cheatDevice);
delete m_renderer;
delete[] m_drawContext;
delete m_backupLoadState;
}
void GameController::setMultiplayerController(MultiplayerController* controller) {
@ -561,6 +564,10 @@ void GameController::loadState(int 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);
@ -578,6 +585,23 @@ void GameController::saveState(int slot) {
});
}
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;
});
}
void GameController::setVideoSync(bool set) {
m_videoSync = set;
if (!m_turbo) {

View File

@ -120,6 +120,7 @@ public slots:
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 @@ private:
bool m_wasPaused;
int m_stateSlot;
GBASerializedState* m_backupLoadState;
GBASerializedState* m_backupSaveState; // TODO: Use this
InputController* m_inputController;
MultiplayerController* m_multiplayer;

View File

@ -697,6 +697,14 @@ void Window::setupMenu(QMenuBar* menubar) {
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();
@ -961,14 +969,12 @@ void Window::setupMenu(QMenuBar* menubar) {
#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