186 lines
6.7 KiB
Python
186 lines
6.7 KiB
Python
import sys
|
|
from textwrap import indent
|
|
|
|
from registers_lookup import registers_lookup
|
|
from decode_bits import decode_bits
|
|
|
|
with open(sys.argv[1]) as f:
|
|
values = [
|
|
int(s.strip(), 16)
|
|
for s in f.read().strip().split(",")
|
|
if s
|
|
]
|
|
|
|
undocumented_registers = {
|
|
0x1720: "WAIT_UNTIL",
|
|
0x2184: "VAP_VSM_VTX_ASSM",
|
|
}
|
|
|
|
def decode_print(register_name, value, paren=False, display_register_name=None):
|
|
if display_register_name is None:
|
|
display_register_name = register_name
|
|
decoded_value = decode_bits(register_name, value)
|
|
head = decoded_value[0][2:]
|
|
tail = indent('\n'.join([f"= {head}", *decoded_value[1:]]), ' ')
|
|
if paren:
|
|
print(f" ({display_register_name})\n{tail}")
|
|
else:
|
|
print(f" {display_register_name}\n{tail}")
|
|
|
|
class Parser:
|
|
def __init__(self, values):
|
|
self.ix = 0
|
|
self.values = values
|
|
|
|
def peek(self):
|
|
return self.values[self.ix]
|
|
|
|
def consume(self):
|
|
value = self.peek()
|
|
self.ix += 1
|
|
return value
|
|
|
|
def skip(self):
|
|
self.ix += 1
|
|
|
|
def packet_type_0(self):
|
|
header = self.consume()
|
|
count = (header >> 16) & 0x3fff
|
|
one_reg = (header >> 15) & 0b1
|
|
reserved = (header >> 13) & 0b11
|
|
base_index = (header >> 0) & 0x1fff
|
|
assert reserved == 0, header
|
|
if one_reg:
|
|
print(f"type 0: {base_index:04x} {count} ONE_REG")
|
|
else:
|
|
#print(f"type 0: {base_index:04x} {count}")
|
|
pass
|
|
while count >= 0:
|
|
address = base_index << 2
|
|
value = self.consume()
|
|
#print(f" {address:04x} = {value:08x}")
|
|
if address in registers_lookup:
|
|
register_name = registers_lookup[address]
|
|
try:
|
|
if one_reg or value == 0:
|
|
assert False
|
|
decode_print(register_name, value)
|
|
except AssertionError:
|
|
print(f" {register_name} = 0x{value:08x}")
|
|
else:
|
|
print(f" {undocumented_registers[address]} = 0x{value:08x}")
|
|
count -= 1
|
|
if not one_reg:
|
|
base_index += 1
|
|
|
|
def packet_type_1(self):
|
|
header = self.consume()
|
|
assert False, header
|
|
|
|
def packet_type_2(self):
|
|
print("type 2")
|
|
self.skip()
|
|
|
|
def packet_type_3(self):
|
|
header = self.consume()
|
|
reserved = (header >> 0) & 0xff
|
|
assert reserved == 0, header
|
|
it_opcode = (header >> 8) & 0xff
|
|
count = (header >> 16) & 0x3fff
|
|
|
|
opcode_names = dict((v, k) for k, v in [
|
|
("3D_DRAW_VBUF", 0x28),
|
|
("3D_DRAW_IMMD", 0x29),
|
|
("3D_DRAW_INDX", 0x2A),
|
|
("LOAD_PALETTE", 0x2C),
|
|
("3D_LOAD_VBPNTR", 0x2F),
|
|
("INDX_BUFFER", 0x33),
|
|
("3D_DRAW_VBUF_2", 0x34),
|
|
("3D_DRAW_IMMD_2", 0x35),
|
|
("3D_DRAW_INDX_2", 0x36),
|
|
("3D_CLEAR_HIZ", 0x37),
|
|
("3D_DRAW_128", 0x39),
|
|
])
|
|
opcode_name = f"{it_opcode:02x}" if it_opcode not in opcode_names else opcode_names[it_opcode]
|
|
|
|
registers = {
|
|
"3D_DRAW_VBUF": ["VAP_VTX_FMT", "VAP_VF_CNTL"],
|
|
"3D_DRAW_IMMD": ["VAP_VTX_FMT", "VAP_VF_CNTL"],
|
|
"3D_DRAW_INDX": ["VAP_VTX_FMT", "VAP_VF_CNTL"],
|
|
"3D_LOAD_VBPNTR": ["VAP_VTX_NUM_ARRAYS",
|
|
"VAP_VTX_AOS_ATTR01",
|
|
"VAP_VTX_AOS_ADDR0",
|
|
"VAP_VTX_AOS_ADDR1",
|
|
"VAP_VTX_AOS_ATTR23",
|
|
"VAP_VTX_AOS_ADDR2",
|
|
"VAP_VTX_AOS_ADDR3",
|
|
"VAP_VTX_AOS_ATTR45",
|
|
"VAP_VTX_AOS_ADDR4",
|
|
"VAP_VTX_AOS_ADDR5",
|
|
"VAP_VTX_AOS_ATTR67",
|
|
"VAP_VTX_AOS_ADDR6",
|
|
"VAP_VTX_AOS_ADDR7",
|
|
"VAP_VTX_AOS_ATTR89",
|
|
"VAP_VTX_AOS_ADDR8",
|
|
"VAP_VTX_AOS_ADDR9",
|
|
"VAP_VTX_AOS_ATTR1011",
|
|
"VAP_VTX_AOS_ADDR10",
|
|
"VAP_VTX_AOS_ADDR11",
|
|
"VAP_VTX_AOS_ATTR1213",
|
|
"VAP_VTX_AOS_ADDR12",
|
|
"VAP_VTX_AOS_ADDR13",
|
|
"VAP_VTX_AOS_ATTR1415",
|
|
"VAP_VTX_AOS_ADDR14",
|
|
"VAP_VTX_AOS_ADDR15"],
|
|
"INDX_BUFFER": [(("ONE_REG_WR", (31, 31)), ("SKIP_COUNT", (18, 16)), ("DESTINATION", (12, 0))),
|
|
(("BUFFER_BASE", (31, 0)),),
|
|
(("BUFFER_SIZE", (31, 0)),)],
|
|
"3D_DRAW_VBUF_2": ["VAP_VF_CNTL"],
|
|
"3D_DRAW_IMMD_2": ["VAP_VF_CNTL"],
|
|
"3D_DRAW_INDX_2": ["VAP_VF_CNTL"],
|
|
}
|
|
|
|
print(f"type 3: op:{opcode_name} count:{count:04x}")
|
|
ix = 0
|
|
while count >= 0:
|
|
value = self.consume()
|
|
if opcode_name in registers and ix < len(registers[opcode_name]):
|
|
register_name = registers[opcode_name][ix]
|
|
if type(register_name) is str:
|
|
if "_AOS_ATTR" in register_name:
|
|
decode_print(register_name[:-2], value, paren=True, display_register_name=register_name)
|
|
elif "_AOS_ADDR" in register_name:
|
|
decode_print(register_name[:-1], value, paren=True, display_register_name=register_name)
|
|
else:
|
|
decode_print(register_name, value, paren=True)
|
|
else:
|
|
print(f" ({opcode_name}__{ix})")
|
|
for i, desc in enumerate(register_name):
|
|
eq_bar = '=' if i == 0 else '|'
|
|
d_name, (high, low) = desc
|
|
mask = (1 << ((high - low) + 1)) - 1
|
|
v = (value >> low) & mask
|
|
print(f' {eq_bar} {opcode_name}__{ix}__{d_name}({v})')
|
|
else:
|
|
print(f" {value:08x}")
|
|
count -= 1
|
|
ix += 1
|
|
|
|
def packet(self):
|
|
value = self.peek()
|
|
packet_type = (value >> 30) & 0b11
|
|
if packet_type == 0:
|
|
self.packet_type_0()
|
|
elif packet_type == 1:
|
|
self.packet_type_1()
|
|
elif packet_type == 2:
|
|
self.packet_type_2()
|
|
elif packet_type == 3:
|
|
self.packet_type_3()
|
|
else:
|
|
assert False
|
|
|
|
parser = Parser(values)
|
|
while parser.ix < len(values):
|
|
parser.packet()
|