From ec5fbb06113b29342e6d4b213144f4dc3e358b03 Mon Sep 17 00:00:00 2001 From: Chase Warrington Date: Sun, 29 Aug 2021 15:48:28 -0400 Subject: [PATCH] Rewrite 32-bit assemblies for 64-bit --- .../Framework/ModLoading/AssemblyLoader.cs | 7 ++++ .../Framework/BaseInstructionHandler.cs | 6 ++++ .../ModLoading/Framework/RecursiveRewriter.cs | 13 ++++++- .../ModLoading/IInstructionHandler.cs | 5 +++ .../Rewriters/ArchitectureAssemblyRewriter.cs | 34 +++++++++++++++++++ src/SMAPI/Metadata/InstructionMetadata.cs | 3 ++ 6 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/SMAPI/Framework/ModLoading/Rewriters/ArchitectureAssemblyRewriter.cs diff --git a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs index 3e35c9dd..ae42909c 100644 --- a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs +++ b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs @@ -336,6 +336,13 @@ namespace StardewModdingAPI.Framework.ModLoading IInstructionHandler[] handlers = new InstructionMetadata().GetHandlers(this.ParanoidMode, platformChanged, this.RewriteMods).ToArray(); RecursiveRewriter rewriter = new RecursiveRewriter( module: module, + rewriteModule: (module) => + { + bool rewritten = false; + foreach (IInstructionHandler handler in handlers) + rewritten |= handler.Handle(module); + return rewritten; + }, rewriteType: (type, replaceWith) => { bool rewritten = false; diff --git a/src/SMAPI/Framework/ModLoading/Framework/BaseInstructionHandler.cs b/src/SMAPI/Framework/ModLoading/Framework/BaseInstructionHandler.cs index 624113b3..d5d1b38e 100644 --- a/src/SMAPI/Framework/ModLoading/Framework/BaseInstructionHandler.cs +++ b/src/SMAPI/Framework/ModLoading/Framework/BaseInstructionHandler.cs @@ -24,6 +24,12 @@ namespace StardewModdingAPI.Framework.ModLoading.Framework /********* ** Public methods *********/ + /// + public virtual bool Handle(ModuleDefinition module) + { + return false; + } + /// public virtual bool Handle(ModuleDefinition module, TypeReference type, Action replaceWith) { diff --git a/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs b/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs index 10f68f0d..52f4003c 100644 --- a/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs +++ b/src/SMAPI/Framework/ModLoading/Framework/RecursiveRewriter.cs @@ -13,6 +13,11 @@ namespace StardewModdingAPI.Framework.ModLoading.Framework /********* ** Delegates *********/ + /// Rewrite a module definition in the assembly code. + /// The current module definition. + /// Returns whether the module was changed. + public delegate bool RewriteModuleDelegate(ModuleDefinition module); + /// Rewrite a type reference in the assembly code. /// The current type reference. /// Replaces the type reference with the given type. @@ -32,6 +37,9 @@ namespace StardewModdingAPI.Framework.ModLoading.Framework /// The module to rewrite. public ModuleDefinition Module { get; } + /// Handle or rewrite a type reference if needed. + public RewriteModuleDelegate RewriteModuleImpl { get; } + /// Handle or rewrite a type reference if needed. public RewriteTypeDelegate RewriteTypeImpl { get; } @@ -46,9 +54,10 @@ namespace StardewModdingAPI.Framework.ModLoading.Framework /// The module to rewrite. /// Handle or rewrite a type reference if needed. /// Handle or rewrite a CIL instruction if needed. - public RecursiveRewriter(ModuleDefinition module, RewriteTypeDelegate rewriteType, RewriteInstructionDelegate rewriteInstruction) + public RecursiveRewriter(ModuleDefinition module, RewriteModuleDelegate rewriteModule, RewriteTypeDelegate rewriteType, RewriteInstructionDelegate rewriteInstruction) { this.Module = module; + this.RewriteModuleImpl = rewriteModule; this.RewriteTypeImpl = rewriteType; this.RewriteInstructionImpl = rewriteInstruction; } @@ -63,6 +72,8 @@ namespace StardewModdingAPI.Framework.ModLoading.Framework try { + changed |= this.RewriteModuleImpl( this.Module ); + foreach (var type in types) changed |= this.RewriteTypeDefinition(type); } diff --git a/src/SMAPI/Framework/ModLoading/IInstructionHandler.cs b/src/SMAPI/Framework/ModLoading/IInstructionHandler.cs index 17c9ba68..d41732f8 100644 --- a/src/SMAPI/Framework/ModLoading/IInstructionHandler.cs +++ b/src/SMAPI/Framework/ModLoading/IInstructionHandler.cs @@ -24,6 +24,11 @@ namespace StardewModdingAPI.Framework.ModLoading /********* ** Methods *********/ + /// Rewrite a module definition if needed. + /// The assembly module. + /// Returns whether the module was changed. + bool Handle(ModuleDefinition module); + /// Rewrite a type reference if needed. /// The assembly module containing the instruction. /// The type definition to handle. diff --git a/src/SMAPI/Framework/ModLoading/Rewriters/ArchitectureAssemblyRewriter.cs b/src/SMAPI/Framework/ModLoading/Rewriters/ArchitectureAssemblyRewriter.cs new file mode 100644 index 00000000..216c042a --- /dev/null +++ b/src/SMAPI/Framework/ModLoading/Rewriters/ArchitectureAssemblyRewriter.cs @@ -0,0 +1,34 @@ +using System; +using HarmonyLib; +using Mono.Cecil; +using Mono.Cecil.Cil; +using StardewModdingAPI.Framework.ModLoading.Framework; +using StardewModdingAPI.Framework.ModLoading.RewriteFacades; + +namespace StardewModdingAPI.Framework.ModLoading.Rewriters +{ + /// Rewrites Harmony 1.x assembly references to work with Harmony 2.x. + internal class ArchitectureAssemblyRewriter : BaseInstructionHandler + { + /********* + ** Public methods + *********/ + /// Construct an instance. + public ArchitectureAssemblyRewriter() + : base(defaultPhrase: "32-bit architecture") { } + + + /// + public override bool Handle( ModuleDefinition module ) + { + if ( module.Attributes.HasFlag( ModuleAttributes.Required32Bit ) ) + { + module.Attributes = module.Attributes & ~ModuleAttributes.Required32Bit; + this.MarkRewritten(); + return true; + } + return false; + } + + } +} diff --git a/src/SMAPI/Metadata/InstructionMetadata.cs b/src/SMAPI/Metadata/InstructionMetadata.cs index a787993a..54e46ed3 100644 --- a/src/SMAPI/Metadata/InstructionMetadata.cs +++ b/src/SMAPI/Metadata/InstructionMetadata.cs @@ -50,6 +50,9 @@ namespace StardewModdingAPI.Metadata // rewrite for SMAPI 3.12 (Harmony 1.x => 2.0 update) yield return new Harmony1AssemblyRewriter(); + + // rewrite for 64-bit mode + yield return new ArchitectureAssemblyRewriter(); } /****