diff --git a/Ryujinx.Cpu/MemoryManagerHostMapped.cs b/Ryujinx.Cpu/MemoryManagerHostMapped.cs
index 8bd3092e2..91fcec327 100644
--- a/Ryujinx.Cpu/MemoryManagerHostMapped.cs
+++ b/Ryujinx.Cpu/MemoryManagerHostMapped.cs
@@ -324,16 +324,16 @@ namespace Ryujinx.Cpu
///
public WritableRegion GetWritableRegion(ulong va, int size, bool tracked = false)
{
- if (tracked)
- {
- SignalMemoryTracking(va, (ulong)size, true);
- }
-
if (size == 0)
{
return new WritableRegion(null, va, Memory.Empty);
}
+ if (tracked)
+ {
+ SignalMemoryTracking(va, (ulong)size, true);
+ }
+
if (IsContiguousAndMapped(va, size))
{
return new WritableRegion(null, va, _backingMemory.GetMemory(GetPhysicalAddressInternal(va), size));
@@ -342,7 +342,7 @@ namespace Ryujinx.Cpu
{
Memory memory = new byte[size];
- GetSpan(va, size).CopyTo(memory.Span);
+ ReadImpl(va, memory.Span);
return new WritableRegion(this, va, memory);
}
@@ -849,17 +849,6 @@ namespace Ryujinx.Cpu
}
}
- private ulong GetPhysicalAddress(ulong va)
- {
- // We return -1L if the virtual address is invalid or unmapped.
- if (!ValidateAddress(va) || !IsMapped(va))
- {
- return ulong.MaxValue;
- }
-
- return GetPhysicalAddressInternal(va);
- }
-
private ulong GetPhysicalAddressInternal(ulong va)
{
return _pageTable.Read(va) + (va & PageMask);
@@ -874,6 +863,6 @@ namespace Ryujinx.Cpu
_memoryEh.Dispose();
}
- private void ThrowInvalidMemoryRegionException(string message) => throw new InvalidMemoryRegionException(message);
+ private static void ThrowInvalidMemoryRegionException(string message) => throw new InvalidMemoryRegionException(message);
}
}
diff --git a/Ryujinx.HLE/HOS/ApplicationLoader.cs b/Ryujinx.HLE/HOS/ApplicationLoader.cs
index 8ceed5ea6..bb79c5bf4 100644
--- a/Ryujinx.HLE/HOS/ApplicationLoader.cs
+++ b/Ryujinx.HLE/HOS/ApplicationLoader.cs
@@ -17,6 +17,7 @@ using Ryujinx.Common.Logging;
using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.Kernel.Process;
using Ryujinx.HLE.Loaders.Executables;
+using Ryujinx.Memory;
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -555,7 +556,14 @@ namespace Ryujinx.HLE.HOS
Graphics.Gpu.GraphicsConfig.TitleId = TitleIdText;
_device.Gpu.HostInitalized.Set();
- Ptc.Initialize(TitleIdText, DisplayVersion, usePtc, _device.Configuration.MemoryManagerMode);
+ MemoryManagerMode memoryManagerMode = _device.Configuration.MemoryManagerMode;
+
+ if (!MemoryBlock.SupportsFlags(MemoryAllocationFlags.ViewCompatible))
+ {
+ memoryManagerMode = MemoryManagerMode.SoftwarePageTable;
+ }
+
+ Ptc.Initialize(TitleIdText, DisplayVersion, usePtc, memoryManagerMode);
metaData.GetNpdm(out Npdm npdm).ThrowIfFailure();
ProgramLoader.LoadNsos(_device.System.KernelContext, out ProcessTamperInfo tamperInfo, metaData, new ProgramInfo(in npdm), executables: programs);
diff --git a/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs b/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs
index a951b3a82..2cd905a75 100644
--- a/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs
+++ b/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs
@@ -21,6 +21,11 @@ namespace Ryujinx.HLE.HOS
{
MemoryManagerMode mode = context.Device.Configuration.MemoryManagerMode;
+ if (!MemoryBlock.SupportsFlags(MemoryAllocationFlags.ViewCompatible))
+ {
+ mode = MemoryManagerMode.SoftwarePageTable;
+ }
+
switch (mode)
{
case MemoryManagerMode.SoftwarePageTable:
diff --git a/Ryujinx.Memory/MemoryBlock.cs b/Ryujinx.Memory/MemoryBlock.cs
index fdc84068d..63719c8c7 100644
--- a/Ryujinx.Memory/MemoryBlock.cs
+++ b/Ryujinx.Memory/MemoryBlock.cs
@@ -11,6 +11,7 @@ namespace Ryujinx.Memory
{
private readonly bool _usesSharedMemory;
private readonly bool _isMirror;
+ private readonly bool _viewCompatible;
private IntPtr _sharedMemory;
private IntPtr _pointer;
@@ -41,7 +42,8 @@ namespace Ryujinx.Memory
}
else if (flags.HasFlag(MemoryAllocationFlags.Reserve))
{
- _pointer = MemoryManagement.Reserve(size, flags.HasFlag(MemoryAllocationFlags.ViewCompatible));
+ _viewCompatible = flags.HasFlag(MemoryAllocationFlags.ViewCompatible);
+ _pointer = MemoryManagement.Reserve(size, _viewCompatible);
}
else
{
@@ -154,7 +156,7 @@ namespace Ryujinx.Memory
/// Throw when is invalid
public void Reprotect(ulong offset, ulong size, MemoryPermission permission, bool throwOnFail = true)
{
- MemoryManagement.Reprotect(GetPointerInternal(offset, size), size, permission, throwOnFail);
+ MemoryManagement.Reprotect(GetPointerInternal(offset, size), size, permission, _viewCompatible, throwOnFail);
}
///
@@ -412,7 +414,27 @@ namespace Ryujinx.Memory
}
}
- private void ThrowObjectDisposed() => throw new ObjectDisposedException(nameof(MemoryBlock));
- private void ThrowInvalidMemoryRegionException() => throw new InvalidMemoryRegionException();
+ ///
+ /// Checks if the specified memory allocation flags are supported on the current platform.
+ ///
+ /// Flags to be checked
+ /// True if the platform supports all the flags, false otherwise
+ public static bool SupportsFlags(MemoryAllocationFlags flags)
+ {
+ if (flags.HasFlag(MemoryAllocationFlags.ViewCompatible))
+ {
+ if (OperatingSystem.IsWindows())
+ {
+ return OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134);
+ }
+
+ return OperatingSystem.IsLinux() || OperatingSystem.IsMacOS();
+ }
+
+ return true;
+ }
+
+ private static void ThrowObjectDisposed() => throw new ObjectDisposedException(nameof(MemoryBlock));
+ private static void ThrowInvalidMemoryRegionException() => throw new InvalidMemoryRegionException();
}
}
diff --git a/Ryujinx.Memory/MemoryManagement.cs b/Ryujinx.Memory/MemoryManagement.cs
index a325532f2..fa21f9d31 100644
--- a/Ryujinx.Memory/MemoryManagement.cs
+++ b/Ryujinx.Memory/MemoryManagement.cs
@@ -108,7 +108,7 @@ namespace Ryujinx.Memory
}
}
- public static void Reprotect(IntPtr address, ulong size, MemoryPermission permission, bool throwOnFail)
+ public static void Reprotect(IntPtr address, ulong size, MemoryPermission permission, bool forView, bool throwOnFail)
{
bool result;
@@ -116,7 +116,7 @@ namespace Ryujinx.Memory
{
IntPtr sizeNint = new IntPtr((long)size);
- result = MemoryManagementWindows.Reprotect(address, sizeNint, permission);
+ result = MemoryManagementWindows.Reprotect(address, sizeNint, permission, forView);
}
else if (OperatingSystem.IsLinux() ||
OperatingSystem.IsMacOS())
diff --git a/Ryujinx.Memory/MemoryManagementWindows.cs b/Ryujinx.Memory/MemoryManagementWindows.cs
index d0700518e..32effbc8e 100644
--- a/Ryujinx.Memory/MemoryManagementWindows.cs
+++ b/Ryujinx.Memory/MemoryManagementWindows.cs
@@ -1,6 +1,5 @@
using Ryujinx.Memory.WindowsShared;
using System;
-using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
@@ -13,11 +12,6 @@ namespace Ryujinx.Memory
private static readonly IntPtr InvalidHandleValue = new IntPtr(-1);
private static readonly IntPtr CurrentProcessHandle = new IntPtr(-1);
- private static bool UseWin10Placeholders;
-
- private static object _emulatedHandleLock = new object();
- private static EmulatedSharedMemoryWindows[] _emulatedShared = new EmulatedSharedMemoryWindows[64];
- private static List _emulatedSharedList = new List();
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr VirtualAlloc(
@@ -87,11 +81,6 @@ namespace Ryujinx.Memory
[DllImport("kernel32.dll")]
private static extern uint GetLastError();
- static MemoryManagementWindows()
- {
- UseWin10Placeholders = OperatingSystem.IsWindowsVersionAtLeast(10, 0, 17134);
- }
-
public static IntPtr Allocate(IntPtr size)
{
return AllocateInternal(size, AllocationType.Reserve | AllocationType.Commit);
@@ -186,24 +175,21 @@ namespace Ryujinx.Memory
}
}
- public static bool Reprotect(IntPtr address, IntPtr size, MemoryPermission permission)
+ public static bool Reprotect(IntPtr address, IntPtr size, MemoryPermission permission, bool forView)
{
- if (UseWin10Placeholders)
+ if (forView)
{
ulong uaddress = (ulong)address;
ulong usize = (ulong)size;
while (usize > 0)
{
- ulong nextGranular = (uaddress & ~EmulatedSharedMemoryWindows.MappingMask) + EmulatedSharedMemoryWindows.MappingGranularity;
- ulong mapSize = Math.Min(usize, nextGranular - uaddress);
-
- if (!VirtualProtect((IntPtr)uaddress, (IntPtr)mapSize, GetProtection(permission), out _))
+ if (!VirtualProtect((IntPtr)uaddress, (IntPtr)PageSize, GetProtection(permission), out _))
{
return false;
}
- uaddress = nextGranular;
- usize -= mapSize;
+ uaddress += PageSize;
+ usize -= PageSize;
}
return true;
@@ -233,27 +219,6 @@ namespace Ryujinx.Memory
return VirtualFree(address, IntPtr.Zero, AllocationType.Release);
}
- private static int GetEmulatedHandle()
- {
- // Assumes we have the handle lock.
-
- for (int i = 0; i < _emulatedShared.Length; i++)
- {
- if (_emulatedShared[i] == null)
- {
- return i + 1;
- }
- }
-
- throw new InvalidProgramException("Too many shared memory handles were created.");
- }
-
- public static bool EmulatedHandleValid(ref int handle)
- {
- handle--;
- return handle >= 0 && handle < _emulatedShared.Length && _emulatedShared[handle] != null;
- }
-
public static IntPtr CreateSharedMemory(IntPtr size, bool reserve)
{
var prot = reserve ? FileMapProtection.SectionReserve : FileMapProtection.SectionCommit;