diff --git a/ChocolArm64/Memory/AMemory.cs b/ChocolArm64/Memory/AMemory.cs index f2abffbf..0d202fed 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(); diff --git a/ChocolArm64/Memory/AMemoryAlloc.cs b/ChocolArm64/Memory/AMemoryAlloc.cs deleted file mode 100644 index b11e7793..00000000 --- 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 44b2cc07..02dd3055 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 c8869e03..bc364452 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 95cb7d6f..fa204460 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 3d56ff92..9cd0a0d4 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 MemoryMapped; public EventHandler MemoryUnmapped; - public HSharedMem(long PhysPos) + public HSharedMem() { Positions = new List(); } diff --git a/Ryujinx.Core/OsHle/Homebrew.cs b/Ryujinx.Core/OsHle/Homebrew.cs index f177b37e..e2e95e4d 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 9929102d..c2389143 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(); - 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 76a4bef3..00000000 --- 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 86d266f6..3b690426 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 9ca9a2bd..f0b568c8 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(); - 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 ec53f47f..212d30a6 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 6ca27f16..e7559a14 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 3b9142c7..51b2e26c 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 0c911116..195fb6a3 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 54fabc67..7f50640d 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 bf9d90e3..a56eeb72 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); }