using System; namespace BizHawk.Emulation.Common { /// /// A memory region and the functionality to read/write from it /// as required by the IMemoryDomains service. /// /// public abstract class MemoryDomain { public enum Endian { Big, Little, Unknown } public string Name { get; protected set; } public long Size { get; protected set; } public int WordSize { get; protected set; } public Endian EndianType { get; protected set; } public bool Writable { get; protected set; } public abstract byte PeekByte(long addr); public abstract void PokeByte(long addr, byte val); /// /// creates a memorydomain that references a managed byte array /// /// if false, writes will be ignored [Obsolete] public static MemoryDomain FromByteArray(string name, Endian endian, byte[] data, bool writable = true, int wordSize = 1) { return new MemoryDomainByteArray(name, endian, data, writable, wordSize); } /// /// create a memorydomain that references an unmanaged memory block /// /// must remain valid as long as the MemoryDomain exists! /// if false, writes will be ignored [Obsolete] public unsafe static MemoryDomain FromIntPtr(string name, long size, Endian endian, IntPtr data, bool writable = true, int wordSize = 1) { return new MemoryDomainIntPtr(name, endian, data, size, writable, wordSize); } /// /// create a memorydomain that references an unmanaged memory block with 16 bit swaps /// /// must remain valid as long as the MemoryDomain exists! /// if false, writes will be ignored [Obsolete] public unsafe static MemoryDomain FromIntPtrSwap16(string name, long size, Endian endian, IntPtr data, bool writable = true) { return new MemoryDomainIntPtrSwap16(name, endian, data, size, writable); } public override string ToString() { return Name; } public virtual ushort PeekUshort(long addr, bool bigEndian) { 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)); } } public virtual uint PeekUint(long addr, bool bigEndian) { 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)); } } public virtual void PokeUshort(long addr, ushort val, bool bigEndian) { 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; } } public virtual void PokeUint(long addr, uint val, bool bigEndian) { 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; } } } }