from binaryninja import * import struct import traceback import os InstructionNames = [ "brk", "ora", None, None, None, "ora", "asl", None, # 0x00 "php", "ora", "asl@", None, None, "ora", "asl", None, # 0x08 "bpl", "ora", None, None, None, "ora", "asl", None, # 0x10 "clc", "ora", None, None, None, "ora", "asl", None, # 0x18 "jsr", "and", None, None, "bit", "and", "rol", None, # 0x20 "plp", "and", "rol@", None, "bit", "and", "rol", None, # 0x28 "bmi", "and", None, None, None, "and", "rol", None, # 0x30 "sec", "and", None, None, None, "and", "rol", None, # 0x38 "rti", "eor", None, None, None, "eor", "lsr", None, # 0x40 "pha", "eor", "lsr@", None, "jmp", "eor", "lsr", None, # 0x48 "bvc", "eor", None, None, None, "eor", "lsr", None, # 0x50 "cli", "eor", None, None, None, "eor", "lsr", None, # 0x58 "rts", "adc", None, None, None, "adc", "ror", None, # 0x60 "pla", "adc", "ror@", None, "jmp", "adc", "ror", None, # 0x68 "bvs", "adc", None, None, None, "adc", "ror", None, # 0x70 "sei", "adc", None, None, None, "adc", "ror", None, # 0x78 None, "sta", None, None, "sty", "sta", "stx", None, # 0x80 "dey", None, "txa", None, "sty", "sta", "stx", None, # 0x88 "bcc", "sta", None, None, "sty", "sta", "stx", None, # 0x90 "tya", "sta", "txs", None, None, "sta", None, None, # 0x98 "ldy", "lda", "ldx", None, "ldy", "lda", "ldx", None, # 0xa0 "tay", "lda", "tax", None, "ldy", "lda", "ldx", None, # 0xa8 "bcs", "lda", None, None, "ldy", "lda", "ldx", None, # 0xb0 "clv", "lda", "tsx", None, "ldy", "lda", "ldx", None, # 0xb8 "cpy", "cmp", None, None, "cpy", "cmp", "dec", None, # 0xc0 "iny", "cmp", "dex", None, "cpy", "cmp", "dec", None, # 0xc8 "bne", "cmp", None, None, None, "cmp", "dec", None, # 0xd0 "cld", "cmp", None, None, None, "cmp", "dec", None, # 0xd8 "cpx", "sbc", None, None, "cpx", "sbc", "inc", None, # 0xe0 "inx", "sbc", "nop", None, "cpx", "sbc", "inc", None, # 0xe8 "beq", "sbc", None, None, None, "sbc", "inc", None, # 0xf0 "sed", "sbc", None, None, None, "sbc", "inc", None # 0xf8 ] NONE = 0 ABS = 1 ABS_DEST = 2 ABS_X = 3 ABS_X_DEST = 4 ABS_Y = 5 ABS_Y_DEST = 6 ACCUM = 7 ADDR = 8 IMMED = 9 IND = 10 IND_X = 11 IND_X_DEST = 12 IND_Y = 13 IND_Y_DEST = 14 REL = 15 ZERO = 16 ZERO_DEST = 17 ZERO_X = 18 ZERO_X_DEST = 19 ZERO_Y = 20 ZERO_Y_DEST = 21 InstructionOperandTypes = [ NONE, IND_X, NONE, NONE, NONE, ZERO, ZERO_DEST, NONE, # 0x00 NONE, IMMED, ACCUM, NONE, NONE, ABS, ABS_DEST, NONE, # 0x08 REL, IND_Y, NONE, NONE, NONE, ZERO_X, ZERO_X_DEST, NONE, # 0x10 NONE, ABS_Y, NONE, NONE, NONE, ABS_X, ABS_X_DEST, NONE, # 0x18 ADDR, IND_X, NONE, NONE, ZERO, ZERO, ZERO_DEST, NONE, # 0x20 NONE, IMMED, ACCUM, NONE, ABS, ABS, ABS_DEST, NONE, # 0x28 REL, IND_Y, NONE, NONE, NONE, ZERO_X, ZERO_X_DEST, NONE, # 0x30 NONE, ABS_Y, NONE, NONE, NONE, ABS_X, ABS_X_DEST, NONE, # 0x38 NONE, IND_X, NONE, NONE, NONE, ZERO, ZERO_DEST, NONE, # 0x40 NONE, IMMED, ACCUM, NONE, ADDR, ABS, ABS_DEST, NONE, # 0x48 REL, IND_Y, NONE, NONE, NONE, ZERO_X, ZERO_X_DEST, NONE, # 0x50 NONE, ABS_Y, NONE, NONE, NONE, ABS_X, ABS_X_DEST, NONE, # 0x58 NONE, IND_X, NONE, NONE, NONE, ZERO, ZERO_DEST, NONE, # 0x60 NONE, IMMED, ACCUM, NONE, IND, ABS, ABS_DEST, NONE, # 0x68 REL, IND_Y, NONE, NONE, NONE, ZERO_X, ZERO_X_DEST, NONE, # 0x70 NONE, ABS_Y, NONE, NONE, NONE, ABS_X, ABS_X_DEST, NONE, # 0x78 NONE, IND_X_DEST, NONE, NONE, ZERO_DEST, ZERO_DEST, ZERO_DEST, NONE, # 0x80 NONE, NONE, NONE, NONE, ABS_DEST, ABS_DEST, ABS_DEST, NONE, # 0x88 REL, IND_Y_DEST, NONE, NONE, ZERO_X_DEST, ZERO_X_DEST, ZERO_Y_DEST, NONE, # 0x90 NONE, ABS_Y_DEST, NONE, NONE, NONE, ABS_X_DEST, NONE, NONE, # 0x98 IMMED, IND_X, IMMED, NONE, ZERO, ZERO, ZERO, NONE, # 0xa0 NONE, IMMED, NONE, NONE, ABS, ABS, ABS, NONE, # 0xa8 REL, IND_Y, NONE, NONE, ZERO_X, ZERO_X, ZERO_Y, NONE, # 0xb0 NONE, ABS_Y, NONE, NONE, ABS_X, ABS_X, ABS_Y, NONE, # 0xb8 IMMED, IND_X, NONE, NONE, ZERO, ZERO, ZERO_DEST, NONE, # 0xc0 NONE, IMMED, NONE, NONE, ABS, ABS, ABS_DEST, NONE, # 0xc8 REL, IND_Y, NONE, NONE, NONE, ZERO_X, ZERO_X_DEST, NONE, # 0xd0 NONE, ABS_Y, NONE, NONE, NONE, ABS_X, ABS_X_DEST, NONE, # 0xd8 IMMED, IND_X, NONE, NONE, ZERO, ZERO, ZERO_DEST, NONE, # 0xe0 NONE, IMMED, NONE, NONE, ABS, ABS, ABS_DEST, NONE, # 0xe8 REL, IND_Y, NONE, NONE, NONE, ZERO_X, ZERO_X_DEST, NONE, # 0xf0 NONE, ABS_Y, NONE, NONE, NONE, ABS_X, ABS_X_DEST, NONE # 0xf8 ] OperandLengths = [ 0, # NONE 2, # ABS 2, # ABS_DEST 2, # ABS_X 2, # ABS_X_DEST 2, # ABS_Y 2, # ABS_Y_DEST 0, # ACCUM 2, # ADDR 1, # IMMED 2, # IND 1, # IND_X 1, # IND_X_DEST 1, # IND_Y 1, # IND_Y_DEST 1, # REL 1, # ZERO 1, # ZREO_DEST 1, # ZERO_X 1, # ZERO_X_DEST 1, # ZERO_Y 1 # ZERO_Y_DEST ] OperandTokens = [ lambda value: [], # NONE lambda value: [InstructionTextToken(PossibleAddressToken, "$%.4x" % value, value)], # ABS lambda value: [InstructionTextToken(PossibleAddressToken, "$%.4x" % value, value)], # ABS_DEST lambda value: [InstructionTextToken(PossibleAddressToken, "$%.4x" % value, value), InstructionTextToken(TextToken, ", "), InstructionTextToken(RegisterToken, "x")], # ABS_X lambda value: [InstructionTextToken(PossibleAddressToken, "$%.4x" % value, value), InstructionTextToken(TextToken, ", "), InstructionTextToken(RegisterToken, "x")], # ABS_X_DEST lambda value: [InstructionTextToken(PossibleAddressToken, "$%.4x" % value, value), InstructionTextToken(TextToken, ", "), InstructionTextToken(RegisterToken, "y")], # ABS_Y lambda value: [InstructionTextToken(PossibleAddressToken, "$%.4x" % value, value), InstructionTextToken(TextToken, ", "), InstructionTextToken(RegisterToken, "y")], # ABS_Y_DEST lambda value: [InstructionTextToken(RegisterToken, "a")], # ACCUM lambda value: [InstructionTextToken(PossibleAddressToken, "$%.4x" % value, value)], # ADDR lambda value: [InstructionTextToken(TextToken, "#"), InstructionTextToken(IntegerToken, "$%.2x" % value, value)], # IMMED lambda value: [InstructionTextToken(TextToken, "["), InstructionTextToken(PossibleAddressToken, "$%.4x" % value, value), InstructionTextToken(TextToken, "]")], # IND lambda value: [InstructionTextToken(TextToken, "["), InstructionTextToken(PossibleAddressToken, "$%.2x" % value, value), InstructionTextToken(TextToken, ", "), InstructionTextToken(RegisterToken, "x"), InstructionTextToken(TextToken, "]")], # IND_X lambda value: [InstructionTextToken(TextToken, "["), InstructionTextToken(PossibleAddressToken, "$%.2x" % value, value), InstructionTextToken(TextToken, ", "), InstructionTextToken(RegisterToken, "x"), InstructionTextToken(TextToken, "]")], # IND_X_DEST lambda value: [InstructionTextToken(TextToken, "["), InstructionTextToken(PossibleAddressToken, "$%.2x" % value, value), InstructionTextToken(TextToken, "], "), InstructionTextToken(RegisterToken, "y")], # IND_Y lambda value: [InstructionTextToken(TextToken, "["), InstructionTextToken(PossibleAddressToken, "$%.2x" % value, value), InstructionTextToken(TextToken, "], "), InstructionTextToken(RegisterToken, "y")], # IND_Y_DEST lambda value: [InstructionTextToken(PossibleAddressToken, "$%.4x" % value, value)], # REL lambda value: [InstructionTextToken(PossibleAddressToken, "$%.2x" % value, value)], # ZERO lambda value: [InstructionTextToken(PossibleAddressToken, "$%.2x" % value, value)], # ZERO_DEST lambda value: [InstructionTextToken(PossibleAddressToken, "$%.2x" % value, value), InstructionTextToken(TextToken, ", "), InstructionTextToken(RegisterToken, "x")], # ZERO_X lambda value: [InstructionTextToken(PossibleAddressToken, "$%.2x" % value, value), InstructionTextToken(TextToken, ", "), InstructionTextToken(RegisterToken, "x")], # ZERO_X_DEST lambda value: [InstructionTextToken(PossibleAddressToken, "$%.2x" % value, value), InstructionTextToken(TextToken, ", "), InstructionTextToken(RegisterToken, "y")], # ZERO_Y lambda value: [InstructionTextToken(PossibleAddressToken, "$%.2x" % value, value), InstructionTextToken(TextToken, ", "), InstructionTextToken(RegisterToken, "y")] # ZERO_Y_DEST ] def indirect_load(il, value): if (value & 0xff) == 0xff: lo_addr = il.const(2, value) hi_addr = il.const(2, (value & 0xff00) | ((value + 1) & 0xff)) lo = il.zero_extend(2, il.load(1, lo_addr)) hi = il.shift_left(2, il.zero_extend(2, il.load(1, hi_addr)), il.const(2, 8)) return il.or_expr(2, lo, hi) return il.load(2, il.const(2, value)) def load_zero_page_16(il, value): if il[value].operation == "LLIL_CONST": if il[value].value == 0xff: lo = il.zero_extend(2, il.load(1, il.const(2, 0xff))) hi = il.shift_left(2, il.zero_extend(2, il.load(1, il.const(2, 0)), il.const(2, 8))) return il.or_expr(2, lo, hi) return il.load(2, il.const(2, il[value].value)) il.append(il.set_reg(1, LLIL_TEMP(0), value)) value = il.reg(1, LLIL_TEMP(0)) lo_addr = value hi_addr = il.add(1, value, il.const(1, 1)) lo = il.zero_extend(2, il.load(1, lo_addr)) hi = il.shift_left(2, il.zero_extend(2, il.load(1, hi_addr)), il.const(2, 8)) return il.or_expr(2, lo, hi) OperandIL = [ lambda il, value: None, # NONE lambda il, value: il.load(1, il.const(2, value)), # ABS lambda il, value: il.const(2, value), # ABS_DEST lambda il, value: il.load(1, il.add(2, il.const(2, value), il.zero_extend(2, il.reg(1, "x")))), # ABS_X lambda il, value: il.add(2, il.const(2, value), il.zero_extend(2, il.reg(1, "x"))), # ABS_X_DEST lambda il, value: il.load(1, il.add(2, il.const(2, value), il.zero_extend(2, il.reg(1, "y")))), # ABS_Y lambda il, value: il.add(2, il.const(2, value), il.zero_extend(2, il.reg(1, "y"))), # ABS_Y_DEST lambda il, value: il.reg(1, "a"), # ACCUM lambda il, value: il.const(2, value), # ADDR lambda il, value: il.const(1, value), # IMMED lambda il, value: indirect_load(il, value), # IND lambda il, value: il.load(1, load_zero_page_16(il, il.add(1, il.const(1, value), il.reg(1, "x")))), # IND_X lambda il, value: load_zero_page_16(il, il.add(1, il.const(1, value), il.reg(1, "x"))), # IND_X_DEST lambda il, value: il.load(1, il.add(2, load_zero_page_16(il, il.const(1, value)), il.reg(1, "y"))), # IND_Y lambda il, value: il.add(2, load_zero_page_16(il, il.const(1, value)), il.reg(1, "y")), # IND_Y_DEST lambda il, value: il.const(2, value), # REL lambda il, value: il.load(1, il.const(2, value)), # ZERO lambda il, value: il.const(2, value), # ZERO_DEST lambda il, value: il.load(1, il.zero_extend(2, il.add(1, il.const(1, value), il.reg(1, "x")))), # ZERO_X lambda il, value: il.zero_extend(2, il.add(1, il.const(1, value), il.reg(1, "x"))), # ZERO_X_DEST lambda il, value: il.load(1, il.zero_extend(2, il.add(1, il.const(1, value), il.reg(1, "y")))), # ZERO_Y lambda il, value: il.zero_extend(2, il.add(1, il.const(1, value), il.reg(1, "y"))) # ZERO_Y_DEST ] def cond_branch(il, cond, dest): t = None if il[dest].operation == "LLIL_CONST": t = il.get_label_for_address(Architecture['6502'].standalone_platform, il[dest].value) if t is None: t = LowLevelILLabel() indirect = True else: indirect = False f = LowLevelILLabel() il.append(il.if_expr(cond, t, f)) if indirect: il.mark_label(t) il.append(il.jump(dest)) il.mark_label(f) return None def jump(il, dest): label = None if il[dest].operation == "LLIL_CONST": label = il.get_label_for_address(Architecture['6502'].standalone_platform, il[dest].value) if label is None: il.append(il.jump(dest)) else: il.append(il.goto(label)) return None def get_p_value(il): c = il.flag_bit(1, "c", 0) z = il.flag_bit(1, "z", 1) i = il.flag_bit(1, "i", 2) d = il.flag_bit(1, "d", 3) b = il.flag_bit(1, "b", 4) v = il.flag_bit(1, "v", 6) s = il.flag_bit(1, "s", 7) return il.or_expr(1, il.or_expr(1, il.or_expr(1, il.or_expr(1, il.or_expr(1, il.or_expr(1, c, z), i), d), b), v), s) def set_p_value(il, value): il.append(il.set_reg(1, LLIL_TEMP(0), value)) il.append(il.set_flag("c", il.test_bit(1, il.reg(1, LLIL_TEMP(0)), il.const(1, 0x01)))) il.append(il.set_flag("z", il.test_bit(1, il.reg(1, LLIL_TEMP(0)), il.const(1, 0x02)))) il.append(il.set_flag("i", il.test_bit(1, il.reg(1, LLIL_TEMP(0)), il.const(1, 0x04)))) il.append(il.set_flag("d", il.test_bit(1, il.reg(1, LLIL_TEMP(0)), il.const(1, 0x08)))) il.append(il.set_flag("b", il.test_bit(1, il.reg(1, LLIL_TEMP(0)), il.const(1, 0x10)))) il.append(il.set_flag("v", il.test_bit(1, il.reg(1, LLIL_TEMP(0)), il.const(1, 0x40)))) il.append(il.set_flag("s", il.test_bit(1, il.reg(1, LLIL_TEMP(0)), il.const(1, 0x80)))) return None def rti(il): set_p_value(il, il.pop(1)) return il.ret(il.pop(2)) InstructionIL = { "adc": lambda il, operand: il.set_reg(1, "a", il.add_carry(1, il.reg(1, "a"), operand, flags = "*")), "asl": lambda il, operand: il.store(1, operand, il.shift_left(1, il.load(1, operand), il.const(1, 1), flags = "czs")), "asl@": lambda il, operand: il.set_reg(1, "a", il.shift_left(1, operand, il.const(1, 1), flags = "czs")), "and": lambda il, operand: il.set_reg(1, "a", il.and_expr(1, il.reg(1, "a"), operand, flags = "zs")), "bcc": lambda il, operand: cond_branch(il, il.flag_condition(LLFC_UGE), operand), "bcs": lambda il, operand: cond_branch(il, il.flag_condition(LLFC_ULT), operand), "beq": lambda il, operand: cond_branch(il, il.flag_condition(LLFC_E), operand), "bit": lambda il, operand: il.and_expr(1, il.reg(1, "a"), operand, flags = "czs"), "bmi": lambda il, operand: cond_branch(il, il.flag("s"), operand), "bne": lambda il, operand: cond_branch(il, il.flag_condition(LLFC_NE), operand), "bpl": lambda il, operand: cond_branch(il, il.not_expr(0, il.flag("s")), operand), "brk": lambda il, operand: il.system_call(), "bvc": lambda il, operand: cond_branch(il, il.not_expr(0, il.flag("v")), operand), "bvs": lambda il, operand: cond_branch(il, il.flag("v"), operand), "clc": lambda il, operand: il.set_flag("c", il.const(0, 0)), "cld": lambda il, operand: il.set_flag("d", il.const(0, 0)), "cli": lambda il, operand: il.set_flag("i", il.const(0, 0)), "clv": lambda il, operand: il.set_flag("v", il.const(0, 0)), "cmp": lambda il, operand: il.sub(1, il.reg(1, "a"), operand, flags = "czs"), "cpx": lambda il, operand: il.sub(1, il.reg(1, "x"), operand, flags = "czs"), "cpy": lambda il, operand: il.sub(1, il.reg(1, "y"), operand, flags = "czs"), "dec": lambda il, operand: il.store(1, operand, il.sub(1, il.load(1, operand), il.const(1, 1), flags = "zs")), "dex": lambda il, operand: il.set_reg(1, "x", il.sub(1, il.reg(1, "x"), il.const(1, 1), flags = "zs")), "dey": lambda il, operand: il.set_reg(1, "y", il.sub(1, il.reg(1, "y"), il.const(1, 1), flags = "zs")), "eor": lambda il, operand: il.set_reg(1, "a", il.xor_expr(1, il.reg(1, "a"), operand, flags = "zs")), "inc": lambda il, operand: il.store(1, operand, il.add(1, il.load(1, operand), il.const(1, 1), flags = "zs")), "inx": lambda il, operand: il.set_reg(1, "x", il.add(1, il.reg(1, "x"), il.const(1, 1), flags = "zs")), "iny": lambda il, operand: il.set_reg(1, "y", il.add(1, il.reg(1, "y"), il.const(1, 1), flags = "zs")), "jmp": lambda il, operand: jump(il, operand), "jsr": lambda il, operand: il.call(operand), "lda": lambda il, operand: il.set_reg(1, "a", operand, flags = "zs"), "ldx": lambda il, operand: il.set_reg(1, "x", operand, flags = "zs"), "ldy": lambda il, operand: il.set_reg(1, "y", operand, flags = "zs"), "lsr": lambda il, operand: il.store(1, operand, il.logical_shift_right(1, il.load(1, operand), il.const(1, 1), flags = "czs")), "lsr@": lambda il, operand: il.set_reg(1, "a", il.logical_shift_right(1, il.reg(1, "a"), il.const(1, 1), flags = "czs")), "nop": lambda il, operand: il.nop(), "ora": lambda il, operand: il.set_reg(1, "a", il.or_expr(1, il.reg(1, "a"), operand, flags = "zs")), "pha": lambda il, operand: il.push(1, il.reg(1, "a")), "php": lambda il, operand: il.push(1, get_p_value(il)), "pla": lambda il, operand: il.set_reg(1, "a", il.pop(1), flags = "zs"), "plp": lambda il, operand: set_p_value(il, il.pop(1)), "rol": lambda il, operand: il.store(1, operand, il.rotate_left_carry(1, il.load(1, operand), il.const(1, 1), flags = "czs")), "rol@": lambda il, operand: il.set_reg(1, "a", il.rotate_left_carry(1, il.reg(1, "a"), il.const(1, 1), flags = "czs")), "ror": lambda il, operand: il.store(1, operand, il.rotate_right_carry(1, il.load(1, operand), il.const(1, 1), flags = "czs")), "ror@": lambda il, operand: il.set_reg(1, "a", il.rotate_right_carry(1, il.reg(1, "a"), il.const(1, 1), flags = "czs")), "rti": lambda il, operand: rti(il), "rts": lambda il, operand: il.ret(il.add(2, il.pop(2), il.const(2, 1))), "sbc": lambda il, operand: il.set_reg(1, "a", il.sub_borrow(1, il.reg(1, "a"), operand, flags = "*")), "sec": lambda il, operand: il.set_flag("c", il.const(0, 1)), "sed": lambda il, operand: il.set_flag("d", il.const(0, 1)), "sei": lambda il, operand: il.set_flag("i", il.const(0, 1)), "sta": lambda il, operand: il.store(1, operand, il.reg(1, "a")), "stx": lambda il, operand: il.store(1, operand, il.reg(1, "x")), "sty": lambda il, operand: il.store(1, operand, il.reg(1, "y")), "tax": lambda il, operand: il.set_reg(1, "x", il.reg(1, "a"), flags = "zs"), "tay": lambda il, operand: il.set_reg(1, "y", il.reg(1, "a"), flags = "zs"), "tsx": lambda il, operand: il.set_reg(1, "x", il.reg(1, "s"), flags = "zs"), "txa": lambda il, operand: il.set_reg(1, "a", il.reg(1, "x"), flags = "zs"), "txs": lambda il, operand: il.set_reg(1, "s", il.reg(1, "x")), "tya": lambda il, operand: il.set_reg(1, "a", il.reg(1, "y"), flags = "zs") } class M6502(Architecture): name = "6502" address_size = 2 default_int_size = 1 regs = { "a": RegisterInfo("a", 1), "x": RegisterInfo("x", 1), "y": RegisterInfo("y", 1), "s": RegisterInfo("s", 1) } stack_pointer = "s" flags = ["c", "z", "i", "d", "b", "v", "s"] flag_write_types = ["*", "czs", "zvs", "zs"] def decode_instruction(self, data, addr): if len(data) < 1: return None, None, None, None opcode = ord(data[0]) instr = InstructionNames[opcode] if instr is None: return None, None, None, None operand = InstructionOperandTypes[opcode] length = 1 + OperandLengths[operand] if len(data) < length: return None, None, None, None if OperandLengths[operand] == 0: value = None elif operand == REL: value = (addr + 2 + struct.unpack("b", data[1])[0]) & 0xffff elif OperandLengths[operand] == 1: value = ord(data[1]) else: value = struct.unpack(" 0: bank_ofs = addr & 0x3fff if (bank_ofs + length) > 0x4000: to_read = 0x4000 - bank_ofs else: to_read = length if length < to_read: to_read = length if (addr >= (bank_ofs + (self.view.__class__.bank * 0x4000))) and (addr < (bank_ofs + ((self.view.__class__.bank + 1) * 0x4000))): self.view.notify_data_written(0x8000 + bank_ofs, to_read) elif (addr >= (bank_ofs + (self.view.rom_length - 0x4000))) and (addr < (bank_ofs + self.view.rom_length)): self.view.notify_data_written(0xc000 + bank_ofs, to_read) length -= to_read addr += to_read def data_inserted(self, view, offset, length): self.view.notify_data_written(0x8000, 0x8000) def data_removed(self, view, offset, length): self.view.notify_data_written(0x8000, 0x8000) class NESView(BinaryView): name = "NES" long_name = "NES ROM" def __init__(self, data): BinaryView.__init__(self, data.file) self.data = data self.notification = NESViewUpdateNotification(self) self.data.register_notification(self.notification) @classmethod def is_valid_for_data(self, data): hdr = data.read(0, 16) if len(hdr) < 16: return False if hdr[0:4] != "NES\x1a": return False rom_banks = struct.unpack("B", hdr[4])[0] if rom_banks < (self.bank + 1): return False return True def init(self): try: hdr = self.data.read(0, 16) self.rom_banks = struct.unpack("B", hdr[4])[0] self.vrom_banks = struct.unpack("B", hdr[5])[0] self.rom_flags = struct.unpack("B", hdr[6])[0] self.mapper_index = struct.unpack("B", hdr[7])[0] | (self.rom_flags >> 4) self.ram_banks = struct.unpack("B", hdr[8])[0] self.rom_offset = 16 if self.rom_flags & 4: self.rom_offset += 512 self.rom_length = self.rom_banks * 0x4000 nmi = struct.unpack("= 0x8000: self.add_function(Architecture['6502'].standalone_platform, addr) return True except: log_error(traceback.format_exc()) return False def perform_is_valid_offset(self, addr): if (addr >= 0x8000) and (addr < 0x10000): return True return False def perform_read(self, addr, length): if addr < 0x8000: return None if addr >= (0x8000 + self.rom_length): return None if (addr + length) > 0x10000: length = 0x10000 - addr result = "" while length > 0: bank_ofs = addr & 0x3fff if (bank_ofs + length) > 0x4000: to_read = 0x4000 - bank_ofs else: to_read = length if addr < 0xc000: data = self.data.read(self.rom_offset + bank_ofs + (self.__class__.bank * 0x4000), to_read) else: data = self.data.read(self.rom_offset + bank_ofs + self.rom_length - 0x4000, to_read) result += data if len(data) < to_read: break length -= to_read addr += to_read return result def perform_write(self, addr, value): if addr < 0x8000: return 0 if addr >= (0x8000 + self.rom_length): return 0 if (addr + len(value)) > (0x8000 + self.rom_length): length = (0x8000 + self.rom_length) - addr else: length = len(value) if (addr + length) > 0x10000: length = 0x10000 - addr offset = 0 while length > 0: bank_ofs = addr & 0x3fff if (bank_ofs + length) > 0x4000: to_write = 0x4000 - bank_ofs else: to_write = length if addr < 0xc000: written = self.data.write(self.rom_offset + bank_ofs + (self.__class__.bank * 0x4000), value[offset : offset + to_write]) else: written = self.data.write(self.rom_offset + bank_ofs + self.rom_length - 0x4000, value[offset : offset + to_write]) if written < to_write: break length -= to_write addr += to_write offset += to_write return offset def perform_get_start(self): return 0 def perform_get_length(self): return 0x10000 def perform_is_executable(self): return True def perform_get_entry_point(self): return struct.unpack("