def loadAssembly(self): # Enable/Disable actions self.actionLoad.setEnabled(False) self.actionRun.setEnabled(True) self.actionPause.setEnabled(True) self.actionStep.setEnabled(True) self.actionStop.setEnabled(True) editor = self.asmEdit editor.setReadOnly() assembly = editor.toPlainText() if not assembly: self.console.appendPlainText("Input Error.") self.restoreEditor() return self.assembler = Assembler(SEG_INIT) self.exe_file = self.assembler.compile(assembly) self.memory = Memory(MEMORY_SIZE, SEGMENT_SIZE) self.memory.load(self.exe_file) # load code segment self.BIU = bus_interface_unit.bus_interface_unit(INSTRUCTION_QUEUE_SIZE, self.exe_file, self.memory) self.EU = execution_unit.execution_unit(self.BIU, True) self.cpu = CPU(self.BIU, self.EU, gui_mode=True) self.refreshModels() self.console.appendPlainText("Initial DS: " + hex(self.BIU.reg['DS'])) self.console.appendPlainText("Initial CS: " + hex(self.BIU.reg['CS'])) self.console.appendPlainText("Initial SS: " + hex(self.BIU.reg['SS'])) self.console.appendPlainText("Initial ES: " + hex(self.BIU.reg['ES'])) self.console.appendPlainText("Initial IP: " + hex(self.BIU.reg['IP'])) self.console.appendPlainText("\nCPU initialized successfully.") self.console.appendPlainText("=" * 60 + '\n')
def test_write_Absolute(): address_mode = Absolute cpu = CPU() memory = Memory(rom=[0x30, 0x01, 0xFF, 0x02, 0x0A, 0x05], ram=list(map(lambda x: x % 256, range(Memory.ram_size())))) cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start) address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 50) assert address == 0x0130 assert memory.ram[address] == 50 assert cpu.cycle == 3 cpu.inc_cycle_by(-cpu.cycle) address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 100) assert address == 0x02FF assert memory.ram[address] == 100 assert cpu.cycle == 3 cpu.inc_cycle_by(-cpu.cycle) address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 67) assert address == 0x050A assert memory.ram[address] == 67 assert cpu.cycle == 3
def test_read_Absolute(): address_mode = Absolute cpu = CPU() memory = Memory(rom=[0x32, 0x02, 0x7F, 0x01, 0xFF, 0x07], ram=list(map(lambda x: x % 256, range(Memory.ram_size())))) cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start) address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 0x0232 assert value == (0x0232 % 256) assert cpu.cycle == 3 cpu.inc_cycle_by(-cpu.cycle) address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 0x017F assert value == (0x017F % 256) assert cpu.cycle == 3 cpu.inc_cycle_by(-cpu.cycle) address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 0x07FF assert value == (0x07FF % 256) assert cpu.cycle == 3
def test_TYA(): cpu = CPU() memory = Memory() cpu.a = 1 cpu.y = 2 TYA = OpCodes.all[152] TYA.exec(cpu, memory) assert cpu.a == 2 assert cpu.zero == False assert cpu.negative == False cpu.y = 0 cpu.a = 1 cpu.inc_cycle_by(-cpu.cycle) TYA.exec(cpu, memory) assert cpu.cycle == (TYA.cycles - 1) assert cpu.a == 0 assert cpu.zero == True assert cpu.negative == False cpu.y = 0b10000001 cpu.a = 1 TYA.exec(cpu, memory) assert cpu.a == 0b10000001 assert cpu.zero == False print(cpu.negative) assert cpu.negative == True
def test_TAY(): cpu = CPU() memory = Memory() cpu.y = 1 cpu.a = 2 TAY = OpCodes.all[168] TAY.exec(cpu, memory) assert cpu.y == 2 assert cpu.zero == False assert cpu.negative == False cpu.a = 0 cpu.y = 1 cpu.inc_cycle_by(-cpu.cycle) TAY.exec(cpu, memory) assert cpu.cycle == (TAY.cycles - 1) assert cpu.y == 0 assert cpu.zero == True assert cpu.negative == False cpu.a = 0b10000001 cpu.y = 1 TAY.exec(cpu, memory) assert cpu.y == 0b10000001 assert cpu.zero == False print(cpu.negative) assert cpu.negative == True
def test_DEY_within_bounds(): instruction = OpCodes.all[0x88] cpu = CPU() memory = Memory() cpu.inc_cycle_by(-cpu.cycle) cpu.y = 7 instruction.exec(cpu, memory) assert cpu.cycle == (instruction.cycles - 1) assert cpu.y == 6 assert cpu.zero == False assert cpu.negative == False
def test_read_IndirectY(): address_mode = IndirectY cpu = CPU() memory = Memory(rom=[0x00, 0x02, 0x7F, 0x01, 0xFF, 0x07], ram=list(map(lambda x: x % 256, range(Memory.ram_size())))) cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start) cpu.y = 4 address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 0x0104 assert value == address % 256 cpu.inc_cycle_by(-cpu.cycle) cpu.y = 0xFF address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 0x0401 assert value == address % 256
def test_write_IndirectY(): address_mode = IndirectY cpu = CPU() memory = Memory(rom=[0x00, 0x02, 0x7F, 0x01, 0xFF, 0x07], ram=list(map(lambda x: x % 256, range(Memory.ram_size())))) cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start) cpu.y = 4 address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 9) assert address == 0x0104 assert memory.ram[address] == 9 cpu.inc_cycle_by(-cpu.cycle) cpu.y = 0xFF address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 50) assert address == 0x0401 assert memory.ram[address] == 50
def test_read_IndirectX(): address_mode = IndirectX cpu = CPU() memory = Memory(rom=[0x00, 0x02, 0x7F, 0x01, 0xFF, 0x07], ram=list(map(lambda x: x % 256, range(Memory.ram_size())))) cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start) cpu.x = 4 address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == (((0x0504 + 1) % 256) << 8 | (0x0504 % 256)) assert value == address % 256 assert cpu.cycle == 5 cpu.inc_cycle_by(-cpu.cycle) cpu.x = 0xFF address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == (((0x0201 + 1) % 256) << 8 | (0x0201 % 256)) assert value == address % 256 assert cpu.cycle == 5
def test_Indirect(): address_mode = Indirect cpu = CPU() memory = Memory(rom=[0x32, 0x02, 0x7F, 0x01, 0xFF, 0x07], ram=list(map(lambda x: x % 256, range(Memory.ram_size())))) cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start) address = address_mode.fetch_address(cpu, memory) assert address == (((0x0232 + 1) % 256) << 8 | (0x0232 % 256)) assert cpu.cycle == 4 cpu.inc_cycle_by(-cpu.cycle) address = address_mode.fetch_address(cpu, memory) assert address == (((0x017F + 1) % 256) << 8 | (0x017F % 256)) assert cpu.cycle == 4 cpu.inc_cycle_by(-cpu.cycle) address = address_mode.fetch_address(cpu, memory) assert address == (((0x07FF + 1) % 256) << 8 | (0x07FF % 256)) assert cpu.cycle == 4
def __init__(self, qApp=None): self.gui = uic.loadUi(_resource('mainwindow.ui')) # Assembly editor get focus on start self.asmEdit = self.gui.findChild(CodeEditor, "asmEdit") # Get console area self.console = self.gui.findChild(QPlainTextEdit, "txtConsole") self.assembler = Assembler(SEG_INIT) self.memory = Memory(MEMORY_SIZE, SEGMENT_SIZE) self.asmEdit.setPlainText(open(_resource('default.asm')).read()) self.BIU = bus_interface_unit.bus_interface_unit(INSTRUCTION_QUEUE_SIZE, self.assembler, self.memory) self.EU = execution_unit.execution_unit(self.BIU, int_msg=True) self.cpu = CPU(self.BIU, self.EU, gui_mode=True) self.emitter = Emitter(self.emitStart) self.emitter.refresh.connect(self.refreshModels) self.setupEditorAndDiagram() self.setupSplitters() self.setupModels() self.setupTrees() self.setupActions() self.gui.showMaximized()
def test_DEY_negative(): instruction = OpCodes.all[0x88] cpu = CPU() memory = Memory() cpu.inc_cycle_by(-cpu.cycle) cpu.y = 0 instruction.exec(cpu, memory) assert cpu.cycle == (instruction.cycles - 1) assert cpu.y == 255 assert cpu.zero == False assert cpu.negative == True cpu.inc_cycle_by(-cpu.cycle) cpu.y = -1 instruction.exec(cpu, memory) assert cpu.cycle == (instruction.cycles - 1) assert cpu.y == 254 assert cpu.zero == False assert cpu.negative == True
def test_DEX_zero(): instruction = OpCodes.all[0xCA] cpu = CPU() memory = Memory() cpu.inc_cycle_by(-cpu.cycle) cpu.x = 1 instruction.exec(cpu, memory) assert cpu.cycle == (instruction.cycles - 1) assert cpu.x == 0 assert cpu.zero == True assert cpu.negative == False cpu.inc_cycle_by(-cpu.cycle) cpu.x = 257 instruction.exec(cpu, memory) assert cpu.cycle == (instruction.cycles - 1) assert cpu.x == 0 assert cpu.zero == True assert cpu.negative == False
def main(): help = ''' Usage: python main.py ./tests/Requirement/bubble_sort.asm -i python main.py ./tests/Interrupt/show_date_time.asm -n 注:-i表示打印中断信息,-n表示禁用debug。tests文件夹内含有大量测试用例 可以参考文档,自行编写汇编语言程序来运行。 ''' DEBUG = True # 是否单步运行 INT_MSG = False # 是否打印中断信息 try: opts,args = getopt.getopt(sys.argv[2:],'-h-n-i',['help','nodebug','interrupt']) for opt_name,opt_value in opts: if opt_name in ('-h','--help'): print(help) exit() if opt_name in ('-n', '--nodebug'): DEBUG = False if opt_name in ('-i', '--interrupt'): INT_MSG = True with open(sys.argv[1], 'r', encoding='utf-8') as file: asm_code = file.read() except: print(help) sys.exit("Parameter incorrect") assembler = Assembler(SEG_INIT) exe_file = assembler.compile(asm_code) memory = Memory(MEMORY_SIZE, SEGMENT_SIZE) memory.load(exe_file) # load code segment BIU = bus_interface_unit.bus_interface_unit(INSTRUCTION_QUEUE_SIZE, exe_file, memory) EU = execution_unit.execution_unit(BIU, INT_MSG) cpu = CPU(BIU, EU, gui_mode=False) print("\nCPU initialized successfully.") print("=" * 80) while not cpu.check_done(): cpu.iterate(debug=DEBUG) cpu.print_end_state()
def emulate(file_path): nestest_log_format = args.nestest automation_mode = args.automation running = True file_contents = read_file(file_path) cartridge = Cartridge.from_bytes(file_contents) ppu = PPU(cartridge.chr_rom, mirroring=cartridge.header.flags_6&0b00000001) memory = Memory(cartridge.prg_rom,ppu=ppu) cpu = CPU(log_compatible_mode=nestest_log_format) ppu.setNMI(cpu,memory,NMI) reset_pos_low = memory.fetch(MemoryPositions.RESET.start) reset_pos_high = memory.fetch(MemoryPositions.RESET.end) reset_pos = MemoryPositions.PRG_ROM_START.wrap( AddressMode.get_16_bits_addr_from_high_low((reset_pos_high << 8) & HIGH_BITS_MASK, reset_pos_low & LOW_BITS_MASK)) cpu.pc = reset_pos if nestest_log_format: # hack for Nintendulator nestest log comparison cpu.flags = 0x24 cpu.inc_cycle_by(7) if automation_mode: cpu.pc = MemoryPositions.PRG_ROM_START.start i = 0 line = 0 while running: try: previous_state = CPUState(pc=cpu.pc, sp=cpu.sp, a=cpu.a, x=cpu.x, y=cpu.y, p=StatusRegisterFlags(int_value=cpu.flags), addr=cpu.addr, data=cpu.data, cycle=cpu.cycle, log_compatible_mode=nestest_log_format) if previous_state.pc == 0xC66E: # TODO: remove, this is a breakpoint for debugging aaaa = "" ppu.reloadControllers()#reloads controllers every tick i+=1 if (i==114): ppu.scanLine(line) i=0 line+=1 if line==262: line=0 decoded = cpu.exec_in_cycle(fetch_and_decode_instruction, cpu, memory) # fetching and decoding a instruction always take 1 cycle if decoded: decoded.exec(cpu, memory) if isinstance(decoded, BRK): # abort program on BRK running = False print("Break") break #print_debug_line(cpu, previous_state, decoded, nestest_log_format) cpu.clear_state_mem() except IndexError as e: # we've reached a program counter that is not within memory bounds print(e) running = False except KeyError as e: # print("Can't find instruction by code {}".format(e)) cpu.inc_pc_by(1) except Exception as e: print(e) cpu.inc_pc_by(1)
class MainWindow(object): def __init__(self, qApp=None): self.gui = uic.loadUi(_resource('mainwindow.ui')) # Assembly editor get focus on start self.asmEdit = self.gui.findChild(CodeEditor, "asmEdit") # Get console area self.console = self.gui.findChild(QPlainTextEdit, "txtConsole") self.assembler = Assembler(SEG_INIT) self.memory = Memory(MEMORY_SIZE, SEGMENT_SIZE) self.asmEdit.setPlainText(open(_resource('default.asm')).read()) self.BIU = bus_interface_unit.bus_interface_unit(INSTRUCTION_QUEUE_SIZE, self.assembler, self.memory) self.EU = execution_unit.execution_unit(self.BIU, int_msg=True) self.cpu = CPU(self.BIU, self.EU, gui_mode=True) self.emitter = Emitter(self.emitStart) self.emitter.refresh.connect(self.refreshModels) self.setupEditorAndDiagram() self.setupSplitters() self.setupModels() self.setupTrees() self.setupActions() self.gui.showMaximized() def setupEditorAndDiagram(self): # self.asmEdit = QPlainTextEdit() self.asmEdit.setFocus() self.asmEdit.setStyleSheet("""QPlainTextEdit{ font-family: 'Hack NF'; font-weight: bold; font-size: 11pt; color: #ccc; background-color: #282828;}""") self.highlight = AssemblyHighlighter(self.asmEdit.document()) def setupSplitters(self): mainsplitter = self.gui.findChild(QSplitter, "mainsplitter") mainsplitter.setStretchFactor(0, 3) mainsplitter.setStretchFactor(1, 3) mainsplitter.setStretchFactor(2, 16) mainsplitter.setStretchFactor(3, 4) mainsplitter.setStretchFactor(4, 3) leftsplitter = self.gui.findChild(QSplitter, "leftsplitter") leftsplitter.setStretchFactor(0, 8) leftsplitter.setStretchFactor(1, 5) leftsplitter.setStretchFactor(2, 9) middlesplitter = self.gui.findChild(QSplitter, "middlesplitter") middlesplitter.setStretchFactor(0, 2) middlesplitter.setStretchFactor(1, 1) def setupModels(self): self.genRegsModel = RegistersModel(self.cpu.EU, ( 'AX', 'BX', 'CX', 'DX', 'SP', 'BP', 'SI', 'DI', )) self.specRegsModel = RegistersModel(self.cpu.BIU, ( 'DS', 'CS', 'SS', 'ES', 'IP', )) self.stateRegsModel = FlagModel(self.cpu.EU, ( 'CF', 'PF', 'AF', 'Z', 'S', 'O', 'TF', 'IF', 'DF', )) self.CodeSegModel = CodeSegModel(self.BIU, self.BIU.reg['IP']) self.StackSegModel = StackSegModel(self.BIU, self.EU.reg['SP']) self.DataSegModel = DataSegModel(self.BIU) def setupTrees(self): treeGenericRegs = self.gui.findChild(QTreeView, "treeGenericRegs") treeGenericRegs.setModel(self.genRegsModel) treeGenericRegs.expandAll() treeGenericRegs.resizeColumnToContents(0) treeGenericRegs.resizeColumnToContents(1) treeSpecificRegs = self.gui.findChild(QTreeView, "treeSpecificRegs") treeSpecificRegs.setModel(self.specRegsModel) treeSpecificRegs.expandAll() treeSpecificRegs.resizeColumnToContents(0) treeSpecificRegs.resizeColumnToContents(1) treeStateRegs = self.gui.findChild(QTreeView, "treeStateRegs") treeStateRegs.setModel(self.stateRegsModel) treeStateRegs.expandAll() treeStateRegs.resizeColumnToContents(0) treeStateRegs.resizeColumnToContents(1) # memory self.treeMemory = self.gui.findChild(QTreeView, "treeMemory") treeMemory = self.treeMemory treeMemory.setModel(self.CodeSegModel) treeMemory.resizeColumnToContents(0) treeMemory.resizeColumnToContents(1) self.treeMemory2 = self.gui.findChild(QTreeView, "treeMemory2") treeMemory2 = self.treeMemory2 treeMemory2.setModel(self.StackSegModel) treeMemory2.resizeColumnToContents(0) treeMemory2.resizeColumnToContents(1) self.treeMemory3 = self.gui.findChild(QTreeView, "treeMemory3") treeMemory3 = self.treeMemory3 treeMemory3.setModel(self.DataSegModel) treeMemory3.resizeColumnToContents(0) treeMemory3.resizeColumnToContents(1) def setupActions(self): self.actionNew = self.gui.findChild(QAction, "actionNew") self.actionNew.triggered.connect(self.newAction) self.actionOpen = self.gui.findChild(QAction, "actionOpen") self.actionOpen.triggered.connect(self.openAction) self.actionSave = self.gui.findChild(QAction, "actionSave") self.actionSave.triggered.connect(self.saveAction) self.actionLoad = self.gui.findChild(QAction, "actionLoad") self.actionLoad.triggered.connect(self.loadAssembly) self.actionRun = self.gui.findChild(QAction, "actionRun") self.actionRun.triggered.connect(self.runAction) self.actionPause = self.gui.findChild(QAction, "actionPause") self.actionPause.triggered.connect(self.pauseAction) self.actionStep = self.gui.findChild(QAction, "actionStep") self.actionStep.triggered.connect(self.nextInstruction) self.actionStop = self.gui.findChild(QAction, "actionStop") self.actionStop.triggered.connect(self.stopAction) def loadAssembly(self): # Enable/Disable actions self.actionLoad.setEnabled(False) self.actionRun.setEnabled(True) self.actionPause.setEnabled(True) self.actionStep.setEnabled(True) self.actionStop.setEnabled(True) editor = self.asmEdit editor.setReadOnly() assembly = editor.toPlainText() if not assembly: self.console.appendPlainText("Input Error.") self.restoreEditor() return self.assembler = Assembler(SEG_INIT) self.exe_file = self.assembler.compile(assembly) self.memory = Memory(MEMORY_SIZE, SEGMENT_SIZE) self.memory.load(self.exe_file) # load code segment self.BIU = bus_interface_unit.bus_interface_unit(INSTRUCTION_QUEUE_SIZE, self.exe_file, self.memory) self.EU = execution_unit.execution_unit(self.BIU, True) self.cpu = CPU(self.BIU, self.EU, gui_mode=True) self.refreshModels() self.console.appendPlainText("Initial DS: " + hex(self.BIU.reg['DS'])) self.console.appendPlainText("Initial CS: " + hex(self.BIU.reg['CS'])) self.console.appendPlainText("Initial SS: " + hex(self.BIU.reg['SS'])) self.console.appendPlainText("Initial ES: " + hex(self.BIU.reg['ES'])) self.console.appendPlainText("Initial IP: " + hex(self.BIU.reg['IP'])) self.console.appendPlainText("\nCPU initialized successfully.") self.console.appendPlainText("=" * 60 + '\n') def newAction(self): self.stopAction() self.asmEdit.setPlainText('\n'*30) self.restoreEditor() def saveAction(self): self.stopAction() filename = QFileDialog().getSaveFileName(self.gui, 'Save file', filter='*.asm', initialFilter='*.asm')[0] if os.path.exists(filename): with open(filename,'w') as f: text=self.asmEdit.toPlainText() f.write(text) def openAction(self): self.stopAction() filename = QFileDialog().getOpenFileName(self.gui, "Open File")[0] if os.path.exists(filename) and self.asmEdit.document().isModified(): answer = QMessageBox.question(self.gui, "Modified Code", """<b>The current code is modified</b> <p>What do you want to do?</p> """, QMessageBox.Discard | QMessageBox.Cancel, QMessageBox.Cancel) if answer == QMessageBox.Cancel: return if os.path.exists(filename): text = open(filename, encoding='utf-8').read() if len(text.split('\n')) < 30: text += '\n' * (30-len(text.split('\n'))) self.asmEdit.setPlainText(text) self.restoreEditor() def emitStart(self, refresh): self.cpu.EU.interrupt = False while not self.cpu.check_done(): self.cpu.iterate(debug=False) refresh.emit() time.sleep(0.1) print("Emit ended") self.actionRun.setEnabled(True) self.actionStep.setEnabled(True) self.cpu.print_end_state() refresh.emit() if self.cpu.EU.shutdown: self.cpu.EU.print("CPU Shutdown.") self.actionLoad.setEnabled(True) self.actionRun.setEnabled(False) self.actionPause.setEnabled(False) self.actionStep.setEnabled(False) self.actionStop.setEnabled(True) def runAction(self): print("run...") self.actionRun.setEnabled(False) self.actionStep.setEnabled(False) self.emitter.start() def nextInstruction(self): print("step...") self.cpu.EU.interrupt = False if not self.cpu.check_done(): self.cpu.iterate(debug=False) self.refreshModels() if self.cpu.EU.shutdown: self.cpu.print_end_state() self.restoreEditor() print("step end") def pauseAction(self): self.cpu.EU.interrupt = True self.actionRun.setEnabled(True) self.actionStep.setEnabled(True) def stopAction(self): self.pauseAction() self.restoreEditor() def restoreEditor(self): # Enable/Disable actions self.actionLoad.setEnabled(True) self.actionRun.setEnabled(False) self.actionPause.setEnabled(False) self.actionStep.setEnabled(False) self.actionStop.setEnabled(False) # Re-enable editor self.asmEdit.setReadOnly(False) self.asmEdit.setFocus() def refreshModels(self): self.console.moveCursor(self.console.textCursor().End) self.console.insertPlainText(self.cpu.EU.output) self.cpu.EU.output = '' self.setupModels() self.setupTrees() def show(self): self.gui.show()
def test_read_AbsoluteX(): address_mode = AbsoluteX cpu = CPU() memory = Memory(rom=[0x32, 0x02, 0x7F, 0x01, 0x00, 0x20], ram=list(map(lambda x: x % 256, range(Memory.ram_size())))) cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start) cpu.x = 0x0A address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 0x023C assert value == (0x023C % 256) cpu.inc_cycle_by(-cpu.cycle) cpu.x = 0xA1 address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 0x0220 assert value == (0x0220 % 256) cpu.inc_cycle_by(-cpu.cycle) cpu.x = 0x07 address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 0x2007
def test_Immediate(): address_mode = Immediate cpu = CPU() memory = Memory(rom=[0x00]) cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc) cpu.inc_pc_by(MemoryPositions.PRG_ROM_START.start) address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 0x00 assert value == 0x00 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc) cpu.inc_pc_by(MemoryPositions.PRG_ROM_START.start) memory.rom[0] = 0x10 address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 0x10 assert value == 0x10 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc) cpu.inc_pc_by(MemoryPositions.PRG_ROM_START.start) memory.rom[0] = 0xFF address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 0xFF assert value == 0xFF
def test_read_Accumulator(): address_mode = Accumulator cpu = CPU() memory = Memory() cpu.inc_cycle_by(-cpu.cycle) address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 5) assert address is None assert cpu.a == 5 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc) cpu.inc_pc_by(MemoryPositions.PRG_ROM_START.start) cpu.a = 0x10 address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 105) assert address is None assert cpu.a == 105 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc) cpu.inc_pc_by(MemoryPositions.PRG_ROM_START.start) cpu.a = 0xFF address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 255) assert address is None assert cpu.a == 255
def test_write_AbsoluteX(): address_mode = AbsoluteX cpu = CPU() memory = Memory(rom=[0x30, 0x01, 0xFF, 0x02, 0x0A, 0x05], ram=list(map(lambda x: x % 256, range(Memory.ram_size())))) cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start) cpu.x = 0x25 address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 20) assert address == 0x0155 assert memory.ram[address] == 20 cpu.inc_cycle_by(-cpu.cycle) cpu.x = 0x30 address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 100) assert address == 0x032F assert memory.ram[address] == 100 cpu.inc_cycle_by(-cpu.cycle) cpu.x = 0x20 address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 67) assert address == 0x052A assert memory.ram[address] == 67
def test_read_Accumulator(): address_mode = Accumulator cpu = CPU() memory = Memory() cpu.a = 0x00 cpu.inc_cycle_by(-cpu.cycle) address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address is None assert value == 0x00 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc) cpu.inc_pc_by(MemoryPositions.PRG_ROM_START.start) cpu.a = 0x10 address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address is None assert value == 0x10 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc) cpu.inc_pc_by(MemoryPositions.PRG_ROM_START.start) cpu.a = 0xFF address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address is None assert value == 0xFF
def test_ROR_accumulator(): instruction = OpCodes.all[0x6A] cpu = CPU() memory = Memory() cpu.inc_cycle_by(-cpu.cycle) cpu.a = 0b00000000 cpu.carry = False instruction.exec(cpu, memory) assert cpu.cycle == (instruction.cycles - 1) assert cpu.a == 0b00000000 assert cpu.zero == True assert cpu.carry == False assert cpu.negative == False cpu.inc_cycle_by(-cpu.cycle) cpu.a = 0b00000001 cpu.carry = False instruction.exec(cpu, memory) assert cpu.cycle == (instruction.cycles - 1) assert cpu.a == 0b00000000 assert cpu.zero == True assert cpu.carry == True assert cpu.negative == False cpu.inc_cycle_by(-cpu.cycle) cpu.a = 0b01000000 cpu.carry = False instruction.exec(cpu, memory) assert cpu.cycle == (instruction.cycles - 1) assert cpu.a == 0b00100000 assert cpu.zero == False assert cpu.carry == False assert cpu.negative == False cpu.inc_cycle_by(-cpu.cycle) cpu.a = 0b10000000 cpu.carry = False instruction.exec(cpu, memory) assert cpu.cycle == (instruction.cycles - 1) assert cpu.a == 0b01000000 assert cpu.zero == False assert cpu.carry == False assert cpu.negative == False cpu.inc_cycle_by(-cpu.cycle) cpu.a = 0b00000000 cpu.carry = True instruction.exec(cpu, memory) assert cpu.cycle == (instruction.cycles - 1) assert cpu.a == 0b10000000 assert cpu.zero == False assert cpu.carry == False assert cpu.negative == True cpu.inc_cycle_by(-cpu.cycle) cpu.a = 0b00000010 cpu.carry = True instruction.exec(cpu, memory) assert cpu.cycle == (instruction.cycles - 1) assert cpu.a == 0b10000001 assert cpu.zero == False assert cpu.carry == False assert cpu.negative == True cpu.inc_cycle_by(-cpu.cycle) cpu.a = 0b01000000 cpu.carry = True instruction.exec(cpu, memory) assert cpu.cycle == (instruction.cycles - 1) assert cpu.a == 0b10100000 assert cpu.zero == False assert cpu.carry == False assert cpu.negative == True cpu.inc_cycle_by(-cpu.cycle) cpu.a = 0b00000001 cpu.carry = True instruction.exec(cpu, memory) assert cpu.cycle == (instruction.cycles - 1) assert cpu.a == 0b10000000 assert cpu.zero == False assert cpu.carry == True assert cpu.negative == True
def test_read_ZeroPageX(): address_mode = ZeroPageX cpu = CPU() memory = Memory(rom=list(range(256)), ram=list(reversed(range(256)))) cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start) cpu.x = 1 address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 1 assert value == 254 assert cpu.cycle == 3 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start + 20) cpu.x = 10 address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 30 assert value == 225 assert cpu.cycle == 3 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start + 100) cpu.x = 5 address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 105 assert value == 150 assert cpu.cycle == 3 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start + 255) cpu.x = 0 address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 255 assert value == 0 assert cpu.cycle == 3 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start + 255) cpu.x = 5 address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 4 assert value == 251 assert cpu.cycle == 3
def test_read_ZeroPage(): address_mode = ZeroPage cpu = CPU() memory = Memory(rom=list(range(256)), ram=list(reversed(range(256)))) cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start) address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 0 assert value == 255 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start + 20) address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 20 assert value == 235 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start + 100) address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 100 assert value == 155 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start + 255) address = address_mode.fetch_address(cpu, memory) value = address_mode.read_from(cpu, memory, address) assert address == 255 assert value == 0
def test_write_ZeroPage(): address_mode = ZeroPage cpu = CPU() memory = Memory(rom=list(range(256))) cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start) address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 6) assert address == 0 assert memory.ram[address] == 6 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start + 20) address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 105) assert address == 20 assert memory.ram[address] == 105 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start + 100) address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 143) assert address == 100 assert memory.ram[address] == 143 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start + 255) address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 255) assert address == 255 assert memory.ram[address] == 255