diff --git a/src/BizHawk.Common/Ranges.cs b/src/BizHawk.Common/Ranges.cs
index df70379da7..1102868463 100644
--- a/src/BizHawk.Common/Ranges.cs
+++ b/src/BizHawk.Common/Ranges.cs
@@ -32,8 +32,8 @@ namespace BizHawk.Common
}
///
- /// represents a closed interval (a.k.a. range) of s64s
- /// (class invariant: ≤ )
+ /// represents a half-open interval (a.k.a. range) of s64s
+ /// (class invariant: < )
///
public sealed class Int64Interval
{
@@ -41,31 +41,33 @@ namespace BizHawk.Common
public readonly long Start;
- public readonly long EndInclusive;
+ public readonly long EndExclusive;
- ///
- internal Int64Interval(long start, long endInclusive)
+ /// ≤
+ internal Int64Interval(long start, long endExclusive)
{
- if (endInclusive < start) throw new ArgumentOutOfRangeException(paramName: nameof(endInclusive), actualValue: endInclusive, message: "interval end < start");
+ if (endExclusive <= start) throw new ArgumentOutOfRangeException(paramName: nameof(endExclusive), actualValue: endExclusive, message: "interval end <= start");
Start = start;
- EndInclusive = endInclusive;
+ EndExclusive = endExclusive;
}
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(long value)
- => Start <= value && value <= EndInclusive;
+ => Start <= value && value < EndExclusive;
///
public ulong Count()
- => (Contains(0L)
- ? (Start == long.MinValue ? MIN_LONG_NEGATION_AS_ULONG : (ulong) -Start) + (ulong) EndInclusive
- : (ulong) (EndInclusive - Start)
- ) + 1UL;
+ => Contains(0L)
+ ? (Start == long.MinValue ? MIN_LONG_NEGATION_AS_ULONG : (ulong) -Start) + (ulong) EndExclusive
+ : (ulong) (EndExclusive - Start);
}
public static class RangeExtensions
{
+ private static ArithmeticException ExclusiveRangeMaxValExc
+ => new("inclusive range end is max. value of integral type");
+
private static ArithmeticException ExclusiveRangeMinValExc
=> new("exclusive range end is min value of integral type");
@@ -81,10 +83,13 @@ namespace BizHawk.Common
public static Int32Interval RangeTo(this int start, int endInclusive)
=> new(start: start, endInclusive: endInclusive);
- ///
+ /// <
+ /// is max. value of integral type (therefore endExclusive is unrepresentable)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Int64Interval RangeTo(this long start, long endInclusive)
- => new(start: start, endInclusive: endInclusive);
+ => endInclusive == long.MaxValue
+ ? throw ExclusiveRangeMaxValExc
+ : new(start: start, endExclusive: endInclusive + 1L);
/// ≤ (empty ranges where = are not permitted)
/// is min value of integral type (therefore ≤ )
@@ -99,7 +104,7 @@ namespace BizHawk.Common
public static Int64Interval RangeToExclusive(this long start, long endExclusive)
=> endExclusive == long.MinValue
? throw ExclusiveRangeMinValExc
- : new(start: start, endInclusive: endExclusive - 1L);
+ : new(start: start, endExclusive: endExclusive);
/// true iff is strictly contained in ( is considered to be OUTSIDE the range if it's exactly equal to either bound)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
diff --git a/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomain.cs b/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomain.cs
index bab9b9df9a..fea315a721 100644
--- a/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomain.cs
+++ b/src/BizHawk.Emulation.Common/Base Implementations/MemoryDomain.cs
@@ -114,7 +114,7 @@ namespace BizHawk.Emulation.Common
using (this.EnterExit())
{
- for (var i = addresses.Start; i <= addresses.EndInclusive; i++)
+ for (var i = addresses.Start; i < addresses.EndExclusive; i++)
{
values[i - addresses.Start] = PeekByte(i);
}
@@ -127,7 +127,7 @@ namespace BizHawk.Emulation.Common
if (values is null) throw new ArgumentNullException(paramName: nameof(values));
var start = addresses.Start;
- var end = addresses.EndInclusive + 1;
+ var end = addresses.EndExclusive;
if ((start & 1) != 0 || (end & 1) != 0)
throw new InvalidOperationException("The API contract doesn't define what to do for unaligned reads and writes!");
@@ -151,7 +151,7 @@ namespace BizHawk.Emulation.Common
if (values is null) throw new ArgumentNullException(paramName: nameof(values));
var start = addresses.Start;
- var end = addresses.EndInclusive + 1;
+ var end = addresses.EndExclusive;
if ((start & 3) != 0 || (end & 3) != 0)
throw new InvalidOperationException("The API contract doesn't define what to do for unaligned reads and writes!");