public void Save(string content) { Kooboo.IO.IOUtility.EnsureDirectoryExists(Path.GetDirectoryName(this.PhysicalPath)); using (FileStream fs = new FileStream(this.PhysicalPath, FileMode.Create, FileAccess.Write, FileShare.Write)) { fs.WriteString(content); } }
/// <summary> /// This method is an alternate way of saving PCCs /// Instead of reconstructing the PCC from the data taken, it instead copies across the existing /// data, appends new exports, updates the export list, changes the namelist location and updates the /// value in the header /// </summary> /// <param name="newFileName">The filename to write to</param> /// <param name="attemptOverwrite">Do you wish to attempt to overwrite the existing export</param> public string appendSave(string newFileName, bool attemptOverwrite, int HeadeNameOffset = 34) { string rtValues = ""; string loc = Path.GetDirectoryName(Application.ExecutablePath); //Get info expInfoEndOffset = ExportOffset + Exports.Sum(export => export.header.Length); if (expDataBegOffset < expInfoEndOffset) expDataBegOffset = expInfoEndOffset; //List<ExportEntry> unchangedExports = Exports.Where(export => !export.hasChanged || (export.hasChanged && export.Data.Length <= export.DataSize)).ToList(); List<ExportEntry> unchangedExports = Exports.Where(export => !export.hasChanged).ToList(); List<ExportEntry> changedExports; List<ExportEntry> replaceExports = null; if (!attemptOverwrite) { //If not trying to overwrite, then select all exports that have been changed changedExports = Exports.Where(export => export.hasChanged).ToList(); //MessageBox.Show("No changed exports = " + changedExports.Count); //throw new NullReferenceException(); } else { //If we are trying to overwrite, then split up the exports that have been changed that can and can't overwrite the originals changedExports = Exports.Where(export => export.hasChanged && export.Data.Length > export.DataSize).ToList(); replaceExports = Exports.Where(export => export.hasChanged && export.Data.Length <= export.DataSize).ToList(); } int max = Exports.Max(maxExport => maxExport.DataOffset); ExportEntry lastExport = Exports.Find(export => export.DataOffset == max); int lastDataOffset = lastExport.DataOffset + lastExport.DataSize; //byte[] oldName; if (!attemptOverwrite) { int offset = ExportOffset; foreach (ExportEntry export in Exports) { if (!export.hasChanged) { offset += export.header.Length; } else break; } rtValues += offset + " "; using (FileStream stream = new FileStream(loc + "\\exec\\infoCache.bin", FileMode.Append)) { stream.Seek(0, SeekOrigin.End); rtValues += stream.Position + " "; //throw new FileNotFoundException(); stream.Write(changedExports[0].header, 32, 8); } } byte[] oldPCC = new byte[lastDataOffset];//Check whether compressed using (FileStream oldPccStream = new FileStream(this.FileName, FileMode.Open)) { //Read the original data up to the last export oldPccStream.Read(oldPCC, 0, lastDataOffset); } //Start writing the new file using (FileStream newPCCStream = new FileStream(newFileName, FileMode.Create)) { newPCCStream.Seek(0, SeekOrigin.Begin); //Write the original file up til the last original export (note that this leaves in all the original exports) newPCCStream.Write(oldPCC, 0, lastDataOffset); if (!attemptOverwrite) { //If we're not trying to overwrite then just append all the changed exports foreach (ExportEntry export in changedExports) { export.DataOffset = (int)newPCCStream.Position; export.DataSize = export.Data.Length; newPCCStream.Write(export.Data, 0, export.Data.Length); } } else { //If we are then move to each offset and overwrite the data with the new exports foreach (ExportEntry export in replaceExports) { //newPCCStream.Position = export.DataOffset; newPCCStream.Seek(export.DataOffset, SeekOrigin.Begin); export.DataSize = export.Data.Length; newPCCStream.Write(export.Data, 0, export.Data.Length); } //Then move to the end and append the new data //newPCCStream.Position = lastDataOffset; newPCCStream.Seek(lastDataOffset, SeekOrigin.Begin); foreach (ExportEntry export in changedExports) { export.DataOffset = (int)newPCCStream.Position; export.DataSize = export.Data.Length; newPCCStream.Write(export.Data, 0, export.Data.Length); } } //Set the new nameoffset and namecounts NameOffset = (int)newPCCStream.Position; NameCount = Names.Count; //Then write out the namelist foreach (NameEntry name in Names) { newPCCStream.WriteValueS32(name.name.Length + 1); newPCCStream.WriteString(name + "\0", (uint)(name.name.Length + 1), Encoding.ASCII); newPCCStream.WriteValueS32(name.unk); newPCCStream.WriteValueS32(name.flags); } //Move to the name info position in the header - not a strong piece of code, but it's working so far //newPCCStream.Position = 34; newPCCStream.Seek(HeadeNameOffset, SeekOrigin.Begin); //And write the new info byte[] nameHeader = new byte[8]; byte[] nameCount = BitConverter.GetBytes(NameCount); byte[] nameOff = BitConverter.GetBytes(NameOffset); for (int i = 0; i < 4; i++) nameHeader[i] = nameCount[i]; for (int i = 0; i < 4; i++) nameHeader[i + 4] = nameOff[i]; newPCCStream.Write(nameHeader, 0, 8); //update the import list newPCCStream.Seek(ImportOffset, SeekOrigin.Begin); foreach (ImportEntry import in Imports) { newPCCStream.Write(import.header, 0, import.header.Length); } //Finally, update the export list newPCCStream.Seek(ExportOffset, SeekOrigin.Begin); foreach (ExportEntry export in Exports) { newPCCStream.Write(export.header, 0, export.header.Length); } if (!attemptOverwrite) { using (FileStream stream = new FileStream(loc + "\\exec\\infoCache.bin", FileMode.Append)) { stream.Seek(0, SeekOrigin.End); rtValues += stream.Position + " "; stream.Write(changedExports[0].header, 32, 8); } } } return rtValues; }
/// <summary> /// Saves to file. /// </summary> /// <param name="filePath">The file path.</param> /// <param name="body">The body.</param> public static void SaveStringToFile(string filePath, string body) { var dir = Path.GetDirectoryName(filePath); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } using (FileStream fileStream = new FileStream(filePath, FileMode.Create, FileAccess.Write)) { fileStream.WriteString(body); } }
/// <summary> /// This method is an alternate way of saving PCCs /// Instead of reconstructing the PCC from the data taken, it instead copies across the existing /// data, appends new exports, updates the export list, changes the namelist location and updates the /// value in the header /// </summary> /// <param name="newFileName">The filename to write to</param> /// <param name="attemptOverwrite">Do you wish to attempt to overwrite the existing export</param> public string altSaveToFile(string newFileName, bool attemptOverwrite, int HeadeNameOffset = 34) { DebugOutput.PrintLn("Saving pcc with alternate method."); string rtValues = ""; string loc = KFreonLib.Misc.Methods.GetExecutingLoc(); //Check whether compressed if (this.bCompressed) KFreonLib.PCCObjects.Misc.PCCDecompress(this.pccFileName); //Get info expInfoEndOffset = ExportOffset + Exports.Sum(export => export.info.Length); if (expDataBegOffset < expInfoEndOffset) expDataBegOffset = expInfoEndOffset; //List<ExportEntry> unchangedExports = Exports.Where(export => !export.hasChanged || (export.hasChanged && export.Data.Length <= export.DataSize)).ToList(); List<ME3ExportEntry> unchangedExports = Exports.Where(export => !export.hasChanged).ToList(); List<ME3ExportEntry> changedExports; List<ME3ExportEntry> replaceExports = null; if (!attemptOverwrite) { //If not trying to overwrite, then select all exports that have been changed changedExports = Exports.Where(export => export.hasChanged).ToList(); //MessageBox.Show("No changed exports = " + changedExports.Count); //throw new NullReferenceException(); } else { //If we are trying to overwrite, then split up the exports that have been changed that can and can't overwrite the originals changedExports = Exports.Where(export => export.hasChanged && export.Data.Length > export.DataSize).ToList(); replaceExports = Exports.Where(export => export.hasChanged && export.Data.Length <= export.DataSize).ToList(); } //ExportEntry lastExport = unchangedExports.Find(export => export.DataOffset == unchangedExports.Max(maxExport => maxExport.DataOffset)); uint max = Exports.Max(maxExport => maxExport.DataOffset); ME3ExportEntry lastExport = Exports.Find(export => export.DataOffset == max); int lastDataOffset = (int)(lastExport.DataOffset + lastExport.DataSize); byte[] oldPCC = new byte[lastDataOffset]; //byte[] oldName; if (!attemptOverwrite) { int offset = ExportOffset; foreach (ME3ExportEntry export in Exports) { if (!export.hasChanged) { offset += export.info.Length; } else break; } rtValues += offset.ToString() + " "; using (FileStream stream = new FileStream(loc + "\\exec\\infoCache.bin", FileMode.Append)) { stream.Seek(0, SeekOrigin.End); rtValues += stream.Position + " "; //throw new FileNotFoundException(); stream.Write(changedExports[0].info, 32, 8); } } using (FileStream oldPccStream = new FileStream(this.pccFileName, FileMode.Open)) { //Read the original data up to the last export oldPccStream.Read(oldPCC, 0, lastDataOffset); #region Unused code /* Maybe implement this if I want to directly copy the names across. * Not useful at this time if (NameOffset == 0x8E) { oldName = new byte[ImportOffset - 0x8E]; oldPccStream.Seek(0x8E, SeekOrigin.Begin); oldPccStream.Read(oldName, 0, (int)oldPccStream.Length - lastDataOffset); } else { oldName = new byte[oldPccStream.Length - lastDataOffset]; oldPccStream.Seek(lastDataOffset, SeekOrigin.Begin); oldPccStream.Read(oldName, 0, (int)oldPccStream.Length - lastDataOffset); } * */ #endregion } //Start writing the new file using (FileStream newPCCStream = new FileStream(newFileName, FileMode.Create)) { Console.WriteLine(); Console.WriteLine("Starting Save"); newPCCStream.Seek(0, SeekOrigin.Begin); Console.WriteLine("newPCCStream length: " + newPCCStream.Length); //Write the original file up til the last original export (note that this leaves in all the original exports) newPCCStream.Write(oldPCC, 0, lastDataOffset); Console.WriteLine("OldPCC length: " + oldPCC.Length); Console.WriteLine("lastDataOFfset: " + lastDataOffset); Console.WriteLine("overwriting?: " + attemptOverwrite); if (!attemptOverwrite) { //If we're not trying to overwrite then just append all the changed exports foreach (ME3ExportEntry export in changedExports) { export.DataOffset = (uint)newPCCStream.Position; export.DataSize = export.Data.Length; newPCCStream.Write(export.Data, 0, export.Data.Length); } } else { Console.WriteLine("replaceExports count: " + replaceExports.Count); //If we are then move to each offset and overwrite the data with the new exports foreach (ME3ExportEntry export in replaceExports) { //newPCCStream.Position = export.DataOffset; newPCCStream.Seek(export.DataOffset, SeekOrigin.Begin); export.DataSize = export.Data.Length; newPCCStream.Write(export.Data, 0, export.Data.Length); //Console.WriteLine("exports.DataOffset: " + export.DataOffset); //Console.WriteLine("export datalength: " + export.Data.Length); } //Then move to the end and append the new data //newPCCStream.Position = lastDataOffset; newPCCStream.Seek(lastDataOffset, SeekOrigin.Begin); Console.WriteLine("changedExports count: " + changedExports.Count); foreach (ME3ExportEntry export in changedExports) { export.DataOffset = (uint)newPCCStream.Position; //Console.WriteLine("newstream position: " + newPCCStream.Position); export.DataSize = export.Data.Length; //Console.WriteLine("export size: " + export.DataSize); newPCCStream.Write(export.Data, 0, export.Data.Length); //Console.WriteLine("datalength: " + export.Data.Length); } } //Set the new nameoffset and namecounts NameOffset = (int)newPCCStream.Position; Console.WriteLine("nameoffset: " + NameOffset); NameCount = Names.Count; Console.WriteLine("namecount: " + Names.Count); //Then write out the namelist foreach (string name in Names) { //Console.WriteLine("name: " + name); newPCCStream.WriteValueS32(-(name.Length + 1)); newPCCStream.WriteString(name + "\0", (uint)(name.Length + 1) * 2, Encoding.Unicode); } Console.WriteLine("newPCCStream.length: " + newPCCStream.Length); //Move to the name info position in the header - not a strong piece of code, but it's working so far //newPCCStream.Position = 34; newPCCStream.Seek(HeadeNameOffset, SeekOrigin.Begin); Console.WriteLine("headernameoffset: " + HeadeNameOffset); //And write the new info byte[] nameHeader = new byte[8]; byte[] nameCount = BitConverter.GetBytes(NameCount); byte[] nameOff = BitConverter.GetBytes(NameOffset); for (int i = 0; i < 4; i++) nameHeader[i] = nameCount[i]; for (int i = 0; i < 4; i++) nameHeader[i + 4] = nameOff[i]; newPCCStream.Write(nameHeader, 0, 8); //Finally, update the export list newPCCStream.Seek(ExportOffset, SeekOrigin.Begin); foreach (ME3ExportEntry export in Exports) { newPCCStream.Write(export.info, 0, export.info.Length); } if (!attemptOverwrite) { using (FileStream stream = new FileStream(loc + "\\exec\\infoCache.bin", FileMode.Append)) { stream.Seek(0, SeekOrigin.End); rtValues += stream.Position + " "; stream.Write(changedExports[0].info, 32, 8); } } } return rtValues; }
private void ExtractAndBuildLog(string extractPath, List<TPFTexInfo> tmptexes) { // Heff: delete earlier temp contents, create temp folder: if (Directory.Exists(extractPath)) Directory.Delete(extractPath, true); Directory.CreateDirectory(extractPath); using (FileStream fs = new FileStream(extractPath + "\\MEResults.log", FileMode.Create)) { var hashes = new List<uint>(); var texes = new List<TPFTexInfo>(); foreach (TPFTexInfo tex in tmptexes) { // KFreon: Ignore textures with no hash if (tex.Hash == 0) continue; // Heff: ignore duplicates so that texmod's generator doesn't include them several times. if (hashes.Contains(tex.Hash)) continue; hashes.Add(tex.Hash); texes.Add(tex); // KFreon: Write hashes to log string hash = KFreonLib.Textures.Methods.FormatTexmodHashAsString(tex.Hash); string name = tex.TexName; if (string.IsNullOrEmpty(name)) name = tex.FileName; string append = "_" + hash + Path.GetExtension(tex.FileName); if (name.Contains(hash)) append = ""; fs.WriteString(hash + "|" + name + append + Environment.NewLine); } fs.WriteString("\0"); Extractor(extractPath, null, t => texes.Contains(t)); } }
/// <summary> /// This method is an alternate way of saving PCCs /// Instead of reconstructing the PCC from the data taken, it instead copies across the existing /// data, appends new exports, updates the export list, changes the namelist location and updates the /// value in the header /// </summary> /// <param name="newFileName">The filename to write to</param> /// public void appendSave(string newFileName) { IEnumerable<ME2ExportEntry> replaceExports; IEnumerable<ME2ExportEntry> appendExports; int lastDataOffset; int max; if (IsAppend) { replaceExports = exports.Where(export => export.DataChanged && export.DataOffset < NameOffset && export.DataSize <= export.OriginalDataSize); appendExports = exports.Where(export => export.DataOffset > NameOffset || (export.DataChanged && export.DataSize > export.OriginalDataSize)); max = exports.Where(exp => exp.DataOffset < NameOffset).Max(e => e.DataOffset); } else { IEnumerable<ME2ExportEntry> changedExports; changedExports = exports.Where(export => export.DataChanged); replaceExports = changedExports.Where(export => export.DataSize <= export.OriginalDataSize); appendExports = changedExports.Except(replaceExports); max = exports.Max(maxExport => maxExport.DataOffset); } ME2ExportEntry lastExport = exports.Find(export => export.DataOffset == max); lastDataOffset = lastExport.DataOffset + lastExport.DataSize; byte[] oldPCC = new byte[lastDataOffset];//Check whether compressed if (IsCompressed) { oldPCC = CompressionHelper.Decompress(FileName).Take(lastDataOffset).ToArray(); IsCompressed = false; } else { using (FileStream oldPccStream = new FileStream(this.FileName, FileMode.Open)) { //Read the original data up to the last export oldPccStream.Read(oldPCC, 0, lastDataOffset); } } //Start writing the new file using (FileStream newPCCStream = new FileStream(newFileName, FileMode.Create)) { newPCCStream.Seek(0, SeekOrigin.Begin); //Write the original file up til the last original export (note that this leaves in all the original exports) newPCCStream.Write(oldPCC, 0, lastDataOffset); //write the in-place export updates foreach (ME2ExportEntry export in replaceExports) { newPCCStream.Seek(export.DataOffset, SeekOrigin.Begin); export.DataSize = export.Data.Length; newPCCStream.WriteBytes(export.Data); } newPCCStream.Seek(lastDataOffset, SeekOrigin.Begin); //Set the new nameoffset and namecounts NameOffset = (int)newPCCStream.Position; NameCount = names.Count; //Then write out the namelist foreach (string name in names) { newPCCStream.WriteValueS32(name.Length + 1); newPCCStream.WriteString(name); newPCCStream.WriteByte(0); newPCCStream.WriteValueS32(-14); } //Write the import list ImportOffset = (int)newPCCStream.Position; ImportCount = imports.Count; foreach (ImportEntry import in imports) { newPCCStream.WriteBytes(import.header); } //append the new data foreach (ME2ExportEntry export in appendExports) { export.DataOffset = (int)newPCCStream.Position; export.DataSize = export.Data.Length; newPCCStream.Write(export.Data, 0, export.Data.Length); } //Write the export list ExportOffset = (int)newPCCStream.Position; ExportCount = exports.Count; foreach (ME2ExportEntry export in exports) { newPCCStream.WriteBytes(export.header); } IsAppend = true; //write the updated header newPCCStream.Seek(0, SeekOrigin.Begin); newPCCStream.WriteBytes(header); } AfterSave(); }
private void ExtractAndBuildLog(string extractPath) { // KFreon: Create path if necessary if (!Directory.Exists(extractPath)) Directory.CreateDirectory(extractPath); using (FileStream fs = new FileStream(extractPath + "\\MEResults.log", FileMode.Create)) { foreach (TPFTexInfo tex in LoadedTexes) { // KFreon: Ignore textures with no hash if (tex.Hash == 0) continue; // KFreon: Write hashes to log string hash = KFreonLib.Textures.Methods.FormatTexmodHashAsString(tex.Hash); fs.WriteString(hash + "|" + tex.FileName + "\n"); } Extractor(extractPath, null, t => t.Hash != 0 && !t.isDef); } }
private void ExtractAndBuildLog(string extractPath) { // Heff: delete earlier temp contents, create temp folder: if (Directory.Exists(extractPath)) Directory.Delete(extractPath, true); Directory.CreateDirectory(extractPath); using (FileStream fs = new FileStream(extractPath + "\\MEResults.log", FileMode.Create)) { var hashes = new List<uint>(); var texes = new List<TPFTexInfo>(); foreach (TPFTexInfo tex in LoadedTexes) { // KFreon: Ignore textures with no hash if (tex.Hash == 0) continue; // Heff: ignore duplicates so that texmod's generator doesn't include them several times. if (hashes.Contains(tex.Hash)) continue; hashes.Add(tex.Hash); texes.Add(tex); // KFreon: Write hashes to log string hash = KFreonLib.Textures.Methods.FormatTexmodHashAsString(tex.Hash); fs.WriteString(hash + "|" + tex.FileName + "\n"); } Extractor(extractPath, null, t => texes.Contains(t)); } }