aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <[email protected]>2017-11-16 12:11:53 -0500
committerDeterminant <[email protected]>2017-11-16 12:11:53 -0500
commit6f84b116a6f52c0611f18994b011a0339abb6310 (patch)
treee2d3cae34904f06070eb5ec6feb952727e254024
parentb37a26bbd774089bb5e774f0ee24a6569b999d76 (diff)
...
-rw-r--r--src/controller.rs59
-rw-r--r--src/ppu.rs30
2 files changed, 79 insertions, 10 deletions
diff --git a/src/controller.rs b/src/controller.rs
new file mode 100644
index 0000000..cc01d0f
--- /dev/null
+++ b/src/controller.rs
@@ -0,0 +1,59 @@
+
+pub trait Controller {
+ fn read(&self) -> u8;
+ fn write(&self, data: u8);
+}
+
+pub mod stdctl {
+ use core::cell::Cell;
+ use controller::Controller;
+ #[derive(Copy, Clone)]
+ pub enum Button {
+ A = 0,
+ B = 1,
+ Select = 2,
+ Start = 3,
+ Up = 4,
+ Down = 5,
+ Left = 6,
+ Right = 7,
+ Null = 8,
+ }
+ pub struct Joystick {
+ strobe: Cell<bool>,
+ reg: Cell<u8>,
+ back_reg: Cell<u8>
+ }
+
+ impl Joystick {
+ pub fn new() -> Self {
+ Joystick{reg: Cell::new(0), strobe: Cell::new(false), back_reg: Cell::new(0)}
+ }
+
+ pub fn set(&self, buttons: &[bool]) {
+ let mut reg = 0;
+ for (i, v) in buttons.iter().enumerate() {
+ if *v {
+ reg |= 1 << i;
+ }
+ }
+ self.reg.set(reg);
+ self.back_reg.set(reg);
+ }
+ }
+
+ impl Controller for Joystick {
+ fn read(&self) -> u8 {
+ let res = self.reg.get() & 1;
+ if !self.strobe.get() {
+ self.reg.set(self.reg.get() >> 1);
+ }
+ res
+ }
+
+ fn write(&self, data: u8) {
+ self.strobe.set(data & 1 == 1);
+ self.reg.set(self.back_reg.get());
+ }
+ }
+}
diff --git a/src/ppu.rs b/src/ppu.rs
index ad9c991..62a8261 100644
--- a/src/ppu.rs
+++ b/src/ppu.rs
@@ -32,11 +32,12 @@ pub struct PPU<'a> {
v: u16, /* current vram addr */
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 */
/* rendering regs & latches */
- /* background registers */
+ /* background register (current two tiles) */
bg_pixel: u64,
- /* background latches */
+ /* background latches for next tile */
bg_nt: u8,
bg_attr: u8,
bg_bit_low: u8,
@@ -178,9 +179,11 @@ impl<'a> PPU<'a> {
self.oamaddr = self.oamaddr.wrapping_add(1);
}
}
+ /*
cpu.cycle += 1;
cpu.cycle += cpu.cycle & 1;
cpu.cycle += 512;
+ */
}
#[inline(always)] fn get_spritesize(&self) -> u8 {(self.ppuctl >> 5) & 1}
@@ -443,7 +446,6 @@ impl<'a> PPU<'a> {
let ppumask = 0x00;
let ppustatus = 0xa0;
let oamaddr = 0x00;
- let w = false;
let buffered_read = 0x00;
let cycle = 370;
let scanline = 240;
@@ -454,7 +456,7 @@ impl<'a> PPU<'a> {
ppustatus,
oamaddr,
reg: 0,
- x: 0, v: 0, t: 0, w, cycle,
+ x: 0, v: 0, t: 0, w: false, f: true, cycle,
bg_pixel: 0,
bg_nt: 0, bg_attr: 0,
bg_bit_low: 0, bg_bit_high: 0,
@@ -483,7 +485,7 @@ impl<'a> PPU<'a> {
pub fn tick(&mut self) -> bool {
let cycle = self.cycle;
if cycle == 0 {
- self.cycle = cycle + 1;
+ self.cycle = 1;
return false;
}
let rendering = self.get_show_bg() || self.get_show_sp();
@@ -526,11 +528,18 @@ impl<'a> PPU<'a> {
self.reset_cx();
self.fetch_sprite();
}
- if pre_line && cycle == 1 {
- /* clear vblank, sprite zero hit & overflow */
- self.ppustatus &= !(PPU::FLAG_VBLANK |
- PPU::FLAG_SPRITE_ZERO | PPU::FLAG_OVERFLOW);
- self.bg_pixel = 0;
+ if pre_line {
+ if cycle == 1 {
+ /* clear vblank, sprite zero hit & overflow */
+ self.ppustatus &= !(PPU::FLAG_VBLANK |
+ PPU::FLAG_SPRITE_ZERO | PPU::FLAG_OVERFLOW);
+ self.bg_pixel = 0
+ } else if cycle == 339 && self.f {
+ self.scanline = 0;
+ self.cycle = 0;
+ self.f = !self.f;
+ return false;
+ }
}
}
} else {
@@ -551,6 +560,7 @@ impl<'a> PPU<'a> {
self.scanline += 1;
if self.scanline > 261 {
self.scanline = 0;
+ self.f = !self.f;
}
}
false