/// <summary> /// Writes the grf to the given Filename /// </summary> /// <param name="destinationPath"></param> /// <param name="repack"> </param> /// <returns></returns> public bool WriteGrf(string destinationPath, bool repack) { // Write to temp file string tmpDestinationPath = destinationPath + "tmp"; using (FileStream fs = File.OpenWrite(tmpDestinationPath)) { using (mWriter = new BinaryWriter(fs)) { int iLengthUnCompressed; byte[] fileTableDataCompressed; using (var fileTableStream = new MemoryStream()) { mWriter.Seek((int)GrfHeaderLen, SeekOrigin.Begin); // Write file binary data & temporary write file table int filesWritten; if (repack || AlwaysRepack) { filesWritten = WriteFileData(fileTableStream); } else { filesWritten = WriteFileDataDirty(fileTableStream); } // Save the offset after writing binary data var thisPos = (int)mWriter.BaseStream.Position; // Write grf header mWriter.Seek(0, SeekOrigin.Begin); foreach (var c in MagicHeader) { mWriter.Write((byte)c); // header (15) } foreach (var c in AllowEncrypt) { mWriter.Write((byte)c); // encrypt (15) } mWriter.Write((uint)(thisPos - GrfHeaderLen)); // tableOffset mWriter.Write(mFilecountNumber1); mWriter.Write((uint)(filesWritten + mFilecountNumber1 + 7)); // number2 // Always default version Version = GrfDefaultVersion; mWriter.Write(Version); // GRF Version mWriter.Seek(thisPos, SeekOrigin.Begin); // Compress file table data iLengthUnCompressed = (int)fileTableStream.Length; fileTableDataCompressed = Deflate.Compress(fileTableStream.ToArray(), true); } // Write length and data mWriter.Write(fileTableDataCompressed.Length); // compressed mWriter.Write(iLengthUnCompressed); // uncompressed mWriter.Write(fileTableDataCompressed, 0, fileTableDataCompressed.Length); // data itself } } // If we want to overwrite the previous opened GRF, close it first if (mFilepath == destinationPath) { Flush(); } // Ensure nothing blocks the move File.Delete(destinationPath); // Move it finally File.Move(destinationPath + "tmp", destinationPath); // Fore clean up GC.Collect(); return(true); }
/// <summary> /// Writes the binary data to the stream. /// </summary> /// <param name="grf"></param> /// <param name="writer"></param> internal void WriteToBinaryTable(RoGrfFile grf, BinaryWriter writer) { // Skip deleted files if (IsDeleted) { return; } byte[] buf; // Update new offset DataOffset = (uint)writer.BaseStream.Position; // Either new or changed? if (IsUpdated == false && IsAdded == false) { // Auto-convert to 0x200 compression (deflate) if (grf.Version != 0x200) { // #1: Decompress buf and update length buf = grf.GetFileData(NameHash, true); LengthUnCompressed = (uint)buf.Length; // #2: Compress and update length buf = Deflate.Compress(buf, true); LengthCompressed = (uint)buf.Length; LengthCompressedAlign = (uint)buf.Length; } else { // Get compressed data buf = grf.GetFileData(NameHash, false); } } else { // Added or updated files, load data from origin filepath if (File.Exists(NewFilepath) == false) { throw new Exception("WriteItems(): File of new or updated item not found: " + NewFilepath); } buf = File.ReadAllBytes(NewFilepath); LengthUnCompressed = (uint)buf.Length; buf = Deflate.Compress(buf, true); LengthCompressed = LengthCompressedAlign = (uint)buf.Length; } try { // Check if the buf is compressed if (buf.Length != LengthCompressed && buf.Length != LengthCompressedAlign) { // The buf has to be compressed, so decompress it byte[] bufUncompressed = Deflate.Decompress(buf); // Update length, if decompression seems to be correct if (bufUncompressed.Length == 0 || bufUncompressed.Length != LengthUnCompressed) { // Narf, corrupt file or something like that // Just write it.. //throw new Exception("WriteItems(): Item " + Filepath + ", DataLen missmatch"); } else { // Decompression was succesfull, so update size LengthCompressed = (uint)Deflate.GetCompressedLength(bufUncompressed); } } // Seems like a valid buf, write it writer.Write(buf); } catch (Exception e) { System.Diagnostics.Debug.WriteLine(e); } }