aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2017-11-14 21:45:39 -0500
committerDeterminant <ted.sybil@gmail.com>2017-11-14 21:45:39 -0500
commit372f447e6007146e6cfa34d0df7723d4586af249 (patch)
tree9817b024a149eb64f967e3d0993268a468d129be
parent4857ed73e80619d6046af223a61242e99e81235a (diff)
...
-rw-r--r--src/main.rs52
-rw-r--r--src/memory.rs2
-rw-r--r--src/mos6502.rs51
-rw-r--r--src/ppu.rs2
4 files changed, 70 insertions, 37 deletions
diff --git a/src/main.rs b/src/main.rs
index 19364c7..2caa797 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -7,10 +7,11 @@ mod mapper;
use std::fs::File;
use std::io::Read;
-use core::cell::RefCell;
+use core::cell::{RefCell, UnsafeCell};
use core::intrinsics::transmute;
use cartridge::*;
-
+use std::time::{Instant, Duration};
+use std::thread::sleep;
extern crate sdl2;
@@ -20,7 +21,7 @@ use sdl2::event::Event;
use sdl2::keyboard::Keycode;
struct DummyWindow {
- buff: RefCell<[[u8; 256]; 240]>
+ buff: RefCell<[[u8; 240]; 256]>
}
impl ppu::Screen for DummyWindow {
@@ -41,12 +42,15 @@ impl ppu::Screen for DummyWindow {
struct SDLWindow {
canvas: RefCell<sdl2::render::WindowCanvas>,
events: RefCell<sdl2::EventPump>,
+ timer: RefCell<sdl2::TimerSubsystem>,
+ frame_buffer: UnsafeCell<[[u8; 240]; 256]>,
}
impl SDLWindow {
fn new() -> Self {
let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
+ let timer = sdl_context.timer().unwrap();
let window = video_subsystem.window("RuNES", 256 * PIXEL_SIZE, 240 * PIXEL_SIZE)
.position_centered()
.opengl()
@@ -58,7 +62,9 @@ impl SDLWindow {
canvas.present();
SDLWindow {
canvas: RefCell::new(canvas),
- events: RefCell::new(sdl_context.event_pump().unwrap())
+ timer: RefCell::new(timer),
+ events: RefCell::new(sdl_context.event_pump().unwrap()),
+ frame_buffer: UnsafeCell::new([[0; 240]; 256])
}
}
@@ -94,16 +100,22 @@ fn get_rgb(color: u8) -> Color {
impl ppu::Screen for SDLWindow {
fn put(&self, x: u8, y: u8, color: u8) {
- let mut canvas = self.canvas.borrow_mut();
- //println!("put {} at {}, {}", color, x, y);
- canvas.set_draw_color(get_rgb(color));
- canvas.fill_rect(Rect::new((x as u32 * PIXEL_SIZE) as i32,
- (y as u32 * PIXEL_SIZE) as i32,
- PIXEL_SIZE, PIXEL_SIZE));
+ unsafe {
+ (*self.frame_buffer.get())[x as usize][y as usize] = color;
+ }
}
fn render(&self) {
let mut canvas = self.canvas.borrow_mut();
+ let fb = unsafe{&*self.frame_buffer.get()};
+ for (x, l) in fb.iter().enumerate() {
+ for (y, c) in l.iter().enumerate() {
+ canvas.set_draw_color(get_rgb(*c));
+ canvas.fill_rect(Rect::new((x as u32 * PIXEL_SIZE) as i32,
+ (y as u32 * PIXEL_SIZE) as i32,
+ PIXEL_SIZE, PIXEL_SIZE));
+ }
+ }
canvas.present();
canvas.set_draw_color(Color::RGB(128, 128, 128));
canvas.clear();
@@ -189,22 +201,34 @@ fn main() {
let mut cpu = mos6502::CPU::new(&mem);
mem.init(&mut cpu, &mut ppu);
let mut cnt = 0;
+ use ppu::Screen;
+ const CYC_PER_FRAME: u32 = mos6502::CPU_FREQ / 60;
+ let duration_per_frame: Duration = Duration::from_millis(1000 / 60);
+ let mut timer = Instant::now();
loop {
- if cnt == 1000 {
+ if cnt >= CYC_PER_FRAME {
+ win.render();
if win.poll() {break}
- cnt = 0;
+ let e = timer.elapsed();
+ if duration_per_frame > e {
+ sleep(duration_per_frame - e);
+ println!("faster {}", (duration_per_frame - e).subsec_nanos() as f64 / 1e6);
+ } else {
+ println!("slower");
+ }
+ timer = Instant::now();
+ cnt -= CYC_PER_FRAME;
}
cpu.step();
//println!("cpu at 0x{:04x}", cpu.get_pc());
while cpu.cycle > 0 {
for _ in 0..3 {
if ppu.tick() {
- println!("triggering nmi");
cpu.trigger_nmi();
}
}
+ cnt += 1;
cpu.cycle -= 1;
}
- cnt += 1;
}
}
diff --git a/src/memory.rs b/src/memory.rs
index 7d14b61..b7ea2c0 100644
--- a/src/memory.rs
+++ b/src/memory.rs
@@ -72,7 +72,7 @@ impl<'a> VMem for CPUMemory<'a> {
} else if addr < 0x4020 {
match addr {
0x4014 => ppu.write_oamdma(data, cpu),
- _ => println!("ignore writing for 0x{:04x}", addr)
+ _ => ()
}
} else if addr < 0x6000 {
} else {
diff --git a/src/mos6502.rs b/src/mos6502.rs
index 59e17de..7b39de4 100644
--- a/src/mos6502.rs
+++ b/src/mos6502.rs
@@ -1,5 +1,6 @@
#![allow(dead_code)]
use memory::VMem;
+pub const CPU_FREQ: u32 = 1789773;
macro_rules! make_optable {
($x:ident, $t: ty) => (pub const $x: [$t; 0x100] = [
/* 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf */
@@ -690,6 +691,7 @@ pub struct CPU<'a> {
macro_rules! make_int {
($f:ident, $v: expr) => (
+ #[inline(always)]
fn $f(&mut self) {
let pc = self.pc;
let sp = self.sp;
@@ -732,6 +734,7 @@ impl<'a> CPU<'a> {
make_int!(irq, IRQ_VECTOR);
pub fn step(&mut self) {
+ //let cycle0 = self.cycle;
if self.int.is_some() {
match self.int {
Some(IntType::NMI) => self.nmi(),
@@ -739,30 +742,34 @@ impl<'a> CPU<'a> {
_ => ()
}
self.int = None;
- return;
- }
- let pc = self.pc;
- let opcode = self.mem.read(pc) as usize;
- let len = INST_LENGTH[opcode];
- let mut code = vec![0; len as usize];
- for i in 0..len as u16 {
- code[i as usize] = self.mem.read(pc + i);
+ } else {
+ let pc = self.pc;
+ let opcode = self.mem.read(pc) as usize;
+ /*
+ let len = INST_LENGTH[opcode];
+ let mut code = vec![0; len as usize];
+ for i in 0..len as u16 {
+ code[i as usize] = self.mem.read(pc + i);
+ }
+ println!("0x{:04x} {} a:{:02x} x:{:02x} y:{:02x} s: {:02x} sp: {:02x}",
+ pc, disasm::parse(opcode as u8, &code[1..]),
+ self.a, self.x, self.y, self.status, self.sp);
+ */
+ /* update opr pointing to operands of current inst */
+ self.opr = pc.wrapping_add(1);
+ /* update program counter pointing to next inst */
+ self.pc = pc.wrapping_add(INST_LENGTH[opcode] as u16);
+ /* get effective address based on addressing mode */
+ self.acc = false;
+ let e = addr::ADDR_MODES[opcode](self) * INST_EXTRA_CYCLE[opcode];
+ /* execute the inst */
+ ops::OPS[opcode](self);
+ self.cycle += (INST_CYCLE[opcode] + e) as u32;
}
- //println!("0x{:04x} {} a:{:02x} x:{:02x} y:{:02x} s: {:02x} sp: {:02x}",
- // pc, disasm::parse(opcode as u8, &code[1..]),
- // self.a, self.x, self.y, self.status, self.sp);
- /* update opr pointing to operands of current inst */
- self.opr = pc.wrapping_add(1);
- /* update program counter pointing to next inst */
- self.pc = pc.wrapping_add(INST_LENGTH[opcode] as u16);
- /* get effective address based on addressing mode */
- self.acc = false;
- let e = addr::ADDR_MODES[opcode](self) * INST_EXTRA_CYCLE[opcode];
- /* execute the inst */
- ops::OPS[opcode](self);
- self.cycle += (INST_CYCLE[opcode] + e) as u32;
+ //(self.cycle - cycle0) as u8
}
+ #[inline(always)]
pub fn get_pc(&self) -> u16 { self.pc }
pub fn reset(&mut self) {
@@ -773,10 +780,12 @@ impl<'a> CPU<'a> {
self.int = None;
}
+ #[inline(always)]
pub fn trigger_nmi(&mut self) {
self.int = Some(IntType::NMI);
}
+ #[inline(always)]
pub fn trigger_irq(&mut self) {
if self.get_int() == 0 {
self.int = Some(match self.int {
diff --git a/src/ppu.rs b/src/ppu.rs
index 8daf009..4759ddc 100644
--- a/src/ppu.rs
+++ b/src/ppu.rs
@@ -4,6 +4,7 @@ use mos6502::CPU;
use core::intrinsics::transmute;
pub trait Screen {
+ #[inline(always)]
fn put(&self, x: u8, y: u8, color: u8);
fn render(&self);
}
@@ -538,7 +539,6 @@ impl<'a> PPU<'a> {
}
}
} else if self.scanline == 241 && cycle == 1 {
- self.scr.render();
if !self.early_read {
self.ppustatus |= PPU::FLAG_VBLANK;
}