Przeglądaj źródła

Allow multiple hid shared memory locations

gdkchan 8 lat temu
rodzic
commit
73cc30cc80

+ 111 - 69
Ryujinx.Core/Hid/Hid.cs

@@ -1,4 +1,6 @@
 using ChocolArm64.Memory;
+using Ryujinx.Core.OsHle.Handles;
+using System;
 using System.Diagnostics;
 
 namespace Ryujinx.Core.Input
@@ -60,33 +62,65 @@ namespace Ryujinx.Core.Input
 
         private const int HidEntryCount = 17;
 
-        private long SharedMemOffset;
+        private object ShMemLock;
 
-        private Switch Ns;
+        private long[] ShMemPositions;
 
-        public Hid(Switch Ns)
+        private IntPtr Ram;
+
+        public Hid(IntPtr Ram)
         {
-            this.Ns = Ns;
+            this.Ram = Ram;
+
+            ShMemLock = new object();
+
+            ShMemPositions = new long[0];
         }
 
-        public void Init(long HidOffset)
+        internal void ShMemMap(object sender, EventArgs e)
         {
-            SharedMemOffset = HidOffset;
+            HSharedMem SharedMem = (HSharedMem)sender;
+
+            lock (ShMemLock)
+            {
+                ShMemPositions = SharedMem.GetVirtualPositions();
+
+                long BasePosition = ShMemPositions[ShMemPositions.Length - 1];
+
+                Logging.Info($"HID shared memory successfully mapped to 0x{BasePosition:x16}!");
+
+                Init(BasePosition);
+            }
+        }
+
+        internal void ShMemUnmap(object sender, EventArgs e)
+        {
+            HSharedMem SharedMem = (HSharedMem)sender;
+
+            lock (ShMemLock)
+            {
+                ShMemPositions = SharedMem.GetVirtualPositions();
+            }
+        }
 
+        private void Init(long BasePosition)
+        {
             InitializeJoyconPair(
+                BasePosition,
                 JoyConColor.Body_Neon_Red,
                 JoyConColor.Buttons_Neon_Red,
                 JoyConColor.Body_Neon_Blue,
                 JoyConColor.Buttons_Neon_Blue);
         }
 
-        public void InitializeJoyconPair(
+        private void InitializeJoyconPair(
+            long        BasePosition,
             JoyConColor LeftColorBody,
             JoyConColor LeftColorButtons,
             JoyConColor RightColorBody,
             JoyConColor RightColorButtons)
         {
-            long BaseControllerOffset = HidControllersOffset + 8 * HidControllerSize;
+            long BaseControllerOffset = BasePosition + HidControllersOffset + 8 * HidControllerSize;
 
             HidControllerType Type =
                 HidControllerType.ControllerType_Handheld |
@@ -125,115 +159,123 @@ namespace Ryujinx.Core.Input
             HidJoystickPosition  LeftStick,
             HidJoystickPosition  RightStick)
         {
-            long ControllerOffset = HidControllersOffset + (int)ControllerId * HidControllerSize;
+            lock (ShMemLock)
+            {
+                foreach (long Position in ShMemPositions)
+                {
+                    long ControllerOffset = Position + HidControllersOffset;
+
+                    ControllerOffset += (int)ControllerId * HidControllerSize;
 
-            ControllerOffset += HidControllerHeaderSize;
+                    ControllerOffset += HidControllerHeaderSize;
 
-            ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize;
+                    ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize;
 
-            long LastEntry = ReadInt64(ControllerOffset + 0x10);
+                    long LastEntry = ReadInt64(ControllerOffset + 0x10);
 
-            long CurrEntry = (LastEntry + 1) % HidEntryCount;
+                    long CurrEntry = (LastEntry + 1) % HidEntryCount;
 
-            long Timestamp = Stopwatch.GetTimestamp();
+                    long Timestamp = Stopwatch.GetTimestamp();
 
-            WriteInt64(ControllerOffset + 0x0,  Timestamp);
-            WriteInt64(ControllerOffset + 0x8,  HidEntryCount);
-            WriteInt64(ControllerOffset + 0x10, CurrEntry);
-            WriteInt64(ControllerOffset + 0x18, HidEntryCount - 1);
+                    WriteInt64(ControllerOffset + 0x0,  Timestamp);
+                    WriteInt64(ControllerOffset + 0x8,  HidEntryCount);
+                    WriteInt64(ControllerOffset + 0x10, CurrEntry);
+                    WriteInt64(ControllerOffset + 0x18, HidEntryCount - 1);
 
-            ControllerOffset += HidControllersLayoutHeaderSize;
+                    ControllerOffset += HidControllersLayoutHeaderSize;
 
-            ControllerOffset += CurrEntry * HidControllersInputEntrySize;
+                    ControllerOffset += CurrEntry * HidControllersInputEntrySize;
 
-            WriteInt64(ControllerOffset + 0x0,  Timestamp);
-            WriteInt64(ControllerOffset + 0x8,  Timestamp);
+                    WriteInt64(ControllerOffset + 0x0,  Timestamp);
+                    WriteInt64(ControllerOffset + 0x8,  Timestamp);
 
-            WriteInt64(ControllerOffset + 0x10, (uint)Buttons);
+                    WriteInt64(ControllerOffset + 0x10, (uint)Buttons);
 
-            WriteInt32(ControllerOffset + 0x18, LeftStick.DX);
-            WriteInt32(ControllerOffset + 0x1c, LeftStick.DY);
+                    WriteInt32(ControllerOffset + 0x18, LeftStick.DX);
+                    WriteInt32(ControllerOffset + 0x1c, LeftStick.DY);
 
-            WriteInt64(ControllerOffset + 0x20, RightStick.DX);
-            WriteInt64(ControllerOffset + 0x24, RightStick.DY);
+                    WriteInt64(ControllerOffset + 0x20, RightStick.DX);
+                    WriteInt64(ControllerOffset + 0x24, RightStick.DY);
 
-            WriteInt64(ControllerOffset + 0x28,
-                (uint)HidControllerConnState.Controller_State_Connected |
-                (uint)HidControllerConnState.Controller_State_Wired);
+                    WriteInt64(ControllerOffset + 0x28,
+                        (uint)HidControllerConnState.Controller_State_Connected |
+                        (uint)HidControllerConnState.Controller_State_Wired);
+                }
+            }
         }
 
         public void SetTouchPoints(params HidTouchPoint[] Points)
         {
-            long LastEntry = ReadInt64(HidTouchScreenOffset + 0x10);
+            lock (ShMemLock)
+            {
+                foreach (long Position in ShMemPositions)
+                {
+                    long TouchScreenOffset = Position + HidTouchScreenOffset;
 
-            long CurrEntry = (LastEntry + 1) % HidEntryCount;
+                    long LastEntry = ReadInt64(TouchScreenOffset + 0x10);
 
-            long Timestamp = Stopwatch.GetTimestamp();
+                    long CurrEntry = (LastEntry + 1) % HidEntryCount;
 
-            WriteInt64(HidTouchScreenOffset + 0x0,  Timestamp);
-            WriteInt64(HidTouchScreenOffset + 0x8,  HidEntryCount);
-            WriteInt64(HidTouchScreenOffset + 0x10, CurrEntry);
-            WriteInt64(HidTouchScreenOffset + 0x18, HidEntryCount - 1);
-            WriteInt64(HidTouchScreenOffset + 0x20, Timestamp);            
+                    long Timestamp = ReadInt64(TouchScreenOffset) + 1;
 
-            long TouchEntryOffset = HidTouchScreenOffset + HidTouchHeaderSize;
+                    WriteInt64(TouchScreenOffset + 0x0,  Timestamp);
+                    WriteInt64(TouchScreenOffset + 0x8,  HidEntryCount);
+                    WriteInt64(TouchScreenOffset + 0x10, CurrEntry);
+                    WriteInt64(TouchScreenOffset + 0x18, HidEntryCount - 1);
+                    WriteInt64(TouchScreenOffset + 0x20, Timestamp);            
 
-            long LastEntryOffset = TouchEntryOffset + LastEntry * HidTouchEntrySize;
+                    long TouchEntryOffset = TouchScreenOffset + HidTouchHeaderSize;
 
-            long LastTimestamp = ReadInt64(LastEntryOffset);
+                    long LastEntryOffset = TouchEntryOffset + LastEntry * HidTouchEntrySize;
 
-            TouchEntryOffset += CurrEntry * HidTouchEntrySize;            
+                    TouchEntryOffset += CurrEntry * HidTouchEntrySize;            
 
-            WriteInt64(TouchEntryOffset + 0x0, LastTimestamp + 1);
-            WriteInt64(TouchEntryOffset + 0x8, Points.Length);
+                    WriteInt64(TouchEntryOffset + 0x0, Timestamp);
+                    WriteInt64(TouchEntryOffset + 0x8, Points.Length);
 
-            TouchEntryOffset += HidTouchEntryHeaderSize;
+                    TouchEntryOffset += HidTouchEntryHeaderSize;
 
-            const int Padding = 0;
+                    const int Padding = 0;
 
-            int Index = 0;
+                    int Index = 0;
 
-            foreach (HidTouchPoint Point in Points)
-            {
-                WriteInt64(TouchEntryOffset + 0x0,  Timestamp);
-                WriteInt32(TouchEntryOffset + 0x8,  Padding);
-                WriteInt32(TouchEntryOffset + 0xc,  Index++);
-                WriteInt32(TouchEntryOffset + 0x10, Point.X);
-                WriteInt32(TouchEntryOffset + 0x14, Point.Y);
-                WriteInt32(TouchEntryOffset + 0x18, Point.DiameterX);
-                WriteInt32(TouchEntryOffset + 0x1c, Point.DiameterY);
-                WriteInt32(TouchEntryOffset + 0x20, Point.Angle);
-                WriteInt32(TouchEntryOffset + 0x24, Padding);
-
-                TouchEntryOffset += HidTouchEntryTouchSize;
+                    foreach (HidTouchPoint Point in Points)
+                    {
+                        WriteInt64(TouchEntryOffset + 0x0,  Timestamp);
+                        WriteInt32(TouchEntryOffset + 0x8,  Padding);
+                        WriteInt32(TouchEntryOffset + 0xc,  Index++);
+                        WriteInt32(TouchEntryOffset + 0x10, Point.X);
+                        WriteInt32(TouchEntryOffset + 0x14, Point.Y);
+                        WriteInt32(TouchEntryOffset + 0x18, Point.DiameterX);
+                        WriteInt32(TouchEntryOffset + 0x1c, Point.DiameterY);
+                        WriteInt32(TouchEntryOffset + 0x20, Point.Angle);
+                        WriteInt32(TouchEntryOffset + 0x24, Padding);
+
+                        TouchEntryOffset += HidTouchEntryTouchSize;
+                    }
+                }
             }
         }
 
         private unsafe long ReadInt64(long Position)
         {
-            Position += SharedMemOffset;
-
             if ((ulong)Position + 8 > AMemoryMgr.AddrSize) return 0;
 
-            return *((long*)((byte*)Ns.Ram + Position));
+            return *((long*)((byte*)Ram + Position));
         }
 
         private unsafe void WriteInt32(long Position, int Value)
         {
-            Position += SharedMemOffset;
-
             if ((ulong)Position + 4 > AMemoryMgr.AddrSize) return;
 
-            *((int*)((byte*)Ns.Ram + Position)) = Value;
+            *((int*)((byte*)Ram + Position)) = Value;
         }
 
         private unsafe void WriteInt64(long Position, long Value)
         {
-            Position += SharedMemOffset;
-
             if ((ulong)Position + 8 > AMemoryMgr.AddrSize) return;
 
-            *((long*)((byte*)Ns.Ram + Position)) = Value;
+            *((long*)((byte*)Ram + Position)) = Value;
         }
     }
 }

+ 2 - 29
Ryujinx.Core/OsHle/Handles/HSharedMem.cs

@@ -7,8 +7,6 @@ namespace Ryujinx.Core.OsHle.Handles
     {
         private List<long> Positions;
 
-        public int PositionsCount => Positions.Count;
-
         public EventHandler<EventArgs> MemoryMapped;
         public EventHandler<EventArgs> MemoryUnmapped;
 
@@ -37,34 +35,9 @@ namespace Ryujinx.Core.OsHle.Handles
             }
         }
 
-        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)
+        public long[] GetVirtualPositions()
         {
-            lock (Positions)
-            {
-                if (Positions.Count > 0)
-                {
-                    Position = Positions[Positions.Count - 1];
-
-                    return true;
-                }
-
-                Position = 0;
-
-                return false;
-            }
+            return Positions.ToArray();
         }
     }
 }

+ 1 - 15
Ryujinx.Core/OsHle/Horizon.cs

@@ -27,7 +27,7 @@ namespace Ryujinx.Core.OsHle
 
         private ConcurrentDictionary<int, Process> Processes;
 
-        private HSharedMem HidSharedMem;
+        internal HSharedMem HidSharedMem;
 
         private Switch Ns;
 
@@ -49,8 +49,6 @@ namespace Ryujinx.Core.OsHle
 
             HidSharedMem = new HSharedMem();
 
-            HidSharedMem.MemoryMapped += HidInit;
-
             HidHandle = Handles.GenerateId(HidSharedMem);
 
             FontHandle = Handles.GenerateId(new HSharedMem());
@@ -166,17 +164,5 @@ namespace Ryujinx.Core.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 0x{Position:x16}!");
-
-                Ns.Hid.Init(Position);
-            }
-        }
     }
 }

+ 8 - 2
Ryujinx.Core/Switch.cs

@@ -27,10 +27,16 @@ namespace Ryujinx.Core
             Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize);
 
             Gpu = new NsGpu(Renderer);
+
             VFs = new VirtualFs();
 
-            Hid      = new Hid(this);
-            Os       = new Horizon(this);
+            Hid = new Hid(Ram);
+
+            Os = new Horizon(this);
+
+            Os.HidSharedMem.MemoryMapped   += Hid.ShMemMap;
+            Os.HidSharedMem.MemoryUnmapped += Hid.ShMemUnmap;
+
             Settings = new SetSys();
         }