Пример #1
0
        public void Encode(Stream input, Stream output)
        {
            _initialRead = true;
            _codeByte    = 0;

            var matches = _matchParser.ParseMatches(input);

            foreach (var match in matches)
            {
                if (input.Position < match.Position)
                {
                    WriteRawData(input, output, match.Position - input.Position);
                }

                if (_initialRead)
                {
                    _initialRead = false;
                }

                WriteMatchData(input, output, match);
            }

            if (input.Position < input.Length)
            {
                WriteRawData(input, output, input.Length - input.Position);
            }

            // Write ending match flag
            output.WriteByte(0x11);
            output.WriteByte(0);
            output.WriteByte(0);
        }
Пример #2
0
        internal void WriteCompressedData(Stream input, Stream output)
        {
            var matches = _matchParser.ParseMatches(input).ToArray();

            int bufferedBlocks = 0, blockBufferLength = 1, lzIndex = 0;

            byte[] blockBuffer = new byte[8 * 4 + 1];

            while (input.Position < input.Length)
            {
                if (bufferedBlocks >= 8)
                {
                    WriteBlockBuffer(output, blockBuffer, blockBufferLength);

                    bufferedBlocks    = 0;
                    blockBufferLength = 1;
                }

                if (lzIndex < matches.Length && input.Position == matches[lzIndex].Position)
                {
                    blockBufferLength = WriteCompressedBlockToBuffer(matches[lzIndex], blockBuffer, blockBufferLength, bufferedBlocks);
                    input.Position   += matches[lzIndex++].Length;
                }
                else
                {
                    blockBuffer[blockBufferLength++] = (byte)input.ReadByte();
                }

                bufferedBlocks++;
            }

            WriteBlockBuffer(output, blockBuffer, blockBufferLength);
        }
Пример #3
0
        public void Encode(Stream input, Stream output)
        {
            var originalOutputPosition = output.Position;

            output.Position += 6;

            var block = new Block();

            var matches = _matchParser.ParseMatches(input);

            foreach (var match in matches)
            {
                // Compress raw data
                if (input.Position < match.Position)
                {
                    CompressRawData(input, output, block, (int)(match.Position - input.Position));
                }

                // Compress match
                CompressMatchData(input, output, block, match);
            }

            // Compress raw data
            if (input.Position < input.Length)
            {
                CompressRawData(input, output, block, (int)(input.Length - input.Position));
            }

            WriteAndResetBuffer(output, block);

            // Write header information
            WriteHeaderData(input, output, originalOutputPosition);
        }
Пример #4
0
        public void Encode(Stream input, Stream output)
        {
            var block = new Block();

            output.Position += 9;

            var matches = _matchParser.ParseMatches(input);

            foreach (var match in matches)
            {
                if (input.Position < match.Position)
                {
                    WriteRawData(input, output, block, match.Position - input.Position);
                }

                WriteMatchData(input, output, block, match);
            }

            if (input.Position < input.Length)
            {
                WriteRawData(input, output, block, input.Length - input.Position);
            }

            if (block.flagCount > 0)
            {
                WriteAndResetBuffer(output, block);
            }

            WriteHeaderData(output, (int)input.Length);
        }
Пример #5
0
        public void Encode(Stream input, Stream output)
        {
            if (input.Length > 0xFFFFFF)
            {
                throw new InvalidOperationException("Data to compress is too long.");
            }

            var compressionHeader = new byte[] { 0x30, (byte)(input.Length & 0xFF), (byte)((input.Length >> 8) & 0xFF), (byte)((input.Length >> 16) & 0xFF) };

            output.Write(compressionHeader, 0, 4);

            _buffer = new byte[0x80];
            var matches = _matchParser.ParseMatches(input);

            foreach (var match in matches)
            {
                if (input.Position < match.Position)
                {
                    // If we have unmatched data before the match, create enough uncompressed blocks
                    HandleUncompressedData(input, output, (int)(match.Position - input.Position));
                }

                // Write matched data as compressed block
                var rleValue = (byte)input.ReadByte();
                HandleCompressedBlock(output, rleValue, match.Length);
                input.Position += match.Length - 1;
            }

            // If there is unmatched data left after last match, handle as uncompressed block
            if (input.Position < input.Length)
            {
                HandleUncompressedData(input, output, (int)(input.Length - input.Position));
            }
        }
