diff options
author | Determinant <[email protected]> | 2017-11-16 12:11:53 -0500 |
---|---|---|
committer | Determinant <[email protected]> | 2017-11-16 12:11:53 -0500 |
commit | 6f84b116a6f52c0611f18994b011a0339abb6310 (patch) | |
tree | e2d3cae34904f06070eb5ec6feb952727e254024 /src | |
parent | b37a26bbd774089bb5e774f0ee24a6569b999d76 (diff) |
...
Diffstat (limited to 'src')
-rw-r--r-- | src/controller.rs | 59 | ||||
-rw-r--r-- | src/ppu.rs | 30 |
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()); + } + } +} @@ -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 |