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::render::start_eventloop;
|
||||||
|
use rmg_001::emulator::Emulator;
|
||||||
|
|
||||||
fn main() -> std::io::Result<()> {
|
fn main() -> std::io::Result<()> {
|
||||||
start_eventloop();
|
start_eventloop();
|
||||||
|
/* let mut emulator = Emulator::new();
|
||||||
|
emulator.cpu_loop(); */
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
10
src/bus.rs
10
src/bus.rs
@ -59,10 +59,10 @@ pub struct Bus {
|
|||||||
|
|
||||||
impl Bus {
|
impl Bus {
|
||||||
pub fn new() -> Self {
|
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.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/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/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/04-op r,imm.gb".to_string()) {
|
||||||
// let game_rom = match ROM::load_file("roms/cpu_instrs_individual/05-op rp.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"),
|
_ => panic!("Could not read ROM"),
|
||||||
};
|
};
|
||||||
let mut data = [0x00; 0x10000];
|
let mut data = [0x00; 0x10000];
|
||||||
|
// Hardware registers after the bootrom
|
||||||
data[0xFF00] = 0b11001111;
|
data[0xFF00] = 0b11001111;
|
||||||
data[0xFF01] = 0x00;
|
data[0xFF01] = 0x00;
|
||||||
data[0xFF02] = 0x7E;
|
data[0xFF02] = 0x7E;
|
||||||
@ -122,10 +123,6 @@ impl Bus {
|
|||||||
// print!("{}", data as char);
|
// print!("{}", data as char);
|
||||||
}
|
}
|
||||||
|
|
||||||
if address == 0xFF06 {
|
|
||||||
println!("Writing {:02X} to modulo", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if BANK_ZERO.in_range(address) || BANK_SWITCHABLE.in_range(address) {
|
if BANK_ZERO.in_range(address) || BANK_SWITCHABLE.in_range(address) {
|
||||||
// println!("WRITING TO ROM");
|
// println!("WRITING TO ROM");
|
||||||
} else if WORK_RAM_1.in_range(address) || WORK_RAM_2.in_range(address) {
|
} 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[address as usize] = data;
|
||||||
self.data[(WORK_RAM_1.begin() + (address - ECHO_RAM.begin())) as usize] = data; // Copy to the working RAM
|
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 {
|
} else if address == TIMER_DIVIDER_REGISTER_ADDRESS {
|
||||||
println!("bus timer reset");
|
|
||||||
self.reset_timer = true;
|
self.reset_timer = true;
|
||||||
} else if address == LCD_CONTROL_ADDRESS && get_bit(data, BitIndex::I7) {
|
} else if address == LCD_CONTROL_ADDRESS && get_bit(data, BitIndex::I7) {
|
||||||
self.data[address as usize] = data;
|
self.data[address as usize] = data;
|
||||||
|
27
src/cpu.rs
27
src/cpu.rs
@ -914,19 +914,17 @@ impl CPU {
|
|||||||
println!("Interrupt: {:?}", interrupt);
|
println!("Interrupt: {:?}", interrupt);
|
||||||
bus.set_interrupt_flag(interrupt, false);
|
bus.set_interrupt_flag(interrupt, false);
|
||||||
self.ime = false;
|
self.ime = false;
|
||||||
|
self.registers.decrement(Register::PC, 3);
|
||||||
self.exec(Opcode::CALL(OpcodeParameter::U16(interrupt.get_vector())), bus);
|
self.exec(Opcode::CALL(OpcodeParameter::U16(interrupt.get_vector())), bus);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_interrupts(&mut self, bus: &mut Bus) -> Option<Interrupt> {
|
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 {
|
if bus.read(INTERRUPT_ENABLE_ADDRESS) & bus.read(INTERRUPT_FLAG_ADDRESS) != 0 {
|
||||||
self.is_halted = false;
|
self.is_halted = false;
|
||||||
}
|
}
|
||||||
|
if !self.ime {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
if bus.get_interrupt(Interrupt::VBlank) {
|
if bus.get_interrupt(Interrupt::VBlank) {
|
||||||
return Some(Interrupt::VBlank);
|
return Some(Interrupt::VBlank);
|
||||||
@ -942,6 +940,14 @@ impl CPU {
|
|||||||
None
|
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) {
|
pub fn run(&mut self, bus: &mut Bus) {
|
||||||
let cycles_start = self.get_cycles();
|
let cycles_start = self.get_cycles();
|
||||||
if let Some(interrupt) = self.check_interrupts(bus) {
|
if let Some(interrupt) = self.check_interrupts(bus) {
|
||||||
@ -953,15 +959,11 @@ impl CPU {
|
|||||||
let (opcode, cycles) = parameter_bytes.parse_opcode();
|
let (opcode, cycles) = parameter_bytes.parse_opcode();
|
||||||
if !env::var("CPU_LOG").is_err() {
|
if !env::var("CPU_LOG").is_err() {
|
||||||
self.log(parameter_bytes);
|
self.log(parameter_bytes);
|
||||||
|
self.increment_exec_calls_count();
|
||||||
}
|
}
|
||||||
self.increment_cycles(cycles);
|
self.increment_cycles(cycles);
|
||||||
self.exec(opcode, bus);
|
self.exec(opcode, bus);
|
||||||
if self.ei_delay && !self.ime {
|
self.ei_delay(bus);
|
||||||
println!("EI delay");
|
|
||||||
self.ei_delay = false;
|
|
||||||
self.run(bus);
|
|
||||||
self.ime = true;
|
|
||||||
}
|
|
||||||
} else if self.is_halted {
|
} else if self.is_halted {
|
||||||
self.increment_cycles(Cycles(1));
|
self.increment_cycles(Cycles(1));
|
||||||
}
|
}
|
||||||
@ -1789,7 +1791,6 @@ impl CPU {
|
|||||||
},
|
},
|
||||||
// Enable interrupts
|
// Enable interrupts
|
||||||
Opcode::EI => {
|
Opcode::EI => {
|
||||||
println!("EI");
|
|
||||||
self.registers.increment(Register::PC, 1);
|
self.registers.increment(Register::PC, 1);
|
||||||
self.ei_delay = true;
|
self.ei_delay = true;
|
||||||
},
|
},
|
||||||
|
@ -118,6 +118,10 @@ impl Emulator {
|
|||||||
}
|
}
|
||||||
self.ppu.do_cycles(&mut self.bus, self.cpu.get_last_op_cycles());
|
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());
|
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;
|
let mut exit = false;
|
||||||
while !exit {
|
while !exit {
|
||||||
self.cpu.run(&mut self.bus);
|
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() >= 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() >= 1068422; // log 3
|
||||||
// exit = self.cpu.get_exec_calls_count() >= 1262766; // log 4
|
// exit = self.cpu.get_exec_calls_count() >= 1262766; // log 4
|
||||||
// exit = self.cpu.get_exec_calls_count() >= 1763388; // log 5
|
// exit = self.cpu.get_exec_calls_count() >= 1763388; // log 5
|
||||||
|
@ -25,7 +25,6 @@ impl Timer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(&mut self, bus: &mut Bus) {
|
pub fn reset(&mut self, bus: &mut Bus) {
|
||||||
println!("timer reset");
|
|
||||||
self.divider = 0;
|
self.divider = 0;
|
||||||
bus.force_write(TIMER_DIVIDER_REGISTER_ADDRESS, 0);
|
bus.force_write(TIMER_DIVIDER_REGISTER_ADDRESS, 0);
|
||||||
}
|
}
|
||||||
@ -49,7 +48,6 @@ impl Timer {
|
|||||||
if tima == 0 {
|
if tima == 0 {
|
||||||
bus.write(TIMER_COUNTER_ADDRESS, bus.read(TIMER_MODULO_ADDRESS));
|
bus.write(TIMER_COUNTER_ADDRESS, bus.read(TIMER_MODULO_ADDRESS));
|
||||||
bus.set_interrupt_flag(Interrupt::Timer, true);
|
bus.set_interrupt_flag(Interrupt::Timer, true);
|
||||||
println!("Timer interrupt set");
|
|
||||||
} else {
|
} else {
|
||||||
bus.write(TIMER_COUNTER_ADDRESS, tima);
|
bus.write(TIMER_COUNTER_ADDRESS, tima);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user