Пример #6
0
        public void Encode(Stream input, Stream output)
        {
            var buffer  = new byte[0x80];
            var matches = _matchParser.ParseMatches(input);

            foreach (var match in matches)
            {
                if (input.Position < match.Position)
                {
                    // If we have unmatched data before the match, create enough uncompressed blocks
                    HandleUncompressedData(input, output, buffer, (int)(match.Position - input.Position));
                }

                // Write matched data as compressed block
                var rleValue = (byte)input.ReadByte();
                HandleCompressedBlock(output, rleValue, match.Length);
                input.Position += match.Length - 1;
            }

            // If there is unmatched data left after last match, handle as uncompressed block
            if (input.Position < input.Length)
            {
                HandleUncompressedData(input, output, buffer, (int)(input.Length - input.Position));
            }
        }
Пример #7
0
        public void Encode(Stream input, Stream output)
        {
            var block = new Block();

            var start = Encoding.ASCII.GetBytes("Wp16");

            output.Write(start, 0, 4);
            output.Write(((int)input.Length).GetArrayLittleEndian(), 0, 4);

            var matches = _matchParser.ParseMatches(input);

            foreach (var match in matches)
            {
                // Compress raw data
                if (input.Position < match.Position)
                {
                    CompressRawData(input, output, block, (int)(match.Position - input.Position));
                }

                // Compress match
                CompressMatchData(input, output, block, match);
            }

            // Compress raw data
            if (input.Position < input.Length)
            {
                CompressRawData(input, output, block, (int)(input.Length - input.Position));
            }

            if (block.flagPosition > 0)
            {
                WriteAndResetBuffer(output, block);
            }
        }
Пример #8
0
        public void Encode(Stream input, Stream output)
        {
            var block = new Block();

            var matches = _matchParser.ParseMatches(input);

            foreach (var match in matches)
            {
                if (input.Position < match.Position)
                {
                    WriteRawData(input, output, block, match.Position - input.Position);
                }

                if (block.initialRead)
                {
                    block.initialRead = false;
                }

                WriteMatchData(input, output, block, match);
            }

            if (input.Position < input.Length)
            {
                WriteRawData(input, output, block, input.Length - input.Position);
            }

            // Write ending match flag
            output.WriteByte(0x11);
            output.WriteByte(0);
            output.WriteByte(0);
        }
Пример #9
0
        public void Encode(Stream input, Stream output)
        {
            _buffer       = new byte[1 + 8 * 2];
            _bufferLength = 1;
            _flagCount    = 0;

            output.Position += 9;

            var matches = _matchParser.ParseMatches(input);

            foreach (var match in matches)
            {
                if (input.Position < match.Position - _matchParser.FindOptions.PreBufferSize)
                {
                    WriteRawData(input, output, match.Position - _matchParser.FindOptions.PreBufferSize - input.Position);
                }

                WriteMatchData(input, output, match);
            }

            if (input.Position < input.Length)
            {
                WriteRawData(input, output, input.Length - input.Position);
            }

            WriteAndResetBuffer(output);

            WriteHeaderData(output, (int)input.Length);
        }
Пример #10
0
        public void Encode(Stream input, Stream output)
        {
            var matches = _matchParser.ParseMatches(input).ToArray();

            var compressedLength = PreCalculateCompressedLength(input.Length, matches);

            var block = new Block();

            using (var inputReverseStream = new ReverseStream(input, input.Length))
                using (var reverseOutputStream = new ReverseStream(output, compressedLength))
                {
                    foreach (var match in matches)
                    {
                        while (match.Position > inputReverseStream.Position)
                        {
                            if (block.codeBlockPosition == 0)
                            {
                                WriteAndResetBuffer(reverseOutputStream, block);
                            }

                            block.codeBlockPosition--;
                            block.buffer[block.bufferLength++] = (byte)inputReverseStream.ReadByte();
                        }

                        var byte1 = ((byte)(match.Length - 3) << 4) | (byte)((match.Displacement - 3) >> 8);
                        var byte2 = match.Displacement - 3;

                        if (block.codeBlockPosition == 0)
                        {
                            WriteAndResetBuffer(reverseOutputStream, block);
                        }

                        block.codeBlock |= (byte)(1 << --block.codeBlockPosition);
                        block.buffer[block.bufferLength++] = (byte)byte1;
                        block.buffer[block.bufferLength++] = (byte)byte2;

                        inputReverseStream.Position += match.Length;
                    }

                    // Write any data after last match, to the buffer
                    while (inputReverseStream.Position < inputReverseStream.Length)
                    {
                        if (block.codeBlockPosition == 0)
                        {
                            WriteAndResetBuffer(reverseOutputStream, block);
                        }

                        block.codeBlockPosition--;
                        block.buffer[block.bufferLength++] = (byte)inputReverseStream.ReadByte();
                    }

                    // Flush remaining buffer to stream
                    WriteAndResetBuffer(reverseOutputStream, block);

                    output.Position = compressedLength;
                    WriteFooterInformation(input, output);
                }
        }
