Exemple #1
0
        private static MemoryStream Decompress(BinaryReader reader, PackedFileHeader header)
        {
            var blockCount       = header.DataBlocksCount;
            var decompressedSize = header.DecompressedSize;
            var isReforged       = header.IsReforgedReplay;

            var decompressedData = new MemoryStream();

            for (var chunk = 0; chunk < blockCount; chunk++)
            {
                var compressedChunkSize = reader.ReadUInt16();
                if (isReforged)
                {
                    reader.BaseStream.Seek(2, SeekOrigin.Current);
                }

                var decompressedChunkSize = reader.ReadUInt16();
                var checksum = reader.ReadUInt32();
                if (isReforged)
                {
                    reader.BaseStream.Seek(2, SeekOrigin.Current);
                }

                using var compressedDataStream = new MemoryStream();
                reader.BaseStream.CopyTo(compressedDataStream, compressedChunkSize, StreamExtensions.DefaultBufferSize);
                compressedDataStream.Position = 0;

                var decompressedDataBytes  = ZLibCompression.Decompress(compressedDataStream, decompressedChunkSize);
                var decompressedDataLength = (chunk + 1 == blockCount) ? (int)(decompressedSize - decompressedData.Length) : decompressedChunkSize;
                decompressedData.Write(decompressedDataBytes, 0, decompressedDataLength);
            }

            decompressedData.Position = 0;
            return(decompressedData);
        }
Exemple #2
0
        public static PackedFile Parse(Stream stream, bool leaveOpen = false)
        {
            var file = new PackedFile();

            using (var reader = new BinaryReader(stream, new UTF8Encoding(false, true), leaveOpen))
            {
                file._header           = PackedFileHeader.FromReader(reader);
                file._decompressedData = Decompress(reader, file._header);
            }

            return(file);
        }
Exemple #3
0
        public static PackedFileHeader FromReader(BinaryReader reader)
        {
            if (new string(reader.ReadChars(HeaderString.Length)) != HeaderString)
            {
                throw new InvalidDataException("Invalid file header.");
            }

            using var crcStream = new MemoryStream();
            using var crcWriter = new BinaryWriter(crcStream);

            var header = new PackedFileHeader();

            header._dataOffset       = reader.ReadUInt32();
            header._compressedSize   = reader.ReadUInt32();
            header._headerVersion    = reader.ReadUInt32();
            header._decompressedSize = reader.ReadUInt32();
            header._dataBlocksCount  = reader.ReadUInt32();

            crcWriter.WriteString(HeaderString);
            crcWriter.Write(header._dataOffset);
            crcWriter.Write(header._compressedSize);
            crcWriter.Write(header._headerVersion);
            crcWriter.Write(header._decompressedSize);
            crcWriter.Write(header._dataBlocksCount);

            if (header._headerVersion == 0x00)
            {
                if (header._dataOffset != 0x40)
                {
                    throw new InvalidDataException("Invalid header size.");
                }

                if (reader.ReadUInt16() != 0)
                {
                    throw new InvalidDataException();
                }

                header._gameVersion = reader.ReadUInt16();

                crcWriter.Write((ushort)0);
                crcWriter.Write((ushort)header._gameVersion);
            }
            else if (header._headerVersion == 0x01)
            {
                if (header._dataOffset != 0x44)
                {
                    throw new InvalidDataException("Invalid header size.");
                }

                header._gameIdentifier = reader.ReadUInt32();
                header._gameVersion    = reader.ReadUInt32();

                crcWriter.Write(header._gameIdentifier);
                crcWriter.Write(header._gameVersion);
            }
            else
            {
                throw new NotSupportedException("Only header version 1 is supported.");
            }

            header._build      = reader.ReadUInt16();
            header._flags      = reader.ReadUInt16();
            header._gameLength = reader.ReadUInt32();
            header._checksum   = reader.ReadUInt32();

            crcWriter.Write(header._build);
            crcWriter.Write(header._flags);
            crcWriter.Write(header._gameLength);
            crcWriter.Write(0U);

            crcStream.Position = 0;
            var crc = new Ionic.Crc.CRC32().GetCrc32(crcStream);

            if (crc != header._checksum)
            {
                throw new InvalidDataException("CRC failed");
            }

            return(header);
        }