User Tools

Site Tools


supercross_2000:ovln

This is an old revision of the document!


Table of Contents

OVLN

This is a compression format used by EA Games


The header takes up the first 0x15 bytes of the compressed file

Offset#BytesDescription
0x004“OVLN”
0x044Compressed size (including the header)
0x084RAM location to decompress
0x0C4RAM location to JAL to when done
0x102Magic Number. If it is 0x10FB then decompress, otherwise directly DMA with uncompressed size.
0x123Uncompressed size

Decompression Code

Python

ovln_parse.py
  1. def bytes_to_int24(arr, offset):
  2. return (arr[offset + 0] << 16) | (arr[offset + 1] << 8) | arr[offset + 2]
  3.  
  4. # get 4 bytes from the array and arrange them in little endian order.
  5. def bytes_to_int_reversed(arr, offset):
  6. arr_boundary = len(arr) - offset # for safety
  7. if arr_boundary >= 4:
  8. return (arr[offset + 3] << 24) | (arr[offset + 2] << 16) | (arr[offset + 1] << 8) | arr[offset]
  9. elif arr_boundary == 3:
  10. return (arr[offset + 2] << 16) | (arr[offset + 1] << 8) | arr[offset]
  11. elif arr_boundary == 2:
  12. return (arr[offset + 1] << 8) | arr[offset]
  13. else:
  14. return arr[offset]
  15.  
  16. def ovln_memset(dst, dst_offset, value, amount):
  17. for i in range(amount):
  18. dst[dst_offset + i] = value
  19.  
  20. def ovln_memcpy(dst, dst_offset, dst_backwards_offset, amount):
  21. src_offset = dst_offset - dst_backwards_offset
  22. for i in range(amount):
  23. dst[dst_offset + i] = dst[src_offset + i]
  24.  
  25. def ovln_fetch_bytes(dst, dst_offset, dst_backwards_offset, amount):
  26. if dst_backwards_offset > 1:
  27. ovln_memcpy(dst, dst_offset, dst_backwards_offset, amount)
  28. else:
  29. ovln_memset(dst, dst_offset, dst[dst_offset - dst_backwards_offset], amount)
  30. return dst_offset + amount
  31.  
  32. def ovln_copy_literal(dst, dst_offset, src, src_offset, amount):
  33. for i in range(amount):
  34. dst[dst_offset + i] = src[src_offset + i]
  35.  
  36. # Input: src = compressed data list
  37. # Output: returns decompressed data list
  38. def ovln_parse(src):
  39. decompressed_size = bytes_to_int24(src, 0x12)
  40. dst = [0] * decompressed_size # Decompressed data list
  41. src_offset = 0x15
  42. dst_offset = 0
  43. while True:
  44. cmd = bytes_to_int_reversed(src, src_offset)
  45. if cmd & 0x80 == 0: # Covers commands 00 to 7F
  46. src_offset += 2
  47. # Copy bytes from the compressed data array
  48. amount_to_copy = cmd & 0x3
  49. ovln_copy_literal(dst, dst_offset, src, src_offset, amount_to_copy)
  50. src_offset += amount_to_copy
  51. dst_offset += amount_to_copy
  52. # Fetch bytes from previous decompressed data
  53. backward_fetch_offset = ((cmd << 3) & 0x300) + ((cmd >> 8) & 0xFF) + 1
  54. amount_of_bytes_to_fetch = ((cmd >> 2) & 0x7) + 3
  55. dst_offset = ovln_fetch_bytes(dst, dst_offset, backward_fetch_offset, amount_of_bytes_to_fetch)
  56. continue
  57. if cmd & 0x40 == 0: # Covers commands 0x80 to 0xBF
  58. # Copy bytes from the compressed data array
  59. src_offset += 3
  60. amount_to_copy = ((cmd >> 8) >> 6) & 0x3
  61. ovln_copy_literal(dst, dst_offset, src, src_offset, amount_to_copy)
  62. src_offset += amount_to_copy
  63. dst_offset += amount_to_copy
  64. # Fetch bytes from previous decompressed data
  65. backward_fetch_offset = (((cmd >> 8) << 8) & 0x3F00) + ((cmd >> 16) & 0xFF) + 1
  66. amount_of_bytes_to_fetch = (cmd & 0x3F) + 4
  67. dst_offset = ovln_fetch_bytes(dst, dst_offset, backward_fetch_offset, amount_of_bytes_to_fetch)
  68. continue
  69. if cmd & 0x20 == 0: # Covers commands 0xC0 to 0xDF
  70. src_offset += 4
  71. amount_to_copy = cmd & 0x3
  72. ovln_copy_literal(dst, dst_offset, src, src_offset, amount_to_copy)
  73. src_offset += amount_to_copy
  74. dst_offset += amount_to_copy
  75. # Fetch bytes from previous decompressed data
  76. backward_fetch_offset = ((cmd << 12) & 0x10000) + (((cmd >> 8) << 8) & 0xFF00) + 1 + ((cmd >> 16) & 0xFF)
  77. amount_of_bytes_to_fetch = ((cmd << 6) & 0x300) + ((cmd >> 24) & 0xFF) + 5
  78. dst_offset = ovln_fetch_bytes(dst, dst_offset, backward_fetch_offset, amount_of_bytes_to_fetch)
  79. continue
  80. src_offset += 1
  81. if (cmd & 0xFF) < 0xFC: # Covers commands 0xE0 to 0xFB
  82. # Copy bytes from the compressed data array
  83. amount_to_copy = ((cmd & 0x1F) + 1) * 4
  84. ovln_copy_literal(dst, dst_offset, src, src_offset, amount_to_copy)
  85. src_offset += amount_to_copy
  86. dst_offset += amount_to_copy
  87. continue
  88. if cmd & 3 != 0: # Copy any left-over bytes
  89. # Copy bytes from the compressed data array
  90. amount_to_copy = cmd & 0x3
  91. ovln_copy_literal(dst, dst_offset, src, src_offset, amount_to_copy)
  92. src_offset += amount_to_copy
  93. dst_offset += amount_to_copy
  94. break # A command of 0xFC, 0xFD, 0xFE, or 0xFF will end the decompression routine.
  95. return dst

supercross_2000/ovln.1562268503.txt.gz · Last modified: 2019/07/04 19:28 by David