supercross_2000:eahd
Table of Contents
EAHD
This is a compression format created by MBL Research and used by EA Games.
Header
The header takes up the first 5 bytes of the compressed file
| Offset | #Bytes | Description |
|---|---|---|
| 0x0 | 2 | Magic Number 0x10FB |
| 0x2 | 3 | Uncompressed size |
Decompression Code
Python
EAHD parser class
- eahd.py
- class EAHD:
- def __init__(self, src):
- self.src = src
- def __bytes_to_int24(self, arr, offset):
- return int.from_bytes(arr[offset:offset+3], byteorder='big')
- def __bytes_to_int_reversed(self, arr, offset):
- return int.from_bytes(arr[offset:offset+4], byteorder='little')
- def __memset(self, dst, dst_offset, value, amount):
- for i in range(amount):
- dst[dst_offset + i] = value
- def __memcpy(self, 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 __fetch_bytes(self, dst, dst_offset, dst_backwards_offset, amount):
- if dst_backwards_offset > 1:
- self.__memcpy(dst, dst_offset, dst_backwards_offset, amount)
- else:
- self.__memset(dst, dst_offset, dst[dst_offset - dst_backwards_offset], amount)
- return dst_offset + amount
- def __copy_literal(self, dst, dst_offset, src, src_offset, amount):
- for i in range(amount):
- dst[dst_offset + i] = src[src_offset + i]
- def parse(self):
- decompressed_size = self.__bytes_to_int24(self.src, 0x2)
- dst = [0] * decompressed_size # Decompressed data list
- src_offset = 0x5
- dst_offset = 0
- while True:
- cmd = self.__bytes_to_int_reversed(self.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
- self.__copy_literal(dst, dst_offset, self.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 = self.__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
- self.__copy_literal(dst, dst_offset, self.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 = self.__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
- self.__copy_literal(dst, dst_offset, self.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 = self.__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
- self.__copy_literal(dst, dst_offset, self.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
- self.__copy_literal(dst, dst_offset, self.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
Using the EAHD parser
- eahd_parser.py
- from eahd import EAHD
- parser = EAHD(bytes) # 'bytes' is the list of compressed bytes.
- uncompressed_bytes = parser.parse()
supercross_2000/eahd.txt · Last modified: by David