From ebddc40550f9107c7b52f8709a12ef070244f8f0 Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Sat, 17 Feb 2018 18:36:08 -0300
Subject: [PATCH] Add events to shared memory, make it work better with direct
 memory

---
 Ryujinx/OsHle/Handles/HSharedMem.cs | 69 +++++++++++++++++++++++++++--
 Ryujinx/OsHle/Horizon.cs            | 42 +++++++++++++-----
 Ryujinx/OsHle/Process.cs            |  4 +-
 Ryujinx/OsHle/Svc/SvcHandler.cs     |  1 +
 Ryujinx/OsHle/Svc/SvcMemory.cs      | 19 ++++----
 Ryujinx/Switch.cs                   |  9 ++--
 Ryujinx/Ui/Program.cs               |  3 +-
 7 files changed, 116 insertions(+), 31 deletions(-)

diff --git a/Ryujinx/OsHle/Handles/HSharedMem.cs b/Ryujinx/OsHle/Handles/HSharedMem.cs
index 2030ff0a4..a493276a2 100644
--- a/Ryujinx/OsHle/Handles/HSharedMem.cs
+++ b/Ryujinx/OsHle/Handles/HSharedMem.cs
@@ -1,13 +1,76 @@
+using System;
+using System.Collections.Generic;
+
 namespace Ryujinx.OsHle.Handles
 {
     class HSharedMem
     {
-        public long PhysPos { get; private set; }
-        public long VirtPos { get; set; }
+        private List<long> Positions;
+
+        public int PositionsCount => Positions.Count;
+
+        public EventHandler<EventArgs> MemoryMapped;
+        public EventHandler<EventArgs> MemoryUnmapped;
 
         public HSharedMem(long PhysPos)
         {
-            this.PhysPos = PhysPos;
+            Positions = new List<long>();
+        }
+
+        public void AddVirtualPosition(long Position)
+        {
+            lock (Positions)
+            {
+                Positions.Add(Position);
+
+                if (MemoryMapped != null)
+                {
+                    MemoryMapped(this, EventArgs.Empty);
+                }
+            }
+        }
+
+        public void RemoveVirtualPosition(long Position)
+        {
+            lock (Positions)
+            {
+                Positions.Remove(Position);
+
+                if (MemoryUnmapped != null)
+                {
+                    MemoryUnmapped(this, EventArgs.Empty);
+                }
+            }
+        }
+
+        public long GetVirtualPosition(int Index)
+        {
+            lock (Positions)
+            {
+                if (Index < 0 || Index >= Positions.Count)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(Index));
+                }
+
+                return Positions[Index];
+            }
+        }
+
+        public bool TryGetLastVirtualPosition(out long Position)
+        {
+            lock (Positions)
+            {
+                if (Positions.Count > 0)
+                {
+                    Position = Positions[Positions.Count - 1];
+
+                    return true;
+                }
+
+                Position = 0;
+
+                return false;
+            }
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx/OsHle/Horizon.cs b/Ryujinx/OsHle/Horizon.cs
index 01380105c..815495eb6 100644
--- a/Ryujinx/OsHle/Horizon.cs
+++ b/Ryujinx/OsHle/Horizon.cs
@@ -31,6 +31,8 @@ namespace Ryujinx.OsHle
 
         private ConcurrentDictionary<int, Process> Processes;
 
+        private HSharedMem HidSharedMem;
+
         private AMemoryAlloc Allocator;
 
         private Switch Ns;
@@ -56,7 +58,12 @@ namespace Ryujinx.OsHle
             HidOffset  = Allocator.Alloc(HidSize);
             FontOffset = Allocator.Alloc(FontSize);
 
-            HidHandle  = Handles.GenerateId(new HSharedMem(HidOffset));
+            HidSharedMem = new HSharedMem(HidOffset);
+
+            HidSharedMem.MemoryMapped += HidInit;
+
+            HidHandle = Handles.GenerateId(HidSharedMem);
+
             FontHandle = Handles.GenerateId(new HSharedMem(FontOffset));
         }
 
@@ -105,7 +112,7 @@ namespace Ryujinx.OsHle
             Processes.TryAdd(ProcessId, MainProcess);
         }
 
-         public void LoadProgram(string FileName)
+        public void LoadProgram(string FileName)
         {
             int ProcessId = IdGen.GenerateId();
 
@@ -139,18 +146,23 @@ namespace Ryujinx.OsHle
             }
         }
 
