private void ReadCompressedData(BitReader br, Stream output, TaikoLz81Tree dispIndexMapping, int index) { // Max displacement 0x8000; Min displacement 2 // Max length 0x102; Min length 1 var length = _counters[index]; if (_counterBitReads[index] != 0) { length += br.ReadBits <int>(_counterBitReads[index]); } var dispIndex = dispIndexMapping.ReadValue(br); var displacement = _dispRanges[dispIndex]; if (_dispBitReads[dispIndex] != 0) { displacement += br.ReadBits <int>(_dispBitReads[dispIndex]); } if (length == 0) { return; } _circularBuffer.Copy(output, displacement, length); }
public void Decode(Stream input, Stream output) { var circularBuffer = new CircularBuffer(0x8000); using (var br = new BitReader(input, BitOrder.LeastSignificantBitFirst, 1, ByteOrder.LittleEndian)) { var initialByte = br.ReadBits <int>(8); // 3 value mappings var rawValueMapping = new TaikoLz81Tree(); rawValueMapping.Build(br, 8); var indexValueMapping = new TaikoLz81Tree(); indexValueMapping.Build(br, 6); var dispIndexMapping = new TaikoLz81Tree(); dispIndexMapping.Build(br, 5); while (true) { var index = indexValueMapping.ReadValue(br); if (index < 0x20) { if (index == 0) { DeobfuscateData(output, initialByte); break; } // Match reading ReadCompressedData(br, output, circularBuffer, dispIndexMapping, index); } else { // Raw data reading ReadUncompressedData(br, output, circularBuffer, rawValueMapping, index - 0x20); } } } }
private void ReadUncompressedData(BitReader br, Stream output, TaikoLz81Tree rawValueMapping, int index) { var counter = _counters[index]; if (_counterBitReads[index] != 0) { counter += br.ReadBits <int>(_counterBitReads[index]); } if (counter == 0) { return; } for (int i = 0; i < counter; i++) { var rawValue = (byte)rawValueMapping.ReadValue(br); output.WriteByte(rawValue); _circularBuffer.WriteByte(rawValue); } }