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_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_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_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_write_ZeroPageX(): address_mode = ZeroPageX 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) cpu.x = 5 address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 6) assert address == 5 assert memory.ram[address] == 6 assert cpu.cycle == 3 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start + 20) cpu.x = 15 address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 105) assert address == 35 assert memory.ram[address] == 105 assert cpu.cycle == 3 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start + 100) cpu.x = 155 address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 143) assert address == 255 assert memory.ram[address] == 143 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) address_mode.write_to(cpu, memory, address, 255) assert address == 255 assert memory.ram[address] == 255 assert cpu.cycle == 3 cpu.inc_cycle_by(-cpu.cycle) cpu.inc_pc_by(-cpu.pc + MemoryPositions.PRG_ROM_START.start + 255) cpu.x = 75 address = address_mode.fetch_address(cpu, memory) address_mode.write_to(cpu, memory, address, 255) assert address == 74 assert memory.ram[address] == 255 assert cpu.cycle == 3
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_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_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_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 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)
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