Blackthorne/Формат сжатия: различия между версиями
Перейти к навигации
Перейти к поиску
(Новая страница: «Часть ресурсов в файле DATA.DAT упаковано модифированным алгоритмом LZSS. Основ…») |
(Орфография) |
||
| Строка 1: | Строка 1: | ||
Часть ресурсов в файле [[Blackthorne/DATA.DAT|DATA.DAT]] упаковано | Часть ресурсов в файле [[Blackthorne/DATA.DAT|DATA.DAT]] упаковано модифицированным алгоритмом LZSS. Основных отличий два — биты в управляющем байте развернуты задом наперед (то есть 8-й бит — это первый байт в потоке) и к размеру копируемых данных из буфера добавляется 3. | ||
Пример на Python: | Пример на Python: | ||
Текущая версия от 18:51, 17 июня 2018
Часть ресурсов в файле 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