def test_nesttest(expected): nes = Bus() cart = Cartridge('nestest.nes') nes.insert_cartridge(cart) nes.cpu_write(0xFFFC, 0x00) nes.reset() assert nes.cpu_read(0xFFFC) == 0x00 assert nes.cpu_read(0xFFFd) == 0xC0 while True: nes.clock() if nes.cpu.complete(): break mock_cpu = CPU(nes) results = {} cycle_errors = 0 test_line_count = len(expected) print(f'\n### Nestest lines={test_line_count} ###') for index, expected_line in enumerate(expected): mock_cpu.reset() pc = nes.cpu.state.pc a = nes.cpu.state.a & 0xFF x = nes.cpu.state.x y = nes.cpu.state.y p = nes.cpu.state.status sp = nes.cpu.state.stkp cycle_count = nes.cpu.state.clock_count ppu_cycle = nes.ppu._cycle ppu_scanline = nes.ppu._scanline opcode = nes.cpu.cpu_read(pc) mock_cpu.state.pc += 1 instruction = nes.cpu.OPCODES[opcode] instruction.addr_mode(mock_cpu) address = create_address_line(nes, mock_cpu, instruction) op_name = f'{instruction.name} {address}' op_bytes = f'{opcode:02X}' for data in mock_cpu.fetches: op_bytes += f' {data:02X}' ns = '*' if instruction.is_non_standard else ' ' result = (f'{pc:04X} {op_bytes:<9}{ns}{op_name:<32}A:{a:02X} ' f'X:{x:02X} Y:{y:02X} P:{p:02X} SP:{sp:02X} ' f'PPU:{ppu_scanline:>3},{ppu_cycle:>3} CYC:{cycle_count}') results[index] = result if not result[:78] == expected_line[:78]: print_context(results, index, expected_line, 25) mock_cpu.state.print_flags() if result[78:] != expected_line[78:]: cycle_errors += 1 error_msg = f'Line {index + 1} did not match the expected result!' assert result[:78] == expected_line[:78], error_msg # assert result == expected_line # strict (includes cycles, scanline and clock) try: clock(nes) except TypeError: msg = f'Operator {instruction.operate.__name__} not implemented!' print(red(msg)) print_context(results, index, expected_line) raise UserWarning(msg) error_1 = nes.cpu_read(0x0002) error_2 = nes.cpu_read(0x0003) msg = f'Error codes: 0x02 = 0x{error_1:02X} 0x03 = 0x{error_2:02X} (nestest.txt)' assert error_1 == 0x00 and error_2 == 0x00, msg print(f'Total number of cycle errors: {cycle_errors}')
from cartridge import Cartridge if __name__ == '__main__': nes = Bus() # cart = Cartridge('tests/nestest.nes') cart = Cartridge('roms/donkeykong.nes') # cart = Cartridge('roms/smb.nes') # cart = Cartridge('roms/ducktales.nes') nes.insert_cartridge(cart) nes.reset() frame_count = 20 now = time.time() while True: nes.clock() if nes.ppu.frame_count == frame_count: break diff = time.time() - now print('------------') print(f'Ran for {frame_count} frames.') print(f'Running time: {diff:.{2}f} seconds') print(f'Frames per second: {frame_count / diff:.{3}f} FPS') print(f'Quality (60 FPS expected): {(frame_count / diff) / 60:.{2}f}') # Best so far: # 2020-10-06 # Ran for 20 frames. # Running time: 9.36 seconds # Frames per second: 2.138 FPS