aboutsummaryrefslogtreecommitdiff
path: root/src/ppu.rs
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2017-11-17 00:30:28 -0500
committerDeterminant <ted.sybil@gmail.com>2017-11-17 00:30:28 -0500
commit0157d11bfc1f0cb01815f75bbf80635f71910b4c (patch)
treebc8743ed76030ae932917ab85165913cb09e3950 /src/ppu.rs
parent35061de86daee3ed46f4a6ba14983672424dce56 (diff)
pass the vbl nmi timing test
Diffstat (limited to 'src/ppu.rs')
-rw-r--r--src/ppu.rs62
1 files changed, 44 insertions, 18 deletions
diff --git a/src/ppu.rs b/src/ppu.rs
index c0f5379..928fe7f 100644
--- a/src/ppu.rs
+++ b/src/ppu.rs
@@ -19,7 +19,7 @@ struct Sprite {
}
pub struct PPU<'a> {
- scanline: u16,
+ pub scanline: u16,
/* registers */
ppuctl: u8,
ppumask: u8,
@@ -33,7 +33,7 @@ pub struct PPU<'a> {
t: u16, /* temporary vram addr */
w: bool, /* first/second write toggle */
f: bool, /* if it is an odd frame */
- cycle: u16, /* cycle in the current scanline */
+ pub cycle: u16, /* cycle in the current scanline */
/* rendering regs & latches */
/* background register (current two tiles) */
bg_pixel: u64,
@@ -48,9 +48,9 @@ pub struct PPU<'a> {
sp_pixel: [u32; 8],
sp_idx: [usize; 8],
sp_cnt: [u8; 8],
- rendering: bool,
+ pub vblank: bool,
buffered_read: u8,
- early_read: bool,
+ early_read: Option<bool>,
/* IO */
mem: PPUMemory<'a>,
scr: &'a Screen,
@@ -75,8 +75,12 @@ impl<'a> PPU<'a> {
let res = (self.ppustatus & !0x1fu8) | (self.reg & 0x1f);
self.ppustatus &= !PPU::FLAG_VBLANK;
self.w = false;
- if self.scanline == 241 && self.cycle == 0 {
- self.early_read = true;
+ if self.scanline == 241 {
+ match self.cycle {
+ 1 => self.early_read = Some(true), /* read before cycle 1 */
+ 2 | 3 => self.early_read = Some(false), /* read on cycle 1 and 2 */
+ _ => ()
+ }
}
res
}
@@ -185,7 +189,7 @@ impl<'a> PPU<'a> {
}
#[inline(always)] fn get_spritesize(&self) -> u8 {(self.ppuctl >> 5) & 1}
- #[inline(always)] fn get_flag_nmi(&self) -> bool { (self.ppuctl >> 7) == 1 }
+ #[inline(always)] pub fn get_flag_nmi(&self) -> bool { (self.ppuctl >> 7) == 1 }
#[inline(always)] fn get_vram_inc(&self) -> u8 { (self.ppuctl >> 2) & 1}
#[inline(always)] fn get_show_leftmost_bg(&self) -> bool { (self.ppumask >> 1) & 1 == 1}
#[inline(always)] fn get_show_leftmost_sp(&self) -> bool { (self.ppumask >> 2) & 1 == 1}
@@ -445,8 +449,8 @@ impl<'a> PPU<'a> {
let ppustatus = 0xa0;
let oamaddr = 0x00;
let buffered_read = 0x00;
- let cycle = 340;
- let scanline = 240;
+ let cycle = 0;
+ let scanline = 261;
PPU {
scanline,
ppuctl,
@@ -463,9 +467,9 @@ impl<'a> PPU<'a> {
sp_idx: [0x100; 8],
sp_pixel: [0; 8],
sp_cnt: [0; 8],
- rendering: false,
+ vblank: false,
buffered_read,
- early_read: false,
+ early_read: None,
mem, scr
}
}
@@ -480,6 +484,11 @@ impl<'a> PPU<'a> {
self.scanline = 240;
}
+ #[inline(always)]
+ pub fn try_nmi(&mut self) -> bool {
+ self.get_flag_vblank() && self.get_flag_nmi()
+ }
+
pub fn tick(&mut self) -> bool {
let cycle = self.cycle;
if cycle == 0 {
@@ -525,6 +534,8 @@ impl<'a> PPU<'a> {
* scanline */
self.reset_cx();
self.fetch_sprite();
+ self.cycle = 258;
+ return false
}
if pre_line && cycle == 339 && self.f {
self.scanline = 0;
@@ -535,21 +546,36 @@ impl<'a> PPU<'a> {
}
} else {
if !rendering { self.bg_pixel = 0 }
- if self.scanline == 241 && cycle == 1 {
- if !self.early_read {
- self.ppustatus |= PPU::FLAG_VBLANK;
+ if self.scanline == 241 {
+ match cycle {
+ 1 => {
+ match self.early_read {
+ Some(true) => (),
+ _ => self.ppustatus |= PPU::FLAG_VBLANK
+ }
+ self.vblank = true;
+ self.scr.render();
+ self.cycle = 2;
+ return false
+ },
+ 3 => {
+ let b = self.early_read.is_none();
+ self.early_read = None;
+ self.cycle = 4;
+ return b && self.try_nmi()
+ },
+ _ => ()
}
- self.scr.render();
- self.cycle = 2;
- self.early_read = false;
- return !self.early_read && self.get_flag_nmi(); /* trigger cpu's NMI */
}
}
if pre_line && cycle == 1 {
/* clear vblank, sprite zero hit & overflow */
+ self.vblank = false;
self.ppustatus &= !(PPU::FLAG_VBLANK |
PPU::FLAG_SPRITE_ZERO | PPU::FLAG_OVERFLOW);
self.bg_pixel = 0;
+ self.cycle = 2;
+ return false
}
self.cycle += 1;
if self.cycle > 340 {