Adding stop button function to help with check update while running a game.

This commit is contained in:
Dmugetsu 2025-02-21 16:09:33 -06:00
parent 9424047214
commit 81369755e4
9 changed files with 195 additions and 14 deletions

View File

@ -102,6 +102,7 @@ Emulator::~Emulator() {
}
void Emulator::Run(const std::filesystem::path& file, const std::vector<std::string> args) {
is_running= true;
const auto eboot_name = file.filename().string();
auto game_folder = file.parent_path();
if (const auto game_folder_name = game_folder.filename().string();
@ -288,6 +289,27 @@ void Emulator::Run(const std::filesystem::path& file, const std::vector<std::str
std::quick_exit(0);
}
void Emulator::saveLastEbootPath(const std::string& path) {
lastEbootPath = path;
}
std::string Emulator::getLastEbootPath() const {
return lastEbootPath;
}
Emulator& Emulator::GetInstance() {
static Emulator instance;
return instance;
}
void Emulator::StopEmulation() {
if (!is_running)
return;
is_running = false;
LOG_INFO(Loader, "Stopping emulator...");
}
void Emulator::LoadSystemModules(const std::string& game_serial) {
constexpr std::array<SysModules, 11> ModulesToLoad{
{{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2},

View File

@ -5,6 +5,10 @@
#include <filesystem>
#include <thread>
#include "common/elf_info.h"
#ifdef ENABLE_QT_GUI
#include <QString>
#endif
#include "common/singleton.h"
#include "core/linker.h"
@ -27,10 +31,17 @@ public:
void Run(const std::filesystem::path& file, const std::vector<std::string> args = {});
void UpdatePlayTime(const std::string& serial);
static Emulator& GetInstance();
void StopEmulation();
bool is_running = false;
void saveLastEbootPath(const std::string& path);
std::string getLastEbootPath() const;
private:
void LoadSystemModules(const std::string& game_serial);
Common::ElfInfo game_info;
std::string lastEbootPath;
Core::MemoryManager* memory;
Input::GameController* controller;
Core::Linker* linker;

View File

@ -29,8 +29,8 @@
using namespace Common::FS;
CheckUpdate::CheckUpdate(const bool showMessage, QWidget* parent)
: QDialog(parent), networkManager(new QNetworkAccessManager(this)) {
CheckUpdate::CheckUpdate(MainWindow* mainWindow, bool showMessage, QWidget* parent)
: QDialog(parent), networkManager(new QNetworkAccessManager(this)), m_mainWindow(mainWindow) {
setWindowTitle(tr("Auto Updater"));
setFixedSize(0, 0);
CheckForUpdates(showMessage);
@ -422,6 +422,13 @@ void CheckUpdate::DownloadUpdate(const QString& url) {
}
void CheckUpdate::Install() {
if (m_mainWindow && m_mainWindow->isGameRunning) {
QMessageBox::warning(this, tr("Update Warning"),
tr("A game is currently running. Please close the game to prevent "
"save file corruption."));
m_mainWindow->StopGameforUpdate(false);
}
QString userPath;
Common::FS::PathToQString(userPath, Common::FS::GetUserPath(Common::FS::PathType::UserDir));

View File

@ -3,17 +3,20 @@
#ifndef CHECKUPDATE_H
#define CHECKUPDATE_H
#pragma once
#include <QCheckBox>
#include <QDialog>
#include <QNetworkAccessManager>
#include <QPushButton>
#include "main_window.h"
class CheckUpdate : public QDialog {
Q_OBJECT
public:
explicit CheckUpdate(const bool showMessage, QWidget* parent = nullptr);
explicit CheckUpdate(MainWindow* mainWindow, bool showMessage, QWidget* parent = nullptr);
CheckUpdate(const bool showMessage, QWidget* parent);
~CheckUpdate();
private slots:
@ -35,6 +38,7 @@ private:
QString updateDownloadUrl;
QNetworkAccessManager* networkManager;
MainWindow* m_mainWindow;
};
#endif // CHECKUPDATE_H

View File

@ -1,10 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <fstream>
#include <iostream>
#include <QDockWidget>
#include <QKeyEvent>
#include <QPlainTextEdit>
#include <QProgressDialog>
#include <SDL3/SDL_events.h>
#include "about_dialog.h"
#include "cheats_patches.h"
@ -30,6 +33,7 @@
#ifdef ENABLE_DISCORD_RPC
#include "common/discord_rpc_handler.h"
#endif
#include <SDL3/SDL_messagebox.h>
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
@ -222,12 +226,10 @@ void MainWindow::LoadGameLists() {
#ifdef ENABLE_UPDATER
void MainWindow::CheckUpdateMain(bool checkSave) {
if (checkSave) {
if (!Config::autoUpdate()) {
return;
}
if (checkSave && !Config::autoUpdate()) {
return;
}
auto checkUpdate = new CheckUpdate(false);
auto checkUpdate = new CheckUpdate(this, false, this);
checkUpdate->exec();
}
#endif
@ -276,6 +278,7 @@ void MainWindow::CreateConnects() {
});
connect(ui->playButton, &QPushButton::clicked, this, &MainWindow::StartGame);
connect(ui->stopButton, &QPushButton::clicked, this, &MainWindow::StopGame);
connect(m_game_grid_frame.get(), &QTableWidget::cellDoubleClicked, this,
&MainWindow::StartGame);
connect(m_game_list_frame.get(), &QTableWidget::cellDoubleClicked, this,
@ -335,7 +338,7 @@ void MainWindow::CreateConnects() {
#ifdef ENABLE_UPDATER
connect(ui->updaterAct, &QAction::triggered, this, [this]() {
auto checkUpdate = new CheckUpdate(true);
auto checkUpdate = new CheckUpdate(this, false, this);
checkUpdate->exec();
});
#endif
@ -1151,6 +1154,10 @@ void MainWindow::HandleResize(QResizeEvent* event) {
}
}
std::string MainWindow::getLastEbootPath() {
return std::string();
}
void MainWindow::AddRecentFiles(QString filePath) {
std::vector<std::string> vec = Config::getRecentFiles();
if (!vec.empty()) {
@ -1226,6 +1233,10 @@ void MainWindow::OnLanguageChanged(const std::string& locale) {
LoadTranslation();
}
static void ShowMessageBox(const std::string& title, const std::string& message) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, title.c_str(), message.c_str(), NULL);
}
bool MainWindow::eventFilter(QObject* obj, QEvent* event) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
@ -1258,3 +1269,33 @@ void MainWindow::StartEmulator(std::filesystem::path path) {
emulator_thread.detach();
#endif
}
void MainWindow::StopGameforUpdate(bool shouldRelaunch) {
if (!isGameRunning) {
return;
}
Core::Emulator& emulator = Core::Emulator::GetInstance();
emulator.StopEmulation();
SDL_Event quitEvent;
quitEvent.type = SDL_EVENT_QUIT;
SDL_PushEvent(&quitEvent);
isGameRunning = false;
}
void MainWindow::StopGame() {
if (!isGameRunning) {
return;
}
Core::Emulator& emulator = Core::Emulator::GetInstance();
emulator.StopEmulation();
if (isGameRunning == true)
;
SDL_Event quitEvent;
quitEvent.type = SDL_EVENT_QUIT + 1;
SDL_PushEvent(&quitEvent);
}

View File

@ -38,6 +38,11 @@ public:
void InstallDragDropPkg(std::filesystem::path file, int pkgNum, int nPkg);
void InstallDirectory();
void StartGame();
void StopGameforUpdate(bool shouldRelaunch);
void StopGame();
std::string lastGamePath;
std::string getLastEbootPath();
bool isGameRunning = false;
private Q_SLOTS:
void ConfigureGuiFromSettings();
@ -65,6 +70,8 @@ private:
void SetUiIcons(bool isWhite);
void InstallPkg();
void BootGame();
bool stopButtonClicked = false;
void AddRecentFiles(QString filePath);
void LoadTranslation();
void PlayBackgroundMusic();
@ -72,7 +79,6 @@ private:
void StartEmulator(std::filesystem::path);
bool isIconBlack = false;
bool isTableList = true;
bool isGameRunning = false;
QActionGroup* m_icon_size_act_group = nullptr;
QActionGroup* m_list_mode_act_group = nullptr;
QActionGroup* m_theme_act_group = nullptr;
@ -127,4 +133,5 @@ protected:
std::filesystem::path last_install_dir = "";
bool delete_file_on_install = false;
bool use_for_all_queued = false;
};

View File

@ -6,6 +6,7 @@
#include <QFileDialog>
#include <QHoverEvent>
#include <fmt/format.h>
#include "main_window.h"
#include "common/config.h"
#include "common/version.h"
@ -167,9 +168,13 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
}
});
connect(ui->checkUpdateButton, &QPushButton::clicked, this, []() {
auto checkUpdate = new CheckUpdate(true);
checkUpdate->exec();
connect(ui->checkUpdateButton, &QPushButton::clicked, this, [this, parent = (parent)]() {
MainWindow* mainWindow = dynamic_cast<MainWindow*>(parent); // Use the captured 'parent'
if (mainWindow) {
auto checkUpdate =
new CheckUpdate(mainWindow, true, this); // Pass MainWindow* and bool
checkUpdate->exec();
}
});
#else
ui->updaterGroupBox->setVisible(false);

View File

@ -1,6 +1,13 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <chrono>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <thread>
#include <sys/stat.h>
#include "SDL3/SDL_events.h"
#include "SDL3/SDL_hints.h"
#include "SDL3/SDL_init.h"
@ -24,6 +31,12 @@
#include "SDL3/SDL_metal.h"
#endif
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
namespace Input {
using Libraries::Pad::OrbisPadButtonDataOffset;
@ -392,11 +405,79 @@ void WindowSDL::WaitEvent() {
case SDL_EVENT_QUIT:
is_open = false;
break;
default:
case SDL_EVENT_QUIT + 1:
is_open = false;
RelaunchEmulator();
break;
}
}
void WindowSDL::RelaunchEmulator() {
#ifdef _WIN32
char emulatorPath[MAX_PATH];
GetModuleFileNameA(nullptr, emulatorPath, MAX_PATH); // Get current executable path
std::string emulatorDir = std::string(emulatorPath);
size_t pos = emulatorDir.find_last_of("\\/");
if (pos != std::string::npos) {
emulatorDir = emulatorDir.substr(0, pos); // Extract directory
}
std::string scriptFileName = std::getenv("TEMP") + std::string("\\relaunch.ps1");
std::ofstream scriptFile(scriptFileName);
if (scriptFile.is_open()) {
scriptFile << "Start-Sleep -Seconds 2\n"
<< "Start-Process -FilePath '" << emulatorPath
<< "' -WorkingDirectory ([WildcardPattern]::Escape('" << emulatorDir << "'))\n";
scriptFile.close();
// Execute PowerShell script
std::string command =
"powershell.exe -ExecutionPolicy Bypass -File \"" + scriptFileName + "\"";
system(command.c_str());
} else {
std::cerr << "Failed to create relaunch script" << std::endl;
}
#elif defined(__linux__) || defined(__APPLE__)
char emulatorPath[1024];
ssize_t count = readlink("/proc/self/exe", emulatorPath, sizeof(emulatorPath) - 1);
if (count != -1) {
emulatorPath[count] = '\0';
} else {
std::cerr << "Failed to get executable path" << std::endl;
return;
}
std::string emulatorDir = std::string(emulatorPath);
size_t pos = emulatorDir.find_last_of("/");
if (pos != std::string::npos) {
emulatorDir = emulatorDir.substr(0, pos); // Extract directory
}
std::string scriptFileName = "/tmp/relaunch.sh";
std::ofstream scriptFile(scriptFileName);
if (scriptFile.is_open()) {
scriptFile << "#!/bin/bash\n"
<< "sleep 2\n"
<< "cd '" << emulatorDir << "'\n"
<< "./'" << emulatorPath + pos + 1 << "' &\n";
scriptFile.close();
// Make script executable
chmod(scriptFileName.c_str(), S_IRWXU);
// Execute bash script
std::string command = "bash " + scriptFileName;
system(command.c_str());
} else {
std::cerr << "Failed to create relaunch script" << std::endl;
}
#endif
}
void WindowSDL::InitTimers() {
SDL_AddTimer(100, &PollController, controller);
SDL_AddTimer(33, Input::MousePolling, (void*)controller);

View File

@ -88,6 +88,8 @@ public:
}
void WaitEvent();
void OnStopButtonClicked();
void RelaunchEmulator();
void InitTimers();
void RequestKeyboard();
@ -106,6 +108,7 @@ private:
SDL_Window* window{};
bool is_shown{};
bool is_open{true};
bool stopButtonClicked = false;
};
} // namespace Frontend