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;
            }
        }