summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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.cpp82
-rw-r--r--src/yuzu/main.h1
6 files changed, 65 insertions, 173 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 {
183 Initialize(system); 183 Initialize(system);
184 } 184 }
185 185
186 SystemResultStatus Run() { 186 void Run() {
187 std::unique_lock<std::mutex> lk(suspend_guard); 187 std::unique_lock<std::mutex> lk(suspend_guard);
188 status = SystemResultStatus::Success;
189 188
190 kernel.Suspend(false); 189 kernel.Suspend(false);
191 core_timing.SyncPause(false); 190 core_timing.SyncPause(false);
192 is_paused.store(false, std::memory_order_relaxed); 191 is_paused.store(false, std::memory_order_relaxed);
193
194 return status;
195 } 192 }
196 193
197 SystemResultStatus Pause() { 194 void Pause() {
198 std::unique_lock<std::mutex> lk(suspend_guard); 195 std::unique_lock<std::mutex> lk(suspend_guard);
199 status = SystemResultStatus::Success;
200 196
201 core_timing.SyncPause(true); 197 core_timing.SyncPause(true);
202 kernel.Suspend(true); 198 kernel.Suspend(true);
203 is_paused.store(true, std::memory_order_relaxed); 199 is_paused.store(true, std::memory_order_relaxed);
204
205 return status;
206 } 200 }
207 201
208 bool IsPaused() const { 202 bool IsPaused() const {
@@ -553,12 +547,12 @@ void System::Initialize() {
553 impl->Initialize(*this); 547 impl->Initialize(*this);
554} 548}
555 549
556SystemResultStatus System::Run() { 550void System::Run() {
557 return impl->Run(); 551 impl->Run();
558} 552}
559 553
560SystemResultStatus System::Pause() { 554void System::Pause() {
561 return impl->Pause(); 555 impl->Pause();
562} 556}
563 557
564bool System::IsPaused() const { 558bool 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:
152 * Run the OS and Application 152 * Run the OS and Application
153 * This function will start emulation and run the relevant devices 153 * This function will start emulation and run the relevant devices
154 */ 154 */
155 [[nodiscard]] SystemResultStatus Run(); 155 void Run();
156 156
157 /** 157 /**
158 * Pause the OS and Application 158 * Pause the OS and Application
159 * This function will pause emulation and stop the relevant devices 159 * This function will pause emulation and stop the relevant devices
160 */ 160 */
161 [[nodiscard]] SystemResultStatus Pause(); 161 void Pause();
162 162
163 /// Check if the core is currently paused. 163 /// Check if the core is currently paused.
164 [[nodiscard]] bool IsPaused() const; 164 [[nodiscard]] bool IsPaused() const;
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 1368b20d5..13782869d 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -46,30 +46,28 @@
46 46
47static Core::Frontend::WindowSystemType GetWindowSystemType(); 47static Core::Frontend::WindowSystemType GetWindowSystemType();
48 48
49EmuThread::EmuThread(Core::System& system_) : system{system_} {} 49EmuThread::EmuThread(Core::System& system) : m_system{system} {}
50 50
51EmuThread::~EmuThread() = default; 51EmuThread::~EmuThread() = default;
52 52
53void EmuThread::run() { 53void EmuThread::run() {
54 std::string name = "EmuControlThread"; 54 const char* name = "EmuControlThread";
55 MicroProfileOnThreadCreate(name.c_str()); 55 MicroProfileOnThreadCreate(name);
56 Common::SetCurrentThreadName(name.c_str()); 56 Common::SetCurrentThreadName(name);
57 57
58 auto& gpu = system.GPU(); 58 auto& gpu = m_system.GPU();
59 auto stop_token = stop_source.get_token(); 59 auto stop_token = m_stop_source.get_token();
60 bool debugger_should_start = system.DebuggerEnabled();
61 60
62 system.RegisterHostThread(); 61 m_system.RegisterHostThread();
63 62
64 // Main process has been loaded. Make the context current to this thread and begin GPU and CPU 63 // Main process has been loaded. Make the context current to this thread and begin GPU and CPU
65 // execution. 64 // execution.
66 gpu.ObtainContext(); 65 gpu.ObtainContext();
67 66
68 emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0); 67 emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
69
70 if (Settings::values.use_disk_shader_cache.GetValue()) { 68 if (Settings::values.use_disk_shader_cache.GetValue()) {
71 system.Renderer().ReadRasterizer()->LoadDiskResources( 69 m_system.Renderer().ReadRasterizer()->LoadDiskResources(
72 system.GetCurrentProcessProgramID(), stop_token, 70 m_system.GetCurrentProcessProgramID(), stop_token,
73 [this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) { 71 [this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) {
74 emit LoadProgress(stage, value, total); 72 emit LoadProgress(stage, value, total);
75 }); 73 });
@@ -79,57 +77,35 @@ void EmuThread::run() {
79 gpu.ReleaseContext(); 77 gpu.ReleaseContext();
80 gpu.Start(); 78 gpu.Start();
81 79
82 system.GetCpuManager().OnGpuReady(); 80 m_system.GetCpuManager().OnGpuReady();
81 m_system.RegisterExitCallback([this] { m_stop_source.request_stop(); });
83 82
84 system.RegisterExitCallback([this]() { 83 if (m_system.DebuggerEnabled()) {
85 stop_source.request_stop(); 84 m_system.InitializeDebugger();
86 SetRunning(false); 85 }
87 });
88 86
89 // Holds whether the cpu was running during the last iteration,
90 // so that the DebugModeLeft signal can be emitted before the
91 // next execution step
92 bool was_active = false;
93 while (!stop_token.stop_requested()) { 87 while (!stop_token.stop_requested()) {
94 if (running) { 88 std::unique_lock lk{m_should_run_mutex};
95 if (was_active) { 89 if (m_should_run) {
96 emit DebugModeLeft(); 90 m_system.Run();
97 } 91 m_is_running.store(true);
92 m_is_running.notify_all();
98 93
99 running_guard = true; 94 Common::CondvarWait(m_should_run_cv, lk, stop_token, [&] { return !m_should_run; });
100 Core::SystemResultStatus result = system.Run();
101 if (result != Core::SystemResultStatus::Success) {
102 running_guard = false;
103 this->SetRunning(false);
104 emit ErrorThrown(result, system.GetStatusDetails());
105 }
106
107 if (debugger_should_start) {
108 system.InitializeDebugger();
109 debugger_should_start = false;
110 }
111
112 running_wait.Wait();
113 result = system.Pause();
114 if (result != Core::SystemResultStatus::Success) {
115 running_guard = false;
116 this->SetRunning(false);
117 emit ErrorThrown(result, system.GetStatusDetails());
118 }
119 running_guard = false;
120
121 if (!stop_token.stop_requested()) {
122 was_active = true;
123 emit DebugModeEntered();
124 }
125 } else { 95 } else {
126 std::unique_lock lock{running_mutex}; 96 m_system.Pause();
127 Common::CondvarWait(running_cv, lock, stop_token, [&] { return IsRunning(); }); 97 m_is_running.store(false);
98 m_is_running.notify_all();
99
100 emit DebugModeEntered();
101 Common::CondvarWait(m_should_run_cv, lk, stop_token, [&] { return m_should_run; });
102 emit DebugModeLeft();
128 } 103 }
129 } 104 }
130 105
131 // Shutdown the main emulated process 106 // Shutdown the main emulated process
132 system.ShutdownMainProcess(); 107 m_system.DetachDebugger();
108 m_system.ShutdownMainProcess();
133 109
134#if MICROPROFILE_ENABLED 110#if MICROPROFILE_ENABLED
135 MicroProfileOnThreadExit(); 111 MicroProfileOnThreadExit();
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h
index b24141fd9..1c2e76369 100644
--- a/src/yuzu/bootmanager.h
+++ b/src/yuzu/bootmanager.h
@@ -47,7 +47,7 @@ class EmuThread final : public QThread {
47 Q_OBJECT 47 Q_OBJECT
48 48
49public: 49public:
50 explicit EmuThread(Core::System& system_); 50 explicit EmuThread(Core::System& system);
51 ~EmuThread() override; 51 ~EmuThread() override;
52 52
53 /** 53 /**
@@ -57,30 +57,30 @@ public:
57 void run() override; 57 void run() override;
58 58
59 /** 59 /**
60 * Sets whether the emulation thread is running or not 60 * Sets whether the emulation thread should run or not
61 * @param running_ Boolean value, set the emulation thread to running if true 61 * @param should_run Boolean value, set the emulation thread to running if true
62 * @note This function is thread-safe
63 */ 62 */
64 void SetRunning(bool running_) { 63 void SetRunning(bool should_run) {
65 std::unique_lock lock{running_mutex}; 64 // TODO: Prevent other threads from modifying the state until we finish.
66 running = running_; 65 {
67 lock.unlock(); 66 // Notify the running thread to change state.
68 running_cv.notify_all(); 67 std::unique_lock run_lk{m_should_run_mutex};
69 if (!running) { 68 m_should_run = should_run;
70 running_wait.Set(); 69 m_should_run_cv.notify_one();
71 /// Wait until effectively paused 70 }
72 while (running_guard) 71
73 ; 72 // Wait until paused, if pausing.
73 if (!should_run) {
74 m_is_running.wait(true);
74 } 75 }
75 } 76 }
76 77
77 /** 78 /**
78 * Check if the emulation thread is running or not 79 * Check if the emulation thread is running or not
79 * @return True if the emulation thread is running, otherwise false 80 * @return True if the emulation thread is running, otherwise false
80 * @note This function is thread-safe
81 */ 81 */
82 bool IsRunning() const { 82 bool IsRunning() const {
83 return running; 83 return m_is_running.load();
84 } 84 }
85 85
86 /** 86 /**
@@ -88,18 +88,17 @@ public:
88 */ 88 */
89 void ForceStop() { 89 void ForceStop() {
90 LOG_WARNING(Frontend, "Force stopping EmuThread"); 90 LOG_WARNING(Frontend, "Force stopping EmuThread");
91 stop_source.request_stop(); 91 m_stop_source.request_stop();
92 SetRunning(false);
93 } 92 }
94 93
95private: 94private:
96 bool running = false; 95 Core::System& m_system;
97 std::stop_source stop_source; 96
98 std::mutex running_mutex; 97 std::stop_source m_stop_source;
99 std::condition_variable_any running_cv; 98 std::mutex m_should_run_mutex;
100 Common::Event running_wait{}; 99 std::condition_variable_any m_should_run_cv;
101 std::atomic_bool running_guard{false}; 100 std::atomic<bool> m_is_running{false};
102 Core::System& system; 101 bool m_should_run{true};
103 102
104signals: 103signals:
105 /** 104 /**
@@ -120,8 +119,6 @@ signals:
120 */ 119 */
121 void DebugModeLeft(); 120 void DebugModeLeft();
122 121
123 void ErrorThrown(Core::SystemResultStatus, std::string);
124
125 void LoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total); 122 void LoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total);
126}; 123};
127 124
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index fe140dce0..820f60e61 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1498,7 +1498,7 @@ void GMainWindow::SetupSigInterrupts() {
1498 1498
1499void GMainWindow::HandleSigInterrupt(int sig) { 1499void GMainWindow::HandleSigInterrupt(int sig) {
1500 if (sig == SIGINT) { 1500 if (sig == SIGINT) {
1501 exit(1); 1501 _exit(1);
1502 } 1502 }
1503 1503
1504 // Calling into Qt directly from a signal handler is not safe, 1504 // Calling into Qt directly from a signal handler is not safe,
@@ -1794,15 +1794,16 @@ void GMainWindow::ShutdownGame() {
1794 Settings::values.use_speed_limit.SetValue(true); 1794 Settings::values.use_speed_limit.SetValue(true);
1795 1795
1796 system->SetShuttingDown(true); 1796 system->SetShuttingDown(true);
1797 system->DetachDebugger();
1798 discord_rpc->Pause(); 1797 discord_rpc->Pause();
1799 1798
1800 RequestGameExit(); 1799 RequestGameExit();
1800 emu_thread->disconnect();
1801 emu_thread->SetRunning(true);
1801 1802
1802 emit EmulationStopping(); 1803 emit EmulationStopping();
1803 1804
1804 // Wait for emulation thread to complete and delete it 1805 // Wait for emulation thread to complete and delete it
1805 if (!emu_thread->wait(5000)) { 1806 if (system->DebuggerEnabled() || !emu_thread->wait(5000)) {
1806 emu_thread->ForceStop(); 1807 emu_thread->ForceStop();
1807 emu_thread->wait(); 1808 emu_thread->wait();
1808 } 1809 }
@@ -2919,8 +2920,6 @@ void GMainWindow::OnStartGame() {
2919 2920
2920 emu_thread->SetRunning(true); 2921 emu_thread->SetRunning(true);
2921 2922
2922 connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError);
2923
2924 UpdateMenuState(); 2923 UpdateMenuState();
2925 OnTasStateChanged(); 2924 OnTasStateChanged();
2926 2925
@@ -3904,79 +3903,6 @@ void GMainWindow::OnMouseActivity() {
3904 mouse_center_timer.stop(); 3903 mouse_center_timer.stop();
3905} 3904}
3906 3905
3907void GMainWindow::OnCoreError(Core::SystemResultStatus result, std::string details) {
3908 QMessageBox::StandardButton answer;
3909 QString status_message;
3910 const QString common_message =
3911 tr("The game you are trying to load requires additional files from your Switch to be "
3912 "dumped "
3913 "before playing.<br/><br/>For more information on dumping these files, please see the "
3914 "following wiki page: <a "
3915 "href='https://yuzu-emu.org/wiki/"
3916 "dumping-system-archives-and-the-shared-fonts-from-a-switch-console/'>Dumping System "
3917 "Archives and the Shared Fonts from a Switch Console</a>.<br/><br/>Would you like to "
3918 "quit "
3919 "back to the game list? Continuing emulation may result in crashes, corrupted save "
3920 "data, or other bugs.");
3921 switch (result) {
3922 case Core::SystemResultStatus::ErrorSystemFiles: {
3923 QString message;
3924 if (details.empty()) {
3925 message =
3926 tr("yuzu was unable to locate a Switch system archive. %1").arg(common_message);
3927 } else {
3928 message = tr("yuzu was unable to locate a Switch system archive: %1. %2")
3929 .arg(QString::fromStdString(details), common_message);
3930 }
3931
3932 answer = QMessageBox::question(this, tr("System Archive Not Found"), message,
3933 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
3934 status_message = tr("System Archive Missing");
3935 break;
3936 }
3937
3938 case Core::SystemResultStatus::ErrorSharedFont: {
3939 const QString message =
3940 tr("yuzu was unable to locate the Switch shared fonts. %1").arg(common_message);
3941 answer = QMessageBox::question(this, tr("Shared Fonts Not Found"), message,
3942 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
3943 status_message = tr("Shared Font Missing");
3944 break;
3945 }
3946
3947 default:
3948 answer = QMessageBox::question(
3949 this, tr("Fatal Error"),
3950 tr("yuzu has encountered a fatal error, please see the log for more details. "
3951 "For more information on accessing the log, please see the following page: "
3952 "<a href='https://community.citra-emu.org/t/how-to-upload-the-log-file/296'>How "
3953 "to "
3954 "Upload the Log File</a>.<br/><br/>Would you like to quit back to the game "
3955 "list? "
3956 "Continuing emulation may result in crashes, corrupted save data, or other "
3957 "bugs."),
3958 QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
3959 status_message = tr("Fatal Error encountered");
3960 break;
3961 }
3962
3963 if (answer == QMessageBox::Yes) {
3964 if (emu_thread) {
3965 ShutdownGame();
3966
3967 Settings::RestoreGlobalState(system->IsPoweredOn());
3968 system->HIDCore().ReloadInputDevices();
3969 UpdateStatusButtons();
3970 }
3971 } else {
3972 // Only show the message if the game is still running.
3973 if (emu_thread) {
3974 emu_thread->SetRunning(true);
3975 message_label->setText(status_message);
3976 }
3977 }
3978}
3979
3980void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) { 3906void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
3981 if (behavior == ReinitializeKeyBehavior::Warning) { 3907 if (behavior == ReinitializeKeyBehavior::Warning) {
3982 const auto res = QMessageBox::information( 3908 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:
332 void ResetWindowSize900(); 332 void ResetWindowSize900();
333 void ResetWindowSize1080(); 333 void ResetWindowSize1080();
334 void OnCaptureScreenshot(); 334 void OnCaptureScreenshot();
335 void OnCoreError(Core::SystemResultStatus, std::string);
336 void OnReinitializeKeys(ReinitializeKeyBehavior behavior); 335 void OnReinitializeKeys(ReinitializeKeyBehavior behavior);
337 void OnLanguageChanged(const QString& locale); 336 void OnLanguageChanged(const QString& locale);
338 void OnMouseActivity(); 337 void OnMouseActivity();