From 117e32a6fffc30cdb895aa98483af7df353a8dd1 Mon Sep 17 00:00:00 2001
From: mpnico <mpnico@gmail.com>
Date: Sat, 11 Sep 2021 22:08:25 +0200
Subject: Implement a "Pause Emulation" option & hotkey (#2428)

* Add a "Pause Emulation" option and hotkey

Closes Ryujinx#1604

* Refactoring how pause is handled

* Applied suggested changes from review

* Applied suggested fixes

* Pass correct suspend type to threads for suspend/resume

* Fix NRE after stoping emulation

* Removing SimulateWakeUpMessage call after resuming emulation

* Skip suspending non game process

* Pause the tickCounter in the ExecutionContext

* Refactoring tickCounter pause/resume as suggested

* Fix Config migration to add pause hotkey

* Fixed pausing only application threads

* Fix exiting emulator while paused

* Avoid pause/resume while already paused/resumed

* Cleanup unused code

* Avoid restarting audio if stopping emulation while in pause.

* Added suggested changes

* Fix ConfigurationState
---
 Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs | 55 ++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

(limited to 'Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs')

diff --git a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs
index fbdd812e..a3691808 100644
--- a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs
@@ -1082,5 +1082,60 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
         }
 
         protected override void Destroy() => Context.Dispose();
+
+        public KernelResult SetActivity(bool pause)
+        {
+            KernelContext.CriticalSection.Enter();
+
+            if (State != ProcessState.Exiting && State != ProcessState.Exited)
+            {
+                if (pause)
+                {
+                    if (IsPaused)
+                    {
+                        KernelContext.CriticalSection.Leave();
+
+                        return KernelResult.InvalidState;
+                    }
+
+                    lock (_threadingLock)
+                    {
+                        foreach (KThread thread in _threads)
+                        {
+                            thread.Suspend(ThreadSchedState.ProcessPauseFlag);
+                        }
+                    }
+
+                    IsPaused = true;
+                }
+                else
+                {
+                    if (!IsPaused)
+                    {
+                        KernelContext.CriticalSection.Leave();
+
+                        return KernelResult.InvalidState;
+                    }
+
+                    lock (_threadingLock)
+                    {
+                        foreach (KThread thread in _threads)
+                        {
+                            thread.Resume(ThreadSchedState.ProcessPauseFlag);
+                        }
+                    }
+
+                    IsPaused = false;
+                }
+
+                KernelContext.CriticalSection.Leave();
+
+                return KernelResult.Success;
+            }
+
+            KernelContext.CriticalSection.Leave();
+
+            return KernelResult.InvalidState;
+        }
     }
 }
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2