From 147d75fca90edd02a4bb3f23ea827006d06fcb48 Mon Sep 17 00:00:00 2001 From: Determinant Date: Mon, 18 Dec 2017 23:52:19 +0800 Subject: ... --- src/bin.rs | 44 +++++++++++++++++++++++++++++--------------- src/ppu.rs | 39 +++++++++++++++++++++++---------------- 2 files changed, 52 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/bin.rs b/src/bin.rs index 622bf49..22c3ac3 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -9,9 +9,11 @@ use std::intrinsics::transmute; //use std::thread; extern crate sdl2; +#[macro_use] extern crate clap; use sdl2::event::Event; use sdl2::keyboard::Keycode; +use clap::{Arg, App}; mod memory; #[macro_use] mod mos6502; @@ -29,7 +31,6 @@ use memory::{CPUMemory, PPUMemory}; use cartridge::{BankType, MirrorType, Cartridge}; use controller::stdctl; -const PIXEL_SCALE: u32 = 4; const RGB_COLORS: [u32; 64] = [ 0x666666, 0x002a88, 0x1412a7, 0x3b00a4, 0x5c007e, 0x6e0040, 0x6c0600, 0x561d00, 0x333500, 0x0b4800, 0x005200, 0x004f08, 0x00404d, 0x000000, 0x000000, 0x000000, @@ -45,8 +46,6 @@ const PIX_WIDTH: u32 = 256; const PIX_HEIGHT: u32 = 240; const FB_PITCH: usize = PIX_WIDTH as usize * 3; const FB_SIZE: usize = PIX_HEIGHT as usize * FB_PITCH; -const WIN_WIDTH: u32 = PIX_WIDTH * PIXEL_SCALE as u32; -const WIN_HEIGHT: u32 = PIX_HEIGHT * PIXEL_SCALE as u32; const AUDIO_SAMPLES: u16 = 4410; const AUDIO_EXTRA_SAMPLES: u16 = 20; const AUDIO_ALL_SAMPLES: u16 = AUDIO_SAMPLES + AUDIO_EXTRA_SAMPLES; @@ -103,10 +102,13 @@ macro_rules! gen_keymap { } impl<'a> SDLWindow<'a> { - fn new(sdl_context: &'a sdl2::Sdl, p1_ctl: &'a stdctl::Joystick) -> Self { + fn new(sdl_context: &'a sdl2::Sdl, + p1_ctl: &'a stdctl::Joystick, + pixel_scale: u32) -> Self { use Keycode::*; let video_subsystem = sdl_context.video().unwrap(); - let window = video_subsystem.window("RuNES", WIN_WIDTH, WIN_HEIGHT) + let window = video_subsystem.window("RuNES", PIX_WIDTH * pixel_scale, + PIX_HEIGHT * pixel_scale) .position_centered() .opengl() .build() @@ -117,7 +119,6 @@ impl<'a> SDLWindow<'a> { .build().unwrap(); let texture_creator = canvas.texture_creator(); canvas.set_draw_color(sdl2::pixels::Color::RGB(255, 255, 255)); - canvas.set_scale(PIXEL_SCALE as f32, PIXEL_SCALE as f32).unwrap(); canvas.clear(); canvas.present(); let mut res = SDLWindow { @@ -317,7 +318,24 @@ fn print_cpu_trace(cpu: &CPU) { } fn main() { - let fname = std::env::args().nth(1).unwrap(); + let matches = App::new("RuNES") + .version("0.1.2") + .author("Ted Yin ") + .about("A Rust NES emulator") + .arg(Arg::with_name("scale") + .short("x") + .long("scale") + .required(false) + .takes_value(true)) + .arg(Arg::with_name("INPUT") + .help("the iNES ROM file") + .required(true) + .index(1)) + .get_matches(); + let scale = std::cmp::min(8, + std::cmp::max(1, + value_t!(matches, "scale", u32).unwrap_or(4))); + let fname = matches.value_of("INPUT").unwrap(); let mut file = File::open(fname).unwrap(); let mut rheader = [0; 16]; println!("read {}", file.read(&mut rheader[..]).unwrap()); @@ -337,7 +355,7 @@ fn main() { mirror as u8, mapper_id); if header.flags6 & 0x04 == 0x04 { - let mut trainer: [u8; 512] = unsafe{std::mem::uninitialized()}; + let mut trainer: [u8; 512] = [0; 512]; file.read(&mut trainer[..]).unwrap(); println!("skipping trainer"); } @@ -347,12 +365,8 @@ fn main() { if chr_len == 0 { chr_len = 0x2000; } - let mut prg_rom = Vec::::with_capacity(prg_len); - let mut chr_rom = Vec::::with_capacity(chr_len); - unsafe { - prg_rom.set_len(prg_len); - chr_rom.set_len(chr_len); - } + let mut prg_rom = vec![0; prg_len]; + let mut chr_rom = vec![0; chr_len]; let sram = vec![0; 0x4000]; println!("read prg {}", file.read(&mut prg_rom[..]).unwrap()); println!("read chr {}", file.read(&mut chr_rom[..]).unwrap()); @@ -375,7 +389,7 @@ fn main() { let p1ctl = stdctl::Joystick::new(); let cart = SimpleCart::new(chr_rom, prg_rom, sram, mirror); - let mut win = Box::new(SDLWindow::new(&sdl_context, &p1ctl)); + let mut win = Box::new(SDLWindow::new(&sdl_context, &p1ctl, scale)); let mut m: Box = match mapper_id { 0 | 2 => Box::new(mapper::Mapper2::new(cart)), 1 => Box::new(mapper::Mapper1::new(cart)), diff --git a/src/ppu.rs b/src/ppu.rs index 87ac6de..45f00d4 100644 --- a/src/ppu.rs +++ b/src/ppu.rs @@ -94,19 +94,13 @@ impl<'a> PPU<'a> { #[inline] pub fn write_oamdata(&mut self, data: u8) { self.reg = data; - unsafe { - let oam_raw = transmute::<&mut[Sprite; 64], &mut[u8; 256]>(&mut self.oam); - oam_raw[self.oamaddr as usize] = data; - self.oamaddr = self.oamaddr.wrapping_add(1); - } + self.get_oam_raw_mut()[self.oamaddr as usize] = data; + self.oamaddr = self.oamaddr.wrapping_add(1); } #[inline] pub fn read_oamdata(&self) -> u8 { - unsafe { - let oam_raw = transmute::<&[Sprite; 64], &[u8; 256]>(&self.oam); - oam_raw[self.oamaddr as usize] - } + self.get_oam_raw()[self.oamaddr as usize] } #[inline] @@ -178,14 +172,16 @@ impl<'a> PPU<'a> { cpu.cycle += 1; cpu.cycle += cpu.cycle & 1; cpu.cycle += 512; - unsafe { - let oam_raw = transmute::<&mut[Sprite; 64], &mut[u8; 256]>(&mut self.oam); + let mut oamaddr = self.oamaddr; + { + let oam_raw = self.get_oam_raw_mut(); for _ in 0..0x100 { - oam_raw[self.oamaddr as usize] = cpu.mem.read(addr); + oam_raw[oamaddr as usize] = cpu.mem.read(addr); addr = addr.wrapping_add(1); - self.oamaddr = self.oamaddr.wrapping_add(1); + oamaddr = oamaddr.wrapping_add(1); } } + self.oamaddr = oamaddr; } #[inline(always)] fn get_spritesize(&self) -> u8 {(self.ppuctl >> 5) & 1} @@ -196,6 +192,15 @@ impl<'a> PPU<'a> { #[inline(always)] fn get_show_bg(&self) -> bool { (self.ppumask >> 3) & 1 == 1} #[inline(always)] fn get_show_sp(&self) -> bool { (self.ppumask >> 4) & 1 == 1} #[inline(always)] pub fn get_flag_vblank(&self) -> bool { (self.ppustatus >> 7) & 1 == 1 } + #[inline(always)] fn get_oam_arr(&self) -> &[[u8; 4]; 64] { + unsafe {transmute::<&[Sprite; 64], &[[u8; 4]; 64]>(&self.oam)} + } + #[inline(always)] fn get_oam_raw_mut(&mut self) -> &mut[u8; 256] { + unsafe {transmute::<&mut[Sprite; 64], &mut[u8; 256]>(&mut self.oam)} + } + #[inline(always)] fn get_oam_raw(&self) -> &[u8; 256] { + unsafe {transmute::<&[Sprite; 64], &[u8; 256]>(&self.oam)} + } const FLAG_OVERFLOW: u8 = 1 << 5; const FLAG_SPRITE_ZERO: u8 = 1 << 6; @@ -333,18 +338,20 @@ impl<'a> PPU<'a> { } if nidx == 8 { let mut m = 0; - unsafe { - let oam_raw = transmute::<&[Sprite; 64], &[[u8; 4]; 64]>(&self.oam); + let mut ppustatus = self.ppustatus; + { + let oam_raw = self.get_oam_arr(); while n < 64 { let y = oam_raw[n][m] as u16; if y <= scanline && scanline < y + h { - self.ppustatus |= PPU::FLAG_OVERFLOW; /* set overflow */ + ppustatus |= PPU::FLAG_OVERFLOW; /* set overflow */ } else { m = (m + 1) & 3; /* emulates hardware bug */ } n += 1; } } + self.ppustatus = ppustatus; } } -- cgit v1.2.3-70-g09d2