summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/core.cpp18
-rw-r--r--src/core/core.h4
-rw-r--r--src/yuzu/bootmanager.cpp82
-rw-r--r--src/yuzu/bootmanager.h51
-rw-r--r--src/yuzu/main.cpp80
-rw-r--r--src/yuzu/main.h1
6 files changed, 64 insertions, 172 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index a738f221f..47292cd78 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -183,26 +183,20 @@ struct System::Impl {
Initialize(system);
}
- SystemResultStatus Run() {
+ void Run() {
std::unique_lock<std::mutex> lk(suspend_guard);
- status = SystemResultStatus::Success;
kernel.Suspend(false);
core_timing.SyncPause(false);
is_paused.store(false, std::memory_order_relaxed);
-
- return status;
}
- SystemResultStatus Pause() {
+ void Pause() {
std::unique_lock<std::mutex> lk(suspend_guard);
- status = SystemResultStatus::Success;
core_timing.SyncPause(true);
kernel.Suspend(true);
is_paused.store(true, std::memory_order_relaxed);
-
- return status;
}
bool IsPaused() const {
@@ -553,12 +547,12 @@ void System::Initialize() {
impl->Initialize(*this);
}
-SystemResultStatus System::Run() {
- return impl->Run();
+void System::Run() {
+ impl->Run();
}
-SystemResultStatus System::Pause() {
- return impl->Pause();
+void System::Pause() {
+ impl->Pause();
}
bool System::IsPaused() const {
diff --git a/src/core/core.h b/src/core/core.h
index 4ebedffd9..fb5cda2f5 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -152,13 +152,13 @@ public:
* Run the OS and Application
* This function will start emulation and run the relevant devices
*/
- [[nodiscard]] SystemResultStatus Run();
+ void Run();
/**
* Pause the OS and Application
* This function will pause emulation and stop the relevant devices
*/
- [[nodiscard]] SystemResultStatus Pause();
+ void Pause();
/// Check if the core is currently paused.
[[nodiscard]] bool IsPaused() const;
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 682b37f47..40b3d91fc 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -46,30 +46,28 @@
static Core::Frontend::WindowSystemType GetWindowSystemType();
-EmuThread::EmuThread(Core::System& system_) : system{system_} {}
+EmuThread::EmuThread(Core::System& system) : m_system{system} {}
EmuThread::~EmuThread() = default;
void EmuThread::run() {
- std::string name = "EmuControlThread";
- MicroProfileOnThreadCreate(name.c_str());
- Common::SetCurrentThreadName(name.c_str());
+ const char* name = "EmuControlThread";
+ MicroProfileOnThreadCreate(name);
+ Common::SetCurrentThreadName(name);
- auto& gpu = system.GPU();
- auto stop_token = stop_source.get_token();
- bool debugger_should_start = system.DebuggerEnabled();
+ auto& gpu = m_system.GPU();
+ auto stop_token = m_stop_source.get_token();
- system.RegisterHostThread();
+ m_system.RegisterHostThread();
// Main process has been loaded. Make the context current to this thread and begin GPU and CPU
// execution.
gpu.ObtainContext();
emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
-
if (Settings::values.use_disk_shader_cache.GetValue()) {
- system.Renderer().ReadRasterizer()->LoadDiskResources(
- system.GetCurrentProcessProgramID(), stop_token,
+ m_system.Renderer().ReadRasterizer()->LoadDiskResources(
+ m_system.GetCurrentProcessProgramID(), stop_token,
[this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) {
emit LoadProgress(stage, value, total);
});
@@ -79,57 +77,35 @@ void EmuThread::run() {
gpu.ReleaseContext();
gpu.Start();
- system.GetCpuManager().OnGpuReady();
+ m_system.GetCpuManager().OnGpuReady();
+ m_system.RegisterExitCallback([this] { m_stop_source.request_stop(); });
- system.RegisterExitCallback([this]() {
- stop_source.request_stop();
- SetRunning(false);
- });
+ if (m_system.DebuggerEnabled()) {
+ m_system.InitializeDebugger();
+ }
- // Holds whether the cpu was running during the last iteration,
- // so that the DebugModeLeft signal can be emitted before the
- // next execution step
- bool was_active = false;
while (!stop_token.stop_requested()) {
- if (running) {
- if (was_active) {
- emit DebugModeLeft();
- }
+ std::unique_lock lk{m_should_run_mutex};
+ if (m_should_run) {
+ m_system.Run();
+ m_is_running.store(true);
+ m_is_running.notify_all();
- running_guard = true;
- Core::SystemResultStatus result = system.Run();
- if (result != Core::SystemResultStatus::Success) {
- running_guard = false;
- this->SetRunning(false);
- emit ErrorThrown(result, system.GetStatusDetails());
- }
-
- if (debugger_should_start) {
- system.InitializeDebugger();
- debugger_should_start = false;
- }
-
- running_wait.Wait();
- result = system.Pause();
- if (result != Core::SystemResultStatus::Success) {
- running_guard = false;
- this->SetRunning(false);
- emit ErrorThrown(result, system.GetStatusDetails());
- }
- running_guard = false;
-
- if (!stop_token.stop_requested()) {
- was_active = true;
- emit DebugModeEntered();
- }
+ Common::CondvarWait(m_should_run_cv, lk, stop_token, [&] { return !m_should_run; });
} else {
- std::unique_lock lock{running_mutex};
- Common::CondvarWait(running_cv, lock, stop_token, [&] { return IsRunning(); });
+ m_system.Pause();
+ m_is_running.store(false);
+ m_is_running.notify_all();
+
+ emit DebugModeEntered();
+ Common::CondvarWait(m_should_run_cv, lk, stop_token, [&] { return m_should_run; });
+ emit DebugModeLeft();
}
}
// Shutdown the main emulated process
- system.ShutdownMainProcess();
+ m_system.DetachDebugger();
+ m_system.ShutdownMainProcess();
#if MICROPROFILE_ENABLED
MicroProfileOnThreadExit();
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index 5bbcf61f7..52867d628 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -47,7 +47,7 @@ class EmuThread final : public QThread {
Q_OBJECT
public:
- explicit EmuThread(Core::System& system_);
+ explicit EmuThread(Core::System& system);
~EmuThread() override;
/**
@@ -57,30 +57,30 @@ public:
void run() override;
/**
- * Sets whether the emulation thread is running or not
- * @param running_ Boolean value, set the emulation thread to running if true
- * @note This function is thread-safe
+ * Sets whether the emulation thread should run or not
+ * @param should_run Boolean value, set the emulation thread to running if true
*/
- void SetRunning(bool running_) {
- std::unique_lock lock{running_mutex};
- running = running_;
- lock.unlock();
- running_cv.notify_all();
- if (!running) {
- running_wait.Set();
- /// Wait until effectively paused
- while (running_guard)
- ;
+ void SetRunning(bool should_run) {
+ // TODO: Prevent other threads from modifying the state until we finish.
+ {
+ // Notify the running thread to change state.
+ std::unique_lock run_lk{m_should_run_mutex};
+ m_should_run = should_run;
+ m_should_run_cv.notify_one();
+ }
+
+ // Wait until paused, if pausing.
+ if (!should_run) {
+ m_is_running.wait(true);
}
}
/**
* Check if the emulation thread is running or not
* @return True if the emulation thread is running, otherwise false
- * @note This function is thread-safe
*/
bool IsRunning() const {
- return running;
+ return m_is_running.load();
}
/**
@@ -88,18 +88,17 @@ public:
*/
void ForceStop() {
LOG_WARNING(Frontend, "Force stopping EmuThread");
- stop_source.request_stop();
- SetRunning(false);
+ m_stop_source.request_stop();
}
private:
- bool running = false;
- std::stop_source stop_source;
- std::mutex running_mutex;
- std::condition_variable_any running_cv;
- Common::Event running_wait{};
- std::atomic_bool running_guard{false};
- Core::System& system;
+ Core::System& m_system;
+
+ std::stop_source m_stop_source;
+ std::mutex m_should_run_mutex;
+ std::condition_variable_any m_should_run_cv;
+ std::atomic<bool> m_is_running{false};
+ bool m_should_run{true};
signals:
/**
@@ -120,8 +119,6 @@ signals:
*/
void DebugModeLeft();
- void ErrorThrown(Core::SystemResultStatus, std::string);
-
void LoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total);
};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 2e6c2311a..c5285ffc9 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1794,15 +1794,16 @@ void GMainWindow::ShutdownGame() {
Settings::values.use_speed_limit.SetValue(true);
system->SetShuttingDown(true);
- system->DetachDebugger();
discord_rpc->Pause();
RequestGameExit();
+ emu_thread->disconnect();
+ emu_thread->SetRunning(true);
emit EmulationStopping();
// Wait for emulation thread to complete and delete it
- if (!emu_thread->wait(5000)) {
+ if (system->DebuggerEnabled() || !emu_thread->wait(5000)) {
emu_thread->ForceStop();
emu_thread->wait();
}
@@ -2916,8 +2917,6 @@ void GMainWindow::OnStartGame() {
emu_thread->SetRunning(true);
- connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError);
-
UpdateMenuState();
OnTasStateChanged();
@@ -3901,79 +3900,6 @@ void GMainWindow::OnMouseActivity() {
mouse_center_timer.stop();
}
-void GMainWindow::OnCoreError(Core::SystemResultStatus result, std::string details) {
- QMessageBox::StandardButton answer;
- QString status_message;
- const QString common_message =
- tr("The game you are trying to load requires additional files from your Switch to be "
- "dumped "
- "before playing.<br/><br/>For more information on dumping these files, please see the "
- "following wiki page: <a "
- "href='https://yuzu-emu.org/wiki/"
- "dumping-system-archives-and-the-shared-fonts-from-a-switch-console/'>Dumping System "
- "Archives and the Shared Fonts from a Switch Console</a>.<br/><br/>Would you like to "
- "quit "
- "back to the game list? Continuing emulation may result in crashes, corrupted save "
- "data, or other bugs.");
- switch (result) {
- case Core::SystemResultStatus::ErrorSystemFiles: {
- QString message;
- if (details.empty()) {
- message =
- tr("yuzu was unable to locate a Switch system archive. %1").arg(common_message);
- } else {
- message = tr("yuzu was unable to locate a Switch system archive: %1. %2")
- .arg(QString::fromStdString(details), common_message);
- }
-
- answer = QMessageBox::question(this, tr("System Archive Not Found"), message,
- QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
- status_message = tr("System Archive Missing");
- break;
- }
-
- case Core::SystemResultStatus::ErrorSharedFont: {
- const QString message =
- tr("yuzu was unable to locate the Switch shared fonts. %1").arg(common_message);
- answer = QMessageBox::question(this, tr("Shared Fonts Not Found"), message,
- QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
- status_message = tr("Shared Font Missing");
- break;
- }
-
- default:
- answer = QMessageBox::question(
- this, tr("Fatal Error"),
- tr("yuzu has encountered a fatal error, please see the log for more details. "
- "For more information on accessing the log, please see the following page: "
- "<a href='https://community.citra-emu.org/t/how-to-upload-the-log-file/296'>How "
- "to "
- "Upload the Log File</a>.<br/><br/>Would you like to quit back to the game "
- "list? "
- "Continuing emulation may result in crashes, corrupted save data, or other "
- "bugs."),
- QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
- status_message = tr("Fatal Error encountered");
- break;
- }
-
- if (answer == QMessageBox::Yes) {
- if (emu_thread) {
- ShutdownGame();
-
- Settings::RestoreGlobalState(system->IsPoweredOn());
- system->HIDCore().ReloadInputDevices();
- UpdateStatusButtons();
- }
- } else {
- // Only show the message if the game is still running.
- if (emu_thread) {
- emu_thread->SetRunning(true);
- message_label->setText(status_message);
- }
- }
-}
-
void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
if (behavior == ReinitializeKeyBehavior::Warning) {
const auto res = QMessageBox::information(
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 1047ba276..5b84c7a00 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -332,7 +332,6 @@ private slots:
void ResetWindowSize900();
void ResetWindowSize1080();
void OnCaptureScreenshot();
- void OnCoreError(Core::SystemResultStatus, std::string);
void OnReinitializeKeys(ReinitializeKeyBehavior behavior);
void OnLanguageChanged(const QString& locale);
void OnMouseActivity();