예제 #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);
        }
예제 #2
0
        public void CompressAndDecompressTest()
        {
            String reference = "Hello World 0123456789";

            byte[]          dataToCompress  = Encoding.Unicode.GetBytes(reference);
            ZLibCompression zLibCompression = new ZLibCompression();

            var compressed   = zLibCompression.Compress(dataToCompress);
            var decompressed = zLibCompression.Decompress(compressed);

            Assert.Equal(reference, Encoding.Unicode.GetString(decompressed));
        }
예제 #3
0
        private Stream Decompress(BinaryReader reader)
        {
            var decompressedData = new MemoryStream();

            for (var chunk = 0; chunk < _header.DataBlocksCount; chunk++)
            {
                var compressedChunkSize   = reader.ReadUInt16();
                var decompressedChunkSize = reader.ReadUInt16();
                var checksum = reader.ReadUInt32();

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

                var decompressedDataBytes = ZLibCompression.Decompress(compressedDataStream, decompressedChunkSize);
                decompressedData.Write(decompressedDataBytes, 0, decompressedDataBytes.Length);
            }

            return(decompressedData);
        }
예제 #4
0
        private Stream GetCompressedStream(Stream baseStream, MpqFileFlags targetFlags, MpqCompressionType compressionType, int targetBlockSize)
        {
            var resultStream = new MemoryStream();
            var singleUnit   = targetFlags.HasFlag(MpqFileFlags.SingleUnit);

            void TryCompress(uint bytes)
            {
                var offset           = baseStream.Position;
                var compressedStream = compressionType switch
                {
                    MpqCompressionType.ZLib => ZLibCompression.Compress(baseStream, (int)bytes, true),

                    _ => throw new NotSupportedException(),
                };

                // Add one because CompressionType byte not written yet.
                var length = compressedStream.Length + 1;

                if (!singleUnit && length >= bytes)
                {
                    baseStream.CopyTo(resultStream, offset, (int)bytes, StreamExtensions.DefaultBufferSize);
                }
                else
                {
                    resultStream.WriteByte((byte)compressionType);
                    compressedStream.Position = 0;
                    compressedStream.CopyTo(resultStream);
                }

                compressedStream.Dispose();

                if (singleUnit)
                {
                    baseStream.Dispose();
                }
            }

            var length = (uint)baseStream.Length;

            if ((targetFlags & MpqFileFlags.Compressed) == 0)
            {
                baseStream.CopyTo(resultStream);
            }
            else if (singleUnit)
            {
                TryCompress(length);
            }
            else
            {
                var blockCount   = (uint)((length + targetBlockSize - 1) / targetBlockSize) + 1;
                var blockOffsets = new uint[blockCount];

                blockOffsets[0]       = 4 * blockCount;
                resultStream.Position = blockOffsets[0];

                for (var blockIndex = 1; blockIndex < blockCount; blockIndex++)
                {
                    var bytesToCompress = blockIndex + 1 == blockCount ? (uint)(baseStream.Length - baseStream.Position) : (uint)targetBlockSize;

                    TryCompress(bytesToCompress);
                    blockOffsets[blockIndex] = (uint)resultStream.Position;
                }

                resultStream.Position = 0;
                using (var writer = new BinaryWriter(resultStream, new System.Text.UTF8Encoding(false, true), true))
                {
                    for (var blockIndex = 0; blockIndex < blockCount; blockIndex++)
                    {
                        writer.Write(blockOffsets[blockIndex]);
                    }
                }
            }

            resultStream.Position = 0;
            return(resultStream);
        }