//internal override void SaveData(BinaryWriter writer) internal override void SaveData(SnipStreamWrapper snipStreamWrapper) { bool hasRecordUnknown = false; //var position = writer.BaseStream.Position; var position = snipStreamWrapper.SnipStream.Position; //WriteString(writer, Name); snipStreamWrapper.WriteStringInFileStream(Name); var compressed = false; byte[] data; //using (var stream = new MemoryStream()) //{ //var dataWriter = new BinaryWriter(stream); snipStreamWrapper.ResetBufferSizeAndPosition(); if (this.FormID == 496431) { compressed = false; } foreach (var subRecord in this.SubRecords) { //subRecord.SaveData(dataWriter); if (subRecord.Name == "????") { hasRecordUnknown = true; } subRecord.SaveData(snipStreamWrapper); //write data into buffer } uint realSize = snipStreamWrapper.OutputBufferLength; if (hasRecordUnknown) { realSize = 0; } //data = stream.ToArray(); //data = stream.ToArray(); if (Properties.Settings.Default.UseDefaultRecordCompression) { compressed = ((this.Flags1 & 0x00040000) != 0) || (Properties.Settings.Default.EnableAutoCompress && Compressor.CompressRecord(Name)) || (Properties.Settings.Default.EnableCompressionLimit && (realSize >= Properties.Settings.Default.CompressionLimit)); //if (compressed) // data = ZLib.Compress(stream, CompressLevel.Best); //data = ZLib.Compress(data); } // ajouter dans zlib un option pour dire oui compresser ou dans le record une variable pour dire que c'est compressé if (Properties.Settings.Default.UsePluginRecordCompression) { compressed = (this.Flags1 & 0x00040000) != 0; } if (compressed & compressLevel != CompressLevel.None) { ZLib.Compress(snipStreamWrapper, compressLevel); data = new byte[ZLibWrapper.OutputBufferLength]; ZLibWrapper.CopyOutputBufferIntoByteArray(data); } else { data = new byte[snipStreamWrapper.OutputBufferLength]; if (snipStreamWrapper.OutputBufferLength > 0) { snipStreamWrapper.CopyOutputBufferToData(ref data); } //data = stream.ToArray(); //data = stream.ToArray(); } //} // using (var stream = new MemoryStream()) var dataSize = (uint)data.Length; var flags = this.Flags1 & ~0x00040000U; if (compressed) { dataSize += 4; flags |= 0x00040000; Debug.WriteLineIf( this.dataSize != dataSize, string.Format("COMPRESSED RECORD [NAME={0} AT POSITION={1}] SIZE DIFFERS FROM ORIGINAL: ORIGINAL={2} ACTUAL={3}, RAW RECORD SIZE={4}", Name, position, this.dataSize, dataSize, realSize)); } snipStreamWrapper.WriteUInt32(dataSize); //writer.Write(dataSize); // Size of compressed section + length snipStreamWrapper.WriteUInt32(flags); //writer.Write(flags); snipStreamWrapper.WriteUInt32(FormID); //writer.Write(this.FormID); snipStreamWrapper.WriteUInt32(Flags2); //writer.Write(this.Flags2); snipStreamWrapper.WriteUInt32(Flags3); //writer.Write(this.Flags3); if (compressed) { snipStreamWrapper.WriteUInt32(realSize); //writer.Write(realSize); } if (dataSize > 0) { snipStreamWrapper.WriteBytesArrayInFileStream(data); //writer.Write(data, 0, data.Length); } }
private void LoadPluginData(FileStream fs, bool headerOnly, string[] recFilter) //LoadPluginData(BinaryReader br, bool headerOnly, string[] recFilter) { bool oldHoldUpdates = HoldUpdates; SnipStreamWrapper snipStreamWrapper = null; try { ZLibWrapper.AllocateBuffers(); RecordsTace.InitListOfRecords(); snipStreamWrapper = new SnipStreamWrapper(fs); //BinaryReader br = new BinaryReader(fs); string s; uint recsize; bool IsOblivion = false; this.Filtered = recFilter != null && recFilter.Length > 0; HoldUpdates = true; s = ReadRecName(snipStreamWrapper.ReadBytes(4)); //s = ReadRecName(br); if (s != "TES4") { throw new Exception("File is not a valid TES4 plugin (Missing TES4 record)"); } // Check for file version by checking the position of the HEDR field in the file. (ie. how big are the record header.) snipStreamWrapper.JumpTo(20, SeekOrigin.Begin); //br.BaseStream.Position = 20; s = ReadRecName(snipStreamWrapper.ReadBytes(4)); //s = ReadRecName(br); if (s == "HEDR") { // Record Header is 20 bytes IsOblivion = true; } else { s = ReadRecName(snipStreamWrapper.ReadBytes(4)); //s = ReadRecName(br); if (s != "HEDR") { throw new Exception("File is not a valid TES4 plugin (Missing HEDR subrecord in the TES4 record)"); } // Record Header is 24 bytes. Or the file is illegal } snipStreamWrapper.JumpTo(4, SeekOrigin.Begin); //br.BaseStream.Position = 4; recsize = snipStreamWrapper.ReadUInt32(); //recsize = br.ReadUInt32(); try { this.AddRecord(new Record("TES4", recsize, snipStreamWrapper, IsOblivion)); } catch (Exception e) { MessageBox.Show(e.Message); } if (!headerOnly) { while (!snipStreamWrapper.Eof()) //while (br.PeekChar() != -1) { s = ReadRecName(snipStreamWrapper.ReadBytes(4)); //s = ReadRecName(br); recsize = snipStreamWrapper.ReadUInt32(); //recsize = br.ReadUInt32(); if (s == "GRUP") { try { this.AddRecord(new GroupRecord(recsize, snipStreamWrapper, IsOblivion, recFilter, false)); //this.AddRecord(new GroupRecord(recsize, br, IsOblivion, recFilter, false)); } catch (Exception e) { MessageBox.Show(e.Message); } } else { bool skip = recFilter != null && Array.IndexOf(recFilter, s) >= 0; if (skip) { long size = recsize + (IsOblivion ? 8 : 12); if ((snipStreamWrapper.ReadUInt32() & 0x00040000) > 0) //if ((br.ReadUInt32() & 0x00040000) > 0) { size += 4; // Add 4 bytes for compressed record since the decompressed size is not included in the record size. } snipStreamWrapper.JumpTo((int)size, SeekOrigin.Current); //br.BaseStream.Position += size; // just position past the data } else { try { this.AddRecord(new Record(s, recsize, snipStreamWrapper, IsOblivion)); //this.AddRecord(new Record(s, recsize, br, IsOblivion)); } catch (Exception e) { MessageBox.Show(e.Message); } } } } } } finally { snipStreamWrapper.CloseAndDisposeFileStream(); snipStreamWrapper = null; Clipboard.SetText("CompressedRecords:" + Environment.NewLine + string.Join <string>(string.Empty, RecordsTace.CompressedRecords) + "AllRecords:" + Environment.NewLine + string.Join <string>(string.Empty, RecordsTace.AllRecords) + "Max Size:" + ZLibWrapper.MaxOutputBufferPosition.ToString(CultureInfo.InvariantCulture)); ZLibWrapper.ReleaseBuffers(); ZLib.ReleaseInflater(); HoldUpdates = oldHoldUpdates; FireRecordListUpdate(this, this); } }
internal Record(string name, uint dataSizeParam, SnipStreamWrapper snipStreamWrapper, bool oblivion) //internal Record(string name, uint dataSize, BinaryReader recordReader, bool oblivion) { bool compressed = false; uint amountRead = 0; uint realSize = 0; //MemoryStream stream = null; //BinaryReader dataReader = null; SubRecord record = null; //long ws; try { this.dataSize = dataSizeParam; this.SubRecords = new AdvancedList <SubRecord>(1) { AllowSorting = false }; //if (snipStreamWrapper.SnipStream.Position >= 1330432) // Name = name; Name = name; RecordsTace.AddRecordToRecordsList(Name); this.Flags1 = snipStreamWrapper.ReadUInt32(); //recordReader.ReadUInt32(); this.FormID = snipStreamWrapper.ReadUInt32(); //recordReader.ReadUInt32(); this.Flags2 = snipStreamWrapper.ReadUInt32(); //recordReader.ReadUInt32(); if (!oblivion) { this.Flags3 = snipStreamWrapper.ReadUInt32(); //recordReader.ReadUInt32(); } //if (this.FormID == 496431) // Name = name; compressed = (this.Flags1 & 0x00040000) != 0; amountRead = 0; realSize = dataSizeParam; if (!compressed) { realSize = dataSizeParam; } if (compressed) { realSize = snipStreamWrapper.ReadUInt32(); // recordReader.ReadUInt32(); // snipStreamWrapper.JumpTo(-4,SeekOrigin.Current); //if (realSize > 0) dataSizeParam -= 4; RecordsTace.AddRecordToCompressedRecordsList(Name); } #if DEBUGCOMPRESSREALSIZE if (compressed & realSize == 0) { Clipboard.SetText(name + " - " + this.FormID.ToString(CultureInfo.InvariantCulture)); } #endif //using (var stream = new MemoryStream(recordReader.ReadBytes((int) dataSize))) //{ //using (var dataReader = compressed ? ZLib.Decompress(stream, (int) realSize) : new BinaryReader(stream)) //{. try { //if (dataSize == 0) // throw new TESParserException("Record.Record: ZLib inflate error. Output buffer is empty."); if (dataSizeParam > 0) //dawnguard.esm at position 6.812.369 at a dataSize == 0 - Record=NAVM { ZLibWrapper.CopyStreamToInputBuffer(snipStreamWrapper.SnipStream, dataSizeParam); //stream = new MemoryStream(recordReader.ReadBytes((int) dataSize)); //dataReader = compressed ? ZLib.Decompress(stream, out compressLevel, (int)realSize) : new BinaryReader(stream); if (compressed & realSize > 0) { //Clipboard.SetText(Name + realSize.ToString(CultureInfo.InvariantCulture)); ZLib.Decompress(compressLevel: out compressLevel, expectedSize: (int)realSize); //Array.Copy(); } else { ZLibWrapper.CopyInputBufferToOutputBuffer(dataSizeParam); } } else { ZLibWrapper.ResetBufferSizeAndPosition(); } } catch (Exception ex) { throw new TESParserException("Record.Record: ZLib error" + Environment.NewLine + "Message: " + ex.Message + Environment.NewLine + "StackTrace: " + ex.StackTrace); } if (compressed & dataSizeParam > 0) //dawnguard.esm at position 6.812.369 at a dataSize == 0 - Record=NAVM { if (ZLibWrapper.OutputBufferLength <= 0) //if (dataReader == null) { throw new TESParserException("Record.Record: ZLib inflate error. Output buffer is empty."); } } while (ZLibWrapper.OutputBufferPosition < ZLibWrapper.OutputBufferLength) //while (dataReader.BaseStream.Position < dataReader.BaseStream.Length) { var type = "XXXX"; uint size = 0; if (realSize == 0) //compressed & { type = "????"; //ReadRecName(ZLibWrapper.Read4Bytes()); size = dataSizeParam; //realSize = dataSizeParam; //this.dataSize = dataSizeParam; } else { type = ReadRecName(ZLibWrapper.Read4Bytes()); //var type = ReadRecName(dataReader); if (type == "XXXX") { ZLibWrapper.ReadUInt16(); //dataReader.ReadUInt16(); size = ZLibWrapper.ReadUInt32(); //dataReader.ReadUInt32(); type = ReadRecName(ZLibWrapper.Read4Bytes()); //ReadRecName(dataReader); ZLibWrapper.ReadUInt16(); //dataReader.ReadUInt16(); } else { size = ZLibWrapper.ReadUInt16(); //dataReader.ReadUInt16(); } } record = new SubRecord(this, type, snipStreamWrapper, size); //record = new SubRecord(this, type, dataReader, size); //var record = new SubRecord(this, type, dataReader, size); this.SubRecords.Add(record); amountRead += (uint)record.Size2; } //} //using (var dataReader = compressed ? ZLib.Decompress(stream, (int) realSize) : new BinaryReader(stream)) //if (dataReader != null) //{ // dataReader.Close(); // dataReader.Dispose(); // dataReader = null; //} if ((compressed & realSize != 0) | (!compressed)) { if (amountRead > realSize) { Debug.Print( " * ERROR: SUB-RECORD {0} DATA DOESN'T MATCH THE SIZE SPECIFIED IN THE HEADER: DATA-SIZE={1} REAL-SIZE={2} AMOUNT-READ={3}", name, dataSizeParam, realSize, amountRead); throw new TESParserException( string.Format( "Subrecord block did not match the size specified in the record header: ExpectedSize={0} ReadSize={1} DataSize={2}", realSize, amountRead, dataSizeParam)); } } this.descNameOverride = this.DefaultDescriptiveName; this.UpdateShortDescription(); // br.BaseStream.Position+=Size; //} //using (var stream = new MemoryStream(recordReader.ReadBytes((int) dataSize))) } catch (Exception ex) { string errMsg = "Message: " + ex.Message + Environment.NewLine + Environment.NewLine + "StackTrace: " + ex.StackTrace + Environment.NewLine + Environment.NewLine + "Source: " + ex.Source + Environment.NewLine + Environment.NewLine + "GetType: " + ex.GetType().ToString(); System.Windows.Forms.Clipboard.SetDataObject(errMsg, true); // Create an EventLog instance and assign its source. EventLog myLog = new EventLog(); myLog.Source = "ThreadException"; myLog.WriteEntry(errMsg); MessageBox.Show(errMsg, "Fatal Error", MessageBoxButtons.OK, MessageBoxIcon.Stop); } finally { //if (stream != null) //{ // stream.Close(); // stream.Dispose(); //} } }
internal void Save(string filePath) { UpdateRecordCount(); string extension = string.Empty; //BinaryWriter bw; SnipStreamWrapper snipStreamWrapper = null; string tmpFile = filePath + ".new"; //if (File.Exists(filePath)) //{ // //bw = new BinaryWriter(File.OpenWrite(filePath + ".new")); // //extension = ".new"; //} //else //{ // //bw = new BinaryWriter(File.OpenWrite(filePath)); // fs = new FileStream(filePath, FileMode.Open, FileAccess.Write); //} //fs = new FileStream(filePath + extension, FileMode.Open, FileAccess.Write); //bw = new BinaryWriter(File.OpenWrite(filePath + extension)); //bw = new BinaryWriter(File.OpenWrite(tmpFile)); FileStream fs = new FileStream(tmpFile, FileMode.Create, FileAccess.Write, FileShare.None); try { ZLibWrapper.AllocateBuffers(); snipStreamWrapper = new SnipStreamWrapper(fs); snipStreamWrapper.AllocateBuffers(); this.SaveData(snipStreamWrapper); Name = Path.GetFileName(filePath); PluginPath = Path.GetDirectoryName(filePath); } finally { //bw.Close(); snipStreamWrapper.CloseAndDisposeFileStream(); snipStreamWrapper.ReleaseBuffers(); snipStreamWrapper = null; fs = null; } try { // ** Create Backup bool backupExists = true; int backupVersion = 0; string backupFolder = CreateBackupFolder(filePath); while (backupExists && backupVersion < 999) { backupExists = File.Exists(Path.Combine(backupFolder, Name) + string.Format(".{0,3:D3}.bak", backupVersion)); if (backupExists) { backupVersion++; } } string backupFile = Path.Combine(backupFolder, Name) + string.Format(".{0,3:D3}.bak", backupVersion); File.Copy(tmpFile, backupFile, true); //if (existed) //{ ////string newFile = filePath; //string backupFile = Path.Combine(backupFolder, Name) + string.Format(".{0,3:D3}.bak", backupVersion); //File.Copy(tmpFile, backupFile, true); if (File.Exists(filePath)) { File.Delete(filePath); } File.Move(tmpFile, filePath); //} } catch (Exception ex) { string msg = string.Format(ex.Message); MessageBox.Show( msg, TranslateUI.TranslateUiGlobalization.ResManager.GetString("Application_Title"), MessageBoxButtons.OK, MessageBoxIcon.Error); Clipboard.SetText(msg); } var tes4 = this.Records.OfType <Record>().FirstOrDefault(x => x.Name == "TES4"); if (tes4 != null && (tes4.Flags1 & 0x80) != 0) { if (Properties.Settings.Default.SaveStringsFiles) { string prefix = Path.Combine(Path.Combine(Path.GetDirectoryName(filePath), "Strings"), Path.GetFileNameWithoutExtension(filePath)); prefix += "_" + Properties.Settings.Default.LocalizationName; this.SaveStrings(prefix); } } StringsDirty = false; }