mod cpu_reset_ram; mod instr_test_v3; mod ppu; mod interrupts; macro_rules! rom_test { ($name:ident, $rom:literal, |$nes:ident| $eval:expr) => { rom_test!($name, $rom, timeout = 10000000, |$nes| $eval); }; ($name:ident, $rom:literal, timeout = $timeout:expr, |$nes:ident| $eval:expr) => { #[test] fn $name() { let rom_file = concat!(env!("ROM_DIR"), "/", $rom); println!("{}: {}", stringify!($name), rom_file); let mut $nes = crate::NES::load_nes_file(rom_file).expect("Failed to create nes object"); $nes.reset_and_run_with_timeout($timeout); println!("Final: {:?}", $nes); $eval } }; ($name:ident, . $rom:literal, |$nes:ident| $eval:expr) => { rom_test!($name, . $rom, timeout = 10000000, |$nes| $eval); }; ($name:ident, . $rom:literal, timeout = $timeout:expr, |$nes:ident| $eval:expr) => { #[test] fn $name() { let rom_file = $rom; println!("{}: {}", stringify!($name), rom_file); let mut $nes = crate::NES::load_nes_file(rom_file).expect("Failed to create nes object"); $nes.reset_and_run_with_timeout($timeout); println!("Final: {:?}", $nes); $eval } }; } pub(crate) use rom_test; rom_test!(basic_cpu, "basic-cpu.nes", |nes| { assert_eq!(nes.last_instruction(), "0x8001 HLT :2 []"); assert_eq!(nes.cpu_cycle(), 10); assert_eq!(nes.cpu.pc, 0x8001); assert_eq!(nes.ppu.pixel, 34); assert_eq!(nes.cpu.sp, 0xFD); nes.repl_nop(); nes.run_with_timeout(200); assert_eq!(nes.last_instruction(), "0x8002 HLT :2 []"); assert_eq!(nes.cpu_cycle(), 12); assert_eq!(nes.cpu.pc, 0x8002); assert_eq!(nes.ppu.pixel, 40); assert_eq!(nes.cpu.sp, 0xFD); }); rom_test!(basic_cpu_with_nop, "basic-cpu-nop.nes", |nes| { assert_eq!(nes.last_instruction(), "0x8002 HLT :2 []"); assert_eq!(nes.cpu_cycle(), 12); assert_eq!(nes.cpu.pc, 0x8002); assert_eq!(nes.ppu.pixel, 40); assert_eq!(nes.cpu.sp, 0xFD); }); rom_test!(read_write, "read_write.nes", |nes| { assert_eq!(nes.last_instruction(), "0x800C HLT :2 []"); assert_eq!(nes.cpu_cycle(), 25); assert_eq!(nes.cpu.pc, 0x800C); assert_eq!(nes.cpu.sp, 0xFD); assert_eq!(nes.cpu.a, 0xAA); assert_eq!(nes.cpu.x, 0xAA); assert_eq!(nes.cpu.y, 0xAA); assert_eq!(nes.mem().peek_cpu(0x0000).unwrap(), 0xAA); assert_eq!(nes.mem().peek_cpu(0x0001).unwrap(), 0xAA); assert_eq!(nes.mem().peek_cpu(0x0002).unwrap(), 0xAA); }); rom_test!(basic_init_0, "basic_init_0.nes", |nes| { assert_eq!(nes.last_instruction(), "0x8017 HLT :2 []"); assert_eq!(nes.cpu_cycle(), 40); assert_eq!(nes.cpu.pc, 0x8017); assert_eq!(nes.cpu.sp, 0xFF); assert_eq!(nes.cpu.a, 0x00); assert_eq!(nes.cpu.x, 0x00); assert_eq!(nes.cpu.y, 0x00); }); rom_test!(basic_init_1, "basic_init_1.nes", |nes| { assert_eq!(nes.last_instruction(), "0x801C HLT :2 []"); assert_eq!(nes.cpu_cycle(), 27402); assert_eq!(nes.cpu.pc, 0x801C); assert_eq!(nes.ppu.pixel, 29); assert_eq!(nes.cpu.sp, 0xFF); assert_eq!(nes.cpu.a, 0x00); assert_eq!(nes.cpu.x, 0x00); assert_eq!(nes.cpu.y, 0x00); }); rom_test!(basic_init_2, "basic_init_2.nes", |nes| { assert_eq!(nes.last_instruction(), "0x8021 HLT :2 []"); assert_eq!(nes.cpu_cycle(), 57179); assert_eq!(nes.cpu.pc, 0x8021); assert_eq!(nes.ppu.pixel, 18); assert_eq!(nes.cpu.sp, 0xFF); assert_eq!(nes.cpu.a, 0x00); assert_eq!(nes.cpu.x, 0x00); assert_eq!(nes.cpu.y, 0x00); }); rom_test!(basic_init_3, "basic_init_3.nes", |nes| { assert_eq!(nes.last_instruction(), "0x8026 HLT :2 []"); assert_eq!(nes.cpu_cycle(), 86963); assert_eq!(nes.cpu.pc, 0x8026); assert_eq!(nes.ppu.pixel, 28); assert_eq!(nes.cpu.sp, 0xFF); assert_eq!(nes.cpu.a, 0x00); assert_eq!(nes.cpu.x, 0x00); assert_eq!(nes.cpu.y, 0x00); }); rom_test!(even_odd, "even_odd.nes", |nes| { assert_eq!(nes.last_instruction(), "0x8023 HLT :2 []"); assert_eq!(nes.cpu_cycle(), 57181); assert_eq!(nes.cpu.pc, 0x8023); assert_eq!(nes.ppu.pixel, 24); assert_eq!(nes.cpu.sp, 0xFF); assert_eq!(nes.cpu.a, 0x00); assert_eq!(nes.cpu.x, 0x08); assert_eq!(nes.cpu.y, 0x00); }); // rom_test!(even_odd, "even_odd.nes", |nes| { // assert_eq!(nes.last_instruction(), "0x8023 HLT :2 []"); // assert_eq!(nes.cpu_cycle(), 57182); // assert_eq!(nes.cpu.pc, 0x8024); // assert_eq!(nes.ppu.pixel, 25); // assert_eq!(nes.cpu.sp, 0xFF); // assert_eq!(nes.cpu.a, 0x00); // assert_eq!(nes.cpu.x, 0x08); // assert_eq!(nes.cpu.y, 0x00); // });