Пример #1
0
        /// <summary>
        /// Reads the uncompressed body of versions equal or above 0x200.
        /// The body is ZIP (deflate) compressed.
        /// </summary>
        /// <param name="binReader"></param>
        /// <param name="fileCount"></param>
        /// <param name="skipFiles"></param>
        /// <returns></returns>
        private bool ReadFilesVersion2(BinaryReader binReader, int fileCount, bool skipFiles)
        {
            int lengthCompressed   = binReader.ReadInt32();
            int lengthUnCompressed = binReader.ReadInt32();

            mFileTableLength = (ulong)lengthUnCompressed;
            var bufCompressed = new byte[lengthCompressed];

            mFiletableUncompressed = new byte[(int)mFileTableLength];
            binReader.Read(bufCompressed, 0, lengthCompressed);

            mFiletableUncompressed = Deflate.Decompress(bufCompressed);

            /*
             * if (mFiletableUncompressed.Length != (int)mFileTableLength) {
             *      throw new Exception("Filesize missmatch! Uncompressed Body Size is not equal to Uncompressed Length!");
             * }
             */
            // Only read body?
            if (skipFiles == false)
            {
                for (int i = 0, offset = 0; i < fileCount; i++)
                {
                    var  filepath = string.Empty;
                    char c;
                    var  itemTableOffset = (uint)offset;

                    while ((c = (char)mFiletableUncompressed[offset++]) != '\0')
                    {
                        filepath += c;
                    }

                    filepath = Tools.UnifyPath(filepath);
                    var item = new RoGrfFileItem {
                        TableOffset = itemTableOffset,
                        Index       = Files.Count,
                        Filepath    = filepath,
                        Flags       = mFiletableUncompressed[offset + 12]
                    };

                    // File or directory?
                    if (item.IsFile)
                    {
                        item.LengthCompressed      = BitConverter.ToUInt32(mFiletableUncompressed, offset);
                        item.LengthCompressedAlign = BitConverter.ToUInt32(mFiletableUncompressed, offset + 4);
                        item.LengthUnCompressed    = BitConverter.ToUInt32(mFiletableUncompressed, offset + 8);
                        // Offset is base offset + grf header
                        item.DataOffset = BitConverter.ToUInt32(mFiletableUncompressed, offset + 13) + GrfHeaderLen;

                        // from eAtehna, DES encryption
                        item.Cycle = 1;
                        switch (item.Flags)
                        {
                        case 3:
                            for (var lop = 10; item.LengthCompressed >= lop; lop = lop * 10, item.Cycle++)
                            {
                            }
                            break;

                        case 5:
                            item.Cycle = 0;
                            break;

                        default:
                            item.Cycle = -1;
                            break;
                        }
                    }
                    else
                    {
                        // skip dirs
                        offset += (int)GrfFileLen;
                        continue;
                    }

                    // FIX: Some files in a tested grf are duplicated?
                    //		I cant remember grf version or something else..
                    if (GetFileByHash(item.NameHash) != null)
                    {
                        // Duplicate file, just skip it
                        offset += (int)GrfFileLen;
                        continue;
                    }
                    Files.Add(item.NameHash, item);
                    mStringlist.Add(item.NameHash);

                    mFileDataLength += item.LengthCompressedAlign;

                    offset += (int)GrfFileLen;

#if !DISABLE_GRF_EVENTS
                    OnItemAdded(item, i, fileCount);
#endif
                }
            }

            return(true);
        }
Пример #2
0
        /// <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);
        }
Пример #3
0
        /// <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);
            }
        }