static private bool loadTexturesMap(string path, List <FoundTexture> textures)
        {
            if (!File.Exists(path))
            {
                Console.WriteLine("Texture map not exist: " + path);
                return(false);
            }
            using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                uint tag     = fs.ReadUInt32();
                uint version = fs.ReadUInt32();
                if (tag != TexExplorer.textureMapBinTag || version != TexExplorer.textureMapBinVersion)
                {
                    Console.WriteLine("Texture map not compatible: " + path);
                    return(false);
                }

                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);
                }
            }

            return(true);
        }
        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 FindTextures(List <FoundTexture> textures, string packagePath, CachePackageMgr cachePackageMgr, ref string log)
        {
            string  errors  = "";
            Package package = null;

            try
            {
                if (cachePackageMgr != null)
                {
                    package = cachePackageMgr.OpenPackage(packagePath);
                }
                else
                {
                    package = new Package(packagePath);
                }
            }
            catch (Exception e)
            {
                string err = "";
                err    += "---- Start --------------------------------------------" + Environment.NewLine;
                err    += "Issue with open package file: " + packagePath + Environment.NewLine;
                err    += e.Message + Environment.NewLine + Environment.NewLine;
                err    += e.StackTrace + Environment.NewLine + Environment.NewLine;
                err    += "---- End ----------------------------------------------" + Environment.NewLine + Environment.NewLine;
                errors += err;
                log    += err;
                return(errors);
            }
            for (int i = 0; i < package.exportsTable.Count; i++)
            {
                int id = package.getClassNameId(package.exportsTable[i].classId);
                if (id == package.nameIdTexture2D ||
                    id == package.nameIdLightMapTexture2D ||
                    id == package.nameIdShadowMapTexture2D ||
                    id == package.nameIdTextureFlipBook)
                {
                    Texture texture = new Texture(package, i, package.getExportData(i));
                    if (!texture.hasImageData())
                    {
                        continue;
                    }

                    Texture.MipMap mipmap       = texture.getTopMipmap();
                    string         name         = package.exportsTable[i].objectName;
                    MatchedTexture matchTexture = new MatchedTexture();
                    bool           slave        = false;
                    matchTexture.exportID = i;
                    matchTexture.path     = GameData.RelativeGameData(packagePath);
                    if (GameData.gameType != MeType.ME1_TYPE)
                    {
                        slave = true;
                    }
                    else
                    if (texture.packageName.ToLowerInvariant() != Path.GetFileNameWithoutExtension(package.packageFile.Name).ToLowerInvariant())
                    {
                        slave = true;
                    }

                    uint crc = texture.getCrcTopMipmap();
                    if (crc == 0)
                    {
                        errors += "Error: Texture " + package.exportsTable[i].objectName + " is broken in package: " + packagePath + ", skipping..." + Environment.NewLine;
                        log    += "Error: Texture " + package.exportsTable[i].objectName + " is broken in package: " + packagePath + ", skipping..." + Environment.NewLine;
                        continue;
                    }

                    FoundTexture foundTexName = textures.Find(s => s.crc == crc);
                    if (foundTexName.crc != 0)
                    {
                        if (slave)
                        {
                            foundTexName.list.Add(matchTexture);
                        }
                        else
                        {
                            foundTexName.list.Insert(0, matchTexture);
                        }
                    }
                    else
                    {
                        FoundTexture foundTex = new FoundTexture();
                        foundTex.list = new List <MatchedTexture>();
                        foundTex.list.Add(matchTexture);
                        foundTex.name        = name;
                        foundTex.crc         = crc;
                        foundTex.packageName = texture.packageName;
                        textures.Add(foundTex);
                    }
                }
            }
            if (cachePackageMgr == null)
            {
                package.Dispose();
            }
            else
            {
                package.DisposeCache();
            }

            return(errors);
        }
Example #4
0
        public void loadTexturesMap(MeType gameId, List <FoundTexture> textures)
        {
            Stream fs;

            byte[] buffer = null;
            if (gameId == MeType.ME1_TYPE)
            {
                pkgs = Program.tablePkgsME1;
            }
            else if (gameId == MeType.ME2_TYPE)
            {
                pkgs = Program.tablePkgsME2;
            }
            else
            {
                pkgs = Program.tablePkgsME3;
            }
            Assembly assembly = Assembly.GetExecutingAssembly();

            string[] resources = assembly.GetManifestResourceNames();
            for (int l = 0; l < resources.Length; l++)
            {
                if (resources[l].Contains("me" + (int)gameId + "map.bin"))
                {
                    using (Stream s = Assembly.GetEntryAssembly().GetManifestResourceStream(resources[l]))
                    {
                        buffer = s.ReadToBuffer(s.Length);
                        break;
                    }
                }
            }
            if (buffer == null)
            {
                throw new Exception();
            }
            MemoryStream tmp = new MemoryStream(buffer);

            if (tmp.ReadUInt32() != 0x504D5443)
            {
                throw new Exception();
            }
            byte[] decompressed = new byte[tmp.ReadUInt32()];
            byte[] compressed   = tmp.ReadToBuffer(tmp.ReadUInt32());
            if (new ZlibHelper.Zlib().Decompress(compressed, (uint)compressed.Length, decompressed) == 0)
            {
                throw new Exception();
            }
            fs = new MemoryStream(decompressed);

            fs.Skip(8);
            uint countTexture = fs.ReadUInt32();

            for (int i = 0; i < countTexture; i++)
            {
                FoundTexture texture = new FoundTexture();
                int          len     = fs.ReadByte();
                texture.name   = fs.ReadStringASCII(len);
                texture.crc    = fs.ReadUInt32();
                texture.width  = fs.ReadInt16();
                texture.height = fs.ReadInt16();
                texture.pixfmt = (PixelFormat)fs.ReadByte();
                texture.flags  = (TexProperty.TextureTypes)fs.ReadByte();
                int countPackages = fs.ReadInt16();
                texture.list = new List <MatchedTexture>();
                for (int k = 0; k < countPackages; k++)
                {
                    MatchedTexture matched = new MatchedTexture();
                    matched.exportID = fs.ReadInt32();
                    if (gameId == MeType.ME1_TYPE)
                    {
                        matched.linkToMaster = fs.ReadInt16();
                        if (matched.linkToMaster != -1)
                        {
                            matched.slave           = true;
                            matched.basePackageName = fs.ReadStringASCIINull();
                        }
                    }
                    matched.removeEmptyMips = fs.ReadByte() != 0;
                    matched.numMips         = fs.ReadByte();
                    matched.path            = pkgs[fs.ReadInt16()];
                    matched.packageName     = Path.GetFileNameWithoutExtension(matched.path).ToUpper();
                    texture.list.Add(matched);
                }
                textures.Add(texture);
            }
        }
