diff --git a/src/BizHawk.BizInvoke/BizInvoker.cs b/src/BizHawk.BizInvoke/BizInvoker.cs
index 56ddf19bec..2f1bef0495 100644
--- a/src/BizHawk.BizInvoke/BizInvoker.cs
+++ b/src/BizHawk.BizInvoke/BizInvoker.cs
@@ -86,6 +86,10 @@ namespace BizHawk.BizInvoke
/// How far into a string pointer the first chair is.
///
private static readonly int StringOffset;
+ ///
+ /// How far into a value array type element 0 is.
+ ///
+ private static readonly int ValueArrayElementOffset;
static BizInvoker()
{
@@ -94,6 +98,7 @@ namespace BizHawk.BizInvoke
ImplModuleBuilder = ImplAssemblyBuilder.DefineDynamicModule("BizInvokerModule");
ClassFieldOffset = BizInvokerUtilities.ComputeClassFirstFieldOffset();
StringOffset = BizInvokerUtilities.ComputeStringOffset();
+ ValueArrayElementOffset = BizInvokerUtilities.ComputeValueArrayElementOffset();
}
///
@@ -546,9 +551,10 @@ namespace BizHawk.BizInvoke
il.Emit(OpCodes.Ldarg, (short)idx);
il.Emit(OpCodes.Dup);
il.Emit(OpCodes.Stloc, loc);
- il.Emit(OpCodes.Ldc_I4_0);
- il.Emit(OpCodes.Ldelema, et);
il.Emit(OpCodes.Conv_I);
+ il.Emit(OpCodes.Ldc_I4, ValueArrayElementOffset);
+ il.Emit(OpCodes.Conv_I);
+ il.Emit(OpCodes.Add);
il.Emit(OpCodes.Br, end);
il.MarkLabel(isNull);
diff --git a/src/BizHawk.BizInvoke/BizInvokerUtilities.cs b/src/BizHawk.BizInvoke/BizInvokerUtilities.cs
index e2bd0b02d2..502fab0991 100644
--- a/src/BizHawk.BizInvoke/BizInvokerUtilities.cs
+++ b/src/BizHawk.BizInvoke/BizInvokerUtilities.cs
@@ -71,6 +71,48 @@ namespace BizHawk.BizInvoke
return ret;
}
+ ///
+ /// Compute the offset to the 0th element of an array of value types
+ ///
+ ///
+ public static int ComputeValueArrayElementOffset()
+ {
+ var arr = new int[4];
+ int ret;
+ fixed (int* p = arr)
+ {
+ U u = new(new U2(arr));
+ ret = (int)((ulong)(UIntPtr) p - (ulong) u.First!.P);
+ }
+ return ret;
+ }
+
+ ///
+ /// Compute the offset to the 0th element of an array of object types
+ /// Slow, so cache it if you need it.
+ ///
+ ///
+ public static int ComputeObjectArrayElementOffset()
+ {
+ var obj = new object[4];
+ var method = new DynamicMethod("ComputeObjectArrayElementOffsetHelper", typeof(int), new[] { typeof(object[]) }, typeof(string).Module, true);
+ var il = method.GetILGenerator();
+ var local = il.DeclareLocal(typeof(object[]), true);
+ il.Emit(OpCodes.Ldarg_0);
+ il.Emit(OpCodes.Stloc, local);
+ il.Emit(OpCodes.Ldarg_0);
+ il.Emit(OpCodes.Ldc_I4_0);
+ il.Emit(OpCodes.Ldelema, typeof(object));
+ il.Emit(OpCodes.Conv_I);
+ il.Emit(OpCodes.Ldarg_0);
+ il.Emit(OpCodes.Conv_I);
+ il.Emit(OpCodes.Sub);
+ il.Emit(OpCodes.Conv_I4);
+ il.Emit(OpCodes.Ret);
+ var del = (Func