diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cartridge.rs | 25 | ||||
-rw-r--r-- | src/main.rs | 128 | ||||
-rw-r--r-- | src/mapper.rs | 84 | ||||
-rw-r--r-- | src/memory.rs | 102 | ||||
-rw-r--r-- | src/ppu.rs | 8 |
5 files changed, 172 insertions, 175 deletions
diff --git a/src/cartridge.rs b/src/cartridge.rs index b8d2b68..0d21a42 100644 --- a/src/cartridge.rs +++ b/src/cartridge.rs @@ -1,5 +1,4 @@ #![allow(dead_code)] -use core::cell::RefCell; #[derive(Copy, Clone)] pub enum MirrorType { @@ -17,33 +16,31 @@ pub enum BankType { } pub struct Cartridge { - chr_rom: RefCell<Vec<u8>>, - prg_rom: RefCell<Vec<u8>>, - sram: RefCell<Vec<u8>>, + chr_rom: Vec<u8>, + prg_rom: Vec<u8>, + sram: Vec<u8>, pub mirror_type: MirrorType } impl Cartridge { pub fn get_size(&self, kind: BankType) -> usize { match kind { - BankType::PrgRom => self.prg_rom.borrow().len(), - BankType::ChrRom => self.chr_rom.borrow().len(), - BankType::Sram => self.sram.borrow().len() + BankType::PrgRom => self.prg_rom.len(), + BankType::ChrRom => self.chr_rom.len(), + BankType::Sram => self.sram.len() } } - pub fn get_bank(&self, base: usize, size: usize, kind: BankType) -> *mut [u8] { + pub fn get_bank(&mut self, base: usize, size: usize, kind: BankType) -> *mut [u8] { &mut (match kind { - BankType::PrgRom => self.prg_rom.borrow_mut(), - BankType::ChrRom => self.chr_rom.borrow_mut(), - BankType::Sram => self.sram.borrow_mut(), + BankType::PrgRom => &mut self.prg_rom, + BankType::ChrRom => &mut self.chr_rom, + BankType::Sram => &mut self.sram, })[base..base + size] } pub fn new(chr_rom: Vec<u8>, prg_rom: Vec<u8>, sram: Vec<u8>, mirror_type: MirrorType) -> Self { - Cartridge{chr_rom: RefCell::new(chr_rom), - prg_rom: RefCell::new(prg_rom), - sram: RefCell::new(sram), mirror_type} + Cartridge{chr_rom, prg_rom, sram, mirror_type} } } diff --git a/src/main.rs b/src/main.rs index 45bece5..6a350ff 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,7 +8,7 @@ mod controller; use std::fs::File; use std::io::Read; -use core::cell::{Cell, RefCell, UnsafeCell}; +use core::cell::RefCell; use core::intrinsics::transmute; use cartridge::*; use controller::stdctl::{Joystick, Button}; @@ -43,15 +43,15 @@ const WIN_WIDTH: u32 = PIX_WIDTH as u32 * PIXEL_SIZE; const WIN_HEIGHT: u32 = PIX_HEIGHT as u32 * PIXEL_SIZE; struct SDLWindow<'a> { - canvas: UnsafeCell<sdl2::render::WindowCanvas>, - events: UnsafeCell<sdl2::EventPump>, - frame_buffer: UnsafeCell<[u8; FB_SIZE]>, - texture: UnsafeCell<sdl2::render::Texture>, - timer: Cell<Instant>, + canvas: sdl2::render::WindowCanvas, + events: sdl2::EventPump, + frame_buffer: [u8; FB_SIZE], + texture: sdl2::render::Texture, + timer: Instant, duration_per_frame: Duration, - p1_button_states: UnsafeCell<[bool; 8]>, + p1_button_states: [bool; 8], p1_ctl: &'a Joystick, - p1_keymap: UnsafeCell<[Button; 256]>, + p1_keymap: [Button; 256], } macro_rules! gen_keymap { @@ -81,41 +81,42 @@ impl<'a> SDLWindow<'a> { canvas.set_draw_color(Color::RGB(255, 255, 255)); canvas.clear(); canvas.present(); - let res = SDLWindow { - canvas: UnsafeCell::new(canvas), - events: UnsafeCell::new(sdl_context.event_pump().unwrap()), - frame_buffer: UnsafeCell::new([0; FB_SIZE]), - texture: UnsafeCell::new(texture_creator.create_texture_streaming( - PixelFormatEnum::RGB24, WIN_WIDTH, WIN_HEIGHT).unwrap()), - timer: Cell::new(Instant::now()), + let mut res = SDLWindow { + canvas, + events: sdl_context.event_pump().unwrap(), + frame_buffer: [0; FB_SIZE], + texture: texture_creator.create_texture_streaming( + PixelFormatEnum::RGB24, WIN_WIDTH, WIN_HEIGHT).unwrap(), + timer: Instant::now(), duration_per_frame: Duration::from_millis(1000 / 60), - p1_button_states: UnsafeCell::new([false; 8]), - p1_ctl, p1_keymap: UnsafeCell::new([Button::Null; 256]) + p1_button_states: [false; 8], + p1_ctl, p1_keymap: [Button::Null; 256] }; - let keymap = unsafe{&mut *res.p1_keymap.get()}; - gen_keymap!(keymap, [I, Button::Up, - K, Button::Down, - J, Button::Left, - L, Button::Right, - Z, Button::A, - X, Button::B, - Return, Button::Start, - S, Button::Select, - Up, Button::Up, - Down, Button::Down, - Left, Button::Left, - Right, Button::Right - ]); + { + let keymap = &mut res.p1_keymap; + gen_keymap!(keymap, [I, Button::Up, + K, Button::Down, + J, Button::Left, + L, Button::Right, + Z, Button::A, + X, Button::B, + Return, Button::Start, + S, Button::Select, + Up, Button::Up, + Down, Button::Down, + Left, Button::Left, + Right, Button::Right + ]); + } res } #[inline] - fn poll(&self) -> bool { + fn poll(&mut self) -> bool { use Keycode::*; - let p1_button_states = unsafe {&mut *self.p1_button_states.get()}; - let p1_keymap = unsafe {&mut *self.p1_keymap.get()}; - let events = unsafe {&mut *self.events.get()}; - for event in events.poll_iter() { + let p1_button_states = &mut self.p1_button_states; + let p1_keymap = &self.p1_keymap; + for event in self.events.poll_iter() { match event { Event::Quit {..} | Event::KeyDown { keycode: Some(Escape), .. } => { return true; @@ -152,35 +153,30 @@ fn get_rgb(color: u8) -> (u8, u8, u8) { } impl<'a> ppu::Screen for SDLWindow<'a> { - fn put(&self, x: u8, y: u8, color: u8) { - unsafe { - let (r, g, b) = get_rgb(color); - let mut base = ((y as u32 * PIXEL_SIZE) as usize * FB_PITCH) + - (x as u32 * 3 * PIXEL_SIZE) as usize; + fn put(&mut self, x: u8, y: u8, color: u8) { + let (r, g, b) = get_rgb(color); + let mut base = ((y as u32 * PIXEL_SIZE) as usize * FB_PITCH) + + (x as u32 * 3 * PIXEL_SIZE) as usize; + for _ in 0..PIXEL_SIZE { + let slice = &mut self.frame_buffer[base..base + 3 * PIXEL_SIZE as usize]; + let mut j = 0; for _ in 0..PIXEL_SIZE { - let slice = &mut (*self.frame_buffer.get())[base..base + 3 * PIXEL_SIZE as usize]; - let mut j = 0; - for _ in 0..PIXEL_SIZE { - slice[j] = r; - slice[j + 1] = g; - slice[j + 2] = b; - j += 3; - } - base += FB_PITCH; + slice[j] = r; + slice[j + 1] = g; + slice[j + 2] = b; + j += 3; } + base += FB_PITCH; } } - fn render(&self) { - let canvas = unsafe{&mut *self.canvas.get()}; - let fb = unsafe{&*self.frame_buffer.get()}; - let texture = unsafe{&mut *self.texture.get()}; - texture.update(None, fb, FB_PITCH).unwrap(); - canvas.clear(); - canvas.copy(&texture, None, Some(Rect::new(0, 0, WIN_WIDTH, WIN_HEIGHT))).unwrap(); - canvas.present(); + fn render(&mut self) { + self.texture.update(None, &self.frame_buffer, FB_PITCH).unwrap(); + self.canvas.clear(); + self.canvas.copy(&self.texture, None, Some(Rect::new(0, 0, WIN_WIDTH, WIN_HEIGHT))).unwrap(); + self.canvas.present(); if self.poll() {std::process::exit(0);} - let e = self.timer.get().elapsed(); + let e = self.timer.elapsed(); if self.duration_per_frame > e { let diff = self.duration_per_frame - e; sleep(diff); @@ -188,7 +184,7 @@ impl<'a> ppu::Screen for SDLWindow<'a> { } else { //println!("{} slower", (e - duration_per_frame).subsec_nanos() as f64 / 1e6); } - self.timer.set(Instant::now()); + self.timer = Instant::now(); //canvas.set_draw_color(Color::RGB(128, 128, 128)); } } @@ -262,15 +258,15 @@ fn main() { } } */ - let cart = cartridge::Cartridge::new(chr_rom, prg_rom, sram, mirror); let p1ctl = Joystick::new(); - let win = SDLWindow::new(&p1ctl); - let mapper = match mapper_id { - 0 | 2 => mapper::Mapper2::new(&cart), + let mut win = SDLWindow::new(&p1ctl); + let mut m = match mapper_id { + 0 | 2 => mapper::Mapper2::new(cartridge::Cartridge::new(chr_rom, prg_rom, sram, mirror)), _ => panic!("unsupported mapper {}", mapper_id) }; - - let mut ppu = ppu::PPU::new(memory::PPUMemory::new(&mapper, &cart), &win); + let mt = m.get_cart().mirror_type; + let mapper = RefCell::new(&mut m as &mut memory::VMem); + let mut ppu = ppu::PPU::new(memory::PPUMemory::new(&mapper, mt), &mut win); let mut cpu = mos6502::CPU::new(memory::CPUMemory::new(&mut ppu, &mapper, Some(&p1ctl), None)); let ptr = &mut cpu as *mut mos6502::CPU; cpu.mem.init(ptr); diff --git a/src/mapper.rs b/src/mapper.rs index 210b59f..fc02ed2 100644 --- a/src/mapper.rs +++ b/src/mapper.rs @@ -1,64 +1,72 @@ #![allow(dead_code)] +extern crate core; use memory::VMem; use cartridge::{Cartridge, BankType}; -use core::cell::UnsafeCell; pub struct Mapper2<'a> { - cart: &'a Cartridge, - prg_bank1: UnsafeCell<&'a [u8]>, - prg_bank2: UnsafeCell<&'a [u8]>, - chr_bank: UnsafeCell<&'a mut [u8]>, - sram: UnsafeCell<&'a mut [u8]>, + cart: Cartridge, + prg_bank1: &'a [u8], + prg_bank2: &'a [u8], + chr_bank: &'a mut [u8], + sram: &'a mut [u8], prg_nbank: usize } impl<'a> VMem for Mapper2<'a> { fn read(&self, addr: u16) -> u8 { let addr = addr as usize; - unsafe { - if addr < 0x2000 { /* 0x2000 size bank */ - (*self.chr_bank.get())[addr] - } else if addr >= 0xc000 { /* 0x4000 size bank */ - (*self.prg_bank2.get())[addr - 0xc000] - } else if addr >= 0x8000 { /* 0x4000 size bank */ - (*self.prg_bank1.get())[addr - 0x8000] - } else if addr >= 0x6000 { - (*self.sram.get())[addr - 0x6000] - } else { - panic!("unmapped address: 0x{:04x}", addr) - } + if addr < 0x2000 { /* 0x2000 size bank */ + self.chr_bank[addr] + } else if addr >= 0xc000 { /* 0x4000 size bank */ + self.prg_bank2[addr - 0xc000] + } else if addr >= 0x8000 { /* 0x4000 size bank */ + self.prg_bank1[addr - 0x8000] + } else if addr >= 0x6000 { + self.sram[addr - 0x6000] + } else { + panic!("unmapped address: 0x{:04x}", addr) } } - fn write(&self, addr: u16, data: u8) { + fn write(&mut self, addr: u16, data: u8) { let addr = addr as usize; - unsafe { - if addr < 0x2000 { - (*self.chr_bank.get())[addr] = data; - } else if addr >= 0x8000 { - (*self.prg_bank1.get()) = - &*self.cart.get_bank(((data as usize) % self.prg_nbank) << 14, - 0x4000, - BankType::PrgRom); - } else if addr >= 0x6000 { - (*self.sram.get())[addr - 0x6000] = data; - } else { - panic!("invalid write to address: 0x{:04x}", addr); + if addr < 0x2000 { + self.chr_bank[addr] = data; + } else if addr >= 0x8000 { + self.prg_bank1 = unsafe { + &*self.cart.get_bank(((data as usize) % self.prg_nbank) << 14, + 0x4000, + BankType::PrgRom) } + } else if addr >= 0x6000 { + self.sram[addr - 0x6000] = data + } else { + panic!("invalid write to address: 0x{:04x}", addr); } } } impl<'a> Mapper2<'a> { - pub fn new(cart: &'a Cartridge) -> Self { + pub fn new(cart: Cartridge) -> Self { unsafe { let nbank = cart.get_size(BankType::PrgRom) >> 14; - Mapper2{cart, - prg_bank1: UnsafeCell::new(&*cart.get_bank(0, 0x4000, BankType::PrgRom)), - prg_bank2: UnsafeCell::new(&*cart.get_bank((nbank - 1) << 14, 0x4000, BankType::PrgRom)), - chr_bank: UnsafeCell::new(&mut *cart.get_bank(0, 0x2000, BankType::ChrRom)), - sram: UnsafeCell::new(&mut *cart.get_bank(0, 0x2000, BankType::Sram)), - prg_nbank: nbank} + let null = core::mem::uninitialized(); + let mut m = Mapper2{cart, + prg_nbank: nbank, + prg_bank1: null, + prg_bank2: null, + chr_bank: core::mem::uninitialized(), + sram: core::mem::uninitialized()}; + { + let c = &mut m.cart; + m.prg_bank1 = &*c.get_bank(0, 0x4000, BankType::PrgRom); + m.prg_bank2 = &*c.get_bank((nbank - 1) << 14, 0x4000, BankType::PrgRom); + m.chr_bank = &mut *c.get_bank(0, 0x2000, BankType::ChrRom); + m.sram = &mut *c.get_bank(0, 0x2000, BankType::Sram); + } + m } } + + pub fn get_cart(&self) -> &Cartridge {&self.cart} } diff --git a/src/memory.rs b/src/memory.rs index f8b6632..6a62678 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -1,47 +1,47 @@ #![allow(dead_code)] use ppu::PPU; use mos6502::CPU; -use cartridge::{MirrorType, Cartridge}; +use cartridge::MirrorType; use controller::Controller; -use core::cell::{UnsafeCell, Cell}; +use core::cell::RefCell; use core::ptr::null_mut; pub trait VMem { fn read(&self, addr: u16) -> u8; - fn write(&self, addr: u16, data: u8); + fn write(&mut self, addr: u16, data: u8); } pub struct CPUMemory<'a> { - sram: UnsafeCell<[u8; 2048]>, - ppu: Cell<*mut PPU<'a>>, - cpu: Cell<*mut CPU<'a>>, - mapper: &'a VMem, + sram: [u8; 2048], + ppu: *mut PPU<'a>, + cpu: *mut CPU<'a>, + mapper: &'a RefCell<&'a mut VMem>, ctl1: Option<&'a Controller>, ctl2: Option<&'a Controller> } impl<'a> CPUMemory<'a> { pub fn new(ppu: &mut PPU<'a>, - mapper: &'a VMem, + mapper: &'a RefCell<&'a mut VMem>, ctl1: Option<&'a Controller>, ctl2: Option<&'a Controller>) -> Self { - CPUMemory{sram: UnsafeCell::new([0; 2048]), - cpu: Cell::new(null_mut()), - ppu: Cell::new(ppu), + CPUMemory{sram: [0; 2048], + cpu: null_mut(), + ppu: ppu, mapper, ctl1, ctl2} } - pub fn init(&self, cpu: *mut CPU<'a>) { - self.cpu.set(cpu); + pub fn init(&mut self, cpu: *mut CPU<'a>) { + self.cpu = cpu; } } impl<'a> VMem for CPUMemory<'a> { fn read(&self, addr: u16) -> u8 { if addr < 0x2000 { - unsafe{(*self.sram.get())[(addr & 0x07ff) as usize]} + self.sram[(addr & 0x07ff) as usize] } else if addr < 0x4000 { - let ppu = unsafe {&mut *self.ppu.get()}; + let ppu = unsafe {&mut *self.ppu}; match addr & 0x7 { 0x2 => ppu.read_status(), 0x4 => ppu.read_oamdata(), @@ -57,15 +57,15 @@ impl<'a> VMem for CPUMemory<'a> { } else if addr < 0x6000 { 0 } else { - self.mapper.read(addr) + self.mapper.borrow().read(addr) } } - fn write(&self, addr: u16, data: u8) { - let ppu = unsafe {&mut *self.ppu.get()}; - let cpu = unsafe {&mut *self.cpu.get()}; + fn write(&mut self, addr: u16, data: u8) { + let ppu = unsafe {&mut *self.ppu}; + let cpu = unsafe {&mut *self.cpu}; if addr < 0x2000 { - unsafe{(*self.sram.get())[(addr & 0x07ff) as usize] = data;} + self.sram[(addr & 0x07ff) as usize] = data; } else if addr < 0x4000 { match addr & 0x7 { 0x0 => { @@ -94,38 +94,36 @@ impl<'a> VMem for CPUMemory<'a> { } } else if addr < 0x6000 { } else { - self.mapper.write(addr, data) + self.mapper.borrow_mut().write(addr, data) } } } pub struct PPUMemory<'a> { - nametable: UnsafeCell<[u8; 0x800]>, - palette: UnsafeCell<[u8; 0x20]>, - cart: &'a Cartridge, - mapper: &'a VMem, + nametable: [u8; 0x800], + palette: [u8; 0x20], + mirror_type: MirrorType, + mapper: &'a RefCell<&'a mut VMem>, } impl<'a> PPUMemory<'a> { - pub fn new(mapper: &'a VMem, - cart: &'a Cartridge) -> Self { + pub fn new(mapper: &'a RefCell<&'a mut VMem>, + mirror_type: MirrorType) -> Self { PPUMemory{ - nametable: UnsafeCell::new([0; 0x800]), - palette: UnsafeCell::new([0; 0x20]), - cart, + nametable: [0; 0x800], + palette: [0; 0x20], + mirror_type, mapper} } pub fn dump(&self) { - unsafe { - for (i, v) in (*self.palette.get()).iter().enumerate() { - print!("{:02x} ", *v); - if (i & 0x7) == 0x7 {println!("@{:02x}", i)} - } - for (i, v) in (*self.nametable.get()).iter().enumerate() { - print!("{:02x} ", *v); - if (i & 0x1f) == 0x1f {println!("@{:02x}", i)} - } + for (i, v) in self.palette.iter().enumerate() { + print!("{:02x} ", *v); + if (i & 0x7) == 0x7 {println!("@{:02x}", i)} + } + for (i, v) in self.nametable.iter().enumerate() { + print!("{:02x} ", *v); + if (i & 0x1f) == 0x1f {println!("@{:02x}", i)} } } } @@ -155,34 +153,32 @@ fn get_mirror_palette(addr: u16) -> u16 { impl<'a> PPUMemory<'a> { #[inline(always)] pub fn read_nametable(&self, addr: u16) -> u8 { - let kind = self.cart.mirror_type; - unsafe {(*self.nametable.get())[(get_mirror_addr(kind, addr) & 0x7ff) as usize]} + self.nametable[(get_mirror_addr(self.mirror_type, addr) & 0x7ff) as usize] } #[inline(always)] - pub fn read_palette(&self, addr: u16) -> u8 { unsafe { - (*self.palette.get())[get_mirror_palette(addr) as usize] - }} + pub fn read_palette(&self, addr: u16) -> u8 { + self.palette[get_mirror_palette(addr) as usize] + } #[inline(always)] - pub fn write_nametable(&self, addr: u16, data: u8) { - let kind = self.cart.mirror_type; - unsafe {(*self.nametable.get())[(get_mirror_addr(kind, addr) & 0x7ff) as usize] = data} + pub fn write_nametable(&mut self, addr: u16, data: u8) { + self.nametable[(get_mirror_addr(self.mirror_type, addr) & 0x7ff) as usize] = data } #[inline(always)] - pub fn write_palette(&self, addr: u16, data: u8) { unsafe { - (*self.palette.get())[get_mirror_palette(addr) as usize] = data; - }} + pub fn write_palette(&mut self, addr: u16, data: u8) { + self.palette[get_mirror_palette(addr) as usize] = data + } #[inline(always)] pub fn read_mapper(&self, addr: u16) -> u8 { - self.mapper.read(addr) + self.mapper.borrow().read(addr) } #[inline(always)] fn write_mapper(&self, addr: u16, data: u8) { - self.mapper.write(addr, data); + self.mapper.borrow_mut().write(addr, data); } } @@ -200,7 +196,7 @@ impl<'a> VMem for PPUMemory<'a> { } } - fn write(&self, mut addr: u16, data: u8) { + fn write(&mut self, mut addr: u16, data: u8) { addr &= 0x3fff; if addr < 0x2000 { self.write_mapper(addr, data); @@ -5,8 +5,8 @@ use core::intrinsics::transmute; pub trait Screen { #[inline(always)] - fn put(&self, x: u8, y: u8, color: u8); - fn render(&self); + fn put(&mut self, x: u8, y: u8, color: u8); + fn render(&mut self); } #[repr(C, packed)] @@ -53,7 +53,7 @@ pub struct PPU<'a> { early_read: Option<bool>, /* IO */ mem: PPUMemory<'a>, - scr: &'a Screen, + scr: &'a mut Screen, } impl<'a> PPU<'a> { @@ -443,7 +443,7 @@ impl<'a> PPU<'a> { })); } - pub fn new(mem: PPUMemory<'a>, scr: &'a Screen) -> Self { + pub fn new(mem: PPUMemory<'a>, scr: &'a mut Screen) -> Self { let ppuctl = 0x00; let ppumask = 0x00; let ppustatus = 0xa0; |