Пример #11
0
        public void Encode(Stream input, Stream output)
        {
            var block = new Block();

            var matches      = _matchParser.ParseMatches(input).ToArray();
            var rawValueTree = CreateRawValueTree(input, matches);

            block.rawValueDictionary = rawValueTree.GetHuffCodes().ToDictionary(node => node.Item1, node => node.Item2);

            block.countIndexes = GetCountIndexes(matches, input.Length);
            var countIndexValueTree = CreateIndexValueTree(block);

            block.countIndexDictionary = countIndexValueTree.GetHuffCodes().ToDictionary(node => node.Item1, node => node.Item2);

            block.dispIndexes = GetDispIndexes(matches);
            var dispIndexTree = CreateDisplacementIndexTree(block);

            block.dispIndexDictionary = dispIndexTree.GetHuffCodes().ToDictionary(node => node.Item1, node => node.Item2);

            using var bw = new BitWriter(output, BitOrder.LeastSignificantBitFirst, 1, ByteOrder.LittleEndian);

            // Without obfuscation
            bw.WriteByte(0x02);

            WriteTreeNode(bw, rawValueTree, 8);
            WriteTreeNode(bw, countIndexValueTree, 6);
            WriteTreeNode(bw, dispIndexTree, 5);

            var countPosition        = 0;
            var displacementPosition = 0;

            foreach (var match in matches)
            {
                // Compress raw data
                if (input.Position < match.Position)
                {
                    CompressRawData(input, bw, block, (int)(match.Position - input.Position), ref countPosition);
                }

                // Compress match
                CompressMatchData(input, bw, block, match, ref countPosition, ref displacementPosition);
            }

            // Compress raw data
            if (input.Position < input.Length)
            {
                CompressRawData(input, bw, block, (int)(input.Length - input.Position), ref countPosition);
            }

            // Write final 0 index
            foreach (var bit in block.countIndexDictionary[block.countIndexes.Last()])
            {
                bw.WriteBit(bit - '0');
            }
        }
Пример #12
0
        public void Encode(Stream input, Stream output)
        {
            var bitLayoutStream         = new MemoryStream();
            var compressedTableStream   = new MemoryStream();
            var uncompressedTableStream = new MemoryStream();

            using var bitLayoutWriter = new BitWriter(bitLayoutStream, BitOrder.MostSignificantBitFirst, 1, ByteOrder.BigEndian);
            using var bwCompressed    = new BinaryWriter(compressedTableStream, Encoding.ASCII, true);
            using var bwUncompressed  = new BinaryWriter(uncompressedTableStream, Encoding.ASCII, true);

            var matches = _matchParser.ParseMatches(input);

            foreach (var match in matches)
            {
                // Write any data before the match, to the uncompressed table
                while (input.Position < match.Position)
                {
                    bitLayoutWriter.WriteBit(1);
                    bwUncompressed.Write((byte)input.ReadByte());
                }

                // Write match data to the compressed table
                var firstByte  = (byte)((match.Displacement - 1) >> 8);
                var secondByte = (byte)(match.Displacement - 1);

                if (match.Length < 0x12)
                {
                    // Since minimum _length should be 3 for Yay0, we get a minimum matchLength of 1 in this case
                    firstByte |= (byte)((match.Length - 2) << 4);
                }
                else
                {
                    // Yes, we do write the _length for a match into the uncompressed data stream, if it's >=0x12
                    bwUncompressed.Write((byte)(match.Length - 0x12));
                }

                bitLayoutWriter.WriteBit(0);
                bwCompressed.Write(firstByte);
                bwCompressed.Write(secondByte);

                input.Position += match.Length;
            }

            // Write any data after last match, to the uncompressed table
            while (input.Position < input.Length)
            {
                bitLayoutWriter.WriteBit(1);
                bwUncompressed.Write((byte)input.ReadByte());
            }

            bitLayoutWriter.Flush();

            WriteCompressedData(input, output, bitLayoutStream, compressedTableStream, uncompressedTableStream);
        }