Example #5
0
        public void PrepareListOfTextures(MeType gameId, bool ipc)
        {
            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),
                                       Program.MAINEXENAME);

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

            if (ipc)
            {
                Console.WriteLine("[IPC]STAGE_CONTEXT STAGE_PRESCAN");
                Console.Out.Flush();
            }

            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.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 (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.packageFiles[i].ToLowerInvariant();
                    long   packageSize = new FileInfo(GameData.GamePath + 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.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 (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();
                    }
                    FindTextures(gameId, textures, modifiedFiles[i], true, ipc);
                }

                for (int i = 0; i < addedFiles.Count; i++, currentPackage++)
                {
                    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();
                    }
                    FindTextures(gameId, textures, addedFiles[i], false, ipc);
                }

                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 (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.packageFiles[i], false, ipc);
                }
            }

            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;
                                    textures[k].list[t]       = slaveTexture;
                                    break;
                                }
                            }
                        }
                    }

                    bool foundSlave = false;
                    for (int s = 0; s < textures[k].list.Count; s++)
                    {
                        if (textures[k].list[s].slave)
                        {
                            foundSlave = true;
                            break;
                        }
                    }
                    bool foundWeakSlave = false;
                    if (!foundSlave)
                    {
                        for (int w = 0; w < textures[k].list.Count; w++)
                        {
                            if (textures[k].list[w].weakSlave)
                            {
                                foundWeakSlave = true;
                                break;
                            }
                        }
                    }
                    if (foundWeakSlave)
                    {
                        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 (!GameData.FullScanME1Game)
            {
                GameData.packageFiles.Sort(new AsciiStringComparer());
            }

            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++)
                    {
                        mem.WriteInt32(GameData.packageFiles[i].Length);
                        mem.WriteStringASCII(GameData.packageFiles[i]);
                    }
                }
                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);
                }
            }

            treeScan = textures;
        }
Example #6
0
        private void FindTextures(MeType gameId, List <FoundTexture> textures, string packagePath, bool modified, bool ipc)
        {
            Package package = null;

            try
            {
                package = new Package(GameData.GamePath + packagePath);
            }
            catch (Exception e)
            {
                if (e.Message.Contains("Problem with PCC file header:"))
                {
                    return;
                }
                if (ipc)
                {
                    Console.WriteLine("[IPC]ERROR Issue opening package file: " + packagePath);
                    Console.Out.Flush();
                }
                else
                {
                    string err = "";
                    err += "---- Start --------------------------------------------" + Environment.NewLine;
                    err += "Issue opening package file: " + packagePath + Environment.NewLine;
                    err += e.Message + Environment.NewLine + Environment.NewLine;
                    err += e.StackTrace + Environment.NewLine + Environment.NewLine;
                    err += "---- End ----------------------------------------------" + Environment.NewLine + Environment.NewLine;
                    Console.WriteLine(err);
                }
                return;
            }
            for (int i = 0; i < package.exportsTable.Count; i++)
            {
                int id = package.getClassNameId(package.exportsTable[i].classId);
                if (id == package.nameIdTexture2D ||
                    id == package.nameIdLightMapTexture2D ||
                    id == package.nameIdShadowMapTexture2D ||
                    id == package.nameIdTextureFlipBook)
                {
                    Texture texture = new Texture(package, i, package.getExportData(i));
                    if (!texture.hasImageData())
                    {
                        continue;
                    }

                    Texture.MipMap mipmap       = texture.getTopMipmap();
                    string         name         = package.exportsTable[i].objectName;
                    MatchedTexture matchTexture = new MatchedTexture();
                    matchTexture.exportID        = i;
                    matchTexture.path            = packagePath;
                    matchTexture.packageName     = texture.packageName;
                    matchTexture.removeEmptyMips = texture.mipMapsList.Exists(s => s.storageType == Texture.StorageTypes.empty);
                    matchTexture.numMips         = texture.mipMapsList.FindAll(s => s.storageType != Texture.StorageTypes.empty).Count;
                    if (gameId == MeType.ME1_TYPE)
                    {
                        matchTexture.basePackageName = texture.basePackageName;
                        matchTexture.slave           = texture.slave;
                        matchTexture.weakSlave       = texture.weakSlave;
                        matchTexture.linkToMaster    = -1;
                        if (matchTexture.slave)
                        {
                            matchTexture.mipmapOffset = mipmap.dataOffset;
                        }
                        else
                        {
                            matchTexture.mipmapOffset = package.exportsTable[i].dataOffset + (uint)texture.properties.propertyEndOffset + mipmap.internalOffset;
                        }
                    }

                    uint crc = 0;
                    try
                    {
                        crc = texture.getCrcTopMipmap();
                    }
                    catch (Exception e)
                    {
                        if (ipc)
                        {
                            Console.WriteLine("[IPC]ERROR Texture " + package.exportsTable[i].objectName + " is broken in package: " + packagePath + ", skipping...");
                            Console.Out.Flush();
                        }
                        else
                        {
                            Console.WriteLine(">>>>>>>>>");
                            Console.WriteLine("Error: Texture " + package.exportsTable[i].objectName + " is broken in package: " +
                                              Environment.NewLine + packagePath);
                            Console.WriteLine(e.Message);
                            Console.WriteLine("Export Id: " + (i + 1));
                            Console.WriteLine("skipping...");
                            Console.WriteLine("<<<<<<<<<" + Environment.NewLine);
                        }
                        continue;
                    }

                    FoundTexture foundTexName = textures.Find(s => s.crc == crc);
                    if (foundTexName.crc != 0)
                    {
                        if (modified && foundTexName.list.Exists(s => (s.exportID == i && s.path.ToLowerInvariant() == packagePath.ToLowerInvariant())))
                        {
                            continue;
                        }
                        if (matchTexture.slave || gameId != MeType.ME1_TYPE)
                        {
                            foundTexName.list.Add(matchTexture);
                        }
                        else
                        {
                            foundTexName.list.Insert(0, matchTexture);
                        }
                    }
                    else
                    {
                        if (modified)
                        {
                            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].exportID == i &&
                                        textures[k].list[t].path.ToLowerInvariant() == packagePath.ToLowerInvariant())
                                    {
                                        MatchedTexture f = textures[k].list[t];
                                        f.path = "";
                                        textures[k].list[t] = f;
                                        found = true;
                                        break;
                                    }
                                }
                                if (found)
                                {
                                    break;
                                }
                            }
                        }
                        FoundTexture foundTex = new FoundTexture();
                        foundTex.list = new List <MatchedTexture>();
                        foundTex.list.Add(matchTexture);
                        foundTex.name = name;
                        foundTex.crc  = crc;
                        if (generateBuiltinMapFiles)
                        {
                            foundTex.width  = texture.getTopMipmap().width;
                            foundTex.height = texture.getTopMipmap().height;
                            foundTex.pixfmt = Image.getPixelFormatType(texture.properties.getProperty("Format").valueName);
                            if (texture.properties.exists("CompressionSettings"))
                            {
                                string cmp = texture.properties.getProperty("CompressionSettings").valueName;
                                if (cmp == "TC_OneBitAlpha")
                                {
                                    foundTex.flags = TexProperty.TextureTypes.OneBitAlpha;
                                }
                                else if (cmp == "TC_Displacementmap")
                                {
                                    foundTex.flags = TexProperty.TextureTypes.Displacementmap;
                                }
                                else if (cmp == "TC_Grayscale")
                                {
                                    foundTex.flags = TexProperty.TextureTypes.GreyScale;
                                }
                                else if (cmp == "TC_Normalmap" ||
                                         cmp == "TC_NormalmapHQ" ||
                                         cmp == "TC_NormalmapAlpha" ||
                                         cmp == "TC_NormalmapUncompressed")
                                {
                                    foundTex.flags = TexProperty.TextureTypes.Normalmap;
                                }
                                else
                                {
                                    throw new Exception();
                                }
                            }
                            else
                            {
                                foundTex.flags = TexProperty.TextureTypes.Normal;
                            }
                        }
                        textures.Add(foundTex);
                    }
                }
            }

            package.Dispose();
        }
