forked from TASEmulators/BizHawk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBuffer.cs
128 lines (118 loc) · 3.76 KB
/
Buffer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
using System;
using System.Runtime.InteropServices;
namespace BizHawk.Common
{
/// <summary>
/// Implements a data simple data buffer with proper life cycle and no bounds checking
/// </summary>
public unsafe class CBuffer<T> : IDisposable
{
public GCHandle Hnd;
public T[] Arr;
public void* Ptr;
public byte* Byteptr;
public int Len;
public int Itemsize;
public static CBuffer<T> malloc(int amt, int itemsize)
{
return new CBuffer<T>(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<byte>
{
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<int>
{
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<short>
{
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
}
}
}