public static Decompress ( string pccFileName ) : byte[] | ||
pccFileName | string | pcc file's name to open. |
return | byte[] |
/// <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 the name list and import list, appends changed and new exports, and then appends the export list. /// Changed exports with the same datasize or smaller are updaed in place. /// </summary> /// <param name="newFileName">The filename to write to</param> private void appendSave(string newFileName) { IEnumerable <IExportEntry> replaceExports; IEnumerable <IExportEntry> 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)); var exportsBeforeNameTable = exports.Where(exp => exp.DataOffset < NameOffset); if (exportsBeforeNameTable.Count() > 0) { max = exportsBeforeNameTable.Max(e => e.DataOffset); } else { //doesn't seem to be actual append... seems to be some sort of bug with mem/me3explorer mixing, or maybe just me3exp, where sequence = 0 lenght max = exports.Max(maxExport => maxExport.DataOffset); } } else { IEnumerable <IExportEntry> 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); } IExportEntry lastExport = exports.Find(export => export.DataOffset == max); lastDataOffset = lastExport.DataOffset + lastExport.DataSize; byte[] oldPCC = new byte[lastDataOffset]; 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 (IExportEntry 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; //Write out the namelist foreach (string name in names) { newPCCStream.WriteValueS32(-(name.Length + 1)); newPCCStream.WriteString(name + "\0", (uint)(name.Length + 1) * 2, Encoding.Unicode); } //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 (IExportEntry export in appendExports) { export.DataOffset = (int)newPCCStream.Position; export.DataSize = export.Data.Length; UpdateOffsets(export); newPCCStream.WriteBytes(export.Data); } //Write the export list ExportOffset = (int)newPCCStream.Position; ExportCount = exports.Count; foreach (ME3ExportEntry export in exports) { newPCCStream.WriteBytes(export.Header); } IsAppend = true; //write the updated header newPCCStream.Seek(0, SeekOrigin.Begin); newPCCStream.WriteBytes(header); } AfterSave(); }
/// <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 <IExportEntry> replaceExports; IEnumerable <IExportEntry> 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 <IExportEntry> 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); } IExportEntry 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(); }
/// <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 the name list and import list, appends changed and new exports, and then appends the export list. /// Changed exports with the same datasize or smaller are updaed in place. /// </summary> /// <param name="newFileName">The filename to write to</param> private void appendSave(string newFileName) { IEnumerable <ME3ExportEntry> replaceExports; IEnumerable <ME3ExportEntry> 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 <ME3ExportEntry> 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); } ME3ExportEntry lastExport = exports.Find(export => export.DataOffset == max); lastDataOffset = lastExport.DataOffset + lastExport.DataSize; byte[] oldPCC = new byte[lastDataOffset]; 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 (ME3ExportEntry 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; //Write out the namelist foreach (string name in names) { newPCCStream.WriteValueS32(-(name.Length + 1)); newPCCStream.WriteString(name + "\0", (uint)(name.Length + 1) * 2, Encoding.Unicode); } //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 (ME3ExportEntry export in appendExports) { export.DataOffset = (int)newPCCStream.Position; export.DataSize = export.Data.Length; //update offsets for pcc-stored audio in wwisestreams if (export.ClassName == "WwiseStream" && export.GetProperty <NameProperty>("Filename") == null) { byte[] binData = export.getBinaryData(); binData.OverwriteRange(12, BitConverter.GetBytes(export.DataOffset + export.propsEnd() + 16)); export.setBinaryData(binData); } newPCCStream.WriteBytes(export.Data); } //Write the export list ExportOffset = (int)newPCCStream.Position; ExportCount = exports.Count; foreach (ME3ExportEntry export in exports) { newPCCStream.WriteBytes(export.header); } IsAppend = true; //write the updated header newPCCStream.Seek(0, SeekOrigin.Begin); newPCCStream.WriteBytes(header); } AfterSave(); }