core_decoder/isp_tsp_parameter.py
2025-08-28 12:52:44 -05:00

176 lines
4.8 KiB
Python

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