2020-01-23 00:21:03 +00:00
|
|
|
#nullable disable
|
|
|
|
|
2011-05-20 09:30:20 +00:00
|
|
|
using System;
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
2013-11-04 00:36:15 +00:00
|
|
|
namespace BizHawk.Common
|
2011-05-20 09:30:20 +00:00
|
|
|
{
|
|
|
|
/// <summary>
|
|
|
|
/// Implements a data simple data buffer with proper life cycle and no bounds checking
|
|
|
|
/// </summary>
|
|
|
|
public unsafe class CBuffer<T> : IDisposable
|
|
|
|
{
|
2013-11-28 22:06:38 +00:00
|
|
|
public GCHandle Hnd;
|
|
|
|
public T[] Arr;
|
|
|
|
public void* Ptr;
|
|
|
|
public byte* Byteptr;
|
|
|
|
public int Len;
|
|
|
|
public int Itemsize;
|
2011-05-20 09:30:20 +00:00
|
|
|
|
2019-12-07 02:29:46 +00:00
|
|
|
public void Write08(int addr, byte val) { Byteptr[addr] = val; }
|
|
|
|
public void Write32(int addr, uint val) { *(uint*)(Byteptr + addr) = val; }
|
|
|
|
public byte Read08(int addr) { return Byteptr[addr]; }
|
|
|
|
public ushort Read16(int addr) { return *(ushort*)(Byteptr + addr); }
|
|
|
|
public uint Read32(int addr) { return *(uint*)(Byteptr + addr); }
|
|
|
|
|
2011-06-10 08:10:16 +00:00
|
|
|
public static CBuffer<T> malloc(int amt, int itemsize)
|
2011-05-20 09:30:20 +00:00
|
|
|
{
|
2011-06-10 08:10:16 +00:00
|
|
|
return new CBuffer<T>(amt, itemsize);
|
2011-05-20 09:30:20 +00:00
|
|
|
}
|
|
|
|
|
2011-06-10 08:10:16 +00:00
|
|
|
public CBuffer(T[] arr, int itemsize)
|
2011-05-20 09:30:20 +00:00
|
|
|
{
|
2019-12-07 00:12:57 +00:00
|
|
|
Itemsize = itemsize;
|
|
|
|
Len = arr.Length;
|
|
|
|
Arr = arr;
|
|
|
|
Hnd = GCHandle.Alloc(arr, GCHandleType.Pinned);
|
|
|
|
Ptr = Hnd.AddrOfPinnedObject().ToPointer();
|
|
|
|
Byteptr = (byte*)Ptr;
|
2011-05-20 09:30:20 +00:00
|
|
|
}
|
2011-06-10 08:10:16 +00:00
|
|
|
public CBuffer(int amt, int itemsize)
|
2011-05-20 09:30:20 +00:00
|
|
|
{
|
2019-12-07 00:12:57 +00:00
|
|
|
Itemsize = itemsize;
|
|
|
|
Len = amt;
|
|
|
|
Arr = new T[amt];
|
|
|
|
Hnd = GCHandle.Alloc(this.Arr, GCHandleType.Pinned);
|
|
|
|
Ptr = Hnd.AddrOfPinnedObject().ToPointer();
|
|
|
|
Byteptr = (byte*)Ptr;
|
|
|
|
Util.Memset(Byteptr, 0, Len * itemsize);
|
2011-05-20 09:30:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
{
|
2013-11-15 00:22:08 +00:00
|
|
|
Dispose(true);
|
|
|
|
GC.SuppressFinalize(this);
|
2011-05-20 09:30:20 +00:00
|
|
|
}
|
|
|
|
|
2013-11-15 00:22:08 +00:00
|
|
|
protected virtual void Dispose(bool disposing)
|
|
|
|
{
|
|
|
|
if (disposing)
|
|
|
|
{
|
2019-12-07 00:12:57 +00:00
|
|
|
if (Arr != null)
|
2013-11-15 00:22:08 +00:00
|
|
|
{
|
2019-12-07 00:12:57 +00:00
|
|
|
Hnd.Free();
|
2013-11-15 00:22:08 +00:00
|
|
|
}
|
2019-12-07 00:12:57 +00:00
|
|
|
Arr = null;
|
2013-11-15 00:22:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
~CBuffer() { Dispose(true); }
|
2011-05-20 09:30:20 +00:00
|
|
|
}
|
|
|
|
|
2013-11-15 00:22:08 +00:00
|
|
|
public sealed class ByteBuffer : CBuffer<byte>
|
2011-05-20 09:30:20 +00:00
|
|
|
{
|
2011-06-10 08:10:16 +00:00
|
|
|
public ByteBuffer(int amt) : base(amt,1) { }
|
|
|
|
public ByteBuffer(byte[] arr) : base(arr,1) { }
|
2011-06-08 06:17:41 +00:00
|
|
|
public byte this[int index]
|
|
|
|
{
|
|
|
|
#if DEBUG
|
2020-01-25 04:53:45 +00:00
|
|
|
get => this.Arr[index];
|
|
|
|
set => this.Arr[index] = value;
|
2011-06-08 06:17:41 +00:00
|
|
|
#else
|
2020-01-25 04:53:45 +00:00
|
|
|
set => Write08(index, value);
|
|
|
|
get => Read08(index);
|
2011-06-08 06:17:41 +00:00
|
|
|
#endif
|
|
|
|
}
|
2011-05-20 09:30:20 +00:00
|
|
|
}
|
2011-06-09 19:45:07 +00:00
|
|
|
|
2013-11-15 00:22:08 +00:00
|
|
|
public sealed class IntBuffer : CBuffer<int>
|
2011-06-09 19:45:07 +00:00
|
|
|
{
|
2011-06-10 08:10:16 +00:00
|
|
|
public IntBuffer(int amt) : base(amt, 4) { }
|
|
|
|
public IntBuffer(int[] arr) : base(arr,4) { }
|
2011-06-09 19:45:07 +00:00
|
|
|
public int this[int index]
|
|
|
|
{
|
|
|
|
#if DEBUG
|
2020-01-25 04:53:45 +00:00
|
|
|
get => this.Arr[index];
|
|
|
|
set => this.Arr[index] = value;
|
2011-06-09 19:45:07 +00:00
|
|
|
#else
|
2020-01-25 04:53:45 +00:00
|
|
|
set => Write32(index<<2, (uint) value);
|
|
|
|
get => (int)Read32(index<<2);
|
2011-06-09 19:45:07 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
2012-10-31 01:55:26 +00:00
|
|
|
|
2013-11-15 00:22:08 +00:00
|
|
|
public sealed class ShortBuffer : CBuffer<short>
|
2012-10-31 01:55:26 +00:00
|
|
|
{
|
|
|
|
public ShortBuffer(int amt) : base(amt, 2) { }
|
|
|
|
public ShortBuffer(short[] arr) : base(arr, 2) { }
|
|
|
|
public short this[int index]
|
|
|
|
{
|
|
|
|
#if DEBUG
|
2020-01-25 04:53:45 +00:00
|
|
|
get => this.Arr[index];
|
|
|
|
set => this.Arr[index] = value;
|
2012-10-31 01:55:26 +00:00
|
|
|
#else
|
2020-01-25 04:53:45 +00:00
|
|
|
set => Write32(index << 1, (uint)value);
|
|
|
|
get => (short)Read16(index << 1);
|
2012-10-31 01:55:26 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
2011-05-20 09:30:20 +00:00
|
|
|
}
|