Skip to content
Snippets Groups Projects
Commit a006b166 authored by João Magalhães's avatar João Magalhães :rocket:
Browse files

Merge branch 'joamag/wasm' into 'master'

Support for WASM :robot:

See merge request !4
parents 240446b4 dc6bd03d
No related branches found
No related tags found
1 merge request!4Support for WASM 🤖
Pipeline #644 passed
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
File moved
...@@ -2,7 +2,7 @@ use std::fmt::Display; ...@@ -2,7 +2,7 @@ use std::fmt::Display;
use crate::{chip8::Chip8, util::random}; use crate::{chip8::Chip8, util::random};
#[cfg(feature = "web")] #[cfg(feature = "wasm")]
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
/// The width of the screen in pixels. /// The width of the screen in pixels.
...@@ -50,7 +50,7 @@ static FONT_SET: [u8; 80] = [ ...@@ -50,7 +50,7 @@ static FONT_SET: [u8; 80] = [
0xf0, 0x80, 0xf0, 0x80, 0x80, // F 0xf0, 0x80, 0xf0, 0x80, 0x80, // F
]; ];
#[cfg_attr(feature = "web", wasm_bindgen)] #[cfg_attr(feature = "wasm", wasm_bindgen)]
pub struct Chip8Classic { pub struct Chip8Classic {
vram: [u8; SCREEN_PIXEL_WIDTH * SCREEN_PIXEL_HEIGHT], vram: [u8; SCREEN_PIXEL_WIDTH * SCREEN_PIXEL_HEIGHT],
ram: [u8; RAM_SIZE], ram: [u8; RAM_SIZE],
...@@ -66,7 +66,6 @@ pub struct Chip8Classic { ...@@ -66,7 +66,6 @@ pub struct Chip8Classic {
keys: [bool; NUM_KEYS], keys: [bool; NUM_KEYS],
} }
#[cfg_attr(feature = "web", wasm_bindgen)]
impl Chip8 for Chip8Classic { impl Chip8 for Chip8Classic {
fn name(&self) -> &str { fn name(&self) -> &str {
"classic" "classic"
...@@ -152,8 +151,9 @@ impl Chip8 for Chip8Classic { ...@@ -152,8 +151,9 @@ impl Chip8 for Chip8Classic {
} }
} }
#[cfg_attr(feature = "wasm", wasm_bindgen)]
impl Chip8Classic { impl Chip8Classic {
#[cfg_attr(feature = "web", wasm_bindgen(constructor))] #[cfg_attr(feature = "wasm", wasm_bindgen(constructor))]
pub fn new() -> Chip8Classic { pub fn new() -> Chip8Classic {
let mut chip8 = Chip8Classic { let mut chip8 = Chip8Classic {
vram: [0u8; SCREEN_PIXEL_WIDTH * SCREEN_PIXEL_HEIGHT], vram: [0u8; SCREEN_PIXEL_WIDTH * SCREEN_PIXEL_HEIGHT],
......
...@@ -2,6 +2,9 @@ use std::io::{Cursor, Read}; ...@@ -2,6 +2,9 @@ use std::io::{Cursor, Read};
use crate::{chip8::Chip8, util::random}; use crate::{chip8::Chip8, util::random};
#[cfg(feature = "wasm")]
use wasm_bindgen::prelude::*;
pub const DISPLAY_WIDTH: usize = 64; pub const DISPLAY_WIDTH: usize = 64;
pub const DISPLAY_HEIGHT: usize = 32; pub const DISPLAY_HEIGHT: usize = 32;
...@@ -33,6 +36,7 @@ static FONT_SET: [u8; 80] = [ ...@@ -33,6 +36,7 @@ static FONT_SET: [u8; 80] = [
0xf0, 0x80, 0xf0, 0x80, 0x80, // F 0xf0, 0x80, 0xf0, 0x80, 0x80, // F
]; ];
#[cfg_attr(feature = "wasm", wasm_bindgen)]
pub struct Chip8Neo { pub struct Chip8Neo {
ram: [u8; RAM_SIZE], ram: [u8; RAM_SIZE],
vram: [u8; DISPLAY_WIDTH * DISPLAY_HEIGHT], vram: [u8; DISPLAY_WIDTH * DISPLAY_HEIGHT],
...@@ -47,7 +51,6 @@ pub struct Chip8Neo { ...@@ -47,7 +51,6 @@ pub struct Chip8Neo {
last_key: u8, last_key: u8,
} }
#[cfg_attr(feature = "web", wasm_bindgen)]
impl Chip8 for Chip8Neo { impl Chip8 for Chip8Neo {
fn name(&self) -> &str { fn name(&self) -> &str {
"neo" "neo"
...@@ -72,6 +75,89 @@ impl Chip8 for Chip8Neo { ...@@ -72,6 +75,89 @@ impl Chip8 for Chip8Neo {
self.reset(); self.reset();
} }
fn beep(&self) -> bool {
self.st > 0
}
fn pc(&self) -> u16 {
self.pc
}
fn sp(&self) -> u8 {
self.sp
}
fn ram(&self) -> Vec<u8> {
self.ram.to_vec()
}
fn vram(&self) -> Vec<u8> {
self.vram.to_vec()
}
fn get_state(&self) -> Vec<u8> {
let mut buffer: Vec<u8> = Vec::new();
buffer.extend(self.ram.iter());
buffer.extend(self.vram.iter());
buffer.extend(self.stack.map(|v| v.to_le_bytes()).iter().flatten());
buffer.extend(self.regs.iter());
buffer.extend(self.pc.to_le_bytes().iter());
buffer.extend(self.i.to_le_bytes().iter());
buffer.extend(self.sp.to_le_bytes().iter());
buffer.extend(self.dt.to_le_bytes().iter());
buffer.extend(self.st.to_le_bytes().iter());
buffer.extend(self.keys.map(|v| v as u8).iter());
buffer.extend(self.last_key.to_le_bytes().iter());
buffer
}
fn set_state(&mut self, state: &[u8]) {
let mut u8_buffer = [0u8; 1];
let mut u16_buffer = [0u8; 2];
let mut regs_buffer = [0u8; REGISTERS_SIZE * 2];
let mut keys_buffer = [0u8; KEYS_SIZE];
let mut cursor = Cursor::new(state.to_vec());
cursor.read_exact(&mut self.ram).unwrap();
cursor.read_exact(&mut self.vram).unwrap();
cursor.read_exact(&mut regs_buffer).unwrap();
self.stack.clone_from_slice(
regs_buffer
.chunks(2)
.map(|v| {
u16_buffer.clone_from_slice(&v[0..2]);
u16::from_le_bytes(u16_buffer)
})
.collect::<Vec<u16>>()
.as_slice(),
);
cursor.read_exact(&mut self.regs).unwrap();
cursor.read_exact(&mut u16_buffer).unwrap();
self.pc = u16::from_le_bytes(u16_buffer);
cursor.read_exact(&mut u16_buffer).unwrap();
self.i = u16::from_le_bytes(u16_buffer);
cursor.read_exact(&mut u8_buffer).unwrap();
self.sp = u8::from_le_bytes(u8_buffer);
cursor.read_exact(&mut u8_buffer).unwrap();
self.dt = u8::from_le_bytes(u8_buffer);
cursor.read_exact(&mut u8_buffer).unwrap();
self.st = u8::from_le_bytes(u8_buffer);
cursor.read_exact(&mut keys_buffer).unwrap();
self.keys.clone_from_slice(
keys_buffer
.map(|v| if v == 1 { true } else { false })
.iter()
.as_slice(),
);
cursor.read_exact(&mut u8_buffer).unwrap();
self.last_key = u8::from_le_bytes(u8_buffer);
}
fn load_rom(&mut self, rom: &[u8]) {
self.ram[ROM_START..ROM_START + rom.len()].clone_from_slice(&rom);
}
fn clock(&mut self) { fn clock(&mut self) {
// fetches the current instruction and increments // fetches the current instruction and increments
// the PC (program counter) accordingly // the PC (program counter) accordingly
...@@ -221,93 +307,11 @@ impl Chip8 for Chip8Neo { ...@@ -221,93 +307,11 @@ impl Chip8 for Chip8Neo {
} }
self.keys[key as usize] = false; self.keys[key as usize] = false;
} }
fn load_rom(&mut self, rom: &[u8]) {
self.ram[ROM_START..ROM_START + rom.len()].clone_from_slice(&rom);
}
fn beep(&self) -> bool {
self.st > 0
}
fn pc(&self) -> u16 {
self.pc
}
fn sp(&self) -> u8 {
self.sp
}
fn ram(&self) -> Vec<u8> {
self.ram.to_vec()
}
fn vram(&self) -> Vec<u8> {
self.vram.to_vec()
}
fn get_state(&self) -> Vec<u8> {
let mut buffer: Vec<u8> = Vec::new();
buffer.extend(self.ram.iter());
buffer.extend(self.vram.iter());
buffer.extend(self.stack.map(|v| v.to_le_bytes()).iter().flatten());
buffer.extend(self.regs.iter());
buffer.extend(self.pc.to_le_bytes().iter());
buffer.extend(self.i.to_le_bytes().iter());
buffer.extend(self.sp.to_le_bytes().iter());
buffer.extend(self.dt.to_le_bytes().iter());
buffer.extend(self.st.to_le_bytes().iter());
buffer.extend(self.keys.map(|v| v as u8).iter());
buffer.extend(self.last_key.to_le_bytes().iter());
buffer
}
fn set_state(&mut self, state: &[u8]) {
let mut u8_buffer = [0u8; 1];
let mut u16_buffer = [0u8; 2];
let mut regs_buffer = [0u8; REGISTERS_SIZE * 2];
let mut keys_buffer = [0u8; KEYS_SIZE];
let mut cursor = Cursor::new(state.to_vec());
cursor.read_exact(&mut self.ram).unwrap();
cursor.read_exact(&mut self.vram).unwrap();
cursor.read_exact(&mut regs_buffer).unwrap();
self.stack.clone_from_slice(
regs_buffer
.chunks(2)
.map(|v| {
u16_buffer.clone_from_slice(&v[0..2]);
u16::from_le_bytes(u16_buffer)
})
.collect::<Vec<u16>>()
.as_slice(),
);
cursor.read_exact(&mut self.regs).unwrap();
cursor.read_exact(&mut u16_buffer).unwrap();
self.pc = u16::from_le_bytes(u16_buffer);
cursor.read_exact(&mut u16_buffer).unwrap();
self.i = u16::from_le_bytes(u16_buffer);
cursor.read_exact(&mut u8_buffer).unwrap();
self.sp = u8::from_le_bytes(u8_buffer);
cursor.read_exact(&mut u8_buffer).unwrap();
self.dt = u8::from_le_bytes(u8_buffer);
cursor.read_exact(&mut u8_buffer).unwrap();
self.st = u8::from_le_bytes(u8_buffer);
cursor.read_exact(&mut keys_buffer).unwrap();
self.keys.clone_from_slice(
keys_buffer
.map(|v| if v == 1 { true } else { false })
.iter()
.as_slice(),
);
cursor.read_exact(&mut u8_buffer).unwrap();
self.last_key = u8::from_le_bytes(u8_buffer);
}
} }
#[cfg_attr(feature = "wasm", wasm_bindgen)]
impl Chip8Neo { impl Chip8Neo {
#[cfg_attr(feature = "web", wasm_bindgen(constructor))] #[cfg_attr(feature = "wasm", wasm_bindgen(constructor))]
pub fn new() -> Chip8Neo { pub fn new() -> Chip8Neo {
let mut chip8 = Chip8Neo { let mut chip8 = Chip8Neo {
ram: [0u8; RAM_SIZE], ram: [0u8; RAM_SIZE],
...@@ -359,3 +363,48 @@ impl Chip8Neo { ...@@ -359,3 +363,48 @@ impl Chip8Neo {
} }
} }
} }
#[cfg_attr(feature = "wasm", wasm_bindgen)]
impl Chip8Neo {
pub fn load_rom_ws(&mut self, rom: &[u8]) {
self.load_rom(rom)
}
pub fn reset_ws(&mut self) {
self.reset()
}
pub fn reset_hard_ws(&mut self) {
self.reset_hard()
}
pub fn vram_ws(&self) -> Vec<u8> {
self.vram()
}
pub fn clock_ws(&mut self) {
self.clock()
}
pub fn clock_dt_ws(&mut self) {
self.clock_dt()
}
pub fn clock_st_ws(&mut self) {
self.clock_st()
}
pub fn key_press_ws(&mut self, key: u8) {
self.key_press(key)
}
pub fn key_lift_ws(&mut self, key: u8) {
self.key_lift(key)
}
}
impl Default for Chip8Neo {
fn default() -> Chip8Neo {
Chip8Neo::new()
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment