From 87326525dee3a6ccb3960be9f0dac44bf19550f1 Mon Sep 17 00:00:00 2001 From: Adam Higerd Date: Tue, 24 Jan 2023 21:22:23 -0600 Subject: [PATCH] detect failed startups and prompt for safe mode --- CHANGES | 1 + src/platform/qt/ConfigController.cpp | 35 ++++++++++++++++++++++++++++ src/platform/qt/ConfigController.h | 7 +++++- src/platform/qt/Window.cpp | 16 +++++++++---- src/platform/qt/Window.h | 2 ++ src/platform/qt/main.cpp | 8 +++++++ 6 files changed, 64 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index 637fdf28fd1..fb763b3b125 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,7 @@ Emulation fixes: Misc: - GB Serialize: Add missing savestate support for MBC6 and NT (newer) - GBA: Improve detection of valid ELF ROMs + - Qt: Detect failed startup and prompt for safe mode 0.10.1: (2023-01-10) Emulation fixes: diff --git a/src/platform/qt/ConfigController.cpp b/src/platform/qt/ConfigController.cpp index 1116dba79ab..667e0ff9d37 100644 --- a/src/platform/qt/ConfigController.cpp +++ b/src/platform/qt/ConfigController.cpp @@ -7,6 +7,7 @@ #include "ActionMapper.h" #include "CoreController.h" +#include "Display.h" #include #include @@ -114,6 +115,16 @@ ConfigController::ConfigController(QObject* parent) fileName.append("qt.ini"); m_settings = std::make_unique(fileName, QSettings::IniFormat); + if (getQtOption("loadStarted").toBool()) { + // If the loadStarted flag is lingering in qt.ini, then that indicates that + // the frontend crashed before clearing the flag. + // Prompt the user to enter into a safe mode to try to get safely started up. + setQtOption("safeModeWarning", true); + } else { + setQtOption("loadStarted", true); + m_settings->sync(); + } + mCoreConfigInit(&m_config, PORT); m_opts.audioSync = CoreController::AUDIO_SYNC; @@ -306,6 +317,16 @@ void ConfigController::setQtOption(const QString& key, const QVariant& value, co } } +void ConfigController::removeQtOption(const QString& key, const QString& group) { + if (!group.isNull()) { + m_settings->beginGroup(group); + } + m_settings->remove(key); + if (!group.isNull()) { + m_settings->endGroup(); + } +} + QStringList ConfigController::getMRU(ConfigController::MRU mruType) const { QStringList mru; m_settings->beginGroup(mruName(mruType)); @@ -353,6 +374,20 @@ void ConfigController::write() { mCoreConfigMap(&m_config, &m_opts); } +void ConfigController::setLoadingComplete() { + removeQtOption("loadStarted"); + write(); +} + +void ConfigController::setSafeMode() { + setQtOption("displayDriver", static_cast(Display::Driver::QT)); + removeQtOption("safeModeWarning"); +} + +void ConfigController::declineSafeMode() { + removeQtOption("safeModeWarning"); +} + void ConfigController::makePortable() { mCoreConfigMakePortable(&m_config); diff --git a/src/platform/qt/ConfigController.h b/src/platform/qt/ConfigController.h index ecd12686763..6eb5e7c633c 100644 --- a/src/platform/qt/ConfigController.h +++ b/src/platform/qt/ConfigController.h @@ -104,6 +104,10 @@ Q_OBJECT const mGraphicsOpts* graphicsOpts() const { return &m_graphicsOpts; } void usage(const char* arg0) const; + void setLoadingComplete(); + void setSafeMode(); + void declineSafeMode(); + static const QString& configDir(); static const QString& cacheDir(); static bool isPortable(); @@ -115,6 +119,7 @@ public slots: void setOption(const char* key, const char* value); void setOption(const char* key, const QVariant& value); void setQtOption(const QString& key, const QVariant& value, const QString& group = QString()); + void removeQtOption(const QString& key, const QString& group = QString()); void makePortable(); void write(); @@ -130,7 +135,7 @@ public slots: mGraphicsOpts m_graphicsOpts{}; std::array m_subparsers; bool m_parsed = false; - + QHash m_argvOptions; QHash m_optionSet; std::unique_ptr m_settings; diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index cdfb5b9c1e1..fc3f9982b9d 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -118,7 +118,7 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi if (value.toBool()) { attachWidget(m_libraryView); } else { - attachWidget(m_screenWidget); + attachWidget(m_screenWidget); } } }, this); @@ -126,9 +126,9 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi ConfigOption* showFilenameInLibrary = m_config->addOption("showFilenameInLibrary"); showFilenameInLibrary->connect([this](const QVariant& value) { - m_libraryView->setShowFilename(value.toBool()); - }, this); - m_config->updateOption("showFilenameInLibrary"); + m_libraryView->setShowFilename(value.toBool()); + }, this); + m_config->updateOption("showFilenameInLibrary"); ConfigOption* libraryStyle = m_config->addOption("libraryStyle"); libraryStyle->connect([this](const QVariant& value) { m_libraryView->setViewStyle(static_cast(value.toInt())); @@ -721,6 +721,7 @@ void Window::showEvent(QShowEvent* event) { } reloadDisplayDriver(); setFocus(); + m_config->setLoadingComplete(); } void Window::hideEvent(QHideEvent* event) { @@ -2176,3 +2177,10 @@ void WindowBackground::paintEvent(QPaintEvent* event) { QRect full(clampSize(QSize(m_aspectWidth, m_aspectHeight), size(), true, false)); painter.drawPixmap(full, logo); } + +bool Window::promptForSafeMode() { + int choice = QMessageBox::warning(nullptr, tr("Safe Mode"), + tr("mGBA detected a problem while starting.\n\nWould you like to reset settings to failsafe values?"), + QMessageBox::Yes | QMessageBox::No, QMessageBox::No); + return choice == QMessageBox::Yes; +} diff --git a/src/platform/qt/Window.h b/src/platform/qt/Window.h index 9495cb3ee74..70749ab8b2a 100644 --- a/src/platform/qt/Window.h +++ b/src/platform/qt/Window.h @@ -69,6 +69,8 @@ Q_OBJECT InputController* inputController() { return &m_inputController; } + static bool promptForSafeMode(); + signals: void startDrawing(); void shutdown(); diff --git a/src/platform/qt/main.cpp b/src/platform/qt/main.cpp index 67668b0118c..05de22ebba1 100644 --- a/src/platform/qt/main.cpp +++ b/src/platform/qt/main.cpp @@ -112,6 +112,14 @@ int main(int argc, char* argv[]) { langTranslator.load(locale, binaryName, "-", ":/translations/"); application.installTranslator(&langTranslator); + if (configController.getQtOption("safeModeWarning").toBool()) { + if (Window::promptForSafeMode()) { + configController.setSafeMode(); + } else { + configController.declineSafeMode(); + } + } + Window* w = application.newWindow(); w->loadConfig(); w->argumentsPassed();