Advertisement
Ameisen

Untitled

May 13th, 2022
1,075
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 2.77 KB | None | 0 0
  1.     [HarmonizeTranspile(
  2.         type: typeof(XTexture2D),
  3.         "PlatformSetData",
  4.         argumentTypes: new[] { typeof(int), typeof(Array), typeof(int), typeof(int) },
  5.         generic: Generic.Struct,
  6.         platform: Platform.MonoGame
  7.     )]
  8.     public static IEnumerable<CodeInstruction> PlatformSetDataTranspiler<T>(IEnumerable<CodeInstruction> instructions, ILGenerator generator) where T : unmanaged {
  9.         static bool HasParameters(MethodInfo method) {
  10.             var parameters = method.GetParameters().Types();
  11.  
  12.             return
  13.                 parameters.ElementAtOrDefaultF(0) == typeof(XTexture2D) &&
  14.                 parameters.ElementAtOrDefaultF(1) == typeof(int) &&
  15.                 (parameters.ElementAtOrDefaultF(2)?.IsAssignableTo(typeof(Array)) ?? false) &&
  16.                 parameters.ElementAtOrDefaultF(3) == typeof(int) &&
  17.                 parameters.ElementAtOrDefaultF(4) == typeof(int);
  18.         }
  19.  
  20.         var preMethod = typeof(PTexture2D).GetMethods(
  21.             name: "OnPlatformSetDataPre",
  22.             bindingFlags: BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public
  23.         ).FirstF(HasParameters)?.MakeGenericMethod(typeof(T));
  24.  
  25.         if (preMethod is null) {
  26.             Debug.Error("Could not apply PlatformSetData patch: could not find MethodInfo for OnPlatformSetDataPre");
  27.             return instructions;
  28.         }
  29.  
  30.         var postMethod = typeof(PTexture2D).GetMethods(
  31.             name: "OnPlatformSetDataPost",
  32.             bindingFlags: BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public
  33.         ).FirstF(HasParameters)?.MakeGenericMethod(typeof(T));
  34.  
  35.         if (postMethod is null) {
  36.             Debug.Error("Could not apply PlatformSetData patch: could not find MethodInfo for OnPlatformSetDataPost");
  37.             return instructions;
  38.         }
  39.  
  40.         var codeInstructions = instructions as CodeInstruction[] ?? instructions.ToArray();
  41.  
  42.         IEnumerable<CodeInstruction> ApplyPatch() {
  43.             var earlyReturn = generator.DefineLabel();
  44.             var postCall = generator.DefineLabel();
  45.  
  46.             yield return new(OpCodes.Ldarg_0);
  47.             yield return new(OpCodes.Ldarg_1);
  48.             yield return new(OpCodes.Ldarg_2);
  49.             yield return new(OpCodes.Ldarg_3);
  50.             yield return new(OpCodes.Ldarg, 4);
  51.             yield return new(OpCodes.Call, preMethod);
  52.  
  53.             yield return new(OpCodes.Brfalse_S, earlyReturn);
  54.  
  55.  
  56.             foreach (var instruction in codeInstructions) {
  57.                 if (instruction == codeInstructions.LastF()) {
  58.                     yield return new(OpCodes.Ldarg_0) { labels = { postCall } };
  59.                     yield return new(OpCodes.Ldarg_1);
  60.                     yield return new(OpCodes.Ldarg_2);
  61.                     yield return new(OpCodes.Ldarg_3);
  62.                     yield return new(OpCodes.Ldarg, 4);
  63.                     yield return new(OpCodes.Call, postMethod);
  64.  
  65.                     instruction.labels.Add(earlyReturn);
  66.                     yield return instruction;
  67.                 }
  68.                 else if (instruction.opcode.Value == OpCodes.Ret.Value) {
  69.                     yield return new(OpCodes.Jmp, postCall);
  70.                 }
  71.                 else {
  72.                     yield return instruction;
  73.                 }
  74.             }
  75.         }
  76.  
  77.         return ApplyPatch();
  78.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement