private void ReadMode0x81(Stream input, Stream output) { using (var br = new BitReader(input, BitOrder.LSBFirst, 1, ByteOrder.LittleEndian)) { var initialByte = br.ReadBits <int>(8); // 3 init holders var rawValueMapping = new Tree(); rawValueMapping.Build(br, 8); var indexValueMapping = new Tree(); indexValueMapping.Build(br, 6); var dispIndexMapping = new Tree(); dispIndexMapping.Build(br, 5); while (true) { var index = indexValueMapping.ReadValue(br); if (index == 0) { if (initialByte < 3) { break; } var iVar4 = initialByte - 2; if (output.Length <= iVar4) { break; } var length = output.Length - iVar4; var position = 0; do { length--; output.Position = position; var byte1 = output.ReadByte(); output.Position = position + iVar4; var byte2 = output.ReadByte(); output.Position--; output.WriteByte((byte)(byte1 + byte2)); position++; } while (length != 0); break; } if (index < 0x20) { // Match reading // Max displacement 0x8000; Min displacement 1 // Max length 0x102; Min length 1 var counter = _counters[index]; if (_counterBitReads[index] != 0) { counter += 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 (counter == 0) { continue; } var bufferIndex = _windowBufferOffset + _windowBuffer.Length - displacement; for (int i = 0; i < counter; i++) { var next = _windowBuffer[bufferIndex++ % _windowBuffer.Length]; output.WriteByte(next); _windowBuffer[_windowBufferOffset] = next; _windowBufferOffset = (_windowBufferOffset + 1) % _windowBuffer.Length; } } else { // Raw data reading index -= 0x20; var counter = _counters[index]; if (_counterBitReads[index] != 0) { counter += br.ReadBits <int>(_counterBitReads[index]); } if (counter == 0) { continue; } for (int i = 0; i < counter; i++) { var rawValue = (byte)rawValueMapping.ReadValue(br); output.WriteByte(rawValue); _windowBuffer[_windowBufferOffset] = rawValue; _windowBufferOffset = (_windowBufferOffset + 1) % _windowBuffer.Length; } } } } }
public void Build(BitReader br, int valueBitCount) { _root = new Node(); ReadNode(br, _root, valueBitCount); }