Skip to content

Commit

Permalink
Hackfix our way around MonoModder BS
Browse files Browse the repository at this point in the history
  • Loading branch information
Popax21 committed Sep 6, 2023
1 parent 06e85f6 commit 3b60666
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 8 deletions.
48 changes: 42 additions & 6 deletions Celeste.Mod.mm/Mod/Helpers/LegacyMonoMod/Misc.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Mono.Cecil;
using Mono.Cecil.Cil;
using MonoMod;
using MonoMod.Cil;
Expand All @@ -24,13 +25,8 @@ public static void Uninitialize() {
}

public static class ILShims {
[RelinkLegacyMonoMod("Mono.Cecil.Cil.Instruction MonoMod.Cil.ILLabel::Target")]
public static Instruction ILLabel_GetTarget(ILLabel label) => label.Target; // This previously used to be a field

[RelinkLegacyMonoMod("System.Int32 MonoMod.Cil.ILCursor::AddReference<T>()")]
//Relinking is done using a MonoModder hackfix because the methods are generic ._.
public static int ILCursor_AddReference<T>(ILCursor cursor, T t) => cursor.AddReference(in t); // Reorg expects an in-argument

[RelinkLegacyMonoMod("System.Int32 MonoMod.Cil.ILCursor::EmitReference<T>()")]
public static int ILCursor_EmitReference<T>(ILCursor cursor, T t) => cursor.EmitReference(in t); // Reorg expects an in-argument
}

Expand Down Expand Up @@ -114,4 +110,44 @@ public static void ReportMonoModCrime(string descr, Assembly perpetrator) {
}

}
}

namespace MonoMod {
partial class MonoModRules {
private static void SetupLegacyMonoModPatcherHackfixes(MonoModder modder) {
// Dear MonoMod.Patcher,
// What the f*ck is this supposed to be!?!?!?
// Sincerely, me :)
// (yes this tells MonoMod to relink ILLabel::Target to ILLabel::Target, and yes this is required)
modder.RelinkMap["Mono.Cecil.Cil.Instruction MonoMod.Cil.ILLabel::Target"] = new RelinkMapEntry("MonoMod.Cil.ILLabel", "Target");

OnPostProcessMethod += static (modder, method) => {
if (!method.HasBody)
return;

// We have to do our own relinking because who the heck would ever want to relink a generic method???????
TypeDefinition ilShimsType = RulesModule.GetType("Celeste.Mod.Helpers.LegacyMonoMod.ILShims");
foreach (Instruction instr in method.Body.Instructions) {
if (!(instr.Operand is MethodReference mref))
continue;

// Check if this is the correct method
if (!mref.HasThis || !(mref.IsGenericInstance || mref.HasGenericParameters) || mref.Parameters.Count != 1)
continue;

if (mref.DeclaringType.FullName != "MonoMod.Cil.ILCursor")
continue;

if (mref.Name != "AddReference" && mref.Name != "EmitReference")
continue;

if (mref.Parameters[0].ParameterType.IsByReference)
continue;

// Relink the reference
instr.Operand = modder.Module.ImportReference(ilShimsType.FindMethod($"ILCursor_{mref.Name}"));
}
};
}
}
}
3 changes: 3 additions & 0 deletions Celeste.Mod.mm/MonoModRules.Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ public static void SetupLegacyMonoModRelinking(MonoModder modder) {
// Replace assembly references which changed
ReplaceAssemblyRefs(modder, static asm => asm.Name.Equals("MonoMod"), GetRulesAssemblyRef("MonoMod.Patcher"));

// Setup MonoMod.Patcher hackfixes (please just let it be rewritten already I have suffered enough ._.)
SetupLegacyMonoModPatcherHackfixes(modder);

// Convert all RelinkLegacyMonoMod attributes to MonoModLinkFrom attributes
foreach (TypeDefinition type in RulesModule.Types)
SetupLegacyMonoModRelinking(modder, type);
Expand Down
10 changes: 8 additions & 2 deletions Celeste.Mod.mm/MonoModRules.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,21 @@ private static void PostProcessType(MonoModder modder, TypeDefinition type) {
if (type.IsCompilerGeneratedEnumerator())
FixEnumeratorDecompile(type);

// Fix short-long opcodes
foreach (MethodDefinition method in type.Methods)
foreach (MethodDefinition method in type.Methods) {
// Run method processors
OnPostProcessMethod?.Invoke(modder, method);

// Fix short-long opcodes
method.FixShortLongOps();
}

// Post-process nested types
foreach (TypeDefinition nested in type.NestedTypes)
PostProcessType(modder, nested);
}

private static event Action<MonoModder, MethodDefinition> OnPostProcessMethod;

#region Commmon Helper Methods
public static AssemblyName GetRulesAssemblyRef(string name) => Assembly.GetExecutingAssembly().GetReferencedAssemblies().First(asm => asm.Name.Equals(name));

Expand Down

0 comments on commit 3b60666

Please sign in to comment.