private static PacketCaptureTestEntry RebuildEntryAsUncompressed(PacketCaptureTestEntry entry) { if (entry.OpCode == NetworkOperationCode.SMSG_COMPRESSED_UPDATE_OBJECT) { //Skip the opcode int decompressedSize = entry.BinaryData.Reinterpret <int>(2); byte[] newBytes = new byte[decompressedSize + 2]; // +2 for opcode ZlibCodec stream = new ZlibCodec(CompressionMode.Decompress) { InputBuffer = entry.BinaryData, NextIn = 2 + 4, //opcode + size AvailableBytesIn = entry.BinaryData.Length, OutputBuffer = newBytes, NextOut = 2, AvailableBytesOut = decompressedSize }; stream.InitializeInflate(true); stream.Inflate(FlushType.None); stream.Inflate(FlushType.Finish); stream.EndInflate(); ((short)(NetworkOperationCode.SMSG_UPDATE_OBJECT)).Reinterpret(newBytes, 0); entry = new PacketCaptureTestEntry(NetworkOperationCode.SMSG_UPDATE_OBJECT, newBytes, entry.FileName); } return(entry); }
public static byte[] Inflate(byte[] compressed) { int bufferSize = 1024 * 64; byte[] buffer = new byte[bufferSize]; ZlibCodec decompressor = new ZlibCodec(); MemoryStream ms = new MemoryStream(); int rc = decompressor.InitializeInflate(); if (rc != ZlibConstants.Z_OK) { throw new Exception("init inflate: " + decompressor.Message); } decompressor.InputBuffer = compressed; decompressor.NextIn = 0; decompressor.AvailableBytesIn = compressed.Length; decompressor.OutputBuffer = buffer; // pass 1: inflate do { decompressor.NextOut = 0; decompressor.AvailableBytesOut = bufferSize; rc = decompressor.Inflate(FlushType.None); if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END) { throw new Exception("inflating: " + decompressor.Message); } ms.Write(decompressor.OutputBuffer, 0, bufferSize - decompressor.AvailableBytesOut); }while (decompressor.AvailableBytesIn > 0 || decompressor.AvailableBytesOut == 0); // pass 2: finish and flush do { decompressor.NextOut = 0; decompressor.AvailableBytesOut = bufferSize; rc = decompressor.Inflate(FlushType.Finish); if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK) { throw new Exception("inflating: " + decompressor.Message); } if (bufferSize - decompressor.AvailableBytesOut > 0) { ms.Write(decompressor.OutputBuffer, 0, bufferSize - decompressor.AvailableBytesOut); } } while (decompressor.AvailableBytesIn > 0 || decompressor.AvailableBytesOut == 0); decompressor.EndInflate(); return(ms.ToArray()); }
public Packet Inflate(int inflatedSize, bool keepStream = true) { var arr = ReadToEnd(); var newarr = new byte[inflatedSize]; if (ClientVersion.RemovedInVersion(ClientVersionBuild.V4_3_0_15005)) { keepStream = false; } if (keepStream) { if (!SessionHandler.z_streams.ContainsKey(ConnectionIndex)) { SessionHandler.z_streams[ConnectionIndex] = new ZlibCodec(CompressionMode.Decompress); } SessionHandler.z_streams[ConnectionIndex].InputBuffer = arr; SessionHandler.z_streams[ConnectionIndex].NextIn = 0; SessionHandler.z_streams[ConnectionIndex].AvailableBytesIn = arr.Length; SessionHandler.z_streams[ConnectionIndex].OutputBuffer = newarr; SessionHandler.z_streams[ConnectionIndex].NextOut = 0; SessionHandler.z_streams[ConnectionIndex].AvailableBytesOut = inflatedSize; SessionHandler.z_streams[ConnectionIndex].Inflate(FlushType.Sync); } else { /*try * { * var inflater = new Inflater(true); * inflater.SetInput(arr, 0, arr.Length); * inflater.Inflate(newarr, 0, inflatedSize); * } * catch (ICSharpCode.SharpZipLib.SharpZipBaseException) * { * var inflater = new Inflater(true); * inflater.SetInput(arr, 0, arr.Length); * inflater.Inflate(newarr, 0, inflatedSize); * }*/ ZlibCodec stream = new ZlibCodec(CompressionMode.Decompress); stream.InputBuffer = arr; stream.NextIn = 0; stream.AvailableBytesIn = arr.Length; stream.OutputBuffer = newarr; stream.NextOut = 0; stream.AvailableBytesOut = inflatedSize; stream.Inflate(FlushType.None); stream.Inflate(FlushType.Finish); stream.EndInflate(); } // Cannot use "using" here var pkt = new Packet(newarr, Opcode, Time, Direction, Number, Writer, FileName); pkt.ConnectionIndex = ConnectionIndex; return(pkt); }
public Packet Inflate(int inflatedSize, bool keepStream = true) { var arr = ReadToEnd(); var newarr = new byte[inflatedSize]; if (ClientVersion.RemovedInVersion(ClientVersionBuild.V4_3_0_15005)) { keepStream = false; } if (keepStream) { int idx = ConnectionIndex; while (!TryInflate(inflatedSize, idx, arr, ref newarr) && idx <= 4) { idx += 1; } } else { /*try * { * var inflater = new Inflater(true); * inflater.SetInput(arr, 0, arr.Length); * inflater.Inflate(newarr, 0, inflatedSize); * } * catch (ICSharpCode.SharpZipLib.SharpZipBaseException) * { * var inflater = new Inflater(true); * inflater.SetInput(arr, 0, arr.Length); * inflater.Inflate(newarr, 0, inflatedSize); * }*/ var stream = new ZlibCodec(CompressionMode.Decompress) { InputBuffer = arr, NextIn = 0, AvailableBytesIn = arr.Length, OutputBuffer = newarr, NextOut = 0, AvailableBytesOut = inflatedSize }; stream.Inflate(FlushType.None); stream.Inflate(FlushType.Finish); stream.EndInflate(); } // Cannot use "using" here var pkt = new Packet(newarr, Opcode, Time, Direction, Number, Writer, FileName) { ConnectionIndex = ConnectionIndex }; return(pkt); }
/// <summary> /// InflateBufferWithPureZlib /// </summary> /// <param name="compressedBytes"></param> /// <param name="length"></param> /// <param name="outs"></param> /// <exception cref="Exception"></exception> public static void InflateBufferWithPureZlib(byte[] compressedBytes, int length, Stream outs) { //int bufferSize = 1024; var buffer = new byte[BufferSize]; var decompressor = new ZlibCodec(); var rc = decompressor.InitializeInflate(); decompressor.InputBuffer = compressedBytes; decompressor.NextIn = 0; decompressor.AvailableBytesIn = length; decompressor.OutputBuffer = buffer; // pass 1: inflate do { decompressor.NextOut = 0; decompressor.AvailableBytesOut = buffer.Length; rc = decompressor.Inflate(FlushType.None); if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END) { throw new Exception("inflating: " + decompressor.Message); } outs.Write(decompressor.OutputBuffer, 0, buffer.Length - decompressor.AvailableBytesOut); } while (decompressor.AvailableBytesIn > 0 && decompressor.AvailableBytesOut == 0); // pass 2: finish and flush do { decompressor.NextOut = 0; decompressor.AvailableBytesOut = buffer.Length; rc = decompressor.Inflate(FlushType.Finish); if (rc != ZlibConstants.Z_STREAM_END && rc != ZlibConstants.Z_OK) { throw new Exception("inflating: " + decompressor.Message); } if (buffer.Length - decompressor.AvailableBytesOut > 0) { outs.Write(buffer, 0, buffer.Length - decompressor.AvailableBytesOut); } } while (decompressor.AvailableBytesIn > 0 && decompressor.AvailableBytesOut == 0); decompressor.EndInflate(); }
public static bool Inflate(byte[] compressed, out byte[] decompressed) { byte[] decompressedBytes = new byte[ushort.MaxValue]; int ret; if (s_Decompressor == null) { s_Decompressor = new ZlibCodec(); ret = s_Decompressor.InitializeInflate(ZlibConstants.WindowBitsDefault, false); if (ret != ZlibConstants.Z_OK) { s_Decompressor = null; decompressed = null; return(false); } } s_Decompressor.InputBuffer = compressed; s_Decompressor.NextIn = 0; s_Decompressor.AvailableBytesIn = compressed.Length; s_Decompressor.OutputBuffer = decompressedBytes; s_Decompressor.NextOut = 0; s_Decompressor.TotalBytesOut = 0; s_Decompressor.AvailableBytesOut = decompressedBytes.Length; ret = s_Decompressor.Inflate(FlushType.Sync); decompressed = new byte[s_Decompressor.TotalBytesOut]; System.Array.Copy(decompressedBytes, decompressed, decompressed.Length); s_Decompressor.ResetInflate(); return(true); }
public static byte[] Inflate(byte[] data, int outputSize) { byte[] output = new Byte[outputSize]; using (MemoryStream ms = new MemoryStream()) { ZlibCodec compressor = new ZlibCodec(); compressor.InitializeInflate(false); compressor.InputBuffer = data; compressor.AvailableBytesIn = data.Length; compressor.NextIn = 0; compressor.OutputBuffer = output; foreach (var f in new FlushType[] { FlushType.None, FlushType.Finish }) { int bytesToWrite = 0; do { compressor.AvailableBytesOut = outputSize; compressor.NextOut = 0; compressor.Inflate(f); bytesToWrite = outputSize - compressor.AvailableBytesOut; if (bytesToWrite > 0) { ms.Write(output, 0, bytesToWrite); } }while ((f == FlushType.None && (compressor.AvailableBytesIn != 0 || compressor.AvailableBytesOut == 0)) || (f == FlushType.Finish && bytesToWrite != 0)); } compressor.EndInflate(); return(ms.ToArray()); } }
private static byte[] ZlibCodecDecompress(byte[] data) { int buffer_size = 0x800; byte[] buffer = new byte[buffer_size]; bool flag = false; using (MemoryStream stream = new MemoryStream()) { ZlibCodec codec = new ZlibCodec(); codec.InitializeInflate(flag); codec.InputBuffer = data; codec.AvailableBytesIn = data.Length; codec.NextIn = 0; codec.OutputBuffer = buffer; FlushType[] typeArray1 = new FlushType[2]; typeArray1[1] = FlushType.Finish; foreach (FlushType type in typeArray1) { int count = 0; do { codec.AvailableBytesOut = buffer_size; codec.NextOut = 0; codec.Inflate(type); count = buffer_size - codec.AvailableBytesOut; if (count > 0) { stream.Write(buffer, 0, count); } }while (((type == FlushType.None) && ((codec.AvailableBytesIn != 0) || (codec.AvailableBytesOut == 0))) || ((type == FlushType.Finish) && (count != 0))); } codec.EndInflate(); return(stream.ToArray()); } }
public Int32 Decompress(byte[] InData, UInt32 InLength, byte[] OutData, UInt32 OutLength, UInt32 InStartIndex = 0, UInt32 OutStartIndex = 0) { if (InData[0 + InStartIndex] != 120 /*'x'*/) { return(0); } _zlib.InitializeInflate(true); _zlib.AvailableBytesIn = Convert.ToInt32(InLength); _zlib.InputBuffer = InData; _zlib.OutputBuffer = OutData; _zlib.AvailableBytesOut = Convert.ToInt32(OutLength); _zlib.NextIn = Convert.ToInt32(InStartIndex); _zlib.NextOut = Convert.ToInt32(OutStartIndex); _zlib.Inflate(FlushType.Finish); int outBytes = Convert.ToInt32(_zlib.TotalBytesOut); if (outBytes != 0) { _zlib.EndInflate(); } return(outBytes); }
public override int Read(byte[] buffer, int offset, int count) { var n = _decompressedBuffer.Read(buffer, offset, count); if (n == count) { return(n); } var readed = _stream.Read(_streamBuffer, 0, _streamBuffer.Length); _inflate.OutputBuffer = _decompressedBuffer.Buffer; _inflate.AvailableBytesOut = _decompressedBuffer.Capacity; _inflate.NextOut = 0; _inflate.InputBuffer = _streamBuffer; _inflate.AvailableBytesIn = readed; _inflate.NextIn = 0; var rc = _inflate.Inflate(Ionic.Zlib.FlushType.None); if (rc != Ionic.Zlib.ZlibConstants.Z_OK) { throw new IOException($"Error '{rc}' while decompressing the data."); } if (_inflate.AvailableBytesIn != 0) { throw new IOException("Decompression buffer too small."); } _decompressedBuffer.Position = 0; _decompressedBuffer.Length = _inflate.NextOut; n += _decompressedBuffer.Read(buffer, offset + n, count - n); return(n); }
public byte[] ExtractBytes(MAS2File f) { BinaryReader reader = new BinaryReader(System.IO.File.OpenRead(this.mas2_file)); reader.BaseStream.Seek(f.FileOffset, SeekOrigin.Begin); byte[] RawData = reader.ReadBytes((int)f.CompressedSize); reader.Close(); if (f.IsCompressed) { byte[] OutputData = new byte[f.UncompressedSize]; // MAS2 compression consists of a simple inflate/deflate process. ZlibCodec codec = new ZlibCodec(CompressionMode.Decompress); codec.InitializeInflate(); codec.InputBuffer = RawData; codec.NextIn = 0; codec.AvailableBytesIn = RawData.Length; codec.OutputBuffer = OutputData; codec.NextOut = 0; codec.AvailableBytesOut = OutputData.Length; codec.Inflate(FlushType.None); codec.EndInflate(); return(OutputData); } else { return(RawData); } }
public ChannelSubBlock(BufferedBinaryReader br, PSPCompression compression, ushort majorVersion) { this.chunkSize = majorVersion > PSPConstants.majorVersion5 ? br.ReadUInt32() : 0U; this.compressedChannelLength = br.ReadUInt32(); this.uncompressedChannelLength = br.ReadUInt32(); this.bitmapType = (PSPDIBType)br.ReadUInt16(); this.channelType = (PSPChannelType)br.ReadUInt16(); this.channelData = null; long dif = (long)this.chunkSize - Version6HeaderSize; if (dif > 0 && majorVersion > PSPConstants.majorVersion5) { br.Position += dif; } if (this.compressedChannelLength > 0U) { switch (compression) { case PSPCompression.None: this.channelData = br.ReadBytes((int)this.compressedChannelLength); break; case PSPCompression.RLE: this.channelData = RLE.Decompress(br.ReadBytes((int)this.compressedChannelLength), this.uncompressedChannelLength); break; case PSPCompression.LZ77: byte[] compressedData = br.ReadBytes((int)this.compressedChannelLength); this.channelData = new byte[this.uncompressedChannelLength]; ZlibCodec codec = new ZlibCodec { AvailableBytesIn = (int)this.compressedChannelLength, AvailableBytesOut = (int)this.uncompressedChannelLength, InputBuffer = compressedData, OutputBuffer = this.channelData }; codec.InitializeInflate(); int status = codec.Inflate(FlushType.Finish); codec.EndInflate(); if (status != ZlibConstants.Z_OK && status != ZlibConstants.Z_STREAM_END) { throw new ZlibException(codec.Message); } break; } } }
/// <summary> /// Decompressed (inflates) a compressed byte array using the Inflate algorithm. /// </summary> /// <param name="compressedData">The deflate-compressed data</param> /// <param name="dictionary">The dictionary originally used to compress the data, or null if no dictionary was used.</param> /// <returns>The uncompressed data</returns> internal static byte[] ZlibDecompressWithDictionary(byte[] compressedData, byte[] dictionary) { using (var ms = new MemoryStream()) { const int bufferSize = 256; var buffer = new byte[bufferSize]; var codec = new ZlibCodec { InputBuffer = compressedData, NextIn = 0, AvailableBytesIn = compressedData.Length }; codec.AssertOk("InitializeInflate", codec.InitializeInflate(false)); if (dictionary != null) { codec.AssertOk("SetDictionary", codec.SetDictionary(dictionary)); } codec.OutputBuffer = buffer; while (true) { codec.NextOut = 0; codec.AvailableBytesOut = bufferSize; var inflateReturnCode = codec.Inflate(FlushType.None); var bytesToWrite = bufferSize - codec.AvailableBytesOut; ms.Write(buffer, 0, bytesToWrite); if (inflateReturnCode == ZlibConstants.Z_STREAM_END) { break; } else if (inflateReturnCode == ZlibConstants.Z_NEED_DICT && dictionary != null) { //implies bytesToWrite was 0 var dictionaryAdler32 = ((int)Adler.Adler32(1u, dictionary, 0, dictionary.Length)); if (codec.Adler32 != dictionaryAdler32) { throw new InvalidOperationException("Compressed data is requesting a dictionary with adler32 " + codec.Adler32 + ", but the dictionary is actually " + dictionaryAdler32); } codec.AssertOk("SetDictionary", codec.SetDictionary(dictionary)); } else { codec.AssertOk("Inflate", inflateReturnCode); } } codec.AssertOk("EndInflate", codec.EndInflate()); return(ms.ToArray()); } }
/// <summary> /// Inflates (decompressed) a single block of data /// </summary> /// <param name="deflatedBytes">The deflated (compressed) data bytes</param> /// <param name="inflatedSize">The size of the bytes once inflated</param> /// <param name="inflatedBytes">The inflated (decompressed) data bytes</param> /// <param name="logger">The logger for debug output</param> /// <returns>Whether or not the inflation was successful</returns> private static bool InflateBlock(byte[] deflatedBytes, int inflatedSize, out byte[] inflatedBytes, ILogger logger) { var output = new byte[inflatedSize]; using (var memoryStream = new MemoryStream()) { var zlibCodec = new ZlibCodec(); zlibCodec.InitializeInflate(true); zlibCodec.InputBuffer = deflatedBytes; zlibCodec.AvailableBytesIn = deflatedBytes.Length; zlibCodec.NextIn = 0; zlibCodec.OutputBuffer = output; foreach (FlushType f in new[] { FlushType.None, FlushType.Finish }) { int bytesToWrite; do { zlibCodec.AvailableBytesOut = inflatedSize; zlibCodec.NextOut = 0; try { zlibCodec.Inflate(f); } catch (Exception e) { inflatedBytes = null; logger.LogError("Exception caught while inflating bytes: " + e); return(false); } bytesToWrite = inflatedSize - zlibCodec.AvailableBytesOut; if (bytesToWrite > 0) { memoryStream.Write(output, 0, bytesToWrite); } } while (f == FlushType.None && (zlibCodec.AvailableBytesIn != 0 || zlibCodec.AvailableBytesOut == 0) || f == FlushType.Finish && bytesToWrite != 0); } zlibCodec.EndInflate(); inflatedBytes = output; return(true); } }
public byte[] Inflate(int expected) { if (expected > chunkSize) { chunkSize = expected; output = new byte[chunkSize]; } stream.OutputBuffer = output; stream.NextOut = 0; stream.AvailableBytesOut = expected; stream.Inflate(FlushType.Sync); return(output); }
/// <summary> /// Decompress the specified inputData. /// </summary> /// <param name="inputData">Input data.</param> /// <returns>decompressed byte array</returns> public static byte[] Decompress(byte[] inputData) { var zlib = new ZlibCodec(Ionic.Zlib.CompressionMode.Decompress); zlib.InputBuffer = inputData; zlib.OutputBuffer = new byte[MAX_PACKET_SIZE]; zlib.NextIn = 0; zlib.AvailableBytesIn = inputData.Length; zlib.NextOut = 0; zlib.AvailableBytesOut = MAX_PACKET_SIZE; zlib.Inflate(FlushType.Finish); var output = new byte[zlib.TotalBytesOut]; Array.Copy(zlib.OutputBuffer, output, (int)zlib.TotalBytesOut); return(output); }
private async ValueTask RunZlibDecompress() { var result = _zlibCodec.InitializeInflate(); if (result < 0) { throw new InvalidOperationException( $"Got error code {result} when initializing inflate routine: {_zlibCodec.Message}"); } var buffer = new byte[Math.Min(1024, _length)]; _zlibCodec.OutputBuffer = buffer; var left = _length; Exception?exception = null; try { while (left > 0) { var readLength = left > buffer.Length ? buffer.Length : left; left -= readLength; var inputBuffer = await _frameReader.ReadBytesAsync( readLength, CancellationToken) .ConfigureAwait(false); _zlibCodec.NextIn = 0; _zlibCodec.InputBuffer = inputBuffer; _zlibCodec.AvailableBytesIn = inputBuffer.Length; while (_zlibCodec.AvailableBytesIn > 0) { _zlibCodec.NextOut = 0; _zlibCodec.AvailableBytesOut = buffer.Length; var start = _zlibCodec.NextOut; result = _zlibCodec.Inflate( left == 0 ? FlushType.Finish : FlushType.Sync); var end = _zlibCodec.NextOut; var length = _zlibCodec.NextOut - start; buffer[start..end]
private string ZlibCodecDecompress(byte[] compressed) { int outputSize = 2048; byte[] output = new Byte[outputSize]; // If you have a ZLIB stream, set this to true. If you have // a bare DEFLATE stream, set this to false. bool expectRfc1950Header = false; using (MemoryStream ms = new MemoryStream()) { ZlibCodec compressor = new ZlibCodec(); compressor.InitializeInflate(expectRfc1950Header); compressor.InputBuffer = compressed; compressor.AvailableBytesIn = compressed.Length; compressor.NextIn = 0; compressor.OutputBuffer = output; foreach (var f in new FlushType[] { FlushType.None, FlushType.Finish }) { int bytesToWrite = 0; do { compressor.AvailableBytesOut = outputSize; compressor.NextOut = 0; compressor.Inflate(f); bytesToWrite = outputSize - compressor.AvailableBytesOut; if (bytesToWrite > 0) { ms.Write(output, 0, bytesToWrite); } }while ((f == FlushType.None && (compressor.AvailableBytesIn != 0 || compressor.AvailableBytesOut == 0)) || (f == FlushType.Finish && bytesToWrite != 0)); } compressor.EndInflate(); return(UTF8Encoding.UTF8.GetString(ms.ToArray())); } }
private void Run() { int rc; int j; int bufferSize = 40000; byte[] compressedBytes = new byte[bufferSize]; byte[] bufferToCompress = new byte[bufferSize]; byte[] decompressedBytes = new byte[bufferSize]; ZlibCodec compressingStream = new ZlibCodec(); rc = compressingStream.InitializeDeflate(CompressionLevel.BestSpeed); CheckForError(compressingStream, rc, "InitializeDeflate"); compressingStream.OutputBuffer = compressedBytes; compressingStream.NextOut = 0; compressingStream.AvailableBytesOut = compressedBytes.Length; // At this point, bufferToCompress is all zeroes, so it should compress // very well: compressingStream.InputBuffer = bufferToCompress; compressingStream.AvailableBytesIn = bufferToCompress.Length; rc = compressingStream.Deflate(FlushType.None); CheckForError(compressingStream, rc, "deflate"); if (compressingStream.AvailableBytesIn != 0) { System.Console.Out.WriteLine("deflate not greedy"); System.Environment.Exit(1); } Console.WriteLine("Stage 1: uncompressed bytes in so far: {0,6}", compressingStream.TotalBytesIn); Console.WriteLine(" compressed bytes out so far: {0,6}", compressingStream.TotalBytesOut); // Feed in already compressed data and switch to no compression: compressingStream.SetDeflateParams(CompressionLevel.None, CompressionStrategy.Default); compressingStream.InputBuffer = compressedBytes; compressingStream.NextIn = 0; compressingStream.AvailableBytesIn = bufferSize / 2; // why? - for fun rc = compressingStream.Deflate(FlushType.None); CheckForError(compressingStream, rc, "Deflate"); Console.WriteLine("Stage 2: uncompressed bytes in so far: {0,6}", compressingStream.TotalBytesIn); Console.WriteLine(" compressed bytes out so far: {0,6}", compressingStream.TotalBytesOut); // Insert data into bufferToCompress, and Switch back to compressing mode: System.Random rnd = new Random(); for (int i = 0; i < bufferToCompress.Length / 1000; i++) { byte b = (byte)rnd.Next(); int n = 500 + rnd.Next(500); for (j = 0; j < n; j++) { bufferToCompress[j + i] = b; } i += j - 1; } compressingStream.SetDeflateParams(CompressionLevel.BestCompression, CompressionStrategy.Filtered); compressingStream.InputBuffer = bufferToCompress; compressingStream.NextIn = 0; compressingStream.AvailableBytesIn = bufferToCompress.Length; rc = compressingStream.Deflate(FlushType.None); CheckForError(compressingStream, rc, "Deflate"); Console.WriteLine("Stage 3: uncompressed bytes in so far: {0,6}", compressingStream.TotalBytesIn); Console.WriteLine(" compressed bytes out so far: {0,6}", compressingStream.TotalBytesOut); rc = compressingStream.Deflate(FlushType.Finish); if (rc != ZlibConstants.Z_STREAM_END) { Console.WriteLine("deflate reported {0}, should report Z_STREAM_END", rc); Environment.Exit(1); } rc = compressingStream.EndDeflate(); CheckForError(compressingStream, rc, "EndDeflate"); Console.WriteLine("Stage 4: uncompressed bytes in (final): {0,6}", compressingStream.TotalBytesIn); Console.WriteLine(" compressed bytes out (final): {0,6}", compressingStream.TotalBytesOut); ZlibCodec decompressingStream = new ZlibCodec(CompressionMode.Decompress); decompressingStream.InputBuffer = compressedBytes; decompressingStream.NextIn = 0; decompressingStream.AvailableBytesIn = bufferSize; // upon inflating, we overwrite the decompressedBytes buffer repeatedly while (true) { decompressingStream.OutputBuffer = decompressedBytes; decompressingStream.NextOut = 0; decompressingStream.AvailableBytesOut = decompressedBytes.Length; rc = decompressingStream.Inflate(FlushType.None); if (rc == ZlibConstants.Z_STREAM_END) { break; } CheckForError(decompressingStream, rc, "inflate large"); } rc = decompressingStream.EndInflate(); CheckForError(decompressingStream, rc, "EndInflate"); if (decompressingStream.TotalBytesOut != 2 * decompressedBytes.Length + bufferSize / 2) { System.Console.WriteLine("bad large inflate: " + decompressingStream.TotalBytesOut); System.Environment.Exit(1); } for (j = 0; j < decompressedBytes.Length; j++) { if (decompressedBytes[j] == 0) { break; } } Console.WriteLine("compressed length: {0}", compressingStream.TotalBytesOut); Console.WriteLine("decompressed length (expected): {0}", 2 * decompressedBytes.Length + bufferSize / 2); Console.WriteLine("decompressed length (actual) : {0}", decompressingStream.TotalBytesOut); }
private void ReadSomeMore() { if (eof) { return; } // Compact the buffer, if we can if (start == end) { // Easy. start = pos = end = 0; } else if (start > 0) { // Not quite as easy. Array.Copy(decompressed_buffer, 0, decompressed_buffer, start, end - start); pos -= start; end -= start; start = 0; } // Now, if necessary, expand the decompressed buffer. if (end >= decompressed_buffer.Length) { // assert(start == 0) if (decompressed_buffer.Length >= (1 << 24)) { throw new IOException("Buffered way more data than should ever be buffered. Giving up."); } byte[] new_buffer = new byte[decompressed_buffer.Length * 2]; Debug.Log("ProtoReader buffer growing to " + (new_buffer.Length) + " bytes."); Array.Copy(new_buffer, 0, decompressed_buffer, 0, end); decompressed_buffer = new_buffer; } // Okay, now we read. How this works depends on whether we're using // compression. if (compressed) { zlib.OutputBuffer = decompressed_buffer; zlib.NextOut = end; zlib.AvailableBytesOut = decompressed_buffer.Length - end; // assert(zlib.AvailableBytesOut > 0) if (zlib.AvailableBytesIn == 0) { zlib.NextIn = 0; zlib.AvailableBytesIn = underlying_stream.Read(compressed_buffer, 0, compressed_buffer.Length); if (zlib.AvailableBytesIn == 0) { eof = true; } } int result = zlib.Inflate(FlushType.Sync); if (result != ZlibConstants.Z_OK && result != ZlibConstants.Z_STREAM_END) { throw new ZlibException("inflating: " + zlib.Message); } end = zlib.NextOut; // heh... heh... heh... } else { // (red, as in the color) int red = underlying_stream.Read(decompressed_buffer, end, decompressed_buffer.Length - end); if (red == 0) { eof = true; } else { // assert(end + red <= decompressed_buffer.Length) end += red; } } }
/// <summary> /// Initializes a new instance of the <see cref="RpxFile"/> class. /// </summary> /// <param name="rpxFilePath">path to the RPX file.</param> /// <param name="verbose">whether to provide verbose output.</param> public RpxFile(string rpxFilePath, bool verbose = false) { Console.WriteLine("Decompressing RPX file..."); this.path = rpxFilePath; this.decompressedPath = this.path + ".extract"; // Remove the temp file if it exists if (File.Exists(this.decompressedPath)) { if (verbose) { Console.WriteLine("Removing file " + System.IO.Path.GetFullPath(this.decompressedPath)); } File.Delete(this.decompressedPath); } this.crcDataOffset = 0; this.header = new RpxHeader(this.path); using (FileStream fs = new FileStream(this.decompressedPath, FileMode.OpenOrCreate, FileAccess.Write)) { using BinaryWriter bw = new BinaryWriter(fs, new ASCIIEncoding()); bw.Write(this.header.Identity); EndianUtility.WriteUInt16BE(bw, this.header.Type); EndianUtility.WriteUInt16BE(bw, this.header.Machine); EndianUtility.WriteUInt32BE(bw, this.header.Version); EndianUtility.WriteUInt32BE(bw, this.header.EntryPoint); EndianUtility.WriteUInt32BE(bw, this.header.PhOffset); EndianUtility.WriteUInt32BE(bw, this.header.SectionHeaderOffset); EndianUtility.WriteUInt32BE(bw, this.header.Flags); EndianUtility.WriteUInt16BE(bw, this.header.EhSize); EndianUtility.WriteUInt16BE(bw, this.header.PhEntSize); EndianUtility.WriteUInt16BE(bw, this.header.PhNum); EndianUtility.WriteUInt16BE(bw, this.header.ShEntSize); EndianUtility.WriteUInt16BE(bw, this.header.SectionHeaderCount); EndianUtility.WriteUInt16BE(bw, this.header.ShStrIndex); EndianUtility.WriteUInt32BE(bw, 0x00000000); EndianUtility.WriteUInt32BE(bw, 0x00000000); EndianUtility.WriteUInt32BE(bw, 0x00000000); while ((ulong)bw.BaseStream.Position < this.header.SectionHeaderDataElfOffset) { bw.Write((byte)0); } while (bw.BaseStream.Position % 0x40 != 0) { bw.Write((byte)0); this.header.SectionHeaderDataElfOffset++; } } this.sectionHeaderIndices = new List <RpxSectionHeaderSort>(); this.sectionHeaders = new List <RpxSectionHeader>(this.header.SectionHeaderCount); this.crcs = new List <uint>(this.header.SectionHeaderCount); if (verbose) { Console.WriteLine(this.header.ToString()); } using (FileStream fs = new FileStream(this.path, FileMode.Open, FileAccess.Read)) { using BinaryReader br = new BinaryReader(fs, new ASCIIEncoding()); // Seek to the Section Header Offset in the file br.BaseStream.Seek(this.header.SectionHeaderOffset, SeekOrigin.Begin); // Read in all of the section headers for (uint i = 0; i < this.header.SectionHeaderCount; i++) { this.crcs.Add(0); // Read in the bytes for the section header byte[] buffer = br.ReadBytes(RpxSectionHeader.SectionHeaderLength); // Create a new section header and add it to the list RpxSectionHeader newSectionHeader = new RpxSectionHeader(buffer); this.sectionHeaders.Add(newSectionHeader); if (newSectionHeader.Offset != 0) { RpxSectionHeaderSort sectionHeaderIndex = new RpxSectionHeaderSort { Index = i, Offset = newSectionHeader.Offset, }; this.sectionHeaderIndices.Add(sectionHeaderIndex); if (verbose) { Console.WriteLine(sectionHeaderIndex.ToString()); } } if (verbose) { Console.WriteLine(newSectionHeader.ToString()); } } } this.sectionHeaderIndices.Sort(); // Iterate through all of the section header indices for (int i = 0; i < this.sectionHeaderIndices.Count; i++) { if (verbose) { Console.WriteLine(this.sectionHeaderIndices[i].ToString()); } else { Console.Write("."); } // Seek to the correct part of the file RpxSectionHeader currentSectionHeader = this.sectionHeaders[(int)this.sectionHeaderIndices[i].Index]; ulong position = currentSectionHeader.Offset; using (FileStream fs = new FileStream(this.path, FileMode.Open, FileAccess.Read)) { using BinaryReader br = new BinaryReader(fs, new ASCIIEncoding()); br.BaseStream.Seek((long)position, SeekOrigin.Begin); currentSectionHeader.Offset = (uint)br.BaseStream.Position; if ((currentSectionHeader.Flags & RpxSectionHeader.SectionHeaderRplZlib) == RpxSectionHeader.SectionHeaderRplZlib) { uint dataSize = currentSectionHeader.Size - 4; currentSectionHeader.Size = EndianUtility.ReadUInt32BE(br); uint blockSize = RpxSectionHeader.ChunkSize; uint have; byte[] bufferIn = new byte[RpxSectionHeader.ChunkSize]; byte[] bufferOut = new byte[RpxSectionHeader.ChunkSize]; ZlibCodec compressor = new ZlibCodec(); compressor.InitializeInflate(true); compressor.AvailableBytesIn = 0; compressor.NextIn = 0; while (dataSize > 0) { blockSize = RpxSectionHeader.ChunkSize; if (dataSize < blockSize) { blockSize = dataSize; } dataSize -= blockSize; bufferIn = br.ReadBytes((int)blockSize); compressor.NextIn = 0; compressor.InputBuffer = bufferIn; compressor.AvailableBytesIn = bufferIn.Length; compressor.OutputBuffer = bufferOut; do { compressor.AvailableBytesOut = (int)RpxSectionHeader.ChunkSize; compressor.NextOut = 0; compressor.Inflate(FlushType.None); have = RpxSectionHeader.ChunkSize - (uint)compressor.AvailableBytesOut; // write the data using (FileStream outFs = new FileStream(this.decompressedPath, FileMode.Append)) { using BinaryWriter bw = new BinaryWriter(outFs, new ASCIIEncoding()); bw.Write(bufferOut, 0, (int)have); } this.crcs[(int)this.sectionHeaderIndices[i].Index] = this.Crc32Rpx(this.crcs[(int)this.sectionHeaderIndices[i].Index], bufferOut, have); }while (compressor.AvailableBytesOut == 0); currentSectionHeader.Flags &= ~RpxSectionHeader.SectionHeaderRplZlib; } } else { uint dataSize = currentSectionHeader.Size; uint blockSize = RpxSectionHeader.ChunkSize; while (dataSize > 0) { byte[] data = new byte[RpxSectionHeader.ChunkSize]; blockSize = RpxSectionHeader.ChunkSize; if (dataSize < blockSize) { blockSize = dataSize; } dataSize -= blockSize; data = br.ReadBytes((int)blockSize); // Write out the section bytes using (FileStream outFs = new FileStream(this.decompressedPath, FileMode.Append)) { using BinaryWriter bw = new BinaryWriter(outFs, new ASCIIEncoding()); bw.Write(data); } this.crcs[(int)this.sectionHeaderIndices[i].Index] = this.Crc32Rpx(this.crcs[(int)this.sectionHeaderIndices[i].Index], data, blockSize); } } // Pad out the section on a 0x40 byte boundary using (FileStream outFs = new FileStream(this.decompressedPath, FileMode.Append)) { using BinaryWriter bw = new BinaryWriter(outFs, new ASCIIEncoding()); while (bw.BaseStream.Position % 0x40 != 0) { bw.Write((byte)0); } } if ((currentSectionHeader.Type & RpxSectionHeader.SectionHeaderRplCrcs) == RpxSectionHeader.SectionHeaderRplCrcs) { this.crcs[(int)this.sectionHeaderIndices[i].Index] = 0; this.crcDataOffset = currentSectionHeader.Offset; } } this.sectionHeaders[(int)this.sectionHeaderIndices[i].Index] = currentSectionHeader; } // Fix the output headers // TODO: This is not currently accurate vs. wiiurpx tool so may need to investigate using (FileStream outFs = new FileStream(this.decompressedPath, FileMode.Open, FileAccess.Write)) { using BinaryWriter bw = new BinaryWriter(outFs, new ASCIIEncoding()); bw.Seek((int)this.header.SectionHeaderOffset, SeekOrigin.Begin); for (uint i = 0; i < this.header.SectionHeaderCount; i++) { EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].Name); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].Type); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].Flags); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].Address); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].Offset); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].Size); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].Link); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].Info); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].AddrAlign); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].EntSize); } using FileStream fs = new FileStream(this.path, FileMode.Open, FileAccess.Read); using BinaryReader br = new BinaryReader(fs, new ASCIIEncoding()); // Seek to the Section Header Offset in the file br.BaseStream.Seek((long)this.crcDataOffset, SeekOrigin.Begin); for (uint i = 0; i < this.header.SectionHeaderCount; i++) { EndianUtility.WriteUInt32BE(bw, this.crcs[(int)i]); } } Console.WriteLine(); Console.WriteLine("Decompression complete."); }
private static SwStorageChunkInfo ReadChunk(SwStorage storage, byte[] blob, int startIndex) { // within a block before offset 0x12 the bytes are yet unknown int index = startIndex + 0x12; uint compressedSize = GetUInt(blob, index); index += 4; uint uncompressedSize = GetUInt(blob, index); index += 4; int nameSize = (int)GetUInt(blob, index); index += 4; int namestart = index; if (namestart + nameSize > blob.Length) { // happens if we try to read the content table return(null); } // the stream names are scrambled ;-) byte[] unrolName = new byte[nameSize]; for (; index < namestart + nameSize; index++) { byte unroledByte = Rol(blob[index], (int)storage.Key); unrolName[index - namestart] = unroledByte; } string chunkName = Encoding.UTF8.GetString(unrolName); if (string.IsNullOrEmpty(chunkName)) { chunkName = "un_" + Guid.NewGuid().ToString(); } int compressedDataStart = namestart + nameSize; SwStorageChunkInfo chunkInfo = new SwStorageChunkInfo(); chunkInfo.ChunkOffset = (uint)startIndex; chunkInfo.CompressedSize = compressedSize; chunkInfo.StartCompressedBlock = compressedDataStart; chunkInfo.ChunkName = chunkName; chunkInfo.HeaderLength = compressedDataStart - startIndex; if (uncompressedSize > 0) { byte[] uncompressedData = new byte[uncompressedSize]; ZlibCodec inflator = new ZlibCodec(); inflator.InitializeInflate(false); inflator.InputBuffer = blob; inflator.AvailableBytesIn = (int)compressedSize; inflator.AvailableBytesOut = (int)uncompressedSize; inflator.NextIn = compressedDataStart; inflator.OutputBuffer = uncompressedData; inflator.NextOut = 0; inflator.Inflate(FlushType.Full); inflator.EndInflate(); chunkInfo.Chunk = uncompressedData; } else { chunkInfo.Chunk = new byte[0]; } return(chunkInfo); }
public override System.Int32 Read(System.Byte[] buffer, System.Int32 offset, System.Int32 count) { // According to MS documentation, any implementation of the IO.Stream.Read function must: // (a) throw an exception if offset & count reference an invalid part of the buffer, // or if count < 0, or if buffer is null // (b) return 0 only upon EOF, or if count = 0 // (c) if not EOF, then return at least 1 byte, up to <count> bytes if (_streamMode == StreamMode.Undefined) { if (!this._stream.CanRead) { throw new ZlibException("The stream is not readable."); } // for the first read, set up some controls. _streamMode = StreamMode.Reader; // (The first reference to _z goes through the private accessor which // may initialize it.) z.AvailableBytesIn = 0; if (_flavor == ZlibStreamFlavor.GZIP) { _gzipHeaderByteCount = _ReadAndValidateGzipHeader(); // workitem 8501: handle edge case (decompress empty stream) if (_gzipHeaderByteCount == 0) { return(0); } } } if (_streamMode != StreamMode.Reader) { throw new ZlibException("Cannot Read after Writing."); } if (count == 0) { return(0); } if (buffer == null) { throw new ArgumentNullException("buffer"); } if (count < 0) { throw new ArgumentOutOfRangeException("count"); } if (offset < buffer.GetLowerBound(0)) { throw new ArgumentOutOfRangeException("offset"); } if ((offset + count) > buffer.GetLength(0)) { throw new ArgumentOutOfRangeException("count"); } int rc = 0; // set up the output of the deflate/inflate codec: _z.OutputBuffer = buffer; _z.NextOut = offset; _z.AvailableBytesOut = count; // This is necessary in case _workingBuffer has been resized. (new byte[]) // (The first reference to _workingBuffer goes through the private accessor which // may initialize it.) _z.InputBuffer = workingBuffer; do { // need data in _workingBuffer in order to deflate/inflate. Here, we check if we have any. if ((_z.AvailableBytesIn == 0) && (!nomoreinput)) { // No data available, so try to Read data from the captive stream. _z.NextIn = 0; _z.AvailableBytesIn = _stream.Read(_workingBuffer, 0, _workingBuffer.Length); if (_z.AvailableBytesIn == 0) { nomoreinput = true; } } // we have data in InputBuffer; now compress or decompress as appropriate rc = _z.Inflate(_flushMode); if (nomoreinput && (rc == ZlibConstants.Z_BUF_ERROR)) { return(0); } if (rc != ZlibConstants.Z_OK && rc != ZlibConstants.Z_STREAM_END) { throw new ZlibException(String.Format(CultureInfo.InvariantCulture, "inflating: rc={0} msg={1}", rc, _z.Message)); } if ((nomoreinput || rc == ZlibConstants.Z_STREAM_END) && (_z.AvailableBytesOut == count)) { break; // nothing more to read } } //while (_z.AvailableBytesOut == count && rc == ZlibConstants.Z_OK); while (_z.AvailableBytesOut > 0 && !nomoreinput && rc == ZlibConstants.Z_OK); // workitem 8557 // is there more room in output? if (_z.AvailableBytesOut > 0) { if (rc == ZlibConstants.Z_OK && _z.AvailableBytesIn == 0) { // deferred } } rc = (count - _z.AvailableBytesOut); // calculate CRC after reading if (crc != null) { crc.SlurpBlock(buffer, offset, rc); } return(rc); }
private void Run() { int rc; int comprLen = 40000; int uncomprLen = comprLen; byte[] CompressedBytes = new byte[comprLen]; byte[] DecompressedBytes = new byte[uncomprLen]; string TextToCompress = "This is the text that will be compressed."; byte[] BytesToCompress = System.Text.ASCIIEncoding.ASCII.GetBytes(TextToCompress); ZlibCodec compressor = new ZlibCodec(CompressionMode.Compress); compressor.InputBuffer = BytesToCompress; compressor.NextIn = 0; compressor.OutputBuffer = CompressedBytes; compressor.NextOut = 0; compressor.AvailableBytesIn = 3; compressor.AvailableBytesOut = CompressedBytes.Length; rc = compressor.Deflate(ZlibConstants.Z_FULL_FLUSH); CheckForError(compressor, rc, "Deflate"); CompressedBytes[3]++; // force an error in first compressed block // dinoch compressor.AvailableBytesIn = TextToCompress.Length - 3; rc = compressor.Deflate(ZlibConstants.Z_FINISH); if (rc != ZlibConstants.Z_STREAM_END) { CheckForError(compressor, rc, "Deflate"); } rc = compressor.EndDeflate(); CheckForError(compressor, rc, "EndDeflate"); comprLen = (int)(compressor.TotalBytesOut); ZlibCodec decompressor = new ZlibCodec(CompressionMode.Decompress); decompressor.InputBuffer = CompressedBytes; decompressor.NextIn = 0; decompressor.AvailableBytesIn = 2; decompressor.OutputBuffer = DecompressedBytes; decompressor.NextOut = 0; decompressor.AvailableBytesOut = DecompressedBytes.Length; rc = decompressor.Inflate(ZlibConstants.Z_NO_FLUSH); CheckForError(decompressor, rc, "Inflate"); decompressor.AvailableBytesIn = CompressedBytes.Length - 2; rc = decompressor.SyncInflate(); CheckForError(decompressor, rc, "SyncInflate"); bool gotException = false; try { rc = decompressor.Inflate(ZlibConstants.Z_FINISH); } catch (ZlibException ex1) { Console.WriteLine("Got Expected Exception: " + ex1); gotException = true; } if (!gotException) { System.Console.Out.WriteLine("inflate should report DATA_ERROR"); /* Because of incorrect adler32 */ System.Environment.Exit(1); } rc = decompressor.EndInflate(); CheckForError(decompressor, rc, "EndInflate"); int j = 0; for (; j < DecompressedBytes.Length; j++) { if (DecompressedBytes[j] == 0) { break; } } var result = System.Text.ASCIIEncoding.ASCII.GetString(DecompressedBytes, 0, j); Console.WriteLine("orig length: {0}", TextToCompress.Length); Console.WriteLine("compressed length: {0}", compressor.TotalBytesOut); Console.WriteLine("uncompressed length: {0}", decompressor.TotalBytesOut); Console.WriteLine("result length: {0}", result.Length); Console.WriteLine("result of inflate:\n(Thi){0}", result); }
public RpxFile(string rpxFilePath) { Console.WriteLine("Decompressing RPX file..."); path = rpxFilePath; decompressedPath = path + ".extract"; // Remove the temp file if it exists if (File.Exists(decompressedPath)) { File.Delete(decompressedPath); } crcDataOffset = 0; header = new RpxHeader(path); using (FileStream fs = new FileStream(decompressedPath, FileMode.OpenOrCreate, FileAccess.Write)) { using (BinaryWriter bw = new BinaryWriter(fs, new ASCIIEncoding())) { bw.Write(header.Identity); EndianUtility.WriteUInt16BE(bw, header.Type); EndianUtility.WriteUInt16BE(bw, header.Machine); EndianUtility.WriteUInt32BE(bw, header.Version); EndianUtility.WriteUInt32BE(bw, header.EntryPoint); EndianUtility.WriteUInt32BE(bw, header.PhOffset); EndianUtility.WriteUInt32BE(bw, header.SectionHeaderOffset); EndianUtility.WriteUInt32BE(bw, header.Flags); EndianUtility.WriteUInt16BE(bw, header.EhSize); EndianUtility.WriteUInt16BE(bw, header.PhEntSize); EndianUtility.WriteUInt16BE(bw, header.PhNum); EndianUtility.WriteUInt16BE(bw, header.ShEntSize); EndianUtility.WriteUInt16BE(bw, header.SectionHeaderCount); EndianUtility.WriteUInt16BE(bw, header.ShStrIndex); EndianUtility.WriteUInt32BE(bw, 0x00000000); EndianUtility.WriteUInt32BE(bw, 0x00000000); EndianUtility.WriteUInt32BE(bw, 0x00000000); while ((ulong)bw.BaseStream.Position < header.SectionHeaderDataElfOffset) { bw.Write((byte)0); } while (bw.BaseStream.Position % 0x40 != 0) { bw.Write((byte)0); header.SectionHeaderDataElfOffset++; } } } sectionHeaderIndices = new List <RpxSectionHeaderSort>(); sectionHeaders = new List <RpxSectionHeader>(header.SectionHeaderCount); crcs = new List <uint>(header.SectionHeaderCount); // TODO: Add debug flag with this output //Console.WriteLine(header.ToString()); using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { using (BinaryReader br = new BinaryReader(fs, new ASCIIEncoding())) { // Seek to the Section Header Offset in the file br.BaseStream.Seek(header.SectionHeaderOffset, SeekOrigin.Begin); // Read in all of the section headers for (UInt32 i = 0; i < header.SectionHeaderCount; i++) { crcs.Add(0); // Read in the bytes for the section header byte[] buffer = br.ReadBytes(RpxSectionHeader.SECTION_HEADER_LENGTH); // Create a new section header and add it to the list RpxSectionHeader newSectionHeader = new RpxSectionHeader(buffer); sectionHeaders.Add(newSectionHeader); if (newSectionHeader.Offset != 0) { RpxSectionHeaderSort sectionHeaderIndex = new RpxSectionHeaderSort(); sectionHeaderIndex.index = i; sectionHeaderIndex.offset = newSectionHeader.Offset; sectionHeaderIndices.Add(sectionHeaderIndex); // TODO: Add debug flag with this output //Console.WriteLine(sectionHeaderIndex.ToString()); } // TODO: Add debug flag with this output //Console.WriteLine(newSectionHeader.ToString()); } } } sectionHeaderIndices.Sort(); // Iterate through all of the section header indices for (int i = 0; i < sectionHeaderIndices.Count; i++) { // Seek to the correct part of the file RpxSectionHeader currentSectionHeader = sectionHeaders[(int)sectionHeaderIndices[i].index]; UInt64 position = currentSectionHeader.Offset; using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { using (BinaryReader br = new BinaryReader(fs, new ASCIIEncoding())) { br.BaseStream.Seek((long)position, SeekOrigin.Begin); currentSectionHeader.Offset = (uint)br.BaseStream.Position; if ((currentSectionHeader.Flags & RpxSectionHeader.SECTION_HEADER_RPL_ZLIB) == RpxSectionHeader.SECTION_HEADER_RPL_ZLIB) { UInt32 dataSize = currentSectionHeader.Size - 4; currentSectionHeader.Size = EndianUtility.ReadUInt32BE(br); UInt32 blockSize = RpxSectionHeader.CHUNK_SIZE; UInt32 have; byte[] bufferIn = new byte[RpxSectionHeader.CHUNK_SIZE]; byte[] bufferOut = new byte[RpxSectionHeader.CHUNK_SIZE]; ZlibCodec compressor = new ZlibCodec(); compressor.InitializeInflate(true); compressor.AvailableBytesIn = 0; compressor.NextIn = 0; while (dataSize > 0) { blockSize = RpxSectionHeader.CHUNK_SIZE; if (dataSize < blockSize) { blockSize = dataSize; } dataSize -= blockSize; bufferIn = br.ReadBytes((int)blockSize); compressor.NextIn = 0; compressor.InputBuffer = bufferIn; compressor.AvailableBytesIn = bufferIn.Length; compressor.OutputBuffer = bufferOut; do { compressor.AvailableBytesOut = (int)RpxSectionHeader.CHUNK_SIZE; compressor.NextOut = 0; compressor.Inflate(FlushType.None); have = RpxSectionHeader.CHUNK_SIZE - (uint)compressor.AvailableBytesOut; // write the data using (FileStream outFs = new FileStream(decompressedPath, FileMode.Append)) { using (BinaryWriter bw = new BinaryWriter(outFs, new ASCIIEncoding())) { bw.Write(bufferOut, 0, (int)have); } } crcs[(int)sectionHeaderIndices[i].index] = Crc32Rpx(crcs[(int)sectionHeaderIndices[i].index], bufferOut, have); } while (compressor.AvailableBytesOut == 0); currentSectionHeader.Flags &= ~RpxSectionHeader.SECTION_HEADER_RPL_ZLIB; } } else { UInt32 dataSize = currentSectionHeader.Size; UInt32 blockSize = RpxSectionHeader.CHUNK_SIZE; while (dataSize > 0) { byte[] data = new byte[RpxSectionHeader.CHUNK_SIZE]; blockSize = RpxSectionHeader.CHUNK_SIZE; if (dataSize < blockSize) { blockSize = dataSize; } dataSize -= blockSize; data = br.ReadBytes((int)blockSize); // Write out the section bytes using (FileStream outFs = new FileStream(decompressedPath, FileMode.Append)) { using (BinaryWriter bw = new BinaryWriter(outFs, new ASCIIEncoding())) { bw.Write(data); } } crcs[(int)sectionHeaderIndices[i].index] = Crc32Rpx(crcs[(int)sectionHeaderIndices[i].index], data, blockSize); } } // Pad out the section on a 0x40 byte boundary using (FileStream outFs = new FileStream(decompressedPath, FileMode.Append)) { using (BinaryWriter bw = new BinaryWriter(outFs, new ASCIIEncoding())) { while (bw.BaseStream.Position % 0x40 != 0) { bw.Write((byte)0); } } } if ((currentSectionHeader.Type & RpxSectionHeader.SECTION_HEADER_RPL_CRCS) == RpxSectionHeader.SECTION_HEADER_RPL_CRCS) { crcs[(int)sectionHeaderIndices[i].index] = 0; crcDataOffset = currentSectionHeader.Offset; } } } sectionHeaders[(int)sectionHeaderIndices[i].index] = currentSectionHeader; } // Fix the output headers // TODO: This is not currently accurate vs. wiiurpx tool so may need to investigate using (FileStream outFs = new FileStream(decompressedPath, FileMode.Open, FileAccess.Write)) { using (BinaryWriter bw = new BinaryWriter(outFs, new ASCIIEncoding())) { bw.Seek((int)header.SectionHeaderOffset, SeekOrigin.Begin); for (UInt32 i = 0; i < header.SectionHeaderCount; i++) { EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].Name); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].Type); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].Flags); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].Address); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].Offset); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].Size); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].Link); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].Info); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].AddrAlign); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].EntSize); } using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { using (BinaryReader br = new BinaryReader(fs, new ASCIIEncoding())) { // Seek to the Section Header Offset in the file br.BaseStream.Seek((long)crcDataOffset, SeekOrigin.Begin); for (UInt32 i = 0; i < header.SectionHeaderCount; i++) { EndianUtility.WriteUInt32BE(bw, crcs[(int)i]); } } } } } Console.WriteLine("Decompression complete."); }
public static void Can_Deserialize_Captures_To_GamePacketPayloads(PacketCaptureTestEntry entry) { Console.WriteLine($"Entry Size: {entry.BinaryData.Length} OpCode: {entry.OpCode}"); //TODO: Test compression another time. if (entry.OpCode == NetworkOperationCode.SMSG_COMPRESSED_UPDATE_OBJECT) { //Skip the opcode int decompressedSize = entry.BinaryData.Reinterpret <int>(2); byte[] newBytes = new byte[decompressedSize + 2]; // +2 for opcode ZlibCodec stream = new ZlibCodec(CompressionMode.Decompress) { InputBuffer = entry.BinaryData, NextIn = 2 + 4, //opcode + size AvailableBytesIn = entry.BinaryData.Length, OutputBuffer = newBytes, NextOut = 2, AvailableBytesOut = decompressedSize }; stream.Inflate(FlushType.None); stream.Inflate(FlushType.Finish); stream.EndInflate(); ((short)(NetworkOperationCode.SMSG_UPDATE_OBJECT)).Reinterpret(newBytes, 0); entry = new PacketCaptureTestEntry(NetworkOperationCode.SMSG_UPDATE_OBJECT, newBytes, entry.FileName); } //arrange SerializerService serializer = Serializer; GamePacketPayload payload; Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); //act try { payload = serializer.Deserialize <GamePacketPayload>(entry.BinaryData); } catch (Exception e) { Console.WriteLine($"Critical failure. Cannot deserialize File: {entry.FileName} FileSize: {entry.BinaryData.Length} \n\n Exception: {e.Message} Stack: {e.StackTrace}"); return; } finally { stopwatch.Stop(); } Console.WriteLine($"Serialization time in ms: {stopwatch.ElapsedMilliseconds}"); foreach (ObjectUpdateBlock block in ((IObjectUpdatePayload)payload).UpdateBlocks.Items) { Console.WriteLine($"Encountered: {block.GetType().Name} Block Type: {block.UpdateType}"); } //assert if (payload == null) { Console.WriteLine($"Resulting capture capture deserialization attempt null for File: {entry.FileName}"); } //We should have deserialized it. We want to make sure the opcode matches if (entry.OpCode != payload.OperationCode) { Console.WriteLine($"Mismatched {nameof(NetworkOperationCode)} on packet capture File: {entry.FileName}. Expected: {entry.OpCode} Was: {payload.OperationCode}"); } }
private void Run() { int rc; int bufferSize = 40000; byte[] compressedBytes = new byte[bufferSize]; byte[] decompressedBytes = new byte[bufferSize]; ZlibCodec compressingStream = new ZlibCodec(); rc = compressingStream.InitializeDeflate(CompressionLevel.LEVEL9_BEST_COMPRESSION); CheckForError(compressingStream, rc, "InitializeDeflate"); string dictionaryWord = "hello "; byte[] dictionary = System.Text.ASCIIEncoding.ASCII.GetBytes(dictionaryWord); string TextToCompress = "hello, hello! How are you, Joe? "; byte[] BytesToCompress = System.Text.ASCIIEncoding.ASCII.GetBytes(TextToCompress); rc = compressingStream.SetDictionary(dictionary); CheckForError(compressingStream, rc, "SetDeflateDictionary"); long dictId = compressingStream.Adler32; compressingStream.OutputBuffer = compressedBytes; compressingStream.NextOut = 0; compressingStream.AvailableBytesOut = bufferSize; compressingStream.InputBuffer = BytesToCompress; compressingStream.NextIn = 0; compressingStream.AvailableBytesIn = BytesToCompress.Length; rc = compressingStream.Deflate(ZlibConstants.Z_FINISH); if (rc != ZlibConstants.Z_STREAM_END) { System.Console.Out.WriteLine("deflate should report Z_STREAM_END"); System.Environment.Exit(1); } rc = compressingStream.EndDeflate(); CheckForError(compressingStream, rc, "deflateEnd"); ZlibCodec decompressingStream = new ZlibCodec(); decompressingStream.InputBuffer = compressedBytes; decompressingStream.NextIn = 0; decompressingStream.AvailableBytesIn = bufferSize; rc = decompressingStream.InitializeInflate(); CheckForError(decompressingStream, rc, "inflateInit"); decompressingStream.OutputBuffer = decompressedBytes; decompressingStream.NextOut = 0; decompressingStream.AvailableBytesOut = decompressedBytes.Length; while (true) { rc = decompressingStream.Inflate(ZlibConstants.Z_NO_FLUSH); if (rc == ZlibConstants.Z_STREAM_END) { break; } if (rc == ZlibConstants.Z_NEED_DICT) { if ((int)decompressingStream.Adler32 != (int)dictId) { System.Console.Out.WriteLine("unexpected dictionary"); System.Environment.Exit(1); } rc = decompressingStream.SetDictionary(dictionary); } CheckForError(decompressingStream, rc, "inflate with dict"); } rc = decompressingStream.EndInflate(); CheckForError(decompressingStream, rc, "EndInflate"); int j = 0; for (; j < decompressedBytes.Length; j++) { if (decompressedBytes[j] == 0) { break; } } var result = System.Text.ASCIIEncoding.ASCII.GetString(decompressedBytes, 0, j); Console.WriteLine("orig length: {0}", TextToCompress.Length); Console.WriteLine("compressed length: {0}", compressingStream.TotalBytesOut); Console.WriteLine("decompressed length: {0}", decompressingStream.TotalBytesOut); Console.WriteLine("result length: {0}", result.Length); Console.WriteLine("result of inflate:\n{0}", result); }