public string removeMipMapsME2ME3(List <FoundTexture> textures, Package package, RemoveMipsEntry removeEntry, MainWindow mainWindow, Installer installer, bool ipc, bool repack) { string errors = ""; for (int l = 0; l < removeEntry.exportIDs.Count; l++) { int exportID = removeEntry.exportIDs[l]; using (Texture texture = new Texture(package, exportID, package.getExportData(exportID), false)) { if (!texture.mipMapsList.Exists(s => s.storageType == Texture.StorageTypes.empty)) { continue; } do { texture.mipMapsList.Remove(texture.mipMapsList.First(s => s.storageType == Texture.StorageTypes.empty)); } while (texture.mipMapsList.Exists(s => s.storageType == Texture.StorageTypes.empty)); texture.properties.setIntValue("SizeX", texture.mipMapsList.First().width); texture.properties.setIntValue("SizeY", texture.mipMapsList.First().height); texture.properties.setIntValue("MipTailBaseIdx", texture.mipMapsList.Count() - 1); using (MemoryStream newData = new MemoryStream()) { newData.WriteFromBuffer(texture.properties.toArray()); newData.WriteFromBuffer(texture.toArray(package.exportsTable[exportID].dataOffset + (uint)newData.Position)); package.setExportData(exportID, newData.ToArray()); } } } if (package.SaveToFile(repack, false, installer != null)) { if (repack && Installer.pkgsToRepack != null) { Installer.pkgsToRepack.Remove(package.packagePath); } if (Installer.pkgsToMarker != null) { Installer.pkgsToMarker.Remove(package.packagePath); } } package.Dispose(); return(errors); }
public string removeMipMapsME1(int phase, List <FoundTexture> textures, Package package, RemoveMipsEntry removeEntry, MainWindow mainWindow, Installer installer, bool ipc) { string errors = ""; for (int l = 0; l < removeEntry.exportIDs.Count; l++) { int exportID = removeEntry.exportIDs[l]; using (Texture texture = new Texture(package, exportID, package.getExportData(exportID), false)) { if (!texture.mipMapsList.Exists(s => s.storageType == Texture.StorageTypes.empty)) { continue; } do { texture.mipMapsList.Remove(texture.mipMapsList.First(s => s.storageType == Texture.StorageTypes.empty)); } while (texture.mipMapsList.Exists(s => s.storageType == Texture.StorageTypes.empty)); texture.properties.setIntValue("SizeX", texture.mipMapsList.First().width); texture.properties.setIntValue("SizeY", texture.mipMapsList.First().height); texture.properties.setIntValue("MipTailBaseIdx", texture.mipMapsList.Count() - 1); FoundTexture foundTexture = new FoundTexture(); int foundListEntry = -1; int foundTextureEntry = -1; string pkgName = GameData.RelativeGameData(package.packagePath).ToLowerInvariant(); for (int k = 0; k < textures.Count; k++) { for (int t = 0; t < textures[k].list.Count; t++) { if (textures[k].list[t].exportID == exportID && textures[k].list[t].path.ToLowerInvariant() == pkgName) { foundTexture = textures[k]; foundTextureEntry = k; foundListEntry = t; break; } } } if (foundListEntry == -1) { if (ipc) { Console.WriteLine("[IPC]ERROR Texture " + package.exportsTable[exportID].objectName + " not found in tree: " + removeEntry.pkgPath + ", skipping..."); Console.Out.Flush(); } else { errors += "Error: Texture " + package.exportsTable[exportID].objectName + " not found in tree: " + removeEntry.pkgPath + ", skipping..." + Environment.NewLine; } continue; } MatchedTexture m = foundTexture.list[foundListEntry]; if (m.linkToMaster != -1) { if (phase == 1) { continue; } MatchedTexture foundMasterTex = foundTexture.list[m.linkToMaster]; if (texture.mipMapsList.Count != foundMasterTex.masterDataOffset.Count) { if (ipc) { Console.WriteLine("[IPC]ERROR Texture " + package.exportsTable[exportID].objectName + " in package: " + foundMasterTex.path + " has wrong reference, skipping..." + Environment.NewLine); Console.Out.Flush(); } else { errors += "Error: Texture " + package.exportsTable[exportID].objectName + " in package: " + foundMasterTex.path + " has wrong reference, skipping..." + Environment.NewLine; } continue; } for (int t = 0; t < texture.mipMapsList.Count; t++) { Texture.MipMap mipmap = texture.mipMapsList[t]; if (mipmap.storageType == Texture.StorageTypes.extLZO || mipmap.storageType == Texture.StorageTypes.extZlib || mipmap.storageType == Texture.StorageTypes.extUnc) { mipmap.dataOffset = foundMasterTex.masterDataOffset[t]; texture.mipMapsList[t] = mipmap; } } } uint packageDataOffset; using (MemoryStream newData = new MemoryStream()) { newData.WriteFromBuffer(texture.properties.toArray()); packageDataOffset = package.exportsTable[exportID].dataOffset + (uint)newData.Position; newData.WriteFromBuffer(texture.toArray(packageDataOffset)); package.setExportData(exportID, newData.ToArray()); } if (m.linkToMaster == -1) { if (phase == 2) { throw new Exception(); } m.masterDataOffset = new List <uint>(); for (int t = 0; t < texture.mipMapsList.Count; t++) { m.masterDataOffset.Add(packageDataOffset + texture.mipMapsList[t].internalOffset); } } m.removeEmptyMips = false; textures[foundTextureEntry].list[foundListEntry] = m; } } if (package.SaveToFile(false, false, installer != null)) { if (Installer.pkgsToMarker != null) { Installer.pkgsToMarker.Remove(package.packagePath); } } package.Dispose(); return(errors); }
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); }
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); }
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(""); } }
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); }