diff --git a/Ryujinx.Cpu/MemoryManager.cs b/Ryujinx.Cpu/MemoryManager.cs index 26cc01c91..3fa08fe75 100644 --- a/Ryujinx.Cpu/MemoryManager.cs +++ b/Ryujinx.Cpu/MemoryManager.cs @@ -1,4 +1,4 @@ -using ARMeilleure.Memory; +using ARMeilleure.Memory; using Ryujinx.Cpu.Tracking; using Ryujinx.Memory; using Ryujinx.Memory.Tracking; @@ -461,7 +461,32 @@ namespace Ryujinx.Cpu } /// - /// Checks if the page at a given CPU virtual address. + /// Checks if a memory range is mapped. + /// + /// Virtual address of the range + /// Size of the range in bytes + /// True if the entire range is mapped, false otherwise + public bool IsRangeMapped(ulong va, ulong size) + { + ulong endVa = (va + size + PageMask) & ~(ulong)PageMask; + + va &= ~(ulong)PageMask; + + while (va < endVa) + { + if (!IsMapped(va)) + { + return false; + } + + va += PageSize; + } + + return true; + } + + /// + /// Checks if the page at a given CPU virtual address is mapped. /// /// Virtual address to check /// True if the address is mapped, false otherwise diff --git a/Ryujinx.Memory.Tests/MockVirtualMemoryManager.cs b/Ryujinx.Memory.Tests/MockVirtualMemoryManager.cs index f9692cfcc..037bedc8c 100644 --- a/Ryujinx.Memory.Tests/MockVirtualMemoryManager.cs +++ b/Ryujinx.Memory.Tests/MockVirtualMemoryManager.cs @@ -15,6 +15,11 @@ namespace Ryujinx.Memory.Tests return NoMappings ? new (ulong address, ulong size)[0] : new (ulong address, ulong size)[] { (va, size) }; } + public bool IsRangeMapped(ulong va, ulong size) + { + return true; + } + public void TrackingReprotect(ulong va, ulong size, MemoryPermission protection) { diff --git a/Ryujinx.Memory/Tracking/IVirtualMemoryManager.cs b/Ryujinx.Memory/Tracking/IVirtualMemoryManager.cs index 6b5474e1f..e6d8e8c98 100644 --- a/Ryujinx.Memory/Tracking/IVirtualMemoryManager.cs +++ b/Ryujinx.Memory/Tracking/IVirtualMemoryManager.cs @@ -4,6 +4,7 @@ { (ulong address, ulong size)[] GetPhysicalRegions(ulong va, ulong size); + bool IsRangeMapped(ulong va, ulong size); void TrackingReprotect(ulong va, ulong size, MemoryPermission protection); } } diff --git a/Ryujinx.Memory/Tracking/MemoryTracking.cs b/Ryujinx.Memory/Tracking/MemoryTracking.cs index 779166c44..aff223e80 100644 --- a/Ryujinx.Memory/Tracking/MemoryTracking.cs +++ b/Ryujinx.Memory/Tracking/MemoryTracking.cs @@ -75,6 +75,7 @@ namespace Ryujinx.Memory.Tracking { VirtualRegion region = results[i]; region.RecalculatePhysicalChildren(); + region.UpdateProtection(); } } } @@ -200,7 +201,7 @@ namespace Ryujinx.Memory.Tracking lock (TrackingLock) { - RegionHandle handle = new RegionHandle(this, address, size); + RegionHandle handle = new RegionHandle(this, address, size, _memoryManager.IsRangeMapped(address, size)); return handle; } diff --git a/Ryujinx.Memory/Tracking/RegionHandle.cs b/Ryujinx.Memory/Tracking/RegionHandle.cs index c00d039b2..96898c214 100644 --- a/Ryujinx.Memory/Tracking/RegionHandle.cs +++ b/Ryujinx.Memory/Tracking/RegionHandle.cs @@ -10,7 +10,7 @@ namespace Ryujinx.Memory.Tracking /// public class RegionHandle : IRegionHandle, IRange { - public bool Dirty { get; private set; } = true; + public bool Dirty { get; private set; } public ulong Address { get; } public ulong Size { get; } @@ -32,8 +32,10 @@ namespace Ryujinx.Memory.Tracking /// Tracking object for the target memory block /// Virtual address of the region to track /// Size of the region to track - internal RegionHandle(MemoryTracking tracking, ulong address, ulong size) + /// Initial value of the dirty flag + internal RegionHandle(MemoryTracking tracking, ulong address, ulong size, bool dirty = true) { + Dirty = dirty; Address = address; Size = size; EndAddress = address + size;