Exemple #1
0
        public XnaToFnaUtil()
        {
            Modder             = new XnaToFnaModder(this);
            Modder.ReadingMode = ReadingMode.Immediate;

            Modder.Strict = false;

            Modder.AssemblyResolver = AssemblyResolver;
            Modder.DependencyDirs   = Directories;

            Modder.MissingDependencyResolver = MissingDependencyResolver;

            using (FileStream xtfStream = new FileStream(Assembly.GetExecutingAssembly().Location, FileMode.Open, FileAccess.Read))
                ThisModule = MonoModExt.ReadModule(xtfStream, new ReaderParameters(ReadingMode.Immediate));
            Modder.DependencyCache[ThisModule.Assembly.Name.Name]     = ThisModule;
            Modder.DependencyCache[ThisModule.Assembly.Name.FullName] = ThisModule;
        }
Exemple #2
0
 public static bool Is(this MemberReference member, MemberInfo other)
 => MonoModExt.Is(member, other);
Exemple #3
0
        public void ScanPath(string path)
        {
            if (Directory.Exists(path))
            {
                // Use the directory as "dependency directory" and scan in it.
                if (Directories.Contains(path))
                {
                    // No need to scan the dir if the dir is scanned...
                    return;
                }

                RestoreBackup(path);

                Log($"[ScanPath] Scanning directory {path}");
                Directories.Add(path);
                AssemblyResolver.AddSearchDirectory(path); // Needs to be added manually as DependencyDirs was already added

                // Most probably the actual game directory - let's just copy XnaToFna.exe to there to be referenced properly.
                string xtfPath = Path.Combine(path, Path.GetFileName(ThisAssembly.Location));
                if (Path.GetDirectoryName(ThisAssembly.Location) != path)
                {
                    Log($"[ScanPath] Found separate game directory - copying XnaToFna.exe and FNA.dll");
                    File.Copy(ThisAssembly.Location, xtfPath, true);

                    string dbExt = null;
                    if (File.Exists(Path.ChangeExtension(ThisAssembly.Location, "pdb")))
                    {
                        dbExt = "pdb";
                    }
                    if (File.Exists(Path.ChangeExtension(ThisAssembly.Location, "mdb")))
                    {
                        dbExt = "mdb";
                    }
                    if (dbExt != null)
                    {
                        File.Copy(Path.ChangeExtension(ThisAssembly.Location, dbExt), Path.ChangeExtension(xtfPath, dbExt), true);
                    }

                    if (File.Exists(Path.Combine(Path.GetDirectoryName(ThisAssembly.Location), "FNA.dll")))
                    {
                        File.Copy(Path.Combine(Path.GetDirectoryName(ThisAssembly.Location), "FNA.dll"), Path.Combine(path, "FNA.dll"), true);
                    }
                    else if (File.Exists(Path.Combine(Path.GetDirectoryName(ThisAssembly.Location), "FNA.dll.tmp")))
                    {
                        File.Copy(Path.Combine(Path.GetDirectoryName(ThisAssembly.Location), "FNA.dll.tmp"), Path.Combine(path, "FNA.dll"), true);
                    }
                }

                ScanPaths(Directory.GetFiles(path));
                return;
            }

            if (File.Exists(path + ".xex"))
            {
                if (!ExtractedXEX.Contains(path))
                {
                    // Remove the original file - let XnaToFna unpack and handle it later.
                    File.Delete(path);
                }
                else
                {
                    // XnaToFna will handle the .xex instead.
                }
                return;
            }

            if (path.EndsWith(".xex"))
            {
                string pathTarget = path.Substring(0, path.Length - 4);
                if (string.IsNullOrEmpty(Path.GetExtension(pathTarget)))
                {
                    return;
                }

                using (Stream streamXEX = File.OpenRead(path))
                    using (BinaryReader reader = new BinaryReader(streamXEX))
                        using (Stream streamRAW = File.OpenWrite(pathTarget)) {
                            XEXImageData data = new XEXImageData(reader);

                            int offset = 0;
                            int size   = data.m_memorySize;

                            // Check if this file is a PE containing an embedded PE.
                            if (data.m_memorySize > 0x10000) // One default segment alignment.
                            {
                                using (MemoryStream streamMEM = new MemoryStream(data.m_memoryData))
                                    using (BinaryReader mem = new BinaryReader(streamMEM)) {
                                        if (mem.ReadUInt32() != 0x00905A4D) // MZ
                                        {
                                            goto WriteRaw;
                                        }
                                        // This is horrible.
                                        streamMEM.Seek(0x00000280, SeekOrigin.Begin);
                                        if (mem.ReadUInt64() != 0x000061746164692E) // ".idata\0\0"
                                        {
                                            goto WriteRaw;
                                        }
                                        streamMEM.Seek(0x00000288, SeekOrigin.Begin);
                                        mem.ReadInt32();          // Virtual size; It's somewhat incorrect?
                                        offset = mem.ReadInt32(); // Virtual offset.
                                        // mem.ReadInt32(); // Raw size; Still incorrect.
                                        // Let's just write everything...
                                        size = data.m_memorySize - offset;
                                    }
                            }

WriteRaw:
                            streamRAW.Write(data.m_memoryData, offset, size);
                        }

                path = pathTarget;
                ExtractedXEX.Add(pathTarget);
            }
            else if (!path.EndsWith(".dll") && !path.EndsWith(".exe"))
            {
                return;
            }

            // Check if .dll is CLR assembly
            AssemblyName name;

            try {
                name = AssemblyName.GetAssemblyName(path);
            } catch {
                return;
            }

            ReaderParameters modReaderParams = Modder.GenReaderParameters(false);
            // Don't ReadWrite if the module being read is XnaToFna or a relink target.
            bool isReadWrite =
#if !CECIL0_9
                modReaderParams.ReadWrite =
#endif
                path != ThisAssembly.Location &&
                !Mappings.Exists(mappings => name.Name == mappings.Target);

            // Only read debug info if it exists
            if (!File.Exists(path + ".mdb") && !File.Exists(Path.ChangeExtension(path, "pdb")))
            {
                modReaderParams.ReadSymbols = false;
            }
            Log($"[ScanPath] Checking assembly {name.Name} ({(isReadWrite ? "rw" : "r-")})");
            ModuleDefinition mod;

            try {
                mod = MonoModExt.ReadModule(path, modReaderParams);
            } catch (Exception e) {
                Log($"[ScanPath] WARNING: Cannot load assembly: {e}");
                return;
            }
            bool add = !isReadWrite || name.Name == ThisAssemblyName;

            if ((mod.Attributes & ModuleAttributes.ILOnly) != ModuleAttributes.ILOnly)
            {
                // Mono.Cecil can't handle mixed mode assemblies.
                Log($"[ScanPath] WARNING: Cannot handle mixed mode assembly {name.Name}");
                if (MixedDeps == MixedDepAction.Stub)
                {
                    ModulesToStub.Add(mod);
                    add = true;
                }
                else
                {
                    if (MixedDeps == MixedDepAction.Remove)
                    {
                        RemoveDeps.Add(name.Name);
                    }
#if !CECIL0_9
                    mod.Dispose();
#endif
                    return;
                }
            }

            if (add && !isReadWrite)   // XNA replacement
            {
                foreach (XnaToFnaMapping mapping in Mappings)
                {
                    if (name.Name == mapping.Target)
                    {
                        mapping.IsActive = true;
                        mapping.Module   = mod;
                        foreach (string from in mapping.Sources)
                        {
                            Log($"[ScanPath] Mapping {from} -> {name.Name}");
                            Modder.RelinkModuleMap[from] = mod;
                        }
                    }
                }
            }
            else if (!add)
            {
                foreach (XnaToFnaMapping mapping in Mappings)
                {
                    if (mod.AssemblyReferences.Any(dep => mapping.Sources.Contains(dep.Name)))
                    {
                        add = true;
                        Log($"[ScanPath] XnaToFna-ing {name.Name}");
                        goto BreakMappings;
                    }
                }
            }
BreakMappings:

            if (add)
            {
                Modules.Add(mod);
                ModulePaths[mod] = path;
            }
            else
            {
#if !CECIL0_9
                mod.Dispose();
#endif
            }
        }