aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Memory
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Memory')
-rw-r--r--Ryujinx.Memory/Range/MultiRange.cs48
-rw-r--r--Ryujinx.Memory/Tracking/MemoryTracking.cs9
-rw-r--r--Ryujinx.Memory/Tracking/RegionHandle.cs25
-rw-r--r--Ryujinx.Memory/Tracking/VirtualRegion.cs12
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>