diff options
Diffstat (limited to 'Ryujinx.Memory')
| -rw-r--r-- | Ryujinx.Memory/Range/MultiRange.cs | 48 | ||||
| -rw-r--r-- | Ryujinx.Memory/Tracking/MemoryTracking.cs | 9 | ||||
| -rw-r--r-- | Ryujinx.Memory/Tracking/RegionHandle.cs | 25 | ||||
| -rw-r--r-- | Ryujinx.Memory/Tracking/VirtualRegion.cs | 12 |
4 files changed, 91 insertions, 3 deletions
diff --git a/Ryujinx.Memory/Range/MultiRange.cs b/Ryujinx.Memory/Range/MultiRange.cs index b40daa8a..3d505c7c 100644 --- a/Ryujinx.Memory/Range/MultiRange.cs +++ b/Ryujinx.Memory/Range/MultiRange.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace Ryujinx.Memory.Range { @@ -76,6 +77,53 @@ namespace Ryujinx.Memory.Range } /// <summary> + /// Gets a slice of the multi-range. + /// </summary> + /// <param name="offset">Offset of the slice into the multi-range in bytes</param> + /// <param name="size">Size of the slice in bytes</param> + /// <returns>A new multi-range representing the given slice of this one</returns> + public MultiRange GetSlice(ulong offset, ulong size) + { + if (HasSingleRange) + { + if (_singleRange.Size - offset < size) + { + throw new ArgumentOutOfRangeException(nameof(size)); + } + + return new MultiRange(_singleRange.Address + offset, size); + } + else + { + var ranges = new List<MemoryRange>(); + + foreach (MemoryRange range in _ranges) + { + if ((long)offset <= 0) + { + ranges.Add(new MemoryRange(range.Address, Math.Min(size, range.Size))); + size -= range.Size; + } + else if (offset < range.Size) + { + ulong sliceSize = Math.Min(size, range.Size - offset); + ranges.Add(new MemoryRange(range.Address + offset, sliceSize)); + size -= sliceSize; + } + + if ((long)size <= 0) + { + break; + } + + offset -= range.Size; + } + + return new MultiRange(ranges.ToArray()); + } + } + + /// <summary> /// Gets the physical region at the specified index. /// </summary> /// <param name="index">Index of the physical region</param> diff --git a/Ryujinx.Memory/Tracking/MemoryTracking.cs b/Ryujinx.Memory/Tracking/MemoryTracking.cs index aff223e8..6485e566 100644 --- a/Ryujinx.Memory/Tracking/MemoryTracking.cs +++ b/Ryujinx.Memory/Tracking/MemoryTracking.cs @@ -74,6 +74,14 @@ namespace Ryujinx.Memory.Tracking for (int i = 0; i < count; i++) { VirtualRegion region = results[i]; + + // If the region has been fully remapped, signal that it has been mapped again. + bool remapped = _memoryManager.IsRangeMapped(region.Address, region.Size); + if (remapped) + { + region.SignalMappingChanged(true); + } + region.RecalculatePhysicalChildren(); region.UpdateProtection(); } @@ -99,6 +107,7 @@ namespace Ryujinx.Memory.Tracking for (int i = 0; i < count; i++) { VirtualRegion region = results[i]; + region.SignalMappingChanged(false); region.RecalculatePhysicalChildren(); } } diff --git a/Ryujinx.Memory/Tracking/RegionHandle.cs b/Ryujinx.Memory/Tracking/RegionHandle.cs index 4da184dd..da3ee99a 100644 --- a/Ryujinx.Memory/Tracking/RegionHandle.cs +++ b/Ryujinx.Memory/Tracking/RegionHandle.cs @@ -12,6 +12,7 @@ namespace Ryujinx.Memory.Tracking public class RegionHandle : IRegionHandle, IRange { public bool Dirty { get; private set; } + public bool Unmapped { get; private set; } public ulong Address { get; } public ulong Size { get; } @@ -37,10 +38,11 @@ namespace Ryujinx.Memory.Tracking /// <param name="tracking">Tracking object for the target memory block</param> /// <param name="address">Virtual address of the region to track</param> /// <param name="size">Size of the region to track</param> - /// <param name="dirty">Initial value of the dirty flag</param> - internal RegionHandle(MemoryTracking tracking, ulong address, ulong size, bool dirty = true) + /// <param name="mapped">True if the region handle starts mapped</param> + internal RegionHandle(MemoryTracking tracking, ulong address, ulong size, bool mapped = true) { - Dirty = dirty; + Dirty = mapped; + Unmapped = !mapped; Address = address; Size = size; EndAddress = address + size; @@ -129,6 +131,23 @@ namespace Ryujinx.Memory.Tracking } /// <summary> + /// Signal that this handle has been mapped or unmapped. + /// </summary> + /// <param name="mapped">True if the handle has been mapped, false if unmapped</param> + internal void SignalMappingChanged(bool mapped) + { + if (Unmapped == mapped) + { + Unmapped = !mapped; + + if (Unmapped) + { + Dirty = false; + } + } + } + + /// <summary> /// Check if this region overlaps with another. /// </summary> /// <param name="address">Base address</param> diff --git a/Ryujinx.Memory/Tracking/VirtualRegion.cs b/Ryujinx.Memory/Tracking/VirtualRegion.cs index 15a11568..fcf2fbe0 100644 --- a/Ryujinx.Memory/Tracking/VirtualRegion.cs +++ b/Ryujinx.Memory/Tracking/VirtualRegion.cs @@ -67,6 +67,18 @@ namespace Ryujinx.Memory.Tracking } /// <summary> + /// Signal that this region has been mapped or unmapped. + /// </summary> + /// <param name="mapped">True if the region has been mapped, false if unmapped</param> + public void SignalMappingChanged(bool mapped) + { + foreach (RegionHandle handle in Handles) + { + handle.SignalMappingChanged(mapped); + } + } + + /// <summary> /// Gets the strictest permission that the child handles demand. Assumes that the tracking lock has been obtained. /// </summary> /// <returns>Protection level that this region demands</returns> |
