aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <[email protected]>2017-11-16 00:29:42 -0500
committerDeterminant <[email protected]>2017-11-16 00:29:42 -0500
commitea9cfd9e1c6672d55370d8475a99f5def4b11752 (patch)
tree379872f30502ca78f4e58fba1ab963d22f00b12e
parentf2ff1e431129877d4b2093546a6864b474ed2219 (diff)
support basic 1p controller
-rw-r--r--src/lib.rs1
-rw-r--r--src/main.rs69
-rw-r--r--src/memory.rs28
-rw-r--r--src/ppu.rs1
4 files changed, 86 insertions, 13 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 93ddf74..0c35e3d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,3 +4,4 @@ mod mos6502;
mod ppu;
mod cartridge;
mod mapper;
+mod controller;
diff --git a/src/main.rs b/src/main.rs
index 17887b5..1b89b23 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,12 +4,14 @@ mod mos6502;
mod ppu;
mod cartridge;
mod mapper;
+mod controller;
use std::fs::File;
use std::io::Read;
use core::cell::{Cell, RefCell, UnsafeCell};
use core::intrinsics::transmute;
use cartridge::*;
+use controller::stdctl::{Joystick, Button};
use std::time::{Instant, Duration};
use std::thread::sleep;
@@ -21,7 +23,7 @@ use sdl2::pixels::PixelFormatEnum;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
-const PIXEL_SIZE: u32 = 3;
+const PIXEL_SIZE: u32 = 2;
const RGB_COLORS: [u32; 64] = [
0x666666, 0x002a88, 0x1412a7, 0x3b00a4, 0x5c007e, 0x6e0040, 0x6c0600, 0x561d00,
0x333500, 0x0b4800, 0x005200, 0x004f08, 0x00404d, 0x000000, 0x000000, 0x000000,
@@ -59,17 +61,19 @@ impl ppu::Screen for DummyWindow {
}
}
-struct SDLWindow {
+struct SDLWindow<'a> {
canvas: RefCell<sdl2::render::WindowCanvas>,
events: RefCell<sdl2::EventPump>,
frame_buffer: UnsafeCell<[u8; FB_SIZE]>,
texture: UnsafeCell<sdl2::render::Texture>,
timer: Cell<Instant>,
- duration_per_frame: Duration
+ duration_per_frame: Duration,
+ p1_button_states: UnsafeCell<[bool; 8]>,
+ p1_ctl: &'a Joystick
}
-impl SDLWindow {
- fn new() -> Self {
+impl<'a> SDLWindow<'a> {
+ fn new(p1_ctl: &'a Joystick) -> Self {
let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
let window = video_subsystem.window("RuNES", WIN_WIDTH, WIN_HEIGHT)
@@ -91,17 +95,61 @@ impl SDLWindow {
texture: UnsafeCell::new(texture_creator.create_texture_streaming(
PixelFormatEnum::RGB24, WIN_WIDTH, WIN_HEIGHT).unwrap()),
timer: Cell::new(Instant::now()),
- duration_per_frame: Duration::from_millis(1000 / 60)
+ duration_per_frame: Duration::from_millis(1000 / 60),
+ p1_button_states: UnsafeCell::new([false; 8]),
+ p1_ctl,
}
}
#[inline(always)]
fn poll(&self) -> bool {
+ use Keycode::*;
+ let p1_button_states = unsafe {&mut *self.p1_button_states.get()};
for event in self.events.borrow_mut().poll_iter() {
match event {
- Event::Quit {..} | Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
+ Event::Quit {..} | Event::KeyDown { keycode: Some(Escape), .. } => {
return true;
},
+ Event::KeyDown { keycode: Some(c), .. } => {
+ let p = match c {
+ I => Button::Up,
+ K => Button::Down,
+ J => Button::Left,
+ L => Button::Right,
+ Z => Button::A,
+ X => Button::B,
+ Return => Button::Start,
+ S => Button::Select,
+ _ => Button::Null
+ };
+ match p {
+ Button::Null => (),
+ i => {
+ p1_button_states[i as usize] = true;
+ self.p1_ctl.set(p1_button_states);
+ }
+ }
+ },
+ Event::KeyUp { keycode: Some(c), .. } => {
+ let p = match c {
+ I => Button::Up,
+ K => Button::Down,
+ J => Button::Left,
+ L => Button::Right,
+ Z => Button::A,
+ X => Button::B,
+ Return => Button::Start,
+ S => Button::Select,
+ _ => Button::Null
+ };
+ match p {
+ Button::Null => (),
+ i => {
+ p1_button_states[i as usize] = false;
+ self.p1_ctl.set(p1_button_states);
+ }
+ }
+ },
_ => ()
}
}
@@ -115,7 +163,7 @@ fn get_rgb(color: u8) -> (u8, u8, u8) {
((c >> 16) as u8, ((c >> 8) & 0xff) as u8, (c & 0xff) as u8)
}
-impl ppu::Screen for SDLWindow {
+impl<'a> ppu::Screen for SDLWindow<'a> {
fn put(&self, x: u8, y: u8, color: u8) {
unsafe {
let (r, g, b) = get_rgb(color);
@@ -228,10 +276,11 @@ fn main() {
*/
let cart = cartridge::Cartridge::new(chr_rom, prg_rom, sram, mirror);
//let win = Window {buff: RefCell::new([[0; 256]; 240])};
- let win = SDLWindow::new();
+ let p1ctl = Joystick::new();
+ let win = SDLWindow::new(&p1ctl);
let mapper = mapper::Mapper2::new(&cart);
let mut ppu = ppu::PPU::new(memory::PPUMemory::new(&mapper, &cart), &win);
- let mut cpu = mos6502::CPU::new(memory::CPUMemory::new(&mut ppu, &mapper));
+ let mut cpu = mos6502::CPU::new(memory::CPUMemory::new(&mut ppu, &mapper, Some(&p1ctl), None));
let ptr = &mut cpu as *mut mos6502::CPU;
cpu.mem.init(ptr);
loop {
diff --git a/src/memory.rs b/src/memory.rs
index 6b960ec..c302af9 100644
--- a/src/memory.rs
+++ b/src/memory.rs
@@ -2,6 +2,7 @@
use ppu::PPU;
use mos6502::CPU;
use cartridge::{MirrorType, Cartridge};
+use controller::Controller;
use core::cell::{UnsafeCell, Cell};
use core::ptr::null_mut;
@@ -14,15 +15,20 @@ pub struct CPUMemory<'a> {
sram: UnsafeCell<[u8; 2048]>,
ppu: Cell<*mut PPU<'a>>,
cpu: Cell<*mut CPU<'a>>,
- mapper: &'a VMem
+ mapper: &'a VMem,
+ ctl1: Option<&'a Controller>,
+ ctl2: Option<&'a Controller>
}
impl<'a> CPUMemory<'a> {
- pub fn new(ppu: *mut PPU<'a>, mapper: &'a VMem) -> Self {
+ pub fn new(ppu: *mut PPU<'a>,
+ mapper: &'a VMem,
+ ctl1: Option<&'a Controller>,
+ ctl2: Option<&'a Controller>) -> Self {
CPUMemory{sram: UnsafeCell::new([0; 2048]),
cpu: Cell::new(null_mut()),
ppu: Cell::new(ppu),
- mapper}
+ mapper, ctl1, ctl2}
}
pub fn init(&self, cpu: *mut CPU<'a>) {
@@ -42,6 +48,18 @@ impl<'a> VMem for CPUMemory<'a> {
0x7 => ppu.read_data(),
_ => 0
}
+ } else if addr < 0x4020 {
+ match addr {
+ 0x4016 => match self.ctl1 {
+ Some(c) => c.read(),
+ None => 0
+ },
+ 0x4017 => match self.ctl2 {
+ Some(c) => c.read(),
+ None => 0
+ },
+ _ => 0
+ }
} else if addr < 0x6000 {
0
} else {
@@ -68,6 +86,10 @@ impl<'a> VMem for CPUMemory<'a> {
} else if addr < 0x4020 {
match addr {
0x4014 => ppu.write_oamdma(data, cpu),
+ 0x4016 => match self.ctl1 {
+ Some(c) => c.write(data),
+ None => ()
+ },
_ => ()
}
} else if addr < 0x6000 {
diff --git a/src/ppu.rs b/src/ppu.rs
index ffb1953..c5b4aec 100644
--- a/src/ppu.rs
+++ b/src/ppu.rs
@@ -531,6 +531,7 @@ impl<'a> PPU<'a> {
/* clear vblank, sprite zero hit & overflow */
self.ppustatus &= !(PPU::FLAG_VBLANK |
PPU::FLAG_SPRITE_ZERO | PPU::FLAG_OVERFLOW);
+ self.bg_pixel = 0;
}
}
} else if self.scanline == 241 && cycle == 1 {