import sys import struct from opcodes import opcodes, i_to_str import types with open(sys.argv[1], 'rb') as f: buf = f.read() rom = memoryview(buf) def u8(offset): global rom value, = struct.unpack("> 0) & 0b111 src = (attr >> 3) & 0b111 arg_size = dest_arg_size(dest_type) src_size = dest_src_size(arg, src) arg_value = uN(offset + 1, arg_size) src_value = uN(offset + 1 + arg_size, src_size) print_size(arg_value, arg_size) print(" <- ", end='') print_size(src_value, src_size) return 1 + arg_size + src_size def opcode_type_1x16(offset, dest_type): arg = u16(offset) print_size(arg, 2) return 2 def opcode_type_setregblock(offset, dest_type): arg = u16(offset) print_size(arg, 2) return 2 def opcode_type_dest(offset, dest_type): attr = u8(offset) src = (attr >> 3) & 0b111 src_size = dest_src_size(dest_type, src) src_arg = uN(offset + 1, src_size) print_size(src_arg, src_size) return 1 + src_size def opcode_type_shift(offset, dest_type): attr = u8(offset) src = (attr >> 3) & 0b111 src_size = dest_src_size(dest_type, src) src_arg = uN(offset + 1, src_size) print_size(src_arg, src_size) shift_arg = u8(offset + 1 + src_size) print(" by ", end='') print_size(shift_arg, 1) return 1 + src_size + 1 def opcode_0(offset, dest_type): return 0 argument_handlers = { "setport": opcode_type_setport, "dest_src": opcode_type_dest_src, "1x16": opcode_type_1x16, "setregblock": opcode_type_1x16, "shift": opcode_type_shift, "dest": opcode_type_dest, "0": opcode_0, } def disassemble(start, length): offset = start offset_end = start + length - 6 while offset < offset_end: opcode = u8(offset) arg_type, name, dest_type = opcodes[opcode] pc = (offset - start) + 6 offset += 1 handler = argument_handlers[arg_type] print(f"{pc:04x} opcode {opcode:02x} {name.rjust(12)} {i_to_str(dest_type).ljust(8)} ", end='') length = handler(offset, dest_type) offset += length print() def parse_table(names, table): structure_size = u16(table + 0) format_revision = u8(table + 2) content_revision = u8(table + 3) print("structure size", structure_size) print("format revision", format_revision) print("content revision", content_revision) table_entries = (structure_size - 4) // 2 for i in range(table_entries): offset = u16(table + 4 + i * 2) if offset == 0: print(f"{i:02x} offset {offset:04x} : ({names[i]})") continue length = u16(offset + 0) format_rev = u8(offset + 2) content_rev = u8(offset + 3) print(f"{i:02x} offset {offset:04x} length {length:04x} format {format_rev:02x} content {content_rev:02x} : ({names[i]})") if i == 0x22: disassemble(offset + 6, length) break def parse_header(): bios_magic = u16(0) assert bios_magic == ATOM_BIOS_MAGIC, bios_magic ati_magic = rstr(ATOM_ATI_MAGIC_OFFSET, len(ATOM_ATI_MAGIC)) assert ati_magic == ATOM_ATI_MAGIC, ati_magic base = u16(ATOM_ROM_TABLE_OFFSET) rom_magic = rstr(base + ATOM_ROM_MAGIC_OFFSET, len(ATOM_ROM_MAGIC)) assert rom_magic == ATOM_ROM_MAGIC, rom_magic print("structure size", u16(0)) cmd_table = u16(base + ATOM_ROM_CMD_OFFSET) data_table = u16(base + ATOM_ROM_DATA_OFFSET) str = rom[u16(base + ATOM_ROM_MSG_OFFSET):] while str[0] == ord(b'\n') or str[0] == ord(b'\r'): str = str[1:] message = [] for i in range(511): if str[i] == 0: break message.append(str[i]) message = bytes(message).strip() print(message) print("command table:") parse_table(_command_table_names, cmd_table) print("\n\n") #print("data table:") #parse_table(data_table) parse_header()