Compare commits

...

2 Commits

Author SHA1 Message Date
Michael Kohl 2789742dfd Add virtual keyboard 2021-04-01 18:32:18 +07:00
Michael Kohl 0b75270984 Update LICENSE 2021-04-01 18:31:38 +07:00
4 changed files with 113 additions and 3 deletions

View File

@ -1,4 +1,4 @@
MIT License Copyright (c) <year> <copyright holders>
MIT License Copyright (c) 2021 Michael Kohl
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,3 +1,37 @@
# rust-chip-8
A CHIP-8 emulator written in Rust
A CHIP-8 emulator written in Rust
## Keyboard mapping
CHIP-8 systems used a hexidecimal keyboard with the following layout:
|---|---|---|---|
| 1 | 2 | 3 | C |
|---|---|---|---|
| 4 | 5 | 6 | D |
|---|---|---|---|
| 7 | 8 | 0 | E |
|---|---|---|---|
| A | 0 | B | F |
|---|---|---|---|
In this emulator the following keys are mapped to the above layout:
|---|---|---|---|
| 1 | 2 | 3 | 4 |
|---|---|---|---|
| Q | W | E | R |
|---|---|---|---|
| A | S | D | F |
|---|---|---|---|
| Z | X | C | V |
|---|---|---|---|
So to get "deadbeef" inside the emulator you'd have to type "rfzrcffv".
## License
MIT License Copyright (c) 2021 Michael Kohl
For the full license text see [LICENSE](./LICENSE).

View File

@ -1,8 +1,11 @@
use sdl2::keyboard::Keycode;
const MEMORY_SIZE: usize = 4096;
const WIDTH: u32 = 64;
const HEIGHT: u32 = 32;
const DATA_REGISTERS: usize = 16;
const STACK_DEPTH: usize = 16;
const KEYS: usize = 16;
pub const SCALE_FACTOR: u32 = 10;
pub const WINDOW_WIDTH: u32 = WIDTH * SCALE_FACTOR;
@ -45,10 +48,13 @@ struct Registers {
type Stack = [u16; STACK_DEPTH];
type Keyboard = [bool; KEYS];
pub struct Chip8 {
memory: Memory,
registers: Registers,
stack: Stack,
keyboard: Keyboard,
}
fn data_register_to_index(register: Register) -> usize {
@ -86,6 +92,7 @@ impl Chip8 {
sp: 0,
},
stack: [0; STACK_DEPTH],
keyboard: [false; KEYS],
}
}
@ -131,6 +138,40 @@ impl Chip8 {
assert!((self.registers.sp as usize) < STACK_DEPTH, "stack overflow");
self.stack[self.registers.sp as usize]
}
pub fn keyboard_map(&self, key: Keycode) -> Option<usize> {
match key {
Keycode::Num1 => Some(1),
Keycode::Num2 => Some(2),
Keycode::Num3 => Some(3),
Keycode::Num4 => Some(12),
Keycode::Q => Some(4),
Keycode::W => Some(5),
Keycode::E => Some(6),
Keycode::R => Some(13),
Keycode::A => Some(7),
Keycode::S => Some(8),
Keycode::D => Some(9),
Keycode::F => Some(14),
Keycode::Z => Some(10),
Keycode::X => Some(0),
Keycode::C => Some(11),
Keycode::V => Some(15),
_ => None,
}
}
pub fn key_down(&mut self, key: usize) -> () {
self.keyboard[key] = true
}
pub fn key_up(&mut self, key: usize) -> () {
self.keyboard[key] = false
}
pub fn is_key_down(&self, key: usize) -> bool {
self.keyboard[key]
}
}
#[cfg(test)]
@ -202,4 +243,21 @@ mod tests {
assert_eq!(chip8.stack_pop(), 255);
assert_eq!(chip8.register_get(Register::SP), 0);
}
#[test]
fn it_maps_physical_keys_to_virtual_ones() {
let mut chip8 = Chip8::new();
assert_eq!(chip8.keyboard_map(Keycode::A), Some(7));
assert_eq!(chip8.keyboard_map(Keycode::X), Some(0));
assert_eq!(chip8.keyboard_map(Keycode::M), None);
}
#[test]
fn it_can_press_and_release_keys() {
let mut chip8 = Chip8::new();
chip8.key_down(1);
assert!(chip8.is_key_down(1));
chip8.key_up(1);
assert!(!chip8.is_key_down(1));
}
}

View File

@ -1,5 +1,5 @@
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::keyboard::{Keycode, Scancode};
use sdl2::pixels::Color;
use sdl2::rect::Rect;
@ -8,6 +8,8 @@ mod chip8;
const EMULATOR_WINDOW_TITLE: &str = "Rust CHIP-8";
fn main() -> Result<(), String> {
let mut chip8 = chip8::Chip8::new();
let sdl_context = sdl2::init()?;
let video_subsystem = sdl_context.video()?;
@ -46,6 +48,22 @@ fn main() -> Result<(), String> {
} => {
break 'mainloop;
}
Event::KeyDown {
keycode: Some(key), ..
} => {
if let Some(vkey) = chip8.keyboard_map(key) {
chip8.key_down(vkey);
println!("key down: {}", vkey);
}
}
Event::KeyUp {
keycode: Some(key), ..
} => {
if let Some(vkey) = chip8.keyboard_map(key) {
chip8.key_up(vkey);
println!("key up: {}", vkey);
}
}
_ => {}
}
}