From 3777fb44cf03d05fdedee00f1a19d30fac73b31b Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Sat, 10 Mar 2018 20:39:16 -0300
Subject: [PATCH] Allow to enable/disable memory checks even on release mode
 through the flag, return error for invalid addresses on SvcMap*Memory svcs,
 do not return error on SvcQueryMemory (instead, return reserved for the end
 of the address space), other minor tweaks

---
 ChocolArm64/AOptimizations.cs                 |   2 +-
 .../Instruction/AInstEmitMemoryHelper.cs      |  86 +++++--
 ChocolArm64/Memory/AMemory.cs                 | 235 ++++++++++++++----
 Ryujinx.Core/Hid/Hid.cs                       | 211 ++++++++--------
 Ryujinx.Core/Loaders/Executable.cs            |  13 +-
 .../Loaders/Executables/IExecutable.cs        |   8 +-
 Ryujinx.Core/Loaders/Executables/Nro.cs       |  18 +-
 Ryujinx.Core/Loaders/Executables/Nso.cs       |  35 ++-
 Ryujinx.Core/OsHle/Horizon.cs                 |   2 +
 Ryujinx.Core/OsHle/Ipc/IpcMessage.cs          |  14 +-
 .../OsHle/Services/Nv/ServiceNvDrv.cs         |  42 ++--
 Ryujinx.Core/OsHle/Svc/SvcMemory.cs           | 107 +++++++-
 Ryujinx.Core/Switch.cs                        |   2 +-
 Ryujinx.Tests/Cpu/CpuTest.cs                  |   2 +-
 Ryujinx/Ui/Program.cs                         |   2 +
 15 files changed, 516 insertions(+), 263 deletions(-)

diff --git a/ChocolArm64/AOptimizations.cs b/ChocolArm64/AOptimizations.cs
index 0cdbd76e..a3c82dcc 100644
--- a/ChocolArm64/AOptimizations.cs
+++ b/ChocolArm64/AOptimizations.cs
@@ -1,4 +1,4 @@
 public static class AOptimizations
 {
-    public static bool EnableMemoryChecks = false;
+    public static bool DisableMemoryChecks = false;
 }
\ No newline at end of file
diff --git a/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs b/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs
index d5a0051b..6ffcf2dc 100644
--- a/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs
+++ b/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs
@@ -45,21 +45,46 @@ namespace ChocolArm64.Instruction
             {
                 switch (Size)
                 {
-                    case 0: Name = nameof(AMemory.ReadVector8);   break;
-                    case 1: Name = nameof(AMemory.ReadVector16);  break;
-                    case 2: Name = nameof(AMemory.ReadVector32);  break;
-                    case 3: Name = nameof(AMemory.ReadVector64);  break;
-                    case 4: Name = nameof(AMemory.ReadVector128); break;
+                    case 0: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.ReadVector8Unchecked)
+                        : nameof(AMemory.ReadVector8); break;
+
+                    case 1: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.ReadVector16Unchecked)
+                        : nameof(AMemory.ReadVector16); break;
+
+                    case 2: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.ReadVector32Unchecked)
+                        : nameof(AMemory.ReadVector32); break;
+
+                    case 3: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.ReadVector64Unchecked)
+                        : nameof(AMemory.ReadVector64); break;
+
+                    case 4: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.ReadVector128Unchecked)
+                        : nameof(AMemory.ReadVector128); break;
                 }
             }
             else
             {
                 switch (Size)
                 {
-                    case 0: Name = nameof(AMemory.ReadByte);   break;
-                    case 1: Name = nameof(AMemory.ReadUInt16); break;
-                    case 2: Name = nameof(AMemory.ReadUInt32); break;
-                    case 3: Name = nameof(AMemory.ReadUInt64); break;
+                    case 0: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.ReadByteUnchecked)
+                        : nameof(AMemory.ReadByte); break;
+
+                    case 1: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.ReadUInt16Unchecked)
+                        : nameof(AMemory.ReadUInt16); break;
+
+                    case 2: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.ReadUInt32Unchecked)
+                        : nameof(AMemory.ReadUInt32); break;
+
+                    case 3: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.ReadUInt64Unchecked)
+                        : nameof(AMemory.ReadUInt64); break;
                 }
             }
             
@@ -107,21 +132,46 @@ namespace ChocolArm64.Instruction
             {
                 switch (Size)
                 {
-                    case 0: Name = nameof(AMemory.WriteVector8);   break;
-                    case 1: Name = nameof(AMemory.WriteVector16);  break;
-                    case 2: Name = nameof(AMemory.WriteVector32);  break;
-                    case 3: Name = nameof(AMemory.WriteVector64);  break;
-                    case 4: Name = nameof(AMemory.WriteVector128); break;
+                    case 0: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.WriteVector8Unchecked)
+                        : nameof(AMemory.WriteVector8); break;
+
+                    case 1: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.WriteVector16Unchecked)
+                        : nameof(AMemory.WriteVector16); break;
+
+                    case 2: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.WriteVector32Unchecked)
+                        : nameof(AMemory.WriteVector32); break;
+
+                    case 3: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.WriteVector64Unchecked)
+                        : nameof(AMemory.WriteVector64); break;
+
+                    case 4: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.WriteVector128Unchecked)
+                        : nameof(AMemory.WriteVector128); break;
                 }
             }
             else
             {
                 switch (Size)
                 {
-                    case 0: Name = nameof(AMemory.WriteByte);   break;
-                    case 1: Name = nameof(AMemory.WriteUInt16); break;
-                    case 2: Name = nameof(AMemory.WriteUInt32); break;
-                    case 3: Name = nameof(AMemory.WriteUInt64); break;
+                    case 0: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.WriteByteUnchecked)
+                        : nameof(AMemory.WriteByte); break;
+
+                    case 1: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.WriteUInt16Unchecked)
+                        : nameof(AMemory.WriteUInt16); break;
+
+                    case 2: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.WriteUInt32Unchecked)
+                        : nameof(AMemory.WriteUInt32); break;
+
+                    case 3: Name = AOptimizations.DisableMemoryChecks
+                        ? nameof(AMemory.WriteUInt64Unchecked)
+                        : nameof(AMemory.WriteUInt64); break;
                 }
             }
 
diff --git a/ChocolArm64/Memory/AMemory.cs b/ChocolArm64/Memory/AMemory.cs
index 7f2dd7d3..d7e11189 100644
--- a/ChocolArm64/Memory/AMemory.cs
+++ b/ChocolArm64/Memory/AMemory.cs
@@ -2,7 +2,6 @@ using ChocolArm64.Exceptions;
 using ChocolArm64.State;
 using System;
 using System.Collections.Generic;
