# megadrive-loader.py # zznop 2019 # # Load ROM as a flat binary, set processor to 68000, # and run the script import idc import idautils import ida_bytes import ida_funcs import ida_segment import ida_name def create_type_and_name(addr, name, _type): '''Create a type and assign a name ''' if _type == 'word': idc.create_word(addr) elif _type == 'dword': idc.create_dword(addr) elif _type == 'qword': idc.create_qword(addr) elif _type == 'byte': idc.create_byte(addr) else: raise KeyError('unknown type: '.format(_type)) ida_name.set_name(addr, name) def create_string_and_name(addr, length, name): '''Create a string literal of size 'length' and name it ''' idc.create_strlit(addr, addr+length) ida_name.set_name(addr, name) def process_rom_vector_table(): '''Annotate vector table and ROM header ''' create_type_and_name(0, 'PtrInitialStack', 'dword') create_type_and_name(4, 'PtrProgramStart', 'dword') create_type_and_name(8, 'VectPtrBusError', 'dword') create_type_and_name(12, 'VectPtrAddressError', 'dword') create_type_and_name(16, 'VectPtrIllegalInstruction', 'dword') create_type_and_name(20, 'VectPtrDivisionByZero', 'dword') create_type_and_name(24, 'VectPtrChkException', 'dword') create_type_and_name(28, 'VectPtrTrapVException', 'dword') create_type_and_name(32, 'VectPtrPrivilegeViolation', 'dword') create_type_and_name(36, 'VectPtrTraceException', 'dword') create_type_and_name(40, 'VectPtrLineAEmulator', 'dword') create_type_and_name(44, 'VectPtrLineFEmulator', 'dword') create_type_and_name(48, 'VectUnused00', 'dword') create_type_and_name(52, 'VectUnused01', 'dword') create_type_and_name(56, 'VectUnused02', 'dword') create_type_and_name(60, 'VectUnused03', 'dword') create_type_and_name(64, 'VectUnused04', 'dword') create_type_and_name(68, 'VectUnused05', 'dword') create_type_and_name(72, 'VectUnused06', 'dword') create_type_and_name(76, 'VectUnused07', 'dword') create_type_and_name(80, 'VectUnused08', 'dword') create_type_and_name(84, 'VectUnused09', 'dword') create_type_and_name(88, 'VectUnused10', 'dword') create_type_and_name(92, 'VectUnused11', 'dword') create_type_and_name(96, 'VectPtrSpuriousException', 'dword') create_type_and_name(100, 'VectPtrIrqL1', 'dword') create_type_and_name(104, 'VectPtrIrqL2', 'dword') create_type_and_name(108, 'VectPtrIrqL3', 'dword') create_type_and_name(112, 'VectPtrIrqL4', 'dword') create_type_and_name(116, 'VectPtrIrqL5', 'dword') create_type_and_name(120, 'VectPtrIrqL6', 'dword') create_type_and_name(124, 'VectPtrIrqL7', 'dword') create_type_and_name(128, 'VectPtrTrap00', 'dword') create_type_and_name(132, 'VectPtrTrap01', 'dword') create_type_and_name(136, 'VectPtrTrap02', 'dword') create_type_and_name(140, 'VectPtrTrap03', 'dword') create_type_and_name(144, 'VectPtrTrap04', 'dword') create_type_and_name(148, 'VectPtrTrap05', 'dword') create_type_and_name(152, 'VectPtrTrap06', 'dword') create_type_and_name(156, 'VectPtrTrap07', 'dword') create_type_and_name(160, 'VectPtrTrap08', 'dword') create_type_and_name(164, 'VectPtrTrap09', 'dword') create_type_and_name(168, 'VectPtrTrap10', 'dword') create_type_and_name(172, 'VectPtrTrap11', 'dword') create_type_and_name(176, 'VectPtrTrap12', 'dword') create_type_and_name(180, 'VectPtrTrap13', 'dword') create_type_and_name(184, 'VectPtrTrap14', 'dword') create_type_and_name(188, 'VectPtrTrap15', 'dword') create_type_and_name(192, 'VectUnused12', 'dword') create_type_and_name(196, 'VectUnused13', 'dword') create_type_and_name(200, 'VectUnused14', 'dword') create_type_and_name(204, 'VectUnused15', 'dword') create_type_and_name(208, 'VectUnused16', 'dword') create_type_and_name(212, 'VectUnused17', 'dword') create_type_and_name(216, 'VectUnused18', 'dword') create_type_and_name(220, 'VectUnused19', 'dword') create_type_and_name(224, 'VectUnused20', 'dword') create_type_and_name(228, 'VectUnused21', 'dword') create_type_and_name(232, 'VectUnused22', 'dword') create_type_and_name(236, 'VectUnused23', 'dword') create_type_and_name(240, 'VectUnused24', 'dword') create_type_and_name(244, 'VectUnused25', 'dword') create_type_and_name(248, 'VectUnused26', 'dword') create_type_and_name(252, 'VectUnused27', 'dword') def process_rom_header(): '''Annotate fields in the ROM header ''' create_string_and_name(256, 16, 'ConsoleName') create_string_and_name(272, 16, 'Copyright') create_string_and_name(288, 48, 'DomesticName') create_string_and_name(336, 48, 'InternationalName') create_string_and_name(384, 14, 'SerialRevision') create_type_and_name(398, 'Checksum', 'word') create_string_and_name(400, 16, 'IoSupport') create_type_and_name(416, 'RomStart', 'dword') create_type_and_name(420, 'RomEnd', 'dword') create_type_and_name(424, 'RamStart', 'dword') create_type_and_name(428, 'RamEnd', 'dword') create_string_and_name(432, 12, 'SramInfo') create_string_and_name(444, 52, 'Notes') create_string_and_name(496, 16, 'Region') def create_functions(): '''Disassemble at program start and exception handlers. And apply names to functions we care about ''' i = 4 while i < 260: addr = ida_bytes.get_32bit(i) ida_funcs.add_func(addr) if i == 4: ida_name.set_name(addr, 'ProgramStart') elif i == 112: ida_name.set_name(addr, 'HBlank') elif i == 120: ida_name.set_name(addr, 'VBlank') i += 4 def create_segments(): '''Create segments ''' rom_start = ida_bytes.get_32bit(416) rom_end = ida_bytes.get_32bit(420) ram_start = ida_bytes.get_32bit(424) ram_end = ida_bytes.get_32bit(428) seg = ida_segment.getseg(rom_start) if seg: ida_segment.set_segm_name(seg, 'ROM') else: ida_segment.add_segm(0, rom_start, rom_end, 'ROM', 'CODE') seg = ida_segment.getseg(ram_start) if seg: ida_segment.set_segm_name(seg, 'RAM') else: ida_segment.add_segm(0, ram_start, ram_end, 'RAM', 'DATA') def main(): create_segments() process_rom_vector_table() process_rom_header() create_functions() if __name__ == '__main__': main()