66 lines
2.0 KiB
Python
66 lines
2.0 KiB
Python
import struct
|
|
from dataclasses import dataclass
|
|
|
|
@dataclass
|
|
class RegionArrayTile:
|
|
last_region: int
|
|
z_clear: int
|
|
flush_accumulate: int
|
|
tile_y_position: int
|
|
tile_x_position: int
|
|
|
|
def __init__(self, value):
|
|
assert (value >> 29) & 1 == 0, value
|
|
assert (value >> 14) & 0x3fff == 0, value
|
|
assert (value >> 0) & 0b11 == 0, value
|
|
self.last_region = (value >> 31) & 0b1
|
|
self.z_clear = (value >> 30) & 0b1
|
|
self.flush_accumulate = (value >> 28) & 0b1
|
|
self.tile_y_position = (value >> 8) & 0b111111
|
|
self.tile_x_position = (value >> 2) & 0b111111
|
|
|
|
@dataclass
|
|
class RegionArrayPointer:
|
|
empty_ptr: int
|
|
pointer_to_object_list: int
|
|
|
|
def __init__(self, value):
|
|
assert (value >> 24) & 0x7f == 0
|
|
assert (value >> 0) & 0b11 == 0
|
|
self.empty_ptr = (value >> 31) & 1
|
|
self.pointer_to_object_list = value & 0xffffff
|
|
|
|
def __repr__(self):
|
|
fields = (
|
|
f'{name}={hex(value)}'
|
|
for field in self.__dataclass_fields__.values() if field.repr
|
|
for name, value in ((field.name, self.__getattribute__(field.name)),)
|
|
)
|
|
return f'{self.__class__.__name__}({", ".join(fields)})'
|
|
|
|
@dataclass
|
|
class RegionArrayEntry:
|
|
tile: RegionArrayTile
|
|
opaque_list_pointer: RegionArrayPointer
|
|
opaque_modifier_volume_list_pointer: RegionArrayPointer
|
|
translucent_list_pointer: RegionArrayPointer
|
|
translucent_modifier_volume_list_pointer: RegionArrayPointer
|
|
punch_through_list_pointer: RegionArrayPointer
|
|
|
|
def decode_region_array_entry(mem, offset):
|
|
next_offset = offset + 6 * 4
|
|
tile, *pointers = struct.unpack("<IIIIII", mem[offset:next_offset])
|
|
return next_offset, RegionArrayEntry(
|
|
RegionArrayTile(tile),
|
|
*map(RegionArrayPointer, pointers),
|
|
)
|
|
|
|
def decode_region_array_entries(mem, offset):
|
|
entries = []
|
|
while True:
|
|
offset, entry = decode_region_array_entry(mem, offset)
|
|
entries.append(entry)
|
|
if entry.tile.last_region:
|
|
break
|
|
return entries
|