Esempio n. 1
0
        public TexExplorer CreateTextureExplorer(MeType type)
        {
            TexExplorer explorer = new TexExplorer(this, type);

            explorer.Text        = "Mass Effect " + (int)type;
            explorer.MdiParent   = this;
            explorer.WindowState = FormWindowState.Maximized;
            explorer.Show();
            return(explorer);
        }
        public string PrepareListOfTextures(TexExplorer texEplorer, CachePackageMgr cachePackageMgr, MainWindow mainWindow, Installer installer, ref string log, bool force = false)
        {
            string errors = "";

            treeScan = null;

            List <FoundTexture> textures = new List <FoundTexture>();
            string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
                                       Assembly.GetExecutingAssembly().GetName().Name);

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            string filename = Path.Combine(path, "me" + (int)GameData.gameType + "map.bin");

            if (force && File.Exists(filename))
            {
                File.Delete(filename);
            }

            if (File.Exists(filename))
            {
                using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite))
                {
                    uint tag     = fs.ReadUInt32();
                    uint version = fs.ReadUInt32();
                    if (tag != TexExplorer.textureMapBinTag || version != TexExplorer.textureMapBinVersion)
                    {
                        if (mainWindow != null)
                        {
                            MessageBox.Show("Wrong " + filename + " file!");
                            mainWindow.updateStatusLabel("");
                            mainWindow.updateStatusLabel2("");
                            texEplorer.Close();
                        }
                        fs.Close();
                        log += "Wrong " + filename + " file!" + Environment.NewLine;
                        return("Wrong " + filename + " file!" + Environment.NewLine);
                    }

                    uint countTexture = fs.ReadUInt32();
                    for (int i = 0; i < countTexture; i++)
                    {
                        FoundTexture texture = new FoundTexture();
                        texture.name        = fs.ReadStringASCIINull();
                        texture.crc         = fs.ReadUInt32();
                        texture.packageName = fs.ReadStringASCIINull();
                        uint countPackages = fs.ReadUInt32();
                        texture.list = new List <MatchedTexture>();
                        for (int k = 0; k < countPackages; k++)
                        {
                            MatchedTexture matched = new MatchedTexture();
                            matched.exportID = fs.ReadInt32();
                            matched.path     = fs.ReadStringASCIINull();
                            texture.list.Add(matched);
                        }
                        textures.Add(texture);
                    }
                    if (fs.Position < new FileInfo(filename).Length)
                    {
                        List <string> packages    = new List <string>();
                        int           numPackages = fs.ReadInt32();
                        for (int i = 0; i < numPackages; i++)
                        {
                            string pkgPath = fs.ReadStringASCIINull();
                            pkgPath = GameData.GamePath + pkgPath;
                            packages.Add(pkgPath);
                        }
                        for (int i = 0; i < packages.Count; i++)
                        {
                            if (GameData.packageFiles.Find(s => s.Equals(packages[i], StringComparison.OrdinalIgnoreCase)) == null)
                            {
                                if (mainWindow != null)
                                {
                                    MessageBox.Show("Detected removal of game files since last game data scan." +
                                                    "\n\nYou need to restore the game to vanilla state and reinstall vanilla DLCs and DLC mods." +
                                                    "\n\nThen from the main menu, select 'Remove Textures Scan File' and start Texture Manager again.");
                                    return("");
                                }
                                else if (!force)
                                {
                                    errors += "Detected removal of game files since last game data scan." + Environment.NewLine + Environment.NewLine +
                                              "You need to restore the game to vanilla state and reinstall vanilla DLCs and DLC mods.";
                                    return("");
                                }
                            }
                        }
                        for (int i = 0; i < GameData.packageFiles.Count; i++)
                        {
                            if (packages.Find(s => s.Equals(GameData.packageFiles[i], StringComparison.OrdinalIgnoreCase)) == null)
                            {
                                if (mainWindow != null)
                                {
                                    MessageBox.Show("Detected additional game files not present in latest game data scan." +
                                                    "\n\nYou need to restore the game to vanilla state and reinstall vanilla DLCs and DLC mods." +
                                                    "\n\nThen from the main menu, select 'Remove Textures Scan File' and start Texture Manager again.");
                                    return("");
                                }
                                else if (!force)
                                {
                                    errors += "Detected additional game files not present in latest game data scan." + Environment.NewLine + Environment.NewLine +
                                              "You need to restore the game to vanilla state and reinstall vanilla DLCs and DLC mods.";
                                    return("");
                                }
                            }
                        }
                    }
                    else
                    {
                        fs.SeekEnd();
                        fs.WriteInt32(GameData.packageFiles.Count);
                        for (int i = 0; i < GameData.packageFiles.Count; i++)
                        {
                            fs.WriteStringASCIINull(GameData.RelativeGameData(GameData.packageFiles[i]));
                        }
                    }
                    treeScan = textures;
                    if (mainWindow != null)
                    {
                        mainWindow.updateStatusLabel("");
                        mainWindow.updateStatusLabel2("");
                    }
                    return(errors);
                }
            }


            if (File.Exists(filename))
            {
                File.Delete(filename);
            }

            if (Misc.detectBrokenMod(GameData.gameType))
            {
                if (mainWindow != null)
                {
                    MessageBox.Show("Detected ME1 Controller or/and Faster Elevators mod!\nMEM will not work properly due broken content in mod.");
                }
                return("");
            }

            if (MipMaps.checkGameDataModded(cachePackageMgr))
            {
                if (mainWindow != null)
                {
                    MessageBox.Show("Detected modded game. Can not continue." +
                                    "\n\nYou need to restore the game to vanilla state and reinstall vanilla DLCs and DLC mods." +
                                    "\n\nThen start Texture Manager again.");
                    return("");
                }
                else if (!force)
                {
                    errors += "Detected modded game. Can not continue." + Environment.NewLine + Environment.NewLine +
                              "You need to restore the game to vanilla state and reinstall vanilla DLCs and DLC mods.";
                    return("");
                }
            }

            if (mainWindow != null)
            {
                DialogResult result = MessageBox.Show("Replacing textures and creating mods requires generating a map of the game's textures.\n" +
                                                      "You only need to do it once.\n\n" +
                                                      "IMPORTANT! Your game needs to be in vanilla state and have all original DLCs and DLC mods installed.\n\n" +
                                                      "Are you sure you want to proceed?", "Textures mapping", MessageBoxButtons.YesNo);
                if (result == DialogResult.No)
                {
                    texEplorer.Close();
                    return("");
                }
            }

            GameData.packageFiles.Sort();
            if (mainWindow != null)
            {
                Misc.startTimer();
            }
            for (int i = 0; i < GameData.packageFiles.Count; i++)
            {
                if (mainWindow != null)
                {
                    mainWindow.updateStatusLabel("Finding textures in package " + (i + 1) + " of " + GameData.packageFiles.Count + " - " + GameData.packageFiles[i]);
                }
                if (installer != null)
                {
                    installer.updateStatusScan("Progress... " + (i * 100 / GameData.packageFiles.Count) + " % ");
                }
                errors += FindTextures(textures, GameData.packageFiles[i], cachePackageMgr, ref log);
            }

            using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write))
            {
                fs.WriteUInt32(TexExplorer.textureMapBinTag);
                fs.WriteUInt32(TexExplorer.textureMapBinVersion);
                fs.WriteInt32(textures.Count);
                for (int i = 0; i < textures.Count; i++)
                {
                    fs.WriteStringASCIINull(textures[i].name);
                    fs.WriteUInt32(textures[i].crc);
                    fs.WriteStringASCIINull(textures[i].packageName);
                    fs.WriteInt32(textures[i].list.Count);
                    for (int k = 0; k < textures[i].list.Count; k++)
                    {
                        fs.WriteInt32(textures[i].list[k].exportID);
                        fs.WriteStringASCIINull(textures[i].list[k].path);
                    }
                }
                fs.WriteInt32(GameData.packageFiles.Count);
                for (int i = 0; i < GameData.packageFiles.Count; i++)
                {
                    fs.WriteStringASCIINull(GameData.RelativeGameData(GameData.packageFiles[i]));
                }
            }

            if (mainWindow != null)
            {
                MipMaps mipmaps = new MipMaps();
                if (GameData.gameType == MeType.ME1_TYPE)
                {
                    errors += mipmaps.removeMipMapsME1(1, textures, null, mainWindow, null);
                    errors += mipmaps.removeMipMapsME1(2, textures, null, mainWindow, null);
                }
                else
                {
                    errors += mipmaps.removeMipMapsME2ME3(textures, null, mainWindow, null);
                }

                var time = Misc.stopTimer();
                mainWindow.updateStatusLabel("Done. Process total time: " + Misc.getTimerFormat(time));
                mainWindow.updateStatusLabel2("");
            }
            treeScan = textures;
            return(errors);
        }
        private string processTextureMod(string filenameMod, int previewIndex, bool extract, bool replace, bool verify,
                                         string outDir, List <FoundTexture> textures, TexExplorer texExplorer, ref string log)
        {
            string errors = "";

            if (filenameMod.EndsWith(".tpf", StringComparison.OrdinalIgnoreCase))
            {
                if (!replace && !extract)
                {
                    throw new Exception();
                }

                int            result;
                string         fileName   = "";
                ulong          dstLen     = 0;
                string[]       ddsList    = null;
                ulong          numEntries = 0;
                IntPtr         handle     = IntPtr.Zero;
                ZlibHelper.Zip zip        = new ZlibHelper.Zip();
                try
                {
                    int indexTpf = -1;
                    handle = zip.Open(filenameMod, ref numEntries, 1);
                    for (ulong i = 0; i < numEntries; i++)
                    {
                        result   = zip.GetCurrentFileInfo(handle, ref fileName, ref dstLen);
                        fileName = fileName.Trim();
                        if (result != 0)
                        {
                            throw new Exception();
                        }
                        if (Path.GetExtension(fileName).ToLowerInvariant() == ".def" ||
                            Path.GetExtension(fileName).ToLowerInvariant() == ".log")
                        {
                            indexTpf = (int)i;
                            break;
                        }
                        result = zip.GoToNextFile(handle);
                        if (result != 0)
                        {
                            throw new Exception();
                        }
                    }
                    byte[] listText = new byte[dstLen];
                    result = zip.ReadCurrentFile(handle, listText, dstLen);
                    if (result != 0)
                    {
                        throw new Exception();
                    }
                    ddsList = Encoding.ASCII.GetString(listText).Trim('\0').Replace("\r", "").TrimEnd('\n').Split('\n');

                    result = zip.GoToFirstFile(handle);
                    if (result != 0)
                    {
                        throw new Exception();
                    }

                    for (uint i = 0; i < numEntries; i++)
                    {
                        if (i == indexTpf)
                        {
                            result = zip.GoToNextFile(handle);
                            continue;
                        }
                        try
                        {
                            uint crc = 0;
                            result = zip.GetCurrentFileInfo(handle, ref fileName, ref dstLen);
                            if (result != 0)
                            {
                                throw new Exception();
                            }
                            fileName = fileName.Trim();
                            foreach (string dds in ddsList)
                            {
                                string ddsFile = dds.Split('|')[1];
                                if (ddsFile.ToLowerInvariant().Trim() != fileName.ToLowerInvariant())
                                {
                                    continue;
                                }
                                crc = uint.Parse(dds.Split('|')[0].Substring(2), System.Globalization.NumberStyles.HexNumber);
                                break;
                            }
                            string filename = Path.GetFileName(fileName);
                            if (crc == 0)
                            {
                                log    += "Skipping file: " + filename + " not found in definition file, entry: " + (i + 1) + " - mod: " + filenameMod + Environment.NewLine;
                                errors += "Skipping file: " + filename + " not found in definition file, entry: " + (i + 1) + " - mod: " + filenameMod + Environment.NewLine;
                                zip.GoToNextFile(handle);
                                continue;
                            }

                            int index = -1;
                            for (int t = 0; t < textures.Count; t++)
                            {
                                if (textures[t].crc == crc)
                                {
                                    index = t;
                                    break;
                                }
                            }
                            if (index != -1)
                            {
                                FoundTexture foundTexture = textures[index];
                                byte[]       data         = new byte[dstLen];
                                result = zip.ReadCurrentFile(handle, data, dstLen);
                                if (result != 0)
                                {
                                    log    += "Error in texture: " + foundTexture.name + string.Format("_0x{0:X8}", crc) + ", skipping texture, entry: " + (i + 1) + " - mod: " + filenameMod + Environment.NewLine;
                                    errors += "Error in texture: " + foundTexture.name + string.Format("_0x{0:X8}", crc) + ", skipping texture, entry: " + (i + 1) + " - mod: " + filenameMod + Environment.NewLine;
                                    zip.GoToNextFile(handle);
                                    continue;
                                }
                                if (texExplorer != null)
                                {
                                    texExplorer._mainWindow.updateStatusLabel("Processing MOD " + Path.GetFileName(filenameMod) +
                                                                              " - File " + (i + 1) + " of " + numEntries + " - " + foundTexture.name);
                                }
                                if (extract)
                                {
                                    string name = foundTexture.name + "_" + string.Format("0x{0:X8}", crc) + Path.GetExtension(fileName);
                                    using (FileStream output = new FileStream(Path.Combine(outDir, name), FileMode.Create, FileAccess.Write))
                                    {
                                        output.Write(data, 0, (int)dstLen);
                                    }
                                }
                                else if (replace)
                                {
                                    int indexPremap = -1;
                                    for (int t = 0; t < texExplorer.texturesPreMap.Count; t++)
                                    {
                                        if (texExplorer.texturesPreMap[t].crc == crc)
                                        {
                                            indexPremap = t;
                                            break;
                                        }
                                    }
                                    if (indexPremap != -1)
                                    {
                                        zip.GoToNextFile(handle);
                                        log += "Texture skipped. File " + filename + string.Format(" - 0x{0:X8}", crc) + " is not present in premap database - mod: " + filenameMod + Environment.NewLine;
                                        continue;
                                    }

                                    PixelFormat pixelFormat = texExplorer.texturesPreMap[indexPremap].pixfmt;
                                    Image       image       = new Image(data, Path.GetExtension(filename));

                                    if (image.mipMaps[0].origWidth / image.mipMaps[0].origHeight !=
                                        texExplorer.texturesPreMap[indexPremap].width / texExplorer.texturesPreMap[indexPremap].height)
                                    {
                                        zip.GoToNextFile(handle);
                                        errors += "Error in texture: " + foundTexture.name + string.Format("_0x{0:X8}", crc) + " This texture has wrong aspect ratio, skipping texture, entry: " + (i + 1) + " - mod: " + filename + Environment.NewLine;
                                        continue;
                                    }

                                    if (!image.checkDDSHaveAllMipmaps() ||
                                        (foundTexture.list.Find(s => s.path != "").numMips > 1 && image.mipMaps.Count() <= 1) ||
                                        (image.pixelFormat != pixelFormat))
                                    {
                                        texExplorer._mainWindow.updateStatusLabel2("Converting/correcting texture: " + foundTexture.name);
                                        bool dxt1HasAlpha  = false;
                                        byte dxt1Threshold = 128;
                                        if (texExplorer.texturesPreMap[indexPremap].flags == TexProperty.TextureTypes.OneBitAlpha)
                                        {
                                            dxt1HasAlpha = true;
                                            if (image.pixelFormat == PixelFormat.ARGB ||
                                                image.pixelFormat == PixelFormat.DXT3 ||
                                                image.pixelFormat == PixelFormat.DXT5)
                                            {
                                                errors += "Warning for texture: " + foundTexture.name + ". This texture converted from full alpha to binary alpha." + Environment.NewLine;
                                            }
                                        }
                                        image.correctMips(pixelFormat, dxt1HasAlpha, dxt1Threshold);
                                    }

                                    ModEntry entry = new ModEntry();
                                    entry.cacheImage  = image;
                                    entry.textureCrc  = crc;
                                    entry.textureName = foundTexture.name;
                                    modsToReplace.Add(entry);
                                }
                            }
                            else
                            {
                                log += "Texture skipped. File " + filename + string.Format(" - 0x{0:X8}", crc) + " is not present in your game setup - mod: " + filenameMod + Environment.NewLine;
                                zip.GoToNextFile(handle);
                                continue;
                            }
                        }
                        catch
                        {
                            log    += "Skipping not compatible content, entry: " + (i + 1) + " file: " + fileName + " - mod: " + filenameMod + Environment.NewLine;
                            errors += "Skipping not compatible content, entry: " + (i + 1) + " file: " + fileName + " - mod: " + filenameMod + Environment.NewLine;
                        }
                        result = zip.GoToNextFile(handle);
                    }
                    zip.Close(handle);
                    handle = IntPtr.Zero;
                }
                catch
                {
                    log    += "Mod is not compatible: " + filenameMod + Environment.NewLine;
                    errors += "Mod is not compatible: " + filenameMod + Environment.NewLine;
                    if (handle != IntPtr.Zero)
                    {
                        zip.Close(handle);
                    }
                    handle = IntPtr.Zero;
                }
                return(errors);
            }
            else if (filenameMod.EndsWith(".mod", StringComparison.OrdinalIgnoreCase))
            {
                if (!replace && !extract)
                {
                    throw new Exception();
                }

                try
                {
                    using (FileStream fs = new FileStream(filenameMod, FileMode.Open, FileAccess.Read))
                    {
                        string package = "";
                        int    len     = fs.ReadInt32();
                        string version = fs.ReadStringASCIINull();
                        if (version.Length < 5) // legacy .mod
                        {
                            fs.SeekBegin();
                        }
                        else
                        {
                            fs.SeekBegin();
                            len     = fs.ReadInt32();
                            version = fs.ReadStringASCII(len); // version
                        }
                        uint numEntries = fs.ReadUInt32();
                        for (uint i = 0; i < numEntries; i++)
                        {
                            BinaryMod mod = new BinaryMod();
                            len = fs.ReadInt32();
                            string desc = fs.ReadStringASCII(len); // description
                            len = fs.ReadInt32();
                            string scriptLegacy = fs.ReadStringASCII(len);
                            string path         = "";
                            if (desc.Contains("Binary Replacement"))
                            {
                                try
                                {
                                    Misc.ParseME3xBinaryScriptMod(scriptLegacy, ref package, ref mod.exportId, ref path);
                                    if (mod.exportId == -1 || package == "" || path == "")
                                    {
                                        throw new Exception();
                                    }
                                }
                                catch
                                {
                                    len = fs.ReadInt32();
                                    fs.Skip(len);
                                    errors += "Skipping not compatible content, entry: " + (i + 1) + " - mod: " + filenameMod + Environment.NewLine;
                                    continue;
                                }
                                mod.packagePath = Path.Combine(GameData.GamePath + path, package);
                                len             = fs.ReadInt32();
                                mod.data        = fs.ReadToBuffer(len);

                                if (!File.Exists(mod.packagePath))
                                {
                                    errors += "Warning: File " + mod.packagePath + " not exists in your game setup." + Environment.NewLine;
                                    log    += "Warning: File " + mod.packagePath + " not exists in your game setup." + Environment.NewLine;
                                    continue;
                                }
                                if (replace)
                                {
                                    ModEntry entry = new ModEntry();
                                    entry.binaryModType = true;
                                    entry.packagePath   = path;
                                    entry.exportId      = mod.exportId;
                                    entry.binaryModData = mod.data;
                                    modsToReplace.Add(entry);
                                }
                            }
                            else
                            {
                                string       textureName = desc.Split(' ').Last();
                                FoundTexture f;
                                int          index = -1;
                                try
                                {
                                    index = Misc.ParseLegacyMe3xScriptMod(textures, scriptLegacy, textureName);
                                    if (index == -1)
                                    {
                                        throw new Exception();
                                    }
                                    f = textures[index];
                                }
                                catch
                                {
                                    len = fs.ReadInt32();
                                    fs.Skip(len);
                                    errors += "Skipping not compatible content, entry: " + (i + 1) + " - mod: " + filenameMod + Environment.NewLine;
                                    continue;
                                }
                                mod.textureCrc  = f.crc;
                                mod.textureName = f.name;
                                len             = fs.ReadInt32();
                                mod.data        = fs.ReadToBuffer(len);

                                if (replace)
                                {
                                    int indexPremap = -1;
                                    try
                                    {
                                        indexPremap = Misc.ParseLegacyMe3xScriptMod(texExplorer.texturesPreMap, scriptLegacy, textureName);
                                        if (indexPremap == -1)
                                        {
                                            throw new Exception();
                                        }
                                    }
                                    catch
                                    {
                                        len = fs.ReadInt32();
                                        fs.Skip(len);
                                        errors += "Skipping not compatible content, entry: " + (i + 1) + " - mod: " + filenameMod + Environment.NewLine;
                                        continue;
                                    }

                                    PixelFormat pixelFormat = texExplorer.texturesPreMap[indexPremap].pixfmt;
                                    Image       image       = new Image(mod.data, Image.ImageFormat.DDS);

                                    if (image.mipMaps[0].origWidth / image.mipMaps[0].origHeight !=
                                        texExplorer.texturesPreMap[indexPremap].width / texExplorer.texturesPreMap[indexPremap].height)
                                    {
                                        errors += "Error in texture: " + f.name + string.Format("_0x{0:X8}", f.crc) + " This texture has wrong aspect ratio, skipping texture, entry: " + (i + 1) + " - mod: " + filenameMod + Environment.NewLine;
                                        continue;
                                    }

                                    if (!image.checkDDSHaveAllMipmaps() ||
                                        (f.list.Find(s => s.path != "").numMips > 1 && image.mipMaps.Count() <= 1) ||
                                        (image.pixelFormat != pixelFormat))
                                    {
                                        texExplorer._mainWindow.updateStatusLabel2("Converting/correcting texture: " + f.name);
                                        bool dxt1HasAlpha  = false;
                                        byte dxt1Threshold = 128;
                                        if (texExplorer.texturesPreMap[indexPremap].flags == TexProperty.TextureTypes.OneBitAlpha)
                                        {
                                            dxt1HasAlpha = true;
                                            if (image.pixelFormat == PixelFormat.ARGB ||
                                                image.pixelFormat == PixelFormat.DXT3 ||
                                                image.pixelFormat == PixelFormat.DXT5)
                                            {
                                                errors += "Warning for texture: " + f.name + ". This texture converted from full alpha to binary alpha." + Environment.NewLine;
                                            }
                                        }
                                        image.correctMips(pixelFormat, dxt1HasAlpha, dxt1Threshold);
                                    }

                                    ModEntry entry = new ModEntry();
                                    entry.cacheImage  = image;
                                    entry.textureCrc  = f.crc;
                                    entry.textureName = f.name;
                                    modsToReplace.Add(entry);
                                }
                            }
                        }
                    }
                }
                catch
                {
                    errors += "Mod is not compatible: " + filenameMod + Environment.NewLine;
                }
                return(errors);
            }

            using (FileStream fs = new FileStream(filenameMod, FileMode.Open, FileAccess.Read))
            {
                if (previewIndex == -1 && !extract && !replace)
                {
                    texExplorer.listViewTextures.BeginUpdate();
                }
                uint tag     = fs.ReadUInt32();
                uint version = fs.ReadUInt32();
                if (tag != TreeScan.TextureModTag || version != TreeScan.TextureModVersion)
                {
                    if (version != TreeScan.TextureModVersion)
                    {
                        errors += "File " + filenameMod + " was made with an older version of MEM, skipping..." + Environment.NewLine;
                        log    += "File " + filenameMod + " was made with an older version of MEM, skipping..." + Environment.NewLine;
                    }
                    else
                    {
                        errors += "File " + filenameMod + " is not a valid MEM mod, skipping..." + Environment.NewLine;
                        log    += "File " + filenameMod + " is not a valid MEM mod, skipping..." + Environment.NewLine;
                    }
                    if (previewIndex == -1 && !extract && !replace)
                    {
                        texExplorer.listViewTextures.EndUpdate();
                    }
                    return(errors);
                }
                else
                {
                    uint gameType = 0;
                    fs.JumpTo(fs.ReadInt64());
                    gameType = fs.ReadUInt32();
                    if ((MeType)gameType != GameData.gameType)
                    {
                        errors += "File " + filenameMod + " is not a MEM mod valid for this game" + Environment.NewLine;
                        log    += "File " + filenameMod + " is not a MEM mod valid for this game" + Environment.NewLine;
                        if (previewIndex == -1 && !extract && !replace)
                        {
                            texExplorer.listViewTextures.EndUpdate();
                        }
                        return(errors);
                    }
                }
                int            numFiles = fs.ReadInt32();
                List <FileMod> modFiles = new List <FileMod>();
                for (int i = 0; i < numFiles; i++)
                {
                    FileMod fileMod = new FileMod();
                    fileMod.tag    = fs.ReadUInt32();
                    fileMod.name   = fs.ReadStringASCIINull();
                    fileMod.offset = fs.ReadInt64();
                    fileMod.size   = fs.ReadInt64();
                    modFiles.Add(fileMod);
                }
                numFiles = modFiles.Count;

                if (texExplorer != null && replace)
                {
                    texExplorer._mainWindow.updateStatusLabel("Processing MOD " + Path.GetFileName(filenameMod));
                }

                for (int i = 0; i < numFiles; i++)
                {
                    string name = "";
                    uint   crc = 0;
                    long   size = 0, dstLen = 0;
                    int    exportId = -1;
                    string pkgPath  = "";
                    byte[] dst      = null;
                    if (previewIndex != -1)
                    {
                        i = previewIndex;
                    }
                    fs.JumpTo(modFiles[i].offset);
                    size = modFiles[i].size;
                    if (modFiles[i].tag == FileTextureTag || modFiles[i].tag == FileTextureTag2)
                    {
                        name = fs.ReadStringASCIINull();
                        crc  = fs.ReadUInt32();
                    }
                    else if (modFiles[i].tag == FileBinaryTag)
                    {
                        name     = modFiles[i].name;
                        exportId = fs.ReadInt32();
                        pkgPath  = fs.ReadStringASCIINull();
                    }
                    else if (modFiles[i].tag == FileXdeltaTag)
                    {
                        name     = modFiles[i].name;
                        exportId = fs.ReadInt32();
                        pkgPath  = fs.ReadStringASCIINull();
                    }

                    if (texExplorer != null && (extract || replace))
                    {
                        texExplorer._mainWindow.updateStatusLabel("Processing MOD " + Path.GetFileName(filenameMod) +
                                                                  " - File " + (i + 1) + " of " + numFiles + " - " + name);
                    }

                    if (previewIndex == -1 && !extract && !replace)
                    {
                        if (modFiles[i].tag == FileTextureTag || modFiles[i].tag == FileTextureTag2)
                        {
                            FoundTexture foundTexture;
                            foundTexture = textures.Find(s => s.crc == crc);
                            if (foundTexture.crc != 0)
                            {
                                ListViewItem item = new ListViewItem(foundTexture.name + " (" + Path.GetFileNameWithoutExtension(foundTexture.list.Find(s => s.path != "").path).ToUpperInvariant() + ")");
                                item.Name = i.ToString();
                                texExplorer.listViewTextures.Items.Add(item);
                            }
                            else
                            {
                                ListViewItem item = new ListViewItem(name + " (Texture not found: " + name + string.Format("_0x{0:X8}", crc) + ")");
                                item.Name = i.ToString();
                                texExplorer.listViewTextures.Items.Add(item);
                                log += "Texture skipped. Texture " + name + string.Format("_0x{0:X8}", crc) + " is not present in your game setup" + Environment.NewLine;
                            }
                        }
                        else if (modFiles[i].tag == FileBinaryTag)
                        {
                            ListViewItem item = new ListViewItem(name + " (Raw Binary Mod)");
                            item.Name = i.ToString();
                            texExplorer.listViewTextures.Items.Add(item);
                        }
                        else if (modFiles[i].tag == FileXdeltaTag)
                        {
                            ListViewItem item = new ListViewItem(name + " (Xdelta Binary Mod)");
                            item.Name = i.ToString();
                            texExplorer.listViewTextures.Items.Add(item);
                        }
                        else
                        {
                            ListViewItem item = new ListViewItem(name + " (Unknown)");
                            item.Name = i.ToString();
                            errors   += "Unknown tag for file: " + name + Environment.NewLine;
                            log      += "Unknown tag for file: " + name + Environment.NewLine;
                        }
                        continue;
                    }

                    if (!replace || (modFiles[i].tag != FileTextureTag && modFiles[i].tag != FileTextureTag2))
                    {
                        dst    = decompressData(fs, size);
                        dstLen = dst.Length;
                    }

                    if (extract)
                    {
                        if (modFiles[i].tag == FileTextureTag)
                        {
                            string filename = name + "_" + string.Format("0x{0:X8}", crc) + ".dds";
                            using (FileStream output = new FileStream(Path.Combine(outDir, Path.GetFileName(filename)), FileMode.Create, FileAccess.Write))
                            {
                                output.Write(dst, 0, (int)dstLen);
                            }
                        }
                        else if (modFiles[i].tag == FileTextureTag2)
                        {
                            string filename = name + "_" + string.Format("0x{0:X8}", crc) + "-memconvert.dds";
                            using (FileStream output = new FileStream(Path.Combine(outDir, Path.GetFileName(filename)), FileMode.Create, FileAccess.Write))
                            {
                                output.Write(dst, 0, (int)dstLen);
                            }
                        }
                        else if (modFiles[i].tag == FileBinaryTag)
                        {
                            string path = pkgPath;
                            string newFilename;
                            if (path.Contains("\\DLC\\"))
                            {
                                string dlcName = path.Split('\\')[3];
                                newFilename = "D" + dlcName.Length + "-" + dlcName + "-";
                            }
                            else
                            {
                                newFilename = "B";
                            }
                            newFilename += Path.GetFileName(path).Length + "-" + Path.GetFileName(path) + "-E" + exportId + ".bin";
                            using (FileStream output = new FileStream(Path.Combine(outDir, newFilename), FileMode.Create, FileAccess.Write))
                            {
                                output.Write(dst, 0, (int)dstLen);
                            }
                        }
                        else if (modFiles[i].tag == FileXdeltaTag)
                        {
                            string path = pkgPath;
                            string newFilename;
                            if (path.Contains("\\DLC\\"))
                            {
                                string dlcName = path.Split('\\')[3];
                                newFilename = "D" + dlcName.Length + "-" + dlcName + "-";
                            }
                            else
                            {
                                newFilename = "B";
                            }
                            newFilename += Path.GetFileName(path).Length + "-" + Path.GetFileName(path) + "-E" + exportId + ".xdelta";
                            using (FileStream output = new FileStream(Path.Combine(outDir, newFilename), FileMode.Create, FileAccess.Write))
                            {
                                output.Write(dst, 0, (int)dstLen);
                            }
                        }
                        else
                        {
                            errors += "Unknown tag for file: " + name + Environment.NewLine;
                            log    += "Unknown tag for file: " + name + Environment.NewLine;
                        }
                        continue;
                    }

                    if (previewIndex != -1)
                    {
                        if (modFiles[i].tag == FileTextureTag || modFiles[i].tag == FileTextureTag2)
                        {
                            Image image = new Image(dst, Image.ImageFormat.DDS);
                            texExplorer.pictureBoxPreview.Image = image.getBitmapARGB();
                        }
                        else
                        {
                            texExplorer.pictureBoxPreview.Image = null;
                        }
                        break;
                    }
                    else if (replace)
                    {
                        if (modFiles[i].tag == FileTextureTag || modFiles[i].tag == FileTextureTag2)
                        {
                            int index = -1;
                            for (int t = 0; t < textures.Count; t++)
                            {
                                if (textures[t].crc == crc)
                                {
                                    index = t;
                                    break;
                                }
                            }
                            if (index != -1)
                            {
                                FoundTexture foundTexture = textures[index];
                                ModEntry     entry        = new ModEntry();
                                entry.textureCrc  = foundTexture.crc;
                                entry.textureName = foundTexture.name;
                                if (modFiles[i].tag == FileTextureTag2)
                                {
                                    entry.markConvert = true;
                                }
                                entry.memPath        = filenameMod;
                                entry.memEntryOffset = fs.Position;
                                entry.memEntrySize   = size;
                                modsToReplace.Add(entry);
                            }
                            else
                            {
                                log += "Error: Texture " + name + string.Format("_0x{0:X8}", crc) + "is not present in your game setup. Texture skipped." + Environment.NewLine;
                            }
                        }
                        else if (modFiles[i].tag == FileBinaryTag)
                        {
                            string path = GameData.GamePath + pkgPath;
                            if (!File.Exists(path))
                            {
                                errors += "Warning: File " + path + " not exists in your game setup." + Environment.NewLine;
                                log    += "Warning: File " + path + " not exists in your game setup." + Environment.NewLine;
                                continue;
                            }
                            ModEntry entry = new ModEntry();
                            entry.binaryModType = true;
                            entry.packagePath   = pkgPath;
                            entry.exportId      = exportId;
                            entry.binaryModData = dst;
                            modsToReplace.Add(entry);
                        }
                        else if (modFiles[i].tag == FileXdeltaTag)
                        {
                            string path = GameData.GamePath + pkgPath;
                            if (!File.Exists(path))
                            {
                                errors += "Warning: File " + path + " not exists in your game setup." + Environment.NewLine;
                                log    += "Warning: File " + path + " not exists in your game setup." + Environment.NewLine;
                                continue;
                            }
                            ModEntry entry  = new ModEntry();
                            Package  pkg    = new Package(path);
                            byte[]   buffer = new Xdelta3Helper.Xdelta3().Decompress(pkg.getExportData(exportId), dst);
                            if (buffer.Length == 0)
                            {
                                errors += "Warning: Xdelta patch for " + path + " failed to apply." + Environment.NewLine;
                                log    += "Warning: Xdelta patch for " + path + " failed to apply." + Environment.NewLine;
                                continue;
                            }
                            entry.binaryModType = true;
                            entry.packagePath   = pkgPath;
                            entry.exportId      = exportId;
                            entry.binaryModData = buffer;
                            modsToReplace.Add(entry);
                            pkg.Dispose();
                        }
                        else
                        {
                            errors += "Error: Unknown tag for file: " + name + Environment.NewLine;
                            log    += "Error: Unknown tag for file: " + name + Environment.NewLine;
                        }
                    }
                    else
                    {
                        throw new Exception();
                    }
                }
                if (previewIndex == -1 && !extract && !replace)
                {
                    texExplorer.listViewTextures.EndUpdate();
                }
            }
            return(errors);
        }
 public string listTextureMod(string filenameMod, List <FoundTexture> textures, TexExplorer texExplorer, ref string log)
 {
     return(processTextureMod(filenameMod, -1, false, false, false, "", textures, texExplorer, ref log));
 }
 public string replaceTextureMod(string filenameMod, List <FoundTexture> textures, TexExplorer texExplorer, bool verify, ref string log)
 {
     return(processTextureMod(filenameMod, -1, false, true, verify, "", textures, texExplorer, ref log));
 }
 public string previewTextureMod(string filenameMod, int previewIndex, List <FoundTexture> textures, TexExplorer texExplorer, ref string log)
 {
     return(processTextureMod(filenameMod, previewIndex, false, false, false, "", textures, texExplorer, ref log));
 }
 public string extractTextureMod(string filenameMod, string outDir, List <FoundTexture> textures, TexExplorer texExplorer, ref string log)
 {
     return(processTextureMod(filenameMod, -1, true, false, false, outDir, textures, texExplorer, ref log));
 }
        private bool generateBuiltinMapFiles = false; // change to true to enable map files generation

        public string PrepareListOfTextures(TexExplorer texEplorer, CachePackageMgr cachePackageMgr,
                                            MainWindow mainWindow, Installer installer, ref string log, bool force = false)
        {
            string errors = "";

            treeScan = null;

            List <FoundTexture> textures = new List <FoundTexture>();
            string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
                                       Assembly.GetExecutingAssembly().GetName().Name);

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            string filename = Path.Combine(path, "me" + (int)GameData.gameType + "map.bin");

            if (force && File.Exists(filename))
            {
                File.Delete(filename);
            }

            if (File.Exists(filename))
            {
                using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite))
                {
                    uint tag     = fs.ReadUInt32();
                    uint version = fs.ReadUInt32();
                    if (tag != TexExplorer.textureMapBinTag || version != TexExplorer.textureMapBinVersion)
                    {
                        if (mainWindow != null)
                        {
                            MessageBox.Show("Detected wrong or old version of textures scan file!" +
                                            "\n\nYou need to restore the game to vanilla state then reinstall optional DLC/PCC mods." +
                                            "\n\nThen from the main menu, select 'Remove Textures Scan File' and start Texture Manager again.");
                            mainWindow.updateStatusLabel("");
                            mainWindow.updateStatusLabel2("");
                            texEplorer.Close();
                        }
                        fs.Close();
                        log += "Detected wrong or old version of textures scan file!" + Environment.NewLine;
                        log += "You need to restore the game to vanilla state then reinstall optional DLC/PCC mods." + Environment.NewLine;
                        log += "Then from the main menu, select 'Remove Textures Scan File' and start Texture Manager again." + Environment.NewLine;
                        return("Detected wrong or old version of textures scan file!" + Environment.NewLine +
                               "You need to restore the game to vanilla state then reinstall optional DLC/PCC mods." + Environment.NewLine +
                               "Then from the main menu, select 'Remove Textures Scan File' and start Texture Manager again." + Environment.NewLine);
                    }

                    uint countTexture = fs.ReadUInt32();
                    for (int i = 0; i < countTexture; i++)
                    {
                        FoundTexture texture = new FoundTexture();
                        int          len     = fs.ReadInt32();
                        texture.name = fs.ReadStringASCII(len);
                        texture.crc  = fs.ReadUInt32();
                        uint countPackages = fs.ReadUInt32();
                        texture.list = new List <MatchedTexture>();
                        for (int k = 0; k < countPackages; k++)
                        {
                            MatchedTexture matched = new MatchedTexture();
                            matched.exportID     = fs.ReadInt32();
                            matched.linkToMaster = fs.ReadInt32();
                            len          = fs.ReadInt32();
                            matched.path = fs.ReadStringASCII(len);
                            texture.list.Add(matched);
                        }
                        textures.Add(texture);
                    }

                    List <string> packages    = new List <string>();
                    int           numPackages = fs.ReadInt32();
                    for (int i = 0; i < numPackages; i++)
                    {
                        int    len     = fs.ReadInt32();
                        string pkgPath = fs.ReadStringASCII(len);
                        pkgPath = GameData.GamePath + pkgPath;
                        packages.Add(pkgPath);
                    }
                    for (int i = 0; i < packages.Count; i++)
                    {
                        if (GameData.packageFiles.Find(s => s.Equals(packages[i], StringComparison.OrdinalIgnoreCase)) == null)
                        {
                            if (mainWindow != null)
                            {
                                MessageBox.Show("Detected removal of game files since last game data scan." +
                                                "\n\nYou need to restore the game to vanilla state then reinstall optional DLC/PCC mods." +
                                                "\n\nThen from the main menu, select 'Remove Textures Scan File' and start Texture Manager again.");
                                return("");
                            }
                            else if (!force)
                            {
                                errors += "Detected removal of game files since last game data scan." + Environment.NewLine + Environment.NewLine +
                                          "You need to restore the game to vanilla state then reinstall optional DLC/PCC mods.";
                                return("");
                            }
                        }
                    }
                    for (int i = 0; i < GameData.packageFiles.Count; i++)
                    {
                        if (packages.Find(s => s.Equals(GameData.packageFiles[i], StringComparison.OrdinalIgnoreCase)) == null)
                        {
                            if (mainWindow != null)
                            {
                                MessageBox.Show("Detected additional game files not present in latest game data scan." +
                                                "\n\nYou need to restore the game to vanilla state then reinstall optional DLC/PCC mods." +
                                                "\n\nThen from the main menu, select 'Remove Textures Scan File' and start Texture Manager again.");
                                return("");
                            }
                            else if (!force)
                            {
                                errors += "Detected additional game files not present in latest game data scan." + Environment.NewLine + Environment.NewLine +
                                          "You need to restore the game to vanilla state then reinstall optional DLC/PCC mods.";
                                return("");
                            }
                        }
                    }

                    treeScan = textures;
                    if (mainWindow != null)
                    {
                        mainWindow.updateStatusLabel("");
                        mainWindow.updateStatusLabel2("");
                    }
                    return(errors);
                }
            }


            if (File.Exists(filename))
            {
                File.Delete(filename);
            }

            if (mainWindow != null)
            {
                List <string> badMods = Misc.detectBrokenMod(GameData.gameType);
                if (badMods.Count != 0)
                {
                    errors = "";
                    for (int l = 0; l < badMods.Count; l++)
                    {
                        errors += badMods[l] + Environment.NewLine;
                    }
                    MessageBox.Show("Detected not compatible mods: \n\n" + errors);
                    return("");
                }
            }

            if (MipMaps.checkGameDataModded(cachePackageMgr))
            {
                if (mainWindow != null)
                {
                    MessageBox.Show("Detected modded game. Can not continue." +
                                    "\n\nYou need to restore the game to vanilla state then reinstall optional DLC/PCC mods." +
                                    "\n\nThen start Texture Manager again.");
                    return("");
                }
                else if (!force)
                {
                    errors += "Detected modded game. Can not continue." + Environment.NewLine + Environment.NewLine +
                              "You need to restore the game to vanilla state then reinstall optional DLC/PCC mods.";
                    return("");
                }
            }

            if (mainWindow != null)
            {
                DialogResult result = MessageBox.Show("Replacing textures and creating mods requires generating a map of the game's textures.\n" +
                                                      "You only need to do it once.\n\n" +
                                                      "IMPORTANT! Your game needs to be in vanilla state and have optional DLC/PCC mods installed.\n\n" +
                                                      "Are you sure you want to proceed?", "Textures mapping", MessageBoxButtons.YesNo);
                if (result == DialogResult.No)
                {
                    texEplorer.Close();
                    return("");
                }
            }

            GameData.packageFiles.Sort();
            if (mainWindow != null)
            {
                Misc.startTimer();
            }
            for (int i = 0; i < GameData.packageFiles.Count; i++)
            {
                if (mainWindow != null)
                {
                    mainWindow.updateStatusLabel("Finding textures in package " + (i + 1) + " of " + GameData.packageFiles.Count + " - " + GameData.packageFiles[i]);
                }
                if (installer != null)
                {
                    installer.updateStatusScan("Scanning textures " + (i * 100 / GameData.packageFiles.Count) + "% ");
                }
                errors += FindTextures(textures, GameData.packageFiles[i], cachePackageMgr, ref log);
            }

            if (GameData.gameType == MeType.ME1_TYPE)
            {
                for (int k = 0; k < textures.Count; k++)
                {
                    for (int t = 0; t < textures[k].list.Count; t++)
                    {
                        uint mipmapOffset = textures[k].list[t].mipmapOffset;
                        if (textures[k].list[t].slave)
                        {
                            MatchedTexture slaveTexture = textures[k].list[t];
                            string         basePkgName  = slaveTexture.basePackageName;
                            if (basePkgName == Path.GetFileNameWithoutExtension(slaveTexture.path).ToUpperInvariant())
                            {
                                throw new Exception();
                            }
                            bool found = false;
                            for (int j = 0; j < textures[k].list.Count; j++)
                            {
                                if (!textures[k].list[j].slave &&
                                    textures[k].list[j].mipmapOffset == mipmapOffset &&
                                    textures[k].list[j].packageName == basePkgName)
                                {
                                    slaveTexture.linkToMaster = j;
                                    textures[k].list[t]       = slaveTexture;
                                    found = true;
                                    break;
                                }
                            }
                            if (!found)
                            {
                                log += "Error: not able match 'slave' texture: + " + textures[k].name + " to 'master'.";
                            }
                        }
                    }
                    if (!textures[k].list.Exists(s => s.slave) &&
                        textures[k].list.Exists(s => s.weakSlave))
                    {
                        List <MatchedTexture> texList = new List <MatchedTexture>();
                        for (int t = 0; t < textures[k].list.Count; t++)
                        {
                            MatchedTexture tex = textures[k].list[t];
                            if (tex.weakSlave)
                            {
                                texList.Add(tex);
                            }
                            else
                            {
                                texList.Insert(0, tex);
                            }
                        }
                        FoundTexture f = textures[k];
                        f.list      = texList;
                        textures[k] = f;
                        if (textures[k].list[0].weakSlave)
                        {
                            continue;
                        }

                        for (int t = 0; t < textures[k].list.Count; t++)
                        {
                            if (textures[k].list[t].weakSlave)
                            {
                                MatchedTexture slaveTexture = textures[k].list[t];
                                string         basePkgName  = slaveTexture.basePackageName;
                                if (basePkgName == Path.GetFileNameWithoutExtension(slaveTexture.path).ToUpperInvariant())
                                {
                                    throw new Exception();
                                }
                                for (int j = 0; j < textures[k].list.Count; j++)
                                {
                                    if (!textures[k].list[j].weakSlave &&
                                        textures[k].list[j].packageName == basePkgName)
                                    {
                                        slaveTexture.linkToMaster = j;
                                        textures[k].list[t]       = slaveTexture;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }

            using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write))
            {
                MemoryStream mem = new MemoryStream();
                mem.WriteUInt32(TexExplorer.textureMapBinTag);
                mem.WriteUInt32(TexExplorer.textureMapBinVersion);
                mem.WriteInt32(textures.Count);
                for (int i = 0; i < textures.Count; i++)
                {
                    mem.WriteInt32(textures[i].name.Length);
                    mem.WriteStringASCII(textures[i].name);
                    mem.WriteUInt32(textures[i].crc);
                    if (generateBuiltinMapFiles)
                    {
                        mem.WriteInt32(textures[i].width);
                        mem.WriteInt32(textures[i].height);
                        mem.WriteInt32((int)textures[i].pixfmt);
                        mem.WriteInt32(textures[i].alphadxt1 ? 1 : 0);
                        mem.WriteInt32(textures[i].numMips);
                    }
                    mem.WriteInt32(textures[i].list.Count);
                    for (int k = 0; k < textures[i].list.Count; k++)
                    {
                        mem.WriteInt32(textures[i].list[k].exportID);
                        mem.WriteInt32(textures[i].list[k].linkToMaster);
                        mem.WriteInt32(textures[i].list[k].path.Length);
                        mem.WriteStringASCII(textures[i].list[k].path);
                    }
                }
                if (!generateBuiltinMapFiles)
                {
                    mem.WriteInt32(GameData.packageFiles.Count);
                    for (int i = 0; i < GameData.packageFiles.Count; i++)
                    {
                        string s = GameData.RelativeGameData(GameData.packageFiles[i]);
                        mem.WriteInt32(s.Length);
                        mem.WriteStringASCII(s);
                    }
                }
                mem.SeekBegin();

                if (generateBuiltinMapFiles)
                {
                    fs.WriteUInt32(0x504D5443);
                    fs.WriteUInt32((uint)mem.Length);
                    byte[] compressed = new ZlibHelper.Zlib().Compress(mem.ToArray(), 9);
                    fs.WriteUInt32((uint)compressed.Length);
                    fs.WriteFromBuffer(compressed);
                }
                else
                {
                    fs.WriteFromStream(mem, mem.Length);
                }
            }

            if (mainWindow != null)
            {
                if (!generateBuiltinMapFiles)
                {
                    MipMaps mipmaps = new MipMaps();
                    if (GameData.gameType == MeType.ME1_TYPE)
                    {
                        errors += mipmaps.removeMipMapsME1(1, textures, null, mainWindow, null);
                        errors += mipmaps.removeMipMapsME1(2, textures, null, mainWindow, null);
                    }
                    else
                    {
                        errors += mipmaps.removeMipMapsME2ME3(textures, null, mainWindow, null);
                    }
                }

                var time = Misc.stopTimer();
                mainWindow.updateStatusLabel("Done. Process total time: " + Misc.getTimerFormat(time));
                mainWindow.updateStatusLabel2("");
            }
            treeScan = textures;
            return(errors);
        }
        private string processTextureMod(string filenameMod, int previewIndex, bool extract, bool replace, bool verify, string outDir, List <FoundTexture> textures, CachePackageMgr cachePackageMgr, TexExplorer texExplorer, ref string log)
        {
            string errors = "";

            if (filenameMod.EndsWith(".tpf", StringComparison.OrdinalIgnoreCase))
            {
                if (!replace && !extract)
                {
                    throw new Exception();
                }

                int            result;
                string         fileName   = "";
                ulong          dstLen     = 0;
                string[]       ddsList    = null;
                ulong          numEntries = 0;
                IntPtr         handle     = IntPtr.Zero;
                ZlibHelper.Zip zip        = new ZlibHelper.Zip();
                try
                {
                    int indexTpf = -1;
                    handle = zip.Open(filenameMod, ref numEntries, 1);
                    for (ulong i = 0; i < numEntries; i++)
                    {
                        result   = zip.GetCurrentFileInfo(handle, ref fileName, ref dstLen);
                        fileName = fileName.Trim();
                        if (result != 0)
                        {
                            throw new Exception();
                        }
                        if (Path.GetExtension(fileName).ToLowerInvariant() == ".def" ||
                            Path.GetExtension(fileName).ToLowerInvariant() == ".log")
                        {
                            indexTpf = (int)i;
                            break;
                        }
                        result = zip.GoToNextFile(handle);
                        if (result != 0)
                        {
                            throw new Exception();
                        }
                    }
                    byte[] listText = new byte[dstLen];
                    result = zip.ReadCurrentFile(handle, listText, dstLen);
                    if (result != 0)
                    {
                        throw new Exception();
                    }
                    ddsList = Encoding.ASCII.GetString(listText).Trim('\0').Replace("\r", "").TrimEnd('\n').Split('\n');

                    result = zip.GoToFirstFile(handle);
                    if (result != 0)
                    {
                        throw new Exception();
                    }

                    for (uint i = 0; i < numEntries; i++)
                    {
                        if (i == indexTpf)
                        {
                            result = zip.GoToNextFile(handle);
                            continue;
                        }
                        try
                        {
                            uint crc = 0;
                            result = zip.GetCurrentFileInfo(handle, ref fileName, ref dstLen);
                            if (result != 0)
                            {
                                throw new Exception();
                            }
                            fileName = fileName.Trim();
                            foreach (string dds in ddsList)
                            {
                                string ddsFile = dds.Split('|')[1];
                                if (ddsFile.ToLowerInvariant().Trim() != fileName.ToLowerInvariant())
                                {
                                    continue;
                                }
                                crc = uint.Parse(dds.Split('|')[0].Substring(2), System.Globalization.NumberStyles.HexNumber);
                                break;
                            }
                            string filename = Path.GetFileName(fileName);
                            if (crc == 0)
                            {
                                log    += "Skipping file: " + filename + " not found in definition file, entry: " + (i + 1) + " - mod: " + filenameMod + Environment.NewLine;
                                errors += "Skipping file: " + filename + " not found in definition file, entry: " + (i + 1) + " - mod: " + filenameMod + Environment.NewLine;
                                zip.GoToNextFile(handle);
                                continue;
                            }

                            FoundTexture foundTexture = textures.Find(s => s.crc == crc);
                            if (foundTexture.crc != 0)
                            {
                                byte[] data = new byte[dstLen];
                                result = zip.ReadCurrentFile(handle, data, dstLen);
                                if (result != 0)
                                {
                                    log    += "Error in texture: " + foundTexture.name + string.Format("_0x{0:X8}", crc) + ", skipping texture, entry: " + (i + 1) + " - mod: " + filenameMod + Environment.NewLine;
                                    errors += "Error in texture: " + foundTexture.name + string.Format("_0x{0:X8}", crc) + ", skipping texture, entry: " + (i + 1) + " - mod: " + filenameMod + Environment.NewLine;
                                    zip.GoToNextFile(handle);
                                    continue;
                                }
                                if (texExplorer != null)
                                {
                                    texExplorer._mainWindow.updateStatusLabel("Processing MOD " + Path.GetFileName(filenameMod) +
                                                                              " - File " + (i + 1) + " of " + numEntries + " - " + foundTexture.name);
                                }
                                if (extract)
                                {
                                    string name = foundTexture.name + "_" + string.Format("0x{0:X8}", crc) + Path.GetExtension(fileName);
                                    using (FileStream output = new FileStream(Path.Combine(outDir, name), FileMode.Create, FileAccess.Write))
                                    {
                                        output.Write(data, 0, (int)dstLen);
                                    }
                                }
                                else
                                {
                                    Image image = new Image(data, Path.GetExtension(filename));
                                    errors += replaceTexture(image, foundTexture.list, cachePackageMgr, foundTexture.name, crc, verify);
                                }
                            }
                            else
                            {
                                log += "Texture skipped. File " + filename + string.Format(" - 0x{0:X8}", crc) + " is not present in your game setup - mod: " + filenameMod + Environment.NewLine;
                                zip.GoToNextFile(handle);
                                continue;
                            }
                        }
                        catch
                        {
                            log    += "Skipping not compatible content, entry: " + (i + 1) + " file: " + fileName + " - mod: " + filenameMod + Environment.NewLine;
                            errors += "Skipping not compatible content, entry: " + (i + 1) + " file: " + fileName + " - mod: " + filenameMod + Environment.NewLine;
                        }
                        result = zip.GoToNextFile(handle);
                    }
                    zip.Close(handle);
                    handle = IntPtr.Zero;
                }
                catch
                {
                    log    += "Mod is not compatible: " + filenameMod + Environment.NewLine;
                    errors += "Mod is not compatible: " + filenameMod + Environment.NewLine;
                    if (handle != IntPtr.Zero)
                    {
                        zip.Close(handle);
                    }
                    handle = IntPtr.Zero;
                }
                return(errors);
            }
            else if (filenameMod.EndsWith(".mod", StringComparison.OrdinalIgnoreCase))
            {
                if (!replace && !extract)
                {
                    throw new Exception();
                }

                try
                {
                    using (FileStream fs = new FileStream(filenameMod, FileMode.Open, FileAccess.Read))
                    {
                        string package = "";
                        int    len     = fs.ReadInt32();
                        string version = fs.ReadStringASCIINull();
                        if (version.Length < 5) // legacy .mod
                        {
                            fs.SeekBegin();
                        }
                        else
                        {
                            fs.SeekBegin();
                            len     = fs.ReadInt32();
                            version = fs.ReadStringASCII(len); // version
                        }
                        uint numEntries = fs.ReadUInt32();
                        for (uint i = 0; i < numEntries; i++)
                        {
                            TexExplorer.BinaryMod mod = new TexExplorer.BinaryMod();
                            len = fs.ReadInt32();
                            string desc = fs.ReadStringASCII(len); // description
                            len = fs.ReadInt32();
                            string scriptLegacy = fs.ReadStringASCII(len);
                            string path         = "";
                            if (desc.Contains("Binary Replacement"))
                            {
                                try
                                {
                                    Misc.ParseME3xBinaryScriptMod(scriptLegacy, ref package, ref mod.exportId, ref path);
                                    if (mod.exportId == -1 || package == "" || path == "")
                                    {
                                        throw new Exception();
                                    }
                                }
                                catch
                                {
                                    len = fs.ReadInt32();
                                    fs.Skip(len);
                                    errors += "Skipping not compatible content, entry: " + (i + 1) + " - mod: " + filenameMod + Environment.NewLine;
                                    continue;
                                }
                                mod.packagePath = Path.Combine(GameData.GamePath + path, package);
                                len             = fs.ReadInt32();
                                mod.data        = fs.ReadToBuffer(len);

                                if (!File.Exists(mod.packagePath))
                                {
                                    errors += "Warning: File " + mod.packagePath + " not exists in your game setup." + Environment.NewLine;
                                    log    += "Warning: File " + mod.packagePath + " not exists in your game setup." + Environment.NewLine;
                                    continue;
                                }
                                Package pkg = cachePackageMgr.OpenPackage(mod.packagePath);
                                pkg.setExportData(mod.exportId, mod.data);
                            }
                            else
                            {
                                string       textureName = desc.Split(' ').Last();
                                FoundTexture f;
                                try
                                {
                                    f = Misc.ParseLegacyMe3xScriptMod(textures, scriptLegacy, textureName);
                                    mod.textureCrc = f.crc;
                                    if (mod.textureCrc == 0)
                                    {
                                        throw new Exception();
                                    }
                                }
                                catch
                                {
                                    len = fs.ReadInt32();
                                    fs.Skip(len);
                                    errors += "Skipping not compatible content, entry: " + (i + 1) + " - mod: " + filenameMod + Environment.NewLine;
                                    continue;
                                }
                                textureName     = f.name;
                                mod.textureName = textureName;
                                len             = fs.ReadInt32();
                                mod.data        = fs.ReadToBuffer(len);

                                PixelFormat pixelFormat = f.pixfmt;
                                Image       image       = new Image(mod.data, Image.ImageFormat.DDS);
                                errors += replaceTexture(image, f.list, cachePackageMgr, f.name, f.crc, verify);
                            }
                        }
                    }
                }
                catch
                {
                    errors += "Mod is not compatible: " + filenameMod + Environment.NewLine;
                }
                return(errors);
            }

            using (FileStream fs = new FileStream(filenameMod, FileMode.Open, FileAccess.Read))
            {
                if (previewIndex == -1 && !extract && !replace)
                {
                    texExplorer.listViewTextures.BeginUpdate();
                }
                uint tag     = fs.ReadUInt32();
                uint version = fs.ReadUInt32();
                if (tag != TexExplorer.TextureModTag || version != TexExplorer.TextureModVersion)
                {
                    if (version != TexExplorer.TextureModVersion)
                    {
                        errors += "File " + filenameMod + " was made with an older version of MEM, skipping..." + Environment.NewLine;
                        log    += "File " + filenameMod + " was made with an older version of MEM, skipping..." + Environment.NewLine;
                    }
                    else
                    {
                        errors += "File " + filenameMod + " is not a valid MEM mod, skipping..." + Environment.NewLine;
                        log    += "File " + filenameMod + " is not a valid MEM mod, skipping..." + Environment.NewLine;
                    }
                    if (previewIndex == -1 && !extract && !replace)
                    {
                        texExplorer.listViewTextures.EndUpdate();
                    }
                    return(errors);
                }
                else
                {
                    uint gameType = 0;
                    fs.JumpTo(fs.ReadInt64());
                    gameType = fs.ReadUInt32();
                    if (textures != null && (MeType)gameType != GameData.gameType)
                    {
                        errors += "File " + filenameMod + " is not a MEM mod valid for this game" + Environment.NewLine;
                        log    += "File " + filenameMod + " is not a MEM mod valid for this game" + Environment.NewLine;
                        if (previewIndex == -1 && !extract && !replace)
                        {
                            texExplorer.listViewTextures.EndUpdate();
                        }
                        return(errors);
                    }
                }
                int            numFiles = fs.ReadInt32();
                List <FileMod> modFiles = new List <FileMod>();
                for (int i = 0; i < numFiles; i++)
                {
                    FileMod fileMod = new FileMod();
                    fileMod.tag    = fs.ReadUInt32();
                    fileMod.name   = fs.ReadStringASCIINull();
                    fileMod.offset = fs.ReadInt64();
                    fileMod.size   = fs.ReadInt64();
                    modFiles.Add(fileMod);
                }
                numFiles = modFiles.Count;

                for (int i = 0; i < numFiles; i++)
                {
                    string name = "";
                    uint   crc = 0;
                    long   size = 0, dstLen = 0;
                    int    exportId = -1;
                    string pkgPath  = "";
                    byte[] dst      = null;
                    if (previewIndex != -1)
                    {
                        i = previewIndex;
                    }
                    fs.JumpTo(modFiles[i].offset);
                    size = modFiles[i].size;
                    if (modFiles[i].tag == FileTextureTag)
                    {
                        name = fs.ReadStringASCIINull();
                        crc  = fs.ReadUInt32();
                    }
                    else if (modFiles[i].tag == FileBinaryTag)
                    {
                        name     = modFiles[i].name;
                        exportId = fs.ReadInt32();
                        pkgPath  = fs.ReadStringASCIINull();
                    }

                    if (texExplorer != null)
                    {
                        texExplorer._mainWindow.updateStatusLabel("Processing MOD " + Path.GetFileName(filenameMod) +
                                                                  " - File " + (i + 1) + " of " + numFiles + " - " + name);
                    }

                    if (previewIndex == -1 && !extract && !replace)
                    {
                        if (modFiles[i].tag == FileTextureTag)
                        {
                            FoundTexture foundTexture;
                            foundTexture = textures.Find(s => s.crc == crc);
                            if (foundTexture.crc != 0)
                            {
                                ListViewItem item = new ListViewItem(foundTexture.name + " (" + Path.GetFileNameWithoutExtension(foundTexture.list[0].path).ToUpperInvariant() + ")");
                                item.Name = i.ToString();
                                texExplorer.listViewTextures.Items.Add(item);
                            }
                            else
                            {
                                ListViewItem item = new ListViewItem(name + " (Texture not found: " + name + string.Format("_0x{0:X8}", crc) + ")");
                                item.Name = i.ToString();
                                texExplorer.listViewTextures.Items.Add(item);
                                log += "Texture skipped. Texture " + name + string.Format("_0x{0:X8}", crc) + " is not present in your game setup" + Environment.NewLine;
                            }
                        }
                        else if (modFiles[i].tag == FileBinaryTag)
                        {
                            ListViewItem item = new ListViewItem(name + " (Binary Mod)");
                            item.Name = i.ToString();
                            texExplorer.listViewTextures.Items.Add(item);
                        }
                        else
                        {
                            ListViewItem item = new ListViewItem(name + " (Unknown)");
                            item.Name = i.ToString();
                            errors   += "Unknown tag for file: " + name + Environment.NewLine;
                            log      += "Unknown tag for file: " + name + Environment.NewLine;
                        }
                        continue;
                    }

                    dst    = decompressData(fs, size);
                    dstLen = dst.Length;

                    if (extract)
                    {
                        if (modFiles[i].tag == FileTextureTag)
                        {
                            string filename = name + "_" + string.Format("0x{0:X8}", crc) + ".dds";
                            using (FileStream output = new FileStream(Path.Combine(outDir, Path.GetFileName(filename)), FileMode.Create, FileAccess.Write))
                            {
                                output.Write(dst, 0, (int)dstLen);
                            }
                        }
                        else if (modFiles[i].tag == FileBinaryTag)
                        {
                            string path = pkgPath;
                            string newFilename;
                            if (path.Contains("\\DLC\\"))
                            {
                                string dlcName = path.Split('\\')[3];
                                newFilename = "D" + dlcName.Length + "-" + dlcName + "-";
                            }
                            else
                            {
                                newFilename = "B";
                            }
                            newFilename += Path.GetFileName(path).Length + "-" + Path.GetFileName(path) + "-E" + exportId + ".bin";
                            using (FileStream output = new FileStream(Path.Combine(outDir, newFilename), FileMode.Create, FileAccess.Write))
                            {
                                output.Write(dst, 0, (int)dstLen);
                            }
                        }
                        else
                        {
                            errors += "Unknown tag for file: " + name + Environment.NewLine;
                            log    += "Unknown tag for file: " + name + Environment.NewLine;
                        }
                        continue;
                    }

                    if (previewIndex != -1)
                    {
                        if (modFiles[i].tag == FileTextureTag)
                        {
                            Image image = new Image(dst, Image.ImageFormat.DDS);
                            texExplorer.pictureBoxPreview.Image = image.getBitmapARGB();
                        }
                        else
                        {
                            texExplorer.pictureBoxPreview.Image = null;
                        }
                        break;
                    }
                    else if (replace)
                    {
                        if (modFiles[i].tag == FileTextureTag)
                        {
                            FoundTexture foundTexture;
                            foundTexture = textures.Find(s => s.crc == crc);
                            if (foundTexture.crc != 0)
                            {
                                Image image = new Image(dst, Image.ImageFormat.DDS);
                                errors += replaceTexture(image, foundTexture.list, cachePackageMgr, foundTexture.name, crc, verify);
                            }
                            else
                            {
                                log += "Error: Texture " + name + string.Format("_0x{0:X8}", crc) + "is not present in your game setup. Texture skipped." + Environment.NewLine;
                            }
                        }
                        else if (modFiles[i].tag == FileBinaryTag)
                        {
                            string path = GameData.GamePath + pkgPath;
                            if (!File.Exists(path))
                            {
                                errors += "Warning: File " + path + " not exists in your game setup." + Environment.NewLine;
                                log    += "Warning: File " + path + " not exists in your game setup." + Environment.NewLine;
                                continue;
                            }
                            Package pkg = cachePackageMgr.OpenPackage(path);
                            pkg.setExportData(exportId, dst);
                        }
                        else
                        {
                            errors += "Error: Unknown tag for file: " + name + Environment.NewLine;
                            log    += "Error: Unknown tag for file: " + name + Environment.NewLine;
                        }
                    }
                    else
                    {
                        throw new Exception();
                    }
                }
                if (previewIndex == -1 && !extract && !replace)
                {
                    texExplorer.listViewTextures.EndUpdate();
                }
            }
            return(errors);
        }
Esempio n. 10
0
        public string PrepareListOfTextures(MeType gameId, TexExplorer texEplorer, MainWindow mainWindow, Installer installer, ref string log, bool ipc)
        {
            string errors = "";

            treeScan = null;
            Misc.MD5FileEntry[] md5Entries;
            if (gameId == MeType.ME1_TYPE)
            {
                pkgs       = Program.tablePkgsME1;
                md5Entries = Program.entriesME1;
            }
            else if (gameId == MeType.ME2_TYPE)
            {
                pkgs       = Program.tablePkgsME2;
                md5Entries = Program.entriesME2;
            }
            else
            {
                pkgs       = Program.tablePkgsME3;
                md5Entries = Program.entriesME3;
            }

            List <FoundTexture> textures = new List <FoundTexture>();
            string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
                                       Assembly.GetExecutingAssembly().GetName().Name);

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            string filename = Path.Combine(path, "me" + (int)gameId + "map.bin");

            if (mainWindow != null)
            {
                if (File.Exists(filename))
                {
                    using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.ReadWrite))
                    {
                        uint tag     = fs.ReadUInt32();
                        uint version = fs.ReadUInt32();
                        if (tag != textureMapBinTag || version != textureMapBinVersion)
                        {
                            MessageBox.Show("Detected wrong or old version of textures scan file!" +
                                            "\n\nYou need to restore the game to vanilla state then reinstall optional DLC/PCC mods." +
                                            "\n\nThen from the main menu, select 'Remove Textures Scan File' and start Texture Manager again.");
                            mainWindow.updateStatusLabel("");
                            mainWindow.updateStatusLabel2("");
                            texEplorer.Close();
                            fs.Close();
                            log += "Detected wrong or old version of textures scan file!" + Environment.NewLine;
                            log += "You need to restore the game to vanilla state then reinstall optional DLC/PCC mods." + Environment.NewLine;
                            log += "Then from the main menu, select 'Remove Textures Scan File' and start Texture Manager again." + Environment.NewLine;
                            return("Detected wrong or old version of textures scan file!" + Environment.NewLine +
                                   "You need to restore the game to vanilla state then reinstall optional DLC/PCC mods." + Environment.NewLine +
                                   "Then from the main menu, select 'Remove Textures Scan File' and start Texture Manager again." + Environment.NewLine);
                        }

                        uint countTexture = fs.ReadUInt32();
                        for (int i = 0; i < countTexture; i++)
                        {
                            FoundTexture texture = new FoundTexture();
                            int          len     = fs.ReadInt32();
                            texture.name = fs.ReadStringASCII(len);
                            texture.crc  = fs.ReadUInt32();
                            uint countPackages = fs.ReadUInt32();
                            texture.list = new List <MatchedTexture>();
                            for (int k = 0; k < countPackages; k++)
                            {
                                MatchedTexture matched = new MatchedTexture();
                                matched.exportID     = fs.ReadInt32();
                                matched.linkToMaster = fs.ReadInt32();
                                len          = fs.ReadInt32();
                                matched.path = fs.ReadStringASCII(len);
                                texture.list.Add(matched);
                            }
                            textures.Add(texture);
                        }

                        List <string> packages    = new List <string>();
                        int           numPackages = fs.ReadInt32();
                        for (int i = 0; i < numPackages; i++)
                        {
                            int    len     = fs.ReadInt32();
                            string pkgPath = fs.ReadStringASCII(len);
                            pkgPath = GameData.GamePath + pkgPath;
                            packages.Add(pkgPath);
                        }
                        for (int i = 0; i < packages.Count; i++)
                        {
                            if (GameData.packageFiles.Find(s => s.Equals(packages[i], StringComparison.OrdinalIgnoreCase)) == null)
                            {
                                MessageBox.Show("Detected removal of game files since last game data scan." +
                                                "\n\nYou need to restore the game to vanilla state then reinstall optional DLC/PCC mods." +
                                                "\n\nThen from the main menu, select 'Remove Textures Scan File' and start Texture Manager again.");
                                return("");
                            }
                        }
                        for (int i = 0; i < GameData.packageFiles.Count; i++)
                        {
                            if (packages.Find(s => s.Equals(GameData.packageFiles[i], StringComparison.OrdinalIgnoreCase)) == null)
                            {
                                MessageBox.Show("Detected additional game files not present in latest game data scan." +
                                                "\n\nYou need to restore the game to vanilla state then reinstall optional DLC/PCC mods." +
                                                "\n\nThen from the main menu, select 'Remove Textures Scan File' and start Texture Manager again.");
                                return("");
                            }
                        }

                        treeScan = textures;
                        mainWindow.updateStatusLabel("");
                        mainWindow.updateStatusLabel2("");
                    }
                    if (!texEplorer.verifyGameDataEmptyMipMapsRemoval())
                    {
                        MessageBox.Show("Detected empty mips in game files." +
                                        "\n\nYou need the game in vanilla state and optional DLC/PCC mods." +
                                        "\n\nThen from the main menu, select 'Remove Textures Scan File' and start Texture Manager again.");
                        return("");
                    }
                    return(errors);
                }

                if (mainWindow != null)
                {
                    List <string> badMods = Misc.detectBrokenMod(GameData.gameType);
                    if (badMods.Count != 0)
                    {
                        errors = "";
                        for (int l = 0; l < badMods.Count; l++)
                        {
                            errors += badMods[l] + Environment.NewLine;
                        }
                        MessageBox.Show("Detected not compatible mods: \n\n" + errors);
                        return("");
                    }

                    List <string> mods = Misc.detectMods(GameData.gameType);
                    if (mods.Count != 0 && GameData.gameType == MeType.ME1_TYPE && GameData.FullScanME1Game)
                    {
                        errors = "";
                        for (int l = 0; l < mods.Count; l++)
                        {
                            errors += mods[l] + Environment.NewLine;
                        }
                        DialogResult resp = MessageBox.Show("Detected NOT compatible/supported mods with this version of game: \n\n" + errors +
                                                            "\n\nPress Cancel to abort or press Ok button to continue.", "Warning !", MessageBoxButtons.OKCancel);
                        if (resp == DialogResult.Cancel)
                        {
                            return("");
                        }
                    }
                }

                DialogResult result = MessageBox.Show("Replacing textures and creating mods requires generating a map of the game's textures.\n" +
                                                      "You only need to do it once.\n\n" +
                                                      "IMPORTANT! Your game needs to be in vanilla state and have optional DLC/PCC mods installed.\n\n" +
                                                      "Are you sure you want to proceed?", "Textures mapping", MessageBoxButtons.YesNo);
                if (result == DialogResult.No)
                {
                    texEplorer.Close();
                    return("");
                }

                Misc.startTimer();
            }

            if (!GameData.FullScanME1Game)
            {
                int count = GameData.packageFiles.Count;
                for (int i = 0; i < count; i++)
                {
                    if (GameData.packageFiles[i].Contains("_IT.") ||
                        GameData.packageFiles[i].Contains("_FR.") ||
                        GameData.packageFiles[i].Contains("_ES.") ||
                        GameData.packageFiles[i].Contains("_DE.") ||
                        GameData.packageFiles[i].Contains("_RA.") ||
                        GameData.packageFiles[i].Contains("_RU.") ||
                        GameData.packageFiles[i].Contains("_PLPC.") ||
                        GameData.packageFiles[i].Contains("_DEU.") ||
                        GameData.packageFiles[i].Contains("_FRA.") ||
                        GameData.packageFiles[i].Contains("_ITA.") ||
                        GameData.packageFiles[i].Contains("_POL."))
                    {
                        GameData.packageFiles.Add(GameData.packageFiles[i]);
                        GameData.packageFiles.RemoveAt(i--);
                        count--;
                    }
                }
            }

            if (!generateBuiltinMapFiles && !GameData.FullScanME1Game)
            {
                List <string> addedFiles    = new List <string>();
                List <string> modifiedFiles = new List <string>();

                loadTexturesMap(gameId, textures);

                List <string> sortedFiles = new List <string>();
                for (int i = 0; i < GameData.packageFiles.Count; i++)
                {
                    sortedFiles.Add(GameData.RelativeGameData(GameData.packageFiles[i]).ToLowerInvariant());
                }
                sortedFiles.Sort();

                for (int k = 0; k < textures.Count; k++)
                {
                    for (int t = 0; t < textures[k].list.Count; t++)
                    {
                        string pkgPath = textures[k].list[t].path.ToLowerInvariant();
                        if (sortedFiles.BinarySearch(pkgPath) >= 0)
                        {
                            continue;
                        }
                        MatchedTexture f = textures[k].list[t];
                        f.path = "";
                        textures[k].list[t] = f;
                    }
                }

                if (installer != null)
                {
                    installer.updateProgressStatus("Scanning packages");
                }
                if (mainWindow != null)
                {
                    mainWindow.updateStatusLabel("Scanning packages...");
                }
                if (ipc)
                {
                    Console.WriteLine("[IPC]STAGE_CONTEXT STAGE_SCAN");
                    Console.Out.Flush();
                }
                for (int i = 0; i < GameData.packageFiles.Count; i++)
                {
                    int    index       = -1;
                    bool   modified    = true;
                    bool   foundPkg    = false;
                    string package     = GameData.RelativeGameData(GameData.packageFiles[i].ToLowerInvariant());
                    long   packageSize = new FileInfo(GameData.packageFiles[i]).Length;
                    for (int p = 0; p < md5Entries.Length; p++)
                    {
                        if (package == md5Entries[p].path.ToLowerInvariant())
                        {
                            foundPkg = true;
                            if (packageSize == md5Entries[p].size)
                            {
                                modified = false;
                                break;
                            }
                            index = p;
                        }
                    }
                    if (foundPkg && modified)
                    {
                        modifiedFiles.Add(md5Entries[index].path);
                    }
                    else if (!foundPkg)
                    {
                        addedFiles.Add(GameData.RelativeGameData(GameData.packageFiles[i]));
                    }
                }

                int lastProgress   = -1;
                int totalPackages  = modifiedFiles.Count + addedFiles.Count;
                int currentPackage = 0;
                if (ipc)
                {
                    Console.WriteLine("[IPC]STAGE_WEIGHT STAGE_SCAN " +
                                      string.Format("{0:0.000000}", ((float)totalPackages / GameData.packageFiles.Count)));
                    Console.Out.Flush();
                }
                for (int i = 0; i < modifiedFiles.Count; i++, currentPackage++)
                {
                    if (installer != null)
                    {
                        installer.updateProgressStatus("Scanning textures " + ((currentPackage + 1) * 100) / totalPackages + "% ");
                    }
                    if (mainWindow != null)
                    {
                        mainWindow.updateStatusLabel("Finding textures in package " + (currentPackage + 1) + " of " + totalPackages + " - " + modifiedFiles[i]);
                    }
                    if (ipc)
                    {
                        Console.WriteLine("[IPC]PROCESSING_FILE " + modifiedFiles[i]);
                        int newProgress = currentPackage * 100 / totalPackages;
                        if (lastProgress != newProgress)
                        {
                            Console.WriteLine("[IPC]TASK_PROGRESS " + newProgress);
                            lastProgress = newProgress;
                        }
                        Console.Out.Flush();
                    }
                    errors += FindTextures(gameId, textures, modifiedFiles[i], true, ref log);
                }

                for (int i = 0; i < addedFiles.Count; i++, currentPackage++)
                {
                    if (installer != null)
                    {
                        installer.updateProgressStatus("Scanning textures " + ((currentPackage + 1) * 100) / totalPackages + "% ");
                    }
                    if (mainWindow != null)
                    {
                        mainWindow.updateStatusLabel("Finding textures in package " + (currentPackage + 1) + " of " + totalPackages + " - " + addedFiles[i]);
                    }
                    if (ipc)
                    {
                        Console.WriteLine("[IPC]PROCESSING_FILE " + addedFiles[i]);
                        int newProgress = currentPackage * 100 / totalPackages;
                        if (lastProgress != newProgress)
                        {
                            Console.WriteLine("[IPC]TASK_PROGRESS " + newProgress);
                            lastProgress = newProgress;
                        }
                        Console.Out.Flush();
                    }
                    errors += FindTextures(gameId, textures, addedFiles[i], false, ref log);
                }

                for (int k = 0; k < textures.Count; k++)
                {
                    bool found = false;
                    for (int t = 0; t < textures[k].list.Count; t++)
                    {
                        if (textures[k].list[t].path != "")
                        {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        textures[k].list.Clear();
                        textures.Remove(textures[k]);
                        k--;
                    }
                }
            }
            else
            {
                int lastProgress = -1;
                for (int i = 0; i < GameData.packageFiles.Count; i++)
                {
                    if (installer != null)
                    {
                        installer.updateProgressStatus("Scanning textures " + ((i + 1) * 100) / GameData.packageFiles.Count + "% ");
                    }
                    if (mainWindow != null)
                    {
                        mainWindow.updateStatusLabel("Finding textures in package " + (i + 1) + " of " + GameData.packageFiles.Count + " - " + GameData.packageFiles[i]);
                    }
                    if (ipc)
                    {
                        Console.WriteLine("[IPC]PROCESSING_FILE " + GameData.packageFiles[i]);
                        int newProgress = i * 100 / GameData.packageFiles.Count;
                        if (lastProgress != newProgress)
                        {
                            Console.WriteLine("[IPC]TASK_PROGRESS " + newProgress);
                            lastProgress = newProgress;
                        }
                        Console.Out.Flush();
                    }
                    FindTextures(gameId, textures, GameData.RelativeGameData(GameData.packageFiles[i]), false, ref log);
                }
            }

            if (gameId == MeType.ME1_TYPE)
            {
                for (int k = 0; k < textures.Count; k++)
                {
                    for (int t = 0; t < textures[k].list.Count; t++)
                    {
                        uint mipmapOffset = textures[k].list[t].mipmapOffset;
                        if (textures[k].list[t].slave)
                        {
                            MatchedTexture slaveTexture = textures[k].list[t];
                            string         basePkgName  = slaveTexture.basePackageName;
                            if (basePkgName == Path.GetFileNameWithoutExtension(slaveTexture.path).ToUpperInvariant())
                            {
                                throw new Exception();
                            }
                            for (int j = 0; j < textures[k].list.Count; j++)
                            {
                                if (!textures[k].list[j].slave &&
                                    textures[k].list[j].mipmapOffset == mipmapOffset &&
                                    textures[k].list[j].packageName == basePkgName)
                                {
                                    slaveTexture.linkToMaster = j;
                                    slaveTexture.slave        = true;
                                    textures[k].list[t]       = slaveTexture;
                                    break;
                                }
                            }
                        }
                    }
                    if (!textures[k].list.Exists(s => s.slave) &&
                        textures[k].list.Exists(s => s.weakSlave))
                    {
                        List <MatchedTexture> texList = new List <MatchedTexture>();
                        for (int t = 0; t < textures[k].list.Count; t++)
                        {
                            MatchedTexture tex = textures[k].list[t];
                            if (tex.weakSlave)
                            {
                                texList.Add(tex);
                            }
                            else
                            {
                                texList.Insert(0, tex);
                            }
                        }
                        FoundTexture f = textures[k];
                        f.list      = texList;
                        textures[k] = f;
                        if (textures[k].list[0].weakSlave)
                        {
                            continue;
                        }

                        for (int t = 0; t < textures[k].list.Count; t++)
                        {
                            if (textures[k].list[t].weakSlave)
                            {
                                MatchedTexture slaveTexture = textures[k].list[t];
                                string         basePkgName  = slaveTexture.basePackageName;
                                if (basePkgName == Path.GetFileNameWithoutExtension(slaveTexture.path).ToUpperInvariant())
                                {
                                    throw new Exception();
                                }
                                for (int j = 0; j < textures[k].list.Count; j++)
                                {
                                    if (!textures[k].list[j].weakSlave &&
                                        textures[k].list[j].packageName == basePkgName)
                                    {
                                        slaveTexture.linkToMaster = j;
                                        slaveTexture.slave        = true;
                                        textures[k].list[t]       = slaveTexture;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }


            if (File.Exists(filename))
            {
                File.Delete(filename);
            }

            using (FileStream fs = new FileStream(filename, FileMode.Create, FileAccess.Write))
            {
                MemoryStream mem = new MemoryStream();
                mem.WriteUInt32(textureMapBinTag);
                mem.WriteUInt32(textureMapBinVersion);
                mem.WriteInt32(textures.Count);

                for (int i = 0; i < textures.Count; i++)
                {
                    if (generateBuiltinMapFiles)
                    {
                        mem.WriteByte((byte)textures[i].name.Length);
                    }
                    else
                    {
                        mem.WriteInt32(textures[i].name.Length);
                    }
                    mem.WriteStringASCII(textures[i].name);
                    mem.WriteUInt32(textures[i].crc);
                    if (generateBuiltinMapFiles)
                    {
                        mem.WriteInt16((short)textures[i].width);
                        mem.WriteInt16((short)textures[i].height);
                        mem.WriteByte((byte)textures[i].pixfmt);
                        mem.WriteByte((byte)textures[i].flags);

                        mem.WriteInt16((short)textures[i].list.Count);
                    }
                    else
                    {
                        mem.WriteInt32(textures[i].list.Count);
                    }
                    for (int k = 0; k < textures[i].list.Count; k++)
                    {
                        mem.WriteInt32(textures[i].list[k].exportID);
                        if (generateBuiltinMapFiles)
                        {
                            if (GameData.gameType == MeType.ME1_TYPE)
                            {
                                mem.WriteInt16((short)textures[i].list[k].linkToMaster);
                                if (textures[i].list[k].linkToMaster != -1)
                                {
                                    mem.WriteStringASCIINull(textures[i].list[k].basePackageName);
                                }
                            }
                            mem.WriteByte(textures[i].list[k].removeEmptyMips ? (byte)1 : (byte)0);
                            mem.WriteByte((byte)textures[i].list[k].numMips);
                            mem.WriteInt16((short)pkgs.IndexOf(textures[i].list[k].path));
                        }
                        else
                        {
                            mem.WriteInt32(textures[i].list[k].linkToMaster);
                            mem.WriteInt32(textures[i].list[k].path.Length);
                            mem.WriteStringASCII(textures[i].list[k].path);
                        }
                    }
                }
                if (!generateBuiltinMapFiles)
                {
                    mem.WriteInt32(GameData.packageFiles.Count);
                    for (int i = 0; i < GameData.packageFiles.Count; i++)
                    {
                        string s = GameData.RelativeGameData(GameData.packageFiles[i]);
                        mem.WriteInt32(s.Length);
                        mem.WriteStringASCII(s);
                    }
                }
                mem.SeekBegin();

                if (generateBuiltinMapFiles)
                {
                    fs.WriteUInt32(0x504D5443);
                    fs.WriteUInt32((uint)mem.Length);
                    byte[] compressed = new ZlibHelper.Zlib().Compress(mem.ToArray(), 9);
                    fs.WriteUInt32((uint)compressed.Length);
                    fs.WriteFromBuffer(compressed);
                }
                else
                {
                    fs.WriteFromStream(mem, mem.Length);
                }
            }

            if (mainWindow != null)
            {
                if (!generateBuiltinMapFiles)
                {
                    MipMaps mipmaps = new MipMaps();
                    if (GameData.gameType == MeType.ME1_TYPE)
                    {
                        errors += mipmaps.removeMipMapsME1(1, textures, mainWindow, null, false);
                        errors += mipmaps.removeMipMapsME1(2, textures, mainWindow, null, false);
                    }
                    else
                    {
                        errors += mipmaps.removeMipMapsME2ME3(textures, mainWindow, null, false, false);
                    }
                    if (GameData.gameType == MeType.ME3_TYPE)
                    {
                        TOCBinFile.UpdateAllTOCBinFiles();
                    }
                }
            }

            treeScan = textures;

            if (mainWindow != null)
            {
                var time = Misc.stopTimer();
                mainWindow.updateStatusLabel("Done. Process total time: " + Misc.getTimerFormat(time));
                mainWindow.updateStatusLabel2("");
            }

            return(errors);
        }
Esempio n. 11
0
        private string processTextureMod(string filenameMod, int previewIndex, bool extract, bool replace, string outDir, List <FoundTexture> textures, CachePackageMgr cachePackageMgr, TexExplorer texExplorer, ref string log)
        {
            string errors = "";

            using (FileStream fs = new FileStream(filenameMod, FileMode.Open, FileAccess.Read))
            {
                if (previewIndex == -1 && !extract && !replace)
                {
                    texExplorer.listViewTextures.BeginUpdate();
                }
                uint tag     = fs.ReadUInt32();
                uint version = fs.ReadUInt32();
                if (tag != TexExplorer.TextureModTag || version != TexExplorer.TextureModVersion)
                {
                    if (version != TexExplorer.TextureModVersion)
                    {
                        errors += "File " + filenameMod + " was made with an older version of MEM, skipping..." + Environment.NewLine;
                        log    += "File " + filenameMod + " was made with an older version of MEM, skipping..." + Environment.NewLine;
                    }
                    else
                    {
                        errors += "File " + filenameMod + " is not a valid MEM mod, skipping..." + Environment.NewLine;
                        log    += "File " + filenameMod + " is not a valid MEM mod, skipping..." + Environment.NewLine;
                    }
                    if (previewIndex == -1 && !extract && !replace)
                    {
                        texExplorer.listViewTextures.EndUpdate();
                    }
                    return(errors);
                }
                else
                {
                    uint gameType = 0;
                    fs.JumpTo(fs.ReadInt64());
                    gameType = fs.ReadUInt32();
                    if (textures != null && (MeType)gameType != GameData.gameType)
                    {
                        errors += "File " + filenameMod + " is not a MEM mod valid for this game" + Environment.NewLine;
                        log    += "File " + filenameMod + " is not a MEM mod valid for this game" + Environment.NewLine;
                        if (previewIndex == -1 && !extract && !replace)
                        {
                            texExplorer.listViewTextures.EndUpdate();
                        }
                        return(errors);
                    }
                }
                int            numFiles = fs.ReadInt32();
                List <FileMod> modFiles = new List <FileMod>();
                for (int i = 0; i < numFiles; i++)
                {
                    FileMod fileMod = new FileMod();
                    fileMod.tag    = fs.ReadUInt32();
                    fileMod.name   = fs.ReadStringASCIINull();
                    fileMod.offset = fs.ReadInt64();
                    fileMod.size   = fs.ReadInt64();
                    modFiles.Add(fileMod);
                }
                numFiles = modFiles.Count;

                for (int i = 0; i < numFiles; i++)
                {
                    string name = "";
                    uint   crc = 0;
                    long   size = 0, dstLen = 0;
                    int    exportId = -1;
                    string pkgPath  = "";
                    byte[] dst      = null;
                    if (previewIndex != -1)
                    {
                        i = previewIndex;
                    }
                    fs.JumpTo(modFiles[i].offset);
                    size = modFiles[i].size;
                    if (modFiles[i].tag == FileTextureTag)
                    {
                        name = fs.ReadStringASCIINull();
                        crc  = fs.ReadUInt32();
                    }
                    else if (modFiles[i].tag == FileBinaryTag)
                    {
                        name     = modFiles[i].name;
                        exportId = fs.ReadInt32();
                        pkgPath  = fs.ReadStringASCIINull();
                    }

                    if (texExplorer != null)
                    {
                        texExplorer._mainWindow.updateStatusLabel("Processing MOD " + Path.GetFileName(filenameMod) +
                                                                  " - File " + (i + 1) + " of " + numFiles + " - " + name);
                    }

                    if (previewIndex == -1 && !extract && !replace)
                    {
                        if (modFiles[i].tag == FileTextureTag)
                        {
                            FoundTexture foundTexture;
                            foundTexture = textures.Find(s => s.crc == crc);
                            if (foundTexture.crc != 0)
                            {
                                ListViewItem item = new ListViewItem(foundTexture.name + " (" + foundTexture.packageName + ")");
                                item.Name = i.ToString();
                                texExplorer.listViewTextures.Items.Add(item);
                            }
                            else
                            {
                                ListViewItem item = new ListViewItem(name + " (Texture not found: " + name + string.Format("_0x{0:X8}", crc) + ")");
                                item.Name = i.ToString();
                                texExplorer.listViewTextures.Items.Add(item);
                                log += "Texture skipped. Texture " + name + string.Format("_0x{0:X8}", crc) + " is not present in your game setup" + Environment.NewLine;
                            }
                        }
                        else if (modFiles[i].tag == FileBinaryTag)
                        {
                            ListViewItem item = new ListViewItem(name + " (Binary Mod)");
                            item.Name = i.ToString();
                            texExplorer.listViewTextures.Items.Add(item);
                        }
                        else
                        {
                            ListViewItem item = new ListViewItem(name + " (Unknown)");
                            item.Name = i.ToString();
                            errors   += "Unknown tag for file: " + name + Environment.NewLine;
                            log      += "Unknown tag for file: " + name + Environment.NewLine;
                        }
                        continue;
                    }

                    dst    = decompressData(fs, size);
                    dstLen = dst.Length;

                    if (extract)
                    {
                        if (modFiles[i].tag == FileTextureTag)
                        {
                            string filename = name + "_" + string.Format("0x{0:X8}", crc) + ".dds";
                            using (FileStream output = new FileStream(Path.Combine(outDir, Path.GetFileName(filename)), FileMode.Create, FileAccess.Write))
                            {
                                output.Write(dst, 0, (int)dstLen);
                            }
                        }
                        else if (modFiles[i].tag == FileBinaryTag)
                        {
                            string filename = name;
                            using (FileStream output = new FileStream(Path.Combine(outDir, Path.GetFileName(filename)), FileMode.Create, FileAccess.Write))
                            {
                                output.Write(dst, 0, (int)dstLen);
                            }
                        }
                        else
                        {
                            errors += "Unknown tag for file: " + name + Environment.NewLine;
                            log    += "Unknown tag for file: " + name + Environment.NewLine;
                        }
                        continue;
                    }

                    if (previewIndex != -1)
                    {
                        if (modFiles[i].tag == FileTextureTag)
                        {
                            DDSImage image = new DDSImage(new MemoryStream(dst, 0, (int)dstLen));
                            texExplorer.pictureBoxPreview.Image = image.mipMaps[0].bitmap;
                        }
                        else
                        {
                            texExplorer.pictureBoxPreview.Image = null;
                        }
                        break;
                    }
                    else if (replace)
                    {
                        if (modFiles[i].tag == FileTextureTag)
                        {
                            FoundTexture foundTexture;
                            foundTexture = textures.Find(s => s.crc == crc);
                            if (foundTexture.crc != 0)
                            {
                                DDSImage image = new DDSImage(new MemoryStream(dst, 0, (int)dstLen));
                                if (!image.checkExistAllMipmaps())
                                {
                                    errors += "Error in texture: " + name + string.Format("_0x{0:X8}", crc) + " Texture skipped. This texture has not all the required mipmaps." + Environment.NewLine;
                                    log    += "Error in texture: " + name + string.Format("_0x{0:X8}", crc) + " Texture skipped. This texture has not all the required mipmaps." + Environment.NewLine;
                                    continue;
                                }
                                errors += replaceTexture(image, foundTexture.list, cachePackageMgr, foundTexture.name, crc);
                            }
                            else
                            {
                                log += "Error: Texture " + name + string.Format("_0x{0:X8}", crc) + "is not present in your game setup. Texture skipped." + Environment.NewLine;
                            }
                        }
                        else if (modFiles[i].tag == FileBinaryTag)
                        {
                            string path = GameData.GamePath + pkgPath;
                            if (!File.Exists(path))
                            {
                                errors += "Warning: File " + path + " not exists in your game setup." + Environment.NewLine;
                                log    += "Warning: File " + path + " not exists in your game setup." + Environment.NewLine;
                                continue;
                            }
                            Package pkg = cachePackageMgr.OpenPackage(path);
                            pkg.setExportData(exportId, dst);
                        }
                        else
                        {
                            errors += "Error: Unknown tag for file: " + name + Environment.NewLine;
                            log    += "Error: Unknown tag for file: " + name + Environment.NewLine;
                        }
                    }
                    else
                    {
                        throw new Exception();
                    }
                }
                if (previewIndex == -1 && !extract && !replace)
                {
                    texExplorer.listViewTextures.EndUpdate();
                }
            }
            return(errors);
        }
Esempio n. 12
0
 public string replaceTextureMod(string filenameMod, List <FoundTexture> textures, CachePackageMgr cachePackageMgr, TexExplorer texExplorer, ref string log)
 {
     return(processTextureMod(filenameMod, -1, false, true, "", textures, cachePackageMgr, texExplorer, ref log));
 }