aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChocolArm64/Memory/AMemory.cs4
-rw-r--r--ChocolArm64/Memory/AMemoryAlloc.cs35
-rw-r--r--ChocolArm64/Memory/AMemoryMapInfo.cs2
-rw-r--r--ChocolArm64/Memory/AMemoryMgr.cs198
-rw-r--r--Ryujinx.Core/Loaders/Executable.cs4
-rw-r--r--Ryujinx.Core/OsHle/Handles/HSharedMem.cs2
-rw-r--r--Ryujinx.Core/OsHle/Homebrew.cs2
-rw-r--r--Ryujinx.Core/OsHle/Horizon.cs23
-rw-r--r--Ryujinx.Core/OsHle/MemoryInfo.cs28
-rw-r--r--Ryujinx.Core/OsHle/MemoryRegions.cs21
-rw-r--r--Ryujinx.Core/OsHle/Process.cs52
-rw-r--r--Ryujinx.Core/OsHle/Svc/SvcHandler.cs3
-rw-r--r--Ryujinx.Core/OsHle/Svc/SvcMemory.cs65
-rw-r--r--Ryujinx.Core/OsHle/Svc/SvcSystem.cs128
-rw-r--r--Ryujinx.Core/VirtualFs.cs12
-rw-r--r--Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs2
-rw-r--r--Ryujinx.Tests/Cpu/CpuTest.cs7
17 files changed, 251 insertions, 337 deletions
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<int, ExMonitor>();
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 PTLvl0Size = 1 << PTLvl0Bits;
- private const int PTLvl1Size = 1 << PTLvl1Bits;
- public const int PageSize = 1 << PTPageBits;
+ private const int PTLvl0Bits = 10;
+ private const int PTLvl1Bits = 10;
+ private const int PTPageBits = 12;
- private const int PTLvl0Mask = PTLvl0Size - 1;
- private const int PTLvl1Mask = PTLvl1Size - 1;
- public const int PageMask = PageSize - 1;
+ private const int PTLvl0Size = 1 << PTLvl0Bits;
+ private const int PTLvl1Size = 1 << PTLvl1Bits;
+ public const int PageSize = 1 << PTPageBits;
- private const int PTLvl0Bit = PTPageBits + PTLvl0Bits;
- private const int PTLvl1Bit = PTPageBits;
+ private const int PTLvl0Mask = PTLvl0Size - 1;
+ private const int PTLvl1Mask = PTLvl1Size - 1;
+ public const int PageMask = PageSize - 1;
- 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();
- }
-
- public long GetUsedMemorySize()
- {
- 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;
- }
-
- public bool SetHeapAddr(long Position)
- {
- if (!IsHeapInitialized)
- {
- HeapAddr = Position;
-
- IsHeapInitialized = true;
-
- return true;
- }
-
- return false;
+ SetPTEntry(Position, Size, new PTEntry(PTMap.Mapped, Perm, Type, 0));
}
- public void SetHeapSize(long Size, int Type)
+ public void Unmap(long Position, long Size)
{
- //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;
+ SetPTEntry(Position, Size, new PTEntry(PTMap.Unmapped, 0, 0, 0));
}
- public void MapPhys(long Position, long Size, int Type, AMemoryPerm Perm)
+ public void Unmap(long Position, long Size, int Type)
{
- 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<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 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<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 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<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;
-
- Memory.Manager.MapPhys(StackBot, MaxStackSize, (int)MemoryType.Normal, AMemoryPerm.RW);
+ MapRWMemRegion(
+ MemoryRegions.MainStackAddress,
+ MemoryRegions.MainStackSize,
+ MemoryType.Normal);
+
+ long StackTop = MemoryRegions.MainStackAddress + MemoryRegions.MainStackSize;
- 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);
}