namespace Ryujinx.Memory.Range { /// /// Range of memory composed of an address and size. /// public readonly record struct MemoryRange { /// /// Special address value used to indicate than an address is invalid. /// internal const ulong InvalidAddress = ulong.MaxValue; /// /// An empty memory range, with a null address and zero size. /// public static MemoryRange Empty => new(0UL, 0); /// /// Start address of the range. /// public ulong Address { get; } /// /// Size of the range in bytes. /// public ulong Size { get; } /// /// Address where the range ends (exclusive). /// public ulong EndAddress => Address + Size; /// /// Creates a new memory range with the specified address and size. /// /// Start address /// Size in bytes public MemoryRange(ulong address, ulong size) { Address = address; Size = size; } /// /// Checks if the range overlaps with another. /// /// The other range to check for overlap /// True if the ranges overlap, false otherwise public bool OverlapsWith(MemoryRange other) { ulong thisAddress = Address; ulong thisEndAddress = EndAddress; ulong otherAddress = other.Address; ulong otherEndAddress = other.EndAddress; // If any of the ranges if invalid (address + size overflows), // then they are never considered to overlap. if (thisEndAddress < thisAddress || otherEndAddress < otherAddress) { return false; } return thisAddress < otherEndAddress && otherAddress < thisEndAddress; } /// /// Checks if a given sub-range of memory is invalid. /// Those are used to represent unmapped memory regions (holes in the region mapping). /// /// Memory range to check /// True if the memory range is considered invalid, false otherwise internal static bool IsInvalid(ref MemoryRange subRange) { return subRange.Address == InvalidAddress; } /// /// Returns a string summary of the memory range. /// /// A string summary of the memory range public override string ToString() { if (Address == InvalidAddress) { return $"[Unmapped 0x{Size:X}]"; } return $"[0x{Address:X}, 0x{EndAddress:X})"; } } }