diff --git a/src/bin/main.rs b/src/bin/main.rs index 4ecd8c1..535a448 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,6 +1,9 @@ use rmg_001::render::start_eventloop; +use rmg_001::emulator::Emulator; fn main() -> std::io::Result<()> { start_eventloop(); + /* let mut emulator = Emulator::new(); + emulator.cpu_loop(); */ Ok(()) } diff --git a/src/bus.rs b/src/bus.rs index bd53f41..cc2d21c 100644 --- a/src/bus.rs +++ b/src/bus.rs @@ -59,10 +59,10 @@ pub struct Bus { impl Bus { pub fn new() -> Self { - // let game_rom = match ROM::load_file("ignore/dr-mario.gb".to_string()) { + let game_rom = match ROM::load_file("ignore/tetris.gb".to_string()) { // let game_rom = match ROM::load_file("roms/cpu_instrs.gb".to_string()) { // let game_rom = match ROM::load_file("roms/cpu_instrs_individual/01-special.gb".to_string()) { - let game_rom = match ROM::load_file("roms/cpu_instrs_individual/02-interrupts.gb".to_string()) { + // let game_rom = match ROM::load_file("roms/cpu_instrs_individual/02-interrupts.gb".to_string()) { // let game_rom = match ROM::load_file("roms/cpu_instrs_individual/03-op sp,hl.gb".to_string()) { // let game_rom = match ROM::load_file("roms/cpu_instrs_individual/04-op r,imm.gb".to_string()) { // let game_rom = match ROM::load_file("roms/cpu_instrs_individual/05-op rp.gb".to_string()) { @@ -77,6 +77,7 @@ impl Bus { _ => panic!("Could not read ROM"), }; let mut data = [0x00; 0x10000]; + // Hardware registers after the bootrom data[0xFF00] = 0b11001111; data[0xFF01] = 0x00; data[0xFF02] = 0x7E; @@ -122,10 +123,6 @@ impl Bus { // print!("{}", data as char); } - if address == 0xFF06 { - println!("Writing {:02X} to modulo", data); - } - if BANK_ZERO.in_range(address) || BANK_SWITCHABLE.in_range(address) { // println!("WRITING TO ROM"); } else if WORK_RAM_1.in_range(address) || WORK_RAM_2.in_range(address) { @@ -138,7 +135,6 @@ impl Bus { self.data[address as usize] = data; self.data[(WORK_RAM_1.begin() + (address - ECHO_RAM.begin())) as usize] = data; // Copy to the working RAM } else if address == TIMER_DIVIDER_REGISTER_ADDRESS { - println!("bus timer reset"); self.reset_timer = true; } else if address == LCD_CONTROL_ADDRESS && get_bit(data, BitIndex::I7) { self.data[address as usize] = data; diff --git a/src/cpu.rs b/src/cpu.rs index ad40e5c..b598e05 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -914,19 +914,17 @@ impl CPU { println!("Interrupt: {:?}", interrupt); bus.set_interrupt_flag(interrupt, false); self.ime = false; + self.registers.decrement(Register::PC, 3); self.exec(Opcode::CALL(OpcodeParameter::U16(interrupt.get_vector())), bus); } pub fn check_interrupts(&mut self, bus: &mut Bus) -> Option { - /* println!("IE {:08b}", bus.read(INTERRUPT_ENABLE_ADDRESS)); - println!("IF {:08b}", bus.read(INTERRUPT_FLAG_ADDRESS)); - println!("---"); */ - if !self.ime && !self.is_halted { - return None; - } if bus.read(INTERRUPT_ENABLE_ADDRESS) & bus.read(INTERRUPT_FLAG_ADDRESS) != 0 { self.is_halted = false; } + if !self.ime { + return None; + } if bus.get_interrupt(Interrupt::VBlank) { return Some(Interrupt::VBlank); @@ -942,6 +940,14 @@ impl CPU { None } + pub fn ei_delay(&mut self, bus: &mut Bus) { + if self.ei_delay && !self.ime { + self.ei_delay = false; + self.run(bus); + self.ime = true; + } + } + pub fn run(&mut self, bus: &mut Bus) { let cycles_start = self.get_cycles(); if let Some(interrupt) = self.check_interrupts(bus) { @@ -953,15 +959,11 @@ impl CPU { let (opcode, cycles) = parameter_bytes.parse_opcode(); if !env::var("CPU_LOG").is_err() { self.log(parameter_bytes); + self.increment_exec_calls_count(); } self.increment_cycles(cycles); self.exec(opcode, bus); - if self.ei_delay && !self.ime { - println!("EI delay"); - self.ei_delay = false; - self.run(bus); - self.ime = true; - } + self.ei_delay(bus); } else if self.is_halted { self.increment_cycles(Cycles(1)); } @@ -1789,7 +1791,6 @@ impl CPU { }, // Enable interrupts Opcode::EI => { - println!("EI"); self.registers.increment(Register::PC, 1); self.ei_delay = true; }, diff --git a/src/emulator.rs b/src/emulator.rs index 6e65acd..747f97b 100644 --- a/src/emulator.rs +++ b/src/emulator.rs @@ -118,6 +118,10 @@ impl Emulator { } self.ppu.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles()); self.timer.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles()); + + // 1 CPU cycle = 238.42ns + // thread::sleep(time::Duration::from_nanos((self.cpu.get_last_op_cycles().0 * 238).try_into().unwrap())); + } } @@ -125,8 +129,15 @@ impl Emulator { let mut exit = false; while !exit { self.cpu.run(&mut self.bus); + if self.bus.reset_timer { + self.bus.reset_timer = false; + self.timer.reset(&mut self.bus); + } + self.ppu.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles()); + self.timer.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles()); // exit = self.cpu.get_exec_calls_count() >= 1258895; // log 1 + exit = self.cpu.get_exec_calls_count() >= 161502; // log 2 // exit = self.cpu.get_exec_calls_count() >= 1068422; // log 3 // exit = self.cpu.get_exec_calls_count() >= 1262766; // log 4 // exit = self.cpu.get_exec_calls_count() >= 1763388; // log 5 diff --git a/src/timer.rs b/src/timer.rs index bdfdcdf..05bf168 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -25,7 +25,6 @@ impl Timer { } pub fn reset(&mut self, bus: &mut Bus) { - println!("timer reset"); self.divider = 0; bus.force_write(TIMER_DIVIDER_REGISTER_ADDRESS, 0); } @@ -49,7 +48,6 @@ impl Timer { if tima == 0 { bus.write(TIMER_COUNTER_ADDRESS, bus.read(TIMER_MODULO_ADDRESS)); bus.set_interrupt_flag(Interrupt::Timer, true); - println!("Timer interrupt set"); } else { bus.write(TIMER_COUNTER_ADDRESS, tima); }