Skip to content

Commit

Permalink
Added was interface
Browse files Browse the repository at this point in the history
  • Loading branch information
aowalke2 committed Mar 17, 2024
1 parent c0647d0 commit 00dbeec
Show file tree
Hide file tree
Showing 11 changed files with 915 additions and 4 deletions.
139 changes: 139 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
workspace = { members = ["desktop", "core"]}
[workspace]
members = ["desktop", "core", "wasm"]

resolver = "2"
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,32 @@

In my quest to build a GBA emulator in rust, I started with a CHIP-8 interpreter in rust

## Running locally

Make sure you have the latest version of rust installed

### Mac Os

- Install [Homebrew](https://brew.sh/)
- Install sdl2 with homebrow: `brew install sdl2`
- Add this `export LIBRARY_PATH="$LIBRARY_PATH:$(brew --prefix)/lib"` to your .zshrc file if you use zsh or your .bashrc file if you use bash
- In root directory of this project do cargo run and point it at the chip8 rom file you would like to run. Ex. `cargo run /ROM_ADDRESS`

### Linux

- Install sdl2 with: `sudo apt update && sudo apt install -y libsdl2`
- Add this `export LIBRARY_PATH="$LIBRARY_PATH:$(brew --prefix)/lib"` to your .zshrc file if you use zsh or your .bashrc file if you use bash
- In root directory of this project do cargo run and point it at the chip8 rom file you would like to run. Ex. `cargo run /ROM_ADDRESS`

## WASM

- Make sure you have wasm-pack installed. If not use `cargo install wasm-pack`
- cd into the wasm directory of this project
- Run: `wasm-pack build --target web`
- Run: `mv pkg/wasm_bg.wasm ../web`
- Run: `mv pkg/wasm.js ../web`
- cd to the main project directory and then start a web server of you choice

## Sources

- [Cowgod's Chip-8 Technical Reference](http://devernay.free.fr/hacks/chip8/C8TECH10.HTM)
Expand Down
3 changes: 1 addition & 2 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ name = "core"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
getrandom = { version = "0.2.12", features = ["js"] }
rand = "0.8.5"
2 changes: 1 addition & 1 deletion core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ impl Interpreter {
}

#[cfg(test)]
mod test {
mod tests {
use super::*;

#[test]
Expand Down
21 changes: 21 additions & 0 deletions wasm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "wasm"
version = "0.1.0"
edition = "2021"

[dependencies]
core = {path = "../core"}
js-sys = "^0.3.69"
wasm-bindgen = "^0.2.92"
web-sys = {version = "^0.3.69", features = [
"CanvasRenderingContext2d",
"Document",
"Element",
"HtmlCanvasElement",
"ImageData",
"KeyboardEvent",
"Window"
]}

[lib]
crate-type = ["cdylib"]
101 changes: 101 additions & 0 deletions wasm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use core::*;
use js_sys::Uint8Array;
use wasm_bindgen::prelude::*;
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement, KeyboardEvent};

#[wasm_bindgen]
pub struct InterpreterWasm {
chip8: Interpreter,
context: CanvasRenderingContext2d,
}

#[wasm_bindgen]
impl InterpreterWasm {
#[wasm_bindgen(constructor)]
pub fn new() -> Result<InterpreterWasm, JsValue> {
let chip8 = Interpreter::new();

let document = web_sys::window().unwrap().document().unwrap();
let canvas = document.get_element_by_id("canvas").unwrap();
let canvas: HtmlCanvasElement = canvas
.dyn_into::<HtmlCanvasElement>()
.map_err(|_| ())
.unwrap();

let context = canvas
.get_context("2d")
.unwrap()
.unwrap()
.dyn_into::<CanvasRenderingContext2d>()
.unwrap();

Ok(InterpreterWasm { chip8, context })
}

#[wasm_bindgen]
pub fn tick(&mut self) {
self.chip8.tick();
}

#[wasm_bindgen]
pub fn tick_timers(&mut self) {
self.chip8.tick_timers();
}

#[wasm_bindgen]
pub fn reset(&mut self) {
self.chip8.reset();
}

#[wasm_bindgen]
pub fn keypress(&mut self, event: KeyboardEvent, pressed: bool) {
let key = event.key();
if let Some(k) = match_key_to_btn(&key) {
self.chip8.keypress(k, pressed);
}
}

#[wasm_bindgen]
pub fn load(&mut self, data: Uint8Array) {
self.chip8.load(&data.to_vec());
}

#[wasm_bindgen]
pub fn draw_screen(&mut self, scale: usize) {
let display = self.chip8.get_screen();
for row in 0..display.len() {
for col in 0..display[0].len() {
if display[row][col] {
self.context.fill_rect(
(col * scale) as f64,
(row * scale) as f64,
scale as f64,
scale as f64,
);
}
}
}
}
}

fn match_key_to_btn(key: &str) -> Option<usize> {
match key {
"1" => Some(0x1),
"2" => Some(0x2),
"3" => Some(0x3),
"4" => Some(0xC),
"q" => Some(0x4),
"w" => Some(0x5),
"e" => Some(0x6),
"r" => Some(0xD),
"a" => Some(0x7),
"s" => Some(0x8),
"d" => Some(0x9),
"f" => Some(0xE),
"z" => Some(0xA),
"x" => Some(0x0),
"c" => Some(0xB),
"v" => Some(0xF),
_ => None,
}
}
17 changes: 17 additions & 0 deletions web/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<title>Chip-8</title>
<meta charset="utf-8" />
</head>
<body>
<h1>Chip-8 Interpreter</h1>
<label for="fileinput">Upload a Chip-8 game</label>
<input type="file" id="fileinput" autocomplete="off" />
<br />
<canvas id="canvas">
If you see this message, then your browser doesn't support HTML5
</canvas>
</body>
<script type="module" src="index.js"></script>
</html>
Loading

0 comments on commit 00dbeec

Please sign in to comment.