import os os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide" import textwrap from pprint import pprint, pformat import sys import pygame from functools import partial from itertools import starmap import time from holly import decode_holly from region_array import decode_region_array_entries from object_list import * from isp_tsp_parameter import parse_parameter texture_memory_filename = sys.argv[1] holly_registers_filename = sys.argv[2] with open(texture_memory_filename, "rb") as f: texture_memory = memoryview(f.read()) with open(holly_registers_filename, "rb") as f: holly_registers = memoryview(f.read()) holly = decode_holly(holly_registers) assert (holly.REGION_BASE & 0b11) == 0, holly.REGION_BASE region_array_entries = decode_region_array_entries(texture_memory, holly.REGION_BASE) 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), ("translucent_list_pointer", entry.translucent_list_pointer), ("translucent_modifier_volume_list_pointer", entry.translucent_modifier_volume_list_pointer), ("punch_through_list_pointer", entry.punch_through_list_pointer), ] if tile_callback is not None: tile_callback(entry.tile) for list_type_name, list_pointer in lists: if DEBUG: print(" " * 4, end='') print(list_type_name, list_pointer) if list_pointer.empty_ptr: continue offset = list_pointer.pointer_to_object_list while True: ol_entry = decode_ol_entry(texture_memory, offset) if DEBUG: print(" " * 8, end='') print(ol_entry) offset += 4 if type(ol_entry) == triangle_array: 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) if DEBUG: print(textwrap.indent( pformat(parameter), " " * 12 )) if type(ol_entry) == object_pointer_block_link: if ol_entry.end_of_list: break else: offset = ol_entry.next_pointer_block if entry.tile.flush_accumulate == 0: if flush_callback is not None: flush_callback(entry.tile) def new_tile_surface(): surface = pygame.Surface((32, 32)) surface.fill((0, 0, 0, 0)) return surface x_tiles = (640 // 32) y_tiles = (480 // 32) primary_buffer = None 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, parameter_address, skip=skip, shadow=0, tag_offset=0, vertex_count=3, modifier_volume=False) assert len(parameter.vertices) == 3, parameter.vertices assert len(parameter.vertices[0].attributes) >= 1, parameter 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) points = [(0, 0), (640, 0), (640, 480), (0, 480)] global primary_buffer pygame.draw.polygon(primary_buffer, color, points) def tile_callback(tile): draw_background(tile) def flush_callback(tile, *, screen): global primary_buffer screen.blit(primary_buffer, (tile.tile_x_position * 32, tile.tile_y_position * 32)) pygame.display.flip() def parameter_callback(tile, list_type_name, list_pointer, ol_entry, parameter): left = tile.tile_x_position * 32 top = tile.tile_y_position * 32 assert type(ol_entry) == triangle_array, ol_entry assert len(parameter.vertices) == 3, parameter.vertices 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 ] alpha = (argb_color >> 24) & 0xff red = (argb_color >> 16) & 0xff green = (argb_color >> 8) & 0xff blue = (argb_color >> 0) & 0xff 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)) global primary_buffer primary_buffer = new_tile_surface() #sys.stdin.readline() walk_region_array(tile_callback=tile_callback, parameter_callback=parameter_callback, flush_callback=partial(flush_callback, screen=screen)) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: break pygame.quit() #main() draw()