aboutsummaryrefslogtreecommitdiff
path: root/src/bin.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin.rs')
-rw-r--r--src/bin.rs105
1 files changed, 96 insertions, 9 deletions
diff --git a/src/bin.rs b/src/bin.rs
index 839b630..d306fb4 100644
--- a/src/bin.rs
+++ b/src/bin.rs
@@ -1,10 +1,12 @@
+#![feature(const_size_of)]
extern crate core;
use std::fs::File;
use std::sync::{Mutex, Condvar};
-use std::io::Read;
+use std::io::{Read, Write};
use std::intrinsics::transmute;
use std::process::exit;
+use std::cell::Cell;
extern crate sdl2;
#[macro_use] extern crate clap;
@@ -14,6 +16,7 @@ use sdl2::keyboard::Keycode;
use sdl2::rect::Rect;
use clap::{Arg, App};
+ mod utils;
mod memory;
#[macro_use] mod mos6502;
mod ppu;
@@ -73,7 +76,17 @@ impl Cartridge for SimpleCart {
BankType::Sram => self.sram.len()
}
}
- fn get_bank<'a>(&mut self, base: usize, size: usize, kind: BankType) -> &'a mut [u8] {
+ fn get_bank<'a>(&self, base: usize, size: usize, kind: BankType) -> &'a [u8] {
+ unsafe {
+ &*((&(match kind {
+ BankType::PrgRom => &self.prg_rom,
+ BankType::ChrRom => &self.chr_rom,
+ BankType::Sram => &self.sram,
+ })[base..base + size]) as *const [u8])
+ }
+ }
+
+ fn get_bank_mut<'a>(&mut self, base: usize, size: usize, kind: BankType) -> &'a mut [u8] {
unsafe {
&mut *((&mut (match kind {
BankType::PrgRom => &mut self.prg_rom,
@@ -82,8 +95,47 @@ impl Cartridge for SimpleCart {
})[base..base + size]) as *mut [u8])
}
}
+
fn get_mirror_type(&self) -> MirrorType {self.mirror_type}
fn set_mirror_type(&mut self, mt: MirrorType) {self.mirror_type = mt}
+
+ fn load(&mut self, reader: &mut utils::Read) -> bool {
+ let len = self.sram.len();
+ (match reader.read(&mut self.sram) {
+ Some(x) => x == len,
+ None => false
+ }) &&
+ utils::load_prefix(&mut self.mirror_type, 0, reader)
+ }
+
+ fn save(&self, writer: &mut utils::Write) -> bool {
+ let len = self.sram.len();
+ (match writer.write(&self.sram) {
+ Some(x) => x == len,
+ None => false
+ }) &&
+ utils::save_prefix(&self.mirror_type, 0, writer)
+ }
+}
+
+struct FileIO(File);
+
+impl utils::Read for FileIO {
+ fn read(&mut self, buf: &mut [u8]) -> Option<usize> {
+ match self.0.read(buf) {
+ Ok(x) => Some(x),
+ Err(_) => None
+ }
+ }
+}
+
+impl utils::Write for FileIO {
+ fn write(&mut self, buf: &[u8]) -> Option<usize> {
+ match self.0.write(buf) {
+ Ok(x) => Some(x),
+ Err(_) => None
+ }
+ }
}
struct SDLWindow<'a> {
@@ -95,6 +147,7 @@ struct SDLWindow<'a> {
p1_ctl: &'a stdctl::Joystick,
p1_keymap: [u8; 256],
copy_area: Option<Rect>,
+ exit_flag: &'a Cell<bool>
}
macro_rules! gen_keymap {
@@ -107,7 +160,8 @@ impl<'a> SDLWindow<'a> {
fn new(sdl_context: &'a sdl2::Sdl,
p1_ctl: &'a stdctl::Joystick,
pixel_scale: u32,
- full_screen: bool) -> Self {
+ full_screen: bool,
+ exit_flag: &'a Cell<bool>) -> Self {
use Keycode::*;
let video_subsystem = sdl_context.video().unwrap();
let mut actual_height = PIX_HEIGHT * pixel_scale;
@@ -139,7 +193,7 @@ impl<'a> SDLWindow<'a> {
PIX_WIDTH, PIX_HEIGHT).unwrap(),
p1_button_state: 0,
p1_ctl, p1_keymap: [stdctl::NULL; 256],
- copy_area
+ copy_area, exit_flag
};
{
let keymap = &mut res.p1_keymap;
@@ -209,7 +263,11 @@ impl<'a> ppu::Screen for SDLWindow<'a> {
self.canvas.clear();
self.canvas.copy(&self.texture, self.copy_area, None).unwrap();
self.canvas.present();
- if self.poll() { exit(0) }
+ if self.poll() {
+ /*
+ */
+ self.exit_flag.set(true)
+ }
}
}
@@ -347,6 +405,11 @@ fn main() {
.help("the iNES ROM file")
.required(true)
.index(1))
+ .arg(Arg::with_name("load")
+ .short("l")
+ .long("load")
+ .required(false)
+ .takes_value(true))
.get_matches();
let scale = std::cmp::min(8,
@@ -356,6 +419,7 @@ fn main() {
/* load and parse iNES file */
let fname = matches.value_of("INPUT").unwrap();
+ let lname = matches.value_of("load");
let mut file = File::open(fname).unwrap();
let mut rheader = [0; 16];
file.read(&mut rheader[..]).unwrap();
@@ -391,7 +455,7 @@ fn main() {
let mut prg_rom = vec![0; prg_len];
let mut chr_rom = vec![0; chr_len];
- let sram = vec![0; 0x4000];
+ let sram = vec![0; 0x2000];
println!("read prg {}", file.read(&mut prg_rom[..]).unwrap());
println!("read chr {}", file.read(&mut chr_rom[..]).unwrap());
@@ -412,9 +476,10 @@ fn main() {
}).unwrap();
/* P1 controller */
let p1ctl = stdctl::Joystick::new();
- /* cartridge & mapper */
+ /* construct mapper from cartridge data */
let cart = SimpleCart::new(chr_rom, prg_rom, sram, mirror);
- let mut win = Box::new(SDLWindow::new(&sdl_context, &p1ctl, scale, full));
+ let exit_flag = Cell::new(false);
+ let mut win = Box::new(SDLWindow::new(&sdl_context, &p1ctl, scale, full, &exit_flag));
let mut m: Box<mapper::Mapper> = match mapper_id {
0 | 2 => Box::new(mapper::Mapper2::new(cart)),
1 => Box::new(mapper::Mapper1::new(cart)),
@@ -428,13 +493,35 @@ fn main() {
let mut apu = APU::new(&mut spkr);
let cpu_ptr = &mut cpu as *mut CPU;
cpu.mem.bus.attach(cpu_ptr, &mut ppu, &mut apu);
- cpu.powerup();
+ match lname {
+ Some(s) => {
+ let mut file = FileIO(File::open(s).unwrap());
+ cpu.load(&mut file);
+ ppu.load(&mut file);
+ apu.load(&mut file);
+ mapper.get_mut().load(&mut file);
+ debug_assert!(cpu.cycle == 0);
+ },
+ None => {
+ cpu.powerup()
+ }
+ }
device.resume();
loop {
/* consume the leftover cycles from the last instruction */
while cpu.cycle > 0 {
cpu.mem.bus.tick()
}
+ if exit_flag.get() {
+ {
+ let mut file = FileIO(File::create("t.dat").unwrap());
+ cpu.save(&mut file);
+ ppu.save(&mut file);
+ apu.save(&mut file);
+ mapper.save(&mut file);
+ }
+ exit(0);
+ }
//print_cpu_trace(&cpu);
cpu.step();
}