fix: properly implement LY==LYC behaviour
This commit is contained in:
parent
b36f4441fa
commit
abdff1251e
|
@ -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(),
|
||||
|
|
20
src/ppu.rs
20
src/ppu.rs
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue