/// <summary> /// Primitive patching. Inserts a jump to 'target' at 'site'. Works even if both methods' /// callers have already been compiled. /// </summary> /// <param name="site"></param> /// <param name="target"></param> public static RedirectCallsState PatchJumpTo(IntPtr site, IntPtr target) { var state = new RedirectCallsState(); // R11 is volatile. unsafe { var sitePtr = (byte*)site.ToPointer(); state.a = *sitePtr; state.b = *(sitePtr + 1); state.c = *(sitePtr + 10); state.d = *(sitePtr + 11); state.e = *(sitePtr + 12); state.f = *((ulong*)(sitePtr + 2)); *sitePtr = 0x49; // mov r11, target *(sitePtr + 1) = 0xBB; *((ulong*)(sitePtr + 2)) = (ulong)target.ToInt64(); *(sitePtr + 10) = 0x41; // jmp r11 *(sitePtr + 11) = 0xFF; *(sitePtr + 12) = 0xE3; } return state; }
public static void Deploy() { if (!deployed) { // Called when placing/removing roads // one of these also affects the combined LOD mesh // NetLane.CalculateGroupData // NetLane.PopulateGroupData // NetLane.RereshInstance - init/render // Called when rendering detailed net // NetLane.RenderInstance - render _NetLane_RefreshInstance_original = typeof(NetLane).GetMethod("RefreshInstance", BindingFlags.Instance | BindingFlags.Public); _NetLane_RefreshInstance_detour = typeof(NetLaneDetour).GetMethod("RefreshInstance", BindingFlags.Instance | BindingFlags.Public); _NetLane_RefreshInstance_state = RedirectionHelper.RedirectCalls(_NetLane_RefreshInstance_original, _NetLane_RefreshInstance_detour); _NetLane_RenderInstance_original = typeof(NetLane).GetMethod("RenderInstance", BindingFlags.Instance | BindingFlags.Public); _NetLane_RenderInstance_detour = typeof(NetLaneDetour).GetMethod("RenderInstance", BindingFlags.Instance | BindingFlags.Public); _NetLane_RenderInstance_state = RedirectionHelper.RedirectCalls(_NetLane_RenderInstance_original, _NetLane_RenderInstance_detour); _NetLane_CalculateGroupData_original = typeof(NetLane).GetMethod("CalculateGroupData", BindingFlags.Instance | BindingFlags.Public); _NetLane_CalculateGroupData_detour = typeof(NetLaneDetour).GetMethod("CalculateGroupData", BindingFlags.Instance | BindingFlags.Public); _NetLane_CalculateGroupData_state = RedirectionHelper.RedirectCalls(_NetLane_CalculateGroupData_original, _NetLane_CalculateGroupData_detour); _NetLane_PopulateGroupData_original = typeof(NetLane).GetMethod("PopulateGroupData", BindingFlags.Instance | BindingFlags.Public); _NetLane_PopulateGroupData_detour = typeof(NetLaneDetour).GetMethod("PopulateGroupData", BindingFlags.Instance | BindingFlags.Public); _NetLane_PopulateGroupData_state = RedirectionHelper.RedirectCalls(_NetLane_PopulateGroupData_original, _NetLane_PopulateGroupData_detour); deployed = true; } }
public static void Deploy() { if (deployed) return; _RenderManager_UpdateData_original = typeof(RenderManager).GetMethod("UpdateData", BindingFlags.Instance | BindingFlags.Public); _RenderManager_UpdateData_detour = typeof(RenderManagerDetour).GetMethod("UpdateData", BindingFlags.Instance | BindingFlags.Public); _RenderManager_UpdateData_state = RedirectionHelper.RedirectCalls(_RenderManager_UpdateData_original, _RenderManager_UpdateData_detour); deployed = true; }
public static void Deploy() { if (!deployed) { _NetLane_RenderInstance_original = typeof(NetSegment).GetMethod("RenderInstance", BindingFlags.Instance | BindingFlags.NonPublic); _NetLane_RenderInstance_detour = typeof(NetSegmentDetour).GetMethod("RenderInstance", BindingFlags.Instance | BindingFlags.NonPublic); _NetLane_RenderInstance_state = RedirectionHelper.RedirectCalls(_NetLane_RenderInstance_original, _NetLane_RenderInstance_detour); deployed = true; } }
public static void Deploy() { if (deployed) return; _NetManager_CreateSegment_original = typeof(NetManager).GetMethod("CreateSegment", BindingFlags.Instance | BindingFlags.Public); _NetManager_CreateSegment_detour = typeof(NetManagerDetour).GetMethod("CreateSegment", BindingFlags.Instance | BindingFlags.Public); _NetManager_CreateSegment_state = RedirectionHelper.RedirectCalls(_NetManager_CreateSegment_original, _NetManager_CreateSegment_detour); _NetManager_ReleaseSegment_original = typeof(NetManager).GetMethod("ReleaseSegment", BindingFlags.Instance | BindingFlags.Public); _NetManager_ReleaseSegment_detour = typeof(NetManagerDetour).GetMethod("ReleaseSegment", BindingFlags.Instance | BindingFlags.Public); _NetManager_ReleaseSegment_state = RedirectionHelper.RedirectCalls(_NetManager_ReleaseSegment_original, _NetManager_ReleaseSegment_detour); deployed = true; }
public static void RevertRedirect(MethodInfo from, RedirectCallsState state) { var fptr1 = from.MethodHandle.GetFunctionPointer(); RevertJumpTo(fptr1, state); }
public static void RevertJumpTo(IntPtr site, RedirectCallsState state) { unsafe { var sitePtr = (byte*)site.ToPointer(); *sitePtr = state.a; // mov r11, target *(sitePtr + 1) = state.b; *((ulong*)(sitePtr + 2)) = state.f; *(sitePtr + 10) = state.c; // jmp r11 *(sitePtr + 11) = state.d; *(sitePtr + 12) = state.e; } }