-        internal bool ExitProcess(int ProcessId) {
-            Process process;
-            var Success = Processes.TryRemove(ProcessId, out process);
-            if (Success) {
-                process.StopAllThreads();
+        internal bool ExitProcess(int ProcessId)
+        {
+            bool Success = Processes.TryRemove(ProcessId, out Process Process);
+            
+            if (Success)
+            {
+                Process.StopAllThreads();
             }
 
-            if (Processes.Count == 0) {
+            if (Processes.Count == 0)
+            {
                 Ns.OnFinish(EventArgs.Empty);
             }
+
             return Success;
         }
+
         internal bool TryGetProcess(int ProcessId, out Process Process)
         {
             if (!Processes.TryGetValue(ProcessId, out Process))
@@ -176,11 +188,21 @@ namespace Ryujinx.OsHle
             Handles.Delete(Handle);
         }
 
+        private void HidInit(object sender, EventArgs e)
+        {
+            HSharedMem SharedMem = (HSharedMem)sender;
+
+            if (SharedMem.TryGetLastVirtualPosition(out long Position))
+            {
+                Logging.Info($"HID shared memory successfully mapped to {Position:x16}!");
+            }
+        }
+
         public long GetVirtHidOffset()
         {
-            HSharedMem HidSharedMem = Handles.GetData<HSharedMem>(HidHandle);
+            HidSharedMem.TryGetLastVirtualPosition(out long Position);
 
-            return HidSharedMem.VirtPos;
+            return Position;
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx/OsHle/Process.cs b/Ryujinx/OsHle/Process.cs
index d1f020b5d..bb27024f7 100644
--- a/Ryujinx/OsHle/Process.cs
+++ b/Ryujinx/OsHle/Process.cs
@@ -118,7 +118,7 @@ namespace Ryujinx.OsHle
         {
             if (MainThread != null)
             {
-                if (MainThread.Thread.IsAlive)
+                while (MainThread.Thread.IsAlive)
                 {
                     MainThread.Thread.StopExecution();
                 }
@@ -126,7 +126,7 @@ namespace Ryujinx.OsHle
 
             foreach (AThread Thread in TlsSlots.Values)
             {
-                if (Thread.IsAlive)
+                while (Thread.IsAlive)
                 {
                     Thread.StopExecution();
                 }
diff --git a/Ryujinx/OsHle/Svc/SvcHandler.cs b/Ryujinx/OsHle/Svc/SvcHandler.cs
index 2191793a0..eaf410576 100644
--- a/Ryujinx/OsHle/Svc/SvcHandler.cs
+++ b/Ryujinx/OsHle/Svc/SvcHandler.cs
@@ -8,6 +8,7 @@ namespace Ryujinx.OsHle.Svc
     partial class SvcHandler
     {
         private delegate void SvcFunc(ARegisters Registers);
+
         private Dictionary<int, SvcFunc> SvcFuncs;
 
         private Switch  Ns;
diff --git a/Ryujinx/OsHle/Svc/SvcMemory.cs b/Ryujinx/OsHle/Svc/SvcMemory.cs
index f6cef4cc9..4711072d3 100644
--- a/Ryujinx/OsHle/Svc/SvcMemory.cs
+++ b/Ryujinx/OsHle/Svc/SvcMemory.cs
@@ -65,21 +65,18 @@ namespace Ryujinx.OsHle.Svc
 
         private void SvcMapSharedMemory(ARegisters Registers)
         {
-            int  Handle   =  (int)Registers.X0;
-            long Position = (long)Registers.X1;
-            long Size     = (long)Registers.X2;
-            int  Perm     =  (int)Registers.X3;
+            int  Handle =  (int)Registers.X0;
+            long Src    = (long)Registers.X1;
+            long Size   = (long)Registers.X2;
+            int  Perm   =  (int)Registers.X3;
 
-            HSharedMem HndData = Ns.Os.Handles.GetData<HSharedMem>(Handle);
+            HSharedMem SharedMem = Ns.Os.Handles.GetData<HSharedMem>(Handle);
 
-            if (HndData != null)
+            if (SharedMem != null)
             {
-                long Src = Position;
-                long Dst = HndData.PhysPos;
+                SharedMem.AddVirtualPosition(Src);
 
-                HndData.VirtPos = Src;
-
-                Memory.Manager.MapPhys(Position, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm);
+                Memory.Manager.MapPhys(Src, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm);
 
                 Registers.X0 = (int)SvcResult.Success;
             }
diff --git a/Ryujinx/Switch.cs b/Ryujinx/Switch.cs
index e912da86b..0e83a37c0 100644
--- a/Ryujinx/Switch.cs
+++ b/Ryujinx/Switch.cs
@@ -15,6 +15,8 @@ namespace Ryujinx
         internal Horizon   Os  { get; private set; }
         internal VirtualFs VFs { get; private set; }
 
+        public event EventHandler Finish;
+
         public Switch(IGalRenderer Renderer)
         {
             Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize);
@@ -24,15 +26,14 @@ namespace Ryujinx
             VFs = new VirtualFs();
         }
 
-        public event EventHandler Finish;
         internal virtual void OnFinish(EventArgs e)
         {
-            EventHandler Handler = Finish;
-            if (Handler != null)
+            if (Finish != null)
             {
-                Handler(this, e);
+                Finish(this, e);
             }
         }
+
         public void Dispose()
         {
             Dispose(true);
diff --git a/Ryujinx/Ui/Program.cs b/Ryujinx/Ui/Program.cs
index 88a8a117c..2f29411a9 100644
--- a/Ryujinx/Ui/Program.cs
+++ b/Ryujinx/Ui/Program.cs
@@ -50,7 +50,8 @@ namespace Ryujinx
 
             using (GLScreen Screen = new GLScreen(Ns, Renderer))
             {
-                Ns.Finish += (Sender, Args) => {
+                Ns.Finish += (Sender, Args) =>
+                {
                     Screen.Exit();
                 };