using System; using System.Runtime.InteropServices; namespace BizHawk.Common { /// /// Implements a data simple data buffer with proper life cycle and no bounds checking /// public unsafe class CBuffer : IDisposable { public GCHandle Hnd; public T[] Arr; public void* Ptr; public byte* Byteptr; public int Len; public int Itemsize; public static CBuffer malloc(int amt, int itemsize) { return new CBuffer(amt, itemsize); } public void Write08(uint addr, byte val) { this.Byteptr[addr] = val; } public void Write16(uint addr, ushort val) { *(ushort*)(this.Byteptr + addr) = val; } public void Write32(uint addr, uint val) { *(uint*)(this.Byteptr + addr) = val; } public void Write64(uint addr, ulong val) { *(ulong*)(this.Byteptr + addr) = val; } public byte Read08(uint addr) { return this.Byteptr[addr]; } public ushort Read16(uint addr) { return *(ushort*)(this.Byteptr + addr); } public uint Read32(uint addr) { return *(uint*)(this.Byteptr + addr); } public ulong Read64(uint addr) { return *(ulong*)(this.Byteptr + addr); } public void Write08(int addr, byte val) { this.Byteptr[addr] = val; } public void Write16(int addr, ushort val) { *(ushort*)(this.Byteptr + addr) = val; } public void Write32(int addr, uint val) { *(uint*)(this.Byteptr + addr) = val; } public void Write64(int addr, ulong val) { *(ulong*)(this.Byteptr + addr) = val; } public byte Read08(int addr) { return this.Byteptr[addr]; } public ushort Read16(int addr) { return *(ushort*)(this.Byteptr + addr); } public uint Read32(int addr) { return *(uint*)(this.Byteptr + addr); } public ulong Read64(int addr) { return *(ulong*)(this.Byteptr + addr); } public CBuffer(T[] arr, int itemsize) { this.Itemsize = itemsize; this.Len = arr.Length; this.Arr = arr; this.Hnd = GCHandle.Alloc(arr, GCHandleType.Pinned); this.Ptr = this.Hnd.AddrOfPinnedObject().ToPointer(); this.Byteptr = (byte*)this.Ptr; } public CBuffer(int amt, int itemsize) { this.Itemsize = itemsize; this.Len = amt; this.Arr = new T[amt]; this.Hnd = GCHandle.Alloc(this.Arr, GCHandleType.Pinned); this.Ptr = this.Hnd.AddrOfPinnedObject().ToPointer(); this.Byteptr = (byte*)this.Ptr; Util.Memset(this.Byteptr, 0, this.Len * itemsize); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (disposing) { if (this.Arr != null) { this.Hnd.Free(); } this.Arr = null; } } ~CBuffer() { Dispose(true); } } public sealed class ByteBuffer : CBuffer { public ByteBuffer(int amt) : base(amt,1) { } public ByteBuffer(byte[] arr) : base(arr,1) { } public byte this[int index] { #if DEBUG get { return this.Arr[index]; } set { this.Arr[index] = value; } #else set { Write08(index, value); } get { return Read08(index);} #endif } } public sealed class IntBuffer : CBuffer { public IntBuffer(int amt) : base(amt, 4) { } public IntBuffer(int[] arr) : base(arr,4) { } public int this[int index] { #if DEBUG get { return this.Arr[index]; } set { this.Arr[index] = value; } #else set { Write32(index<<2, (uint) value); } get { return (int)Read32(index<<2);} #endif } } public sealed class ShortBuffer : CBuffer { public ShortBuffer(int amt) : base(amt, 2) { } public ShortBuffer(short[] arr) : base(arr, 2) { } public short this[int index] { #if DEBUG get { return this.Arr[index]; } set { this.Arr[index] = value; } #else set { Write32(index << 1, (uint)value); } get { return (short)Read16(index << 1); } #endif } } }