public void Build(BitReader br, int valueBitCount) { _root = new Node(); ReadNode(br, _root, valueBitCount); }
public static byte[] Decompress(byte[] data, byte[] prev = null) { var output = new List <byte>(); var outputPosition = 0; if (prev != null) { output = new List <byte>(prev); outputPosition = prev.Length; } using (var br = new BitReader(new MemoryStream(data), 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 displacementIndexMapping = new Tree(); displacementIndexMapping.Build(br, 5); while (true) { var index = indexValueMapping.ReadValue(br); if (index == 0) { // Finish decompression if (initialByte < 3) { break; } var outputLength = output.Count - outputPosition; var iVar4 = initialByte - 2; if (outputLength <= iVar4) { break; } var length = outputLength - iVar4; var position = 0; do { length--; var byte1 = output[outputPosition + position]; var byte2 = output[outputPosition + iVar4 + position]; output[outputPosition + iVar4 + position] = (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 displacementIndex = displacementIndexMapping.ReadValue(br); var displacement = DisplacementRanges[displacementIndex]; if (DisplacementBitReads[displacementIndex] != 0) { displacement += br.ReadBits <int>(DisplacementBitReads[displacementIndex]); } if (counter == 0) { continue; } var bufferIndex = _windowBufferPosition + WindowBuffer.Length - displacement; for (int i = 0; i < counter; i++) { var next = WindowBuffer[bufferIndex++ % WindowBuffer.Length]; output.Add(next); WindowBuffer[_windowBufferPosition] = next; _windowBufferPosition = (_windowBufferPosition + 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.Add(rawValue); WindowBuffer[_windowBufferPosition] = rawValue; _windowBufferPosition = (_windowBufferPosition + 1) % WindowBuffer.Length; } } } } return(output.ToArray()); }