diff --git a/Source/RMG/UserInterface/MainWindow.cpp b/Source/RMG/UserInterface/MainWindow.cpp index 1b5d40b5..db11086d 100644 --- a/Source/RMG/UserInterface/MainWindow.cpp +++ b/Source/RMG/UserInterface/MainWindow.cpp @@ -182,6 +182,8 @@ void MainWindow::initializeUI(bool launchROM) &MainWindow::on_RomBrowser_PlayGame); connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::PlayGameWith, this, &MainWindow::on_RomBrowser_PlayGameWith); + connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::PlayGameWithSlot, this, + &MainWindow::on_RomBrowser_PlayGameWithSlot); connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::EditGameSettings, this, &MainWindow::on_RomBrowser_EditGameSettings); connect(this->ui_Widget_RomBrowser, &Widget::RomBrowserWidget::EditGameInputSettings, this, @@ -557,7 +559,7 @@ void MainWindow::connectEmulationThreadSignals(void) Qt::BlockingQueuedConnection); } -void MainWindow::launchEmulationThread(QString cartRom, QString diskRom, bool refreshRomListAfterEmulation) +void MainWindow::launchEmulationThread(QString cartRom, QString diskRom, bool refreshRomListAfterEmulation, int slot) { CoreSettingsSave(); @@ -593,6 +595,13 @@ void MainWindow::launchEmulationThread(QString cartRom, QString diskRom, bool re this->ui_LaunchInFullscreen = false; } + this->ui_LoadSaveStateSlotCounter = 0; + this->ui_LoadSaveStateSlot = slot; + if (slot != -1) + { + this->ui_LoadSaveStateSlotTimerId = this->startTimer(100); + } + this->ui_CheckVideoSizeTimerId = this->startTimer(2000); this->ui_HideCursorInEmulation = CoreSettingsGetBoolValue(SettingsID::GUI_HideCursorInEmulation); @@ -1181,6 +1190,21 @@ void MainWindow::timerEvent(QTimerEvent *event) CoreSetVideoSize(expectedWidth, expectedHeight); } } + else if (timerId == this->ui_LoadSaveStateSlotTimerId) + { + if (!CoreIsEmulationRunning()) + { + return; + } + + if (!CoreSetSaveStateSlot(this->ui_LoadSaveStateSlot) || + !CoreLoadSaveState()) + { + return; + } + + this->killTimer(this->ui_LoadSaveStateSlotTimerId); + } } void MainWindow::on_EventFilter_KeyPressed(QKeyEvent *event) @@ -1904,6 +1928,11 @@ void MainWindow::on_RomBrowser_PlayGameWith(CoreRomType type, QString file) this->launchEmulationThread(mainRom, otherRom); } +void MainWindow::on_RomBrowser_PlayGameWithSlot(QString file, int slot) +{ + this->launchEmulationThread(file, "", false, slot); +} + void MainWindow::on_RomBrowser_ChangeRomDirectory(void) { QString dir; @@ -2391,6 +2420,11 @@ void MainWindow::on_Core_StateCallback(CoreStateCallbackType type, int value) QString dateTimeText = this->getSaveStateSlotDateTimeText(slotAction); std::string message = "Selected save slot: " + std::to_string(value); + if (this->ui_LoadSaveStateSlotTimerId != -1) + { + return; + } + // add date and time when available if (!dateTimeText.isEmpty()) { @@ -2430,7 +2464,28 @@ void MainWindow::on_Core_StateCallback(CoreStateCallbackType type, int value) } break; case CoreStateCallbackType::SaveStateLoaded: { - if (value == 0) + if (this->ui_LoadSaveStateSlotTimerId != -1 && value == 0) + { + this->ui_LoadSaveStateSlotCounter++; + if (this->ui_LoadSaveStateSlotCounter >= 10) + { // give up after 10 attempts + this->showErrorMessage("Failed to load save state"); + this->ui_LoadSaveStateSlotCounter = 0; + this->ui_LoadSaveStateSlotTimerId = -1; + this->ui_LoadSaveStateSlot = -1; + } + else + { + this->ui_LoadSaveStateSlotTimerId = this->startTimer(500); + } + } + else if (this->ui_LoadSaveStateSlotTimerId != -1 && value != 0) + { + this->ui_LoadSaveStateSlotCounter = 0; + this->ui_LoadSaveStateSlotTimerId = -1; + this->ui_LoadSaveStateSlot = -1; + } + else if (value == 0) { OnScreenDisplaySetMessage("Failed to load save state."); } diff --git a/Source/RMG/UserInterface/MainWindow.hpp b/Source/RMG/UserInterface/MainWindow.hpp index df8de8c0..483a2f62 100644 --- a/Source/RMG/UserInterface/MainWindow.hpp +++ b/Source/RMG/UserInterface/MainWindow.hpp @@ -76,6 +76,7 @@ class MainWindow : public QMainWindow, private Ui::MainWindow bool ui_LaunchInFullscreen = false; bool ui_QuitAfterEmulation = false; bool ui_RefreshRomListAfterEmulation = false; + int ui_LoadSaveStateSlot = -1; VidExtRenderMode ui_VidExtRenderMode = VidExtRenderMode::OpenGL; @@ -112,6 +113,9 @@ class MainWindow : public QMainWindow, private Ui::MainWindow int ui_UpdateSaveStateSlotTimerId = 0; int ui_CheckVideoSizeTimerId = 0; + int ui_LoadSaveStateSlotCounter = 0; + int ui_LoadSaveStateSlotTimerId = -1; + QString ui_WindowTitle; Dialog::LogDialog logDialog; @@ -132,7 +136,7 @@ class MainWindow : public QMainWindow, private Ui::MainWindow void initializeEmulationThread(void); void connectEmulationThreadSignals(void); - void launchEmulationThread(QString cartRom, QString diskRom = "", bool refreshRomListAfterEmulation = false); + void launchEmulationThread(QString cartRom, QString diskRom = "", bool refreshRomListAfterEmulation = false, int slot = -1); QString getSaveStateSlotDateTimeText(QAction* action); QString getSaveStateSlotText(QAction* action, int slot); @@ -214,6 +218,7 @@ class MainWindow : public QMainWindow, private Ui::MainWindow void on_RomBrowser_PlayGame(QString file); void on_RomBrowser_PlayGameWith(CoreRomType type, QString file); + void on_RomBrowser_PlayGameWithSlot(QString file, int slot); void on_RomBrowser_ChangeRomDirectory(void); void on_RomBrowser_RomInformation(QString file); void on_RomBrowser_EditGameSettings(QString file); diff --git a/Source/RMG/UserInterface/Widget/RomBrowser/RomBrowserWidget.cpp b/Source/RMG/UserInterface/Widget/RomBrowser/RomBrowserWidget.cpp index 0eb74d4b..d0c86e68 100644 --- a/Source/RMG/UserInterface/Widget/RomBrowser/RomBrowserWidget.cpp +++ b/Source/RMG/UserInterface/Widget/RomBrowser/RomBrowserWidget.cpp @@ -174,6 +174,7 @@ RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent) this->contextMenu = new QMenu(this); this->action_PlayGame = new QAction(this); this->action_PlayGameWith = new QAction(this); + this->menu_PlayGameWithSlot = new QMenu(this); this->action_RefreshRomList = new QAction(this); this->action_OpenRomDirectory = new QAction(this); this->action_ChangeRomDirectory = new QAction(this); @@ -192,6 +193,7 @@ RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent) // configure context menu contents this->action_PlayGame->setText("Play Game"); this->action_PlayGameWith->setText("Play Game with Disk"); + this->menu_PlayGameWithSlot->menuAction()->setText("Play Game with State"); this->action_RefreshRomList->setText("Refresh ROM List"); this->action_OpenRomDirectory->setText("Open ROM Directory"); this->action_ChangeRomDirectory->setText("Change ROM Directory..."); @@ -219,6 +221,7 @@ RomBrowserWidget::RomBrowserWidget(QWidget *parent) : QStackedWidget(parent) // configure context menu this->contextMenu->addAction(this->action_PlayGame); this->contextMenu->addAction(this->action_PlayGameWith); + this->contextMenu->addMenu(this->menu_PlayGameWithSlot); this->contextMenu->addSeparator(); this->contextMenu->addAction(this->action_RefreshRomList); this->contextMenu->addSeparator(); @@ -600,6 +603,7 @@ void RomBrowserWidget::customContextMenuRequested(QPoint position) this->action_PlayGame->setEnabled(hasSelection); this->action_PlayGameWith->setEnabled(hasSelection); + this->menu_PlayGameWithSlot->menuAction()->setEnabled(hasSelection); this->action_RomInformation->setEnabled(hasSelection); this->action_EditGameSettings->setEnabled(hasSelection); this->action_EditGameInputSettings->setEnabled(hasSelection && CorePluginsHasROMConfig(CorePluginType::Input)); @@ -611,6 +615,11 @@ void RomBrowserWidget::customContextMenuRequested(QPoint position) this->action_RemoveCoverImage->setEnabled(hasSelection && !data.coverFile.isEmpty()); this->action_RemoveCoverImage->setVisible(view == this->gridViewWidget); + if (hasSelection) + { + this->generateStateMenu(); + } + if (hasSelection && data.type == CoreRomType::Disk) { // disk selected this->action_PlayGameWith->setText("Play Game with Cartridge"); @@ -658,6 +667,49 @@ void RomBrowserWidget::generateColumnsMenu(void) } } +void RomBrowserWidget::generateStateMenu(void) +{ + this->menu_PlayGameWithSlot->clear(); + + RomBrowserModelData data; + + if (!this->getCurrentData(data)) + { + return; + } + + std::filesystem::path saveStatePath; + QString saveStateSlotText; + + for (int i = 0; i < 10; i++) + { + if (!CoreGetSaveStatePath(data.header, data.settings, i, saveStatePath)) + { + continue; + } + + QFileInfo saveStateFileInfo(QString::fromStdWString(saveStatePath.wstring())); + if (!saveStatePath.empty() && saveStateFileInfo.exists()) + { + saveStateSlotText = "Slot " + QString::number(i) + " - "; + saveStateSlotText += saveStateFileInfo.lastModified().toString("dd/MM/yyyy hh:mm"); + + QAction* slotAction = this->menu_PlayGameWithSlot->addAction(saveStateSlotText, QKeySequence()); + connect(slotAction, &QAction::triggered, [=, this]() + { + QString slotText = slotAction->text().split(" ").at(1); + // sometimes the text can contain a '&' + // which will make the toInt() function return 0 + // so strip it out + slotText.remove('&'); + this->on_Action_PlayGameWithSlot(slotText.toInt()); + }); + } + } + + this->menu_PlayGameWithSlot->setDisabled(this->menu_PlayGameWithSlot->isEmpty()); +} + void RomBrowserWidget::on_listViewWidget_sortIndicatorChanged(int logicalIndex, Qt::SortOrder sortOrder) { CoreSettingsSetValue(SettingsID::RomBrowser_ListViewSortSection, logicalIndex); @@ -891,6 +943,18 @@ void RomBrowserWidget::on_Action_PlayGameWith(void) emit this->PlayGameWith(data.type, data.file); } +void RomBrowserWidget::on_Action_PlayGameWithSlot(int slot) +{ + RomBrowserModelData data; + + if (!this->getCurrentData(data)) + { + return; + } + + emit this->PlayGameWithSlot(data.file, slot); +} + void RomBrowserWidget::on_Action_RefreshRomList(void) { this->RefreshRomList(); diff --git a/Source/RMG/UserInterface/Widget/RomBrowser/RomBrowserWidget.hpp b/Source/RMG/UserInterface/Widget/RomBrowser/RomBrowserWidget.hpp index 2cf80669..fdc0a308 100644 --- a/Source/RMG/UserInterface/Widget/RomBrowser/RomBrowserWidget.hpp +++ b/Source/RMG/UserInterface/Widget/RomBrowser/RomBrowserWidget.hpp @@ -88,6 +88,7 @@ class RomBrowserWidget : public QStackedWidget QAction* action_SetCoverImage; QAction* action_RemoveCoverImage; + QMenu* menu_PlayGameWithSlot; QMenu* menu_Columns; QAction* action_ColumnsMenuEntry; @@ -110,6 +111,7 @@ class RomBrowserWidget : public QStackedWidget void on_DoubleClicked(const QModelIndex& index); void customContextMenuRequested(QPoint position); void generateColumnsMenu(void); + void generateStateMenu(void); void on_listViewWidget_sortIndicatorChanged(int logicalIndex, Qt::SortOrder sortOrder); void on_listViewWidget_sectionResized(int logicalIndex, int oldWidth, int newWidth); @@ -126,6 +128,7 @@ class RomBrowserWidget : public QStackedWidget void on_Action_PlayGame(void); void on_Action_PlayGameWith(void); + void on_Action_PlayGameWithSlot(int); void on_Action_RefreshRomList(void); void on_Action_OpenRomDirectory(void); void on_Action_ChangeRomDirectory(void); @@ -140,6 +143,7 @@ class RomBrowserWidget : public QStackedWidget signals: void PlayGame(QString); void PlayGameWith(CoreRomType, QString); + void PlayGameWithSlot(QString, int); void EditGameSettings(QString); void EditGameInputSettings(QString); void Cheats(QString);