diff --git a/src/BizHawk.BizInvoke/CallingConventionAdapter.cs b/src/BizHawk.BizInvoke/CallingConventionAdapter.cs
index e85363effb..da08373914 100644
--- a/src/BizHawk.BizInvoke/CallingConventionAdapter.cs
+++ b/src/BizHawk.BizInvoke/CallingConventionAdapter.cs
@@ -132,14 +132,14 @@ namespace BizHawk.BizInvoke
throw new InvalidOperationException();
}
- private readonly MemoryBlockBase _memory;
+ private readonly MemoryBlock _memory;
private readonly object _sync = new object();
private readonly WeakReference[] _refs;
public SysVHostMsGuest()
{
int size = 4 * 1024 * 1024;
- _memory = MemoryBlockBase.CallPlatformCtor((ulong)size);
+ _memory = MemoryBlock.Create((ulong)size);
_memory.Activate();
_refs = new WeakReference[size / BlockSize];
}
@@ -185,7 +185,7 @@ namespace BizHawk.BizInvoke
private void WriteThunk(byte[] data, int placeholderIndex, IntPtr p, int index)
{
- _memory.Protect(_memory.Start, _memory.Size, MemoryBlockBase.Protection.RW);
+ _memory.Protect(_memory.Start, _memory.Size, MemoryBlock.Protection.RW);
var ss = _memory.GetStream(_memory.Start + (ulong)index * BlockSize, BlockSize, true);
ss.Write(data, 0, data.Length);
for (int i = data.Length; i < BlockSize; i++)
@@ -193,7 +193,7 @@ namespace BizHawk.BizInvoke
ss.Position = placeholderIndex;
var bw = new BinaryWriter(ss);
bw.Write((long)p);
- _memory.Protect(_memory.Start, _memory.Size, MemoryBlockBase.Protection.RX);
+ _memory.Protect(_memory.Start, _memory.Size, MemoryBlock.Protection.RX);
}
private IntPtr GetThunkAddress(int index)
diff --git a/src/BizHawk.BizInvoke/MemoryBlock.cs b/src/BizHawk.BizInvoke/MemoryBlock.cs
index e146127c06..28d6ab8eea 100644
--- a/src/BizHawk.BizInvoke/MemoryBlock.cs
+++ b/src/BizHawk.BizInvoke/MemoryBlock.cs
@@ -1,238 +1,255 @@
-using System;
-using System.Runtime.InteropServices;
-using System.IO;
-
-namespace BizHawk.BizInvoke
-{
- public sealed class MemoryBlock : MemoryBlockBase
- {
- ///
- /// handle returned by CreateFileMapping
- ///
- private IntPtr _handle;
-
- ///
- /// failed to create file mapping
- public MemoryBlock(ulong start, ulong size) : base(start, size)
- {
- _handle = Kernel32.CreateFileMapping(
- Kernel32.INVALID_HANDLE_VALUE,
- IntPtr.Zero,
- Kernel32.FileMapProtection.PageExecuteReadWrite | Kernel32.FileMapProtection.SectionCommit,
- (uint)(Size >> 32),
- (uint)Size,
- null
- );
- if (_handle == IntPtr.Zero) throw new InvalidOperationException($"{nameof(Kernel32.CreateFileMapping)}() returned NULL");
- }
-
- /// is or failed to map file view
- public override void Activate()
- {
- if (Active)
- throw new InvalidOperationException("Already active");
- if (Kernel32.MapViewOfFileEx(
- _handle,
- Kernel32.FileMapAccessType.Read | Kernel32.FileMapAccessType.Write | Kernel32.FileMapAccessType.Execute,
- 0,
- 0,
- Z.UU(Size),
- Z.US(Start)
- ) != Z.US(Start))
- {
- throw new InvalidOperationException($"{nameof(Kernel32.MapViewOfFileEx)}() returned NULL");
- }
- ProtectAll();
- Active = true;
- }
-
- /// is or failed to unmap file view
- public override void Deactivate()
- {
- if (!Active)
- throw new InvalidOperationException("Not active");
- if (!Kernel32.UnmapViewOfFile(Z.US(Start)))
- throw new InvalidOperationException($"{nameof(Kernel32.UnmapViewOfFile)}() returned NULL");
- Active = false;
- }
-
- /// snapshot already taken, is , or failed to make memory read-only
- public override void SaveXorSnapshot()
- {
- if (_snapshot != null)
- throw new InvalidOperationException("Snapshot already taken");
- if (!Active)
- throw new InvalidOperationException("Not active");
-
- // temporarily switch the entire block to `R`: in case some areas are unreadable, we don't want
- // that to complicate things
- Kernel32.MemoryProtection old;
- if (!Kernel32.VirtualProtect(Z.UU(Start), Z.UU(Size), Kernel32.MemoryProtection.READONLY, out old))
- throw new InvalidOperationException($"{nameof(Kernel32.VirtualProtect)}() returned FALSE!");
-
- _snapshot = new byte[Size];
- var ds = new MemoryStream(_snapshot, true);
- var ss = GetStream(Start, Size, false);
- ss.CopyTo(ds);
- XorHash = WaterboxUtils.Hash(_snapshot);
-
- ProtectAll();
- }
-
- /// is or failed to make memory read-only
- public override byte[] FullHash()
- {
- if (!Active)
- throw new InvalidOperationException("Not active");
- // temporarily switch the entire block to `R`
- Kernel32.MemoryProtection old;
- if (!Kernel32.VirtualProtect(Z.UU(Start), Z.UU(Size), Kernel32.MemoryProtection.READONLY, out old))
- throw new InvalidOperationException($"{nameof(Kernel32.VirtualProtect)}() returned FALSE!");
- var ret = WaterboxUtils.Hash(GetStream(Start, Size, false));
- ProtectAll();
- return ret;
- }
-
- private static Kernel32.MemoryProtection GetKernelMemoryProtectionValue(Protection prot)
- {
- Kernel32.MemoryProtection p;
- switch (prot)
- {
- case Protection.None: p = Kernel32.MemoryProtection.NOACCESS; break;
- case Protection.R: p = Kernel32.MemoryProtection.READONLY; break;
- case Protection.RW: p = Kernel32.MemoryProtection.READWRITE; break;
- case Protection.RX: p = Kernel32.MemoryProtection.EXECUTE_READ; break;
- default: throw new ArgumentOutOfRangeException(nameof(prot));
- }
- return p;
- }
-
- protected override void ProtectAll()
- {
- int ps = 0;
- for (int i = 0; i < _pageData.Length; i++)
- {
- if (i == _pageData.Length - 1 || _pageData[i] != _pageData[i + 1])
- {
- var p = GetKernelMemoryProtectionValue(_pageData[i]);
- ulong zstart = GetStartAddr(ps);
- ulong zend = GetStartAddr(i + 1);
- Kernel32.MemoryProtection old;
- if (!Kernel32.VirtualProtect(Z.UU(zstart), Z.UU(zend - zstart), p, out old))
- throw new InvalidOperationException($"{nameof(Kernel32.VirtualProtect)}() returned FALSE!");
- ps = i + 1;
- }
- }
- }
-
- /// failed to protect memory
- public override void Protect(ulong start, ulong length, Protection prot)
- {
- if (length == 0)
- return;
- int pstart = GetPage(start);
- int pend = GetPage(start + length - 1);
-
- var p = GetKernelMemoryProtectionValue(prot);
- for (int i = pstart; i <= pend; i++)
- _pageData[i] = prot; // also store the value for later use
-
- if (Active) // it's legal to Protect() if we're not active; the information is just saved for the next activation
- {
- var computedStart = WaterboxUtils.AlignDown(start);
- var computedEnd = WaterboxUtils.AlignUp(start + length);
- var computedLength = computedEnd - computedStart;
-
- Kernel32.MemoryProtection old;
- if (!Kernel32.VirtualProtect(Z.UU(computedStart),
- Z.UU(computedLength), p, out old))
- throw new InvalidOperationException($"{nameof(Kernel32.VirtualProtect)}() returned FALSE!");
- }
- }
-
- public override void Dispose(bool disposing)
- {
- if (_handle != IntPtr.Zero)
- {
- if (Active)
- Deactivate();
- Kernel32.CloseHandle(_handle);
- _handle = IntPtr.Zero;
- }
- }
-
- ~MemoryBlock()
- {
- Dispose(false);
- }
-
- private static class Kernel32
- {
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern bool VirtualProtect(UIntPtr lpAddress, UIntPtr dwSize,
- MemoryProtection flNewProtect, out MemoryProtection lpflOldProtect);
-
- [Flags]
- public enum MemoryProtection : uint
- {
- EXECUTE = 0x10,
- EXECUTE_READ = 0x20,
- EXECUTE_READWRITE = 0x40,
- EXECUTE_WRITECOPY = 0x80,
- NOACCESS = 0x01,
- READONLY = 0x02,
- READWRITE = 0x04,
- WRITECOPY = 0x08,
- GUARD_Modifierflag = 0x100,
- NOCACHE_Modifierflag = 0x200,
- WRITECOMBINE_Modifierflag = 0x400
- }
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern IntPtr CreateFileMapping(
- IntPtr hFile,
- IntPtr lpFileMappingAttributes,
- FileMapProtection flProtect,
- uint dwMaximumSizeHigh,
- uint dwMaximumSizeLow,
- string lpName);
-
- [Flags]
- public enum FileMapProtection : uint
- {
- PageReadonly = 0x02,
- PageReadWrite = 0x04,
- PageWriteCopy = 0x08,
- PageExecuteRead = 0x20,
- PageExecuteReadWrite = 0x40,
- SectionCommit = 0x8000000,
- SectionImage = 0x1000000,
- SectionNoCache = 0x10000000,
- SectionReserve = 0x4000000,
- }
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern bool CloseHandle(IntPtr hObject);
-
- [DllImport("kernel32.dll", SetLastError = true)]
- public static extern bool UnmapViewOfFile(IntPtr lpBaseAddress);
-
- [DllImport("kernel32.dll")]
- public static extern IntPtr MapViewOfFileEx(IntPtr hFileMappingObject,
- FileMapAccessType dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow,
- UIntPtr dwNumberOfBytesToMap, IntPtr lpBaseAddress);
-
- [Flags]
- public enum FileMapAccessType : uint
- {
- Copy = 0x01,
- Write = 0x02,
- Read = 0x04,
- AllAccess = 0x08,
- Execute = 0x20,
- }
-
- public static readonly IntPtr INVALID_HANDLE_VALUE = Z.US(0xffffffffffffffff);
- }
- }
-}
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using BizHawk.Common;
+
+namespace BizHawk.BizInvoke
+{
+ public abstract class MemoryBlock : IDisposable
+ {
+ /// allocate bytes starting at a particular address
+ /// is not aligned or is 0
+ protected MemoryBlock(ulong start, ulong size)
+ {
+ if (!WaterboxUtils.Aligned(start))
+ throw new ArgumentOutOfRangeException(nameof(start), start, "start address must be aligned");
+ if (size == 0)
+ throw new ArgumentOutOfRangeException(nameof(size), size, "cannot create 0-length block");
+ Start = start;
+ Size = WaterboxUtils.AlignUp(size);
+ EndExclusive = Start + Size;
+ _pageData = new Protection[GetPage(EndExclusive - 1) + 1];
+ }
+
+ /// stores last set memory protection value for each page
+ protected readonly Protection[] _pageData;
+
+ /// end address of the memory block (not part of the block; class invariant: equal to + )
+ public readonly ulong EndExclusive;
+
+ /// total size of the memory block
+ public readonly ulong Size;
+
+ /// starting address of the memory block
+ public readonly ulong Start;
+
+ /// snapshot for XOR buffer
+ protected byte[] _snapshot;
+
+ /// true if this is currently swapped in
+ public bool Active { get; protected set; }
+
+ public byte[] XorHash { get; protected set; }
+
+ /// get a page index within the block
+ protected int GetPage(ulong addr)
+ {
+ if (addr < Start || EndExclusive <= addr) throw new ArgumentOutOfRangeException(nameof(addr), addr, "invalid address");
+ return (int) ((addr - Start) >> WaterboxUtils.PageShift);
+ }
+
+ /// get a start address for a page index within the block
+ protected ulong GetStartAddr(int page) => ((ulong) page << WaterboxUtils.PageShift) + Start;
+
+ /// Get a stream that can be used to read or write from part of the block. Does not check for or change !
+ /// or end (= + - 1) are outside [, ), the range of the block
+ public Stream GetStream(ulong start, ulong length, bool writer)
+ {
+ if (start < Start)
+ throw new ArgumentOutOfRangeException(nameof(start), start, "invalid address");
+ if (EndExclusive < start + length)
+ throw new ArgumentOutOfRangeException(nameof(length), length, "requested length implies invalid end address");
+ return new MemoryViewStream(!writer, writer, (long) start, (long) length, this);
+ }
+
+ /// get a stream that can be used to read or write from part of the block. both reads and writes will be XORed against an earlier recorded snapshot
+ /// or end (= + - 1) are outside [, ), the range of the block
+ /// no snapshot taken (haven't called )
+ public Stream GetXorStream(ulong start, ulong length, bool writer)
+ {
+ if (start < Start) throw new ArgumentOutOfRangeException(nameof(start), start, "invalid address");
+ if (EndExclusive < start + length) throw new ArgumentOutOfRangeException(nameof(length), length, "requested length implies invalid end address");
+ if (_snapshot == null) throw new InvalidOperationException("No snapshot taken!");
+ return new MemoryViewXorStream(!writer, writer, (long) start, (long) length, this, _snapshot, (long) (start - Start));
+ }
+
+ /// activate the memory block, swapping it in at the pre-specified address
+ public abstract void Activate();
+
+ /// deactivate the memory block, removing it from RAM but leaving it immediately available to swap back in
+ public abstract void Deactivate();
+
+ /// take a hash of the current full contents of the block, including unreadable areas
+ public abstract byte[] FullHash();
+
+ /// set r/w/x protection on a portion of memory. rounded to encompassing pages
+ public abstract void Protect(ulong start, ulong length, Protection prot);
+
+ /// restore all recorded protections
+ protected abstract void ProtectAll();
+
+ /// take a snapshot of the entire memory block's contents, for use in
+ public abstract void SaveXorSnapshot();
+
+ public abstract void Dispose(bool disposing);
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ~MemoryBlock()
+ {
+ Dispose(false);
+ }
+
+ /// allocate bytes starting at a particular address
+ public static MemoryBlock Create(ulong start, ulong size) => OSTailoredCode.IsUnixHost
+ ? (MemoryBlock) new MemoryBlockUnix(start, size)
+ : new MemoryBlockWindows(start, size);
+
+ /// allocate bytes at any address
+ public static MemoryBlock Create(ulong size) => Create(0, size);
+
+ /// Memory protection constant
+ public enum Protection : byte { None, R, RW, RX }
+
+ private class MemoryViewStream : Stream
+ {
+ public MemoryViewStream(bool readable, bool writable, long ptr, long length, MemoryBlock owner)
+ {
+ _readable = readable;
+ _writable = writable;
+ _ptr = ptr;
+ _length = length;
+ _owner = owner;
+ _pos = 0;
+ }
+
+ private readonly long _length;
+ private readonly MemoryBlock _owner;
+ private readonly long _ptr;
+ private readonly bool _readable;
+ private readonly bool _writable;
+
+ private long _pos;
+
+ public override bool CanRead => _readable;
+ public override bool CanSeek => true;
+ public override bool CanWrite => _writable;
+ public override long Length => _length;
+ public override long Position
+ {
+ get => _pos;
+ set
+ {
+ if (value < 0 || _length < value) throw new ArgumentOutOfRangeException();
+ _pos = value;
+ }
+ }
+
+ private void EnsureNotDisposed()
+ {
+ if (_owner.Start == 0)
+ throw new ObjectDisposedException(nameof(MemoryBlock));
+ }
+
+ public override void Flush() {}
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ if (!_readable) throw new InvalidOperationException();
+ if (count < 0 || buffer.Length < count + offset) throw new ArgumentOutOfRangeException();
+ EnsureNotDisposed();
+
+ count = (int) Math.Min(count, _length - _pos);
+ Marshal.Copy(Z.SS(_ptr + _pos), buffer, offset, count);
+ _pos += count;
+ return count;
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ long newpos;
+ switch (origin)
+ {
+ default:
+ case SeekOrigin.Begin:
+ newpos = offset;
+ break;
+ case SeekOrigin.Current:
+ newpos = _pos + offset;
+ break;
+ case SeekOrigin.End:
+ newpos = _length + offset;
+ break;
+ }
+ Position = newpos;
+ return newpos;
+ }
+
+ public override void SetLength(long value)
+ {
+ throw new InvalidOperationException();
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ if (!_writable) throw new InvalidOperationException();
+ if (count < 0 || _length - _pos < count || buffer.Length < count + offset) throw new ArgumentOutOfRangeException();
+ EnsureNotDisposed();
+
+ Marshal.Copy(buffer, offset, Z.SS(_ptr + _pos), count);
+ _pos += count;
+ }
+ }
+
+ private class MemoryViewXorStream : MemoryViewStream
+ {
+ public MemoryViewXorStream(bool readable, bool writable, long ptr, long length, MemoryBlock owner, byte[] initial, long offset)
+ : base(readable, writable, ptr, length, owner)
+ {
+ _initial = initial;
+ _offset = (int) offset;
+ }
+
+ /// the initial data to XOR against for both reading and writing
+ private readonly byte[] _initial;
+
+ /// offset into the XOR data that this stream is representing
+ private readonly int _offset;
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ var pos = (int) Position;
+ count = base.Read(buffer, offset, count);
+ XorTransform(_initial, _offset + pos, buffer, offset, count);
+ return count;
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ var pos = (int) Position;
+ if (count < 0 || Length - pos < count || buffer.Length < count + offset) throw new ArgumentOutOfRangeException();
+
+ // is mutating the buffer passed to Stream.Write kosher?
+ XorTransform(_initial, _offset + pos, buffer, offset, count);
+ base.Write(buffer, offset, count);
+ }
+
+ /// bounds check already done by calling method i.e. in base.Read (for ) or in
+ private static unsafe void XorTransform(byte[] source, int sourceOffset, byte[] dest, int destOffset, int length)
+ {
+ // TODO: C compilers can make this pretty snappy, but can the C# jitter? Or do we need intrinsics
+ fixed (byte* _s = source, _d = dest)
+ {
+ byte* s = _s + sourceOffset;
+ byte* d = _d + destOffset;
+ byte* sEnd = s + length;
+ while (s < sEnd) *d++ ^= *s++;
+ }
+ }
+ }
+ }
+}
diff --git a/src/BizHawk.BizInvoke/MemoryBlockBase.cs b/src/BizHawk.BizInvoke/MemoryBlockBase.cs
deleted file mode 100644
index 1219c9b4d2..0000000000
--- a/src/BizHawk.BizInvoke/MemoryBlockBase.cs
+++ /dev/null
@@ -1,255 +0,0 @@
-using System;
-using System.IO;
-using System.Runtime.InteropServices;
-using BizHawk.Common;
-
-namespace BizHawk.BizInvoke
-{
- public abstract class MemoryBlockBase : IDisposable
- {
- /// allocate bytes starting at a particular address
- /// is not aligned or is 0
- protected MemoryBlockBase(ulong start, ulong size)
- {
- if (!WaterboxUtils.Aligned(start))
- throw new ArgumentOutOfRangeException(nameof(start), start, "start address must be aligned");
- if (size == 0)
- throw new ArgumentOutOfRangeException(nameof(size), size, "cannot create 0-length block");
- Start = start;
- Size = WaterboxUtils.AlignUp(size);
- EndExclusive = Start + Size;
- _pageData = new Protection[GetPage(EndExclusive - 1) + 1];
- }
-
- /// stores last set memory protection value for each page
- protected readonly Protection[] _pageData;
-
- /// end address of the memory block (not part of the block; class invariant: equal to + )
- public readonly ulong EndExclusive;
-
- /// total size of the memory block
- public readonly ulong Size;
-
- /// starting address of the memory block
- public readonly ulong Start;
-
- /// snapshot for XOR buffer
- protected byte[] _snapshot;
-
- /// true if this is currently swapped in
- public bool Active { get; protected set; }
-
- public byte[] XorHash { get; protected set; }
-
- /// get a page index within the block
- protected int GetPage(ulong addr)
- {
- if (addr < Start || EndExclusive <= addr) throw new ArgumentOutOfRangeException(nameof(addr), addr, "invalid address");
- return (int) ((addr - Start) >> WaterboxUtils.PageShift);
- }
-
- /// get a start address for a page index within the block
- protected ulong GetStartAddr(int page) => ((ulong) page << WaterboxUtils.PageShift) + Start;
-
- /// Get a stream that can be used to read or write from part of the block. Does not check for or change !
- /// or end (= + - 1) are outside [, ), the range of the block
- public Stream GetStream(ulong start, ulong length, bool writer)
- {
- if (start < Start)
- throw new ArgumentOutOfRangeException(nameof(start), start, "invalid address");
- if (EndExclusive < start + length)
- throw new ArgumentOutOfRangeException(nameof(length), length, "requested length implies invalid end address");
- return new MemoryViewStream(!writer, writer, (long) start, (long) length, this);
- }
-
- /// get a stream that can be used to read or write from part of the block. both reads and writes will be XORed against an earlier recorded snapshot
- /// or end (= + - 1) are outside [, ), the range of the block
- /// no snapshot taken (haven't called )
- public Stream GetXorStream(ulong start, ulong length, bool writer)
- {
- if (start < Start) throw new ArgumentOutOfRangeException(nameof(start), start, "invalid address");
- if (EndExclusive < start + length) throw new ArgumentOutOfRangeException(nameof(length), length, "requested length implies invalid end address");
- if (_snapshot == null) throw new InvalidOperationException("No snapshot taken!");
- return new MemoryViewXorStream(!writer, writer, (long) start, (long) length, this, _snapshot, (long) (start - Start));
- }
-
- /// activate the memory block, swapping it in at the pre-specified address
- public abstract void Activate();
-
- /// deactivate the memory block, removing it from RAM but leaving it immediately available to swap back in
- public abstract void Deactivate();
-
- /// take a hash of the current full contents of the block, including unreadable areas
- public abstract byte[] FullHash();
-
- /// set r/w/x protection on a portion of memory. rounded to encompassing pages
- public abstract void Protect(ulong start, ulong length, Protection prot);
-
- /// restore all recorded protections
- protected abstract void ProtectAll();
-
- /// take a snapshot of the entire memory block's contents, for use in
- public abstract void SaveXorSnapshot();
-
- public abstract void Dispose(bool disposing);
-
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- ~MemoryBlockBase()
- {
- Dispose(false);
- }
-
- /// allocate bytes starting at a particular address
- public static MemoryBlockBase CallPlatformCtor(ulong start, ulong size) => OSTailoredCode.IsUnixHost
- ? (MemoryBlockBase) new MemoryBlockUnix(start, size)
- : new MemoryBlock(start, size);
-
- /// allocate bytes at any address
- public static MemoryBlockBase CallPlatformCtor(ulong size) => CallPlatformCtor(0, size);
-
- /// Memory protection constant
- public enum Protection : byte { None, R, RW, RX }
-
- private class MemoryViewStream : Stream
- {
- public MemoryViewStream(bool readable, bool writable, long ptr, long length, MemoryBlockBase owner)
- {
- _readable = readable;
- _writable = writable;
- _ptr = ptr;
- _length = length;
- _owner = owner;
- _pos = 0;
- }
-
- private readonly long _length;
- private readonly MemoryBlockBase _owner;
- private readonly long _ptr;
- private readonly bool _readable;
- private readonly bool _writable;
-
- private long _pos;
-
- public override bool CanRead => _readable;
- public override bool CanSeek => true;
- public override bool CanWrite => _writable;
- public override long Length => _length;
- public override long Position
- {
- get => _pos;
- set
- {
- if (value < 0 || _length < value) throw new ArgumentOutOfRangeException();
- _pos = value;
- }
- }
-
- private void EnsureNotDisposed()
- {
- if (_owner.Start == 0)
- throw new ObjectDisposedException(nameof(MemoryBlockBase));
- }
-
- public override void Flush() {}
-
- public override int Read(byte[] buffer, int offset, int count)
- {
- if (!_readable) throw new InvalidOperationException();
- if (count < 0 || buffer.Length < count + offset) throw new ArgumentOutOfRangeException();
- EnsureNotDisposed();
-
- count = (int) Math.Min(count, _length - _pos);
- Marshal.Copy(Z.SS(_ptr + _pos), buffer, offset, count);
- _pos += count;
- return count;
- }
-
- public override long Seek(long offset, SeekOrigin origin)
- {
- long newpos;
- switch (origin)
- {
- default:
- case SeekOrigin.Begin:
- newpos = offset;
- break;
- case SeekOrigin.Current:
- newpos = _pos + offset;
- break;
- case SeekOrigin.End:
- newpos = _length + offset;
- break;
- }
- Position = newpos;
- return newpos;
- }
-
- public override void SetLength(long value)
- {
- throw new InvalidOperationException();
- }
-
- public override void Write(byte[] buffer, int offset, int count)
- {
- if (!_writable) throw new InvalidOperationException();
- if (count < 0 || _length - _pos < count || buffer.Length < count + offset) throw new ArgumentOutOfRangeException();
- EnsureNotDisposed();
-
- Marshal.Copy(buffer, offset, Z.SS(_ptr + _pos), count);
- _pos += count;
- }
- }
-
- private class MemoryViewXorStream : MemoryViewStream
- {
- public MemoryViewXorStream(bool readable, bool writable, long ptr, long length, MemoryBlockBase owner, byte[] initial, long offset)
- : base(readable, writable, ptr, length, owner)
- {
- _initial = initial;
- _offset = (int) offset;
- }
-
- /// the initial data to XOR against for both reading and writing
- private readonly byte[] _initial;
-
- /// offset into the XOR data that this stream is representing
- private readonly int _offset;
-
- public override int Read(byte[] buffer, int offset, int count)
- {
- var pos = (int) Position;
- count = base.Read(buffer, offset, count);
- XorTransform(_initial, _offset + pos, buffer, offset, count);
- return count;
- }
-
- public override void Write(byte[] buffer, int offset, int count)
- {
- var pos = (int) Position;
- if (count < 0 || Length - pos < count || buffer.Length < count + offset) throw new ArgumentOutOfRangeException();
-
- // is mutating the buffer passed to Stream.Write kosher?
- XorTransform(_initial, _offset + pos, buffer, offset, count);
- base.Write(buffer, offset, count);
- }
-
- /// bounds check already done by calling method i.e. in base.Read (for ) or in
- private static unsafe void XorTransform(byte[] source, int sourceOffset, byte[] dest, int destOffset, int length)
- {
- // TODO: C compilers can make this pretty snappy, but can the C# jitter? Or do we need intrinsics
- fixed (byte* _s = source, _d = dest)
- {
- byte* s = _s + sourceOffset;
- byte* d = _d + destOffset;
- byte* sEnd = s + length;
- while (s < sEnd) *d++ ^= *s++;
- }
- }
- }
- }
-}
diff --git a/src/BizHawk.BizInvoke/MemoryBlockUnix.cs b/src/BizHawk.BizInvoke/MemoryBlockUnix.cs
index b3914cd7de..36ad113680 100644
--- a/src/BizHawk.BizInvoke/MemoryBlockUnix.cs
+++ b/src/BizHawk.BizInvoke/MemoryBlockUnix.cs
@@ -5,12 +5,12 @@ using static BizHawk.BizInvoke.POSIXLibC;
namespace BizHawk.BizInvoke
{
- public sealed class MemoryBlockUnix : MemoryBlockBase
+ public sealed class MemoryBlockUnix : MemoryBlock
{
/// handle returned by
private int _fd;
- ///
+ ///
/// failed to get file descriptor (never thrown as is thrown first)
/// always
public MemoryBlockUnix(ulong start, ulong size) : base(start, size)
@@ -22,7 +22,7 @@ namespace BizHawk.BizInvoke
#endif
}
- /// is or failed to map memory
+ /// is or failed to map memory
public override void Activate()
{
if (Active) throw new InvalidOperationException("Already active");
@@ -34,7 +34,7 @@ namespace BizHawk.BizInvoke
Active = true;
}
- /// is or failed to unmap memory
+ /// is or failed to unmap memory
public override void Deactivate()
{
if (!Active) throw new InvalidOperationException("Not active");
@@ -45,7 +45,7 @@ namespace BizHawk.BizInvoke
Active = false;
}
- /// is or failed to make memory read-only
+ /// is or failed to make memory read-only
public override byte[] FullHash()
{
if (!Active) throw new InvalidOperationException("Not active");
@@ -100,7 +100,7 @@ namespace BizHawk.BizInvoke
}
}
- /// snapshot already taken, is , or failed to make memory read-only
+ /// snapshot already taken, is , or failed to make memory read-only
public override void SaveXorSnapshot()
{
if (_snapshot != null) throw new InvalidOperationException("Snapshot already taken");
diff --git a/src/BizHawk.BizInvoke/MemoryBlockWindows.cs b/src/BizHawk.BizInvoke/MemoryBlockWindows.cs
new file mode 100644
index 0000000000..ba2f6a3591
--- /dev/null
+++ b/src/BizHawk.BizInvoke/MemoryBlockWindows.cs
@@ -0,0 +1,238 @@
+using System;
+using System.Runtime.InteropServices;
+using System.IO;
+
+namespace BizHawk.BizInvoke
+{
+ public sealed class MemoryBlockWindows : MemoryBlock
+ {
+ ///
+ /// handle returned by CreateFileMapping
+ ///
+ private IntPtr _handle;
+
+ ///
+ /// failed to create file mapping
+ public MemoryBlockWindows(ulong start, ulong size) : base(start, size)
+ {
+ _handle = Kernel32.CreateFileMapping(
+ Kernel32.INVALID_HANDLE_VALUE,
+ IntPtr.Zero,
+ Kernel32.FileMapProtection.PageExecuteReadWrite | Kernel32.FileMapProtection.SectionCommit,
+ (uint)(Size >> 32),
+ (uint)Size,
+ null
+ );
+ if (_handle == IntPtr.Zero) throw new InvalidOperationException($"{nameof(Kernel32.CreateFileMapping)}() returned NULL");
+ }
+
+ /// is or failed to map file view
+ public override void Activate()
+ {
+ if (Active)
+ throw new InvalidOperationException("Already active");
+ if (Kernel32.MapViewOfFileEx(
+ _handle,
+ Kernel32.FileMapAccessType.Read | Kernel32.FileMapAccessType.Write | Kernel32.FileMapAccessType.Execute,
+ 0,
+ 0,
+ Z.UU(Size),
+ Z.US(Start)
+ ) != Z.US(Start))
+ {
+ throw new InvalidOperationException($"{nameof(Kernel32.MapViewOfFileEx)}() returned NULL");
+ }
+ ProtectAll();
+ Active = true;
+ }
+
+ /// is or failed to unmap file view
+ public override void Deactivate()
+ {
+ if (!Active)
+ throw new InvalidOperationException("Not active");
+ if (!Kernel32.UnmapViewOfFile(Z.US(Start)))
+ throw new InvalidOperationException($"{nameof(Kernel32.UnmapViewOfFile)}() returned NULL");
+ Active = false;
+ }
+
+ /// snapshot already taken, is , or failed to make memory read-only
+ public override void SaveXorSnapshot()
+ {
+ if (_snapshot != null)
+ throw new InvalidOperationException("Snapshot already taken");
+ if (!Active)
+ throw new InvalidOperationException("Not active");
+
+ // temporarily switch the entire block to `R`: in case some areas are unreadable, we don't want
+ // that to complicate things
+ Kernel32.MemoryProtection old;
+ if (!Kernel32.VirtualProtect(Z.UU(Start), Z.UU(Size), Kernel32.MemoryProtection.READONLY, out old))
+ throw new InvalidOperationException($"{nameof(Kernel32.VirtualProtect)}() returned FALSE!");
+
+ _snapshot = new byte[Size];
+ var ds = new MemoryStream(_snapshot, true);
+ var ss = GetStream(Start, Size, false);
+ ss.CopyTo(ds);
+ XorHash = WaterboxUtils.Hash(_snapshot);
+
+ ProtectAll();
+ }
+
+ /// is or failed to make memory read-only
+ public override byte[] FullHash()
+ {
+ if (!Active)
+ throw new InvalidOperationException("Not active");
+ // temporarily switch the entire block to `R`
+ Kernel32.MemoryProtection old;
+ if (!Kernel32.VirtualProtect(Z.UU(Start), Z.UU(Size), Kernel32.MemoryProtection.READONLY, out old))
+ throw new InvalidOperationException($"{nameof(Kernel32.VirtualProtect)}() returned FALSE!");
+ var ret = WaterboxUtils.Hash(GetStream(Start, Size, false));
+ ProtectAll();
+ return ret;
+ }
+
+ private static Kernel32.MemoryProtection GetKernelMemoryProtectionValue(Protection prot)
+ {
+ Kernel32.MemoryProtection p;
+ switch (prot)
+ {
+ case Protection.None: p = Kernel32.MemoryProtection.NOACCESS; break;
+ case Protection.R: p = Kernel32.MemoryProtection.READONLY; break;
+ case Protection.RW: p = Kernel32.MemoryProtection.READWRITE; break;
+ case Protection.RX: p = Kernel32.MemoryProtection.EXECUTE_READ; break;
+ default: throw new ArgumentOutOfRangeException(nameof(prot));
+ }
+ return p;
+ }
+
+ protected override void ProtectAll()
+ {
+ int ps = 0;
+ for (int i = 0; i < _pageData.Length; i++)
+ {
+ if (i == _pageData.Length - 1 || _pageData[i] != _pageData[i + 1])
+ {
+ var p = GetKernelMemoryProtectionValue(_pageData[i]);
+ ulong zstart = GetStartAddr(ps);
+ ulong zend = GetStartAddr(i + 1);
+ Kernel32.MemoryProtection old;
+ if (!Kernel32.VirtualProtect(Z.UU(zstart), Z.UU(zend - zstart), p, out old))
+ throw new InvalidOperationException($"{nameof(Kernel32.VirtualProtect)}() returned FALSE!");
+ ps = i + 1;
+ }
+ }
+ }
+
+ /// failed to protect memory
+ public override void Protect(ulong start, ulong length, Protection prot)
+ {
+ if (length == 0)
+ return;
+ int pstart = GetPage(start);
+ int pend = GetPage(start + length - 1);
+
+ var p = GetKernelMemoryProtectionValue(prot);
+ for (int i = pstart; i <= pend; i++)
+ _pageData[i] = prot; // also store the value for later use
+
+ if (Active) // it's legal to Protect() if we're not active; the information is just saved for the next activation
+ {
+ var computedStart = WaterboxUtils.AlignDown(start);
+ var computedEnd = WaterboxUtils.AlignUp(start + length);
+ var computedLength = computedEnd - computedStart;
+
+ Kernel32.MemoryProtection old;
+ if (!Kernel32.VirtualProtect(Z.UU(computedStart),
+ Z.UU(computedLength), p, out old))
+ throw new InvalidOperationException($"{nameof(Kernel32.VirtualProtect)}() returned FALSE!");
+ }
+ }
+
+ public override void Dispose(bool disposing)
+ {
+ if (_handle != IntPtr.Zero)
+ {
+ if (Active)
+ Deactivate();
+ Kernel32.CloseHandle(_handle);
+ _handle = IntPtr.Zero;
+ }
+ }
+
+ ~MemoryBlockWindows()
+ {
+ Dispose(false);
+ }
+
+ private static class Kernel32
+ {
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern bool VirtualProtect(UIntPtr lpAddress, UIntPtr dwSize,
+ MemoryProtection flNewProtect, out MemoryProtection lpflOldProtect);
+
+ [Flags]
+ public enum MemoryProtection : uint
+ {
+ EXECUTE = 0x10,
+ EXECUTE_READ = 0x20,
+ EXECUTE_READWRITE = 0x40,
+ EXECUTE_WRITECOPY = 0x80,
+ NOACCESS = 0x01,
+ READONLY = 0x02,
+ READWRITE = 0x04,
+ WRITECOPY = 0x08,
+ GUARD_Modifierflag = 0x100,
+ NOCACHE_Modifierflag = 0x200,
+ WRITECOMBINE_Modifierflag = 0x400
+ }
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern IntPtr CreateFileMapping(
+ IntPtr hFile,
+ IntPtr lpFileMappingAttributes,
+ FileMapProtection flProtect,
+ uint dwMaximumSizeHigh,
+ uint dwMaximumSizeLow,
+ string lpName);
+
+ [Flags]
+ public enum FileMapProtection : uint
+ {
+ PageReadonly = 0x02,
+ PageReadWrite = 0x04,
+ PageWriteCopy = 0x08,
+ PageExecuteRead = 0x20,
+ PageExecuteReadWrite = 0x40,
+ SectionCommit = 0x8000000,
+ SectionImage = 0x1000000,
+ SectionNoCache = 0x10000000,
+ SectionReserve = 0x4000000,
+ }
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern bool CloseHandle(IntPtr hObject);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern bool UnmapViewOfFile(IntPtr lpBaseAddress);
+
+ [DllImport("kernel32.dll")]
+ public static extern IntPtr MapViewOfFileEx(IntPtr hFileMappingObject,
+ FileMapAccessType dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow,
+ UIntPtr dwNumberOfBytesToMap, IntPtr lpBaseAddress);
+
+ [Flags]
+ public enum FileMapAccessType : uint
+ {
+ Copy = 0x01,
+ Write = 0x02,
+ Read = 0x04,
+ AllAccess = 0x08,
+ Execute = 0x20,
+ }
+
+ public static readonly IntPtr INVALID_HANDLE_VALUE = Z.US(0xffffffffffffffff);
+ }
+ }
+}
diff --git a/src/BizHawk.BizInvoke/POSIXLibC.cs b/src/BizHawk.BizInvoke/POSIXLibC.cs
index 6d61c32b8f..db3e7a956a 100644
--- a/src/BizHawk.BizInvoke/POSIXLibC.cs
+++ b/src/BizHawk.BizInvoke/POSIXLibC.cs
@@ -1,7 +1,7 @@
using System;
using System.Runtime.InteropServices;
-using static BizHawk.BizInvoke.MemoryBlockBase;
+using static BizHawk.BizInvoke.MemoryBlock;
namespace BizHawk.BizInvoke
{
diff --git a/src/BizHawk.Emulation.Cores/Waterbox/ElfLoader.cs b/src/BizHawk.Emulation.Cores/Waterbox/ElfLoader.cs
index 140b169ec5..c454f2d4cc 100644
--- a/src/BizHawk.Emulation.Cores/Waterbox/ElfLoader.cs
+++ b/src/BizHawk.Emulation.Cores/Waterbox/ElfLoader.cs
@@ -33,7 +33,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
private bool _everythingSealed;
- public MemoryBlockBase Memory { get; private set; }
+ public MemoryBlock Memory { get; private set; }
public string ModuleName { get; }
@@ -94,9 +94,9 @@ namespace BizHawk.Emulation.Cores.Waterbox
.ToList();
- Memory = MemoryBlock.CallPlatformCtor(start, size);
+ Memory = MemoryBlock.Create(start, size);
Memory.Activate();
- Memory.Protect(Memory.Start, Memory.Size, MemoryBlockBase.Protection.RW);
+ Memory.Protect(Memory.Start, Memory.Size, MemoryBlock.Protection.RW);
foreach (var seg in loadsegs)
{
@@ -170,23 +170,23 @@ namespace BizHawk.Emulation.Cores.Waterbox
///
private void Protect()
{
- Memory.Protect(Memory.Start, Memory.Size, MemoryBlockBase.Protection.R);
+ Memory.Protect(Memory.Start, Memory.Size, MemoryBlock.Protection.R);
foreach (var sec in _elf.Sections.Where(s => (s.Flags & SectionFlags.Allocatable) != 0))
{
if (_everythingSealed && IsSpecialReadonlySection(sec))
continue;
if ((sec.Flags & SectionFlags.Executable) != 0)
- Memory.Protect(sec.LoadAddress, sec.Size, MemoryBlockBase.Protection.RX);
+ Memory.Protect(sec.LoadAddress, sec.Size, MemoryBlock.Protection.RX);
else if ((sec.Flags & SectionFlags.Writable) != 0)
- Memory.Protect(sec.LoadAddress, sec.Size, MemoryBlockBase.Protection.RW);
+ Memory.Protect(sec.LoadAddress, sec.Size, MemoryBlock.Protection.RW);
}
}
// connect all of the .wbxsyscall stuff
public void ConnectSyscalls(IImportResolver syscalls)
{
- Memory.Protect(Memory.Start, Memory.Size, MemoryBlockBase.Protection.RW);
+ Memory.Protect(Memory.Start, Memory.Size, MemoryBlock.Protection.RW);
var tmp = new IntPtr[1];
var ptrSize = (ulong)IntPtr.Size;
@@ -343,7 +343,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
throw new InvalidOperationException("Memory consistency check failed. Is this savestate from different SyncSettings?");
}
- Memory.Protect(Memory.Start, Memory.Size, MemoryBlockBase.Protection.RW);
+ Memory.Protect(Memory.Start, Memory.Size, MemoryBlock.Protection.RW);
foreach (var s in _savedSections)
{
diff --git a/src/BizHawk.Emulation.Cores/Waterbox/Heap.cs b/src/BizHawk.Emulation.Cores/Waterbox/Heap.cs
index 24d0629dec..9ac0916276 100644
--- a/src/BizHawk.Emulation.Cores/Waterbox/Heap.cs
+++ b/src/BizHawk.Emulation.Cores/Waterbox/Heap.cs
@@ -11,7 +11,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
///
internal sealed class Heap : IBinaryStateable, IDisposable
{
- public MemoryBlockBase Memory { get; private set; }
+ public MemoryBlock Memory { get; private set; }
///
/// name, used in identifying errors
///
@@ -30,7 +30,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
public Heap(ulong start, ulong size, string name)
{
- Memory = MemoryBlockBase.CallPlatformCtor(start, size);
+ Memory = MemoryBlock.Create(start, size);
Used = 0;
Name = name;
Console.WriteLine("Created heap `{1}` at {0:x16}:{2:x16}", start, name, start + size);
@@ -62,7 +62,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
throw new InvalidOperationException($"Failed to allocate {size} bytes from heap {Name}");
}
ulong ret = Memory.Start + allocstart;
- Memory.Protect(Memory.Start + Used, newused - Used, MemoryBlockBase.Protection.RW);
+ Memory.Protect(Memory.Start + Used, newused - Used, MemoryBlock.Protection.RW);
Used = newused;
Console.WriteLine($"Allocated {size} bytes on {Name}, utilization {Used}/{Memory.Size} ({100.0 * Used / Memory.Size:0.#}%)");
return ret;
@@ -72,7 +72,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
{
if (!Sealed)
{
- Memory.Protect(Memory.Start, Used, MemoryBlockBase.Protection.R);
+ Memory.Protect(Memory.Start, Used, MemoryBlock.Protection.R);
_hash = WaterboxUtils.Hash(Memory.GetStream(Memory.Start, Used, false));
Sealed = true;
}
@@ -116,8 +116,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
var usedAligned = WaterboxUtils.AlignUp(used);
- Memory.Protect(Memory.Start, Memory.Size, MemoryBlockBase.Protection.None);
- Memory.Protect(Memory.Start, used, MemoryBlockBase.Protection.RW);
+ Memory.Protect(Memory.Start, Memory.Size, MemoryBlock.Protection.None);
+ Memory.Protect(Memory.Start, used, MemoryBlock.Protection.RW);
var ms = Memory.GetXorStream(Memory.Start, usedAligned, true);
WaterboxUtils.CopySome(br.BaseStream, ms, (long)usedAligned);
Used = used;
diff --git a/src/BizHawk.Emulation.Cores/Waterbox/MapHeap.cs b/src/BizHawk.Emulation.Cores/Waterbox/MapHeap.cs
index 8b34a4aff3..f6cac6282d 100644
--- a/src/BizHawk.Emulation.Cores/Waterbox/MapHeap.cs
+++ b/src/BizHawk.Emulation.Cores/Waterbox/MapHeap.cs
@@ -13,7 +13,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
///
internal sealed class MapHeap : IBinaryStateable, IDisposable
{
- public MemoryBlockBase Memory { get; private set; }
+ public MemoryBlock Memory { get; private set; }
///
/// name, used in identifying errors
///
@@ -40,18 +40,18 @@ namespace BizHawk.Emulation.Cores.Waterbox
return ((ulong)page << WaterboxUtils.PageShift) + Memory.Start;
}
- private const MemoryBlockBase.Protection FREE = (MemoryBlockBase.Protection)255;
+ private const MemoryBlock.Protection FREE = (MemoryBlock.Protection)255;
- private readonly MemoryBlockBase.Protection[] _pages;
+ private readonly MemoryBlock.Protection[] _pages;
private readonly byte[] _pagesAsBytes;
public MapHeap(ulong start, ulong size, string name)
{
size = WaterboxUtils.AlignUp(size);
- Memory = MemoryBlockBase.CallPlatformCtor(start, size);
+ Memory = MemoryBlock.Create(start, size);
Name = name;
_pagesAsBytes = new byte[size >> WaterboxUtils.PageShift];
- _pages = (MemoryBlockBase.Protection[])(object)_pagesAsBytes;
+ _pages = (MemoryBlock.Protection[])(object)_pagesAsBytes;
for (var i = 0; i < _pages.Length; i++)
_pages[i] = FREE;
Console.WriteLine($"Created {nameof(MapHeap)} `{name}` at {start:x16}:{start + size:x16}");
@@ -102,7 +102,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
return -1;
}
- private void ProtectInternal(int startPage, int numPages, MemoryBlockBase.Protection prot, bool wasUsed)
+ private void ProtectInternal(int startPage, int numPages, MemoryBlock.Protection prot, bool wasUsed)
{
for (var i = startPage; i < startPage + numPages; i++)
_pages[i] = prot;
@@ -111,9 +111,9 @@ namespace BizHawk.Emulation.Cores.Waterbox
ulong length = ((ulong)numPages) << WaterboxUtils.PageShift;
if (prot == FREE)
{
- Memory.Protect(start, length, MemoryBlockBase.Protection.RW);
+ Memory.Protect(start, length, MemoryBlock.Protection.RW);
WaterboxUtils.ZeroMemory(Z.US(start), (long)length);
- Memory.Protect(start, length, MemoryBlockBase.Protection.None);
+ Memory.Protect(start, length, MemoryBlock.Protection.None);
Used -= length;
Console.WriteLine($"Freed {length} bytes on {Name}, utilization {Used}/{Memory.Size} ({100.0 * Used / Memory.Size:0.#}%)");
}
@@ -142,7 +142,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
var p = _pages[i];
ulong zstart = GetStartAddr(ps);
ulong zlength = (ulong)(i - ps + 1) << WaterboxUtils.PageShift;
- Memory.Protect(zstart, zlength, p == FREE ? MemoryBlockBase.Protection.None : p);
+ Memory.Protect(zstart, zlength, p == FREE ? MemoryBlock.Protection.None : p);
ps = i + 1;
}
}
@@ -161,7 +161,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
return true;
}
- public ulong Map(ulong size, MemoryBlockBase.Protection prot)
+ public ulong Map(ulong size, MemoryBlock.Protection prot)
{
if (size == 0)
return 0;
@@ -216,14 +216,14 @@ namespace BizHawk.Emulation.Cores.Waterbox
var copyPageLen = Math.Min(oldNumPages, newNumPages);
var data = new byte[copyDataLen];
- Memory.Protect(start, copyDataLen, MemoryBlockBase.Protection.RW);
+ Memory.Protect(start, copyDataLen, MemoryBlock.Protection.RW);
Marshal.Copy(Z.US(start), data, 0, (int)copyDataLen);
- var pages = new MemoryBlockBase.Protection[copyPageLen];
+ var pages = new MemoryBlock.Protection[copyPageLen];
Array.Copy(_pages, oldStartPage, pages, 0, copyPageLen);
ProtectInternal(oldStartPage, oldNumPages, FREE, true);
- ProtectInternal(newStartPage, newNumPages, MemoryBlockBase.Protection.RW, false);
+ ProtectInternal(newStartPage, newNumPages, MemoryBlock.Protection.RW, false);
var ret = GetStartAddr(newStartPage);
Marshal.Copy(data, 0, Z.US(ret), (int)copyDataLen);
@@ -241,7 +241,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
return Protect(start, size, FREE);
}
- public bool Protect(ulong start, ulong size, MemoryBlockBase.Protection prot)
+ public bool Protect(ulong start, ulong size, MemoryBlock.Protection prot)
{
if (start < Memory.Start || start + size > Memory.EndExclusive || size == 0)
return false;
@@ -274,7 +274,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
bw.Write(Memory.XorHash);
bw.Write(_pagesAsBytes);
- Memory.Protect(Memory.Start, Memory.Size, MemoryBlockBase.Protection.R);
+ Memory.Protect(Memory.Start, Memory.Size, MemoryBlock.Protection.R);
var srcs = Memory.GetXorStream(Memory.Start, Memory.Size, false);
for (int i = 0, addr = 0; i < _pages.Length; i++, addr += WaterboxUtils.PageSize)
{
@@ -305,7 +305,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
throw new InvalidOperationException("Unexpected error reading!");
Used = 0;
- Memory.Protect(Memory.Start, Memory.Size, MemoryBlockBase.Protection.RW);
+ Memory.Protect(Memory.Start, Memory.Size, MemoryBlock.Protection.RW);
var dsts = Memory.GetXorStream(Memory.Start, Memory.Size, true);
for (int i = 0, addr = 0; i < _pages.Length; i++, addr += WaterboxUtils.PageSize)
{
@@ -333,7 +333,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
{
ulong siz = (ulong)(rnd.Next(256 * 1024) + 384 * 1024);
siz = siz / 4096 * 4096;
- var ptr = mmo.Map(siz, MemoryBlockBase.Protection.RW);
+ var ptr = mmo.Map(siz, MemoryBlock.Protection.RW);
allocs.Add(ptr, siz);
}
@@ -349,7 +349,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
{
ulong siz = (ulong)(rnd.Next(256 * 1024) + 384 * 1024);
siz = siz / 4096 * 4096;
- var ptr = mmo.Map(siz, MemoryBlockBase.Protection.RW);
+ var ptr = mmo.Map(siz, MemoryBlock.Protection.RW);
allocs.Add(ptr, siz);
}
diff --git a/src/BizHawk.Emulation.Cores/Waterbox/Swappable.cs b/src/BizHawk.Emulation.Cores/Waterbox/Swappable.cs
index a84431ffb7..64c9aa9a4e 100644
--- a/src/BizHawk.Emulation.Cores/Waterbox/Swappable.cs
+++ b/src/BizHawk.Emulation.Cores/Waterbox/Swappable.cs
@@ -28,14 +28,14 @@ namespace BizHawk.Emulation.Cores.Waterbox
///
/// everything to swap in for context switches
///
- private List _memoryBlocks = new List();
+ private List _memoryBlocks = new List();
///
/// an informative name for each memory block: used for debugging purposes
///
private List _memoryBlockNames = new List();
- protected void AddMemoryBlock(MemoryBlockBase block, string name)
+ protected void AddMemoryBlock(MemoryBlock block, string name)
{
_memoryBlocks.Add(block);
_memoryBlockNames.Add(name);
diff --git a/src/BizHawk.Emulation.Cores/Waterbox/Syscalls.cs b/src/BizHawk.Emulation.Cores/Waterbox/Syscalls.cs
index e36c31d767..fd8428a0ca 100644
--- a/src/BizHawk.Emulation.Cores/Waterbox/Syscalls.cs
+++ b/src/BizHawk.Emulation.Cores/Waterbox/Syscalls.cs
@@ -399,18 +399,18 @@ namespace BizHawk.Emulation.Cores.Waterbox
{
if (address != IntPtr.Zero)
return Z.SS(-1);
- MemoryBlockBase.Protection mprot;
+ MemoryBlock.Protection mprot;
switch (prot)
{
- case 0: mprot = MemoryBlockBase.Protection.None; break;
+ case 0: mprot = MemoryBlock.Protection.None; break;
default:
case 6: // W^X
case 7: // W^X
case 4: // exec only????
case 2: return Z.SS(-1); // write only????
- case 3: mprot = MemoryBlockBase.Protection.RW; break;
- case 1: mprot = MemoryBlockBase.Protection.R; break;
- case 5: mprot = MemoryBlockBase.Protection.RX; break;
+ case 3: mprot = MemoryBlock.Protection.RW; break;
+ case 1: mprot = MemoryBlock.Protection.R; break;
+ case 5: mprot = MemoryBlock.Protection.RX; break;
}
if ((flags & 0x20) == 0)
{
@@ -448,18 +448,18 @@ namespace BizHawk.Emulation.Cores.Waterbox
[BizExport(CallingConvention.Cdecl, EntryPoint = "__wsyscalltab[10]")]
public int MProtect(UIntPtr address, UIntPtr size, int prot)
{
- MemoryBlockBase.Protection mprot;
+ MemoryBlock.Protection mprot;
switch (prot)
{
- case 0: mprot = MemoryBlockBase.Protection.None; break;
+ case 0: mprot = MemoryBlock.Protection.None; break;
default:
case 6: // W^X
case 7: // W^X
case 4: // exec only????
case 2: return -1; // write only????
- case 3: mprot = MemoryBlockBase.Protection.RW; break;
- case 1: mprot = MemoryBlockBase.Protection.R; break;
- case 5: mprot = MemoryBlockBase.Protection.RX; break;
+ case 3: mprot = MemoryBlock.Protection.RW; break;
+ case 1: mprot = MemoryBlock.Protection.R; break;
+ case 5: mprot = MemoryBlock.Protection.RX; break;
}
return _parent._mmapheap.Protect((ulong)address, (ulong)size, mprot) ? 0 : -1;
}