feat: implement LCDSTAT interrupt
This commit is contained in:
parent
c64417fdce
commit
5a42d76f1e
11
src/bus.rs
11
src/bus.rs
|
@ -223,7 +223,16 @@ impl Bus {
|
|||
0xFF42 => self.ppu.pos.scroll_y = byte,
|
||||
0xFF43 => self.ppu.pos.scroll_x = byte,
|
||||
0xFF44 => self.ppu.pos.line_y = byte,
|
||||
0xFF45 => self.ppu.pos.ly_compare = byte == 0x01, // FIXME: We don't consider the possibility of a byte being different form 0x00 or 0x01
|
||||
0xFF45 => {
|
||||
// Update LYC
|
||||
self.ppu.pos.ly_compare = byte;
|
||||
|
||||
// Update Coincidence Flag
|
||||
if self.ppu.stat.coincidence_intr() {
|
||||
let are_equal = self.ppu.pos.line_y == byte;
|
||||
self.ppu.stat.set_coincidence(are_equal);
|
||||
}
|
||||
}
|
||||
0xFF47 => self.ppu.monochrome.bg_palette = byte.into(),
|
||||
0xFF48 => self.ppu.monochrome.obj_palette_0 = byte.into(),
|
||||
0xFF49 => self.ppu.monochrome.obj_palette_1 = byte.into(),
|
||||
|
|
16
src/cpu.rs
16
src/cpu.rs
|
@ -76,24 +76,9 @@ impl Cpu {
|
|||
pub fn step(&mut self) -> Cycles {
|
||||
let opcode = self.fetch();
|
||||
let instr = self.decode(opcode);
|
||||
|
||||
// println!(
|
||||
// "Addr: {:#06X} | Opcode: {:#04X} | Instr: {:X?}",
|
||||
// self.reg.pc, opcode, instr
|
||||
// );
|
||||
|
||||
let cycles = self.execute(instr);
|
||||
|
||||
// if self.bus.read_byte(0xFF02) == 0x81 {
|
||||
// let c = self.bus.read_byte(0xFF01) as char;
|
||||
// self.bus.write_byte(0xFF02, 0x00);
|
||||
|
||||
// print!("{}", c);
|
||||
// std::io::stdout().flush().unwrap();
|
||||
// }
|
||||
|
||||
self.bus.step(cycles);
|
||||
|
||||
self.handle_interrupts();
|
||||
|
||||
cycles
|
||||
|
@ -188,7 +173,6 @@ impl Cpu {
|
|||
|
||||
// Disable all future interrupts
|
||||
self.set_ime(false);
|
||||
|
||||
self.execute(Instruction::CALL(Always, register))
|
||||
}
|
||||
None => Cycles::new(0), // NO Interrupts were enabled and / or requested
|
||||
|
|
34
src/ppu.rs
34
src/ppu.rs
|
@ -39,9 +39,6 @@ impl Ppu {
|
|||
pub fn step(&mut self, cycles: Cycles) {
|
||||
self.cycles += cycles;
|
||||
|
||||
// let tmp: u32 = self.cycles.into();
|
||||
// println!("Mode: {:?} | Cycles: {}", self.mode, tmp);
|
||||
|
||||
match self.stat.mode() {
|
||||
Mode::OamScan => {
|
||||
if self.cycles >= 80.into() {
|
||||
|
@ -59,6 +56,10 @@ impl Ppu {
|
|||
if self.cycles >= 172.into() {
|
||||
self.cycles %= 172;
|
||||
|
||||
if self.stat.hblank_intr() {
|
||||
self.interrupt.set_lcd_stat(true);
|
||||
}
|
||||
|
||||
self.stat.set_mode(Mode::HBlank);
|
||||
self.draw_scanline();
|
||||
}
|
||||
|
@ -71,12 +72,26 @@ impl Ppu {
|
|||
|
||||
let next_mode = if self.pos.line_y >= 144 {
|
||||
self.interrupt.set_vblank(true);
|
||||
|
||||
if self.stat.vblank_intr() {
|
||||
self.interrupt.set_lcd_stat(true);
|
||||
}
|
||||
|
||||
Mode::VBlank
|
||||
} else {
|
||||
if self.stat.oam_intr() {
|
||||
self.interrupt.set_lcd_stat(true);
|
||||
}
|
||||
|
||||
Mode::OamScan
|
||||
};
|
||||
|
||||
self.stat.set_mode(next_mode);
|
||||
|
||||
if self.stat.coincidence_intr() {
|
||||
let are_equal = self.pos.line_y == self.pos.ly_compare;
|
||||
self.stat.set_coincidence(are_equal);
|
||||
}
|
||||
}
|
||||
}
|
||||
Mode::VBlank => {
|
||||
|
@ -90,6 +105,11 @@ impl Ppu {
|
|||
self.stat.set_mode(Mode::OamScan);
|
||||
self.pos.line_y = 0;
|
||||
}
|
||||
|
||||
if self.stat.coincidence_intr() {
|
||||
let are_equal = self.pos.line_y == self.pos.ly_compare;
|
||||
self.stat.set_coincidence(are_equal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -192,11 +212,11 @@ impl Interrupt {
|
|||
bitfield! {
|
||||
pub struct LCDStatus(u8);
|
||||
impl Debug;
|
||||
pub lyc_ly_intr, set_lyc_ly_intr: 6;
|
||||
pub coincidence_intr, set_coincidence_intr: 6;
|
||||
pub oam_intr, set_oam_intr: 5;
|
||||
pub vblank_intr, set_vblank_intr: 4;
|
||||
pub hblank_intr, set_hblank_intr: 3;
|
||||
pub coincidence, _: 2; // LYC == LY Flag
|
||||
pub coincidence, set_coincidence: 2; // LYC == LY Flag
|
||||
from into Mode, _mode, set_mode: 1, 0;
|
||||
}
|
||||
|
||||
|
@ -215,7 +235,7 @@ impl Clone for LCDStatus {
|
|||
|
||||
impl Default for LCDStatus {
|
||||
fn default() -> Self {
|
||||
Self(0)
|
||||
Self(0x80) // bit 7 is always 1
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -268,7 +288,7 @@ pub struct ScreenPosition {
|
|||
pub scroll_y: u8,
|
||||
pub scroll_x: u8,
|
||||
pub line_y: u8,
|
||||
pub ly_compare: bool,
|
||||
pub ly_compare: u8,
|
||||
pub window_y: u8,
|
||||
pub window_x: u8,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue