187 lines
6.6 KiB
Python
187 lines
6.6 KiB
Python
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()
|