aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDeterminant <ted.sybil@gmail.com>2017-12-18 23:52:19 +0800
committerDeterminant <ted.sybil@gmail.com>2017-12-18 23:52:19 +0800
commit147d75fca90edd02a4bb3f23ea827006d06fcb48 (patch)
tree6e7ea0d47e04931001259105e1678ed1e4ce3daf
parent9379a6241cfcfc5192e2581dc3911b8a0c61c256 (diff)
...
-rw-r--r--Cargo.lock117
-rw-r--r--Cargo.toml5
-rw-r--r--src/bin.rs44
-rw-r--r--src/ppu.rs39
4 files changed, 172 insertions, 33 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c2e8d2b..95dbb86 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,14 +1,49 @@
[[package]]
+name = "ansi_term"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "atty"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "bitflags"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "bitflags"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "cfg-if"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
+name = "clap"
+version = "2.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "fuchsia-zircon"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -25,6 +60,15 @@ dependencies = [
]
[[package]]
+name = "kernel32-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "lazy_static"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -76,9 +120,23 @@ dependencies = [
]
[[package]]
-name = "runes"
+name = "redox_syscall"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "redox_termios"
version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
+ "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "runes"
+version = "0.1.2"
+dependencies = [
+ "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)",
"sdl2 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -103,11 +161,59 @@ dependencies = [
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
+[[package]]
+name = "strsim"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "termion"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "unicode-width"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "vec_map"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "winapi-build"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
[metadata]
+"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455"
+"checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
+"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
+"checksum clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f"
"checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
"checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
+"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0"
"checksum num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cc4083e14b542ea3eb9b5f33ff48bd373a92d78687e74f4cc0a30caeb754f0ca"
@@ -115,5 +221,14 @@ dependencies = [
"checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01"
"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070"
"checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd"
+"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0"
+"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
"checksum sdl2 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a74c2a98a354b20713b90cce70aef9e927e46110d1bc4ef728fd74e0d53eba60"
"checksum sdl2-sys 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c543ce8a6e33a30cb909612eeeb22e693848211a84558d5a00bb11e791b7ab7"
+"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
+"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
+"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
+"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
+"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
+"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
diff --git a/Cargo.toml b/Cargo.toml
index 2194651..381e2d1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "runes"
-version = "0.1.1"
+version = "0.1.2"
authors = ["Determinant <tederminant@gmail.com>"]
description = "A no-std NES emulator library written purely in Rust."
repository = "https://github.com/Determinant/runes"
@@ -12,6 +12,9 @@ license = "MIT"
version = "0.31"
features = ["unsafe_textures"]
+[dev-dependencies.clap]
+version = "2.29.0"
+
[lib]
name = "runes"
path = "src/lib.rs"
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 <tederminant@gmail.com>")
+ .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::<u8>::with_capacity(prg_len);
- let mut chr_rom = Vec::<u8>::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<mapper::Mapper> = 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;
}
}