diff --git a/ChocolArm64/Memory/AMemory.cs b/ChocolArm64/Memory/AMemory.cs
index f2abffbf47..0d202fed30 100644
--- a/ChocolArm64/Memory/AMemory.cs
+++ b/ChocolArm64/Memory/AMemory.cs
@@ -41,9 +41,9 @@ namespace ChocolArm64.Memory
 
         private byte* RamPtr;
 
-        public AMemory(IntPtr Ram, AMemoryAlloc Allocator)
+        public AMemory(IntPtr Ram)
         {
-            Manager = new AMemoryMgr(Allocator);
+            Manager = new AMemoryMgr();
 
             Monitors = new Dictionary<int, ExMonitor>();
 
diff --git a/ChocolArm64/Memory/AMemoryAlloc.cs b/ChocolArm64/Memory/AMemoryAlloc.cs
deleted file mode 100644
index b11e779314..0000000000
--- a/ChocolArm64/Memory/AMemoryAlloc.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using ChocolArm64.Exceptions;
-
-namespace ChocolArm64.Memory
-{
-    public class AMemoryAlloc
-    {
-        private long PhysPos;
-
-        public long Alloc(long Size)
-        {
-            long Position = PhysPos;
-
-            Size = AMemoryHelper.PageRoundUp(Size);
-
-            PhysPos += Size;
-
-            if (PhysPos > AMemoryMgr.RamSize || PhysPos < 0)
-            {
-                throw new VmmOutOfMemoryException(Size);
-            }
-
-            return Position;
-        }
-
-        public void Free(long Position)
-        {
-            //TODO
-        }
-
-        public long GetFreeMem()
-        {
-            return AMemoryMgr.RamSize - PhysPos;
-        }
-    }
-}
\ No newline at end of file
diff --git a/ChocolArm64/Memory/AMemoryMapInfo.cs b/ChocolArm64/Memory/AMemoryMapInfo.cs
index 44b2cc079e..02dd3055cc 100644
--- a/ChocolArm64/Memory/AMemoryMapInfo.cs
+++ b/ChocolArm64/Memory/AMemoryMapInfo.cs
@@ -1,6 +1,6 @@
 namespace ChocolArm64.Memory
 {
-    public struct AMemoryMapInfo
+    public class AMemoryMapInfo
     {
         public long Position { get; private set; }
         public long Size     { get; private set; }
diff --git a/ChocolArm64/Memory/AMemoryMgr.cs b/ChocolArm64/Memory/AMemoryMgr.cs
index c8869e03e1..bc36445242 100644
--- a/ChocolArm64/Memory/AMemoryMgr.cs
+++ b/ChocolArm64/Memory/AMemoryMgr.cs
@@ -1,3 +1,5 @@
+using System;
+
 namespace ChocolArm64.Memory
 {
     public class AMemoryMgr
@@ -5,22 +7,20 @@ namespace ChocolArm64.Memory
         public const long AddrSize = RamSize;
         public const long RamSize  = 4L * 1024 * 1024 * 1024;
 
-        private const int  PTLvl0Bits = 11;
-        private const int  PTLvl1Bits = 13;
-        private const int  PTPageBits = 12;
+        private const int PTLvl0Bits = 10;
+        private const int PTLvl1Bits = 10;
+        private const int PTPageBits = 12;
 
-        private const int  PTLvl0Size = 1 << PTLvl0Bits;
-        private const int  PTLvl1Size = 1 << PTLvl1Bits;
-        public  const int  PageSize   = 1 << PTPageBits;
+        private const int PTLvl0Size = 1 << PTLvl0Bits;
+        private const int PTLvl1Size = 1 << PTLvl1Bits;
+        public  const int PageSize   = 1 << PTPageBits;
 
-        private const int  PTLvl0Mask = PTLvl0Size - 1;
-        private const int  PTLvl1Mask = PTLvl1Size - 1;
-        public  const int  PageMask   = PageSize   - 1;
+        private const int PTLvl0Mask = PTLvl0Size - 1;
+        private const int PTLvl1Mask = PTLvl1Size - 1;
+        public  const int PageMask   = PageSize   - 1;
 
-        private const int  PTLvl0Bit  = PTPageBits + PTLvl0Bits;
-        private const int  PTLvl1Bit  = PTPageBits;
-
-        private AMemoryAlloc Allocator;
+        private const int PTLvl0Bit  = PTPageBits + PTLvl1Bits;
+        private const int PTLvl1Bit  = PTPageBits;
 
         private enum PTMap
         {
@@ -47,132 +47,24 @@ namespace ChocolArm64.Memory
 
         private PTEntry[][] PageTable;
 
-        private bool IsHeapInitialized;
-
-        public long HeapAddr { get; private set; }
-        public long HeapSize { get; private set; }
-
-        public AMemoryMgr(AMemoryAlloc Allocator)
+        public AMemoryMgr()
         {
-            this.Allocator = Allocator;
-
             PageTable = new PTEntry[PTLvl0Size][];
         }
 
-        public long GetTotalMemorySize()
+        public void Map(long Position, long Size, int Type, AMemoryPerm Perm)
         {
-            return Allocator.GetFreeMem() + GetUsedMemorySize();
+            SetPTEntry(Position, Size, new PTEntry(PTMap.Mapped, Perm, Type, 0));
         }
 
-        public long GetUsedMemorySize()
+        public void Unmap(long Position, long Size)
         {
-            long Size = 0;
-
-            for (int L0 = 0; L0 < PageTable.Length; L0++)
-            {
-                if (PageTable[L0] == null)
-                {
-                    continue;
-                }
-
-                for (int L1 = 0; L1 < PageTable[L0].Length; L1++)
-                {
-                    Size += PageTable[L0][L1].Map != PTMap.Unmapped ? PageSize : 0;
-                }
-            }
-
-            return Size;
+            SetPTEntry(Position, Size, new PTEntry(PTMap.Unmapped, 0, 0, 0));
         }
 
-        public bool SetHeapAddr(long Position)
+        public void Unmap(long Position, long Size, int Type)
         {
-            if (!IsHeapInitialized)
-            {
-                HeapAddr = Position;
-
-                IsHeapInitialized = true;
-
-                return true;
-            }
-
-            return false;
-        }
-
-        public void SetHeapSize(long Size, int Type)
-        {
-            //TODO: Return error when theres no enough space to allocate heap.
-            Size = AMemoryHelper.PageRoundUp(Size);
-
-            long Position = HeapAddr;
-
-            if ((ulong)Size < (ulong)HeapSize)
-            {
-                //Try to free now free area if size is smaller than old size.
-                Position += Size;
-
-                while ((ulong)Size < (ulong)HeapSize)
-                {
-                    Allocator.Free(Position);
-
-                    Position += PageSize;
-                }
-            }
-            else
-            {
-                //Allocate extra needed size.
-                Position += HeapSize;
-                Size     -= HeapSize;
-
-                MapPhys(Position, Size, Type, AMemoryPerm.RW);
-            }
-
-            HeapSize = Size;
-        }
-
-        public void MapPhys(long Position, long Size, int Type, AMemoryPerm Perm)
-        {
-            while (Size > 0)
-            {
-                if (!IsMapped(Position))
-                {
-                    SetPTEntry(Position, new PTEntry(PTMap.Mapped, Perm, Type, 0));
-                }
-
-                long CPgSize = PageSize - (Position & PageMask);
-
-                Position += CPgSize;
-                Size     -= CPgSize;
-            }
-        }
-
-        public void MapMirror(long Src, long Dst, long Size, int Type)
-        {
-            Src = AMemoryHelper.PageRoundDown(Src);
-            Dst = AMemoryHelper.PageRoundDown(Dst);
-
-            Size = AMemoryHelper.PageRoundUp(Size);
-
-            long PagesCount = Size / PageSize;
-
-            while (PagesCount-- > 0)
-            {
-                PTEntry SrcEntry = GetPTEntry(Src);
-                PTEntry DstEntry = GetPTEntry(Dst);
-
-                DstEntry.Map  = PTMap.Mapped;
-                DstEntry.Type = Type;
-                DstEntry.Perm = SrcEntry.Perm;
-
-                SrcEntry.Perm = AMemoryPerm.None;
-
-                SrcEntry.Attr |= 1;
-
-                SetPTEntry(Src, SrcEntry);
-                SetPTEntry(Dst, DstEntry);
-
-                Src += PageSize;
-                Dst += PageSize;
-            }
+            SetPTEntry(Position, Size, Type, new PTEntry(PTMap.Unmapped, 0, 0, 0));
         }
 
         public void Reprotect(long Position, long Size, AMemoryPerm Perm)
@@ -197,12 +89,22 @@ namespace ChocolArm64.Memory
 
         public AMemoryMapInfo GetMapInfo(long Position)
         {
+            if (!IsValidPosition(Position))
+            {
+                return null;
+            }
+
             Position = AMemoryHelper.PageRoundDown(Position);
 
             PTEntry BaseEntry = GetPTEntry(Position);
 
             bool IsSameSegment(long Pos)
             {
+                if (!IsValidPosition(Pos))
+                {
+                    return false;
+                }
+
                 PTEntry Entry = GetPTEntry(Pos);
 
                 return Entry.Map  == BaseEntry.Map  &&
@@ -269,6 +171,16 @@ namespace ChocolArm64.Memory
             return GetPTEntry(Position).Perm.HasFlag(Perm);
         }
 
+        public bool IsValidPosition(long Position)
+        {
+            if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
+            {
+                return false;
+            }
+
+            return true;
+        }
+
         public bool IsMapped(long Position)
         {
             if (Position >> PTLvl0Bits + PTLvl1Bits + PTPageBits != 0)
@@ -300,8 +212,38 @@ namespace ChocolArm64.Memory
             return PageTable[L0][L1];
         }
 
+        private void SetPTEntry(long Position, long Size, PTEntry Entry)
+        {
+            while (Size > 0)
+            {
+                SetPTEntry(Position, Entry);
+
+                Position += PageSize;
+                Size     -= PageSize;
+            }
+        }
+
+        private void SetPTEntry(long Position, long Size, int Type, PTEntry Entry)
+        {
+            while (Size > 0)
+            {
+                if (GetPTEntry(Position).Type == Type)
+                {
+                    SetPTEntry(Position, Entry);
+                }
+
+                Position += PageSize;
+                Size     -= PageSize;
+            }
+        }
+
         private void SetPTEntry(long Position, PTEntry Entry)
         {
+            if (!IsValidPosition(Position))
+            {
+                throw new ArgumentOutOfRangeException(nameof(Position));
+            }
+
             long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
             long L1 = (Position >> PTLvl1Bit) & PTLvl1Mask;
 
diff --git a/Ryujinx.Core/Loaders/Executable.cs b/Ryujinx.Core/Loaders/Executable.cs
index 95cb7d6f6c..fa204460f6 100644
--- a/Ryujinx.Core/Loaders/Executable.cs
+++ b/Ryujinx.Core/Loaders/Executable.cs
@@ -96,7 +96,7 @@ namespace Ryujinx.Core.Loaders
             MemoryType  Type,
             AMemoryPerm Perm)
         {
-            Memory.Manager.MapPhys(Position, Data.Count, (int)Type, AMemoryPerm.Write);
+            Memory.Manager.Map(Position, Data.Count, (int)Type, AMemoryPerm.Write);
 
             for (int Index = 0; Index < Data.Count; Index++)
             {
@@ -108,7 +108,7 @@ namespace Ryujinx.Core.Loaders
 
         private void MapBss(long Position, long Size)
         {
-            Memory.Manager.MapPhys(Position, Size, (int)MemoryType.Normal, AMemoryPerm.RW);
+            Memory.Manager.Map(Position, Size, (int)MemoryType.Normal, AMemoryPerm.RW);
         }
 
         private ElfRel GetRelocation(long Position)
diff --git a/Ryujinx.Core/OsHle/Handles/HSharedMem.cs b/Ryujinx.Core/OsHle/Handles/HSharedMem.cs
index 3d56ff9209..9cd0a0d47e 100644
--- a/Ryujinx.Core/OsHle/Handles/HSharedMem.cs
+++ b/Ryujinx.Core/OsHle/Handles/HSharedMem.cs
@@ -12,7 +12,7 @@ namespace Ryujinx.Core.OsHle.Handles
         public EventHandler<EventArgs> MemoryMapped;
         public EventHandler<EventArgs> MemoryUnmapped;
 
-        public HSharedMem(long PhysPos)
+        public HSharedMem()
         {
             Positions = new List<long>();
         }
diff --git a/Ryujinx.Core/OsHle/Homebrew.cs b/Ryujinx.Core/OsHle/Homebrew.cs
index f177b37e36..e2e95e4d41 100644
--- a/Ryujinx.Core/OsHle/Homebrew.cs
+++ b/Ryujinx.Core/OsHle/Homebrew.cs
@@ -7,7 +7,7 @@ namespace Ryujinx.Core.OsHle
         //http://switchbrew.org/index.php?title=Homebrew_ABI
         public static void WriteHbAbiData(AMemory Memory, long Position, int MainThreadHandle)
         {
-            Memory.Manager.MapPhys(Position, AMemoryMgr.PageSize, (int)MemoryType.Normal, AMemoryPerm.RW);
+            Memory.Manager.Map(Position, AMemoryMgr.PageSize, (int)MemoryType.Normal, AMemoryPerm.RW);
 
             //MainThreadHandle
             WriteConfigEntry(Memory, ref Position, 1, 0, MainThreadHandle);
diff --git a/Ryujinx.Core/OsHle/Horizon.cs b/Ryujinx.Core/OsHle/Horizon.cs
index 9929102d60..c238914398 100644
--- a/Ryujinx.Core/OsHle/Horizon.cs
+++ b/Ryujinx.Core/OsHle/Horizon.cs
@@ -1,4 +1,3 @@
-using ChocolArm64.Memory;
 using Ryujinx.Core.Loaders.Executables;
 using Ryujinx.Core.OsHle.Handles;
 using Ryujinx.Core.OsHle.Utilities;
@@ -16,9 +15,6 @@ namespace Ryujinx.Core.OsHle
         internal int HidHandle  { get; private set; }
         internal int FontHandle { get; private set; }
 
-        public long HidOffset  { get; private set; }
-        public long FontOffset { get; private set; }
-
         internal IdPool IdGen    { get; private set; }
         internal IdPool NvMapIds { get; private set; }
 
@@ -33,8 +29,6 @@ namespace Ryujinx.Core.OsHle
 
         private HSharedMem HidSharedMem;
 
-        private AMemoryAlloc Allocator;
-
         private Switch Ns;
 
         public Horizon(Switch Ns)
@@ -53,18 +47,13 @@ namespace Ryujinx.Core.OsHle
 
             Processes = new ConcurrentDictionary<int, Process>();
 
-            Allocator = new AMemoryAlloc();
-
-            HidOffset  = Allocator.Alloc(HidSize);
-            FontOffset = Allocator.Alloc(FontSize);
-
-            HidSharedMem = new HSharedMem(HidOffset);
+            HidSharedMem = new HSharedMem();
 
             HidSharedMem.MemoryMapped += HidInit;
 
             HidHandle = Handles.GenerateId(HidSharedMem);
 
-            FontHandle = Handles.GenerateId(new HSharedMem(FontOffset));
+            FontHandle = Handles.GenerateId(new HSharedMem());
         }
 
         public void LoadCart(string ExeFsDir, string RomFsFile = null)
@@ -76,7 +65,7 @@ namespace Ryujinx.Core.OsHle
 
             int ProcessId = IdGen.GenerateId();
 
-            Process MainProcess = new Process(Ns, Allocator, ProcessId);
+            Process MainProcess = new Process(Ns, ProcessId);
 
             void LoadNso(string FileName)
             {
@@ -106,7 +95,6 @@ namespace Ryujinx.Core.OsHle
             LoadNso("subsdk*");
             LoadNso("sdk");
 
-            MainProcess.InitializeHeap();
             MainProcess.Run();
 
             Processes.TryAdd(ProcessId, MainProcess);
@@ -118,7 +106,7 @@ namespace Ryujinx.Core.OsHle
 
             int ProcessId = IdGen.GenerateId();
 
-            Process MainProcess = new Process(Ns, Allocator, ProcessId);
+            Process MainProcess = new Process(Ns, ProcessId);
 
             using (FileStream Input = new FileStream(FileName, FileMode.Open))
             {
@@ -128,7 +116,6 @@ namespace Ryujinx.Core.OsHle
             }
 
             MainProcess.SetEmptyArgs();
-            MainProcess.InitializeHeap();
             MainProcess.Run(IsNro);
 
             Processes.TryAdd(ProcessId, MainProcess);
@@ -186,7 +173,7 @@ namespace Ryujinx.Core.OsHle
 
             if (SharedMem.TryGetLastVirtualPosition(out long Position))
             {
-                Logging.Info($"HID shared memory successfully mapped to {Position:x16}!");
+                Logging.Info($"HID shared memory successfully mapped to 0x{Position:x16}!");
 
                 Ns.Hid.Init(Position);
             }
diff --git a/Ryujinx.Core/OsHle/MemoryInfo.cs b/Ryujinx.Core/OsHle/MemoryInfo.cs
deleted file mode 100644
index 76a4bef3ba..0000000000
--- a/Ryujinx.Core/OsHle/MemoryInfo.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using ChocolArm64.Memory;
-
-namespace Ryujinx.Core.OsHle
-{
-    struct MemoryInfo
-    {
-        public long BaseAddress;
-        public long Size;
-        public int  MemType;
-        public int  MemAttr;
-        public int  MemPerm;
-        public int  IpcRefCount;
-        public int  DeviceRefCount;
-        public int  Padding; //SBZ
-
-        public MemoryInfo(AMemoryMapInfo MapInfo)
-        {
-            BaseAddress    = MapInfo.Position;
-            Size           = MapInfo.Size;
-            MemType        = MapInfo.Type;
-            MemAttr        = MapInfo.Attr;
-            MemPerm        = (int)MapInfo.Perm;
-            IpcRefCount    = 0;
-            DeviceRefCount = 0;
-            Padding        = 0;
-        }
-    }
-}
\ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/MemoryRegions.cs b/Ryujinx.Core/OsHle/MemoryRegions.cs
index 86d266f60d..3b69042607 100644
--- a/Ryujinx.Core/OsHle/MemoryRegions.cs
+++ b/Ryujinx.Core/OsHle/MemoryRegions.cs
@@ -1,11 +1,28 @@
+using ChocolArm64.Memory;
+
 namespace Ryujinx.Core.OsHle
 {
     static class MemoryRegions
     {
-        public const long MapRegionAddress = 0x80000000;
+        public const long AddrSpaceStart = 0x08000000;
+
+        public const long MapRegionAddress = 0x10000000;
         public const long MapRegionSize    = 0x40000000;
 
+        public const long MainStackSize = 0x100000;
+
+        public const long MainStackAddress = AMemoryMgr.AddrSize - MainStackSize;
+
+        public const long TlsPagesSize = 0x4000;
+
+        public const long TlsPagesAddress = MainStackAddress - TlsPagesSize;
+
         public const long HeapRegionAddress = MapRegionAddress + MapRegionSize;
-        public const long HeapRegionSize    = 0x40000000;
+
+        public const long TotalMemoryUsed = HeapRegionAddress + TlsPagesSize + MainStackSize;
+
+        public const long TotalMemoryAvailable = AMemoryMgr.RamSize - AddrSpaceStart;
+
+        public const long AddrSpaceSize = AMemoryMgr.AddrSize - AddrSpaceStart;
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Process.cs b/Ryujinx.Core/OsHle/Process.cs
index 9ca9a2bd5c..f0b568c8ce 100644
--- a/Ryujinx.Core/OsHle/Process.cs
+++ b/Ryujinx.Core/OsHle/Process.cs
@@ -15,19 +15,15 @@ namespace Ryujinx.Core.OsHle
 {
     public class Process : IDisposable
     {
-        private const int  MaxStackSize  = 8 * 1024 * 1024;
-
         private const int  TlsSize       = 0x200;
         private const int  TotalTlsSlots = 32;
-        private const int  TlsTotalSize  = TotalTlsSlots * TlsSize;
-        private const long TlsPageAddr   = (AMemoryMgr.AddrSize - TlsTotalSize) & ~AMemoryMgr.PageMask;
 
         private Switch Ns;
 
-        private ATranslator Translator;
-
         public int ProcessId { get; private set; }
 
+        private ATranslator Translator;
+
         public AMemory Memory { get; private set; }
 
         public KProcessScheduler Scheduler { get; private set; }
@@ -44,12 +40,12 @@ namespace Ryujinx.Core.OsHle
 
         private long ImageBase;
 
-        public Process(Switch Ns, AMemoryAlloc Allocator, int ProcessId)
+        public Process(Switch Ns, int ProcessId)
         {
             this.Ns        = Ns;
             this.ProcessId = ProcessId;
 
-            Memory = new AMemory(Ns.Ram, Allocator);
+            Memory = new AMemory(Ns.Ram);
 
             Scheduler = new KProcessScheduler();
 
@@ -61,13 +57,12 @@ namespace Ryujinx.Core.OsHle
 
             Executables = new List<Executable>();
 
-            ImageBase = 0x8000000;
+            ImageBase = MemoryRegions.AddrSpaceStart;
 
-            Memory.Manager.MapPhys(
-                TlsPageAddr,
-                TlsTotalSize,
-                (int)MemoryType.ThreadLocal,
-                AMemoryPerm.RW);
+            MapRWMemRegion(
+                MemoryRegions.TlsPagesAddress,
+                MemoryRegions.TlsPagesSize,
+                MemoryType.ThreadLocal);
         }
 
         public void LoadProgram(IExecutable Program)
@@ -86,11 +81,6 @@ namespace Ryujinx.Core.OsHle
             ImageBase += AMemoryMgr.PageSize;
         }
 
-        public void InitializeHeap()
-        {
-            Memory.Manager.SetHeapAddr(MemoryRegions.HeapRegionAddress);
-        }
-
         public bool Run(bool UseHbAbi = false)
         {
             if (Executables.Count == 0)
@@ -98,11 +88,14 @@ namespace Ryujinx.Core.OsHle
                 return false;
             }
 
-            long StackBot = TlsPageAddr - MaxStackSize;
+            MapRWMemRegion(
+                MemoryRegions.MainStackAddress,
+                MemoryRegions.MainStackSize,
+                MemoryType.Normal);
+            
+            long StackTop = MemoryRegions.MainStackAddress + MemoryRegions.MainStackSize;
 
-            Memory.Manager.MapPhys(StackBot, MaxStackSize, (int)MemoryType.Normal, AMemoryPerm.RW);
-
-            int Handle = MakeThread(Executables[0].ImageBase, TlsPageAddr, 0, 0, 0);
+            int Handle = MakeThread(Executables[0].ImageBase, StackTop, 0, 0, 0);
 
             if (Handle == -1)
             {
@@ -113,7 +106,7 @@ namespace Ryujinx.Core.OsHle
 
             if (UseHbAbi)
             {
-                long HbAbiDataPosition = (Executables[0].ImageEnd + 0xfff) & ~0xfff;
+                long HbAbiDataPosition = AMemoryHelper.PageRoundUp(Executables[0].ImageEnd);
 
                 Homebrew.WriteHbAbiData(Memory, HbAbiDataPosition, Handle);
 
@@ -126,6 +119,11 @@ namespace Ryujinx.Core.OsHle
             return true;
         }
 
+        private void MapRWMemRegion(long Position, long Size, MemoryType Type)
+        {
+            Memory.Manager.Map(Position, Size, (int)Type, AMemoryPerm.RW);
+        }
+
         public void StopAllThreads()
         {
             if (MainThread != null)
@@ -188,12 +186,14 @@ namespace Ryujinx.Core.OsHle
                 return -1;
             }
 
+            long Tpidr = MemoryRegions.TlsPagesAddress + TlsSlot * TlsSize;
+
             Thread.ThreadState.Break     += BreakHandler;
             Thread.ThreadState.SvcCall   += SvcHandler.SvcCall;
             Thread.ThreadState.Undefined += UndefinedHandler;
             Thread.ThreadState.ProcessId  = ProcessId;
             Thread.ThreadState.ThreadId   = Ns.Os.IdGen.GenerateId();
-            Thread.ThreadState.Tpidr      = TlsPageAddr + TlsSlot * TlsSize;
+            Thread.ThreadState.Tpidr      = Tpidr;
             Thread.ThreadState.X0         = (ulong)ArgsPtr;
             Thread.ThreadState.X1         = (ulong)Handle;
             Thread.ThreadState.X31        = (ulong)StackTop;
@@ -267,7 +267,7 @@ namespace Ryujinx.Core.OsHle
 
         private int GetTlsSlot(long Position)
         {
-            return (int)((Position - TlsPageAddr) / TlsSize);
+            return (int)((Position - MemoryRegions.TlsPagesAddress) / TlsSize);
         }
 
         public HThread GetThread(long Tpidr)
diff --git a/Ryujinx.Core/OsHle/Svc/SvcHandler.cs b/Ryujinx.Core/OsHle/Svc/SvcHandler.cs
index ec53f47ff2..212d30a6c3 100644
--- a/Ryujinx.Core/OsHle/Svc/SvcHandler.cs
+++ b/Ryujinx.Core/OsHle/Svc/SvcHandler.cs
@@ -17,6 +17,8 @@ namespace Ryujinx.Core.OsHle.Svc
         private AMemory Memory;
 
         private static Random Rng;
+        
+        private ulong CurrentHeapSize;
 
         public SvcHandler(Switch Ns, Process Process)
         {
@@ -25,6 +27,7 @@ namespace Ryujinx.Core.OsHle.Svc
                 { 0x01, SvcSetHeapSize                   },
                 { 0x03, SvcSetMemoryAttribute            },
                 { 0x04, SvcMapMemory                     },
+                { 0x05, SvcUnmapMemory                   },
                 { 0x06, SvcQueryMemory                   },
                 { 0x07, SvcExitProcess                   },
                 { 0x08, SvcCreateThread                  },
diff --git a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs
index 6ca27f16d0..e7559a1408 100644
--- a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs
+++ b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs
@@ -10,10 +10,21 @@ namespace Ryujinx.Core.OsHle.Svc
         {
             uint Size = (uint)ThreadState.X1;
 
-            Memory.Manager.SetHeapSize(Size, (int)MemoryType.Heap);
+            long Position = MemoryRegions.HeapRegionAddress;
+
+            if (Size > CurrentHeapSize)
+            {
+                Memory.Manager.Map(Position, Size, (int)MemoryType.Heap, AMemoryPerm.RW);
+            }
+            else
+            {
+                Memory.Manager.Unmap(Position + Size, (long)CurrentHeapSize - Size);
+            }
+
+            CurrentHeapSize = Size;
 
             ThreadState.X0 = (int)SvcResult.Success;
-            ThreadState.X1 = (ulong)Memory.Manager.HeapAddr;
+            ThreadState.X1 = (ulong)Position;
         }
 
         private void SvcSetMemoryAttribute(AThreadState ThreadState)
@@ -42,7 +53,30 @@ namespace Ryujinx.Core.OsHle.Svc
             long Src  = (long)ThreadState.X1;
             long Size = (long)ThreadState.X2;
 
-            Memory.Manager.MapMirror(Src, Dst, Size, (int)MemoryType.MappedMemory);
+            AMemoryMapInfo SrcInfo = Memory.Manager.GetMapInfo(Src);
+
+            Memory.Manager.Map(Dst, Size, (int)MemoryType.MappedMemory, SrcInfo.Perm);
+
+            Memory.Manager.Reprotect(Src, Size, AMemoryPerm.None);
+
+            Memory.Manager.SetAttrBit(Src, Size, 0);
+
+            ThreadState.X0 = (int)SvcResult.Success;
+        }
+
+        private void SvcUnmapMemory(AThreadState ThreadState)
+        {
+            long Dst  = (long)ThreadState.X0;
+            long Src  = (long)ThreadState.X1;
+            long Size = (long)ThreadState.X2;
+
+            AMemoryMapInfo DstInfo = Memory.Manager.GetMapInfo(Dst);
+
+            Memory.Manager.Unmap(Dst, Size, (int)MemoryType.MappedMemory);
+
+            Memory.Manager.Reprotect(Src, Size, DstInfo.Perm);
+
+            Memory.Manager.ClearAttrBit(Src, Size, 0);
 
             ThreadState.X0 = (int)SvcResult.Success;
         }
@@ -54,17 +88,22 @@ namespace Ryujinx.Core.OsHle.Svc
 
             AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Position);
 
-            MemoryInfo Info = new MemoryInfo(MapInfo);
+            if (MapInfo == null)
+            {
+                //TODO: Correct error code.
+                ThreadState.X0 = ulong.MaxValue;
 
-            Memory.WriteInt64(InfoPtr + 0x00, Info.BaseAddress);
-            Memory.WriteInt64(InfoPtr + 0x08, Info.Size);
-            Memory.WriteInt32(InfoPtr + 0x10, Info.MemType);
-            Memory.WriteInt32(InfoPtr + 0x14, Info.MemAttr);
-            Memory.WriteInt32(InfoPtr + 0x18, Info.MemPerm);
-            Memory.WriteInt32(InfoPtr + 0x1c, Info.IpcRefCount);
-            Memory.WriteInt32(InfoPtr + 0x20, Info.DeviceRefCount);
-            Memory.WriteInt32(InfoPtr + 0x24, Info.Padding);
+                return;
+            }
 
+            Memory.WriteInt64(InfoPtr + 0x00, MapInfo.Position);
+            Memory.WriteInt64(InfoPtr + 0x08, MapInfo.Size);
+            Memory.WriteInt32(InfoPtr + 0x10, MapInfo.Type);
+            Memory.WriteInt32(InfoPtr + 0x14, MapInfo.Attr);
+            Memory.WriteInt32(InfoPtr + 0x18, (int)MapInfo.Perm);
+            Memory.WriteInt32(InfoPtr + 0x1c, 0);
+            Memory.WriteInt32(InfoPtr + 0x20, 0);
+            Memory.WriteInt32(InfoPtr + 0x24, 0);
             //TODO: X1.
 
             ThreadState.X0 = (int)SvcResult.Success;
@@ -84,7 +123,7 @@ namespace Ryujinx.Core.OsHle.Svc
             {
                 SharedMem.AddVirtualPosition(Src);
 
-                Memory.Manager.MapPhys(Src, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm);
+                Memory.Manager.Map(Src, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm);
 
                 ThreadState.X0 = (int)SvcResult.Success;
             }
diff --git a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs
index 3b9142c789..51b2e26c6f 100644
--- a/Ryujinx.Core/OsHle/Svc/SvcSystem.cs
+++ b/Ryujinx.Core/OsHle/Svc/SvcSystem.cs
@@ -11,7 +11,14 @@ namespace Ryujinx.Core.OsHle.Svc
 {
     partial class SvcHandler
     {
-        private void SvcExitProcess(AThreadState ThreadState) => Ns.Os.ExitProcess(ThreadState.ProcessId);
+        private const int AllowedCpuIdBitmask = 0b1111;
+
+        private const bool EnableProcessDebugging = false;
+
+        private void SvcExitProcess(AThreadState ThreadState)
+        {
+            Ns.Os.ExitProcess(ThreadState.ProcessId);
+        }
 
         private void SvcCloseHandle(AThreadState ThreadState)
         {
@@ -162,79 +169,62 @@ namespace Ryujinx.Core.OsHle.Svc
 
             switch (InfoType)
             {
-                case 0:  ThreadState.X1 = AllowedCpuIdBitmask();           break;
-                case 2:  ThreadState.X1 = GetMapRegionBaseAddr();          break;
-                case 3:  ThreadState.X1 = GetMapRegionSize();              break;
-                case 4:  ThreadState.X1 = GetHeapRegionBaseAddr();         break;
-                case 5:  ThreadState.X1 = GetHeapRegionSize();             break;
-                case 6:  ThreadState.X1 = GetTotalMem();                   break;
-                case 7:  ThreadState.X1 = GetUsedMem();                    break;
-                case 8:  ThreadState.X1 = IsCurrentProcessBeingDebugged(); break;
-                case 11: ThreadState.X1 = GetRnd64();                      break;
-                case 12: ThreadState.X1 = GetAddrSpaceBaseAddr();          break;
-                case 13: ThreadState.X1 = GetAddrSpaceSize();              break;
-                case 14: ThreadState.X1 = GetMapRegionBaseAddr();          break;
-                case 15: ThreadState.X1 = GetMapRegionSize();              break;
+                case 0:
+                    ThreadState.X1 = AllowedCpuIdBitmask;
+                    break;
+
+                case 2:
+                    ThreadState.X1 = MemoryRegions.MapRegionAddress;
+                    break;
+
+                case 3:
+                    ThreadState.X1 = MemoryRegions.MapRegionSize;
+                    break;
+
+                case 4:
+                    ThreadState.X1 = MemoryRegions.HeapRegionAddress;
+                    break;
+
+                case 5:
+                    ThreadState.X1 = CurrentHeapSize;
+                    break;
+
+                case 6:
+                    ThreadState.X1 = MemoryRegions.TotalMemoryAvailable;
+                    break;
+    
+                case 7:
+                    ThreadState.X1 = MemoryRegions.TotalMemoryUsed + CurrentHeapSize;
+                    break;
+
+                case 8:
+                    ThreadState.X1 = EnableProcessDebugging ? 1 : 0;
+                    break;
+
+                case 11:
+                    ThreadState.X1 = (ulong)Rng.Next() + ((ulong)Rng.Next() << 32);
+                    break;
+
+                case 12:
+                    ThreadState.X1 = MemoryRegions.AddrSpaceStart;
+                    break;
+
+                case 13:
+                    ThreadState.X1 = MemoryRegions.AddrSpaceSize;
+                    break;
+
+                case 14:
+                    ThreadState.X1 = MemoryRegions.MapRegionAddress;
+                    break;
+
+                case 15:
+                    ThreadState.X1 = MemoryRegions.MapRegionSize;
+                    break;
 
                 default: throw new NotImplementedException($"SvcGetInfo: {InfoType} {Handle} {InfoId}");
             }
 
             ThreadState.X0 = (int)SvcResult.Success;
         }
-        
-        private ulong AllowedCpuIdBitmask()
-        {
-            return 0xF; //Mephisto value.
-        }
-
-        private ulong GetMapRegionBaseAddr()
-        {
-            return MemoryRegions.MapRegionAddress;
-        }
-
-        private ulong GetMapRegionSize()
-        {
-            return MemoryRegions.MapRegionSize;
-        }
-
-        private ulong GetHeapRegionBaseAddr()
-        {
-            return MemoryRegions.HeapRegionAddress;
-        }
-
-        private ulong GetHeapRegionSize()
-        {
-            return MemoryRegions.HeapRegionSize;
-        }
-
-        private ulong GetTotalMem()
-        {
-            return (ulong)Memory.Manager.GetTotalMemorySize();
-        }
-
-        private ulong GetUsedMem()
-        {
-            return (ulong)Memory.Manager.GetUsedMemorySize();
-        }
-
-        private ulong IsCurrentProcessBeingDebugged()
-        {
-            return (ulong)0;
-        }
-
-        private ulong GetRnd64()
-        {
-            return (ulong)Rng.Next() + ((ulong)Rng.Next() << 32);
-        }
-
-        private ulong GetAddrSpaceBaseAddr()
-        {
-            return 0x08000000;
-        }
-
-        private ulong GetAddrSpaceSize()
-        {
-            return AMemoryMgr.AddrSize - GetAddrSpaceBaseAddr();
-        }
     }
 }
diff --git a/Ryujinx.Core/VirtualFs.cs b/Ryujinx.Core/VirtualFs.cs
index 0c91111659..195fb6a3c6 100644
--- a/Ryujinx.Core/VirtualFs.cs
+++ b/Ryujinx.Core/VirtualFs.cs
@@ -5,9 +5,9 @@ namespace Ryujinx.Core
 {
     class VirtualFs : IDisposable
     {
-        private const string BasePath   = "Fs";
-        private const string SavesPath  = "Saves";
-        private const string SdCardPath = "SdCard";
+        private const string BasePath   = "RyuFs";
+        private const string NandPath   = "nand";
+        private const string SdCardPath = "sdmc";
 
         public Stream RomFs { get; private set; }
 
@@ -35,7 +35,7 @@ namespace Ryujinx.Core
 
         public string GetSdCardPath() => MakeDirAndGetFullPath(SdCardPath);
 
-        public string GetGameSavesPath() => MakeDirAndGetFullPath(SavesPath);
+        public string GetGameSavesPath() => MakeDirAndGetFullPath(NandPath);
 
         private string MakeDirAndGetFullPath(string Dir)
         {
@@ -56,7 +56,9 @@ namespace Ryujinx.Core
 
         public string GetBasePath()
         {
-            return Path.Combine(Directory.GetCurrentDirectory(), BasePath);
+            string AppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
+
+            return Path.Combine(AppDataPath, BasePath);
         }
 
         public void Dispose()
diff --git a/Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs b/Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs
index 54fabc6719..7f50640d59 100644
--- a/Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs
+++ b/Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs
@@ -16,7 +16,7 @@ namespace Ryujinx.Graphics.Gpu
         private const int  PTLvl1Mask = PTLvl1Size - 1;
         private const int  PageMask   = PageSize   - 1;
 
-        private const int  PTLvl0Bit  = PTPageBits + PTLvl0Bits;
+        private const int  PTLvl0Bit  = PTPageBits + PTLvl1Bits;
         private const int  PTLvl1Bit  = PTPageBits;
 
         private const long PteUnmapped = -1;
diff --git a/Ryujinx.Tests/Cpu/CpuTest.cs b/Ryujinx.Tests/Cpu/CpuTest.cs
index bf9d90e33d..a56eeb7281 100644
--- a/Ryujinx.Tests/Cpu/CpuTest.cs
+++ b/Ryujinx.Tests/Cpu/CpuTest.cs
@@ -17,7 +17,6 @@ namespace Ryujinx.Tests.Cpu
         private long EntryPoint;
 
         private IntPtr Ram;
-        private AMemoryAlloc Allocator;
         private AMemory Memory;
         private AThread Thread;
 
@@ -31,9 +30,8 @@ namespace Ryujinx.Tests.Cpu
 
             Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize);
             ATranslator Translator = new ATranslator();
-            Allocator = new AMemoryAlloc();
-            Memory = new AMemory(Ram, Allocator);
-            Memory.Manager.MapPhys(Position, Size, 2, AMemoryPerm.Read | AMemoryPerm.Write | AMemoryPerm.Execute);
+            Memory = new AMemory(Ram);
+            Memory.Manager.Map(Position, Size, 2, AMemoryPerm.Read | AMemoryPerm.Write | AMemoryPerm.Execute);
             Thread = new AThread(Translator, Memory, ThreadPriority.Normal, EntryPoint);
         }
 
@@ -42,7 +40,6 @@ namespace Ryujinx.Tests.Cpu
         {
             Thread = null;
             Memory = null;
-            Allocator = null;
             Marshal.FreeHGlobal(Ram);
         }