Пример #13
0
        public void Encode(Stream input, Stream output)
        {
            var decompressedSize = CreateVlc((int)input.Length);
            var unk1             = CreateVlc(0x19);
            var unk2             = CreateVlc(0);

            output.Write(decompressedSize, 0, decompressedSize.Length);
            output.Write(unk1, 0, unk1.Length);
            output.Write(unk2, 0, unk2.Length);

            var matches = _matchParser.ParseMatches(input).ToArray();

            WriteCompressedData(input, output, matches);
        }
Пример #14
0
        public void Encode(Stream input, Stream output)
        {
            if (input.Length > 0xFFFFFF)
            {
                throw new InvalidOperationException("Data to compress is too long.");
            }

            var compressionHeader = new byte[] { 0x11, (byte)(input.Length & 0xFF), (byte)((input.Length >> 8) & 0xFF), (byte)((input.Length >> 16) & 0xFF) };

            output.Write(compressionHeader, 0, 4);

            var matches = _matchParser.ParseMatches(input).ToArray();

            WriteCompressedData(input, output, matches);
        }
Пример #15
0
        public void Encode(Stream input, Stream output)
        {
            var bitLayoutStream         = new MemoryStream();
            var compressedTableStream   = new MemoryStream();
            var uncompressedTableStream = new MemoryStream();

            using var bitLayoutWriter = new BitWriter(bitLayoutStream, BitOrder.MsbFirst, 1, ByteOrder.BigEndian);
            using var bwCompressed    = new BinaryWriter(compressedTableStream, Encoding.ASCII, true);
            using var bwUncompressed  = new BinaryWriter(uncompressedTableStream, Encoding.ASCII, true);

            var matches = _matchParser.ParseMatches(input);

            foreach (var match in matches)
            {
                // Write any data before the match, to the uncompressed table
                while (input.Position < match.Position)
                {
                    bitLayoutWriter.WriteBit(1);
                    bwUncompressed.Write((byte)input.ReadByte());
                }

                // Write match data to the compressed table
                var firstByte  = (byte)((byte)((match.Length - 3) << 4) | (byte)((match.Displacement - 1) >> 8));
                var secondByte = (byte)(match.Displacement - 1);
                bitLayoutWriter.WriteBit(0);
                bwCompressed.Write(firstByte);
                bwCompressed.Write(secondByte);

                input.Position += match.Length;
            }

            // Write any data after last match, to the uncompressed table
            while (input.Position < input.Length)
            {
                bitLayoutWriter.WriteBit(1);
                bwUncompressed.Write((byte)input.ReadByte());
            }

            bitLayoutWriter.Flush();

            WriteCompressedData(input, output, bitLayoutStream, compressedTableStream, uncompressedTableStream);
        }
Пример #16
0
        public void Encode(Stream input, Stream output)
        {
            output.Position += 0xC;

            var matches = _matchParser.ParseMatches(input);

            foreach (var match in matches)
            {
                if (input.Position < match.Position)
                {
                    WriteRawData(input, output, match.Position - input.Position);
                }

                WriteMatchData(input, output, match);
            }

            if (input.Position < input.Length)
            {
                WriteRawData(input, output, input.Length - input.Position);
            }
        }
Пример #17
0
        public void Encode(Stream input, Stream output)
        {
            _flagBuffer   = 0;
            _flagPosition = 0;
            _buffer       = new byte[32 * 2]; // at max 32 matches, one match is 2 bytes
            _bufferLength = 0;

            var start = Encoding.ASCII.GetBytes("Wp16");

            output.Write(start, 0, 4);
            output.Write(((int)input.Length).GetArrayLittleEndian(), 0, 4);

            var matches = _matchParser.ParseMatches(input);

            foreach (var match in matches)
            {
                // Compress raw data
                if (input.Position < match.Position)
                {
                    CompressRawData(input, output, (int)(match.Position - input.Position));
                }

                // Compress match
                CompressMatchData(input, output, match);
            }

            // Compress raw data
            if (input.Position < input.Length)
            {
                CompressRawData(input, output, (int)(input.Length - input.Position));
            }

            if (_flagPosition > 0)
            {
                WriteAndResetBuffer(output);
            }
        }
