Browse Source

Add Sdl rendering, Add keyboard input

main
arnaucube 3 years ago
parent
commit
d68feb1fd9
8 changed files with 101 additions and 11 deletions
  1. +1
    -1
      README.md
  2. +15
    -5
      chip8/src/lib.rs
  3. BIN
      roms/TETRIS
  4. BIN
      roms/chip8-picture.ch8
  5. BIN
      roms/invaders.c8
  6. BIN
      roms/pong.c8
  7. BIN
      roms/slipperyslope.ch8
  8. +85
    -5
      src/main.rs

+ 1
- 1
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

+ 15
- 5
chip8/src/lib.rs

@ -16,7 +16,7 @@ pub struct Chip8 {
sound_timer: u8,
stack: [u16; 16],
sp: isize,
key: [u8; 16],
pub key: [u8; 16],
pub draw_flag: bool,
}
@ -71,12 +71,13 @@ impl Chip8 {
}
}
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 @@ impl Chip8 {
if self.gfx[pos] == 1 {
self.v[0xF] = 1;
} else {
self.v[0xF] ^= 1;
self.gfx[pos] ^= 1;
}
}
}
@ -367,7 +368,7 @@ impl Chip8 {
}
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
@ -382,6 +383,15 @@ impl Chip8 {
}
_ => 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;
}
}
}

BIN
roms/TETRIS


BIN
roms/chip8-picture.ch8


BIN
roms/invaders.c8


BIN
roms/pong.c8


BIN
roms/slipperyslope.ch8


+ 85
- 5
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 @@ impl SdlEmulator {
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 @@ fn main() {
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));
}
}

Loading…
Cancel
Save