Example #7
0
        public string removeMipMapsME1(int phase, List <FoundTexture> textures, CachePackageMgr cachePackageMgr,
                                       MainWindow mainWindow, Installer installer, bool forceZlib = false)
        {
            string errors = "";

            for (int i = 0; i < GameData.packageFiles.Count; i++)
            {
                bool modified = false;
                if (mainWindow != null)
                {
                    mainWindow.updateStatusLabel("Removing empty mipmaps (" + phase + ") - package " + (i + 1) + " of " + GameData.packageFiles.Count + " - " + GameData.packageFiles[i]);
                    mainWindow.updateStatusLabel2("");
                }
                if (installer != null)
                {
                    installer.updateStatusMipMaps("Removing empty mipmaps " + ((GameData.packageFiles.Count * (phase - 1) + i + 1) * 100 / (GameData.packageFiles.Count * 2)) + "% ");
                }
                Package package = null;

                try
                {
                    if (cachePackageMgr != null)
                    {
                        package = cachePackageMgr.OpenPackage(GameData.packageFiles[i]);
                    }
                    else
                    {
                        package = new Package(GameData.packageFiles[i], true);
                    }
                }
                catch (Exception e)
                {
                    string err = "";
                    err    += "---- Start --------------------------------------------" + Environment.NewLine;
                    err    += "Issue with open package file: " + GameData.packageFiles[i] + Environment.NewLine;
                    err    += e.Message + Environment.NewLine + Environment.NewLine;
                    err    += e.StackTrace + Environment.NewLine + Environment.NewLine;
                    err    += "---- End ----------------------------------------------" + Environment.NewLine + Environment.NewLine;
                    errors += err;
                    continue;
                }

                for (int l = 0; l < package.exportsTable.Count; l++)
                {
                    int id = package.getClassNameId(package.exportsTable[l].classId);
                    if (id == package.nameIdTexture2D ||
                        id == package.nameIdTextureFlipBook)
                    {
                        using (Texture texture = new Texture(package, l, package.getExportData(l), false))
                        {
                            if (!texture.hasImageData() ||
                                !texture.mipMapsList.Exists(s => s.storageType == Texture.StorageTypes.empty))
                            {
                                continue;
                            }
                            do
                            {
                                texture.mipMapsList.Remove(texture.mipMapsList.First(s => s.storageType == Texture.StorageTypes.empty));
                            } while (texture.mipMapsList.Exists(s => s.storageType == Texture.StorageTypes.empty));
                            texture.properties.setIntValue("SizeX", texture.mipMapsList.First().width);
                            texture.properties.setIntValue("SizeY", texture.mipMapsList.First().height);
                            texture.properties.setIntValue("MipTailBaseIdx", texture.mipMapsList.Count() - 1);

                            FoundTexture foundTexture   = new FoundTexture();
                            int          foundListEntry = -1;
                            string       pkgName        = GameData.RelativeGameData(package.packagePath).ToLowerInvariant();
                            for (int k = 0; k < textures.Count; k++)
                            {
                                for (int t = 0; t < textures[k].list.Count; t++)
                                {
                                    if (textures[k].list[t].exportID == l &&
                                        textures[k].list[t].path.ToLowerInvariant() == pkgName)
                                    {
                                        foundTexture   = textures[k];
                                        foundListEntry = t;
                                        break;
                                    }
                                }
                            }
                            if (foundListEntry == -1)
                            {
                                errors += "Error: Texture " + package.exportsTable[l].objectName + " not found in package: " + GameData.packageFiles[i] + ", skipping..." + Environment.NewLine;
                                goto skip;
                            }

                            if (foundTexture.list[foundListEntry].linkToMaster != -1)
                            {
                                if (phase == 1)
                                {
                                    continue;
                                }

                                MatchedTexture foundMasterTex = foundTexture.list[foundTexture.list[foundListEntry].linkToMaster];
                                Package        masterPkg      = null;
                                if (cachePackageMgr != null)
                                {
                                    masterPkg = cachePackageMgr.OpenPackage(GameData.GamePath + foundMasterTex.path);
                                }
                                else
                                {
                                    masterPkg = new Package(GameData.GamePath + foundMasterTex.path);
                                }
                                int    masterExportId = foundMasterTex.exportID;
                                byte[] masterData     = masterPkg.getExportData(masterExportId);
                                masterPkg.DisposeCache();
                                using (Texture masterTexture = new Texture(masterPkg, masterExportId, masterData, false))
                                {
                                    if (texture.mipMapsList.Count != masterTexture.mipMapsList.Count)
                                    {
                                        errors += "Error: Texture " + package.exportsTable[l].objectName + " in package: " + GameData.packageFiles[i] + " has wrong reference, skipping..." + Environment.NewLine;
                                        goto skip;
                                    }
                                    for (int t = 0; t < texture.mipMapsList.Count; t++)
                                    {
                                        Texture.MipMap mipmap = texture.mipMapsList[t];
                                        if (mipmap.storageType == Texture.StorageTypes.extLZO ||
                                            mipmap.storageType == Texture.StorageTypes.extZlib ||
                                            mipmap.storageType == Texture.StorageTypes.extUnc)
                                        {
                                            mipmap.dataOffset      = masterPkg.exportsTable[masterExportId].dataOffset + (uint)masterTexture.properties.propertyEndOffset + masterTexture.mipMapsList[t].internalOffset;
                                            texture.mipMapsList[t] = mipmap;
                                        }
                                    }
                                }
                                if (cachePackageMgr == null)
                                {
                                    masterPkg.Dispose();
                                }
                            }
skip:
                            using (MemoryStream newData = new MemoryStream())
                            {
                                newData.WriteFromBuffer(texture.properties.toArray());
                                newData.WriteFromBuffer(texture.toArray(package.exportsTable[l].dataOffset + (uint)newData.Position));
                                package.setExportData(l, newData.ToArray());
                            }
                            modified = true;
                        }
                    }
                }
                if (cachePackageMgr == null)
                {
                    if (modified)
                    {
                        if (package.compressed && package.compressionType != Package.CompressionType.Zlib)
                        {
                            package.SaveToFile(forceZlib);
                        }
                        else
                        {
                            package.SaveToFile();
                        }
                    }
                    package.Dispose();
                }
                else
                {
                    package.DisposeCache();
                }
            }
            return(errors);
        }
