diff --git a/applepy.py b/applepy.py index 7754ec4..4f2e69d 100755 --- a/applepy.py +++ b/applepy.py @@ -17,7 +17,7 @@ import wave class Display: - + characters = [ [0b00000, 0b01110, 0b10001, 0b10101, 0b10111, 0b10110, 0b10000, 0b01111], [0b00000, 0b00100, 0b01010, 0b10001, 0b10001, 0b11111, 0b10001, 0b10001], @@ -84,7 +84,7 @@ class Display: [0b00000, 0b01000, 0b00100, 0b00010, 0b00001, 0b00010, 0b00100, 0b01000], [0b00000, 0b01110, 0b10001, 0b00010, 0b00100, 0b00100, 0b00000, 0b00100] ] - + lores_colours = [ (0, 0, 0), # black (208, 0, 48), # magenta / dark red @@ -103,7 +103,7 @@ class Display: (64, 255, 144), # aquamarine / light green (255, 255, 255), # white ] - + def __init__(self): self.screen = pygame.display.set_mode((560, 384)) pygame.display.set_caption("ApplePy") @@ -115,7 +115,7 @@ class Display: self.page = 1 self.text = True self.colour = False - + self.chargen = [] for c in self.characters: chars = [[pygame.Surface((14, 16)), pygame.Surface((14, 16))], @@ -134,33 +134,33 @@ class Display: pixels[2 * col + 1][2 * row] = on if bit else off del pixels self.chargen.append(chars) - + def txtclr(self): self.text = False - + def txtset(self): self.text = True self.colour = False - + def mixclr(self): self.mix = False - + def mixset(self): self.mix = True self.colour = True - + def lowscr(self): self.page = 1 - + def hiscr(self): self.page = 2 - + def lores(self): self.high_res = False - + def hires(self): self.high_res = True - + def update(self, address, value): if self.page == 1: start_text = 0x400 @@ -170,33 +170,33 @@ class Display: start_hires = 0x4000 else: return - + if start_text <= address <= start_text + 0x3FF: base = address - start_text self.flash_chars[self.page - 1][base] = value hi, lo = divmod(base, 0x80) row_group, column = divmod(lo, 0x28) row = hi + 8 * row_group - + if row_group == 3: return - + if self.text or not self.mix or not row < 20: mode, ch = divmod(value, 0x40) - + if mode == 0: inv = True elif mode == 1: inv = self.flash_on else: inv = False - + self.screen.blit(self.chargen[ch][self.colour][inv], (2 * (column * 7), 2 * (row * 8))) else: pixels = pygame.PixelArray(self.screen) if not self.high_res: lower, upper = divmod(value, 0x10) - + for dx in range(14): for dy in range(8): x = column * 14 + dx @@ -207,7 +207,7 @@ class Display: y = row * 16 + dy pixels[x][y] = self.lores_colours[lower] del pixels - + elif start_hires <= address <= start_hires + 0x1FFF: if self.high_res: base = address - start_hires @@ -215,21 +215,21 @@ class Display: hi, lo = divmod(b, 0x80) row_group, column = divmod(lo, 0x28) row = 8 * (hi + 8 * row_group) + row8 - + if self.mix and row >= 160: return - + if row < 192 and column < 40: - + pixels = pygame.PixelArray(self.screen) msb = value // 0x80 - + for b in range(7): c = value & (1 << b) xx = (column * 7 + b) x = 2 * xx y = 2 * row - + if msb: if xx % 2: pixels[x][y] = (0, 0, 0) @@ -252,10 +252,10 @@ class Display: pixels[x][y] = (255, 0, 255) if c else (0, 0, 0) pixels[x + 1][y] = (0, 0, 0) pixels[x + 1][y] = (255, 0, 255) if c else (0, 0, 0) # @@@ - + pixels[x][y + 1] = (0, 0, 0) pixels[x + 1][y + 1] = (0, 0, 0) - + del pixels def flash(self): @@ -268,15 +268,15 @@ class Display: class Speaker: - + CPU_CYCLES_PER_SAMPLE = 60 CHECK_INTERVAL = 1000 - + def __init__(self): pygame.mixer.pre_init(11025, -16, 1) pygame.init() self.reset() - + def toggle(self, cycle): if self.last_toggle is not None: l = (cycle - self.last_toggle) / Speaker.CPU_CYCLES_PER_SAMPLE @@ -284,18 +284,18 @@ class Speaker: self.buffer.extend((l - 2) * [16384] if self.polarity else [-16384]) self.polarity = not self.polarity self.last_toggle = cycle - + def reset(self): self.last_toggle = None self.buffer = [] self.polarity = False - + def play(self): sample_array = numpy.int16(self.buffer) sound = pygame.sndarray.make_sound(sample_array) sound.play() self.reset() - + def update(self, cycle): if self.buffer and (cycle - self.last_toggle) > self.CHECK_INTERVAL: self.play() @@ -322,13 +322,13 @@ class Cassette: class SoftSwitches: - + def __init__(self, display, speaker, cassette): self.kbd = 0x00 self.display = display self.speaker = speaker self.cassette = cassette - + def read_byte(self, cycle, address): assert 0xC000 <= address <= 0xCFFF if address == 0xC000: @@ -409,11 +409,11 @@ class Apple2: self.display.update(addr, val) else: break - + for event in pygame.event.get(): if event.type == pygame.QUIT: quit = True - + if event.type == pygame.KEYDOWN: key = ord(event.unicode) if event.unicode else 0 if event.key == pygame.K_LEFT: @@ -424,7 +424,7 @@ class Apple2: if key == 0x7F: key = 0x08 self.softswitches.kbd = 0x80 + (key & 0x7F) - + update_cycle += 1 if update_cycle >= 1024: self.display.flash() @@ -432,7 +432,7 @@ class Apple2: if self.speaker: self.speaker.update(cycle) update_cycle = 0 - + def usage(): print >>sys.stderr, "ApplePy - an Apple ][ emulator in Python" diff --git a/applepy_curses.py b/applepy_curses.py index a232c40..794d94d 100644 --- a/applepy_curses.py +++ b/applepy_curses.py @@ -18,13 +18,13 @@ def write_screen(win, address, value): hi, lo = divmod(base, 0x80) row_group, column = divmod(lo, 0x28) row = hi + 8 * row_group - + # skip if writing to row group 3 if row_group == 3: return - + c = chr(0x20 + ((value + 0x20) % 0x40)) - + if value < 0x40: attr = curses.A_DIM elif value < 0x80: @@ -33,7 +33,7 @@ def write_screen(win, address, value): attr = curses.A_UNDERLINE else: attr = curses.A_DIM - + try: win.addch(row, column, c, attr) except curses.error: @@ -95,7 +95,7 @@ def run(win): pass except TypeError: pass - + def usage(): print >>sys.stderr, "ApplePy - an Apple ][ emulator in Python" diff --git a/cpu6502.py b/cpu6502.py index c29c4cc..d9aac61 100644 --- a/cpu6502.py +++ b/cpu6502.py @@ -22,50 +22,50 @@ def signed(x): class ROM: - + def __init__(self, start, size): self.start = start self.end = start + size - 1 self._mem = [0x00] * size - + def load(self, address, data): for offset, datum in enumerate(data): self._mem[address - self.start + offset] = datum - + def load_file(self, address, filename): with open(filename, "rb") as f: for offset, datum in enumerate(f.read()): self._mem[address - self.start + offset] = ord(datum) - + def read_byte(self, address): assert self.start <= address <= self.end return self._mem[address - self.start] class RAM(ROM): - + def write_byte(self, address, value): self._mem[address] = value class Memory: - + def __init__(self, options=None, use_bus=True): self.use_bus = use_bus self.rom = ROM(0xD000, 0x3000) - + if options: self.rom.load_file(0xD000, options.rom) - + self.ram = RAM(0x0000, 0xC000) - + if options and options.ram: self.ram.load_file(0x0000, options.ram) - + def load(self, address, data): if address < 0xC000: self.ram.load(address, data) - + def read_byte(self, cycle, address): if address < 0xC000: return self.ram.read_byte(address) @@ -73,16 +73,16 @@ class Memory: return self.bus_read(cycle, address) else: return self.rom.read_byte(address) - + def read_word(self, cycle, address): return self.read_byte(cycle, address) + (self.read_byte(cycle + 1, address + 1) << 8) - + def read_word_bug(self, cycle, address): if address % 0x100 == 0xFF: return self.read_byte(cycle, address) + (self.read_byte(cycle + 1, address & 0xFF00) << 8) else: return self.read_word(cycle, address) - + def write_byte(self, cycle, address, value): if address < 0xC000: self.ram.write_byte(address, value) @@ -116,9 +116,9 @@ class Disassemble: def __init__(self, cpu, memory): self.cpu = cpu self.memory = memory - + self.setup_ops() - + def setup_ops(self): self.ops = [(1, "???")] * 0x100 self.ops[0x00] = (1, "BRK", ) @@ -272,14 +272,14 @@ class Disassemble: self.ops[0xF9] = (3, "SBC", self.absolute_y_mode) self.ops[0xFD] = (3, "SBC", self.absolute_x_mode) self.ops[0xFE] = (3, "INC", self.absolute_x_mode) - + def absolute_mode(self, pc): a = self.cpu.read_word(pc + 1) return { "operand": "$%04X" % a, "memory": [a, 2, self.cpu.read_word(a)], } - + def absolute_x_mode(self, pc): a = self.cpu.read_word(pc + 1) e = a + self.cpu.x_index @@ -287,7 +287,7 @@ class Disassemble: "operand": "$%04X,X" % a, "memory": [e, 1, self.cpu.read_byte(e)], } - + def absolute_y_mode(self, pc): a = self.cpu.read_word(pc + 1) e = a + self.cpu.y_index @@ -295,19 +295,19 @@ class Disassemble: "operand": "$%04X,Y" % a, "memory": [e, 1, self.cpu.read_byte(e)], } - + def immediate_mode(self, pc): return { "operand": "#$%02X" % (self.cpu.read_byte(pc + 1)), } - + def indirect_mode(self, pc): a = self.cpu.read_word(pc + 1) return { "operand": "($%04X)" % a, "memory": [a, 2, self.cpu.read_word(a)], } - + def indirect_x_mode(self, pc): z = self.cpu.read_byte(pc + 1) a = self.cpu.read_word((z + self.cpu.x_index) % 0x100) @@ -315,7 +315,7 @@ class Disassemble: "operand": "($%02X,X)" % z, "memory": [a, 1, self.cpu.read_byte(a)], } - + def indirect_y_mode(self, pc): z = self.cpu.read_byte(pc + 1) a = self.cpu.read_word(z) + self.cpu.y_index @@ -323,19 +323,19 @@ class Disassemble: "operand": "($%02X),Y" % z, "memory": [a, 1, self.cpu.read_byte(a)], } - + def relative_mode(self, pc): return { "operand": "$%04X" % (pc + signed(self.cpu.read_byte(pc + 1) + 2)), } - + def zero_page_mode(self, pc): a = self.cpu.read_byte(pc + 1) return { "operand": "$%02X" % a, "memory": [a, 1, self.cpu.read_byte(a)], } - + def zero_page_x_mode(self, pc): z = self.cpu.read_byte(pc + 1) a = (z + self.cpu.x_index) % 0x100 @@ -343,7 +343,7 @@ class Disassemble: "operand": "$%02X,X" % z, "memory": [a, 1, self.cpu.read_byte(a)], } - + def zero_page_y_mode(self, pc): z = self.cpu.read_byte(pc + 1) a = (z + self.cpu.y_index) % 0x100 @@ -351,7 +351,7 @@ class Disassemble: "operand": "$%02X,Y" % z, "memory": [a, 1, self.cpu.read_byte(a)], } - + def disasm(self, pc): op = self.cpu.read_byte(pc) info = self.ops[op] @@ -501,19 +501,19 @@ class ControlHandlerFactory: class CPU: - + STACK_PAGE = 0x100 RESET_VECTOR = 0xFFFC - + def __init__(self, options, memory): self.memory = memory self.control_server = BaseHTTPServer.HTTPServer(("127.0.0.1", 6502), ControlHandlerFactory(self)) - + self.accumulator = 0x00 self.x_index = 0x00 self.y_index = 0x00 - + self.carry_flag = 0 self.zero_flag = 0 self.interrupt_disable_flag = 0 @@ -521,18 +521,18 @@ class CPU: self.break_flag = 1 self.overflow_flag = 0 self.sign_flag = 0 - + self.stack_pointer = 0xFF - + self.cycles = 0 - + self.setup_ops() self.reset() if options.pc is not None: self.program_counter = options.pc self.running = True self.quit = False - + def setup_ops(self): self.ops = [None] * 0x100 self.ops[0x00] = lambda: self.BRK() @@ -686,10 +686,10 @@ class CPU: self.ops[0xF9] = lambda: self.SBC(self.absolute_y_mode()) self.ops[0xFD] = lambda: self.SBC(self.absolute_x_mode()) self.ops[0xFE] = lambda: self.INC(self.absolute_x_mode(rmw=True)) - + def reset(self): self.program_counter = self.read_word(self.RESET_VECTOR) - + def run(self, bus_port): global bus bus = socket.socket() @@ -725,7 +725,7 @@ class CPU: else: self.ops[op]() count -= 1 - + def test_run(self, start, end): self.program_counter = start while True: @@ -741,34 +741,34 @@ class CPU: break else: self.ops[op]() - + #### - + def get_pc(self, inc=1): pc = self.program_counter self.program_counter += inc return pc - + def read_byte(self, address): return self.memory.read_byte(self.cycles, address) - + def read_word(self, address): return self.memory.read_word(self.cycles, address) - + def read_word_bug(self, address): return self.memory.read_word_bug(self.cycles, address) - + def read_pc_byte(self): return self.read_byte(self.get_pc()) - + def read_pc_word(self): return self.read_word(self.get_pc(2)) def write_byte(self, address, value): self.memory.write_byte(self.cycles, address, value) - + #### - + def status_from_byte(self, status): self.carry_flag = [0, 1][0 != status & 1] self.zero_flag = [0, 1][0 != status & 2] @@ -777,143 +777,143 @@ class CPU: self.break_flag = [0, 1][0 != status & 16] self.overflow_flag = [0, 1][0 != status & 64] self.sign_flag = [0, 1][0 != status & 128] - + def status_as_byte(self): - return self.carry_flag | self.zero_flag << 1 | self.interrupt_disable_flag << 2 | self.decimal_mode_flag << 3 | self.break_flag << 4 | 1 << 5 | self.overflow_flag << 6 | self.sign_flag << 7 - + return self.carry_flag | self.zero_flag << 1 | self.interrupt_disable_flag << 2 | self.decimal_mode_flag << 3 | self.break_flag << 4 | 1 << 5 | self.overflow_flag << 6 | self.sign_flag << 7 + #### - + def push_byte(self, byte): self.write_byte(self.STACK_PAGE + self.stack_pointer, byte) self.stack_pointer = (self.stack_pointer - 1) % 0x100 - + def pull_byte(self): self.stack_pointer = (self.stack_pointer + 1) % 0x100 return self.read_byte(self.STACK_PAGE + self.stack_pointer) - + def push_word(self, word): hi, lo = divmod(word, 0x100) self.push_byte(hi) self.push_byte(lo) - + def pull_word(self): s = self.STACK_PAGE + self.stack_pointer + 1 self.stack_pointer += 2 return self.read_word(s) - + #### - + def immediate_mode(self): return self.get_pc() - + def absolute_mode(self): self.cycles += 2 return self.read_pc_word() - + def absolute_x_mode(self, rmw=False): if rmw: self.cycles += 1 return self.absolute_mode() + self.x_index - + def absolute_y_mode(self, rmw=False): if rmw: self.cycles += 1 return self.absolute_mode() + self.y_index - + def zero_page_mode(self): self.cycles += 1 return self.read_pc_byte() - + def zero_page_x_mode(self): self.cycles += 1 return (self.zero_page_mode() + self.x_index) % 0x100 - + def zero_page_y_mode(self): self.cycles += 1 return (self.zero_page_mode() + self.y_index) % 0x100 - + def indirect_mode(self): self.cycles += 2 return self.read_word_bug(self.absolute_mode()) - + def indirect_x_mode(self): self.cycles += 4 return self.read_word_bug((self.read_pc_byte() + self.x_index) % 0x100) - + def indirect_y_mode(self, rmw=False): if rmw: self.cycles += 4 else: self.cycles += 3 return self.read_word_bug(self.read_pc_byte()) + self.y_index - + def relative_mode(self): pc = self.get_pc() return pc + 1 + signed(self.read_byte(pc)) - + #### - + def update_nz(self, value): value = value % 0x100 self.zero_flag = [0, 1][(value == 0)] self.sign_flag = [0, 1][((value & 0x80) != 0)] return value - + def update_nzc(self, value): self.carry_flag = [0, 1][(value > 0xFF)] return self.update_nz(value) - + #### - + # LOAD / STORE - + def LDA(self, operand_address): self.accumulator = self.update_nz(self.read_byte(operand_address)) - + def LDX(self, operand_address): self.x_index = self.update_nz(self.read_byte(operand_address)) - + def LDY(self, operand_address): self.y_index = self.update_nz(self.read_byte(operand_address)) - + def STA(self, operand_address): self.write_byte(operand_address, self.accumulator) - + def STX(self, operand_address): self.write_byte(operand_address, self.x_index) - + def STY(self, operand_address): self.write_byte(operand_address, self.y_index) - + # TRANSFER - + def TAX(self): self.x_index = self.update_nz(self.accumulator) - + def TXA(self): self.accumulator = self.update_nz(self.x_index) - + def TAY(self): self.y_index = self.update_nz(self.accumulator) - + def TYA(self): self.accumulator = self.update_nz(self.y_index) - + def TSX(self): self.x_index = self.update_nz(self.stack_pointer) - + def TXS(self): self.stack_pointer = self.x_index - + # SHIFTS / ROTATES - + def ASL(self, operand_address=None): if operand_address is None: self.accumulator = self.update_nzc(self.accumulator << 1) else: self.cycles += 2 self.write_byte(operand_address, self.update_nzc(self.read_byte(operand_address) << 1)) - + def ROL(self, operand_address=None): if operand_address is None: a = self.accumulator << 1 @@ -926,7 +926,7 @@ class CPU: if self.carry_flag: m = m | 0x01 self.write_byte(operand_address, self.update_nzc(m)) - + def ROR(self, operand_address=None): if operand_address is None: if self.carry_flag: @@ -940,7 +940,7 @@ class CPU: m = m | 0x100 self.carry_flag = m % 2 self.write_byte(operand_address, self.update_nz(m >> 1)) - + def LSR(self, operand_address=None): if operand_address is None: self.carry_flag = self.accumulator % 2 @@ -949,224 +949,224 @@ class CPU: self.cycles += 2 self.carry_flag = self.read_byte(operand_address) % 2 self.write_byte(operand_address, self.update_nz(self.read_byte(operand_address) >> 1)) - + # JUMPS / RETURNS - + def JMP(self, operand_address): self.cycles -= 1 self.program_counter = operand_address - + def JSR(self, operand_address): self.cycles += 2 self.push_word(self.program_counter - 1) self.program_counter = operand_address - + def RTS(self): self.cycles += 4 self.program_counter = self.pull_word() + 1 - + # BRANCHES - + def BCC(self, operand_address): if not self.carry_flag: self.cycles += 1 self.program_counter = operand_address - + def BCS(self, operand_address): if self.carry_flag: self.cycles += 1 self.program_counter = operand_address - + def BEQ(self, operand_address): if self.zero_flag: self.cycles += 1 self.program_counter = operand_address - + def BNE(self, operand_address): if not self.zero_flag: self.cycles += 1 self.program_counter = operand_address - + def BMI(self, operand_address): if self.sign_flag: self.cycles += 1 self.program_counter = operand_address - + def BPL(self, operand_address): if not self.sign_flag: self.cycles += 1 self.program_counter = operand_address - + def BVC(self, operand_address): if not self.overflow_flag: self.cycles += 1 self.program_counter = operand_address - + def BVS(self, operand_address): if self.overflow_flag: self.cycles += 1 self.program_counter = operand_address - + # SET / CLEAR FLAGS - + def CLC(self): self.carry_flag = 0 - + def CLD(self): self.decimal_mode_flag = 0 - + def CLI(self): self.interrupt_disable_flag = 0 - + def CLV(self): self.overflow_flag = 0 - + def SEC(self): self.carry_flag = 1 - + def SED(self): self.decimal_mode_flag = 1 - + def SEI(self): self.interrupt_disable_flag = 1 - + # INCREMENT / DECREMENT - + def DEC(self, operand_address): self.cycles += 2 self.write_byte(operand_address, self.update_nz(self.read_byte(operand_address) - 1)) - + def DEX(self): self.x_index = self.update_nz(self.x_index - 1) - + def DEY(self): self.y_index = self.update_nz(self.y_index - 1) - + def INC(self, operand_address): self.cycles += 2 self.write_byte(operand_address, self.update_nz(self.read_byte(operand_address) + 1)) - + def INX(self): self.x_index = self.update_nz(self.x_index + 1) - + def INY(self): self.y_index = self.update_nz(self.y_index + 1) - + # PUSH / PULL - + def PHA(self): self.cycles += 1 self.push_byte(self.accumulator) - + def PHP(self): self.cycles += 1 self.push_byte(self.status_as_byte()) - + def PLA(self): self.cycles += 2 self.accumulator = self.update_nz(self.pull_byte()) - + def PLP(self): self.cycles += 2 self.status_from_byte(self.pull_byte()) - + # LOGIC - + def AND(self, operand_address): self.accumulator = self.update_nz(self.accumulator & self.read_byte(operand_address)) - + def ORA(self, operand_address): self.accumulator = self.update_nz(self.accumulator | self.read_byte(operand_address)) - + def EOR(self, operand_address): self.accumulator = self.update_nz(self.accumulator ^ self.read_byte(operand_address)) - + # ARITHMETIC - + def ADC(self, operand_address): # @@@ doesn't handle BCD yet assert not self.decimal_mode_flag - + a2 = self.accumulator a1 = signed(a2) m2 = self.read_byte(operand_address) m1 = signed(m2) - + # twos complement addition result1 = a1 + m1 + self.carry_flag - + # unsigned addition result2 = a2 + m2 + self.carry_flag - + self.accumulator = self.update_nzc(result2) - + # perhaps this could be calculated from result2 but result1 is more intuitive self.overflow_flag = [0, 1][(result1 > 127) | (result1 < -128)] - + def SBC(self, operand_address): # @@@ doesn't handle BCD yet assert not self.decimal_mode_flag - + a2 = self.accumulator a1 = signed(a2) m2 = self.read_byte(operand_address) m1 = signed(m2) - + # twos complement subtraction result1 = a1 - m1 - [1, 0][self.carry_flag] - + # unsigned subtraction result2 = a2 - m2 - [1, 0][self.carry_flag] - + self.accumulator = self.update_nz(result2) self.carry_flag = [0, 1][(result2 >= 0)] - + # perhaps this could be calculated from result2 but result1 is more intuitive self.overflow_flag = [0, 1][(result1 > 127) | (result1 < -128)] - + # BIT - + def BIT(self, operand_address): value = self.read_byte(operand_address) self.sign_flag = ((value >> 7) % 2) # bit 7 self.overflow_flag = ((value >> 6) % 2) # bit 6 self.zero_flag = [0, 1][((self.accumulator & value) == 0)] - + # COMPARISON - + def CMP(self, operand_address): result = self.accumulator - self.read_byte(operand_address) self.carry_flag = [0, 1][(result >= 0)] self.update_nz(result) - + def CPX(self, operand_address): result = self.x_index - self.read_byte(operand_address) self.carry_flag = [0, 1][(result >= 0)] self.update_nz(result) - + def CPY(self, operand_address): result = self.y_index - self.read_byte(operand_address) self.carry_flag = [0, 1][(result >= 0)] self.update_nz(result) - + # SYSTEM - + def NOP(self): pass - + def BRK(self): self.cycles += 5 self.push_word(self.program_counter + 1) self.push_byte(self.status_as_byte()) self.program_counter = self.read_word(0xFFFE) self.break_flag = 1 - + def RTI(self): self.cycles += 4 self.status_from_byte(self.pull_byte()) self.program_counter = self.pull_word() - - + + # @@@ IRQ # @@@ NMI @@ -1225,6 +1225,6 @@ if __name__ == "__main__": sys.exit(0) mem = Memory(options) - + cpu = CPU(options, mem) cpu.run(options.bus) diff --git a/tests.py b/tests.py index 6a5d606..eba4448 100644 --- a/tests.py +++ b/tests.py @@ -3,16 +3,16 @@ from cpu6502 import Memory, CPU class TestMemory(unittest.TestCase): - + def setUp(self): self.memory = Memory(use_bus=False) - + def test_load(self): self.memory.load(0x1000, [0x01, 0x02, 0x03]) self.assertEqual(self.memory.read_byte(None, 0x1000), 0x01) self.assertEqual(self.memory.read_byte(None, 0x1001), 0x02) self.assertEqual(self.memory.read_byte(None, 0x1002), 0x03) - + def test_write(self): self.memory.write_byte(None, 0x1000, 0x11) self.memory.write_byte(None, 0x1001, 0x12) @@ -23,12 +23,12 @@ class TestMemory(unittest.TestCase): class TestLoadStoreOperations(unittest.TestCase): - + def setUp(self): self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) self.memory.load(0x1000, [0x00, 0x01, 0x7F, 0x80, 0xFF]) - + def test_LDA(self): self.cpu.LDA(0x1000) self.assertEqual(self.cpu.accumulator, 0x00) @@ -50,7 +50,7 @@ class TestLoadStoreOperations(unittest.TestCase): self.assertEqual(self.cpu.accumulator, 0xFF) self.assertEqual(self.cpu.sign_flag, 1) self.assertEqual(self.cpu.zero_flag, 0) - + def test_LDX(self): self.cpu.LDX(0x1000) self.assertEqual(self.cpu.x_index, 0x00) @@ -72,7 +72,7 @@ class TestLoadStoreOperations(unittest.TestCase): self.assertEqual(self.cpu.x_index, 0xFF) self.assertEqual(self.cpu.sign_flag, 1) self.assertEqual(self.cpu.zero_flag, 0) - + def test_LDY(self): self.cpu.LDY(0x1000) self.assertEqual(self.cpu.y_index, 0x00) @@ -94,17 +94,17 @@ class TestLoadStoreOperations(unittest.TestCase): self.assertEqual(self.cpu.y_index, 0xFF) self.assertEqual(self.cpu.sign_flag, 1) self.assertEqual(self.cpu.zero_flag, 0) - + def test_STA(self): self.cpu.accumulator = 0x37 self.cpu.STA(0x2000) self.assertEqual(self.memory.read_byte(None, 0x2000), 0x37) - + def test_STX(self): self.cpu.x_index = 0x38 self.cpu.STX(0x2000) self.assertEqual(self.memory.read_byte(None, 0x2000), 0x38) - + def test_STY(self): self.cpu.y_index = 0x39 self.cpu.STY(0x2000) @@ -112,11 +112,11 @@ class TestLoadStoreOperations(unittest.TestCase): class TestRegisterTransferOperations(unittest.TestCase): - + def setUp(self): self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) - + def test_TAX(self): self.cpu.accumulator = 0x00 self.cpu.TAX() @@ -133,7 +133,7 @@ class TestRegisterTransferOperations(unittest.TestCase): self.assertEqual(self.cpu.x_index, 0xFF) self.assertEqual(self.cpu.sign_flag, 1) self.assertEqual(self.cpu.zero_flag, 0) - + def test_TAY(self): self.cpu.accumulator = 0x00 self.cpu.TAY() @@ -150,7 +150,7 @@ class TestRegisterTransferOperations(unittest.TestCase): self.assertEqual(self.cpu.y_index, 0xFF) self.assertEqual(self.cpu.sign_flag, 1) self.assertEqual(self.cpu.zero_flag, 0) - + def test_TXA(self): self.cpu.x_index = 0x00 self.cpu.TXA() @@ -167,7 +167,7 @@ class TestRegisterTransferOperations(unittest.TestCase): self.assertEqual(self.cpu.accumulator, 0xFF) self.assertEqual(self.cpu.sign_flag, 1) self.assertEqual(self.cpu.zero_flag, 0) - + def test_TYA(self): self.cpu.y_index = 0x00 self.cpu.TYA() @@ -187,22 +187,22 @@ class TestRegisterTransferOperations(unittest.TestCase): class TestStackOperations(unittest.TestCase): - + def setUp(self): self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) - + def test_TSX(self): s = self.cpu.stack_pointer self.cpu.TSX() self.assertEqual(self.cpu.x_index, s) # @@@ check NZ? - + def test_TXS(self): x = self.cpu.x_index self.cpu.TXS() self.assertEqual(self.cpu.stack_pointer, x) - + def test_PHA_and_PLA(self): self.cpu.accumulator = 0x00 self.cpu.PHA() @@ -225,7 +225,7 @@ class TestStackOperations(unittest.TestCase): self.assertEqual(self.cpu.accumulator, 0x00) self.assertEqual(self.cpu.zero_flag, 1) self.assertEqual(self.cpu.sign_flag, 0) - + def test_PHP_and_PLP(self): p = self.cpu.status_as_byte() self.cpu.PHP() @@ -235,11 +235,11 @@ class TestStackOperations(unittest.TestCase): class TestLogicalOperations(unittest.TestCase): - + def setUp(self): self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) - + def test_AND(self): self.memory.write_byte(None, 0x1000, 0x37) self.cpu.accumulator = 0x34 @@ -252,7 +252,7 @@ class TestLogicalOperations(unittest.TestCase): self.assertEqual(self.cpu.accumulator, 0x00) self.assertEqual(self.cpu.zero_flag, 1) self.assertEqual(self.cpu.sign_flag, 0) - + def test_EOR(self): self.memory.write_byte(None, 0x1000, 0x37) self.cpu.accumulator = 0x34 @@ -270,7 +270,7 @@ class TestLogicalOperations(unittest.TestCase): self.assertEqual(self.cpu.accumulator, 0x00) self.assertEqual(self.cpu.zero_flag, 1) self.assertEqual(self.cpu.sign_flag, 0) - + def test_ORA(self): self.memory.write_byte(None, 0x1000, 0x37) self.cpu.accumulator = 0x34 @@ -288,7 +288,7 @@ class TestLogicalOperations(unittest.TestCase): self.assertEqual(self.cpu.accumulator, 0x00) self.assertEqual(self.cpu.zero_flag, 1) self.assertEqual(self.cpu.sign_flag, 0) - + def test_BIT(self): self.memory.write_byte(None, 0x1000, 0x00) self.cpu.accumulator = 0x00 @@ -323,15 +323,15 @@ class TestLogicalOperations(unittest.TestCase): class TestArithmeticOperations(unittest.TestCase): - + def setUp(self): self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) - + def test_ADC_without_BCD(self): - + ## test cases from http://www.6502.org/tutorials/vflag.html - + # 1 + 1 = 2 (C = 0; V = 0) self.cpu.carry_flag = 0 self.cpu.accumulator = 0x01 @@ -340,7 +340,7 @@ class TestArithmeticOperations(unittest.TestCase): self.assertEqual(self.cpu.accumulator, 0x02) self.assertEqual(self.cpu.carry_flag, 0) self.assertEqual(self.cpu.overflow_flag, 0) - + # 1 + -1 = 0 (C = 1; V = 0) self.cpu.carry_flag = 0 self.cpu.accumulator = 0x01 @@ -349,7 +349,7 @@ class TestArithmeticOperations(unittest.TestCase): self.assertEqual(self.cpu.accumulator, 0x00) self.assertEqual(self.cpu.carry_flag, 1) self.assertEqual(self.cpu.overflow_flag, 0) - + # 127 + 1 = 128 (C = 0; V = 1) self.cpu.carry_flag = 0 self.cpu.accumulator = 0x7F @@ -358,7 +358,7 @@ class TestArithmeticOperations(unittest.TestCase): self.assertEqual(self.cpu.accumulator, 0x80) # @@@ self.assertEqual(self.cpu.carry_flag, 0) self.assertEqual(self.cpu.overflow_flag, 1) - + # -128 + -1 = -129 (C = 1; V = 1) self.cpu.carry_flag = 0 self.cpu.accumulator = 0x80 @@ -367,7 +367,7 @@ class TestArithmeticOperations(unittest.TestCase): self.assertEqual(self.cpu.accumulator, 0x7F) # @@@ self.assertEqual(self.cpu.carry_flag, 1) self.assertEqual(self.cpu.overflow_flag, 1) - + # 63 + 64 + 1 = 128 (C = 0; V = 1) self.cpu.carry_flag = 1 self.cpu.accumulator = 0x3F @@ -376,7 +376,7 @@ class TestArithmeticOperations(unittest.TestCase): self.assertEqual(self.cpu.accumulator, 0x80) self.assertEqual(self.cpu.carry_flag, 0) self.assertEqual(self.cpu.overflow_flag, 1) - + def test_SBC_without_BCD(self): self.cpu.accumulator = 0x02 self.memory.write_byte(None, 0x1000, 0x01) @@ -384,16 +384,16 @@ class TestArithmeticOperations(unittest.TestCase): self.assertEqual(self.cpu.accumulator, 0x00) self.assertEqual(self.cpu.carry_flag, 1) self.assertEqual(self.cpu.overflow_flag, 0) - + self.cpu.accumulator = 0x01 self.memory.write_byte(None, 0x1000, 0x02) self.cpu.SBC(0x1000) self.assertEqual(self.cpu.accumulator, 0xFF) self.assertEqual(self.cpu.carry_flag, 0) self.assertEqual(self.cpu.overflow_flag, 0) # @@@ - + ## test cases from http://www.6502.org/tutorials/vflag.html - + # 0 - 1 = -1 (V = 0) self.cpu.carry_flag = 1 self.cpu.accumulator = 0x00 @@ -402,7 +402,7 @@ class TestArithmeticOperations(unittest.TestCase): self.assertEqual(self.cpu.accumulator, 0xFF) self.assertEqual(self.cpu.carry_flag, 0) self.assertEqual(self.cpu.overflow_flag, 0) # @@@ - + # -128 - 1 = -129 (V = 1) self.cpu.carry_flag = 1 self.cpu.accumulator = 0x80 @@ -411,7 +411,7 @@ class TestArithmeticOperations(unittest.TestCase): self.assertEqual(self.cpu.accumulator, 0x7F) self.assertEqual(self.cpu.carry_flag, 1) self.assertEqual(self.cpu.overflow_flag, 1) - + # 127 - -1 = 128 (V = 1) self.cpu.carry_flag = 1 self.cpu.accumulator = 0x7F @@ -420,7 +420,7 @@ class TestArithmeticOperations(unittest.TestCase): self.assertEqual(self.cpu.accumulator, 0x80) self.assertEqual(self.cpu.carry_flag, 0) self.assertEqual(self.cpu.overflow_flag, 1) - + # -64 -64 -1 = -129 (V = 1) self.cpu.carry_flag = 0 self.cpu.accumulator = 0xC0 @@ -429,9 +429,9 @@ class TestArithmeticOperations(unittest.TestCase): self.assertEqual(self.cpu.accumulator, 0x7F) self.assertEqual(self.cpu.carry_flag, 1) self.assertEqual(self.cpu.overflow_flag, 1) # @@@ - + ## @@@ BCD versions still to do - + def test_CMP(self): self.cpu.accumulator = 0x0A self.memory.write_byte(None, 0x1000, 0x09) @@ -439,35 +439,35 @@ class TestArithmeticOperations(unittest.TestCase): self.assertEqual(self.cpu.sign_flag, 0) self.assertEqual(self.cpu.zero_flag, 0) self.assertEqual(self.cpu.carry_flag, 1) - + self.cpu.accumulator = 0x0A self.memory.write_byte(None, 0x1000, 0x0B) self.cpu.CMP(0x1000) self.assertEqual(self.cpu.sign_flag, 1) self.assertEqual(self.cpu.zero_flag, 0) self.assertEqual(self.cpu.carry_flag, 0) - + self.cpu.accumulator = 0x0A self.memory.write_byte(None, 0x1000, 0x0A) self.cpu.CMP(0x1000) self.assertEqual(self.cpu.sign_flag, 0) self.assertEqual(self.cpu.zero_flag, 1) self.assertEqual(self.cpu.carry_flag, 1) - + self.cpu.accumulator = 0xA0 self.memory.write_byte(None, 0x1000, 0x0A) self.cpu.CMP(0x1000) self.assertEqual(self.cpu.sign_flag, 1) self.assertEqual(self.cpu.zero_flag, 0) self.assertEqual(self.cpu.carry_flag, 1) - + self.cpu.accumulator = 0x0A self.memory.write_byte(None, 0x1000, 0xA0) self.cpu.CMP(0x1000) self.assertEqual(self.cpu.sign_flag, 0) # @@@ self.assertEqual(self.cpu.zero_flag, 0) self.assertEqual(self.cpu.carry_flag, 0) - + def test_CPX(self): self.cpu.x_index = 0x0A self.memory.write_byte(None, 0x1000, 0x09) @@ -475,35 +475,35 @@ class TestArithmeticOperations(unittest.TestCase): self.assertEqual(self.cpu.sign_flag, 0) self.assertEqual(self.cpu.zero_flag, 0) self.assertEqual(self.cpu.carry_flag, 1) - + self.cpu.x_index = 0x0A self.memory.write_byte(None, 0x1000, 0x0B) self.cpu.CPX(0x1000) self.assertEqual(self.cpu.sign_flag, 1) self.assertEqual(self.cpu.zero_flag, 0) self.assertEqual(self.cpu.carry_flag, 0) - + self.cpu.x_index = 0x0A self.memory.write_byte(None, 0x1000, 0x0A) self.cpu.CPX(0x1000) self.assertEqual(self.cpu.sign_flag, 0) self.assertEqual(self.cpu.zero_flag, 1) self.assertEqual(self.cpu.carry_flag, 1) - + self.cpu.x_index = 0xA0 self.memory.write_byte(None, 0x1000, 0x0A) self.cpu.CPX(0x1000) self.assertEqual(self.cpu.sign_flag, 1) self.assertEqual(self.cpu.zero_flag, 0) self.assertEqual(self.cpu.carry_flag, 1) - + self.cpu.x_index = 0x0A self.memory.write_byte(None, 0x1000, 0xA0) self.cpu.CPX(0x1000) self.assertEqual(self.cpu.sign_flag, 0) # @@@ self.assertEqual(self.cpu.zero_flag, 0) self.assertEqual(self.cpu.carry_flag, 0) - + def test_CPY(self): self.cpu.y_index = 0x0A self.memory.write_byte(None, 0x1000, 0x09) @@ -511,28 +511,28 @@ class TestArithmeticOperations(unittest.TestCase): self.assertEqual(self.cpu.sign_flag, 0) self.assertEqual(self.cpu.zero_flag, 0) self.assertEqual(self.cpu.carry_flag, 1) - + self.cpu.y_index = 0x0A self.memory.write_byte(None, 0x1000, 0x0B) self.cpu.CPY(0x1000) self.assertEqual(self.cpu.sign_flag, 1) self.assertEqual(self.cpu.zero_flag, 0) self.assertEqual(self.cpu.carry_flag, 0) - + self.cpu.y_index = 0x0A self.memory.write_byte(None, 0x1000, 0x0A) self.cpu.CPY(0x1000) self.assertEqual(self.cpu.sign_flag, 0) self.assertEqual(self.cpu.zero_flag, 1) self.assertEqual(self.cpu.carry_flag, 1) - + self.cpu.y_index = 0xA0 self.memory.write_byte(None, 0x1000, 0x0A) self.cpu.CPY(0x1000) self.assertEqual(self.cpu.sign_flag, 1) self.assertEqual(self.cpu.zero_flag, 0) self.assertEqual(self.cpu.carry_flag, 1) - + self.cpu.y_index = 0x0A self.memory.write_byte(None, 0x1000, 0xA0) self.cpu.CPY(0x1000) @@ -542,11 +542,11 @@ class TestArithmeticOperations(unittest.TestCase): class TestIncrementDecrementOperations(unittest.TestCase): - + def setUp(self): self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) - + def test_INC(self): self.memory.write_byte(None, 0x1000, 0x00) self.cpu.INC(0x1000) @@ -563,7 +563,7 @@ class TestIncrementDecrementOperations(unittest.TestCase): self.assertEqual(self.memory.read_byte(None, 0x1000), 0x00) self.assertEqual(self.cpu.sign_flag, 0) self.assertEqual(self.cpu.zero_flag, 1) - + def test_INX(self): self.cpu.x_index = 0x00 self.cpu.INX() @@ -580,7 +580,7 @@ class TestIncrementDecrementOperations(unittest.TestCase): self.assertEqual(self.cpu.x_index, 0x00) self.assertEqual(self.cpu.sign_flag, 0) self.assertEqual(self.cpu.zero_flag, 1) - + def test_INY(self): self.cpu.y_index = 0x00 self.cpu.INY() @@ -597,7 +597,7 @@ class TestIncrementDecrementOperations(unittest.TestCase): self.assertEqual(self.cpu.y_index, 0x00) self.assertEqual(self.cpu.sign_flag, 0) self.assertEqual(self.cpu.zero_flag, 1) - + def test_DEC(self): self.memory.write_byte(None, 0x1000, 0x01) self.cpu.DEC(0x1000) @@ -614,7 +614,7 @@ class TestIncrementDecrementOperations(unittest.TestCase): self.assertEqual(self.memory.read_byte(None, 0x1000), 0xFF) self.assertEqual(self.cpu.sign_flag, 1) self.assertEqual(self.cpu.zero_flag, 0) - + def test_DEX(self): self.cpu.x_index = 0x01 self.cpu.DEX() @@ -631,7 +631,7 @@ class TestIncrementDecrementOperations(unittest.TestCase): self.assertEqual(self.cpu.x_index, 0xFF) self.assertEqual(self.cpu.sign_flag, 1) self.assertEqual(self.cpu.zero_flag, 0) - + def test_DEY(self): self.cpu.y_index = 0x01 self.cpu.DEY() @@ -651,11 +651,11 @@ class TestIncrementDecrementOperations(unittest.TestCase): class TestShiftOperations(unittest.TestCase): - + def setUp(self): self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) - + def test_ASL(self): self.cpu.accumulator = 0x01 self.cpu.ASL() @@ -675,7 +675,7 @@ class TestShiftOperations(unittest.TestCase): self.assertEqual(self.cpu.sign_flag, 0) self.assertEqual(self.cpu.zero_flag, 1) self.assertEqual(self.cpu.carry_flag, 1) - + def test_LSR(self): self.cpu.accumulator = 0x01 self.cpu.LSR() @@ -695,7 +695,7 @@ class TestShiftOperations(unittest.TestCase): self.assertEqual(self.cpu.sign_flag, 0) self.assertEqual(self.cpu.zero_flag, 0) self.assertEqual(self.cpu.carry_flag, 0) - + def test_ROL(self): self.cpu.carry_flag = 0 self.cpu.accumulator = 0x80 @@ -725,7 +725,7 @@ class TestShiftOperations(unittest.TestCase): self.assertEqual(self.cpu.sign_flag, 0) self.assertEqual(self.cpu.zero_flag, 0) # @@@ self.assertEqual(self.cpu.carry_flag, 1) - + def test_ROR(self): self.cpu.carry_flag = 0 self.cpu.accumulator = 0x01 @@ -758,29 +758,29 @@ class TestShiftOperations(unittest.TestCase): class TestJumpCallOperations(unittest.TestCase): - + def setUp(self): self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) - + def test_JMP(self): self.cpu.JMP(0x1000) self.assertEqual(self.cpu.program_counter, 0x1000) - + def test_JSR(self): self.cpu.program_counter = 0x1000 self.cpu.JSR(0x2000) self.assertEqual(self.cpu.program_counter, 0x2000) self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 1), 0xFF) self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 2), 0x0F) - + def test_RTS(self): self.memory.write_byte(None, self.cpu.STACK_PAGE + 0xFF, 0x12) self.memory.write_byte(None, self.cpu.STACK_PAGE + 0xFE, 0x33) self.cpu.stack_pointer = 0xFD self.cpu.RTS() self.assertEqual(self.cpu.program_counter, 0x1234) - + def test_JSR_and_RTS(self): self.cpu.program_counter = 0x1000 self.cpu.JSR(0x2000) @@ -790,11 +790,11 @@ class TestJumpCallOperations(unittest.TestCase): class TestBranchOperations(unittest.TestCase): - + def setUp(self): self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) - + def test_BCC(self): self.cpu.program_counter = 0x1000 self.cpu.carry_flag = 1 @@ -804,7 +804,7 @@ class TestBranchOperations(unittest.TestCase): self.cpu.carry_flag = 0 self.cpu.BCC(0x2000) self.assertEqual(self.cpu.program_counter, 0x2000) - + def test_BCS(self): self.cpu.program_counter = 0x1000 self.cpu.carry_flag = 0 @@ -814,7 +814,7 @@ class TestBranchOperations(unittest.TestCase): self.cpu.carry_flag = 1 self.cpu.BCS(0x2000) self.assertEqual(self.cpu.program_counter, 0x2000) - + def test_BEQ(self): self.cpu.program_counter = 0x1000 self.cpu.zero_flag = 0 @@ -824,7 +824,7 @@ class TestBranchOperations(unittest.TestCase): self.cpu.zero_flag = 1 self.cpu.BEQ(0x2000) self.assertEqual(self.cpu.program_counter, 0x2000) - + def test_BMI(self): self.cpu.program_counter = 0x1000 self.cpu.sign_flag = 0 @@ -834,7 +834,7 @@ class TestBranchOperations(unittest.TestCase): self.cpu.sign_flag = 1 self.cpu.BMI(0x2000) self.assertEqual(self.cpu.program_counter, 0x2000) - + def test_BNE(self): self.cpu.program_counter = 0x1000 self.cpu.zero_flag = 1 @@ -844,7 +844,7 @@ class TestBranchOperations(unittest.TestCase): self.cpu.zero_flag = 0 self.cpu.BNE(0x2000) self.assertEqual(self.cpu.program_counter, 0x2000) - + def test_BPL(self): self.cpu.program_counter = 0x1000 self.cpu.sign_flag = 1 @@ -854,7 +854,7 @@ class TestBranchOperations(unittest.TestCase): self.cpu.sign_flag = 0 self.cpu.BPL(0x2000) self.assertEqual(self.cpu.program_counter, 0x2000) - + def test_BVC(self): self.cpu.program_counter = 0x1000 self.cpu.overflow_flag = 1 @@ -864,7 +864,7 @@ class TestBranchOperations(unittest.TestCase): self.cpu.overflow_flag = 0 self.cpu.BVC(0x2000) self.assertEqual(self.cpu.program_counter, 0x2000) - + def test_BVS(self): self.cpu.program_counter = 0x1000 self.cpu.overflow_flag = 0 @@ -877,41 +877,41 @@ class TestBranchOperations(unittest.TestCase): class TestStatusFlagOperations(unittest.TestCase): - + def setUp(self): self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) - + def test_CLC(self): self.cpu.carry_flag = 1 self.cpu.CLC() self.assertEqual(self.cpu.carry_flag, 0) - + def test_CLD(self): self.cpu.decimal_mode_flag = 1 self.cpu.CLD() self.assertEqual(self.cpu.decimal_mode_flag, 0) - + def test_CLI(self): self.cpu.interrupt_disable_flag = 1 self.cpu.CLI() self.assertEqual(self.cpu.interrupt_disable_flag, 0) - + def test_CLV(self): self.cpu.overflow_flag = 1 self.cpu.CLV() self.assertEqual(self.cpu.overflow_flag, 0) - + def test_SEC(self): self.cpu.carry_flag = 0 self.cpu.SEC() self.assertEqual(self.cpu.carry_flag, 1) - + def test_SED(self): self.cpu.decimal_mode_flag = 0 self.cpu.SED() self.assertEqual(self.cpu.decimal_mode_flag, 1) - + def test_SEI(self): self.cpu.interrupt_disable_flag = 0 self.cpu.SEI() @@ -919,11 +919,11 @@ class TestStatusFlagOperations(unittest.TestCase): class TestSystemFunctionOperations(unittest.TestCase): - + def setUp(self): self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) - + def test_BRK(self): self.cpu.program_counter = 0x1000 self.memory.rom.load(0xFFFE, [0x00, 0x20]) @@ -934,7 +934,7 @@ class TestSystemFunctionOperations(unittest.TestCase): self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 1), status) self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 2), 0x01) self.assertEqual(self.memory.read_byte(None, self.cpu.STACK_PAGE + self.cpu.stack_pointer + 3), 0x10) - + def test_RTI(self): self.memory.write_byte(None, self.cpu.STACK_PAGE + 0xFF, 0x12) self.memory.write_byte(None, self.cpu.STACK_PAGE + 0xFE, 0x33) @@ -943,17 +943,17 @@ class TestSystemFunctionOperations(unittest.TestCase): self.cpu.RTI() self.assertEqual(self.cpu.program_counter, 0x1233) self.assertEqual(self.cpu.status_as_byte(), 0x20) - + def test_NOP(self): self.cpu.NOP() class Test6502Bugs(unittest.TestCase): - + def setUp(self): self.memory = Memory(use_bus=False) self.cpu = CPU(self.memory) - + def test_zero_page_x(self): self.cpu.x_index = 0x01 self.memory.load(0x1000, [0x00, 0x7F, 0xFF]) @@ -961,7 +961,7 @@ class Test6502Bugs(unittest.TestCase): self.assertEqual(self.cpu.zero_page_x_mode(), 0x01) self.assertEqual(self.cpu.zero_page_x_mode(), 0x80) self.assertEqual(self.cpu.zero_page_x_mode(), 0x00) - + def test_indirect(self): self.memory.load(0x20, [0x00, 0x20]) self.memory.load(0x00, [0x12]) @@ -971,29 +971,29 @@ class Test6502Bugs(unittest.TestCase): self.memory.load(0x2000, [0x05]) self.memory.load(0x1234, [0x05]) self.memory.load(0x2345, [0x00, 0xF0]) - + self.cpu.program_counter = 0x1000 - + self.cpu.x_index = 0x00 self.cpu.LDA(self.cpu.indirect_x_mode()) self.assertEqual(self.cpu.accumulator, 0x05) - + self.cpu.y_index = 0x00 self.cpu.LDA(self.cpu.indirect_y_mode()) self.assertEqual(self.cpu.accumulator, 0x05) - + self.cpu.y_index = 0x00 self.cpu.LDA(self.cpu.indirect_y_mode()) self.assertEqual(self.cpu.accumulator, 0x05) - + self.cpu.x_index = 0x00 self.cpu.LDA(self.cpu.indirect_x_mode()) self.assertEqual(self.cpu.accumulator, 0x05) - + self.cpu.x_index = 0xFF self.cpu.LDA(self.cpu.indirect_x_mode()) self.assertEqual(self.cpu.accumulator, 0x05) - + self.assertEqual(self.cpu.indirect_mode(), 0xF000)