fix: properly implement LY==LYC behaviour
This commit is contained in:
parent
b36f4441fa
commit
abdff1251e
13
src/bus.rs
13
src/bus.rs
|
@ -245,7 +245,7 @@ impl Bus {
|
||||||
0xFF00 => self.joypad.status.update(byte),
|
0xFF00 => self.joypad.status.update(byte),
|
||||||
0xFF01 => self.serial.next = byte,
|
0xFF01 => self.serial.next = byte,
|
||||||
0xFF02 => self.serial.control = byte.into(),
|
0xFF02 => self.serial.control = byte.into(),
|
||||||
0xFF04 => self.timer.divider = 0x00,
|
0xFF04 => self.timer.divider = 0x0000,
|
||||||
0xFF05 => self.timer.counter = byte,
|
0xFF05 => self.timer.counter = byte,
|
||||||
0xFF06 => self.timer.modulo = byte,
|
0xFF06 => self.timer.modulo = byte,
|
||||||
0xFF07 => self.timer.control = byte.into(),
|
0xFF07 => self.timer.control = byte.into(),
|
||||||
|
@ -258,7 +258,7 @@ impl Bus {
|
||||||
0xFF25 => self.sound.control.output = byte.into(),
|
0xFF25 => self.sound.control.output = byte.into(),
|
||||||
0xFF26 => self.sound.control.status = byte.into(), // FIXME: Should we control which bytes are written to here?
|
0xFF26 => self.sound.control.status = byte.into(), // FIXME: Should we control which bytes are written to here?
|
||||||
0xFF40 => self.ppu.control = byte.into(),
|
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,
|
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,
|
||||||
|
@ -267,9 +267,12 @@ impl Bus {
|
||||||
self.ppu.pos.ly_compare = byte;
|
self.ppu.pos.ly_compare = byte;
|
||||||
|
|
||||||
// Update Coincidence Flag
|
// Update Coincidence Flag
|
||||||
if self.ppu.stat.coincidence_int() {
|
let are_equal = self.ppu.pos.line_y == byte;
|
||||||
let are_equal = self.ppu.pos.line_y == byte;
|
self.ppu.stat.set_coincidence(are_equal);
|
||||||
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(),
|
0xFF47 => self.ppu.monochrome.bg_palette = byte.into(),
|
||||||
|
|
28
src/ppu.rs
28
src/ppu.rs
|
@ -103,10 +103,13 @@ impl Ppu {
|
||||||
self.cycles %= 456;
|
self.cycles %= 456;
|
||||||
self.pos.line_y += 1;
|
self.pos.line_y += 1;
|
||||||
|
|
||||||
// New Scanline is next, check for LYC=LY
|
// Update LY==LYC bit
|
||||||
if self.stat.coincidence_int() {
|
let are_equal = self.pos.line_y == self.pos.ly_compare;
|
||||||
let are_equal = self.pos.line_y == self.pos.ly_compare;
|
self.stat.set_coincidence(are_equal);
|
||||||
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 {
|
let next_mode = if self.pos.line_y >= 144 {
|
||||||
|
@ -140,10 +143,13 @@ impl Ppu {
|
||||||
self.cycles %= 456;
|
self.cycles %= 456;
|
||||||
self.pos.line_y += 1;
|
self.pos.line_y += 1;
|
||||||
|
|
||||||
// New Scanline is next, check for LYC=LY
|
// Update LY==LYC bit
|
||||||
if self.stat.coincidence_int() {
|
let are_equal = self.pos.line_y == self.pos.ly_compare;
|
||||||
let are_equal = self.pos.line_y == self.pos.ly_compare;
|
self.stat.set_coincidence(are_equal);
|
||||||
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 {
|
if self.pos.line_y == 154 {
|
||||||
|
@ -687,8 +693,8 @@ impl PixelFetcher {
|
||||||
let id = self.bg.tile.id.expect("Tile Number unexpectedly missing");
|
let id = self.bg.tile.id.expect("Tile Number unexpectedly missing");
|
||||||
|
|
||||||
let tile_data_addr = match control.tile_data_addr() {
|
let tile_data_addr = match control.tile_data_addr() {
|
||||||
TileDataAddress::X8800 => 0x9000u16.wrapping_add((id as i8 * 16) as u16),
|
TileDataAddress::X8800 => 0x9000u16.wrapping_add((id as i8).wrapping_mul(16) as u16),
|
||||||
TileDataAddress::X8000 => 0x8000 + (id as u16 * 16),
|
TileDataAddress::X8000 => 0x8000 + (id as u16).wrapping_mul(16),
|
||||||
};
|
};
|
||||||
|
|
||||||
let offset = 2 * if window {
|
let offset = 2 * if window {
|
||||||
|
@ -737,7 +743,7 @@ impl PixelFetcher {
|
||||||
(line_y + scroll_y) % 8
|
(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;
|
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 Copy for LCDStatus {}
|
||||||
impl Clone for LCDStatus {
|
impl Clone for LCDStatus {
|
||||||
fn clone(&self) -> Self {
|
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 {
|
impl From<LCDStatus> for u8 {
|
||||||
fn from(status: LCDStatus) -> Self {
|
fn from(status: LCDStatus) -> Self {
|
||||||
status.0
|
status.0
|
||||||
|
|
Loading…
Reference in New Issue