fix: properly implement LY==LYC behaviour

This commit is contained in:
Rekai Nyangadzayi Musuka 2021-05-05 08:29:39 -05:00
parent b36f4441fa
commit abdff1251e
3 changed files with 35 additions and 22 deletions

View File

@ -245,7 +245,7 @@ impl Bus {
0xFF00 => self.joypad.status.update(byte),
0xFF01 => self.serial.next = byte,
0xFF02 => self.serial.control = byte.into(),
0xFF04 => self.timer.divider = 0x00,
0xFF04 => self.timer.divider = 0x0000,
0xFF05 => self.timer.counter = byte,
0xFF06 => self.timer.modulo = byte,
0xFF07 => self.timer.control = byte.into(),
@ -258,7 +258,7 @@ impl Bus {
0xFF25 => self.sound.control.output = byte.into(),
0xFF26 => self.sound.control.status = byte.into(), // FIXME: Should we control which bytes are written to here?
0xFF40 => self.ppu.control = byte.into(),
0xFF41 => self.ppu.stat = byte.into(),
0xFF41 => self.ppu.stat.update(byte),
0xFF42 => self.ppu.pos.scroll_y = byte,
0xFF43 => self.ppu.pos.scroll_x = byte,
0xFF44 => self.ppu.pos.line_y = byte,
@ -267,9 +267,12 @@ impl Bus {
self.ppu.pos.ly_compare = byte;
// Update Coincidence Flag
if self.ppu.stat.coincidence_int() {
let are_equal = self.ppu.pos.line_y == byte;
self.ppu.stat.set_coincidence(are_equal);
// If enabled, request a LCD STAT interrupt
if self.ppu.stat.coincidence_int() && are_equal {
self.ppu.int.set_lcd_stat(true);
}
}
0xFF47 => self.ppu.monochrome.bg_palette = byte.into(),

View File

@ -103,10 +103,13 @@ impl Ppu {
self.cycles %= 456;
self.pos.line_y += 1;
// New Scanline is next, check for LYC=LY
if self.stat.coincidence_int() {
// Update LY==LYC bit
let are_equal = self.pos.line_y == self.pos.ly_compare;
self.stat.set_coincidence(are_equal);
// Request LCD STAT interrupt if conditions met
if self.stat.coincidence_int() && are_equal {
self.int.set_lcd_stat(true);
}
let next_mode = if self.pos.line_y >= 144 {
@ -140,10 +143,13 @@ impl Ppu {
self.cycles %= 456;
self.pos.line_y += 1;
// New Scanline is next, check for LYC=LY
if self.stat.coincidence_int() {
// Update LY==LYC bit
let are_equal = self.pos.line_y == self.pos.ly_compare;
self.stat.set_coincidence(are_equal);
// Request LCD STAT interrupt if conditions met
if self.stat.coincidence_int() && are_equal {
self.int.set_lcd_stat(true);
}
if self.pos.line_y == 154 {
@ -687,8 +693,8 @@ impl PixelFetcher {
let id = self.bg.tile.id.expect("Tile Number unexpectedly missing");
let tile_data_addr = match control.tile_data_addr() {
TileDataAddress::X8800 => 0x9000u16.wrapping_add((id as i8 * 16) as u16),
TileDataAddress::X8000 => 0x8000 + (id as u16 * 16),
TileDataAddress::X8800 => 0x9000u16.wrapping_add((id as i8).wrapping_mul(16) as u16),
TileDataAddress::X8000 => 0x8000 + (id as u16).wrapping_mul(16),
};
let offset = 2 * if window {
@ -737,7 +743,7 @@ impl PixelFetcher {
(line_y + scroll_y) % 8
};
0x8000 + (attr.tile_index as u16 * 16) + offset as u16
0x8000 + (tile_number as u16 * 16) + offset as u16
}
}

View File

@ -13,6 +13,16 @@ bitfield! {
pub from into PpuMode, mode, set_mode: 1, 0;
}
impl LCDStatus {
pub fn update(&mut self, byte: u8) {
// Bytes 2 -> 0 are read only
let mask = 0b00000111;
let read_only = self.0 & mask;
self.0 = (byte & !mask) | read_only;
}
}
impl Copy for LCDStatus {}
impl Clone for LCDStatus {
fn clone(&self) -> Self {
@ -26,12 +36,6 @@ impl Default for LCDStatus {
}
}
impl From<u8> for LCDStatus {
fn from(byte: u8) -> Self {
Self(byte)
}
}
impl From<LCDStatus> for u8 {
fn from(status: LCDStatus) -> Self {
status.0