mirror of
https://github.com/FranLMSP/rmg-001.git
synced 2024-11-23 10:12:11 +00:00
Interrupts tests passing
This commit is contained in:
parent
806a4bf211
commit
659f602b2a
@ -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(())
|
||||
}
|
||||
|
10
src/bus.rs
10
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;
|
||||
|
27
src/cpu.rs
27
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<Interrupt> {
|
||||
/* 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;
|
||||
},
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user