2013-11-04 02:11:40 +00:00
|
|
|
|
using System;
|
|
|
|
|
|
|
|
|
|
namespace BizHawk.Emulation.Common
|
|
|
|
|
{
|
2016-12-14 15:11:07 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// A memory region and the functionality to read/write from it
|
|
|
|
|
/// as required by the IMemoryDomains service.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <seealso cref="IMemoryDomains" />
|
2016-04-13 23:50:06 +00:00
|
|
|
|
public abstract class MemoryDomain
|
2013-11-04 02:11:40 +00:00
|
|
|
|
{
|
|
|
|
|
public enum Endian { Big, Little, Unknown }
|
|
|
|
|
|
2016-04-13 23:50:06 +00:00
|
|
|
|
public string Name { get; protected set; }
|
2013-11-04 02:11:40 +00:00
|
|
|
|
|
2016-04-13 23:50:06 +00:00
|
|
|
|
public long Size { get; protected set; }
|
2015-01-18 13:53:21 +00:00
|
|
|
|
|
2016-04-13 23:50:06 +00:00
|
|
|
|
public int WordSize { get; protected set; }
|
2015-01-18 13:53:21 +00:00
|
|
|
|
|
2016-04-13 23:50:06 +00:00
|
|
|
|
public Endian EndianType { get; protected set; }
|
2015-02-22 15:19:38 +00:00
|
|
|
|
|
2016-04-13 23:50:06 +00:00
|
|
|
|
public bool Writable { get; protected set; }
|
2015-01-18 13:53:21 +00:00
|
|
|
|
|
2016-04-13 23:50:06 +00:00
|
|
|
|
public abstract byte PeekByte(long addr);
|
2015-01-18 13:53:21 +00:00
|
|
|
|
|
2016-04-13 23:50:06 +00:00
|
|
|
|
public abstract void PokeByte(long addr, byte val);
|
2016-03-27 21:35:34 +00:00
|
|
|
|
|
2015-01-21 17:36:22 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// creates a memorydomain that references a managed byte array
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="writable">if false, writes will be ignored</param>
|
2016-04-13 23:50:06 +00:00
|
|
|
|
[Obsolete]
|
|
|
|
|
public static MemoryDomain FromByteArray(string name, Endian endian, byte[] data, bool writable = true, int wordSize = 1)
|
2016-03-27 21:35:34 +00:00
|
|
|
|
{
|
2016-04-13 23:50:06 +00:00
|
|
|
|
return new MemoryDomainByteArray(name, endian, data, writable, wordSize);
|
2016-03-27 21:35:34 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// create a memorydomain that references an unmanaged memory block
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="data">must remain valid as long as the MemoryDomain exists!</param>
|
|
|
|
|
/// <param name="writable">if false, writes will be ignored</param>
|
2016-04-13 23:50:06 +00:00
|
|
|
|
[Obsolete]
|
|
|
|
|
public unsafe static MemoryDomain FromIntPtr(string name, long size, Endian endian, IntPtr data, bool writable = true, int wordSize = 1)
|
2016-03-27 21:35:34 +00:00
|
|
|
|
{
|
2016-04-13 23:50:06 +00:00
|
|
|
|
return new MemoryDomainIntPtr(name, endian, data, size, writable, wordSize);
|
2014-08-15 21:21:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-09-08 14:50:36 +00:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// create a memorydomain that references an unmanaged memory block with 16 bit swaps
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="data">must remain valid as long as the MemoryDomain exists!</param>
|
|
|
|
|
/// <param name="writable">if false, writes will be ignored</param>
|
2016-04-13 23:50:06 +00:00
|
|
|
|
[Obsolete]
|
|
|
|
|
public unsafe static MemoryDomain FromIntPtrSwap16(string name, long size, Endian endian, IntPtr data, bool writable = true)
|
2014-09-08 14:50:36 +00:00
|
|
|
|
{
|
2016-04-13 23:50:06 +00:00
|
|
|
|
return new MemoryDomainIntPtrSwap16(name, endian, data, size, writable);
|
2014-09-08 14:50:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2013-11-04 02:11:40 +00:00
|
|
|
|
public override string ToString()
|
|
|
|
|
{
|
|
|
|
|
return Name;
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-13 23:50:06 +00:00
|
|
|
|
public virtual ushort PeekUshort(long addr, bool bigEndian)
|
2013-11-04 02:11:40 +00:00
|
|
|
|
{
|
|
|
|
|
Endian endian = bigEndian ? Endian.Big : Endian.Little;
|
|
|
|
|
switch (endian)
|
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
case Endian.Big:
|
|
|
|
|
return (ushort)((PeekByte(addr) << 8) | (PeekByte(addr + 1)));
|
|
|
|
|
case Endian.Little:
|
|
|
|
|
return (ushort)((PeekByte(addr)) | (PeekByte(addr + 1) << 8));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-13 23:50:06 +00:00
|
|
|
|
public virtual uint PeekUint(long addr, bool bigEndian)
|
2013-11-04 02:11:40 +00:00
|
|
|
|
{
|
|
|
|
|
Endian endian = bigEndian ? Endian.Big : Endian.Little;
|
|
|
|
|
switch (endian)
|
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
case Endian.Big:
|
|
|
|
|
return (uint)((PeekByte(addr) << 24)
|
|
|
|
|
| (PeekByte(addr + 1) << 16)
|
|
|
|
|
| (PeekByte(addr + 2) << 8)
|
|
|
|
|
| (PeekByte(addr + 3) << 0));
|
|
|
|
|
case Endian.Little:
|
|
|
|
|
return (uint)((PeekByte(addr) << 0)
|
|
|
|
|
| (PeekByte(addr + 1) << 8)
|
|
|
|
|
| (PeekByte(addr + 2) << 16)
|
|
|
|
|
| (PeekByte(addr + 3) << 24));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-13 23:50:06 +00:00
|
|
|
|
public virtual void PokeUshort(long addr, ushort val, bool bigEndian)
|
2013-11-04 02:11:40 +00:00
|
|
|
|
{
|
|
|
|
|
Endian endian = bigEndian ? Endian.Big : Endian.Little;
|
|
|
|
|
switch (endian)
|
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
case Endian.Big:
|
|
|
|
|
PokeByte(addr + 0, (byte)(val >> 8));
|
|
|
|
|
PokeByte(addr + 1, (byte)(val));
|
|
|
|
|
break;
|
|
|
|
|
case Endian.Little:
|
|
|
|
|
PokeByte(addr + 0, (byte)(val));
|
|
|
|
|
PokeByte(addr + 1, (byte)(val >> 8));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-13 23:50:06 +00:00
|
|
|
|
public virtual void PokeUint(long addr, uint val, bool bigEndian)
|
2013-11-04 02:11:40 +00:00
|
|
|
|
{
|
|
|
|
|
Endian endian = bigEndian ? Endian.Big : Endian.Little;
|
|
|
|
|
switch (endian)
|
|
|
|
|
{
|
|
|
|
|
default:
|
|
|
|
|
case Endian.Big:
|
|
|
|
|
PokeByte(addr + 0, (byte)(val >> 24));
|
|
|
|
|
PokeByte(addr + 1, (byte)(val >> 16));
|
|
|
|
|
PokeByte(addr + 2, (byte)(val >> 8));
|
|
|
|
|
PokeByte(addr + 3, (byte)(val));
|
|
|
|
|
break;
|
|
|
|
|
case Endian.Little:
|
|
|
|
|
PokeByte(addr + 0, (byte)(val));
|
|
|
|
|
PokeByte(addr + 1, (byte)(val >> 8));
|
|
|
|
|
PokeByte(addr + 2, (byte)(val >> 16));
|
|
|
|
|
PokeByte(addr + 3, (byte)(val >> 24));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|