From 372f447e6007146e6cfa34d0df7723d4586af249 Mon Sep 17 00:00:00 2001 From: Determinant Date: Tue, 14 Nov 2017 21:45:39 -0500 Subject: ... --- src/main.rs | 52 ++++++++++++++++++++++++++++++++++++++-------------- src/memory.rs | 2 +- src/mos6502.rs | 51 ++++++++++++++++++++++++++++++--------------------- src/ppu.rs | 2 +- 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, events: RefCell, + timer: RefCell, + 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; } -- cgit v1.2.3-70-g09d2