-
Notifications
You must be signed in to change notification settings - Fork 59
Description
Unity Version: 2022.3.28f1 (IL2CPP)
BepInEx Version: Both 6.0.0-be.733 and 6.0.0-pre.2
Game : Suikoden I&II HD Remaster
Using the simple following code :
[HarmonyPatch(typeof(EVENTCON), nameof(EVENTCON.EventAtariCheckFunc1))]
[HarmonyPostfix]
static void CheckAtari(ref RECT rec)
{
Plugin.Log.LogWarning($"x={rec.x} y={rec.y} w={rec.w} h={rec.h}");
}
Or even with the simpler code :
[HarmonyPatch(typeof(EVENTCON), nameof(EVENTCON.EventAtariCheckFunc1))]
[HarmonyPrefix]
static void CheckAtari()
{
}
To patch this function :
private void EventAtariCheckFunc1(int pno, int dir, ref RECT rec)
It results in the "ref RECT rec" always returning a rec with zeroed data. I had to check with a debugger (x96dbg).
In the console I get this info with the patch :
x=512 y=768 w=0 h=0
The assembly code at the call site for EventAtariCheckFunc1 :
Result without the patch :
As you can see the data for the rec which is on the stack, is not zeroed at the address pointed by the R9 register. 0x300 (=768) corresponds to the y value of rec and 0x200 (=512) corresponds to the x value of the rec.
Result with the patch :
Now the data for rec is zeroed !!! The hook displayed the data of rec properly, so its data is lost at some point after the Postfix.
Decompiled RECT:
[StructLayout(LayoutKind.Explicit)]
public struct RECT
{
private static readonly System.IntPtr NativeFieldInfoPtr_x;
private static readonly System.IntPtr NativeFieldInfoPtr_y;
private static readonly System.IntPtr NativeFieldInfoPtr_w;
private static readonly System.IntPtr NativeFieldInfoPtr_h;
private static readonly System.IntPtr NativeMethodInfoPtr__ctor_Public_Void_Int32_Int32_Int32_Int32_0;
[FieldOffset(0)]
public int x;
[FieldOffset(4)]
public int y;
[FieldOffset(8)]
public int w;
[FieldOffset(12)]
public int h;
[CallerCount(28)]
[CachedScanResults(RefRangeStart = 739593, RefRangeEnd = 739621, XrefRangeStart = 739593, XrefRangeEnd = 739593, MetadataInitTokenRva = 0L, MetadataInitFlagRva = 0L)]
public unsafe RECT([DefaultParameterValue(null)] int _x, [DefaultParameterValue(null)] int _y, [DefaultParameterValue(null)] int _w, [DefaultParameterValue(null)] int _h)
{
System.IntPtr* ptr = stackalloc System.IntPtr[4];
*ptr = (nint)(&_x);
*(int**)((byte*)ptr + checked((nuint)1u * unchecked((nuint)sizeof(System.IntPtr)))) = &_y;
*(int**)((byte*)ptr + checked((nuint)2u * unchecked((nuint)sizeof(System.IntPtr)))) = &_w;
*(int**)((byte*)ptr + checked((nuint)3u * unchecked((nuint)sizeof(System.IntPtr)))) = &_h;
System.Runtime.CompilerServices.Unsafe.SkipInit(out System.IntPtr exc);
System.IntPtr intPtr = IL2CPP.il2cpp_runtime_invoke(NativeMethodInfoPtr__ctor_Public_Void_Int32_Int32_Int32_Int32_0, (nint)System.Runtime.CompilerServices.Unsafe.AsPointer(ref this), (void**)ptr, ref exc);
Il2CppException.RaiseExceptionIfNecessary(exc);
}
static RECT()
{
Il2CppClassPointerStore<RECT>.NativeClassPtr = IL2CPP.GetIl2CppClass("GSDShare.dll", "", "RECT");
IL2CPP.il2cpp_runtime_class_init(Il2CppClassPointerStore<RECT>.NativeClassPtr);
NativeFieldInfoPtr_x = IL2CPP.GetIl2CppField(Il2CppClassPointerStore<RECT>.NativeClassPtr, "x");
NativeFieldInfoPtr_y = IL2CPP.GetIl2CppField(Il2CppClassPointerStore<RECT>.NativeClassPtr, "y");
NativeFieldInfoPtr_w = IL2CPP.GetIl2CppField(Il2CppClassPointerStore<RECT>.NativeClassPtr, "w");
NativeFieldInfoPtr_h = IL2CPP.GetIl2CppField(Il2CppClassPointerStore<RECT>.NativeClassPtr, "h");
NativeMethodInfoPtr__ctor_Public_Void_Int32_Int32_Int32_Int32_0 = IL2CPP.GetIl2CppMethodByToken(Il2CppClassPointerStore<RECT>.NativeClassPtr, 100663932);
}
public unsafe Il2CppSystem.Object BoxIl2CppObject()
{
return new Il2CppSystem.Object(IL2CPP.il2cpp_value_box(Il2CppClassPointerStore<RECT>.NativeClassPtr, (nint)System.Runtime.CompilerServices.Unsafe.AsPointer(ref this)));
}
}
Decompiled EVENTCON :
[CallerCount(17)]
[CachedScanResults(RefRangeStart = 105008, RefRangeEnd = 105025, XrefRangeStart = 104988, XrefRangeEnd = 105008, MetadataInitTokenRva = 0L, MetadataInitFlagRva = 0L)]
public unsafe void EventAtariCheckFunc1([DefaultParameterValue(null)] int pno, [DefaultParameterValue(null)] int dir, [DefaultParameterValue(null)] ref RECT rec)
{
IL2CPP.Il2CppObjectBaseToPtrNotNull(this);
System.IntPtr* ptr = stackalloc System.IntPtr[3];
*ptr = (nint)(&pno);
*(int**)((byte*)ptr + checked((nuint)1u * unchecked((nuint)sizeof(System.IntPtr)))) = &dir;
*(void**)((byte*)ptr + checked((nuint)2u * unchecked((nuint)sizeof(System.IntPtr)))) = System.Runtime.CompilerServices.Unsafe.AsPointer(ref rec);
System.Runtime.CompilerServices.Unsafe.SkipInit(out System.IntPtr exc);
System.IntPtr intPtr = IL2CPP.il2cpp_runtime_invoke(NativeMethodInfoPtr_EventAtariCheckFunc1_Private_Void_Int32_Int32_byref_RECT_0, IL2CPP.Il2CppObjectBaseToPtrNotNull(this), (void**)ptr, ref exc);
Il2CppInterop.Runtime.Il2CppException.RaiseExceptionIfNecessary(exc);
}




