aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs175
1 files changed, 166 insertions, 9 deletions
diff --git a/src/main.rs b/src/main.rs
index 447fa85..cd39d39 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,24 +4,181 @@ mod mos6502;
mod ppu;
mod cartridge;
mod mapper;
-use core::ptr::null_mut;
+
+use std::fs::File;
+use std::io::Read;
+use core::cell::RefCell;
+use core::intrinsics::transmute;
+use cartridge::*;
+
+
+extern crate sdl2;
+
+use sdl2::pixels::Color;
+use sdl2::rect::Rect;
struct Window {
+ buff: RefCell<[[u8; 256]; 240]>
}
impl ppu::Screen for Window {
- fn put(&mut self, x: u8, y: u8, color: u8) {
- println!("put color 0x{:02x} at ({}, {})", color, x, y);
+ fn put(&self, x: u8, y: u8, color: u8) {
+ self.buff.borrow_mut()[y as usize][x as usize] = color;
}
fn render(&self) {
- println!("a frame has been redrawn");
+ println!("a frame has been redrawn:");
+ for r in self.buff.borrow().iter() {
+ for c in r.iter() {
+ print!("{:02x}", c);
+ }
+ println!("");
+ }
+ }
+}
+
+struct SDLWindow {
+ canvas: RefCell<sdl2::render::WindowCanvas>
+}
+
+impl SDLWindow {
+ fn new() -> Self {
+ let sdl_context = sdl2::init().unwrap();
+ let video_subsystem = sdl_context.video().unwrap();
+ let window = video_subsystem.window("rust-sdl2 demo: Video", 256 * PIXEL_SIZE, 240 * PIXEL_SIZE)
+ .position_centered()
+ .opengl()
+ .build()
+ .unwrap();
+ let mut canvas = window.into_canvas().build().unwrap();
+ canvas.set_draw_color(Color::RGB(255, 255, 255));
+ canvas.clear();
+ canvas.present();
+ SDLWindow {
+ canvas: RefCell::new(canvas)
+ }
}
}
+const PIXEL_SIZE: u32 = 2;
+const COLORS: [u32; 64] = [
+ 0x666666, 0x002A88, 0x1412A7, 0x3B00A4, 0x5C007E, 0x6E0040, 0x6C0600, 0x561D00,
+ 0x333500, 0x0B4800, 0x005200, 0x004F08, 0x00404D, 0x000000, 0x000000, 0x000000,
+ 0xADADAD, 0x155FD9, 0x4240FF, 0x7527FE, 0xA01ACC, 0xB71E7B, 0xB53120, 0x994E00,
+ 0x6B6D00, 0x388700, 0x0C9300, 0x008F32, 0x007C8D, 0x000000, 0x000000, 0x000000,
+ 0xFFFEFF, 0x64B0FF, 0x9290FF, 0xC676FF, 0xF36AFF, 0xFE6ECC, 0xFE8170, 0xEA9E22,
+ 0xBCBE00, 0x88D800, 0x5CE430, 0x45E082, 0x48CDDE, 0x4F4F4F, 0x000000, 0x000000,
+ 0xFFFEFF, 0xC0DFFF, 0xD3D2FF, 0xE8C8FF, 0xFBC2FF, 0xFEC4EA, 0xFECCC5, 0xF7D8A5,
+ 0xE4E594, 0xCFEF96, 0xBDF4AB, 0xB3F3CC, 0xB5EBF2, 0xB8B8B8, 0x000000, 0x000000,
+];
+
+fn get_rgb(color: u8) -> Color {
+ let c = COLORS[color as usize];
+ Color::RGB((c >> 16) as u8, ((c >> 8) & 0xff) as u8, (c & 0xff) as u8)
+}
+
+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.draw_rect(Rect::new((x as u32 * PIXEL_SIZE) as i32,
+ (y as u32 * PIXEL_SIZE) as i32,
+ PIXEL_SIZE, PIXEL_SIZE));
+ }
+
+ fn render(&self) {
+ let mut canvas = self.canvas.borrow_mut();
+ canvas.present();
+ canvas.clear();
+ }
+}
+
+#[repr(C, packed)]
+struct INesHeader {
+ magic: [u8; 4],
+ prg_rom_nbanks: u8,
+ chr_rom_nbanks: u8,
+ flags6: u8,
+ flags7: u8,
+ prg_ram_nbanks: u8,
+ flags9: u8,
+ flags10: u8,
+ padding: [u8; 5]
+}
+
fn main() {
- //let mut ppu = ppu::PPU::new(
- let mut cart = cartridge::Cartridge::new();
- let mut mapper = mapper::Mapper2::new(&mut cart);
- let mut mem = memory::CPUMemory::new(null_mut(), null_mut(), &mut mapper);
- let cpu = mos6502::CPU::new(&mut mem);
+ let fname = std::env::args().nth(1).unwrap();
+ let mut file = File::open(fname).unwrap();
+ let mut rheader = [0; 16];
+ println!("read {}", file.read(&mut rheader[..]).unwrap());
+ let header = unsafe{transmute::<[u8; 16], INesHeader>(rheader)};
+ let mirror = match ((header.flags6 >> 2) & 2) | (header.flags6 & 1) {
+ 0 => MirrorType::Horizontal,
+ 1 => MirrorType::Vertical,
+ 2 => MirrorType::Single0,
+ 3 => MirrorType::Single1,
+ _ => MirrorType::Four,
+ };
+ let mapper_id = (header.flags7 & 0xf0) | (header.flags6 >> 4);
+ println!("maigc:{} prg:{} chr:{} mirror:{} mapper:{}",
+ std::str::from_utf8(&header.magic).unwrap(),
+ header.prg_rom_nbanks,
+ header.chr_rom_nbanks,
+ mirror as u8,
+ mapper_id);
+ if header.flags6 & 0x04 == 0x04 {
+ let mut trainer: [u8; 512] = unsafe{std::mem::uninitialized()};
+ file.read(&mut trainer[..]);
+ println!("skipping trainer");
+ }
+
+ let prg_len = header.prg_rom_nbanks as usize * 0x4000;
+ let mut chr_len = header.chr_rom_nbanks as usize * 0x2000;
+ 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 sram = vec![0; 0x4000];
+ println!("read prg {}", file.read(&mut prg_rom[..]).unwrap());
+ for (i, v) in prg_rom.iter().enumerate() {
+ print!("{:02x} ", v);
+ if i & 15 == 15 {
+ println!(" {:04x}", i);
+ }
+ }
+ println!("read chr {}", file.read(&mut chr_rom[..]).unwrap());
+ for (i, v) in chr_rom.iter().enumerate() {
+ print!("{:02x} ", v);
+ if i & 15 == 15 {
+ println!("");
+ }
+ }
+ let cart = cartridge::Cartridge::new(chr_rom, prg_rom, sram, mirror);
+ //let win = Window {buff: RefCell::new([[0; 256]; 240])};
+ let win = SDLWindow::new();
+ let mapper = mapper::Mapper2::new(&cart);
+ let pmem = memory::PPUMemory::new(&mapper, &cart);
+ let mem = memory::CPUMemory::new(&mapper);
+ let mut ppu = ppu::PPU::new(&pmem, &win);
+ let mut cpu = mos6502::CPU::new(&mem);
+ mem.init(&mut cpu, &mut ppu);
+
+ loop {
+ 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();
+ }
+ }
+ cpu.cycle -= 1;
+ }
+ }
}