58 lines
2.0 KiB
Python
58 lines
2.0 KiB
Python
def hal_decompress(comp: bytes) -> bytes:
|
|
"""
|
|
HAL decompression based on exhal by devinacker
|
|
https://github.com/devinacker/exhal
|
|
"""
|
|
inpos = 0
|
|
|
|
inval = 0
|
|
output = bytearray()
|
|
while inval != 0xFF:
|
|
remaining = 65536 - inpos
|
|
if remaining < 1:
|
|
return bytes()
|
|
inval = comp[inpos]
|
|
inpos += 1
|
|
if inval == 0xFF:
|
|
break
|
|
if (inval & 0xE0) == 0xE0:
|
|
command = (inval >> 2) & 0x07
|
|
length = (((inval & 0x03) << 8) | comp[inpos]) + 1
|
|
inpos += 1
|
|
else:
|
|
command = inval >> 5
|
|
length = (inval & 0x1F) + 1
|
|
if (command == 2 and ((len(output) + 2*length) > 65536)) or (len(output) + length) > 65536:
|
|
return bytes()
|
|
if command == 0:
|
|
output.extend(comp[inpos:inpos+length])
|
|
inpos += length
|
|
elif command == 1:
|
|
output.extend([comp[inpos] for _ in range(length)])
|
|
inpos += 1
|
|
elif command == 2:
|
|
output.extend([comp[x] for _ in range(length) for x in (inpos, inpos+1)])
|
|
inpos += 2
|
|
elif command == 3:
|
|
output.extend([comp[inpos] + i for i in range(length)])
|
|
inpos += 1
|
|
elif command == 4 or command == 7:
|
|
offset = (comp[inpos] << 8) | comp[inpos + 1]
|
|
if (offset + length) > 65536:
|
|
return bytes()
|
|
output.extend(output[offset:offset+length])
|
|
inpos += 2
|
|
elif command == 5:
|
|
offset = (comp[inpos] << 8) | comp[inpos + 1]
|
|
if (offset + length) > 65536:
|
|
return bytes()
|
|
output.extend([int('{:08b}'.format(x)[::-1], 2) for x in output[offset:offset+length]])
|
|
inpos += 2
|
|
elif command == 6:
|
|
offset = (comp[inpos] << 8) | comp[inpos + 1]
|
|
if offset < length - 1:
|
|
return bytes()
|
|
output.extend([output[offset - x] for x in range(length)])
|
|
inpos += 2
|
|
return bytes(output)
|