diff --git a/CMakeLists.txt b/CMakeLists.txt index 989d040..978ba03 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -299,6 +299,8 @@ set(CORE src/core/file_format/elf.cpp src/core/file_format/psf.h src/core/file_format/trp.cpp src/core/file_format/trp.h + src/core/emulator_state.cpp + src/core/emulator_state.h ) set(INPUT src/input/controller.cpp diff --git a/src/common/config.cpp b/src/common/config.cpp index 9241669..fcda949 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -222,15 +222,6 @@ static string config_version = Common::g_scm_rev; // These entries aren't stored in the config static bool overrideControllerColor = false; static int controllerCustomColorRGB[3] = {0, 0, 255}; -static bool isGameRunning = false; - -bool getGameRunning() { - return isGameRunning; -} - -void setGameRunning(bool running) { - isGameRunning = running; -} std::filesystem::path getSysModulesPath() { if (sys_modules_path.empty()) { diff --git a/src/common/config.h b/src/common/config.h index 2e6879d..1356795 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -27,8 +27,6 @@ void load(const std::filesystem::path& path, bool is_game_specific = false); void save(const std::filesystem::path& path, bool is_game_specific = false); void resetGameSpecificValue(std::string entry); -bool getGameRunning(); -void setGameRunning(bool running); int getVolumeSlider(); void setVolumeSlider(int volumeValue, bool is_game_specific = false); std::string getTrophyKey(); diff --git a/src/core/emulator_state.cpp b/src/core/emulator_state.cpp new file mode 100644 index 0000000..1e9bed6 --- /dev/null +++ b/src/core/emulator_state.cpp @@ -0,0 +1,30 @@ +// SPDX-FileCopyrightText: Copyright 2025 shadLauncher4 Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "emulator_state.h" + +std::shared_ptr EmulatorState::s_instance = nullptr; +std::mutex EmulatorState::s_mutex; + +EmulatorState::EmulatorState() {} + +EmulatorState::~EmulatorState() {} + +std::shared_ptr EmulatorState::GetInstance() { + std::lock_guard lock(s_mutex); + if (!s_instance) + s_instance = std::make_shared(); + return s_instance; +} + +void EmulatorState::SetInstance(std::shared_ptr instance) { + std::lock_guard lock(s_mutex); + s_instance = instance; +} + +bool EmulatorState::IsGameRunning() const { + return m_running; +} +void EmulatorState::SetGameRunning(bool running) { + m_running = running; +} \ No newline at end of file diff --git a/src/core/emulator_state.h b/src/core/emulator_state.h new file mode 100644 index 0000000..3190ad4 --- /dev/null +++ b/src/core/emulator_state.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: Copyright 2025 shadLauncher4 Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include + +class EmulatorState { +public: + EmulatorState(); + ~EmulatorState(); + + static std::shared_ptr GetInstance(); + static void SetInstance(std::shared_ptr instance); + + bool IsGameRunning() const; + void SetGameRunning(bool running); + +private: + static std::shared_ptr s_instance; + static std::mutex s_mutex; + + // state variables + bool m_running = false; +}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 7e29154..13b381e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,6 +13,7 @@ #ifdef _WIN32 #include #endif +#include // Custom message handler to ignore Qt logs void customMessageHandler(QtMsgType, const QMessageLogContext&, const QString&) {} @@ -29,6 +30,8 @@ int main(int argc, char* argv[]) { QApplication a(argc, argv); QApplication::setDesktopFileName("net.shadps4.qtlauncher"); + std::shared_ptr m_emu_state = std::make_shared(); + EmulatorState::SetInstance(m_emu_state); // Load configurations and initialize Qt application const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); diff --git a/src/qt_gui/cheats_patches.cpp b/src/qt_gui/cheats_patches.cpp index ec45ae9..94cc901 100644 --- a/src/qt_gui/cheats_patches.cpp +++ b/src/qt_gui/cheats_patches.cpp @@ -32,6 +32,7 @@ #include "common/logging/log.h" #include "common/memory_patcher.h" #include "common/path_util.h" +#include "core/emulator_state.h" CheatsPatches::CheatsPatches(std::shared_ptr gui_settings, std::shared_ptr ipc_client, const QString& gameName, @@ -1246,7 +1247,7 @@ void CheatsPatches::applyCheat(const QString& modName, bool enabled) { if (!m_cheats.contains(modName)) return; - if (!Config::getGameRunning() && enabled) { + if (!EmulatorState::GetInstance()->IsGameRunning() && enabled) { QMessageBox::critical(this, tr("Error"), tr("Can't apply cheats before the game is started")); uncheckAllCheatCheckBoxes(); @@ -1262,7 +1263,7 @@ void CheatsPatches::applyCheat(const QString& modName, bool enabled) { std::string offsetStr = memoryMod.offset.toStdString(); std::string valueStr = value.toStdString(); - if (!Config::getGameRunning()) + if (!EmulatorState::GetInstance()->IsGameRunning()) return; // Determine if the hint field is present diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index a745034..90e017e 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -19,6 +19,7 @@ #include "common/path_util.h" #include "common/scm_rev.h" #include "compatibility_info.h" +#include "core/emulator_state.h" #include "create_shortcut.h" #include "game_info.h" #include "gui_settings.h" @@ -446,9 +447,9 @@ public: } if (selected == &gameConfigConfigure || selected == &gameConfigCreate) { - auto settingsWindow = - new SettingsDialog(m_gui_settings, m_compat_info, m_ipc_client, widget, - Config::getGameRunning(), true, serialStr.toStdString()); + auto settingsWindow = new SettingsDialog( + m_gui_settings, m_compat_info, m_ipc_client, widget, + EmulatorState::GetInstance()->IsGameRunning(), true, serialStr.toStdString()); settingsWindow->exec(); } diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 616f496..bf0f1ec 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -18,6 +18,7 @@ #include "common/scm_rev.h" #include "common/versions.h" #include "control_settings.h" +#include "core/emulator_state.h" #include "dimensions_dialog.h" #include "game_install_dialog.h" #include "hotkeys.h" @@ -140,7 +141,7 @@ void MainWindow::StopGame() { } void MainWindow::onGameClosed() { - Config::setGameRunning(false); + EmulatorState::GetInstance()->SetGameRunning(false); is_paused = false; // clear dialogs when game closed @@ -160,7 +161,7 @@ void MainWindow::toggleLabelsUnderIcons() { bool showLabels = ui->toggleLabelsAct->isChecked(); m_gui_settings->SetValue(gui::mw_showLabelsUnderIcons, showLabels); UpdateToolbarLabels(); - if (Config::getGameRunning()) { + if (EmulatorState::GetInstance()->IsGameRunning()) { UpdateToolbarButtons(); } } @@ -485,7 +486,7 @@ void MainWindow::CreateConnects() { connect(ui->configureAct, &QAction::triggered, this, [this]() { auto settingsDialog = new SettingsDialog(m_gui_settings, m_compat_info, m_ipc_client, this, - Config::getGameRunning()); + EmulatorState::GetInstance()->IsGameRunning()); connect(settingsDialog, &SettingsDialog::LanguageChanged, this, &MainWindow::OnLanguageChanged); @@ -520,7 +521,7 @@ void MainWindow::CreateConnects() { connect(ui->settingsButton, &QPushButton::clicked, this, [this]() { auto settingsDialog = new SettingsDialog(m_gui_settings, m_compat_info, m_ipc_client, this, - Config::getGameRunning()); + EmulatorState::GetInstance()->IsGameRunning()); connect(settingsDialog, &SettingsDialog::LanguageChanged, this, &MainWindow::OnLanguageChanged); @@ -555,13 +556,15 @@ void MainWindow::CreateConnects() { connect(ui->controllerButton, &QPushButton::clicked, this, [this]() { ControlSettings* remapWindow = new ControlSettings( - m_game_info, m_ipc_client, Config::getGameRunning(), runningGameSerial, this); + m_game_info, m_ipc_client, EmulatorState::GetInstance()->IsGameRunning(), + runningGameSerial, this); remapWindow->exec(); }); connect(ui->keyboardButton, &QPushButton::clicked, this, [this]() { - auto kbmWindow = new KBMSettings(m_game_info, m_ipc_client, Config::getGameRunning(), - runningGameSerial, this); + auto kbmWindow = + new KBMSettings(m_game_info, m_ipc_client, + EmulatorState::GetInstance()->IsGameRunning(), runningGameSerial, this); kbmWindow->exec(); }); @@ -584,7 +587,8 @@ void MainWindow::CreateConnects() { }); connect(ui->configureHotkeys, &QAction::triggered, this, [this]() { - auto hotkeyDialog = new Hotkeys(m_ipc_client, Config::getGameRunning(), this); + auto hotkeyDialog = + new Hotkeys(m_ipc_client, EmulatorState::GetInstance()->IsGameRunning(), this); hotkeyDialog->exec(); }); @@ -1338,7 +1342,7 @@ bool MainWindow::eventFilter(QObject* obj, QEvent* event) { } void MainWindow::StartEmulator(std::filesystem::path path, QStringList args) { - if (Config::getGameRunning()) { + if (EmulatorState::GetInstance()->IsGameRunning()) { QMessageBox::critical(nullptr, tr("Run Game"), QString(tr("Game is already running!"))); return; } @@ -1366,7 +1370,7 @@ tr("No emulator version was selected.\nThe Version Manager menu will then open.\ final_args.append(args); - Config::setGameRunning(true); + EmulatorState::GetInstance()->SetGameRunning(true); last_game_path = path; QString workDir = QDir::currentPath(); @@ -1376,7 +1380,7 @@ tr("No emulator version was selected.\nThe Version Manager menu will then open.\ void MainWindow::StartEmulatorExecutable(std::filesystem::path emuPath, QString gameArg, QStringList args, bool disable_ipc) { - if (Config::getGameRunning()) { + if (EmulatorState::GetInstance()->IsGameRunning()) { QMessageBox::critical(nullptr, tr("Run Emulator"), QString(tr("Emulator is already running!"))); return; @@ -1436,7 +1440,7 @@ void MainWindow::StartEmulatorExecutable(std::filesystem::path emuPath, QString return; } - Config::setGameRunning(true); + EmulatorState::GetInstance()->SetGameRunning(true); QString workDir = QDir::currentPath(); m_ipc_client->startEmulator(fileInfo, args, workDir, disable_ipc); } diff --git a/src/qt_gui/settings_dialog.cpp b/src/qt_gui/settings_dialog.cpp index 3a95283..dbf7799 100644 --- a/src/qt_gui/settings_dialog.cpp +++ b/src/qt_gui/settings_dialog.cpp @@ -22,6 +22,7 @@ #include "background_music_player.h" #include "common/logging/backend.h" #include "common/logging/filter.h" +#include "core/emulator_state.h" #include "log_presets_dialog.h" #include "sdl_event_wrapper.h" #include "settings_dialog.h" @@ -243,7 +244,7 @@ SettingsDialog::SettingsDialog(std::shared_ptr gui_settings, connect(ui->horizontalVolumeSlider, &QSlider::valueChanged, this, [this](int value) { VolumeSliderChange(value); - if (Config::getGameRunning()) + if (EmulatorState::GetInstance()->IsGameRunning()) m_ipc_client->adjustVol(value, is_game_specific); }); @@ -448,7 +449,7 @@ SettingsDialog::SettingsDialog(std::shared_ptr gui_settings, ui->RCASValue->setText(RCASValue); }); - if (Config::getGameRunning()) { + if (EmulatorState::GetInstance()->IsGameRunning()) { connect(ui->RCASSlider, &QSlider::valueChanged, this, [this](int value) { m_ipc_client->setRcasAttenuation(value); }); connect(ui->FSRCheckBox, &QCheckBox::checkStateChanged, this, @@ -1213,7 +1214,7 @@ void SettingsDialog::SyncRealTimeWidgetstoConfig() { is_game_specific ? Config::resetGameSpecificValue("volumeSlider") : Config::setVolumeSlider(sliderValue); - if (Config::getGameRunning()) { + if (EmulatorState::GetInstance()->IsGameRunning()) { m_ipc_client->setFsr(toml::find_or(gs_data, "GPU", "fsrEnabled", true)); m_ipc_client->setRcas(toml::find_or(gs_data, "GPU", "rcasEnabled", true)); m_ipc_client->setRcasAttenuation(