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,
|
0xFF42 => self.ppu.pos.scroll_y = byte,
|
||||||
0xFF43 => self.ppu.pos.scroll_x = byte,
|
0xFF43 => self.ppu.pos.scroll_x = byte,
|
||||||
0xFF44 => self.ppu.pos.line_y = 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(),
|
0xFF47 => self.ppu.monochrome.bg_palette = byte.into(),
|
||||||
0xFF48 => self.ppu.monochrome.obj_palette_0 = byte.into(),
|
0xFF48 => self.ppu.monochrome.obj_palette_0 = byte.into(),
|
||||||
0xFF49 => self.ppu.monochrome.obj_palette_1 = 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 {
|
pub fn step(&mut self) -> Cycles {
|
||||||
let opcode = self.fetch();
|
let opcode = self.fetch();
|
||||||
let instr = self.decode(opcode);
|
let instr = self.decode(opcode);
|
||||||
|
|
||||||
// println!(
|
|
||||||
// "Addr: {:#06X} | Opcode: {:#04X} | Instr: {:X?}",
|
|
||||||
// self.reg.pc, opcode, instr
|
|
||||||
// );
|
|
||||||
|
|
||||||
let cycles = self.execute(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.bus.step(cycles);
|
||||||
|
|
||||||
self.handle_interrupts();
|
self.handle_interrupts();
|
||||||
|
|
||||||
cycles
|
cycles
|
||||||
|
@ -188,7 +173,6 @@ impl Cpu {
|
||||||
|
|
||||||
// Disable all future interrupts
|
// Disable all future interrupts
|
||||||
self.set_ime(false);
|
self.set_ime(false);
|
||||||
|
|
||||||
self.execute(Instruction::CALL(Always, register))
|
self.execute(Instruction::CALL(Always, register))
|
||||||
}
|
}
|
||||||
None => Cycles::new(0), // NO Interrupts were enabled and / or requested
|
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) {
|
pub fn step(&mut self, cycles: Cycles) {
|
||||||
self.cycles += cycles;
|
self.cycles += cycles;
|
||||||
|
|
||||||
// let tmp: u32 = self.cycles.into();
|
|
||||||
// println!("Mode: {:?} | Cycles: {}", self.mode, tmp);
|
|
||||||
|
|
||||||
match self.stat.mode() {
|
match self.stat.mode() {
|
||||||
Mode::OamScan => {
|
Mode::OamScan => {
|
||||||
if self.cycles >= 80.into() {
|
if self.cycles >= 80.into() {
|
||||||
|
@ -59,6 +56,10 @@ impl Ppu {
|
||||||
if self.cycles >= 172.into() {
|
if self.cycles >= 172.into() {
|
||||||
self.cycles %= 172;
|
self.cycles %= 172;
|
||||||
|
|
||||||
|
if self.stat.hblank_intr() {
|
||||||
|
self.interrupt.set_lcd_stat(true);
|
||||||
|
}
|
||||||
|
|
||||||
self.stat.set_mode(Mode::HBlank);
|
self.stat.set_mode(Mode::HBlank);
|
||||||
self.draw_scanline();
|
self.draw_scanline();
|
||||||
}
|
}
|
||||||
|
@ -71,12 +72,26 @@ impl Ppu {
|
||||||
|
|
||||||
let next_mode = if self.pos.line_y >= 144 {
|
let next_mode = if self.pos.line_y >= 144 {
|
||||||
self.interrupt.set_vblank(true);
|
self.interrupt.set_vblank(true);
|
||||||
|
|
||||||
|
if self.stat.vblank_intr() {
|
||||||
|
self.interrupt.set_lcd_stat(true);
|
||||||
|
}
|
||||||
|
|
||||||
Mode::VBlank
|
Mode::VBlank
|
||||||
} else {
|
} else {
|
||||||
|
if self.stat.oam_intr() {
|
||||||
|
self.interrupt.set_lcd_stat(true);
|
||||||
|
}
|
||||||
|
|
||||||
Mode::OamScan
|
Mode::OamScan
|
||||||
};
|
};
|
||||||
|
|
||||||
self.stat.set_mode(next_mode);
|
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 => {
|
Mode::VBlank => {
|
||||||
|
@ -90,6 +105,11 @@ impl Ppu {
|
||||||
self.stat.set_mode(Mode::OamScan);
|
self.stat.set_mode(Mode::OamScan);
|
||||||
self.pos.line_y = 0;
|
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! {
|
bitfield! {
|
||||||
pub struct LCDStatus(u8);
|
pub struct LCDStatus(u8);
|
||||||
impl Debug;
|
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 oam_intr, set_oam_intr: 5;
|
||||||
pub vblank_intr, set_vblank_intr: 4;
|
pub vblank_intr, set_vblank_intr: 4;
|
||||||
pub hblank_intr, set_hblank_intr: 3;
|
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;
|
from into Mode, _mode, set_mode: 1, 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +235,7 @@ impl Clone for LCDStatus {
|
||||||
|
|
||||||
impl Default for LCDStatus {
|
impl Default for LCDStatus {
|
||||||
fn default() -> Self {
|
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_y: u8,
|
||||||
pub scroll_x: u8,
|
pub scroll_x: u8,
|
||||||
pub line_y: u8,
|
pub line_y: u8,
|
||||||
pub ly_compare: bool,
|
pub ly_compare: u8,
|
||||||
pub window_y: u8,
|
pub window_y: u8,
|
||||||
pub window_x: u8,
|
pub window_x: u8,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue