Allow multiple hid shared memory locations

This commit is contained in:
gdkchan 2018-03-05 02:09:52 -03:00
parent 344fc8a55d
commit 73cc30cc80
4 changed files with 132 additions and 125 deletions

View File

@ -1,4 +1,6 @@
using ChocolArm64.Memory; using ChocolArm64.Memory;
using Ryujinx.Core.OsHle.Handles;
using System;
using System.Diagnostics; using System.Diagnostics;
namespace Ryujinx.Core.Input namespace Ryujinx.Core.Input
@ -60,33 +62,65 @@ namespace Ryujinx.Core.Input
private const int HidEntryCount = 17; 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( InitializeJoyconPair(
BasePosition,
JoyConColor.Body_Neon_Red, JoyConColor.Body_Neon_Red,
JoyConColor.Buttons_Neon_Red, JoyConColor.Buttons_Neon_Red,
JoyConColor.Body_Neon_Blue, JoyConColor.Body_Neon_Blue,
JoyConColor.Buttons_Neon_Blue); JoyConColor.Buttons_Neon_Blue);
} }
public void InitializeJoyconPair( private void InitializeJoyconPair(
long BasePosition,
JoyConColor LeftColorBody, JoyConColor LeftColorBody,
JoyConColor LeftColorButtons, JoyConColor LeftColorButtons,
JoyConColor RightColorBody, JoyConColor RightColorBody,
JoyConColor RightColorButtons) JoyConColor RightColorButtons)
{ {
long BaseControllerOffset = HidControllersOffset + 8 * HidControllerSize; long BaseControllerOffset = BasePosition + HidControllersOffset + 8 * HidControllerSize;
HidControllerType Type = HidControllerType Type =
HidControllerType.ControllerType_Handheld | HidControllerType.ControllerType_Handheld |
@ -125,115 +159,123 @@ namespace Ryujinx.Core.Input
HidJoystickPosition LeftStick, HidJoystickPosition LeftStick,
HidJoystickPosition RightStick) HidJoystickPosition RightStick)
{ {
long ControllerOffset = HidControllersOffset + (int)ControllerId * HidControllerSize; lock (ShMemLock)
{
foreach (long Position in ShMemPositions)
{
long ControllerOffset = Position + HidControllersOffset;
ControllerOffset += HidControllerHeaderSize; ControllerOffset += (int)ControllerId * HidControllerSize;
ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize; ControllerOffset += HidControllerHeaderSize;
long LastEntry = ReadInt64(ControllerOffset + 0x10); ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize;
long CurrEntry = (LastEntry + 1) % HidEntryCount; long LastEntry = ReadInt64(ControllerOffset + 0x10);
long Timestamp = Stopwatch.GetTimestamp(); long CurrEntry = (LastEntry + 1) % HidEntryCount;
WriteInt64(ControllerOffset + 0x0, Timestamp); long Timestamp = Stopwatch.GetTimestamp();
WriteInt64(ControllerOffset + 0x8, HidEntryCount);
WriteInt64(ControllerOffset + 0x10, CurrEntry);
WriteInt64(ControllerOffset + 0x18, HidEntryCount - 1);
ControllerOffset += HidControllersLayoutHeaderSize; WriteInt64(ControllerOffset + 0x0, Timestamp);
WriteInt64(ControllerOffset + 0x8, HidEntryCount);
WriteInt64(ControllerOffset + 0x10, CurrEntry);
WriteInt64(ControllerOffset + 0x18, HidEntryCount - 1);
ControllerOffset += CurrEntry * HidControllersInputEntrySize; ControllerOffset += HidControllersLayoutHeaderSize;
WriteInt64(ControllerOffset + 0x0, Timestamp); ControllerOffset += CurrEntry * HidControllersInputEntrySize;
WriteInt64(ControllerOffset + 0x8, Timestamp);
WriteInt64(ControllerOffset + 0x10, (uint)Buttons); WriteInt64(ControllerOffset + 0x0, Timestamp);
WriteInt64(ControllerOffset + 0x8, Timestamp);
WriteInt32(ControllerOffset + 0x18, LeftStick.DX); WriteInt64(ControllerOffset + 0x10, (uint)Buttons);
WriteInt32(ControllerOffset + 0x1c, LeftStick.DY);
WriteInt64(ControllerOffset + 0x20, RightStick.DX); WriteInt32(ControllerOffset + 0x18, LeftStick.DX);
WriteInt64(ControllerOffset + 0x24, RightStick.DY); WriteInt32(ControllerOffset + 0x1c, LeftStick.DY);
WriteInt64(ControllerOffset + 0x28, WriteInt64(ControllerOffset + 0x20, RightStick.DX);
(uint)HidControllerConnState.Controller_State_Connected | WriteInt64(ControllerOffset + 0x24, RightStick.DY);
(uint)HidControllerConnState.Controller_State_Wired);
WriteInt64(ControllerOffset + 0x28,
(uint)HidControllerConnState.Controller_State_Connected |
(uint)HidControllerConnState.Controller_State_Wired);
}
}
} }
public void SetTouchPoints(params HidTouchPoint[] Points) public void SetTouchPoints(params HidTouchPoint[] Points)
{ {
long LastEntry = ReadInt64(HidTouchScreenOffset + 0x10); lock (ShMemLock)
long CurrEntry = (LastEntry + 1) % HidEntryCount;
long Timestamp = Stopwatch.GetTimestamp();
WriteInt64(HidTouchScreenOffset + 0x0, Timestamp);
WriteInt64(HidTouchScreenOffset + 0x8, HidEntryCount);
WriteInt64(HidTouchScreenOffset + 0x10, CurrEntry);
WriteInt64(HidTouchScreenOffset + 0x18, HidEntryCount - 1);
WriteInt64(HidTouchScreenOffset + 0x20, Timestamp);
long TouchEntryOffset = HidTouchScreenOffset + HidTouchHeaderSize;
long LastEntryOffset = TouchEntryOffset + LastEntry * HidTouchEntrySize;
long LastTimestamp = ReadInt64(LastEntryOffset);
TouchEntryOffset += CurrEntry * HidTouchEntrySize;
WriteInt64(TouchEntryOffset + 0x0, LastTimestamp + 1);
WriteInt64(TouchEntryOffset + 0x8, Points.Length);
TouchEntryOffset += HidTouchEntryHeaderSize;
const int Padding = 0;
int Index = 0;
foreach (HidTouchPoint Point in Points)
{ {
WriteInt64(TouchEntryOffset + 0x0, Timestamp); foreach (long Position in ShMemPositions)
WriteInt32(TouchEntryOffset + 0x8, Padding); {
WriteInt32(TouchEntryOffset + 0xc, Index++); long TouchScreenOffset = Position + HidTouchScreenOffset;
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; long LastEntry = ReadInt64(TouchScreenOffset + 0x10);
long CurrEntry = (LastEntry + 1) % HidEntryCount;
long Timestamp = ReadInt64(TouchScreenOffset) + 1;
WriteInt64(TouchScreenOffset + 0x0, Timestamp);
WriteInt64(TouchScreenOffset + 0x8, HidEntryCount);
WriteInt64(TouchScreenOffset + 0x10, CurrEntry);
WriteInt64(TouchScreenOffset + 0x18, HidEntryCount - 1);
WriteInt64(TouchScreenOffset + 0x20, Timestamp);
long TouchEntryOffset = TouchScreenOffset + HidTouchHeaderSize;
long LastEntryOffset = TouchEntryOffset + LastEntry * HidTouchEntrySize;
TouchEntryOffset += CurrEntry * HidTouchEntrySize;
WriteInt64(TouchEntryOffset + 0x0, Timestamp);
WriteInt64(TouchEntryOffset + 0x8, Points.Length);
TouchEntryOffset += HidTouchEntryHeaderSize;
const int Padding = 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;
}
}
} }
} }
private unsafe long ReadInt64(long Position) private unsafe long ReadInt64(long Position)
{ {
Position += SharedMemOffset;
if ((ulong)Position + 8 > AMemoryMgr.AddrSize) return 0; 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) private unsafe void WriteInt32(long Position, int Value)
{ {
Position += SharedMemOffset;
if ((ulong)Position + 4 > AMemoryMgr.AddrSize) return; 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) private unsafe void WriteInt64(long Position, long Value)
{ {
Position += SharedMemOffset;
if ((ulong)Position + 8 > AMemoryMgr.AddrSize) return; if ((ulong)Position + 8 > AMemoryMgr.AddrSize) return;
*((long*)((byte*)Ns.Ram + Position)) = Value; *((long*)((byte*)Ram + Position)) = Value;
} }
} }
} }

View File

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

View File

@ -27,7 +27,7 @@ namespace Ryujinx.Core.OsHle
private ConcurrentDictionary<int, Process> Processes; private ConcurrentDictionary<int, Process> Processes;
private HSharedMem HidSharedMem; internal HSharedMem HidSharedMem;
private Switch Ns; private Switch Ns;
@ -49,8 +49,6 @@ namespace Ryujinx.Core.OsHle
HidSharedMem = new HSharedMem(); HidSharedMem = new HSharedMem();
HidSharedMem.MemoryMapped += HidInit;
HidHandle = Handles.GenerateId(HidSharedMem); HidHandle = Handles.GenerateId(HidSharedMem);
FontHandle = Handles.GenerateId(new HSharedMem()); FontHandle = Handles.GenerateId(new HSharedMem());
@ -166,17 +164,5 @@ namespace Ryujinx.Core.OsHle
Handles.Delete(Handle); 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);
}
}
} }
} }

View File

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