-using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 
 namespace ChocolArm64.Memory
@@ -139,71 +138,77 @@ namespace ChocolArm64.Memory
             }
         }
 
-        public sbyte ReadSByte(long Position) => (sbyte)ReadByte  (Position);
-        public short ReadInt16(long Position) => (short)ReadUInt16(Position);
-        public int   ReadInt32(long Position) =>   (int)ReadUInt32(Position);
-        public long  ReadInt64(long Position) =>  (long)ReadUInt64(Position);
+        public sbyte ReadSByte(long Position)
+        {
+            return (sbyte)ReadByte(Position);
+        }
+
+        public short ReadInt16(long Position)
+        {
+            return (short)ReadUInt16(Position);
+        }
+
+        public int ReadInt32(long Position)
+        {
+            return (int)ReadUInt32(Position);
+        }
+
+        public long ReadInt64(long Position)
+        {
+            return (long)ReadUInt64(Position);
+        }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public byte ReadByte(long Position)
         {
             EnsureAccessIsValid(Position, AMemoryPerm.Read);
 
-            return *((byte*)(RamPtr + (uint)Position));
+            return ReadByteUnchecked(Position);
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public ushort ReadUInt16(long Position)
         {
             EnsureAccessIsValid(Position + 0, AMemoryPerm.Read);
             EnsureAccessIsValid(Position + 1, AMemoryPerm.Read);
 
-            return *((ushort*)(RamPtr + (uint)Position));
+            return ReadUInt16Unchecked(Position);
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public uint ReadUInt32(long Position)
         {
             EnsureAccessIsValid(Position + 0, AMemoryPerm.Read);
             EnsureAccessIsValid(Position + 3, AMemoryPerm.Read);
 
-            return *((uint*)(RamPtr + (uint)Position));
+            return ReadUInt32Unchecked(Position);
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public ulong ReadUInt64(long Position)
         {
             EnsureAccessIsValid(Position + 0, AMemoryPerm.Read);
             EnsureAccessIsValid(Position + 7, AMemoryPerm.Read);
 
-            return *((ulong*)(RamPtr + (uint)Position));
+            return ReadUInt64Unchecked(Position);
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public AVec ReadVector8(long Position)
         {
             return new AVec() { B0 = ReadByte(Position) };
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public AVec ReadVector16(long Position)
         {
             return new AVec() { H0 = ReadUInt16(Position) };
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public AVec ReadVector32(long Position)
         {
             return new AVec() { W0 = ReadUInt32(Position) };
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public AVec ReadVector64(long Position)
         {
             return new AVec() { X0 = ReadUInt64(Position) };
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public AVec ReadVector128(long Position)
         {
             return new AVec()
@@ -213,93 +218,229 @@ namespace ChocolArm64.Memory
             };
         }
 
-        public void WriteSByte(long Position, sbyte Value) => WriteByte  (Position,   (byte)Value);
-        public void WriteInt16(long Position, short Value) => WriteUInt16(Position, (ushort)Value);
-        public void WriteInt32(long Position, int   Value) => WriteUInt32(Position,   (uint)Value);
-        public void WriteInt64(long Position, long  Value) => WriteUInt64(Position,  (ulong)Value);
+        public sbyte ReadSByteUnchecked(long Position)
+        {
+            return (sbyte)ReadByteUnchecked(Position);
+        }
+
+        public short ReadInt16Unchecked(long Position)
+        {
+            return (short)ReadUInt16Unchecked(Position);
+        }
+
+        public int ReadInt32Unchecked(long Position)
+        {
+            return (int)ReadUInt32Unchecked(Position);
+        }
+
+        public long ReadInt64Unchecked(long Position)
+        {
+            return (long)ReadUInt64Unchecked(Position);
+        }
+
+        public byte ReadByteUnchecked(long Position)
+        {
+            return *((byte*)(RamPtr + (uint)Position));
+        }
+
+        public ushort ReadUInt16Unchecked(long Position)
+        {
+            return *((ushort*)(RamPtr + (uint)Position));
+        }
+
+        public uint ReadUInt32Unchecked(long Position)
+        {
+            return *((uint*)(RamPtr + (uint)Position));
+        }
+
+        public ulong ReadUInt64Unchecked(long Position)
+        {
+            return *((ulong*)(RamPtr + (uint)Position));
+        }
+
+        public AVec ReadVector8Unchecked(long Position)
+        {
+            return new AVec() { B0 = ReadByteUnchecked(Position) };
+        }
+
+        public AVec ReadVector16Unchecked(long Position)
+        {
+            return new AVec() { H0 = ReadUInt16Unchecked(Position) };
+        }
+
+        public AVec ReadVector32Unchecked(long Position)
+        {
+            return new AVec() { W0 = ReadUInt32Unchecked(Position) };
+        }
+
+        public AVec ReadVector64Unchecked(long Position)
+        {
+            return new AVec() { X0 = ReadUInt64Unchecked(Position) };
+        }
+
+        public AVec ReadVector128Unchecked(long Position)
+        {
+            return new AVec()
+            {
+                X0 = ReadUInt64Unchecked(Position + 0),
+                X1 = ReadUInt64Unchecked(Position + 8)
+            };
+        }
+
+        public void WriteSByte(long Position, sbyte Value)
+        {
+            WriteByte(Position, (byte)Value);
+        }
+
+        public void WriteInt16(long Position, short Value)
+        {
+            WriteUInt16(Position, (ushort)Value);
+        }
+
+        public void WriteInt32(long Position, int Value)
+        {
+            WriteUInt32(Position, (uint)Value);
+        }
+
+        public void WriteInt64(long Position, long Value)
+        {
+            WriteUInt64(Position, (ulong)Value);
+        }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void WriteByte(long Position, byte Value)
         {
             EnsureAccessIsValid(Position, AMemoryPerm.Write);
 
-            *((byte*)(RamPtr + (uint)Position)) = Value;
+            WriteByteUnchecked(Position, Value);
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void WriteUInt16(long Position, ushort Value)
         {
             EnsureAccessIsValid(Position + 0, AMemoryPerm.Write);
             EnsureAccessIsValid(Position + 1, AMemoryPerm.Write);
 
-            *((ushort*)(RamPtr + (uint)Position)) = Value;
+            WriteUInt16Unchecked(Position, Value);
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void WriteUInt32(long Position, uint Value)
         {
             EnsureAccessIsValid(Position + 0, AMemoryPerm.Write);
             EnsureAccessIsValid(Position + 3, AMemoryPerm.Write);
 
-            *((uint*)(RamPtr + (uint)Position)) = Value;
+            WriteUInt32Unchecked(Position, Value);
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void WriteUInt64(long Position, ulong Value)
         {
             EnsureAccessIsValid(Position + 0, AMemoryPerm.Write);
             EnsureAccessIsValid(Position + 7, AMemoryPerm.Write);
 
-            *((ulong*)(RamPtr + (uint)Position)) = Value;
+            WriteUInt64Unchecked(Position, Value);
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void WriteVector8(long Position, AVec Value)
         {
             WriteByte(Position, Value.B0);
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void WriteVector16(long Position, AVec Value)
         {
             WriteUInt16(Position, Value.H0);
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void WriteVector32(long Position, AVec Value)
         {
             WriteUInt32(Position, Value.W0);
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void WriteVector64(long Position, AVec Value)
         {
             WriteUInt64(Position, Value.X0);
         }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public void WriteVector128(long Position, AVec Value)
         {
             WriteUInt64(Position + 0, Value.X0);
             WriteUInt64(Position + 8, Value.X1);
         }
 
+        public void WriteSByteUnchecked(long Position, sbyte Value)
+        {
+            WriteByteUnchecked(Position, (byte)Value);
+        }
+
+        public void WriteInt16Unchecked(long Position, short Value)
+        {
+            WriteUInt16Unchecked(Position, (ushort)Value);
+        }
+
+        public void WriteInt32Unchecked(long Position, int Value)
+        {
+            WriteUInt32Unchecked(Position, (uint)Value);
+        }
+
+        public void WriteInt64Unchecked(long Position, long Value)
+        {
+            WriteUInt64Unchecked(Position, (ulong)Value);
+        }
+
+        public void WriteByteUnchecked(long Position, byte Value)
+        {
+            *((byte*)(RamPtr + (uint)Position)) = Value;
+        }
+
+        public void WriteUInt16Unchecked(long Position, ushort Value)
+        {
+            *((ushort*)(RamPtr + (uint)Position)) = Value;
+        }
+
+        public void WriteUInt32Unchecked(long Position, uint Value)
+        {
+            *((uint*)(RamPtr + (uint)Position)) = Value;
+        }
+
+        public void WriteUInt64Unchecked(long Position, ulong Value)
+        {
+            *((ulong*)(RamPtr + (uint)Position)) = Value;
+        }
+
+        public void WriteVector8Unchecked(long Position, AVec Value)
+        {
+            WriteByteUnchecked(Position, Value.B0);
+        }
+
+        public void WriteVector16Unchecked(long Position, AVec Value)
+        {
+            WriteUInt16Unchecked(Position, Value.H0);
+        }
+
+        public void WriteVector32Unchecked(long Position, AVec Value)
+        {
+            WriteUInt32Unchecked(Position, Value.W0);
+        }
+
+        public void WriteVector64Unchecked(long Position, AVec Value)
+        {
+            WriteUInt64Unchecked(Position, Value.X0);
+        }
+
+        public void WriteVector128Unchecked(long Position, AVec Value)
+        {
+            WriteUInt64Unchecked(Position + 0, Value.X0);
+            WriteUInt64Unchecked(Position + 8, Value.X1);
+        }
+
         private void EnsureAccessIsValid(long Position, AMemoryPerm Perm)
         {
-#if DEBUG
-            if (AOptimizations.EnableMemoryChecks)
+            if (!Manager.IsMapped(Position))
             {
-                if (!Manager.IsMapped(Position))
-                {
-                    throw new VmmPageFaultException(Position);
-                }
-
-                if (!Manager.HasPermission(Position, Perm))
-                {
-                    throw new VmmAccessViolationException(Position, Perm);
-                }
+                throw new VmmPageFaultException(Position);
+            }
+
+            if (!Manager.HasPermission(Position, Perm))
+            {
+                throw new VmmAccessViolationException(Position, Perm);
             }
-#endif
         }
 
         public void Dispose()
diff --git a/Ryujinx.Core/Hid/Hid.cs b/Ryujinx.Core/Hid/Hid.cs
index 16976889..76ecf5ff 100644
--- a/Ryujinx.Core/Hid/Hid.cs
+++ b/Ryujinx.Core/Hid/Hid.cs
@@ -1,4 +1,5 @@
-using Ryujinx.Core.OsHle.Handles;
+using ChocolArm64.Memory;
+using Ryujinx.Core.OsHle.Handles;
 using System;
 
 namespace Ryujinx.Core.Input
@@ -64,15 +65,11 @@ namespace Ryujinx.Core.Input
 
         private long[] ShMemPositions;
 
-        private long CurrControllerEntry;
-        private long CurrTouchEntry;
-        private long CurrTouchSampleCounter;
+        private AMemory Memory;
 
-        private Switch Ns;
-
-        public Hid(Switch Ns)
+        public Hid(AMemory Memory)
         {
-            this.Ns = Ns;
+            this.Memory = Memory;
 
             ShMemLock = new object();
 
@@ -138,20 +135,20 @@ namespace Ryujinx.Core.Input
 
             HidControllerColorDesc SplitColorDesc = 0;
 
-            Ns.Memory.WriteInt32(BaseControllerOffset + 0x0,  (int)Type);
+            Memory.WriteInt32Unchecked(BaseControllerOffset + 0x0,  (int)Type);
 
-            Ns.Memory.WriteInt32(BaseControllerOffset + 0x4,  IsHalf ? 1 : 0);
+            Memory.WriteInt32Unchecked(BaseControllerOffset + 0x4,  IsHalf ? 1 : 0);
 
-            Ns.Memory.WriteInt32(BaseControllerOffset + 0x8,  (int)SingleColorDesc);
-            Ns.Memory.WriteInt32(BaseControllerOffset + 0xc,  (int)SingleColorBody);
-            Ns.Memory.WriteInt32(BaseControllerOffset + 0x10, (int)SingleColorButtons);
-            Ns.Memory.WriteInt32(BaseControllerOffset + 0x14, (int)SplitColorDesc);
+            Memory.WriteInt32Unchecked(BaseControllerOffset + 0x8,  (int)SingleColorDesc);
+            Memory.WriteInt32Unchecked(BaseControllerOffset + 0xc,  (int)SingleColorBody);
+            Memory.WriteInt32Unchecked(BaseControllerOffset + 0x10, (int)SingleColorButtons);
+            Memory.WriteInt32Unchecked(BaseControllerOffset + 0x14, (int)SplitColorDesc);
 
-            Ns.Memory.WriteInt32(BaseControllerOffset + 0x18, (int)LeftColorBody);
-            Ns.Memory.WriteInt32(BaseControllerOffset + 0x1c, (int)LeftColorButtons);
+            Memory.WriteInt32Unchecked(BaseControllerOffset + 0x18, (int)LeftColorBody);
+            Memory.WriteInt32Unchecked(BaseControllerOffset + 0x1c, (int)LeftColorButtons);
 
-            Ns.Memory.WriteInt32(BaseControllerOffset + 0x20, (int)RightColorBody);
-            Ns.Memory.WriteInt32(BaseControllerOffset + 0x24, (int)RightColorButtons);
+            Memory.WriteInt32Unchecked(BaseControllerOffset + 0x20, (int)RightColorBody);
+            Memory.WriteInt32Unchecked(BaseControllerOffset + 0x24, (int)RightColorButtons);
         }
 
         public void SetJoyconButton(
@@ -165,116 +162,102 @@ namespace Ryujinx.Core.Input
             {
                 foreach (long Position in ShMemPositions)
                 {
-                    WriteJoyconButtons(
-                        Position,
-                        ControllerId,
-                        ControllerLayout,
-                        Buttons,
-                        LeftStick,
-                        RightStick);
+                    long ControllerOffset = Position + HidControllersOffset;
+
+                    ControllerOffset += (int)ControllerId * HidControllerSize;
+
+                    ControllerOffset += HidControllerHeaderSize;
+
+                    ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize;
+
+                    long LastEntry = Memory.ReadInt64Unchecked(ControllerOffset + 0x10);
+
+                    long CurrEntry = (LastEntry + 1) % HidEntryCount;
+
+                    long Timestamp = GetTimestamp();
+
+                    Memory.WriteInt64Unchecked(ControllerOffset + 0x0,  Timestamp);
+                    Memory.WriteInt64Unchecked(ControllerOffset + 0x8,  HidEntryCount);
+                    Memory.WriteInt64Unchecked(ControllerOffset + 0x10, CurrEntry);
+                    Memory.WriteInt64Unchecked(ControllerOffset + 0x18, HidEntryCount - 1);
+
+                    ControllerOffset += HidControllersLayoutHeaderSize;
+
+                    ControllerOffset += CurrEntry * HidControllersInputEntrySize;
+
+                    Memory.WriteInt64Unchecked(ControllerOffset + 0x0,  Timestamp);
+                    Memory.WriteInt64Unchecked(ControllerOffset + 0x8,  Timestamp);
+
+                    Memory.WriteInt64Unchecked(ControllerOffset + 0x10, (uint)Buttons);
+
+                    Memory.WriteInt32Unchecked(ControllerOffset + 0x18, LeftStick.DX);
+                    Memory.WriteInt32Unchecked(ControllerOffset + 0x1c, LeftStick.DY);
+
+                    Memory.WriteInt64Unchecked(ControllerOffset + 0x20, RightStick.DX);
+                    Memory.WriteInt64Unchecked(ControllerOffset + 0x24, RightStick.DY);
+
+                    Memory.WriteInt64Unchecked(ControllerOffset + 0x28,
+                        (uint)HidControllerConnState.Controller_State_Connected |
+                        (uint)HidControllerConnState.Controller_State_Wired);
                 }
             }
         }
 
-        private void WriteJoyconButtons(
-            long                 BasePosition,
-            HidControllerId      ControllerId,
-            HidControllerLayouts ControllerLayout,
-            HidControllerButtons Buttons,
-            HidJoystickPosition  LeftStick,
-            HidJoystickPosition  RightStick)
-        {
-            long ControllerOffset = BasePosition + HidControllersOffset;
-
-            ControllerOffset += (int)ControllerId * HidControllerSize;
-
-            ControllerOffset += HidControllerHeaderSize;
-
-            ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize;
-
-            CurrControllerEntry = (CurrControllerEntry + 1) % HidEntryCount;
-
-            long Timestamp = GetTimestamp();
-
-            Ns.Memory.WriteInt64(ControllerOffset + 0x0,  Timestamp);
-            Ns.Memory.WriteInt64(ControllerOffset + 0x8,  HidEntryCount);
-            Ns.Memory.WriteInt64(ControllerOffset + 0x10, CurrControllerEntry);
-            Ns.Memory.WriteInt64(ControllerOffset + 0x18, HidEntryCount - 1);
-
-            ControllerOffset += HidControllersLayoutHeaderSize;
-
-            ControllerOffset += CurrControllerEntry * HidControllersInputEntrySize;
-
-            Ns.Memory.WriteInt64(ControllerOffset + 0x0,  Timestamp);
-            Ns.Memory.WriteInt64(ControllerOffset + 0x8,  Timestamp);
-
-            Ns.Memory.WriteInt64(ControllerOffset + 0x10, (uint)Buttons);
-
-            Ns.Memory.WriteInt32(ControllerOffset + 0x18, LeftStick.DX);
-            Ns.Memory.WriteInt32(ControllerOffset + 0x1c, LeftStick.DY);
-
-            Ns.Memory.WriteInt32(ControllerOffset + 0x20, RightStick.DX);
-            Ns.Memory.WriteInt32(ControllerOffset + 0x24, RightStick.DY);
-
-            Ns.Memory.WriteInt64(ControllerOffset + 0x28,
-                (uint)HidControllerConnState.Controller_State_Connected |
-                (uint)HidControllerConnState.Controller_State_Wired);
-        }
-
         public void SetTouchPoints(params HidTouchPoint[] Points)
         {
             lock (ShMemLock)
             {
                 foreach (long Position in ShMemPositions)
                 {
-                    WriteTouchPoints(Position, Points);
+                    long TouchScreenOffset = Position + HidTouchScreenOffset;
+
+                    long LastEntry = Memory.ReadInt64Unchecked(TouchScreenOffset + 0x10);
+
+                    long CurrEntry = (LastEntry + 1) % HidEntryCount;
+
+                    long Timestamp = GetTimestamp();
+
+                    Memory.WriteInt64Unchecked(TouchScreenOffset + 0x0,  Timestamp);
+                    Memory.WriteInt64Unchecked(TouchScreenOffset + 0x8,  HidEntryCount);
+                    Memory.WriteInt64Unchecked(TouchScreenOffset + 0x10, CurrEntry);
+                    Memory.WriteInt64Unchecked(TouchScreenOffset + 0x18, HidEntryCount - 1);
+                    Memory.WriteInt64Unchecked(TouchScreenOffset + 0x20, Timestamp);            
+
+                    long TouchEntryOffset = TouchScreenOffset + HidTouchHeaderSize;
+
+                    long LastEntryOffset = TouchEntryOffset + LastEntry * HidTouchEntrySize;
+
+                    long SampleCounter = Memory.ReadInt64Unchecked(LastEntryOffset) + 1;
+
+                    TouchEntryOffset += CurrEntry * HidTouchEntrySize;
+
+                    Memory.WriteInt64Unchecked(TouchEntryOffset + 0x0, SampleCounter);
+                    Memory.WriteInt64Unchecked(TouchEntryOffset + 0x8, Points.Length);
+
+                    TouchEntryOffset += HidTouchEntryHeaderSize;
+
+                    const int Padding = 0;
+
+                    int Index = 0;
+
+                    foreach (HidTouchPoint Point in Points)
+                    {
+                        Memory.WriteInt64Unchecked(TouchEntryOffset + 0x0,  Timestamp);
+                        Memory.WriteInt32Unchecked(TouchEntryOffset + 0x8,  Padding);
+                        Memory.WriteInt32Unchecked(TouchEntryOffset + 0xc,  Index++);
+                        Memory.WriteInt32Unchecked(TouchEntryOffset + 0x10, Point.X);
+                        Memory.WriteInt32Unchecked(TouchEntryOffset + 0x14, Point.Y);
+                        Memory.WriteInt32Unchecked(TouchEntryOffset + 0x18, Point.DiameterX);
+                        Memory.WriteInt32Unchecked(TouchEntryOffset + 0x1c, Point.DiameterY);
+                        Memory.WriteInt32Unchecked(TouchEntryOffset + 0x20, Point.Angle);
+                        Memory.WriteInt32Unchecked(TouchEntryOffset + 0x24, Padding);
+
+                        TouchEntryOffset += HidTouchEntryTouchSize;
+                    }
                 }
             }
         }
 
-        private void WriteTouchPoints(long BasePosition, params HidTouchPoint[] Points)
-        {
-            long TouchScreenOffset = BasePosition + HidTouchScreenOffset;
-
-            long Timestamp = GetTimestamp();
-
-            CurrTouchEntry = (CurrTouchEntry + 1) % HidEntryCount;
-
-            Ns.Memory.WriteInt64(TouchScreenOffset + 0x0,  Timestamp);
-            Ns.Memory.WriteInt64(TouchScreenOffset + 0x8,  HidEntryCount);
-            Ns.Memory.WriteInt64(TouchScreenOffset + 0x10, CurrTouchEntry);
-            Ns.Memory.WriteInt64(TouchScreenOffset + 0x18, HidEntryCount - 1);
-            Ns.Memory.WriteInt64(TouchScreenOffset + 0x20, Timestamp);            
-
-            long TouchEntryOffset = TouchScreenOffset + HidTouchHeaderSize;
-
-            TouchEntryOffset += CurrTouchEntry * HidTouchEntrySize;            
-
-            Ns.Memory.WriteInt64(TouchEntryOffset + 0x0, CurrTouchSampleCounter++);
-            Ns.Memory.WriteInt64(TouchEntryOffset + 0x8, Points.Length);
-
-            TouchEntryOffset += HidTouchEntryHeaderSize;
-
-            const int Padding = 0;
-
-            int Index = 0;
-
-            foreach (HidTouchPoint Point in Points)
-            {
-                Ns.Memory.WriteInt64(TouchEntryOffset + 0x0,  Timestamp);
-                Ns.Memory.WriteInt32(TouchEntryOffset + 0x8,  Padding);
-                Ns.Memory.WriteInt32(TouchEntryOffset + 0xc,  Index++);
-                Ns.Memory.WriteInt32(TouchEntryOffset + 0x10, Point.X);
-                Ns.Memory.WriteInt32(TouchEntryOffset + 0x14, Point.Y);
-                Ns.Memory.WriteInt32(TouchEntryOffset + 0x18, Point.DiameterX);
-                Ns.Memory.WriteInt32(TouchEntryOffset + 0x1c, Point.DiameterY);
-                Ns.Memory.WriteInt32(TouchEntryOffset + 0x20, Point.Angle);
-                Ns.Memory.WriteInt32(TouchEntryOffset + 0x24, Padding);
-
-                TouchEntryOffset += HidTouchEntryTouchSize;
-            }
-        }
-
         private long GetTimestamp()
         {
             return Environment.TickCount * 19_200;
diff --git a/Ryujinx.Core/Loaders/Executable.cs b/Ryujinx.Core/Loaders/Executable.cs
index fa204460..943b8e51 100644
--- a/Ryujinx.Core/Loaders/Executable.cs
+++ b/Ryujinx.Core/Loaders/Executable.cs
@@ -34,7 +34,7 @@ namespace Ryujinx.Core.Loaders
 
             if (Exe.Mod0Offset == 0)
             {
-                int BssOffset = Exe.DataOffset + Exe.Data.Count;
+                int BssOffset = Exe.DataOffset + Exe.Data.Length;
                 int BssSize   = Exe.BssSize;
 
                 MapBss(ImageBase + BssOffset, BssSize);
@@ -92,18 +92,15 @@ namespace Ryujinx.Core.Loaders
 
         private void WriteData(
             long        Position,
-            IList<byte> Data,
+            byte[]      Data,
             MemoryType  Type,
             AMemoryPerm Perm)
         {
-            Memory.Manager.Map(Position, Data.Count, (int)Type, AMemoryPerm.Write);
+            Memory.Manager.Map(Position, Data.Length, (int)Type, AMemoryPerm.Write);
 
-            for (int Index = 0; Index < Data.Count; Index++)
-            {
-                Memory.WriteByte(Position + Index, Data[Index]);
-            }
+            AMemoryHelper.WriteBytes(Memory, Position, Data);
 
-            Memory.Manager.Reprotect(Position, Data.Count, Perm);
+            Memory.Manager.Reprotect(Position, Data.Length, Perm);
         }
 
         private void MapBss(long Position, long Size)
diff --git a/Ryujinx.Core/Loaders/Executables/IExecutable.cs b/Ryujinx.Core/Loaders/Executables/IExecutable.cs
index 73787b1d..09d0aab2 100644
--- a/Ryujinx.Core/Loaders/Executables/IExecutable.cs
+++ b/Ryujinx.Core/Loaders/Executables/IExecutable.cs
@@ -1,12 +1,10 @@
-using System.Collections.ObjectModel;
-
 namespace Ryujinx.Core.Loaders.Executables
 {
     public interface IExecutable
     {
-        ReadOnlyCollection<byte> Text { get; }
-        ReadOnlyCollection<byte> RO   { get; }
-        ReadOnlyCollection<byte> Data { get; }
+        byte[] Text { get; }
+        byte[] RO   { get; }
+        byte[] Data { get; }
 
         int Mod0Offset { get; }
         int TextOffset { get; }
diff --git a/Ryujinx.Core/Loaders/Executables/Nro.cs b/Ryujinx.Core/Loaders/Executables/Nro.cs
index 3cbc4c5d..9f4ef59f 100644
--- a/Ryujinx.Core/Loaders/Executables/Nro.cs
+++ b/Ryujinx.Core/Loaders/Executables/Nro.cs
@@ -1,18 +1,12 @@
-using System;
-using System.Collections.ObjectModel;
 using System.IO;
 
 namespace Ryujinx.Core.Loaders.Executables
 {
     class Nro : IExecutable
     {
-        private byte[] m_Text;
-        private byte[] m_RO;
-        private byte[] m_Data;
-
-        public ReadOnlyCollection<byte> Text => Array.AsReadOnly(m_Text);
-        public ReadOnlyCollection<byte> RO   => Array.AsReadOnly(m_RO);
-        public ReadOnlyCollection<byte> Data => Array.AsReadOnly(m_Data);
+        public byte[] Text { get; private set; }
+        public byte[] RO   { get; private set; }
+        public byte[] Data { get; private set; }
 
         public int Mod0Offset { get; private set; }
         public int TextOffset { get; private set; }
@@ -54,9 +48,9 @@ namespace Ryujinx.Core.Loaders.Executables
                 return Reader.ReadBytes(Size);
             }
 
-            m_Text = Read(TextOffset, TextSize);
-            m_RO   = Read(ROOffset,   ROSize);
-            m_Data = Read(DataOffset, DataSize);
+            Text = Read(TextOffset, TextSize);
+            RO   = Read(ROOffset,   ROSize);
+            Data = Read(DataOffset, DataSize);
         }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.Core/Loaders/Executables/Nso.cs b/Ryujinx.Core/Loaders/Executables/Nso.cs
index 7b8bf253..7341ba62 100644
--- a/Ryujinx.Core/Loaders/Executables/Nso.cs
+++ b/Ryujinx.Core/Loaders/Executables/Nso.cs
@@ -1,19 +1,14 @@
 using Ryujinx.Core.Loaders.Compression;
 using System;
-using System.Collections.ObjectModel;
 using System.IO;
 
 namespace Ryujinx.Core.Loaders.Executables
 {
     class Nso : IExecutable
     {
-        private byte[] m_Text;
-        private byte[] m_RO;
-        private byte[] m_Data;
-
-        public ReadOnlyCollection<byte> Text => Array.AsReadOnly(m_Text);
-        public ReadOnlyCollection<byte> RO   => Array.AsReadOnly(m_RO);
-        public ReadOnlyCollection<byte> Data => Array.AsReadOnly(m_Data);
+        public byte[] Text { get; private set; }
+        public byte[] RO   { get; private set; }
+        public byte[] Data { get; private set; }
 
         public int Mod0Offset { get; private set; }
         public int TextOffset { get; private set; }
@@ -57,9 +52,9 @@ namespace Ryujinx.Core.Loaders.Executables
 
             byte[] BuildId = Reader.ReadBytes(0x20);
 
-            int TextSize   = Reader.ReadInt32();
-            int ROSize     = Reader.ReadInt32();
-            int DataSize   = Reader.ReadInt32();
+            int TextSize = Reader.ReadInt32();
+            int ROSize   = Reader.ReadInt32();
+            int DataSize = Reader.ReadInt32();
 
             Input.Seek(0x24, SeekOrigin.Current);
 
@@ -82,38 +77,38 @@ namespace Ryujinx.Core.Loaders.Executables
             //Text segment
             Input.Seek(TextOffset, SeekOrigin.Begin);
 
-            m_Text = Reader.ReadBytes(TextSize);
+            Text = Reader.ReadBytes(TextSize);
 
             if (Flags.HasFlag(NsoFlags.IsTextCompressed) || true)
             {
-                m_Text = Lz4.Decompress(m_Text, TextDecSize);
+                Text = Lz4.Decompress(Text, TextDecSize);
             }
 
             //Read-only data segment
             Input.Seek(ROOffset, SeekOrigin.Begin);
 
-            m_RO = Reader.ReadBytes(ROSize);
+            RO = Reader.ReadBytes(ROSize);
 
             if (Flags.HasFlag(NsoFlags.IsROCompressed) || true)
             {
-                m_RO = Lz4.Decompress(m_RO, RODecSize);
+                RO = Lz4.Decompress(RO, RODecSize);
             }
 
             //Data segment
             Input.Seek(DataOffset, SeekOrigin.Begin);
 
-            m_Data = Reader.ReadBytes(DataSize);
+            Data = Reader.ReadBytes(DataSize);
 
             if (Flags.HasFlag(NsoFlags.IsDataCompressed) || true)
             {
-                m_Data = Lz4.Decompress(m_Data, DataDecSize);
+                Data = Lz4.Decompress(Data, DataDecSize);
             }
 
-            using (MemoryStream Text = new MemoryStream(m_Text))
+            using (MemoryStream TextMS = new MemoryStream(Text))
             {
-                BinaryReader TextReader = new BinaryReader(Text);
+                BinaryReader TextReader = new BinaryReader(TextMS);
 
-                Text.Seek(4, SeekOrigin.Begin);
+                TextMS.Seek(4, SeekOrigin.Begin);
 
                 Mod0Offset = TextReader.ReadInt32();
             }
diff --git a/Ryujinx.Core/OsHle/Horizon.cs b/Ryujinx.Core/OsHle/Horizon.cs
index a8f5df7c..c61e18e9 100644
--- a/Ryujinx.Core/OsHle/Horizon.cs
+++ b/Ryujinx.Core/OsHle/Horizon.cs
@@ -52,6 +52,8 @@ namespace Ryujinx.Core.OsHle
             HidHandle = Handles.GenerateId(HidSharedMem);
 
             FontHandle = Handles.GenerateId(new HSharedMem());
+
+            HidSharedMem.AddVirtualPosition(0);
         }
 
         public void LoadCart(string ExeFsDir, string RomFsFile = null)
diff --git a/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs b/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs
index cc26df10..ebb3dbca 100644
--- a/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs
+++ b/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs
@@ -217,16 +217,26 @@ namespace Ryujinx.Core.OsHle.Ipc
 
         public long GetSendBuffPtr()
         {
-            if (SendBuff.Count > 0 && SendBuff[0].Position != 0)
+            if (SendBuff.Count > 0 && SendBuff[0].Size != 0)
             {
                 return SendBuff[0].Position;
             }
 
-            if (PtrBuff.Count > 0 && PtrBuff[0].Position != 0)
+            if (PtrBuff.Count > 0 && PtrBuff[0].Size != 0)
             {
                 return PtrBuff[0].Position;
             }
 
+            if (ReceiveBuff.Count > 0 && ReceiveBuff[0].Size != 0)
+            {
+                return ReceiveBuff[0].Position;
+            }
+
+            if (RecvListBuff.Count > 0 && RecvListBuff[0].Size != 0)
+            {
+                return RecvListBuff[0].Position;
+            }
+
             return -1;
         }
     }
diff --git a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs
index 515c15e0..3c0c46fe 100644
--- a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs
+++ b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs
@@ -81,7 +81,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
             
             FileDesc FdData = Context.Ns.Os.Fds.GetData<FileDesc>(Fd);
 
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             Context.ResponseData.Write(0);
 
@@ -139,7 +139,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvGpuAsIoctlBindChannel(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             int Fd = Context.Memory.ReadInt32(Position);
 
@@ -148,7 +148,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvGpuAsIoctlAllocSpace(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             MemReader Reader = new MemReader(Context.Memory, Position);
 
@@ -174,7 +174,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvGpuAsIoctlMapBufferEx(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             MemReader Reader = new MemReader(Context.Memory, Position);
 
@@ -207,7 +207,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvGpuAsIoctlGetVaRegions(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             MemReader Reader = new MemReader(Context.Memory, Position);
             MemWriter Writer = new MemWriter(Context.Memory, Position);
@@ -237,7 +237,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvGpuAsIoctlInitializeEx(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             MemReader Reader = new MemReader(Context.Memory, Position);
 
@@ -254,7 +254,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvHostIoctlCtrlGetConfig(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             MemReader Reader = new MemReader(Context.Memory, Position);
             MemWriter Writer = new MemWriter(Context.Memory, Position + 0x82);
@@ -269,7 +269,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvHostIoctlCtrlEventWait(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             MemReader Reader = new MemReader(Context.Memory, Position);
 
@@ -285,7 +285,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvGpuIoctlZcullGetCtxSize(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             Context.Memory.WriteInt32(Position, 1);
 
@@ -294,7 +294,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvGpuIoctlZcullGetInfo(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             MemWriter Writer = new MemWriter(Context.Memory, Position);
 
@@ -314,7 +314,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvGpuIoctlGetCharacteristics(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             MemReader Reader = new MemReader(Context.Memory, Position);
             MemWriter Writer = new MemWriter(Context.Memory, Position);
@@ -376,7 +376,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvGpuIoctlGetTpcMasks(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             MemReader Reader = new MemReader(Context.Memory, Position);
 
@@ -390,7 +390,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvGpuIoctlZbcGetActiveSlotMask(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             Context.Memory.WriteInt32(Position + 0, 7);
             Context.Memory.WriteInt32(Position + 4, 1);
@@ -400,14 +400,14 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvMapIoctlChannelSetUserData(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             return 0;
         }
 
         private static long NvMapIoctlChannelSetNvMap(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             int Fd = Context.Memory.ReadInt32(Position);
 
@@ -416,7 +416,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvMapIoctlChannelSubmitGpFifo(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             MemReader Reader = new MemReader(Context.Memory, Position);
             MemWriter Writer = new MemWriter(Context.Memory, Position + 0x10);
@@ -455,7 +455,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvMapIoctlChannelAllocObjCtx(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             int ClassNum = Context.Memory.ReadInt32(Position + 0);
             int Flags    = Context.Memory.ReadInt32(Position + 4);
@@ -467,7 +467,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvMapIoctlChannelZcullBind(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             MemReader Reader = new MemReader(Context.Memory, Position);
 
@@ -480,7 +480,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvMapIoctlChannelSetErrorNotifier(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             MemReader Reader = new MemReader(Context.Memory, Position);
 
@@ -494,7 +494,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvMapIoctlChannelSetPriority(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             int Priority = Context.Memory.ReadInt32(Position);
 
@@ -503,7 +503,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
 
         private static long NvMapIoctlChannelAllocGpFifoEx2(ServiceCtx Context)
         {
-            long Position = Context.Request.PtrBuff[0].Position;
+            long Position = Context.Request.GetSendBuffPtr();
 
             MemReader Reader = new MemReader(Context.Memory, Position);
             MemWriter Writer = new MemWriter(Context.Memory, Position + 0xc);
diff --git a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs
index bf946e4f..c15f449b 100644
--- a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs
+++ b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs
@@ -55,6 +55,24 @@ namespace Ryujinx.Core.OsHle.Svc
             long Src  = (long)ThreadState.X1;
             long Size = (long)ThreadState.X2;
 
+            if (!IsValidPosition(Src))
+            {
+                Logging.Warn($"Tried to map Memory at invalid src address {Src:x16}!");
+
+                ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
+
+                return;
+            }
+
+            if (!IsValidMapPosition(Dst))
+            {
+                Logging.Warn($"Tried to map Memory at invalid dst address {Dst:x16}!");
+
+                ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
+
+                return;
+            }
+
             AMemoryMapInfo SrcInfo = Memory.Manager.GetMapInfo(Src);
 
             Memory.Manager.Map(Dst, Size, (int)MemoryType.MappedMemory, SrcInfo.Perm);
@@ -72,6 +90,24 @@ namespace Ryujinx.Core.OsHle.Svc
             long Src  = (long)ThreadState.X1;
             long Size = (long)ThreadState.X2;
 
+            if (!IsValidPosition(Src))
+            {
+                Logging.Warn($"Tried to unmap Memory at invalid src address {Src:x16}!");
+
+                ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
+
+                return;
+            }
+
+            if (!IsValidMapPosition(Dst))
+            {
+                Logging.Warn($"Tried to unmap Memory at invalid dst address {Dst:x16}!");
+
+                ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
+
+                return;
+            }
+
             AMemoryMapInfo DstInfo = Memory.Manager.GetMapInfo(Dst);
 
             Memory.Manager.Unmap(Dst, Size, (int)MemoryType.MappedMemory);
@@ -92,9 +128,11 @@ namespace Ryujinx.Core.OsHle.Svc
 
             if (MapInfo == null)
             {
-                ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
+                long AddrSpaceEnd = MemoryRegions.AddrSpaceStart + MemoryRegions.AddrSpaceSize;
 
-                return;
+                long ReservedSize = (long)(ulong.MaxValue - (ulong)AddrSpaceEnd) + 1;
+
+                MapInfo = new AMemoryMapInfo(AddrSpaceEnd, ReservedSize, (int)MemoryType.Reserved, 0, AMemoryPerm.None);
             }
 
             Memory.WriteInt64(InfoPtr + 0x00, MapInfo.Position);
@@ -118,15 +156,26 @@ namespace Ryujinx.Core.OsHle.Svc
             long Size   = (long)ThreadState.X2;
             int  Perm   =  (int)ThreadState.X3;
 
+            if (!IsValidPosition(Src))
+            {
+                Logging.Warn($"Tried to map SharedMemory at invalid address {Src:x16}!");
+
+                ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
+
+                return;
+            }
+
             HSharedMem SharedMem = Ns.Os.Handles.GetData<HSharedMem>(Handle);
 
             if (SharedMem != null)
             {
+                Memory.Manager.Map(Src, Size, (int)MemoryType.SharedMemory, AMemoryPerm.Write);
+
                 AMemoryHelper.FillWithZeros(Memory, Src, (int)Size);
 
-                SharedMem.AddVirtualPosition(Src);
+                Memory.Manager.Reprotect(Src, Size, (AMemoryPerm)Perm);
 
-                Memory.Manager.Map(Src, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm);
+                SharedMem.AddVirtualPosition(Src);
 
                 ThreadState.X0 = 0;
             }
@@ -136,14 +185,25 @@ namespace Ryujinx.Core.OsHle.Svc
 
         private void SvcUnmapSharedMemory(AThreadState ThreadState)
         {
-            int  Handle   =  (int)ThreadState.X0;
-            long Position = (long)ThreadState.X1;
-            long Size     = (long)ThreadState.X2;
+            int  Handle =  (int)ThreadState.X0;
+            long Src    = (long)ThreadState.X1;
+            long Size   = (long)ThreadState.X2;
+
+            if (!IsValidPosition(Src))
+            {
+                Logging.Warn($"Tried to unmap SharedMemory at invalid address {Src:x16}!");
+
+                ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
+
+                return;
+            }
 
             HSharedMem HndData = Ns.Os.Handles.GetData<HSharedMem>(Handle);
 
             if (HndData != null)
             {
+                Memory.Manager.Unmap(Src, Size, (int)MemoryType.SharedMemory);
+
                 ThreadState.X0 = 0;
             }
 
@@ -152,20 +212,41 @@ namespace Ryujinx.Core.OsHle.Svc
 
         private void SvcCreateTransferMemory(AThreadState ThreadState)
         {
-            long Position = (long)ThreadState.X1;
-            long Size     = (long)ThreadState.X2;
-            int  Perm     =  (int)ThreadState.X3;
+            long Src  = (long)ThreadState.X1;
+            long Size = (long)ThreadState.X2;
+            int  Perm =  (int)ThreadState.X3;
 
-            AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Position);
+            if (!IsValidPosition(Src))
+            {
+                Logging.Warn($"Tried to create TransferMemory at invalid address {Src:x16}!");
 
-            Memory.Manager.Reprotect(Position, Size, (AMemoryPerm)Perm);
+                ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
 
-            HTransferMem HndData = new HTransferMem(Memory, MapInfo.Perm, Position, Size);
+                return;
+            }
+
+            AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Src);
+
+            Memory.Manager.Reprotect(Src, Size, (AMemoryPerm)Perm);
+
+            HTransferMem HndData = new HTransferMem(Memory, MapInfo.Perm, Src, Size);
 
             int Handle = Ns.Os.Handles.GenerateId(HndData);
 
             ThreadState.X1 = (ulong)Handle;
             ThreadState.X0 = 0;
         }
+
+        private static bool IsValidPosition(long Position)
+        {
+            return Position >= MemoryRegions.AddrSpaceStart &&
+                   Position <  MemoryRegions.AddrSpaceStart + MemoryRegions.AddrSpaceSize; 
+        }
+
+        private static bool IsValidMapPosition(long Position)
+        {
+            return Position >= MemoryRegions.MapRegionAddress &&
+                   Position <  MemoryRegions.MapRegionAddress + MemoryRegions.MapRegionSize; 
+        }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.Core/Switch.cs b/Ryujinx.Core/Switch.cs
index dff7802b..f7ce109f 100644
--- a/Ryujinx.Core/Switch.cs
+++ b/Ryujinx.Core/Switch.cs
@@ -30,7 +30,7 @@ namespace Ryujinx.Core
 
             VFs = new VirtualFs();
 
-            Hid = new Hid(this);
+            Hid = new Hid(Memory);
 
             Statistics = new PerformanceStatistics();
 
diff --git a/Ryujinx.Tests/Cpu/CpuTest.cs b/Ryujinx.Tests/Cpu/CpuTest.cs
index c4f0bbd7..0b35a7a6 100644
--- a/Ryujinx.Tests/Cpu/CpuTest.cs
+++ b/Ryujinx.Tests/Cpu/CpuTest.cs
@@ -47,7 +47,7 @@ namespace Ryujinx.Tests.Cpu
 
         protected void Opcode(uint Opcode)
         {
-            Thread.Memory.WriteUInt32(Position, Opcode);
+            Thread.Memory.WriteUInt32Unchecked(Position, Opcode);
             Position += 4;
         }
 
diff --git a/Ryujinx/Ui/Program.cs b/Ryujinx/Ui/Program.cs
index b5f8cb97..b67e52bd 100644
--- a/Ryujinx/Ui/Program.cs
+++ b/Ryujinx/Ui/Program.cs
@@ -10,6 +10,8 @@ namespace Ryujinx
     {
         static void Main(string[] args)
         {
+            AOptimizations.DisableMemoryChecks = true;
+
             Config.Read();
 
             Console.Title = "Ryujinx Console";