public void ApplyCommonChanges(ModuleDefinition mod, string tag = "Relink") { if (DestroyPublicKeyTokens.Contains(mod.Assembly.Name.Name)) { Log($"[{tag}] Destroying public key token for module {mod.Assembly.Name.Name}"); mod.Assembly.Name.PublicKeyToken = new byte[0]; } Log($"[{tag}] Updating dependencies"); for (int i = 0; i < mod.AssemblyReferences.Count; i++) { AssemblyNameReference dep = mod.AssemblyReferences[i]; // Main mapping mass. foreach (XnaToFnaMapping mapping in Mappings) { if (mapping.Sources.Contains(dep.Name) && // Check if the target module has been found and cached Modder.DependencyCache.ContainsKey(mapping.Target)) { // Check if module already depends on the remap if (mod.AssemblyReferences.Any(existingDep => existingDep.Name == mapping.Target)) { // If so, just remove the dependency. mod.AssemblyReferences.RemoveAt(i); i--; goto NextDep; } Log($"[{tag}] Replacing dependency {dep.Name} -> {mapping.Target}"); // Replace the dependency. mod.AssemblyReferences[i] = Modder.DependencyCache[mapping.Target].Assembly.Name; // Only check until first match found. goto NextDep; } } // Didn't remap; Check for RemoveDeps if (RemoveDeps.Contains(dep.Name)) { // Remove any unwanted (f.e. mixed) dependencies. Log($"[{tag}] Removing unwanted dependency {dep.Name}"); mod.AssemblyReferences.RemoveAt(i); i--; goto NextDep; } // Didn't remove // Check for DestroyPublicKeyTokens if (DestroyPublicKeyTokens.Contains(dep.Name)) { Log($"[{tag}] Destroying public key token for dependency {dep.Name}"); dep.PublicKeyToken = new byte[0]; } // Check for ModulesToStub (formerly managed references) if (ModulesToStub.Any(stub => stub.Assembly.Name.Name == dep.Name)) { // Fix stubbed dependencies. Log($"[{tag}] Fixing stubbed dependency {dep.Name}"); dep.IsWindowsRuntime = false; dep.HasPublicKey = false; } // Check for .NET compact (X360) version if (dep.Version == DotNetX360Version) { // Replace public key token. dep.PublicKeyToken = DotNetFrameworkKeyToken; // Technically .NET 2(?), but let's just bump the version. dep.Version = DotNetFramework4Version; } NextDep: continue; } if (AddAssemblyReference && !mod.AssemblyReferences.Any(dep => dep.Name == ThisAssemblyName)) { // Add XnaToFna as dependency Log($"[{tag}] Adding dependency XnaToFna"); mod.AssemblyReferences.Add(Modder.DependencyCache[ThisAssemblyName].Assembly.Name); } if (mod.Runtime < TargetRuntime.Net_4_0) { // XNA 3.0 / 3.1 and X360 games depend on a .NET Framework pre-4.0 mod.Runtime = TargetRuntime.Net_4_0; // TODO: What about the System.*.dll dependencies? } Log($"[{tag}] Updating module attributes"); mod.Attributes &= ~ModuleAttributes.StrongNameSigned; if (PreferredPlatform != ILPlatform.Keep) { // "Clear" to AnyCPU. mod.Architecture = TargetArchitecture.I386; mod.Attributes &= ~ModuleAttributes.Required32Bit & ~ModuleAttributes.Preferred32Bit; switch (PreferredPlatform) { case ILPlatform.x86: mod.Architecture = TargetArchitecture.I386; mod.Attributes |= ModuleAttributes.Required32Bit; break; case ILPlatform.x64: mod.Architecture = TargetArchitecture.AMD64; break; case ILPlatform.x86Pref: mod.Architecture = TargetArchitecture.I386; mod.Attributes |= ModuleAttributes.Preferred32Bit; break; } } bool mixed = (mod.Attributes & ModuleAttributes.ILOnly) != ModuleAttributes.ILOnly; if (ModulesToStub.Count != 0 || mixed) { Log($"[{tag}] Making assembly unsafe"); mod.Attributes |= ModuleAttributes.ILOnly; for (int i = 0; i < mod.Assembly.CustomAttributes.Count; i++) { CustomAttribute attrib = mod.Assembly.CustomAttributes[i]; if (attrib.AttributeType.FullName == "System.CLSCompliantAttribute") { mod.Assembly.CustomAttributes.RemoveAt(i); i--; } } if (!mod.CustomAttributes.Any(ca => ca.AttributeType.FullName == "System.Security.UnverifiableCodeAttribute")) { mod.AddAttribute(mod.ImportReference(m_UnverifiableCodeAttribute_ctor)); } } // MonoMod needs to relink some types (f.e. XnaToFnaHelper) via FindType, which requires a dependency map. Log($"[{tag}] Mapping dependencies for MonoMod"); Modder.MapDependencies(mod); }