Пример #18
0
        public void Encode(Stream input, Stream output)
        {
            var originalOutputPosition = output.Position;

            output.Position += 6;

            _codeBlock         = 0;
            _codeBlockPosition = 0;
            _buffer            = new byte[4 * 3]; // each buffer can be at max 4 triplets of uncompressed data; a triplet is 3 bytes
            _bufferLength      = 0;

            var matches = _matchParser.ParseMatches(input);

            foreach (var match in matches)
            {
                // Compress raw data
                if (input.Position < match.Position)
                {
                    CompressRawData(input, output, (int)(match.Position - input.Position));
                }

                // Compress match
                CompressMatchData(input, output, match);
            }

            // Compress raw data
            if (input.Position < input.Length)
            {
                CompressRawData(input, output, (int)(input.Length - input.Position));
            }

            WriteAndResetBuffer(output);

            // Write header information
            WriteHeaderData(input, output, originalOutputPosition);
        }
Пример #19
0
        public void Encode(Stream input, Stream output)
        {
            var matches = _matchParser.ParseMatches(input);

            foreach (var match in matches)
            {
                // Compress raw data
                if (input.Position < match.Position)
                {
                    CompressRawData(input, output, (int)(match.Position - input.Position));
                }

                // Compress match
                CompressMatchData(input, output, match);
            }

            // Compress raw data
            if (input.Position < input.Length)
            {
                CompressRawData(input, output, (int)(input.Length - input.Position));
            }

            output.Write(new byte[3], 0, 3);
        }
Пример #20
0
        public void Encode(Stream input, Stream output)
        {
            var matches = _matchParser.ParseMatches(input).ToArray();

            var compressedLength = PrecalculateCompressedLength(input.Length, matches);

            _codeBlock         = 0;
            _codeBlockPosition = 8;
            // We write all data backwards into the buffer; starting from last element down to first
            // We have 8 blocks; A block can be at max 2 bytes, defining a match
            _buffer       = new byte[8 * 2];
            _bufferLength = 0;

            using (var inputReverseStream = new ReverseStream(input, input.Length))
                using (var reverseOutputStream = new ReverseStream(output, compressedLength))
                {
                    foreach (var match in matches)
                    {
                        while (match.Position > inputReverseStream.Position)
                        {
                            if (_codeBlockPosition == 0)
                            {
                                WriteAndResetBuffer(reverseOutputStream);
                            }

                            _codeBlockPosition--;
                            _buffer[_bufferLength++] = (byte)inputReverseStream.ReadByte();
                        }

                        var byte1 = ((byte)(match.Length - 3) << 4) | (byte)((match.Displacement - 3) >> 8);
                        var byte2 = match.Displacement - 3;

                        if (_codeBlockPosition == 0)
                        {
                            WriteAndResetBuffer(reverseOutputStream);
                        }

                        _codeBlock |= (byte)(1 << --_codeBlockPosition);
                        _buffer[_bufferLength++] = (byte)byte1;
                        _buffer[_bufferLength++] = (byte)byte2;

                        inputReverseStream.Position += match.Length;
                    }

                    // Write any data after last match, to the buffer
                    while (inputReverseStream.Position < inputReverseStream.Length)
                    {
                        if (_codeBlockPosition == 0)
                        {
                            WriteAndResetBuffer(reverseOutputStream);
                        }

                        _codeBlockPosition--;
                        _buffer[_bufferLength++] = (byte)inputReverseStream.ReadByte();
                    }

                    // Flush remaining buffer to stream
                    WriteAndResetBuffer(reverseOutputStream);

                    output.Position = compressedLength;
                    WriteFooterInformation(input, output);
                }
        }
Пример #21
0
        public void Encode(Stream input, Stream output)
        {
            var matches = _matchParser.ParseMatches(input).ToArray();

            WriteCompressedData(input, output, matches);
        }
