from dataclasses import dataclass from functools import partial import struct @dataclass class IspTspInstructionWordMV: volume_instruction: int culling_mode: int def __init__(self, value): assert (value & 0x7ffffff) == 0 self.volume_instruction = (value >> 29) & 0b111 self.culling_mode = (value >> 27) & 0b11 @dataclass class IspTspInstructionWord: depth_compare_mode: int culling_mode: int z_write_disable: int texture: int offset: int gouraud_shading: int _16bit_uv: int cache_bypass: int dcalc_ctrl: int def __init__(self, value): 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 self.texture = (value >> 25) & 1 self.offset = (value >> 24) & 1 self.gouraud_shading = (value >> 23) & 1 self._16bit_uv = (value >> 22) & 1 self.cache_bypass = (value >> 21) & 1 self.dcalc_ctrl = (value >> 20) & 1 @dataclass class TspInstructionWord: src_alpha_instr: int dst_alpha_instr: int src_select: int dst_select: int fog_control: int color_clamp: int use_alpha: int ignore_texture_alpha: int flip_uv: int clamp_uv: int filter_mode: int super_sample_texture: int mip_map_d_adjust: int texture_shading_instruction: int texture_u_size: int texture_v_size: int def __init__(self, value): self.src_alpha_instr = (value >> 29) & 0b111 self.dst_alpha_instr = (value >> 26) & 0b111 self.src_select = (value >> 25) & 1 self.dst_select = (value >> 24) & 1 self.fog_control = (value >> 22) & 0b11 self.color_clamp = (value >> 21) & 1 self.use_alpha = (value >> 20) & 1 self.ignore_texture_alpha = (value >> 19) & 1 self.flip_uv = (value >> 17) & 0b11 self.clamp_uv = (value >> 15) & 0b11 self.filter_mode = (value >> 13) & 0b11 self.super_sample_texture = (value >> 12) & 1 self.mip_map_d_adjust = (value >> 8) & 0b1111 self.texture_shading_instruction = (value >> 6) & 0b11 self.texture_u_size = (value >> 3) & 0b111 self.texture_v_size = (value >> 0) & 0b111 @dataclass class TextureControlWord: mip_mapped: int vq_compressed: int pixel_format: int scan_order: int stride_select: int texture_address: int def __init__(self, value): assert (value >> 21) & 0b1111 == 0 self.mip_mapped = (value >> 31) & 1 self.vq_compressed = (value >> 30) & 1 self.pixel_format = (value >> 27) & 0b111 self.scan_order = (value >> 26) & 1 self.stride_select = (value >> 25) & 1 self.texture_address = ((value >> 0) & 0x1fffff) * 8 @dataclass class Vertex: x: float y: float z: float attributes: list @dataclass class ISPTSPParameter: isp_tsp_instruction_word: IspTspInstructionWord tsp_instruction_word: TspInstructionWord texture_control_word: TextureControlWord vertices: list[Vertex] @dataclass class ISPTSPParameterMV: isp_tsp_instruction_word: IspTspInstructionWord vertices: list[Vertex] def expected_skip_size(isp_tsp): pass def parse_parameter(mem, offset, skip, shadow, tag_offset, vertex_count, modifier_volume): assert skip >= 0, skip 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 unpack_int = partial(unpack, t="I") unpack_float = partial(unpack, t="f") if modifier_volume: assert skip == 3, skip parameter = ISPTSPParameterMV( IspTspInstructionWordMV(unpack_int(0)), vertices=[] ) value1 = unpack_int(1) assert value1 == 0, value1 value2 = unpack_int(2) assert value2 == 0, value2 else: parameter = ISPTSPParameter( IspTspInstructionWord(unpack_int(0)), TspInstructionWord(unpack_int(1)), TextureControlWord(unpack_int(2)), vertices=[] ) assert tag_offset == 0, tag_offset # FIXME i = 3 for _ in range(vertex_count): vertex = Vertex( x = unpack_float(i + 0), y = unpack_float(i + 1), z = unpack_float(i + 2), attributes=[] ) j = 3 while j < skip: vertex.attributes.append(unpack_int(i + j)) j += 1 parameter.vertices.append(vertex) i += skip return offset + i * 4, parameter