def dcp(self): v = u8(self._data - 1) self._bus.write(self._addr, v) tmp = u8(self._a.value - v) self._flag.z = (tmp == 0) self._flag.n = (tmp >> 7 & 1) == 1 self._flag.c = ((self._a.value - v) & 0xff00) == 0 return False
def asl(self): val = u8(self._data << 1) if self._addr == -1: self._a.value = u8(self._data << 1) else: self._bus.write(self._addr, val) self._flag.c = (self._data >> 7 & 1) == 1 self._flag.n = (val >> 7 & 1) == 1 self._flag.z = (val == 0) return False
def sbc(self): c = self._flag.c res = self._a.value - self._data - (0 if c else 1) self._flag.n = (u8(res) >> 7 & 1) == 1 self._flag.z = u8(res) == 0 self._flag.c = (res & 0xff00) == 0 ah = self._a.value >> 7 & 1 mh = self._data >> 7 & 1 rh = u8(res) >> 7 & 1 self._flag.v = (ah == 1 and mh == 0 and rh == 0) or (ah == 0 and mh == 1 and rh == 1) self._a.value = u8(res) return False
def adc(self): c = self._flag.c res = self._a.value + self._data + (1 if c else 0) self._flag.n = (u8(res) >> 7 & 1) == 1 self._flag.z = (u8(res) == 0) self._flag.c = (res & 0xff00) != 0 ah = (self._a.value >> 7) & 1 dh = (self._data >> 7) & 1 rh = (u8(res) >> 7 & 1) self._flag.v = (ah == 0 and dh == 0 and rh == 1) or (ah == 1 and dh == 1 and rh == 0) self._a.value = u8(res) return False
def isc(self): v = u8(self._data + 1) tmp = self._a.value - v - (0 if self._flag.c else 1) self._bus.write(self._addr, v) self._flag.z = (self._a.value == 0) self._flag.n = (self._a.value >> 7 & 1) == 1 self._flag.c = (tmp & 0xff00) == 0 ah = (self._a.value >> 7 & 1) mh = (v >> 7 & 1) rh = (u8(tmp) >> 7 & 1) self._flag.v = (ah == 0 and mh == 1 and rh == 1) or (ah == 1 and mh == 0 and rh == 0) self._a.value = u8(tmp) return False
def slo(self): v = u8(self._data * 2) self._bus.write(self._addr, v) self._a.value |= v self._flag.c = (self._data >> 7 & 1) == 1 self._flag.z = (self._a.value == 0) self._flag.n = (self._a.value >> 7 & 1) == 1 return False
def rra(self): # ROR new_carry = (self._data & 1) == 1 val = self._data >> 1 if self._flag.c: val |= (1 << 7) self._bus.write(self._addr, val) # ADC c = new_carry res = self._a.value + val + (1 if c else 0) self._flag.n = (u8(res) >> 7 & 1) == 1 self._flag.z = (u8(res) == 0) self._flag.c = (res & 0xff00) != 0 ah = (self._a.value >> 7) & 1 dh = (val >> 7) & 1 rh = (u8(res) >> 7 & 1) self._flag.v = (ah == 0 and dh == 0 and rh == 1) or (ah == 1 and dh == 1 and rh == 0) self._a.value = u8(res) return True
def make_filename(hdr, filetype): magic, version, flags, moffs, metaoffs = struct.unpack("<IIIIQ", hdr[0:24]) if magic == 0x454353 and version == 3 and flags == 0x30040: meta = hdr[metaoffs:] t = u8(meta, 4) if t < 0x1C: name = "{}-{:02}.pkg".format(FSTYPE[t], g_typecount[t]) g_typecount[t] += 1 return name return "unknown-0x{:x}.pkg".format(filetype)
def __init__(self): self.v = u8() bit_map = { 'sprite_overflow': 5, 'sprite_0_hit': 6, 'vblank_in': 7 } for k, v in bit_map.iteritems(): self.__dict__['get_' + k] = functools.partial(_getter, idx=v) self.__dict__['set_' + k] = functools.partial(_setter, idx=v)
def rla(self): # ROL new_carry = (self._data >> 7 & 1) == 1 val = u8(self._data << 1) if self._flag.c: val |= 1 self._bus.write(self._addr, val) self._flag.c = new_carry # AND self._a.value &= val self._flag.z = (self._a.value == 0) self._flag.n = (self._a.value >> 7 & 1) == 1 return False
def rol(self): new_carry = (self._data >> 7 & 1) == 1 val = u8(self._data << 1) if self._flag.c: val |= 1 if self._addr == -1: self._a.value = val else: self._bus.write(self._addr, val) self._flag.c = new_carry self._flag.z = (val == 0) self._flag.n = (val >> 7 & 1) == 1 return False
def __init__(self): self.v = u8() bit_map = { 'gray_scale': 0, 'show_background_left': 1, 'show_sprites_left': 2, 'show_background': 3, 'show_sprites': 4, 'emphasize_red': 5, 'emphasize_green': 6, 'emphasize_blue': 7 } for k, v in bit_map.iteritems(): self.__dict__['get_' + k] = functools.partial(_getter, idx=v) self.__dict__['set_' + k] = functools.partial(_setter, idx=v)
def __init__(self): self.v = u8() bit_map = { # 0: add 1, going across; 1: add 32,going down. 'vram_increment': 2, # pt = pattern table # 0 : 0x1000; 1: 0x1000. ignored in 8*16 mode 'sprite_pt_address': 3, # 0 : 0x000; 1: 0x1000. 'background_pt_address': 4, # 0 : 8*8; 1 : 8*16. 'sprite_size': 5, # 0 : read backdrop from ext pins; 1 : output color on ext pins. 'master_slave': 6, # 0 : off; 1 : on. generate an NMI at the start of the vertical blanking interval. 'nmi_vblank': 7 } for k, v in bit_map.iteritems(): self.__dict__['get_' + k] = functools.partial(_getter, idx=v) self.__dict__['set_' + k] = functools.partial(_setter, idx=v)
def pre_fill(self, read_data=True): opcode = self._bus.read(self._pc.value) ins = self._ins[opcode] mode = ins.addr_mode() cross_boundry = False if mode == AddrMode.Implied: self._addr = -1 self._data = -1 elif mode == AddrMode.Absolute: lo = self.fetch(1) hi = self.fetch(2) self._addr = u16((hi << 8) + lo) if read_data: self._data = self._bus.read(self._addr) elif mode == AddrMode.Accumulator: self._addr = -1 self._data = self._a.value elif mode == AddrMode.Immediate: self._addr = -1 self._data = self.fetch(1) elif mode == AddrMode.ZeroPage: self._addr = self.fetch(1) if read_data: self._data = self._bus.read(self._addr) elif mode == AddrMode.Relative: self._addr = -1 self._data = self.fetch(1) prev_ = self._next_addr next_ = self._next_addr + s8(self._data) if (prev_ & 0xff00) != (next_ & 0xff00): cross_boundry = True elif mode == AddrMode.IndexedIndirectY: addr = self.fetch(1) lo = self._bus.read(addr) hi = self._bus.read((addr + 1) % 256) self._addr = u16((hi << 8) + lo + self._y.value) if read_data: self._data = self._bus.read(self._addr) cross_boundry = (lo + self._y.value) > 0xff elif mode == AddrMode.ZeroIndexedIndirectX: index = u8(self.fetch(1) + self._x.value) self._addr = u16(self._bus.read(index) + ((self._bus.read((index + 1) & 0xff)) << 8)) if read_data: self._data = self._bus.read(self._addr) elif mode == AddrMode.AbslouteIndirect: addr = self.fetch(1) + (self.fetch(2) << 8) if (addr & 0xff) == 0xff: self._addr = self._bus.read(addr) + (self._bus.read(addr & 0xff00) << 8) else: self._addr = self._bus.read(addr) + (self._bus.read(addr + 1) << 8) self._data = -1 elif mode == AddrMode.AbslouteIndexedY: self._addr = u16(self._y.value + self.fetch(1) + (self.fetch(2) << 8)) if read_data: self._data = self._bus.read(self._addr) cross_boundry = (self._y.value + self.fetch(1) > 0xff) elif mode == AddrMode.ZeroIndexedX: self._addr = u8(self._x.value + self.fetch(1)) if read_data: self._data = self._bus.read(self._addr) elif mode == AddrMode.ZeroIndexedY: self._addr = u8(self._y.value + self.fetch(1)) if read_data: self._data = self._bus.read(self._addr) elif mode == AddrMode.AbslouteIndexedX: self._addr = u16(self._x.value + self.fetch(1) + (self.fetch(2) << 8)) if read_data: self._data = self._bus.read(self._addr) cross_boundry = (self._x.value + self.fetch(1) > 0xff) else: assert False, 'Need to impl, {}'.format(mode) return cross_boundry
def inx(self): self._x.value = u8(self._x.value + 1) self._flag.z = (self._x.value == 0) self._flag.n = (self._x.value >> 7 & 1) == 1 return False
def cpx(self): value = self._x.value - self._data self._flag.z = (u8(value) == 0) self._flag.n = (u8(value) >> 7 & 1) == 1 self._flag.c = (self._x.value >= self._data) return False
def dec(self): val = u8(self._data - 1) self._bus.write(self._addr, val) self._flag.n = (val >> 7 & 1) == 1 self._flag.z = (val == 0) return False
def __init__(self, machine): # machine self.machine = machine # cycles self.cycles = 0 # 当前指令执行时间 self.wait_cycles = 0 # program counter self.pc = u16() # stack pointer self.sp = u8(CPU_SP_INIT) # accumulator self.acc = u8() # status # 0 1 2 3 4 5 6 7 # Carry Zero Interrupt Decimal Break - Overflow Negative self.p = u8(CPU_P_INIT) # x index self.x = u8() # y index self.y = u8() # total cycles self.cycles = 0 # wait cycles self.wait_cycles = 0 # current interrupt self.current_interrupt = None p_bit_map = { 'carry': 0, 'zero': 1, 'interrupt': 2, 'decimal': 3, 'break': 4, 'overflow': 6, 'negative': 7 } for k, v in p_bit_map.iteritems(): self.__dict__[k] = types.MethodType(functools.partial(Cpu._p_test, i=v), self) self.__dict__['set_' + k] = types.MethodType(functools.partial(Cpu._p_set, i=v), self) # setup opcodes executor # key = bytecode, value = (function, addressing, cycles) self.opcodes = { 0x00: (self.brk, self.am_implied, 7), 0x01: (self.ora, self.am_indexed_indirect, 6), 0x03: (self.slo, self.am_indexed_indirect, 8), 0x04: (self.nop, self.am_zero_page, 3), # maybe tsb(test and set bits) 0x05: (self.ora, self.am_zero_page, 2), 0x06: (self.asl, self.am_zero_page, 5), 0x07: (self.slo, self.am_zero_page, 5), 0x08: (self.php, self.am_implied, 3), 0x09: (self.ora, self.am_immediate, 2), 0x0a: (self.asl_acc, self.am_accumulator, 2), 0x0c: (self.nop, self.am_absolute, 4), 0x0d: (self.ora, self.am_absolute, 4), 0x0e: (self.asl, self.am_absolute, 6), 0x0f: (self.slo, self.am_absolute, 6), 0x10: (self.bpl, self.am_relative, 2), 0x11: (self.ora, self.am_indirect_indexed, 5), 0x13: (self.slo, self.am_indirect_indexed, 8), 0x14: (self.nop, self.am_zero_page_x, 4), 0x15: (self.ora, self.am_zero_page_x, 4), 0x16: (self.asl, self.am_zero_page_x, 6), 0x17: (self.slo, self.am_zero_page_x, 6), 0x18: (self.clc, self.am_implied, 2), 0x19: (self.ora, self.am_absolute_y, 4), 0x1a: (self.nop, self.am_implied, 2), 0x1b: (self.slo, self.am_absolute_y, 7), 0x1c: (self.nop, self.am_absolute_x, 4), 0x1d: (self.ora, self.am_absolute_x, 4), 0x1e: (self.asl, self.am_absolute_x, 7), 0x1f: (self.slo, self.am_absolute_x, 7), 0x20: (self.jsr, self.am_absolute, 6), 0x21: (self.and_, self.am_indexed_indirect, 6), 0x23: (self.rla, self.am_indexed_indirect, 8), 0x24: (self.bit, self.am_zero_page, 3), 0x25: (self.and_, self.am_zero_page, 3), 0x26: (self.rol, self.am_zero_page, 5), 0x27: (self.rla, self.am_zero_page, 5), 0x28: (self.plp, self.am_implied, 4), 0x29: (self.and_, self.am_immediate, 2), 0x2a: (self.rol_acc, self.am_accumulator, 2), 0x2c: (self.bit, self.am_absolute, 4), 0x2d: (self.and_, self.am_absolute, 4), 0x2e: (self.rol, self.am_absolute, 6), 0x2f: (self.rla, self.am_absolute, 6), 0x30: (self.bmi, self.am_relative, 2), 0x31: (self.and_, self.am_indirect_indexed, 5), 0x33: (self.rla, self.am_indirect_indexed, 8), 0x34: (self.nop, self.am_zero_page_x, 4), 0x35: (self.and_, self.am_zero_page_x, 4), 0x36: (self.rol, self.am_zero_page_x, 6), 0x37: (self.rla, self.am_zero_page_x, 6), 0x38: (self.sec, self.am_implied, 2), 0x39: (self.and_, self.am_absolute_y, 4), 0x3a: (self.nop, self.am_implied, 2), 0x3b: (self.rla, self.am_absolute_y, 7), 0x3c: (self.nop, self.am_absolute_x, 4), 0x3d: (self.and_, self.am_absolute_x, 4), 0x3e: (self.rol, self.am_absolute_x, 7), 0x3f: (self.rla, self.am_absolute_x, 7), 0x40: (self.rti, self.am_implied, 6), 0x41: (self.eor, self.am_indexed_indirect, 6), 0x43: (self.sre, self.am_indexed_indirect, 8), 0x44: (self.nop, self.am_zero_page, 3), 0x45: (self.eor, self.am_zero_page, 3), 0x46: (self.lsr, self.am_zero_page, 5), 0x47: (self.sre, self.am_zero_page, 5), 0x48: (self.pha, self.am_implied, 3), 0x49: (self.eor, self.am_immediate, 2), 0x4a: (self.lsr_acc, self.am_accumulator, 2), 0x4c: (self.jmp, self.am_absolute, 3), 0x4d: (self.eor, self.am_absolute, 4), 0x4e: (self.lsr, self.am_absolute, 6), 0x4f: (self.sre, self.am_absolute, 6), 0x50: (self.bvc, self.am_relative, 2), 0x51: (self.eor, self.am_indirect_indexed, 5), 0x53: (self.sre, self.am_indirect_indexed, 8), 0x54: (self.nop, self.am_zero_page_x, 4), 0x55: (self.eor, self.am_zero_page_x, 4), 0x56: (self.lsr, self.am_zero_page_x, 6), 0x57: (self.sre, self.am_zero_page_x, 6), 0x58: (self.cli, self.am_implied, 2), 0x59: (self.eor, self.am_absolute_y, 4), 0x5a: (self.nop, self.am_implied, 2), 0x5b: (self.sre, self.am_absolute_y, 7), 0x5c: (self.nop, self.am_absolute_x, 4), 0x5d: (self.eor, self.am_absolute_x, 4), 0x5e: (self.lsr, self.am_absolute_x, 7), 0x5f: (self.sre, self.am_absolute_x, 7), 0x60: (self.rts, self.am_implied, 6), 0x61: (self.adc, self.am_indexed_indirect, 6), 0x63: (self.rra, self.am_indexed_indirect, 8), 0x64: (self.nop, self.am_zero_page, 3), 0x65: (self.adc, self.am_zero_page, 3), 0x66: (self.ror, self.am_zero_page, 5), 0x67: (self.rra, self.am_zero_page, 5), 0x68: (self.pla, self.am_implied, 4), 0x69: (self.adc, self.am_immediate, 2), 0x6a: (self.ror_acc, self.am_accumulator, 2), 0x6c: (self.jmp, self.am_indirect, 5), 0x6d: (self.adc, self.am_absolute, 4), 0x6e: (self.ror, self.am_absolute, 6), 0x6f: (self.rra, self.am_absolute, 6), 0x70: (self.bvs, self.am_relative, 2), 0x71: (self.adc, self.am_indirect_indexed, 5), 0x73: (self.rra, self.am_indirect_indexed, 8), 0x74: (self.nop, self.am_zero_page_x, 4), 0x75: (self.adc, self.am_zero_page_x, 4), 0x76: (self.ror, self.am_zero_page_x, 6), 0x77: (self.rra, self.am_zero_page_x, 6), 0x78: (self.sei, self.am_implied, 2), 0x79: (self.adc, self.am_absolute_y, 4), 0x7a: (self.nop, self.am_implied, 2), 0x7b: (self.rra, self.am_absolute_y, 7), 0x7c: (self.nop, self.am_absolute_x, 4), 0x7d: (self.adc, self.am_absolute_x, 4), 0x7e: (self.ror, self.am_absolute_x, 7), 0x7f: (self.rra, self.am_absolute_x, 7), 0x80: (self.nop, self.am_immediate, 2), 0x81: (self.sta, self.am_indexed_indirect, 6), 0x83: (self.sax, self.am_indexed_indirect, 6), 0x84: (self.sty, self.am_zero_page, 3), 0x85: (self.sta, self.am_zero_page, 3), 0x86: (self.stx, self.am_zero_page, 3), 0x87: (self.sax, self.am_zero_page, 3), 0x88: (self.dey, self.am_implied, 2), 0x89: (self.nop, self.am_immediate, 2), 0x8a: (self.txa, self.am_implied, 2), 0x8c: (self.sty, self.am_absolute, 4), 0x8d: (self.sta, self.am_absolute, 4), 0x8e: (self.stx, self.am_absolute, 4), 0x8f: (self.sax, self.am_absolute, 4), 0x90: (self.bcc, self.am_relative, 2), 0x91: (self.sta, self.am_indirect_indexed, 6), 0x94: (self.sty, self.am_zero_page_x, 4), 0x95: (self.sta, self.am_zero_page_x, 4), 0x96: (self.stx, self.am_zero_page_y, 4), 0x97: (self.sax, self.am_zero_page_y, 4), 0x98: (self.tya, self.am_implied, 2), 0x99: (self.sta, self.am_absolute_y, 5), 0x9a: (self.txs, self.am_implied, 2), 0x9d: (self.sta, self.am_absolute_x, 5), 0xa0: (self.ldy, self.am_immediate, 2), 0xa1: (self.lda, self.am_indexed_indirect, 6), 0xa2: (self.ldx, self.am_immediate, 2), 0xa3: (self.lax, self.am_indexed_indirect, 6), 0xa4: (self.ldy, self.am_zero_page, 3), 0xa5: (self.lda, self.am_zero_page, 3), 0xa6: (self.ldx, self.am_zero_page, 3), 0xa7: (self.lax, self.am_zero_page, 3), 0xa8: (self.tay, self.am_implied, 2), 0xa9: (self.lda, self.am_immediate, 2), 0xaa: (self.tax, self.am_implied, 2), 0xac: (self.ldy, self.am_absolute, 4), 0xad: (self.lda, self.am_absolute, 4), 0xae: (self.ldx, self.am_absolute, 4), 0xaf: (self.lax, self.am_absolute, 4), 0xb0: (self.bcs, self.am_relative, 2), 0xb1: (self.lda, self.am_indirect_indexed, 5), 0xb3: (self.lax, self.am_indirect_indexed, 5), 0xb4: (self.ldy, self.am_zero_page_x, 4), 0xb5: (self.lda, self.am_zero_page_x, 4), 0xb6: (self.ldx, self.am_zero_page_y, 4), 0xb7: (self.lax, self.am_zero_page_y, 4), 0xb8: (self.clv, self.am_implied, 2), 0xb9: (self.lda, self.am_absolute_y, 4), 0xba: (self.tsx, self.am_implied, 2), 0xbc: (self.ldy, self.am_absolute_x, 4), 0xbd: (self.lda, self.am_absolute_x, 4), 0xbe: (self.ldx, self.am_absolute_y, 4), 0xbf: (self.lax, self.am_absolute_y, 4), 0xc0: (self.cpy, self.am_immediate, 2), 0xc1: (self.cmp, self.am_indexed_indirect, 2), 0xc3: (self.dcp, self.am_indexed_indirect, 8), 0xc4: (self.cpy, self.am_zero_page, 3), 0xc5: (self.cmp, self.am_zero_page, 3), 0xc6: (self.dec, self.am_zero_page, 5), 0xc7: (self.dcp, self.am_zero_page, 5), 0xc8: (self.iny, self.am_implied, 2), 0xc9: (self.cmp, self.am_immediate, 2), 0xca: (self.dex, self.am_implied, 2), 0xcc: (self.cpy, self.am_absolute, 4), 0xcd: (self.cmp, self.am_absolute, 4), 0xce: (self.dec, self.am_absolute, 6), 0xcf: (self.dcp, self.am_absolute, 6), 0xd0: (self.bne, self.am_relative, 2), 0xd1: (self.cmp, self.am_indirect_indexed, 5), 0xd3: (self.dcp, self.am_indirect_indexed, 8), 0xd4: (self.nop, self.am_zero_page_x, 4), 0xd5: (self.cmp, self.am_zero_page_x, 4), 0xd6: (self.dec, self.am_zero_page_x, 6), 0xd7: (self.dcp, self.am_zero_page_x, 6), 0xd8: (self.cld, self.am_implied, 2), 0xd9: (self.cmp, self.am_absolute_y, 4), 0xda: (self.nop, self.am_implied, 2), 0xdb: (self.dcp, self.am_absolute_y, 7), 0xdc: (self.nop, self.am_absolute_x, 4), 0xdd: (self.cmp, self.am_absolute_x, 4), 0xde: (self.dec, self.am_absolute_x, 7), 0xdf: (self.dcp, self.am_absolute_x, 7), 0xe0: (self.cpx, self.am_immediate, 2), 0xe1: (self.sbc, self.am_indexed_indirect, 6), 0xe3: (self.isb, self.am_indexed_indirect, 8), 0xe4: (self.cpx, self.am_zero_page, 3), 0xe5: (self.sbc, self.am_zero_page, 3), 0xe6: (self.inc, self.am_zero_page, 5), 0xe7: (self.isb, self.am_zero_page, 5), 0xe8: (self.inx, self.am_implied, 2), 0xe9: (self.sbc, self.am_immediate, 2), 0xea: (self.nop, self.am_implied, 2), 0xeb: (self.sbc, self.am_immediate, 2), 0xec: (self.cpx, self.am_absolute, 4), 0xee: (self.inc, self.am_absolute, 6), 0xef: (self.isb, self.am_absolute, 6), 0xed: (self.sbc, self.am_absolute, 4), 0xf0: (self.beq, self.am_relative, 2), 0xf1: (self.sbc, self.am_indirect_indexed, 5), 0xf3: (self.isb, self.am_indirect_indexed, 8), 0xf4: (self.nop, self.am_zero_page_x, 4), 0xf5: (self.sbc, self.am_zero_page_x, 4), 0xf6: (self.inc, self.am_zero_page_x, 6), 0xf7: (self.isb, self.am_zero_page_x, 6), 0xf8: (self.sed, self.am_implied, 2), 0xf9: (self.sbc, self.am_absolute_y, 4), 0xfa: (self.nop, self.am_implied, 2), 0xfb: (self.isb, self.am_absolute_y, 7), 0xfc: (self.nop, self.am_absolute_x, 4), 0xfd: (self.sbc, self.am_absolute_x, 4), 0xfe: (self.inc, self.am_absolute_x, 7), 0xff: (self.isb, self.am_absolute_x, 7) }
def dey(self): self._y.value = u8(self._y.value - 1) self._flag.z = (self._y.value == 0) self._flag.n = (self._y.value >> 7 & 1) == 1 return False
def inc(self): val = u8(1 + self._data) self._bus.write(self._addr, val) self._flag.z = (val == 0) self._flag.n = (val >> 7 & 1) == 1 return False