Example #8
0
        public string removeMipMapsME1(int phase, List <FoundTexture> textures, Package package, RemoveMipsEntry removeEntry, MainWindow mainWindow, Installer installer, bool ipc)
        {
            string errors = "";

            for (int l = 0; l < removeEntry.exportIDs.Count; l++)
            {
                int exportID = removeEntry.exportIDs[l];
                using (Texture texture = new Texture(package, exportID, package.getExportData(exportID), false))
                {
                    if (!texture.mipMapsList.Exists(s => s.storageType == Texture.StorageTypes.empty))
                    {
                        continue;
                    }
                    do
                    {
                        texture.mipMapsList.Remove(texture.mipMapsList.First(s => s.storageType == Texture.StorageTypes.empty));
                    } while (texture.mipMapsList.Exists(s => s.storageType == Texture.StorageTypes.empty));
                    texture.properties.setIntValue("SizeX", texture.mipMapsList.First().width);
                    texture.properties.setIntValue("SizeY", texture.mipMapsList.First().height);
                    texture.properties.setIntValue("MipTailBaseIdx", texture.mipMapsList.Count() - 1);

                    FoundTexture foundTexture      = new FoundTexture();
                    int          foundListEntry    = -1;
                    int          foundTextureEntry = -1;
                    string       pkgName           = GameData.RelativeGameData(package.packagePath).ToLowerInvariant();
                    for (int k = 0; k < textures.Count; k++)
                    {
                        for (int t = 0; t < textures[k].list.Count; t++)
                        {
                            if (textures[k].list[t].exportID == exportID &&
                                textures[k].list[t].path.ToLowerInvariant() == pkgName)
                            {
                                foundTexture      = textures[k];
                                foundTextureEntry = k;
                                foundListEntry    = t;
                                break;
                            }
                        }
                    }
                    if (foundListEntry == -1)
                    {
                        if (ipc)
                        {
                            Console.WriteLine("[IPC]ERROR Texture " + package.exportsTable[exportID].objectName + " not found in tree: " + removeEntry.pkgPath + ", skipping...");
                            Console.Out.Flush();
                        }
                        else
                        {
                            errors += "Error: Texture " + package.exportsTable[exportID].objectName + " not found in tree: " + removeEntry.pkgPath + ", skipping..." + Environment.NewLine;
                        }
                        continue;
                    }

                    MatchedTexture m = foundTexture.list[foundListEntry];
                    if (m.linkToMaster != -1)
                    {
                        if (phase == 1)
                        {
                            continue;
                        }

                        MatchedTexture foundMasterTex = foundTexture.list[m.linkToMaster];
                        if (texture.mipMapsList.Count != foundMasterTex.masterDataOffset.Count)
                        {
                            if (ipc)
                            {
                                Console.WriteLine("[IPC]ERROR Texture " + package.exportsTable[exportID].objectName + " in package: " + foundMasterTex.path + " has wrong reference, skipping..." + Environment.NewLine);
                                Console.Out.Flush();
                            }
                            else
                            {
                                errors += "Error: Texture " + package.exportsTable[exportID].objectName + " in package: " + foundMasterTex.path + " has wrong reference, skipping..." + Environment.NewLine;
                            }
                            continue;
                        }
                        for (int t = 0; t < texture.mipMapsList.Count; t++)
                        {
                            Texture.MipMap mipmap = texture.mipMapsList[t];
                            if (mipmap.storageType == Texture.StorageTypes.extLZO ||
                                mipmap.storageType == Texture.StorageTypes.extZlib ||
                                mipmap.storageType == Texture.StorageTypes.extUnc)
                            {
                                mipmap.dataOffset      = foundMasterTex.masterDataOffset[t];
                                texture.mipMapsList[t] = mipmap;
                            }
                        }
                    }

                    uint packageDataOffset;
                    using (MemoryStream newData = new MemoryStream())
                    {
                        newData.WriteFromBuffer(texture.properties.toArray());
                        packageDataOffset = package.exportsTable[exportID].dataOffset + (uint)newData.Position;
                        newData.WriteFromBuffer(texture.toArray(packageDataOffset));
                        package.setExportData(exportID, newData.ToArray());
                    }

                    if (m.linkToMaster == -1)
                    {
                        if (phase == 2)
                        {
                            throw new Exception();
                        }
                        m.masterDataOffset = new List <uint>();
                        for (int t = 0; t < texture.mipMapsList.Count; t++)
                        {
                            m.masterDataOffset.Add(packageDataOffset + texture.mipMapsList[t].internalOffset);
                        }
                    }

                    m.removeEmptyMips = false;
                    textures[foundTextureEntry].list[foundListEntry] = m;
                }
            }
            if (package.SaveToFile(false, false, installer != null))
            {
                if (Installer.pkgsToMarker != null)
                {
                    Installer.pkgsToMarker.Remove(package.packagePath);
                }
            }
            package.Dispose();

            return(errors);
        }
        private string FindTextures(List <FoundTexture> textures, string packagePath, CachePackageMgr cachePackageMgr, ref string log)
        {
            string  errors  = "";
            Package package = null;

            try
            {
                if (cachePackageMgr != null)
                {
                    package = cachePackageMgr.OpenPackage(packagePath);
                }
                else
                {
                    package = new Package(packagePath);
                }
            }
            catch (Exception e)
            {
                string err = "";
                err    += "---- Start --------------------------------------------" + Environment.NewLine;
                err    += "Issue with open package file: " + packagePath + Environment.NewLine;
                err    += e.Message + Environment.NewLine + Environment.NewLine;
                err    += e.StackTrace + Environment.NewLine + Environment.NewLine;
                err    += "---- End ----------------------------------------------" + Environment.NewLine + Environment.NewLine;
                errors += err;
                log    += err;
                return(errors);
            }
            for (int i = 0; i < package.exportsTable.Count; i++)
            {
                int id = package.getClassNameId(package.exportsTable[i].classId);
                if (id == package.nameIdTexture2D ||
                    id == package.nameIdLightMapTexture2D ||
                    id == package.nameIdShadowMapTexture2D ||
                    id == package.nameIdTextureFlipBook)
                {
                    Texture texture = new Texture(package, i, package.getExportData(i));
                    if (!texture.hasImageData())
                    {
                        continue;
                    }

                    Texture.MipMap mipmap       = texture.getTopMipmap();
                    string         name         = package.exportsTable[i].objectName;
                    MatchedTexture matchTexture = new MatchedTexture();
                    matchTexture.exportID    = i;
                    matchTexture.path        = GameData.RelativeGameData(packagePath);
                    matchTexture.packageName = texture.packageName;
                    if (GameData.gameType == MeType.ME1_TYPE)
                    {
                        matchTexture.basePackageName = texture.basePackageName;
                        matchTexture.slave           = texture.slave;
                        matchTexture.weakSlave       = texture.weakSlave;
                        matchTexture.linkToMaster    = -1;
                        if (matchTexture.slave)
                        {
                            matchTexture.mipmapOffset = mipmap.dataOffset;
                        }
                        else
                        {
                            matchTexture.mipmapOffset = package.exportsTable[i].dataOffset + (uint)texture.properties.propertyEndOffset + mipmap.internalOffset;
                        }
                    }

                    uint crc = 0;
                    try
                    {
                        crc = texture.getCrcTopMipmap();
                    }
                    catch
                    {
                    }
                    if (crc == 0)
                    {
                        errors += "Error: Texture " + package.exportsTable[i].objectName + " is broken in package: " + packagePath + ", skipping..." + Environment.NewLine;
                        log    += "Error: Texture " + package.exportsTable[i].objectName + " is broken in package: " + packagePath + ", skipping..." + Environment.NewLine;
                        continue;
                    }

                    FoundTexture foundTexName = textures.Find(s => s.crc == crc);
                    if (foundTexName.crc != 0)
                    {
                        if (matchTexture.slave || GameData.gameType != MeType.ME1_TYPE)
                        {
                            foundTexName.list.Add(matchTexture);
                        }
                        else
                        {
                            foundTexName.list.Insert(0, matchTexture);
                        }
                    }
                    else
                    {
                        FoundTexture foundTex = new FoundTexture();
                        foundTex.list = new List <MatchedTexture>();
                        foundTex.list.Add(matchTexture);
                        foundTex.name = name;
                        foundTex.crc  = crc;
                        if (generateBuiltinMapFiles)
                        {
                            foundTex.width  = texture.getTopMipmap().width;
                            foundTex.height = texture.getTopMipmap().height;
                            foundTex.pixfmt = Image.getEngineFormatType(texture.properties.getProperty("Format").valueName);
                            if (foundTex.pixfmt == PixelFormat.DXT1 &&
                                texture.properties.exists("CompressionSettings") &&
                                texture.properties.getProperty("CompressionSettings").valueName == "TC_OneBitAlpha")
                            {
                                foundTex.alphadxt1 = true;
                            }
                        }
                        textures.Add(foundTex);
                    }
                }
            }

            if (cachePackageMgr == null)
            {
                package.Dispose();
            }
            else
            {
                package.DisposeCache();
            }

            return(errors);
        }
        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);
        }
