예제 #1
0
 public Installer()
 {
     InitializeComponent();
     Text            = "MEM Installer v" + Application.ProductVersion + " for ALOT";
     mipMaps         = new MipMaps();
     treeScan        = new TreeScan();
     cachePackageMgr = new CachePackageMgr(null, this);
 }
        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);
        }
예제 #4
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);
        }
예제 #5
0
        static public bool checkGameDataModded(CachePackageMgr cachePackageMgr)
        {
            EmptyMipMaps[] entries = new EmptyMipMaps[]
            {
                new EmptyMipMaps
                {
                    gameType    = MeType.ME1_TYPE,
                    packagePath = @"\BioGame\CookedPC\Packages\GameObjects\Characters\Humanoids\HumanMale\BIOG_HMM_HED_PROMorph.upk",
                    exportId    = 304,
                    crc         = 0x80B2CBCF,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME1_TYPE,
                    packagePath = @"\BioGame\CookedPC\Packages\GameObjects\Characters\Humanoids\HumanFemale\BIOG_HMF_HED_PROMorph_R.upk",
                    exportId    = 279,
                    crc         = 0x422AAA0D,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME1_TYPE,
                    packagePath = @"\BioGame\CookedPC\BIOG_ASA_ARM_MRC_R.upk",
                    exportId    = 71,
                    crc         = 0x077202BD,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME1_TYPE,
                    packagePath = @"\BioGame\CookedPC\Packages\GameObjects\Characters\Humanoids\HumanFemale\BIOG_HMF_HED_PROMorph_R.upk",
                    exportId    = 259,
                    crc         = 0x8F331825,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME1_TYPE,
                    packagePath = @"\BioGame\CookedPC\Packages\GameObjects\Characters\Humanoids\HumanFemale\BIOG_HMF_HED_PROMorph_R.upk",
                    exportId    = 262,
                    crc         = 0x2CC6F67C,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME1_TYPE,
                    packagePath = @"\BioGame\CookedPC\Packages\GameObjects\Characters\Humanoids\Turian\BIOG_TUR_HED_PROMorph_R.upk",
                    exportId    = 115,
                    crc         = 0x39A26907,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME1_TYPE,
                    packagePath = @"\BioGame\CookedPC\Packages\GameObjects\Characters\Humanoids\HumanMale\BIOG_HMM_HED_PROMorph.upk",
                    exportId    = 356,
                    crc         = 0xCD4AD3A5,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME1_TYPE,
                    packagePath = @"\BioGame\CookedPC\Packages\GameObjects\Characters\Humanoids\HumanMale\BIOG_HMM_HED_PROMorph.upk",
                    exportId    = 360,
                    crc         = 0x0898E4C4,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME1_TYPE,
                    packagePath = @"\BioGame\CookedPC\Packages\GameObjects\Characters\Humanoids\HumanFemale\BIOG_HMF_ARM_CTH_R.upk",
                    exportId    = 243,
                    crc         = 0x8D20F3EB,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME1_TYPE,
                    packagePath = @"\BioGame\CookedPC\Packages\GameObjects\Characters\Humanoids\Turian\BIOG_TUR_HED_SAR.upk",
                    exportId    = 51,
                    crc         = 0x4F24BAAF,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME1_TYPE,
                    packagePath = @"\BioGame\CookedPC\Packages\GameObjects\Characters\Humanoids\HumanMale\BIOG_HMM_HED_PROMorph.upk",
                    exportId    = 394,
                    crc         = 0x947A74A8,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME1_TYPE,
                    packagePath = @"\BioGame\CookedPC\Packages\GameObjects\Characters\Humanoids\HumanMale\BIOG_HMM_HED_PROMorph.upk",
                    exportId    = 341,
                    crc         = 0x72D6575F,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME1_TYPE,
                    packagePath = @"\BioGame\CookedPC\Packages\GameObjects\Characters\Humanoids\Krogan\BIOG_KRO_HED_PROMorph.upk",
                    exportId    = 61,
                    crc         = 0x822EEFB1,
                },


                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BioA_N7Spdr2_100.pcc",
                    exportId    = 13796,
                    crc         = 0x80B2CBCF,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BioD_JunCvL_100Landing.pcc",
                    exportId    = 6105,
                    crc         = 0x72D6575F,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BioD_EndGm2_440Normandy.pcc",
                    exportId    = 2569,
                    crc         = 0xCD4AD3A5,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BioD_HorCr1_303AshKaidan.pcc",
                    exportId    = 3781,
                    crc         = 0x0898E4C4,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BIOG_HMM_HED_PROMorph.pcc",
                    exportId    = 2495,
                    crc         = 0x947A74A8,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BioD_JnkKgA_300Labs.pcc",
                    exportId    = 5785,
                    crc         = 0xECA7DA8F,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BioD_CitAsL_210FirstStop.pcc",
                    exportId    = 4117,
                    crc         = 0x822EEFB1,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BioD_EndGm1_110ROMGarrus.pcc",
                    exportId    = 5076,
                    crc         = 0x6E3C2E30,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BioD_OmgGrA_113AlamoAssault.pcc",
                    exportId    = 4864,
                    crc         = 0x6CD2B8F2,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BioH_END_Professor_00.pcc",
                    exportId    = 5894,
                    crc         = 0x9A987362,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BioD_EndGm1_110ROMMirranda.pcc",
                    exportId    = 8808,
                    crc         = 0xB389BFE6,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BIOG_HMF_HED_PROMorph_R.pcc",
                    exportId    = 3073,
                    crc         = 0x5674B1E3,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BioD_HorCr1_303AshKaidan.pcc",
                    exportId    = 3757,
                    crc         = 0x422AAA0D,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BioD_BchLmL_102BeachFight.pcc",
                    exportId    = 5869,
                    crc         = 0x9CA124E8,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BioA_N7Mmnt7.pcc",
                    exportId    = 10440,
                    crc         = 0x2A01319D,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BioD_ProNor.pcc",
                    exportId    = 21224,
                    crc         = 0x40197218,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BioD_Nor_231Morinth.pcc",
                    exportId    = 1922,
                    crc         = 0x27539E1B,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BioD_CitAsL.pcc",
                    exportId    = 8798,
                    crc         = 0x42EE7CBF,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME2_TYPE,
                    packagePath = @"\BioGame\CookedPC\BioD_Nor_110DebriefLeadVixen.pcc",
                    exportId    = 4433,
                    crc         = 0xD30672BD,
                },


                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioA_CitSam_000LevelTrans.pcc",
                    exportId    = 4607,
                    crc         = 0x0F4E701E,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioD_CitHub_EmbassyP3.pcc",
                    exportId    = 8182,
                    crc         = 0x27539E1B,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioD_Cat003_380DesksConvos.pcc",
                    exportId    = 9460,
                    crc         = 0x42EE7CBF,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioA_GthLeg_000LevelTrans.pcc",
                    exportId    = 3500,
                    crc         = 0xD30672BD,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioA_CitHub_000Docking.pcc",
                    exportId    = 3625,
                    crc         = 0xF51672AC,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioD_CerJcb_150MainDoor.pcc",
                    exportId    = 7722,
                    crc         = 0xEDC5BFE7,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioD_CitHub_WardsFluxP3.pcc",
                    exportId    = 11443,
                    crc         = 0xF95D3472,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioD_CitHub_Dock.pcc",
                    exportId    = 11485,
                    crc         = 0xE8271883,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioD_CerMir_375Lab_vid.pcc",
                    exportId    = 4630,
                    crc         = 0x4D73F4F6,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BIOG_HMF_HED_PROMorph_R.pcc",
                    exportId    = 7552,
                    crc         = 0xF6BFD7B5,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioA_MPCer_000Translevel.pcc",
                    exportId    = 6294,
                    crc         = 0x3451A823,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioA_Cat002_050Shuttle.pcc",
                    exportId    = 2995,
                    crc         = 0xF394E97A,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioD_CitHub_000ProCit.pcc",
                    exportId    = 6451,
                    crc         = 0x2DCFDEA9,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BIOG_HMM_HED_PROMorph.pcc",
                    exportId    = 8818,
                    crc         = 0xB2900BF5,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioD_Cat003_780FinalConvos.pcc",
                    exportId    = 9938,
                    crc         = 0x6574CE07,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioD_Gth001_560Gethries.pcc",
                    exportId    = 7227,
                    crc         = 0x36DACF3F,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioA_Kro001_000LevelTrans.pcc",
                    exportId    = 7156,
                    crc         = 0x1198BA9D,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioD_End001_436CRGrunt.pcc",
                    exportId    = 1568,
                    crc         = 0xECA7DA8F,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioD_End001_436CRMordin.pcc",
                    exportId    = 1456,
                    crc         = 0x9A987362,
                },
                new EmptyMipMaps
                {
                    gameType    = MeType.ME3_TYPE,
                    packagePath = @"\BioGame\CookedPCConsole\BioA_CitHub_Council.pcc",
                    exportId    = 6653,
                    crc         = 0x8645A85C,
                },
            };

            for (int i = 0; i < entries.Count(); i++)
            {
                if (GameData.gameType == entries[i].gameType)
                {
                    Package package = null;
                    try
                    {
                        if (cachePackageMgr != null)
                        {
                            package = cachePackageMgr.OpenPackage(GameData.GamePath + entries[i].packagePath);
                        }
                        else
                        {
                            package = new Package(GameData.GamePath + entries[i].packagePath);
                        }
                    }
                    catch
                    {
                        return(false);
                    }
                    Texture texture = new Texture(package, entries[i].exportId, package.getExportData(entries[i].exportId));
                    if (texture.getCrcTopMipmap() != entries[i].crc)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
예제 #6
0
        public string removeMipMapsME2ME3(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 - package " + (i + 1) + " of " + GameData.packageFiles.Count + " - " + GameData.packageFiles[i]);
                    mainWindow.updateStatusLabel2("");
                }
                if (installer != null)
                {
                    installer.updateStatusMipMaps("Removing empty mipmaps " + (i * 100 / GameData.packageFiles.Count) + "%");
                }
                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);

                            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();
                }
            }
            if (GameData.gameType == MeType.ME3_TYPE)
            {
                TOCBinFile.UpdateAllTOCBinFiles();
            }
            return(errors);
        }