Пример #22
0
        public void Encode(Stream input, Stream output)
        {
            var originalOutputPosition = output.Position;

            output.Position += 0x10;

            _codeBlock         = 0;
            _codeBlockPosition = 0;
            _buffer            = new byte[8 * 2]; // each buffer can be at max 8 pairs of compressed matches; a compressed match is 2 bytes
            _bufferLength      = 0;

            var matches = _matchParser.ParseMatches(input);

            foreach (var match in matches)
            {
                // Write any data before the match, to the uncompressed table
                while (input.Position < match.Position - _matchParser.FindOptions.PreBufferSize)
                {
                    if (_codeBlockPosition == 8)
                    {
                        WriteAndResetBuffer(output);
                    }

                    _codeBlock |= (byte)(1 << _codeBlockPosition++);
                    _buffer[_bufferLength++] = (byte)input.ReadByte();
                }

                // Write match data to the buffer
                var bufferPosition = (match.Position - match.Displacement) % WindowBufferLength;
                var firstByte      = (byte)bufferPosition;
                var secondByte     = (byte)(((bufferPosition >> 2) & 0xC0) | (byte)(match.Length - 3));

                if (_codeBlockPosition == 8)
                {
                    WriteAndResetBuffer(output);
                }

                _codeBlockPosition++; // Since a match is flagged with a 0 bit, we don't need a bit shift and just increase the position
                _buffer[_bufferLength++] = firstByte;
                _buffer[_bufferLength++] = secondByte;

                input.Position += match.Length;
            }

            // Write any data after last match, to the buffer
            while (input.Position < input.Length)
            {
                if (_codeBlockPosition == 8)
                {
                    WriteAndResetBuffer(output);
                }

                _codeBlock |= (byte)(1 << _codeBlockPosition++);
                _buffer[_bufferLength++] = (byte)input.ReadByte();
            }

            // Flush remaining buffer to stream
            WriteAndResetBuffer(output);

            // Write header information
            WriteHeaderData(input, output, originalOutputPosition);
        }
Пример #23
0
        public void Encode(Stream input, Stream output)
        {
            var originalOutputPosition = output.Position;

            output.Position += 0x10;

            _codeBlock         = 0;
            _codeBlockPosition = 8;
            _buffer            = new byte[8 * 3]; // each buffer can be at max 8 pairs of compressed matches; a compressed match can be at max 3 bytes
            _bufferLength      = 0;

            var matches = _matchParser.ParseMatches(input);

            foreach (var match in matches)
            {
                // Write any data before the match, to the buffer
                while (input.Position < match.Position)
                {
                    if (_codeBlockPosition == 0)
                    {
                        WriteAndResetBuffer(output);
                    }

                    _codeBlock |= (byte)(1 << --_codeBlockPosition);
                    _buffer[_bufferLength++] = (byte)input.ReadByte();
                }

                // Write match data to the buffer
                var firstByte  = (byte)((match.Displacement - 1) >> 8);
                var secondByte = (byte)(match.Displacement - 1);

                if (match.Length < 0x12)
                {
                    // Since minimum _length should be 3 for Yay0, we get a minimum matchLength of 1 in this case
                    firstByte |= (byte)((match.Length - 2) << 4);
                }

                if (_codeBlockPosition == 0)
                {
                    WriteAndResetBuffer(output);
                }

                _codeBlockPosition--; // Since a match is flagged with a 0 bit, we don't need a bit shift and just decrease the position
                _buffer[_bufferLength++] = firstByte;
                _buffer[_bufferLength++] = secondByte;
                if (match.Length >= 0x12)
                {
                    _buffer[_bufferLength++] = (byte)(match.Length - 0x12);
                }

                input.Position += match.Length;
            }

            // Write any data after last match, to the buffer
            while (input.Position < input.Length)
            {
                if (_codeBlockPosition == 0)
                {
                    WriteAndResetBuffer(output);
                }

                _codeBlock |= (byte)(1 << --_codeBlockPosition);
                _buffer[_bufferLength++] = (byte)input.ReadByte();
            }

            // Flush remaining buffer to stream
            WriteAndResetBuffer(output);

            // Write header information
            WriteHeaderData(input, output, originalOutputPosition);
        }