Example #11
0
        public void RepackTexturesTFC(List <FoundTexture> textures, MainWindow mainWindow, CachePackageMgr cachePackageMgr)
        {
            if (GameData.gameType == MeType.ME2_TYPE)
            {
                for (int i = 0; i < textures.Count; i++)
                {
                    FoundTexture foundTexture = textures[i];
                    if (mainWindow != null)
                    {
                        mainWindow.updateStatusLabel("Texture: " + (i + 1) + " of " + textures.Count);
                        mainWindow.updateStatusLabel2("");
                    }
                    string  TFCfilename = "", TFCfilenameTemp, prevTFCfilename = "";
                    Texture prevTexture = null;
                    for (int index2 = 0; index2 < foundTexture.list.Count; index2++)
                    {
                        MatchedTexture matchedTexture = foundTexture.list[index2];
                        string         packagePath    = GameData.GamePath + matchedTexture.path;
                        Package        package        = cachePackageMgr.OpenPackage(packagePath);
                        Texture        texture        = new Texture(package, matchedTexture.exportID, package.getExportData(matchedTexture.exportID));
                        if (!texture.mipMapsList.Exists(b => b.storageType == Texture.StorageTypes.extLZO || b.storageType == Texture.StorageTypes.extUnc || b.storageType == Texture.StorageTypes.extZlib))
                        {
                            continue;
                        }

                        bool modified = false;
                        for (int l = 0; l < texture.mipMapsList.Count; l++)
                        {
                            Texture.MipMap mipmap = texture.mipMapsList[l];
                            if (((int)mipmap.storageType & (int)Texture.StorageFlags.externalFile) != 0)
                            {
                                string archive = texture.properties.getProperty("TextureFileCacheName").valueName;
                                TFCfilename = Path.Combine(GameData.MainData, archive + ".tfc");
                                if (packagePath.ToLowerInvariant().Contains("\\dlc"))
                                {
                                    string DLCArchiveFile = Path.Combine(Path.GetDirectoryName(packagePath), archive + ".tfc");
                                    if (File.Exists(DLCArchiveFile))
                                    {
                                        TFCfilename = DLCArchiveFile;
                                    }
                                    else if (GameData.gameType == MeType.ME2_TYPE)
                                    {
                                        TFCfilename = Path.Combine(GameData.MainData, "Textures.tfc");
                                    }
                                }

                                TFCfilenameTemp = TFCfilename + ".TempTFC";
                                if (!File.Exists(TFCfilenameTemp))
                                {
                                    using (FileStream fs = new FileStream(TFCfilenameTemp, FileMode.CreateNew, FileAccess.Write))
                                    {
                                        byte[] guid = new byte[16];
                                        Array.Copy(texture.properties.getProperty("TFCFileGuid").valueStruct, guid, 16);
                                        fs.WriteFromBuffer(guid);
                                    }
                                }

                                if (TFCfilename != prevTFCfilename)
                                {
                                    using (FileStream fs = new FileStream(TFCfilename, FileMode.Open, FileAccess.Read))
                                    {
                                        fs.JumpTo(mipmap.dataOffset);
                                        using (FileStream fsNew = new FileStream(TFCfilenameTemp, FileMode.Append, FileAccess.Write))
                                        {
                                            fsNew.SeekEnd();
                                            mipmap.dataOffset = (uint)fsNew.Position;
                                            if (mipmap.storageType == Texture.StorageTypes.extLZO ||
                                                mipmap.storageType == Texture.StorageTypes.extZlib)
                                            {
                                                fsNew.WriteFromStream(fs, mipmap.compressedSize);
                                            }
                                            else
                                            {
                                                fsNew.WriteFromStream(fs, mipmap.uncompressedSize);
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    Texture.MipMap tmpMipmap = prevTexture.getMipmap(mipmap.width, mipmap.height);
                                    if (mipmap.storageType != tmpMipmap.storageType)
                                    {
                                        throw new Exception("");
                                    }
                                    mipmap.dataOffset = tmpMipmap.dataOffset;
                                }
                                texture.mipMapsList[l] = mipmap;
                                modified = true;
                            }
                        }

                        if (modified)
                        {
                            prevTFCfilename = TFCfilename;
                            prevTexture     = texture;
                            using (MemoryStream newData = new MemoryStream())
                            {
                                newData.WriteFromBuffer(texture.properties.toArray());
                                newData.WriteFromBuffer(texture.toArray(package.exportsTable[matchedTexture.exportID].dataOffset + (uint)newData.Position));
                                //package.setExportData(matchedTexture.exportID, newData.ToArray());
                            }
                        }
                    }
                }
            }
            if (mainWindow != null)
            {
                mainWindow.updateStatusLabel("");
            }

            List <string> tfcFles = Directory.GetFiles(GameData.GamePath, "*.TempTFC", SearchOption.AllDirectories).Where(item => item.EndsWith(".TempTFC", StringComparison.OrdinalIgnoreCase)).ToList();

            for (int i = 0; i < tfcFles.Count; i++)
            {
                string newname = tfcFles[i].Substring(0, tfcFles[i].IndexOf(".TempTFC"));
                File.Delete(newname);
                File.Move(tfcFles[i], newname);
            }
            //cachePackageMgr.CloseAllWithSave();

            if (mainWindow != null)
            {
                mainWindow.updateStatusLabel("Done.");
                mainWindow.updateStatusLabel("");
            }
        }
Example #12
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);
        }
        public string replaceTexture(DDSImage image, List <MatchedTexture> list, CachePackageMgr cachePackageMgr, string textureName, uint crc)
        {
            List <Texture> masterTextures = new List <Texture>();
            Texture        arcTexture = null, cprTexture = null;
            string         errors = "";

            for (int n = 0; n < list.Count; n++)
            {
                MatchedTexture nodeTexture = list[n];
                Package        package     = cachePackageMgr.OpenPackage(GameData.GamePath + nodeTexture.path);
                Texture        texture     = new Texture(package, nodeTexture.exportID, package.getExportData(nodeTexture.exportID));
                while (texture.mipMapsList.Exists(s => s.storageType == Texture.StorageTypes.empty))
                {
                    texture.mipMapsList.Remove(texture.mipMapsList.First(s => s.storageType == Texture.StorageTypes.empty));
                }
                bool master = true;
                if (GameData.gameType == MeType.ME1_TYPE)
                {
                    if (texture.packageName.ToLowerInvariant() != Path.GetFileNameWithoutExtension(package.packageFile.Name).ToLowerInvariant())
                    {
                        master = false;
                        if (!masterTextures.Exists(s => s.packageName.ToLowerInvariant() == texture.packageName.ToLowerInvariant()))
                        {
                            errors += "Error in texture: " + textureName + " Broken game file: " + nodeTexture.path + ", skipping texture..." + Environment.NewLine;
                            continue;
                        }
                    }
                }

                if (texture.mipMapsList.Count > 1 && image.mipMaps.Count() <= 1)
                {
                    errors += "Error in texture: " + textureName + " This texture has not all the required mipmaps, skipping texture..." + Environment.NewLine;
                    break;
                }

                string    fmt       = texture.properties.getProperty("Format").valueName;
                DDSFormat ddsFormat = DDSImage.convertFormat(fmt);
                if (image.ddsFormat != ddsFormat)
                {
                    errors += "Error in texture: " + textureName + " This texture has wrong texture format, should be: " + ddsFormat + ", skipping texture..." + Environment.NewLine;
                    break;
                }

                if (image.mipMaps[0].origWidth / image.mipMaps[0].origHeight !=
                    texture.mipMapsList[0].width / texture.mipMapsList[0].height)
                {
                    errors += "Error in texture: " + textureName + " This texture has wrong aspect ratio, skipping texture..." + Environment.NewLine;
                    break;
                }

                // remove lower mipmaps from source image which not exist in game data
                for (int t = 0; t < image.mipMaps.Count(); t++)
                {
                    if (image.mipMaps[t].origWidth <= texture.mipMapsList[0].width &&
                        image.mipMaps[t].origHeight <= texture.mipMapsList[0].height &&
                        texture.mipMapsList.Count > 1)
                    {
                        if (!texture.mipMapsList.Exists(m => m.width == image.mipMaps[t].origWidth && m.height == image.mipMaps[t].origHeight))
                        {
                            image.mipMaps.RemoveAt(t--);
                        }
                    }
                }

                bool skip = false;
                // reuse lower mipmaps from game data which not exist in source image
                for (int t = 0; t < texture.mipMapsList.Count; t++)
                {
                    if (texture.mipMapsList[t].width <= image.mipMaps[0].origWidth &&
                        texture.mipMapsList[t].height <= image.mipMaps[0].origHeight)
                    {
                        if (!image.mipMaps.Exists(m => m.origWidth == texture.mipMapsList[t].width && m.origHeight == texture.mipMapsList[t].height))
                        {
                            byte[] data = texture.getMipMapData(texture.mipMapsList[t]);
                            if (data == null)
                            {
                                errors += "Error in game data: " + nodeTexture.path + ", skipping texture..." + Environment.NewLine;
                                skip    = true;
                                break;
                            }
                            DDSImage.MipMap mipmap = new DDSImage.MipMap(data, ddsFormat, texture.mipMapsList[t].width, texture.mipMapsList[t].height);
                            image.mipMaps.Add(mipmap);
                        }
                    }
                }
                if (skip)
                {
                    continue;
                }

                package.DisposeCache();

                bool   triggerCacheArc = false, triggerCacheCpr = false;
                string archiveFile = "";
                byte[] origGuid    = new byte[16];
                if (texture.properties.exists("TextureFileCacheName"))
                {
                    Array.Copy(texture.properties.getProperty("TFCFileGuid").valueStruct, origGuid, 16);
                    string archive = texture.properties.getProperty("TextureFileCacheName").valueName;
                    archiveFile = Path.Combine(GameData.MainData, archive + ".tfc");
                    if (nodeTexture.path.ToLowerInvariant().Contains("\\dlc"))
                    {
                        string DLCArchiveFile = Path.Combine(Path.GetDirectoryName(GameData.GamePath + nodeTexture.path), archive + ".tfc");
                        if (File.Exists(DLCArchiveFile))
                        {
                            archiveFile = DLCArchiveFile;
                        }
                        else if (!File.Exists(archiveFile))
                        {
                            List <string> files = Directory.GetFiles(GameData.bioGamePath, archive + ".tfc",
                                                                     SearchOption.AllDirectories).Where(item => item.EndsWith(".tfc", StringComparison.OrdinalIgnoreCase)).ToList();
                            if (files.Count == 0)
                            {
                                archiveFile = Path.Combine(GameData.MainData, "Textures.tfc");
                            }
                            else if (files.Count == 1)
                            {
                                archiveFile = files[0];
                            }
                            else
                            {
                                throw new Exception("");
                            }
                        }
                    }
                    long fileLength = new FileInfo(archiveFile).Length;
                    if (fileLength + 0x5000000 > 0x80000000)
                    {
                        archiveFile = "";
                        foreach (TFCTexture newGuid in guids)
                        {
                            archiveFile = Path.Combine(GameData.MainData, newGuid.name + ".tfc");
                            if (!File.Exists(archiveFile))
                            {
                                texture.properties.setNameValue("TextureFileCacheName", newGuid.name);
                                texture.properties.setStructValue("TFCFileGuid", "Guid", newGuid.guid);
                                using (FileStream fs = new FileStream(archiveFile, FileMode.CreateNew, FileAccess.Write))
                                {
                                    fs.WriteFromBuffer(newGuid.guid);
                                }
                                break;
                            }
                            else
                            {
                                fileLength = new FileInfo(archiveFile).Length;
                                if (fileLength + 0x5000000 < 0x80000000)
                                {
                                    texture.properties.setNameValue("TextureFileCacheName", newGuid.name);
                                    texture.properties.setStructValue("TFCFileGuid", "Guid", newGuid.guid);
                                    break;
                                }
                            }
                            archiveFile = "";
                        }
                        if (archiveFile == "")
                        {
                            throw new Exception("No free TFC texture file!");
                        }
                    }
                }

                List <Texture.MipMap> mipmaps = new List <Texture.MipMap>();
                for (int m = 0; m < image.mipMaps.Count(); m++)
                {
                    Texture.MipMap mipmap = new Texture.MipMap();
                    mipmap.width  = image.mipMaps[m].origWidth;
                    mipmap.height = image.mipMaps[m].origHeight;
                    if (texture.existMipmap(mipmap.width, mipmap.height))
                    {
                        mipmap.storageType = texture.getMipmap(mipmap.width, mipmap.height).storageType;
                    }
                    else
                    {
                        mipmap.storageType = texture.getTopMipmap().storageType;
                        if (GameData.gameType == MeType.ME1_TYPE && master == false)
                        {
                            if (mipmap.storageType == Texture.StorageTypes.pccUnc ||
                                mipmap.storageType == Texture.StorageTypes.pccLZO ||
                                mipmap.storageType == Texture.StorageTypes.pccZlib)
                            {
                                mipmap.storageType = Texture.StorageTypes.extLZO;
                            }
                        }
                        else if (GameData.gameType == MeType.ME2_TYPE || GameData.gameType == MeType.ME3_TYPE)
                        {
                            if (texture.properties.exists("TextureFileCacheName") && texture.mipMapsList.Count > 1)
                            {
                                if (texture.mipMapsList.Count < 6)
                                {
                                    mipmap.storageType = Texture.StorageTypes.pccUnc;
                                    if (!texture.properties.exists("NeverStream"))
                                    {
                                        if (package.existsNameId("NeverStream"))
                                        {
                                            texture.properties.addBoolValue("NeverStream", true);
                                        }
                                        else
                                        {
                                            goto skip;
                                        }
                                    }
                                }
                                else
                                {
                                    if (GameData.gameType == MeType.ME2_TYPE)
                                    {
                                        mipmap.storageType = Texture.StorageTypes.extLZO;
                                    }
                                    else
                                    {
                                        mipmap.storageType = Texture.StorageTypes.extZlib;
                                    }
                                }
                            }
                        }
                    }

                    if (mipmap.storageType == Texture.StorageTypes.extLZO)
                    {
                        mipmap.storageType = Texture.StorageTypes.extZlib;
                    }
                    if (mipmap.storageType == Texture.StorageTypes.pccLZO)
                    {
                        mipmap.storageType = Texture.StorageTypes.pccZlib;
                    }

                    mipmap.uncompressedSize = image.mipMaps[m].data.Length;
                    if (GameData.gameType == MeType.ME1_TYPE)
                    {
                        if (mipmap.storageType == Texture.StorageTypes.pccLZO ||
                            mipmap.storageType == Texture.StorageTypes.pccZlib)
                        {
                            if (master)
                            {
                                mipmap.newData = texture.compressTexture(image.mipMaps[m].data, mipmap.storageType);
                            }
                            else
                            {
                                mipmap.newData = masterTextures.Find(s => s.packageName.ToLowerInvariant() == texture.packageName.ToLowerInvariant()).mipMapsList[m].newData;
                            }
                            mipmap.compressedSize = mipmap.newData.Length;
                        }
                        if (mipmap.storageType == Texture.StorageTypes.pccUnc)
                        {
                            mipmap.compressedSize = mipmap.uncompressedSize;
                            mipmap.newData        = image.mipMaps[m].data;
                        }
                        if ((mipmap.storageType == Texture.StorageTypes.extLZO ||
                             mipmap.storageType == Texture.StorageTypes.extZlib) && master == false)
                        {
                            mipmap.compressedSize = masterTextures.Find(s => s.packageName.ToLowerInvariant() == texture.packageName.ToLowerInvariant()).mipMapsList[m].compressedSize;
                            mipmap.dataOffset     = masterTextures.Find(s => s.packageName.ToLowerInvariant() == texture.packageName.ToLowerInvariant()).mipMapsList[m].dataOffset;
                        }
                    }
                    else
                    {
                        if (mipmap.storageType == Texture.StorageTypes.extZlib ||
                            mipmap.storageType == Texture.StorageTypes.extLZO)
                        {
                            if (cprTexture == null || (cprTexture != null && mipmap.storageType != cprTexture.mipMapsList[m].storageType))
                            {
                                mipmap.newData  = texture.compressTexture(image.mipMaps[m].data, mipmap.storageType);
                                triggerCacheCpr = true;
                            }
                            else
                            {
                                if (cprTexture.mipMapsList[m].width != mipmap.width ||
                                    cprTexture.mipMapsList[m].height != mipmap.height)
                                {
                                    throw new Exception();
                                }
                                mipmap.newData = cprTexture.mipMapsList[m].newData;
                            }
                            mipmap.compressedSize = mipmap.newData.Length;
                        }
                        if (mipmap.storageType == Texture.StorageTypes.pccUnc ||
                            mipmap.storageType == Texture.StorageTypes.extUnc)
                        {
                            mipmap.compressedSize = mipmap.uncompressedSize;
                            mipmap.newData        = image.mipMaps[m].data;
                        }
                        if (mipmap.storageType == Texture.StorageTypes.extZlib ||
                            mipmap.storageType == Texture.StorageTypes.extLZO ||
                            mipmap.storageType == Texture.StorageTypes.extUnc)
                        {
                            if (arcTexture == null ||
                                !StructuralComparisons.StructuralEqualityComparer.Equals(
                                    arcTexture.properties.getProperty("TFCFileGuid").valueStruct,
                                    texture.properties.getProperty("TFCFileGuid").valueStruct))
                            {
                                triggerCacheArc = true;
                                Texture.MipMap oldMipmap = texture.getMipmap(mipmap.width, mipmap.height);
                                if (StructuralComparisons.StructuralEqualityComparer.Equals(origGuid,
                                                                                            texture.properties.getProperty("TFCFileGuid").valueStruct) &&
                                    oldMipmap.width != 0 && mipmap.newData.Length <= oldMipmap.compressedSize)
                                {
                                    try
                                    {
                                        using (FileStream fs = new FileStream(archiveFile, FileMode.Open, FileAccess.Write))
                                        {
                                            fs.JumpTo(oldMipmap.dataOffset);
                                            mipmap.dataOffset = oldMipmap.dataOffset;
                                            fs.WriteFromBuffer(mipmap.newData);
                                        }
                                    }
                                    catch
                                    {
                                        throw new Exception("Problem with access to TFC file: " + archiveFile);
                                    }
                                }
                                else
                                {
                                    try
                                    {
                                        using (FileStream fs = new FileStream(archiveFile, FileMode.Open, FileAccess.Write))
                                        {
                                            fs.SeekEnd();
                                            mipmap.dataOffset = (uint)fs.Position;
                                            fs.WriteFromBuffer(mipmap.newData);
                                        }
                                    }
                                    catch
                                    {
                                        throw new Exception("Problem with access to TFC file: " + archiveFile);
                                    }
                                }
                            }
                            else
                            {
                                if (arcTexture.mipMapsList[m].width != mipmap.width ||
                                    arcTexture.mipMapsList[m].height != mipmap.height)
                                {
                                    throw new Exception();
                                }
                                mipmap.dataOffset = arcTexture.mipMapsList[m].dataOffset;
                            }
                        }
                    }

                    mipmap.width  = image.mipMaps[m].width;
                    mipmap.height = image.mipMaps[m].height;
                    mipmaps.Add(mipmap);
                    if (texture.mipMapsList.Count() == 1)
                    {
                        break;
                    }
                }
                texture.replaceMipMaps(mipmaps);
                texture.properties.setIntValue("SizeX", texture.mipMapsList.First().width);
                texture.properties.setIntValue("SizeY", texture.mipMapsList.First().height);
                if (texture.properties.exists("MipTailBaseIdx"))
                {
                    texture.properties.setIntValue("MipTailBaseIdx", texture.mipMapsList.Count() - 1);
                }
                if (GameData.gameType == MeType.ME1_TYPE && crc == 0x39A26907)
                {
                    if (!texture.properties.exists("LODGroup"))
                    {
                        texture.properties.addByteValue("LODGroup", "TEXTUREGROUP_Character", 1025);
                    }
                    else
                    {
                        texture.properties.setByteValue("LODGroup", "TEXTUREGROUP_Character", 1025);
                    }
                }

                using (MemoryStream newData = new MemoryStream())
                {
                    newData.WriteFromBuffer(texture.properties.toArray());
                    newData.WriteFromBuffer(texture.toArray(0)); // filled later
                    package.setExportData(nodeTexture.exportID, newData.ToArray());
                }

                using (MemoryStream newData = new MemoryStream())
                {
                    newData.WriteFromBuffer(texture.properties.toArray());
                    newData.WriteFromBuffer(texture.toArray(package.exportsTable[nodeTexture.exportID].dataOffset + (uint)newData.Position));
                    package.setExportData(nodeTexture.exportID, newData.ToArray());
                }

                if (GameData.gameType == MeType.ME1_TYPE)
                {
                    if (master)
                    {
                        masterTextures.Add(texture);
                    }
                }
                else
                {
                    if (triggerCacheCpr)
                    {
                        cprTexture = texture;
                    }
                    if (triggerCacheArc)
                    {
                        arcTexture = texture;
                    }
                }
skip:
                package = null;
            }
            masterTextures = null;
            arcTexture     = cprTexture = null;

            return(errors);
        }