34 lines
1.3 KiB
GDScript3
34 lines
1.3 KiB
GDScript3
|
static func decompress_lzss(rom: StreamPeer, uncompressed_length:=0) -> PoolByteArray:
|
||
|
# Algorithm from http://slickproductions.org/slickwiki/index.php/Noisecross:Final_Fantasy_V_Compression
|
||
|
# Reuploaded at https://www.ff6hacking.com/ff5wiki/index.php/Compression#Decompression_Type_02_.28LZSS.29
|
||
|
if not uncompressed_length:
|
||
|
uncompressed_length = rom.get_u16()
|
||
|
var output := PoolByteArray()
|
||
|
var buffer := PoolByteArray()
|
||
|
buffer.resize(0x800)
|
||
|
buffer.fill(0)
|
||
|
var buffer_p := 0x07DE
|
||
|
while len(output) < uncompressed_length:
|
||
|
var bitmap_byte := rom.get_u8()
|
||
|
for i in range(8):
|
||
|
var bit := (bitmap_byte >> i) & 1
|
||
|
if bit:
|
||
|
var b := rom.get_u8()
|
||
|
output.append(b)
|
||
|
buffer[buffer_p] = b
|
||
|
buffer_p = (buffer_p+1) % 0x800
|
||
|
else:
|
||
|
# Reuse bytes from previously decompressed buffer
|
||
|
var b1 := rom.get_u8() # lower 8 bits of offset
|
||
|
var b2 := rom.get_u8() # upper 3 bits of offset, 5bit length-3
|
||
|
var offset := b1 | ((b2 & 0xE0) << 3) # 11bit is [0, 0x7FF]
|
||
|
var length := (b2 & 0x1F) + 3 # The +3 is likely because the compression overhead makes this a sensible minimum
|
||
|
for j in range(length):
|
||
|
var b := buffer[offset]
|
||
|
output.append(b)
|
||
|
buffer[buffer_p] = b
|
||
|
buffer_p = (buffer_p+1) % 0x800
|
||
|
offset = (offset+1) % 0x800
|
||
|
output.resize(uncompressed_length)
|
||
|
return output
|