def PPUADDR_INC(self, value=1): v = FlagByte(0x0) v[0:8] = self._PPUADDR[0] v[8:16] = self._PPUADDR[1] v.value += value self._PPUADDR[0] = v[0:8] self._PPUADDR[1] = v[8:16]
def set_overflow(self, data): data = FlagByte(data) overflow = data[6] self._registers.overflow = overflow
def set_negative(self, data): data = FlagByte(data) negative = data[7] self._registers.negative = negative
def habdle_ins(self, ins, address, data): if ins == 'JMP': self._registers.PC = address elif ins == 'BRK': self._running = False return elif ins == 'LDX': self._registers.X = data self.set_zero_negative(data) elif ins == 'STX': self.write_address(address, self._registers.X) elif ins == 'JSR': pc = self._registers.PC - 1 self.push_stack(pc, hex_digit=True) self._registers.PC = address elif ins == 'SEC': self._registers.carry = 1 elif ins == 'SEI': self._registers.interrupt_disable = 1 elif ins == 'SED': self._registers.decimal = 1 elif ins == 'BCS': if self._registers.carry == 1: self._registers.PC = address elif ins == 'CLC': self._registers.carry = 0 elif ins == 'BCC': if self._registers.carry == 0: self._registers.PC = address elif ins == 'LDA': self._registers.A = data self.set_zero_negative(data) elif ins == 'BEQ': if self._registers.zero == 1: self._registers.PC = address elif ins == 'BNE': if self._registers.zero == 0: self._registers.PC = address elif ins == 'STA': self.write_address(address, self._registers.A) elif ins == 'STY': self.write_address(address, self._registers.Y) elif ins == 'BIT': zf = 0 if self._registers.A & data else 1 self._registers.zero = zf self.set_negative(data) self.set_overflow(data) elif ins == 'BVS': if self._registers.overflow == 1: self._registers.PC = address elif ins == 'BVC': if self._registers.overflow == 0: self._registers.PC = address elif ins == 'BPL': if self._registers.negative == 0: self._registers.PC = address elif ins == 'RTS': pc = self.pop_stack(hex_digit=True) self._registers.PC = pc + 1 elif ins == 'PHP': p = FlagByte(self._registers.P) p[4] = 1 # 当 P 被 指令 PHP BRK 压入栈时, 压入的 P 的第 4 位被设置成 1 self.push_stack(p.value) elif ins == 'PLA': data_ = self.pop_stack() self.set_zero_negative(data_) self._registers.A = data_ elif ins == 'PLP': data_ = FlagByte(self.pop_stack()) # 用弹出的值的 第 0 1 2 3 6 7 位 来设置 P 的 第 0 1 2 3 6 7 位 的值 pre_p = self._registers.P pre_p = FlagByte(pre_p) data_[4] = pre_p[4] data_[5] = pre_p[5] self._registers.P = data_.value elif ins == 'AND': a = self._registers.A a &= data self.set_zero_negative(a) self._registers.A = a elif ins == 'CMP': result = self._registers.A - data self.set_zero_negative(result) self.set_negative(result) self.set_carry(result >= 0) elif ins == 'CLD': self._registers.decimal = 0 elif ins == 'PHA': self.push_stack(self._registers.A) elif ins == 'ORA': self._registers.A |= data self.set_zero_negative(self._registers.A) elif ins == 'CLV': self._registers.overflow = 0 elif ins == 'EOR': self._registers.A ^= data self.set_zero_negative(self._registers.A) elif ins == 'ADC': a = self._registers.A result = self._registers.A + data + self._registers.carry self.set_carry(result >> 8) low, high = self.split_number(result) self._registers.A = low self.set_overflow_by_expression(not ((a ^ data) & 0x80) and ((a ^ low) & 0x80)) self.set_zero_negative(low) elif ins == 'LDY': self._registers.Y = data self.set_zero_negative(data) elif ins == 'CPY': res = self._registers.Y - data self.set_carry(self._registers.Y >= data) self.set_zero_negative(res) elif ins == 'CPX': res = self._registers.X - data self.set_carry(self._registers.X >= data) self.set_zero_negative(res) elif ins == 'SBC': res = self._registers.A - data - (0 if self._registers.carry else 1) low, high = self.split_number(res) self.set_carry(not high) self.set_overflow_by_expression(((self._registers.A ^ data) & 0x80) & ((self._registers.A ^ high) & 0x80)) self._registers.A = low self.set_zero_negative(low) elif ins == 'INY': res = self._registers.Y + 1 res = self.eight_digit(res) self.set_zero_negative(res) self._registers.Y = res elif ins == 'INX': res = self._registers.X + 1 res = self.eight_digit(res) self.set_zero_negative(res) self._registers.X = res elif ins == 'DEY': res = self._registers.Y - 1 res = self.eight_digit(res) self.set_zero_negative(res) self._registers.Y = res elif ins == 'DEX': res = self._registers.X - 1 res = self.eight_digit(res) self.set_zero_negative(res) self._registers.X = res elif ins == 'TAY': res = self._registers.A self.set_zero_negative(res) self._registers.Y = res elif ins == 'TAX': res = self._registers.A self.set_zero_negative(res) self._registers.X = res elif ins == 'TYA': res = self._registers.Y self.set_zero_negative(res) self._registers.A = res elif ins == 'TXA': res = self._registers.X self.set_zero_negative(res) self._registers.A = res elif ins == 'TSX': res = self._registers.S self.set_zero_negative(res) self._registers.X = res elif ins == 'TXS': res = self._registers.X self._registers.S = res elif ins == 'RTI': p = self.pop_stack() p = FlagByte(p) p[4] = self._registers.b_flag p[5] = 1 self._registers.P = p.value self._registers.PC = self.pop_stack(hex_digit=True) elif ins == 'LSR': if address != -1: a = data else: a = self._registers.A self._registers.carry = a & 1 a >>= 1 a = self.eight_digit(a) self.set_zero_negative(a) if address != -1: self.write_address(address, a) else: self._registers.A = a elif ins == 'ASL': if address != -1: a = data else: a = self._registers.A self._registers.carry = a >> 7 a <<= 1 a = self.eight_digit(a) self.set_zero_negative(a) if address != -1: self.write_address(address, a) else: self._registers.A = a elif ins == 'ROR': if address != -1: a = data else: a = self._registers.A zero = a & 1 a >>= 1 a ^= self._registers.carry << 7 self._registers.carry = zero a = self.eight_digit(a) self.set_zero_negative(a) if address != -1: self.write_address(address, a) else: self._registers.A = a elif ins == 'ROL': if address != -1: a = data else: a = self._registers.A seven = (a & 1 << 7) >> 7 a <<= 1 a ^= self._registers.carry self._registers.carry = seven a = self.eight_digit(a) self.set_zero_negative(a) if address != -1: self.write_address(address, a) else: self._registers.A = a elif ins == 'NOP': pass elif ins == 'BMI': if self._registers.negative == 1: self._registers.PC = address elif ins == "INC": d = self.eight_digit(data + 1) self.set_zero_negative(d) self.write_address(address, d) elif ins == "DEC": d = self.eight_digit(data - 1) self.set_zero_negative(d) self.write_address(address, d) elif ins == 'LAX': self._registers.X = self._registers.A = data self.set_zero_negative(data) elif ins == 'SAX': self.write_address(address, self._registers.A & self._registers.X) elif ins == 'DCP': data -= 1 data = self.eight_digit(data) self.write_address(address, data) result = self.hex_digit(self._registers.A - data) self.set_carry(result < 0x100) self.set_zero_negative(self.eight_digit(result)) elif ins == 'ISB': data += 1 data = self.eight_digit(data) self.write_address(address, data) resul16 = self.hex_digit(self._registers.A - data - (0 if self._registers.carry else 1)) self.set_carry(not resul16 >> 8) result8 = self.eight_digit(resul16) A = self._registers.A self.set_overflow_by_expression(((A ^ result8) & 0x80) and ((A ^ data) & 0x80)) self._registers.A = result8 self.set_zero_negative(result8) elif ins == 'SLO': self.set_carry(data >> 7) data <<= 1 data = self.eight_digit(data) self.write_address(address, data) self._registers.A |= data self.set_zero_negative(self._registers.A) elif ins == 'RLA': data <<= 1 data = self.hex_digit(data) if self._registers.carry: data |= 0x1 self.set_carry(data > 0xff) result8 = self.eight_digit(data) self.write_address(address, result8) a = self._registers.A & result8 self.set_zero_negative(a) self._registers.A = a elif ins == 'SRE': self.set_carry(data & 1) data >>= 1 data = self.eight_digit(data) self.write_address(address, data) a = self._registers.A a ^= data self.set_zero_negative(a) self._registers.A = a elif ins == 'RRA': if self._registers.carry: data |= 0x100 self._registers.carry = data & 1 data >>= 1 self.write_address(address, self.eight_digit(data)) a = self._registers.A resul16 = a + data + (1 if self._registers.carry else 0) self.set_carry(resul16 >> 8) result8 = self.eight_digit(resul16) self.set_overflow_by_expression(not ((a ^ data) & 0x80) and ((a ^ result8) & 0x80)) self._registers.A = result8 self.set_zero_negative(result8) else: raise NotImplementedError("稍等一下, {} 指令还没实现".format(ins))
class Registers: PC = 0 # Program Counter # A = 0 # Accumulator # X = 0 # Indexes # Y = 0 # Indexes # S = 0xFD # Stack Pointer _INNER = bytearray([0, 0, 0, 0xFD]) _P = FlagByte(0x24) # Status Register r''' 7 bit 0 ---- ---- NVss DIZC |||| |||| |||| |||+- Carry |||| ||+-- Zero |||| |+--- Interrupt Disable |||| +---- Decimal ||++------ No CPU effect, see: the B flag |+-------- Overflow +--------- Negative 关于 B flag 注意:第几位 是从 第 0 位 开始数的 第 5 位永远为 1 当 P 被 指令 PHP BRK 压入栈时, 压入的 P 的第 4 位被设置成 1 当 P 由于 中断 \IRQ \NMI 被压入栈时, 压入的 P 的第 4 位被设置成 0 当 P 被指令 PLP RTI 设置为栈中弹出的值时,不影响 第 4 5 位 ''' @property def A(self): return self._INNER[0] @A.setter def A(self, value): self._INNER[0] = value @property def X(self): return self._INNER[1] @X.setter def X(self, value): self._INNER[1] = value @property def Y(self): return self._INNER[2] @Y.setter def Y(self, value): self._INNER[2] = value @property def S(self): return self._INNER[3] @S.setter def S(self, value): self._INNER[3] = value @property def carry(self): return self._P[0] @carry.setter def carry(self, value): self._P[0] = value @property def zero(self): return self._P[1] @zero.setter def zero(self, value): self._P[1] = value @property def interrupt_disable(self): return self._P[2] @interrupt_disable.setter def interrupt_disable(self, value): self._P[2] = value @property def decimal(self): return self._P[3] @decimal.setter def decimal(self, value): self._P[3] = value @property def b_flag(self): return self._P[4] @b_flag.setter def b_flag(self, value): self._P[4] = value @property def overflow(self): return self._P[6] @overflow.setter def overflow(self, value): self._P[6] = value @property def negative(self): return self._P[7] @negative.setter def negative(self, value): self._P[7] = value @property def P(self): return self._P.value @P.setter def P(self, value): self._P = FlagByte(value) @classmethod def to_real_address(cls, sp): return sp | (0x01 << 8)
def P(self, value): self._P = FlagByte(value)
def PPUADDR(self): v = FlagByte(0x0) v[0:8] = self._PPUADDR[0] v[8:16] = self._PPUADDR[1] return v.value
def split_number(cls, num: int): n = FlagByte(num) low, high = n[0:8], n[8:16] return low, high
def from_low_high_to_int(cls, low: int or bytes, high: int or bytes): v = FlagByte(0x0) v[0:8] = low v[8:16] = high return v.value
def low_high(cls, val): pc = FlagByte(val) return pc[0:8], pc[8:16]