예제 #7
0
        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);
        }
예제 #8
0
        private bool generateBuiltinMapFiles = false; // change to true to enable map files generation

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

            treeScan = null;

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                    if (previewIndex != -1)
                    {
                        if (modFiles[i].tag == FileTextureTag)
                        {
                            Image image = new Image(dst, Image.ImageFormat.DDS);
                            texExplorer.pictureBoxPreview.Image = image.getBitmapARGB();
                        }
                        else
                        {
                            texExplorer.pictureBoxPreview.Image = null;
                        }
                        break;
                    }
                    else if (replace)
                    {
                        if (modFiles[i].tag == FileTextureTag)
                        {
                            FoundTexture foundTexture;
                            foundTexture = textures.Find(s => s.crc == crc);
                            if (foundTexture.crc != 0)
                            {
                                Image image = new Image(dst, Image.ImageFormat.DDS);
                                errors += replaceTexture(image, foundTexture.list, cachePackageMgr, foundTexture.name, crc, verify);
                            }
                            else
                            {
                                log += "Error: Texture " + name + string.Format("_0x{0:X8}", crc) + "is not present in your game setup. Texture skipped." + Environment.NewLine;
                            }
                        }
                        else if (modFiles[i].tag == FileBinaryTag)
                        {
                            string path = GameData.GamePath + pkgPath;
                            if (!File.Exists(path))
                            {
                                errors += "Warning: File " + path + " not exists in your game setup." + Environment.NewLine;
                                log    += "Warning: File " + path + " not exists in your game setup." + Environment.NewLine;
                                continue;
                            }
                            Package pkg = cachePackageMgr.OpenPackage(path);
                            pkg.setExportData(exportId, dst);
                        }
                        else
                        {
                            errors += "Error: Unknown tag for file: " + name + Environment.NewLine;
                            log    += "Error: Unknown tag for file: " + name + Environment.NewLine;
                        }
                    }
                    else
                    {
                        throw new Exception();
                    }
                }
                if (previewIndex == -1 && !extract && !replace)
                {
                    texExplorer.listViewTextures.EndUpdate();
                }
            }
            return(errors);
        }
 public string listTextureMod(string filenameMod, List <FoundTexture> textures, CachePackageMgr cachePackageMgr, TexExplorer texExplorer, ref string log)
 {
     return(processTextureMod(filenameMod, -1, false, false, false, "", textures, cachePackageMgr, texExplorer, ref log));
 }
 public string replaceTextureMod(string filenameMod, List <FoundTexture> textures, CachePackageMgr cachePackageMgr, TexExplorer texExplorer, bool verify, ref string log)
 {
     return(processTextureMod(filenameMod, -1, false, true, verify, "", textures, cachePackageMgr, texExplorer, ref log));
 }
 public string previewTextureMod(string filenameMod, int previewIndex, List <FoundTexture> textures, CachePackageMgr cachePackageMgr, TexExplorer texExplorer, ref string log)
 {
     return(processTextureMod(filenameMod, previewIndex, false, false, false, "", textures, cachePackageMgr, texExplorer, ref log));
 }
 public string extractTextureMod(string filenameMod, string outDir, List <FoundTexture> textures, CachePackageMgr cachePackageMgr, TexExplorer texExplorer, ref string log)
 {
     return(processTextureMod(filenameMod, -1, true, false, false, outDir, textures, cachePackageMgr, texExplorer, ref log));
 }
예제 #14
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("");
            }
        }
예제 #15
0
        private string processTextureMod(string filenameMod, int previewIndex, bool extract, bool replace, string outDir, List <FoundTexture> textures, CachePackageMgr cachePackageMgr, TexExplorer texExplorer, ref string log)
        {
            string errors = "";

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

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

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

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

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

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

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