GBA.Unity/Assets/emulator/MemoryUtil.cs

180 lines
5.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Collections.Concurrent;
using static OptimeGBA.Bits;
using System.Runtime.InteropServices;
namespace OptimeGBA
{
public static unsafe class MemoryUtil
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong GetUlong(byte[] arr, uint addr)
{
return
((ulong)arr[addr + 0] << 0) |
((ulong)arr[addr + 1] << 8) |
((ulong)arr[addr + 2] << 16) |
((ulong)arr[addr + 3] << 24) |
((ulong)arr[addr + 4] << 32) |
((ulong)arr[addr + 5] << 40) |
((ulong)arr[addr + 6] << 48) |
((ulong)arr[addr + 7] << 56);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint GetUint(byte[] arr, uint addr)
{
return (uint)(
(arr[addr + 0] << 0) |
(arr[addr + 1] << 8) |
(arr[addr + 2] << 16) |
(arr[addr + 3] << 24)
);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ushort GetUshort(byte[] arr, uint addr)
{
return (ushort)(
(arr[addr + 0] << 0) |
(arr[addr + 1] << 8)
);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte GetByte(byte[] arr, uint addr)
{
return arr[addr];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong GetUlong(byte* arr, uint addr)
{
return *(ulong*)(arr + addr);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint GetUint(byte* arr, uint addr)
{
return *(uint*)(arr + addr);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ushort GetUshort(byte* arr, uint addr)
{
return *(ushort*)(arr + addr);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte GetByte(byte* arr, uint addr)
{
return *(byte*)(arr + addr);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetUlong(byte[] arr, uint addr, ulong val)
{
arr[addr + 0] = (byte)(val >> 0);
arr[addr + 1] = (byte)(val >> 8);
arr[addr + 2] = (byte)(val >> 16);
arr[addr + 3] = (byte)(val >> 24);
arr[addr + 4] = (byte)(val >> 32);
arr[addr + 5] = (byte)(val >> 40);
arr[addr + 6] = (byte)(val >> 48);
arr[addr + 7] = (byte)(val >> 56);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetUint(byte[] arr, uint addr, uint val)
{
arr[addr + 0] = (byte)(val >> 0);
arr[addr + 1] = (byte)(val >> 8);
arr[addr + 2] = (byte)(val >> 16);
arr[addr + 3] = (byte)(val >> 24);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetUshort(byte[] arr, uint addr, ushort val)
{
arr[addr + 0] = (byte)(val >> 0);
arr[addr + 1] = (byte)(val >> 8);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetByte(byte[] arr, uint addr, byte val)
{
arr[addr] = val;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetUlong(byte* arr, uint addr, ulong val)
{
*(ulong*)(arr + addr) = val;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetUint(byte* arr, uint addr, uint val)
{
*(uint*)(arr + addr) = val;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetUshort(byte* arr, uint addr, ushort val)
{
*(ushort*)(arr + addr) = val;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SetByte(byte* arr, uint addr, byte val)
{
*(byte*)(arr + addr) = val;
}
public static byte* AllocateUnmanagedArray(int size)
{
byte* arr = (byte*)Marshal.AllocHGlobal(size).ToPointer();
// Zero out array
for (int i = 0; i < size; i++)
{
arr[i] = 0;
}
return arr;
}
public static ushort* AllocateUnmanagedArray16(int size)
{
ushort* arr = (ushort*)Marshal.AllocHGlobal(size * sizeof(ushort)).ToPointer();
// Zero out array
for (int i = 0; i < size; i++)
{
arr[i] = 0;
}
return arr;
}
public static uint* AllocateUnmanagedArray32(int size)
{
uint* arr = (uint*)Marshal.AllocHGlobal(size * sizeof(uint)).ToPointer();
// Zero out array
for (int i = 0; i < size; i++)
{
arr[i] = 0;
}
return arr;
}
public static void FreeUnmanagedArray(void* arr)
{
Marshal.FreeHGlobal(new IntPtr(arr));
}
}
}