arnaucube
arnaucube/chip8-rsPublic Self-hosted repository
Add Sdl rendering, Add keyboard input
arnaucube root@arnaucube.com
Sun, 18 Oct 2020 10:28:36 +0200
commit

d68feb1fd98117ecb8c065ae60accb35fe058ffd

parent

2bcc24b2a91e80f4fc085fd3a00601b7cd10146a

M README.md → README.md

@@ -1,6 +1,6 @@

# chip8-rs CHIP-8 emulator written in Rust. -(Done from the Go implementation: https://github.com/arnaucube/go-chip8) +(Done with the Go implementation: https://github.com/arnaucube/go-chip8) https://en.wikipedia.org/wiki/CHIP-8
M chip8/src/lib.rs → chip8/src/lib.rs

@@ -16,7 +16,7 @@ delay_timer: u8,

sound_timer: u8, stack: [u16; 16], sp: isize, - key: [u8; 16], + pub key: [u8; 16], pub draw_flag: bool, }

@@ -71,12 +71,13 @@ 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; + 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; + // println!("{:?} {:?}", self.opcode, self.pc); // Decode Opcode // https://en.wikipedia.org/wiki/CHIP-8#Opcode_table

@@ -275,7 +276,7 @@ }

if self.gfx[pos] == 1 { self.v[0xF] = 1; } else { - self.v[0xF] ^= 1; + self.gfx[pos] ^= 1; } } }

@@ -367,7 +368,7 @@ self.memory[self.index as usize + i] = self.v[i];

} self.pc += 2; } - 0x0064 => { + 0x0065 => { // 0xFX65 Fills V0 to VX (including VX) with values // from memory starting at address I. The offset from I // is increased by 1 for each value written, but I

@@ -381,6 +382,15 @@ _ => println!("unk {:x}", self.opcode),

} } _ => println!("opc {:x}", self.opcode), + } + if self.delay_timer > 0 { + self.delay_timer -= 1; + } + if self.sound_timer > 0 { + if self.sound_timer == 1 { + println!("Beep"); + } + self.sound_timer -= 1; } } }
M src/main.rs → src/main.rs

@@ -1,6 +1,11 @@

+use std::collections::HashMap; +use std::{thread, time}; extern crate sdl2; +use sdl2::event::Event; +use sdl2::keyboard::Keycode; use sdl2::pixels::Color; +use sdl2::rect::Rect; use sdl2::render::Canvas; use clap::{App, Arg};

@@ -11,7 +16,9 @@ struct SdlEmulator {

w: usize, h: usize, zoom: usize, + sdl_context: sdl2::Sdl, canvas: Canvas<sdl2::video::Window>, + vkeys: HashMap<Keycode, u8>, chip8: Chip8, }

@@ -23,26 +30,97 @@ let sdl_context = sdl2::init().unwrap();

let video_subsystem = sdl_context.video().unwrap(); let window = video_subsystem - .window("rust-sdl2 demo", 800, 600) + .window("rust-sdl2 demo", (w * zoom) as u32, (h * zoom) as u32) .position_centered() .build() .unwrap(); let mut canvas = window.into_canvas().build().unwrap(); + let mut vkeys: HashMap<Keycode, u8> = HashMap::new(); + vkeys.insert(Keycode::Num1, 0x01); + vkeys.insert(Keycode::Num2, 0x02); + vkeys.insert(Keycode::Num3, 0x03); + vkeys.insert(Keycode::Num4, 0x0c); + vkeys.insert(Keycode::Q, 0x04); + vkeys.insert(Keycode::W, 0x05); + vkeys.insert(Keycode::E, 0x06); + vkeys.insert(Keycode::R, 0x07); + vkeys.insert(Keycode::A, 0x08); + vkeys.insert(Keycode::S, 0x09); + vkeys.insert(Keycode::D, 0x0E); + vkeys.insert(Keycode::F, 0x0A); + vkeys.insert(Keycode::Z, 0x00); + vkeys.insert(Keycode::X, 0x0B); + vkeys.insert(Keycode::V, 0x0F); + SdlEmulator { w, h, zoom, + sdl_context, canvas, + vkeys, chip8: c, } } fn draw_graphics(&mut self) { - // TODO + self.canvas.set_draw_color(Color::RGB(0, 0, 0)); + self.canvas.clear(); + self.canvas.set_draw_color(Color::RGB(255, 255, 255)); + for y in 0..self.h { + for x in 0..self.w { + let pixel = self.chip8.gfx[y * self.w + x]; + if pixel != 0 { + self.canvas.fill_rect(Rect::new( + (x * self.zoom) as i32, + (y * self.zoom) as i32, + (self.zoom) as u32, + (self.zoom) as u32, + )); + } + } + } + + self.canvas.present(); + self.chip8.draw_flag = false; } - fn set_keys(&mut self) { - // TODO + fn set_keys(&mut self) -> Result<(), String> { + let mut events = self.sdl_context.event_pump()?; + for event in events.poll_iter() { + match event { + Event::Quit { .. } => { + println!("Quit"); + std::process::exit(0); + } + Event::KeyDown { + keycode: Some(keycode), + .. + } => { + println!("k {:?}", keycode); + if self.vkeys.contains_key(&keycode) { + let k_hex = self.vkeys.get(&keycode).unwrap(); + self.chip8.key[*k_hex as usize] = 1; + } + } + Event::KeyUp { + keycode: Some(keycode), + .. + } => { + println!("k {:?}", keycode); + if self.vkeys.contains_key(&keycode) { + let k_hex = self.vkeys.get(&keycode).unwrap(); + self.chip8.key[*k_hex as usize] = 0; + } + if keycode == Keycode::Escape { + println!("EXIT"); + std::process::exit(0); + } + } + _ => {} + } + } + Ok(()) } }

@@ -66,12 +144,14 @@ };

println!("{:?}", file); let mut e = SdlEmulator::new(64, 32, 8); + e.chip8.load_game(file); + loop { e.chip8.emulate_cycle(); if e.chip8.draw_flag { e.draw_graphics(); } e.set_keys(); - // delay + std::thread::sleep(time::Duration::from_millis(1000 / 60)); } }