Blackthorne/Формат сжатия
Перейти к навигации
Перейти к поиску
Часть ресурсов в файле DATA.DAT упаковано модифицированным алгоритмом LZSS. Основных отличий два — биты в управляющем байте развернуты задом наперед (то есть 8-й бит — это первый байт в потоке) и к размеру копируемых данных из буфера добавляется 3.
Пример на Python:
def bits(byte): # Backward access return ( byte & 1, (byte >> 1) & 1, (byte >> 2) & 1, (byte >> 3) & 1, (byte >> 4) & 1, (byte >> 5) & 1, (byte >> 6) & 1, (byte >> 7) & 1, ) def control(word): return ( (word >> 12) + 3, # Blocksize (3 is custom from Blizzard) word & 0x0fff # Position on buffer ) def LZSS_BT_Unpack(stream): unpacked_size = Int32ul.parse(stream[0:4]) buffer = bytearray(4096) buffer_pos = 0 unpacked_pos = 0 # first 4 bytes - size of unpacked data pos = 4 unpacked = bytearray() while pos < len(stream): # First byte is control byte. Each bit controls what is next byte would be: # 1 - non-compressed, 0 - compressed 2-byte control_byte = bits(stream[pos]) pos += 1 for bit in control_byte: # Non-compressed data if bit == 1: buffer[buffer_pos] = stream[pos] buffer_pos += 1 if buffer_pos >= len(buffer): buffer_pos -= len(buffer) unpacked.append(stream[pos]) pos += 1 unpacked_pos += 1 if unpacked_pos >= unpacked_size: break # Compressed data else: block_size, buffer_offset = control(Int16ul.parse(stream[pos:pos + 2])) pos += 2 i = 0 while i < block_size: buffer[buffer_pos] = buffer[buffer_offset] buffer_pos += 1 if buffer_pos >= len(buffer): buffer_pos -= len(buffer) unpacked.append(buffer[buffer_offset]) unpacked_pos += 1 buffer_offset += 1 if buffer_offset >= len(buffer): buffer_offset -= len(buffer) i += 1 if unpacked_pos >= unpacked_size: break return unpacked