diff --git a/isp_tsp_parameter.py b/isp_tsp_parameter.py index f7405d2..37c5119 100644 --- a/isp_tsp_parameter.py +++ b/isp_tsp_parameter.py @@ -25,7 +25,7 @@ class IspTspInstructionWord: dcalc_ctrl: int def __init__(self, value): - assert (value & 0xfffff) == 0 + assert (value & 0xfffff) == 0, (value, hex(value)) self.depth_compare_mode = (value >> 29) & 0b111 self.culling_mode = (value >> 27) & 0b11 self.z_write_disable = (value >> 26) & 1 @@ -114,14 +114,19 @@ class ISPTSPParameterMV: def expected_skip_size(isp_tsp): pass -def parse_parameter(mem, offset, skip, tag_offset, vertex_count, modifier_volume): +def parse_parameter(mem, offset, skip, shadow, tag_offset, vertex_count, modifier_volume): assert skip >= 0, skip - skip = (skip + 3) # size of one vertex + assert shadow in {True, False} + if shadow: + skip = (skip * 2 + 3) + else: + skip = (skip + 3) # size of one vertex params = [] def unpack(i, t): i_offset = offset + i * 4 + #print("I_OFFSET:", i_offset) value, = struct.unpack("<" + t, mem[i_offset:i_offset + 4]) return value diff --git a/main.py b/main.py index b85bdd0..bfcb6fd 100644 --- a/main.py +++ b/main.py @@ -28,10 +28,12 @@ assert (holly.REGION_BASE & 0b11) == 0, holly.REGION_BASE region_array_entries = decode_region_array_entries(texture_memory, holly.REGION_BASE) -DEBUG = False +DEBUG = True def walk_region_array(*, tile_callback=None, parameter_callback=None, flush_callback=None): for entry in region_array_entries: + if DEBUG: + print(entry.tile) lists = [ ("opaque_list_pointer", entry.opaque_list_pointer), ("opaque_modifier_volume_list_pointer", entry.opaque_modifier_volume_list_pointer), @@ -56,15 +58,15 @@ def walk_region_array(*, tile_callback=None, parameter_callback=None, flush_call print(ol_entry) offset += 4 if type(ol_entry) == triangle_array: - param_offset = ol_entry.triangle_array_start + param_offset = holly.PARAM_BASE + ol_entry.triangle_array_start for i in range(ol_entry.number_of_triangles + 1): modifier_volume = list_type_name in {"opaque_modifier_volume_list_pointer", "translucent_modifier_volume_list_pointer"} param_offset, parameter = parse_parameter(texture_memory, param_offset, skip=ol_entry.skip, + shadow=ol_entry.shadow, tag_offset=0, vertex_count=3, modifier_volume=modifier_volume) - if parameter_callback is not None: parameter_callback(entry.tile, list_type_name, list_pointer, ol_entry, parameter) @@ -85,7 +87,7 @@ def walk_region_array(*, tile_callback=None, parameter_callback=None, flush_call flush_callback(entry.tile) def new_tile_surface(): - surface = pygame.Surface((32, 32), pygame.SRCALPHA) + surface = pygame.Surface((32, 32)) surface.fill((0, 0, 0, 0)) return surface @@ -98,9 +100,11 @@ def draw_background(tile): t = holly.ISP_BACKGND_T skip = (t >> 24) & 0b111 tag_address = ((t >> 3) & 0x1fffff) * 4 + parameter_address = tag_address + holly.PARAM_BASE - param_offset, parameter = parse_parameter(texture_memory, tag_address, + param_offset, parameter = parse_parameter(texture_memory, parameter_address, skip=skip, + shadow=0, tag_offset=0, vertex_count=3, modifier_volume=False) @@ -115,49 +119,49 @@ def draw_background(tile): points = [(0, 0), (640, 0), (640, 480), (0, 480)] - tile_ix = tile.tile_y_position * x_tiles + tile.tile_x_position + global primary_buffer pygame.draw.polygon(primary_buffer, color, points) def tile_callback(tile): draw_background(tile) def flush_callback(tile, *, screen): - tile_ix = tile.tile_y_position * x_tiles + tile.tile_x_position + global primary_buffer screen.blit(primary_buffer, (tile.tile_x_position * 32, tile.tile_y_position * 32)) pygame.display.flip() - time.sleep(0.1) - def parameter_callback(tile, list_type_name, list_pointer, ol_entry, parameter): - # tile=RegionArrayTile(last_region=1, z_clear=0, flush_accumulate=0, tile_y_position=14, tile_x_position=19) - if list_type_name != "opaque_list_pointer": - return - left = tile.tile_x_position * 32 top = tile.tile_y_position * 32 - tile_ix = tile.tile_y_position * x_tiles + tile.tile_x_position - assert type(ol_entry) == triangle_array, ol_entry assert len(parameter.vertices) == 3, parameter.vertices - assert len(parameter.vertices[0].attributes) >= 1, parameter + + if list_type_name in {"opaque_modifier_volume_list_pointer", "translucent_modifier_volume_list_pointer"}: + argb_color = 0x00000000 + return + else: + assert len(parameter.vertices[0].attributes) >= 1, parameter + argb_color = parameter.vertices[0].attributes[0] points = [ (vertex.x - left, vertex.y - top) for vertex in parameter.vertices ] - argb_color = parameter.vertices[0].attributes[0] alpha = (argb_color >> 24) & 0xff red = (argb_color >> 16) & 0xff green = (argb_color >> 8) & 0xff blue = (argb_color >> 0) & 0xff - color = (red, green, blue, alpha) - - assert red > 10 or blue > 10 or green > 10, argb_color + color = (red, green, blue) pygame.draw.polygon(primary_buffer, color, points) +def main(): + walk_region_array(tile_callback=None, + parameter_callback=None, + flush_callback=None) + def draw(): pygame.init() screen = pygame.display.set_mode((640, 480)) @@ -178,4 +182,5 @@ def draw(): pygame.quit() +#main() draw() diff --git a/object_list.py b/object_list.py index 51f1539..ea922b2 100644 --- a/object_list.py +++ b/object_list.py @@ -16,6 +16,14 @@ class triangle_strip: self.skip = (value >> 21) & 0b111 self.triangle_strip_start = (value & 0x1fffff) << 2 + 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 triangle_array: number_of_triangles: int @@ -31,6 +39,14 @@ class triangle_array: self.skip = (value >> 21) & 0b111 self.triangle_array_start = (value & 0x1fffff) << 2 + 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 quad_array: number_of_quads: int @@ -46,6 +62,14 @@ class quad_array: self.skip = (value >> 21) & 0b111 self.quad_array_start = (value & 0x1fffff) << 2 + 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 object_pointer_block_link: end_of_list: int @@ -58,6 +82,13 @@ class object_pointer_block_link: self.end_of_list = (value >> 28) & 1 self.next_pointer_block = 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)})' def decode_ol_entry(mem, offset): value, = struct.unpack("> 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