diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..62061be --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "chip8-rs" +version = "0.0.1" +authors = ["arnaucube "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +clap = "2.33.3" +chip8 = {path="./chip8"} diff --git a/README.md b/README.md new file mode 100644 index 0000000..5c33c5f --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# chip8-rs + +CHIP-8 emulator written in Rust. +(Done from the Go implementation: https://github.com/arnaucube/go-chip8) + +https://en.wikipedia.org/wiki/CHIP-8 diff --git a/chip8/.gitignore b/chip8/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/chip8/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/chip8/Cargo.toml b/chip8/Cargo.toml new file mode 100644 index 0000000..e67dfc4 --- /dev/null +++ b/chip8/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "chip8" +version = "0.1.0" +authors = ["arnaucube "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/chip8/src/lib.rs b/chip8/src/lib.rs new file mode 100644 index 0000000..ab0fea2 --- /dev/null +++ b/chip8/src/lib.rs @@ -0,0 +1,93 @@ +use std::fs; +use std::io::Read; + +const w: usize = 64; +const h: usize = 32; + +pub struct Chip8 { + opcode: u16, + memory: [u8; 4096], + v: [u8; 16], + index: u16, + pc: u16, + gfx: [u8; w * h], + delay_timer: u8, + sound_timer: u8, + stack: [u16; 16], + sp: isize, + key: [u8; 16], + pub draw_flag: bool, +} + +const font_set: [u8; 80] = [ + 0xF0, 0x90, 0x90, 0x90, 0xF0, // 0 + 0x20, 0x60, 0x20, 0x20, 0x70, // 1 + 0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2 + 0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3 + 0x90, 0x90, 0xF0, 0x10, 0x10, // 4 + 0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5 + 0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6 + 0xF0, 0x10, 0x20, 0x40, 0x40, // 7 + 0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8 + 0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9 + 0xF0, 0x90, 0xF0, 0x90, 0x90, // A + 0xE0, 0x90, 0xE0, 0x90, 0xE0, // B + 0xF0, 0x80, 0x80, 0x80, 0xF0, // C + 0xE0, 0x90, 0x90, 0x90, 0xE0, // D + 0xF0, 0x80, 0xF0, 0x80, 0xF0, // E + 0xF0, 0x80, 0xF0, 0x80, 0x80, // F +]; + +impl Chip8 { + pub fn new() -> Chip8 { + let mut c = Chip8 { + opcode: 0, + memory: [0; 4096], + v: [0; 16], + index: 0, + pc: 0x200, + gfx: [0; w * h], + delay_timer: 0, + sound_timer: 0, + stack: [0; 16], + sp: 0, + key: [0; 16], + draw_flag: false, + }; + + for i in 0..font_set.len() { + c.memory[i] = font_set[i]; + } + c + } + pub fn load_game(&mut self, filepath: &str) { + let mut f = fs::File::open(filepath).expect("can not load rom file"); + let metadata = fs::metadata(filepath).expect("unable to read metadata"); + let mut b = vec![0; metadata.len() as usize]; + f.read(&mut b).expect("buffer overflow"); + for i in 0..b.len() { + self.memory[512 + i] = b[i]; + } + } + pub fn emulate_cycle(&mut self) { + self.opcode = (self.memory[self.pc as usize] as u16) << 8 + | self.memory[(self.pc + 1) as usize] as u16; + let x: usize = ((self.opcode & 0x0F00) >> 8) as usize; + let y: usize = ((self.opcode & 0x00F0) >> 4) as usize; + let nn: u8 = (self.opcode & 0x00FF) as u8; + let nnn: u16 = (self.opcode & 0x0FFF) as u16; + // TODO + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_load_game() { + let mut c = Chip8::new(); + c.load_game("Cargo.toml"); + c.emulate_cycle(); + // println!("{:?}", c.memory); + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..b8c3a24 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,59 @@ +use clap::{App, Arg}; + +use chip8::Chip8; + +struct SdlEmulator { + w: usize, + h: usize, + zoom: usize, + chip8: Chip8, +} + +impl SdlEmulator { + fn new(w: usize, h: usize, zoom: usize) -> SdlEmulator { + let mut c = Chip8::new(); + + SdlEmulator { + w, + h, + zoom, + chip8: c, + } + } + fn draw_graphics(&mut self) { + // TODO + } + fn set_keys(&mut self) { + // TODO + } +} + +fn main() { + let matches = App::new("chip8-rs") + .version("0.0.1") + .about("chip8 emulator") + .arg( + Arg::with_name("file") + .short("f") + .long("file") + .takes_value(true) + .help("File path of the rom to load"), + ) + .get_matches(); + let file = matches.value_of("file"); + let file = match file { + Some(file) => file, + _ => panic!("Please specify file path of the rom to load"), + }; + println!("{:?}", file); + + let mut e = SdlEmulator::new(64, 32, 8); + loop { + e.chip8.emulate_cycle(); + if e.chip8.draw_flag { + e.draw_graphics(); + } + e.set_keys(); + // delay + } +}