User Tools


    Site Tools

    supercross_2000:eahd

    Table of Contents

    EAHD

    This is a compression format created by MBL Research and used by EA Games.


    The header takes up the first 5 bytes of the compressed file

    Offset#BytesDescription
    0x02Magic Number 0x10FB
    0x23Uncompressed size

    Decompression Code

    Python

    EAHD parser class

    eahd.py
    1. class EAHD:
    2. def __init__(self, src):
    3. self.src = src
    4.  
    5. def __bytes_to_int24(self, arr, offset):
    6. return int.from_bytes(arr[offset:offset+3], byteorder='big')
    7.  
    8. def __bytes_to_int_reversed(self, arr, offset):
    9. return int.from_bytes(arr[offset:offset+4], byteorder='little')
    10.  
    11. def __memset(self, dst, dst_offset, value, amount):
    12. for i in range(amount):
    13. dst[dst_offset + i] = value
    14.  
    15. def __memcpy(self, dst, dst_offset, dst_backwards_offset, amount):
    16. src_offset = dst_offset - dst_backwards_offset
    17. for i in range(amount):
    18. dst[dst_offset + i] = dst[src_offset + i]
    19.  
    20. def __fetch_bytes(self, dst, dst_offset, dst_backwards_offset, amount):
    21. if dst_backwards_offset > 1:
    22. self.__memcpy(dst, dst_offset, dst_backwards_offset, amount)
    23. else:
    24. self.__memset(dst, dst_offset, dst[dst_offset - dst_backwards_offset], amount)
    25. return dst_offset + amount
    26.  
    27. def __copy_literal(self, dst, dst_offset, src, src_offset, amount):
    28. for i in range(amount):
    29. dst[dst_offset + i] = src[src_offset + i]
    30.  
    31. def parse(self):
    32. decompressed_size = self.__bytes_to_int24(self.src, 0x2)
    33. dst = [0] * decompressed_size # Decompressed data list
    34. src_offset = 0x5
    35. dst_offset = 0
    36. while True:
    37. cmd = self.__bytes_to_int_reversed(self.src, src_offset)
    38. if cmd & 0x80 == 0: # Covers commands 00 to 7F
    39. src_offset += 2
    40. # Copy bytes from the compressed data array
    41. amount_to_copy = cmd & 0x3
    42. self.__copy_literal(dst, dst_offset, self.src, src_offset, amount_to_copy)
    43. src_offset += amount_to_copy
    44. dst_offset += amount_to_copy
    45. # Fetch bytes from previous decompressed data
    46. backward_fetch_offset = ((cmd << 3) & 0x300) + ((cmd >> 8) & 0xFF) + 1
    47. amount_of_bytes_to_fetch = ((cmd >> 2) & 0x7) + 3
    48. dst_offset = self.__fetch_bytes(dst, dst_offset, backward_fetch_offset, amount_of_bytes_to_fetch)
    49. continue
    50. if cmd & 0x40 == 0: # Covers commands 0x80 to 0xBF
    51. # Copy bytes from the compressed data array
    52. src_offset += 3
    53. amount_to_copy = ((cmd >> 8) >> 6) & 0x3
    54. self.__copy_literal(dst, dst_offset, self.src, src_offset, amount_to_copy)
    55. src_offset += amount_to_copy
    56. dst_offset += amount_to_copy
    57. # Fetch bytes from previous decompressed data
    58. backward_fetch_offset = (((cmd >> 8) << 8) & 0x3F00) + ((cmd >> 16) & 0xFF) + 1
    59. amount_of_bytes_to_fetch = (cmd & 0x3F) + 4
    60. dst_offset = self.__fetch_bytes(dst, dst_offset, backward_fetch_offset, amount_of_bytes_to_fetch)
    61. continue
    62. if cmd & 0x20 == 0: # Covers commands 0xC0 to 0xDF
    63. src_offset += 4
    64. amount_to_copy = cmd & 0x3
    65. self.__copy_literal(dst, dst_offset, self.src, src_offset, amount_to_copy)
    66. src_offset += amount_to_copy
    67. dst_offset += amount_to_copy
    68. # Fetch bytes from previous decompressed data
    69. backward_fetch_offset = ((cmd << 12) & 0x10000) + (((cmd >> 8) << 8) & 0xFF00) + 1 + ((cmd >> 16) & 0xFF)
    70. amount_of_bytes_to_fetch = ((cmd << 6) & 0x300) + ((cmd >> 24) & 0xFF) + 5
    71. dst_offset = self.__fetch_bytes(dst, dst_offset, backward_fetch_offset, amount_of_bytes_to_fetch)
    72. continue
    73. src_offset += 1
    74. if (cmd & 0xFF) < 0xFC: # Covers commands 0xE0 to 0xFB
    75. # Copy bytes from the compressed data array
    76. amount_to_copy = ((cmd & 0x1F) + 1) * 4
    77. self.__copy_literal(dst, dst_offset, self.src, src_offset, amount_to_copy)
    78. src_offset += amount_to_copy
    79. dst_offset += amount_to_copy
    80. continue
    81. if cmd & 3 != 0: # Copy any left-over bytes
    82. # Copy bytes from the compressed data array
    83. amount_to_copy = cmd & 0x3
    84. self.__copy_literal(dst, dst_offset, self.src, src_offset, amount_to_copy)
    85. src_offset += amount_to_copy
    86. dst_offset += amount_to_copy
    87. break # A command of 0xFC, 0xFD, 0xFE, or 0xFF will end the decompression routine.
    88. return dst

    Using the EAHD parser

    eahd_parser.py
    1. from eahd import EAHD
    2.  
    3. parser = EAHD(bytes) # 'bytes' is the list of compressed bytes.
    4. uncompressed_bytes = parser.parse()
    supercross_2000/eahd.txt · Last modified: by David