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); }
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 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); }
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[] 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()); } }
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 Inflator() { output = new byte[chunkSize]; stream = new ZlibCodec(CompressionMode.Decompress); stream.InitializeInflate(); output = new byte[chunkSize]; }
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()); }
/// <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()); } }
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> /// 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); } }
/// <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 ProtoReader(Stream underlying_stream, bool compressed) { this.underlying_stream = underlying_stream; this.compressed = compressed; this.decompressed_buffer = new byte[1024]; if (compressed) { // Obviously, we won't need these if we're not reading // compressed data. this.compressed_buffer = new byte[1024]; this.zlib = new ZlibCodec(); zlib.InitializeInflate(true); // true = want RFC1950 header zlib.InputBuffer = compressed_buffer; zlib.NextIn = 0; zlib.AvailableBytesIn = 0; } }
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 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); }
/// <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."); }
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."); }
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); }