Hack64 Wiki
Other Titles
Hack64 Wiki
Other Titles
This is an old revision of the document!
This is a compression format used by EA Games
The header takes up the first 0x15 bytes of the compressed file
Offset | #Bytes | Description |
---|---|---|
0x00 | 4 | “OVLN” |
0x04 | 4 | Compressed size (including the header) |
0x08 | 4 | RAM location to decompress |
0x0C | 4 | RAM location to JAL to when done |
0x10 | 2 | Magic Number. If it is 0x10FB then decompress, otherwise directly DMA with uncompressed size. |
0x12 | 3 | Uncompressed size |
def bytes_to_int24(arr, offset): return int.from_bytes(arr[offset:offset+4], byteorder='big') >> 8 def bytes_to_int_reversed(arr, offset): return int.from_bytes(arr[offset:offset+4], byteorder='little') def ovln_memset(dst, dst_offset, value, amount): for i in range(amount): dst[dst_offset + i] = value def ovln_memcpy(dst, dst_offset, dst_backwards_offset, amount): src_offset = dst_offset - dst_backwards_offset for i in range(amount): dst[dst_offset + i] = dst[src_offset + i] def ovln_fetch_bytes(dst, dst_offset, dst_backwards_offset, amount): if dst_backwards_offset > 1: ovln_memcpy(dst, dst_offset, dst_backwards_offset, amount) else: ovln_memset(dst, dst_offset, dst[dst_offset - dst_backwards_offset], amount) return dst_offset + amount def ovln_copy_literal(dst, dst_offset, src, src_offset, amount): for i in range(amount): dst[dst_offset + i] = src[src_offset + i] # Input: src = compressed data list # Output: returns decompressed data list def ovln_parse(src): decompressed_size = bytes_to_int24(src, 0x12) dst = [0] * decompressed_size # Decompressed data list src_offset = 0x15 dst_offset = 0 while True: cmd = bytes_to_int_reversed(src, src_offset) if cmd & 0x80 == 0: # Covers commands 00 to 7F src_offset += 2 # Copy bytes from the compressed data array amount_to_copy = cmd & 0x3 ovln_copy_literal(dst, dst_offset, src, src_offset, amount_to_copy) src_offset += amount_to_copy dst_offset += amount_to_copy # Fetch bytes from previous decompressed data backward_fetch_offset = ((cmd << 3) & 0x300) + ((cmd >> 8) & 0xFF) + 1 amount_of_bytes_to_fetch = ((cmd >> 2) & 0x7) + 3 dst_offset = ovln_fetch_bytes(dst, dst_offset, backward_fetch_offset, amount_of_bytes_to_fetch) continue if cmd & 0x40 == 0: # Covers commands 0x80 to 0xBF # Copy bytes from the compressed data array src_offset += 3 amount_to_copy = ((cmd >> 8) >> 6) & 0x3 ovln_copy_literal(dst, dst_offset, src, src_offset, amount_to_copy) src_offset += amount_to_copy dst_offset += amount_to_copy # Fetch bytes from previous decompressed data backward_fetch_offset = (((cmd >> 8) << 8) & 0x3F00) + ((cmd >> 16) & 0xFF) + 1 amount_of_bytes_to_fetch = (cmd & 0x3F) + 4 dst_offset = ovln_fetch_bytes(dst, dst_offset, backward_fetch_offset, amount_of_bytes_to_fetch) continue if cmd & 0x20 == 0: # Covers commands 0xC0 to 0xDF src_offset += 4 amount_to_copy = cmd & 0x3 ovln_copy_literal(dst, dst_offset, src, src_offset, amount_to_copy) src_offset += amount_to_copy dst_offset += amount_to_copy # Fetch bytes from previous decompressed data backward_fetch_offset = ((cmd << 12) & 0x10000) + (((cmd >> 8) << 8) & 0xFF00) + 1 + ((cmd >> 16) & 0xFF) amount_of_bytes_to_fetch = ((cmd << 6) & 0x300) + ((cmd >> 24) & 0xFF) + 5 dst_offset = ovln_fetch_bytes(dst, dst_offset, backward_fetch_offset, amount_of_bytes_to_fetch) continue src_offset += 1 if (cmd & 0xFF) < 0xFC: # Covers commands 0xE0 to 0xFB # Copy bytes from the compressed data array amount_to_copy = ((cmd & 0x1F) + 1) * 4 ovln_copy_literal(dst, dst_offset, src, src_offset, amount_to_copy) src_offset += amount_to_copy dst_offset += amount_to_copy continue if cmd & 3 != 0: # Copy any left-over bytes # Copy bytes from the compressed data array amount_to_copy = cmd & 0x3 ovln_copy_literal(dst, dst_offset, src, src_offset, amount_to_copy) src_offset += amount_to_copy dst_offset += amount_to_copy break # A command of 0xFC, 0xFD, 0xFE, or 0xFF will end the decompression routine. return dst