From 6ae8d084b418b6f7863d46e5998e39dc8baccd9d Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sat, 7 Oct 2023 22:10:10 +0300 Subject: [PATCH] Use mutex for synchronizing the UI with the emulator thread --- include/panda_qt/main_window.hpp | 7 +++-- src/panda_qt/main_window.cpp | 48 ++++++++++++++++++++++++-------- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/include/panda_qt/main_window.hpp b/include/panda_qt/main_window.hpp index e4a45487..3bbabf35 100644 --- a/include/panda_qt/main_window.hpp +++ b/include/panda_qt/main_window.hpp @@ -6,8 +6,9 @@ #include #include #include -#include #include +#include +#include #include "emulator.hpp" #include "panda_qt/screen.hpp" @@ -27,9 +28,11 @@ class MainWindow : public QMainWindow { std::thread emuThread; std::atomic appRunning = true; // Is the application itself running? - std::atomic needToLoadROM = false; + std::mutex messageQueueMutex; // Used for synchronizing messages between the emulator and UI std::filesystem::path romToLoad = ""; + bool needToLoadROM = false; + ScreenWidget screen; QComboBox* themeSelect = nullptr; QMenuBar* menuBar = nullptr; diff --git a/src/panda_qt/main_window.cpp b/src/panda_qt/main_window.cpp index 8c57e335..809f56e0 100644 --- a/src/panda_qt/main_window.cpp +++ b/src/panda_qt/main_window.cpp @@ -70,13 +70,17 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent) void MainWindow::emuThreadMainLoop() { while (appRunning) { - if (needToLoadROM.load()) { - bool success = emu->loadROM(romToLoad); - if (!success) { - printf("Failed to load ROM"); - } + { + std::unique_lock lock(messageQueueMutex); - needToLoadROM.store(false, std::memory_order::seq_cst); + if (needToLoadROM) { + needToLoadROM = false; + + bool success = emu->loadROM(romToLoad); + if (!success) { + printf("Failed to load ROM"); + } + } } emu->runFrame(); @@ -99,17 +103,22 @@ void MainWindow::swapEmuBuffer() { void MainWindow::selectROM() { // Are we already waiting for a ROM to be loaded? Then complain about it! - if (needToLoadROM.load()) { - QMessageBox::warning(this, tr("Already loading ROM"), tr("Panda3DS is already busy loading a ROM, please wait")); - return; + { + std::unique_lock lock(messageQueueMutex); + if (needToLoadROM) { + QMessageBox::warning(this, tr("Already loading ROM"), tr("Panda3DS is already busy loading a ROM, please wait")); + return; + } } auto path = QFileDialog::getOpenFileName(this, tr("Select 3DS ROM to load"), "", tr("Nintendo 3DS ROMs (*.3ds *.cci *.cxi *.app *.3dsx *.elf *.axf)")); if (!path.isEmpty()) { + std::unique_lock lock(messageQueueMutex); + romToLoad = path.toStdU16String(); - needToLoadROM.store(true, std::memory_order_seq_cst); + needToLoadROM = true; } } @@ -184,7 +193,6 @@ void MainWindow::setTheme(Theme theme) { } void MainWindow::dumpRomFS() { - // TODO: LOCK FILE MUTEX HERE auto folder = QFileDialog::getExistingDirectory( this, tr("Select folder to dump RomFS files to"), "", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks ); @@ -192,7 +200,23 @@ void MainWindow::dumpRomFS() { if (folder.isEmpty()) { return; } - std::filesystem::path path(folder.toStdU16String()); + + // TODO: This might break if the game accesses RomFS while we're dumping, we should move it to the emulator thread when we've got a message queue going + messageQueueMutex.lock(); RomFS::DumpingResult res = emu->dumpRomFS(path); + messageQueueMutex.unlock(); + + switch (res) { + case RomFS::DumpingResult::Success: break; // Yay! + case RomFS::DumpingResult::InvalidFormat: + QMessageBox::warning( + this, tr("Invalid format for RomFS dumping"), tr("The currently loaded app is not in a format that supports RomFS!") + ); + break; + + case RomFS::DumpingResult::NoRomFS: + QMessageBox::warning(this, tr("No RomFS found"), tr("No RomFS partition was found in the loaded app")); + break; + } } \ No newline at end of file