public static void DecompressTexture(byte[] DecompressedBuffer, MemoryStream stream, StorageTypes type, int uncompressedSize, int compressedSize) { uint blockTag = stream.ReadUInt32(); if (blockTag != textureTag) { throw new Exception("Texture tag wrong"); } uint blockSize = stream.ReadUInt32(); if (blockSize != maxBlockSize) { throw new Exception("Texture header broken"); } uint compressedChunkSize = stream.ReadUInt32(); uint uncompressedChunkSize = stream.ReadUInt32(); if (uncompressedChunkSize != uncompressedSize) { throw new Exception("Texture header broken"); } uint blocksCount = (uncompressedChunkSize + maxBlockSize - 1) / maxBlockSize; if ((compressedChunkSize + SizeOfChunk + SizeOfChunkBlock * blocksCount) != compressedSize) { throw new Exception("Texture header broken"); } var blocks = new List <ChunkBlock>(); for (uint b = 0; b < blocksCount; b++) { ChunkBlock block = new ChunkBlock { comprSize = stream.ReadUInt32(), uncomprSize = stream.ReadUInt32() }; blocks.Add(block); } for (int b = 0; b < blocks.Count; b++) { ChunkBlock block = blocks[b]; block.compressedBuffer = stream.ReadToBuffer(blocks[b].comprSize); block.uncompressedBuffer = new byte[maxBlockSize * 2]; blocks[b] = block; } Parallel.For(0, blocks.Count, b => { uint dstLen; ChunkBlock block = blocks[b]; if (type == StorageTypes.extLZO || type == StorageTypes.pccLZO) { dstLen = LZO2.Decompress(block.compressedBuffer, block.comprSize, block.uncompressedBuffer); } else if (type == StorageTypes.extZlib || type == StorageTypes.pccZlib) { dstLen = Zlib.Decompress(block.compressedBuffer, block.comprSize, block.uncompressedBuffer); } else if (type == StorageTypes.extLZMA) { block.uncompressedBuffer = LZMA.Decompress(block.compressedBuffer, block.uncomprSize); dstLen = (uint)block.uncompressedBuffer.Length; } else { throw new Exception("Compression type not expected!"); } if (dstLen != block.uncomprSize) { throw new Exception("Decompressed data size not expected!"); } }); int dstPos = 0; for (int b = 0; b < blocks.Count; b++) { Buffer.BlockCopy(blocks[b].uncompressedBuffer, 0, DecompressedBuffer, dstPos, (int)blocks[b].uncomprSize); dstPos += (int)blocks[b].uncomprSize; } }