From 5ec145e0544bf81d56ab620a80dcabe3507c42b3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Magalh=C3=A3es?= <joamag@gmail.com>
Date: Sun, 19 Jun 2022 15:21:41 +0100
Subject: [PATCH] feat: initial WASM version

---
 README.md                             |   9 +-
 examples/web/chip_ahoyto.d.ts         |  57 +++++
 examples/web/chip_ahoyto.js           | 312 ++++++++++++++++++++++++++
 examples/web/chip_ahoyto_bg.wasm      | Bin 0 -> 37577 bytes
 examples/web/chip_ahoyto_bg.wasm.d.ts |  13 ++
 examples/web/index.html               |   9 +
 examples/web/index.js                 |  14 ++
 src/chip8_neo.rs                      | 185 ++++++++-------
 8 files changed, 515 insertions(+), 84 deletions(-)
 create mode 100644 examples/web/chip_ahoyto.d.ts
 create mode 100644 examples/web/chip_ahoyto.js
 create mode 100644 examples/web/chip_ahoyto_bg.wasm
 create mode 100644 examples/web/chip_ahoyto_bg.wasm.d.ts
 create mode 100644 examples/web/index.html
 create mode 100644 examples/web/index.js

diff --git a/README.md b/README.md
index ed27bc0..3c2257f 100644
--- a/README.md
+++ b/README.md
@@ -25,13 +25,20 @@ The work of this emulator was inspired/started by [jc-chip8](https://github.com/
 
 ## Build
 
-### WASM
+### WASM for Node.js
 
 ```bash
 cargo install wasm-pack
 wasm-pack build --release --target=nodejs -- --features wasm
 ```
 
+### WASM for Web
+
+```bash
+cargo install wasm-pack
+wasm-pack build --release --target=web -- --features wasm
+```
+
 ## Reason
 
 And... yes this is the real inspiration behind the emulator's name:
diff --git a/examples/web/chip_ahoyto.d.ts b/examples/web/chip_ahoyto.d.ts
new file mode 100644
index 0000000..967df31
--- /dev/null
+++ b/examples/web/chip_ahoyto.d.ts
@@ -0,0 +1,57 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+*/
+export class Chip8Classic {
+  free(): void;
+/**
+*/
+  constructor();
+}
+/**
+*/
+export class Chip8Neo {
+  free(): void;
+/**
+*/
+  constructor();
+/**
+* @param {Uint8Array} rom
+*/
+  load_rom_ws(rom: Uint8Array): void;
+/**
+*/
+  reset_ws(): void;
+/**
+*/
+  reset_hard_ws(): void;
+/**
+*/
+  clock_ws(): void;
+}
+
+export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
+
+export interface InitOutput {
+  readonly memory: WebAssembly.Memory;
+  readonly __wbg_chip8neo_free: (a: number) => void;
+  readonly chip8neo_new: () => number;
+  readonly chip8neo_load_rom_ws: (a: number, b: number, c: number) => void;
+  readonly chip8neo_reset_ws: (a: number) => void;
+  readonly chip8neo_reset_hard_ws: (a: number) => void;
+  readonly chip8neo_clock_ws: (a: number) => void;
+  readonly __wbg_chip8classic_free: (a: number) => void;
+  readonly chip8classic_new: () => number;
+  readonly __wbindgen_malloc: (a: number) => number;
+  readonly __wbindgen_exn_store: (a: number) => void;
+}
+
+/**
+* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
+* for everything else, calls `WebAssembly.instantiate` directly.
+*
+* @param {InitInput | Promise<InitInput>} module_or_path
+*
+* @returns {Promise<InitOutput>}
+*/
+export default function init (module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>;
diff --git a/examples/web/chip_ahoyto.js b/examples/web/chip_ahoyto.js
new file mode 100644
index 0000000..792feab
--- /dev/null
+++ b/examples/web/chip_ahoyto.js
@@ -0,0 +1,312 @@
+
+let wasm;
+
+const heap = new Array(32).fill(undefined);
+
+heap.push(undefined, null, true, false);
+
+function getObject(idx) { return heap[idx]; }
+
+let heap_next = heap.length;
+
+function dropObject(idx) {
+    if (idx < 36) return;
+    heap[idx] = heap_next;
+    heap_next = idx;
+}
+
+function takeObject(idx) {
+    const ret = getObject(idx);
+    dropObject(idx);
+    return ret;
+}
+
+function addHeapObject(obj) {
+    if (heap_next === heap.length) heap.push(heap.length + 1);
+    const idx = heap_next;
+    heap_next = heap[idx];
+
+    heap[idx] = obj;
+    return idx;
+}
+
+const cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
+
+cachedTextDecoder.decode();
+
+let cachegetUint8Memory0 = null;
+function getUint8Memory0() {
+    if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== wasm.memory.buffer) {
+        cachegetUint8Memory0 = new Uint8Array(wasm.memory.buffer);
+    }
+    return cachegetUint8Memory0;
+}
+
+function getStringFromWasm0(ptr, len) {
+    return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
+}
+
+let WASM_VECTOR_LEN = 0;
+
+function passArray8ToWasm0(arg, malloc) {
+    const ptr = malloc(arg.length * 1);
+    getUint8Memory0().set(arg, ptr / 1);
+    WASM_VECTOR_LEN = arg.length;
+    return ptr;
+}
+
+function handleError(f, args) {
+    try {
+        return f.apply(this, args);
+    } catch (e) {
+        wasm.__wbindgen_exn_store(addHeapObject(e));
+    }
+}
+
+function getArrayU8FromWasm0(ptr, len) {
+    return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
+}
+/**
+*/
+export class Chip8Classic {
+
+    static __wrap(ptr) {
+        const obj = Object.create(Chip8Classic.prototype);
+        obj.ptr = ptr;
+
+        return obj;
+    }
+
+    __destroy_into_raw() {
+        const ptr = this.ptr;
+        this.ptr = 0;
+
+        return ptr;
+    }
+
+    free() {
+        const ptr = this.__destroy_into_raw();
+        wasm.__wbg_chip8classic_free(ptr);
+    }
+    /**
+    */
+    constructor() {
+        const ret = wasm.chip8classic_new();
+        return Chip8Classic.__wrap(ret);
+    }
+}
+/**
+*/
+export class Chip8Neo {
+
+    static __wrap(ptr) {
+        const obj = Object.create(Chip8Neo.prototype);
+        obj.ptr = ptr;
+
+        return obj;
+    }
+
+    __destroy_into_raw() {
+        const ptr = this.ptr;
+        this.ptr = 0;
+
+        return ptr;
+    }
+
+    free() {
+        const ptr = this.__destroy_into_raw();
+        wasm.__wbg_chip8neo_free(ptr);
+    }
+    /**
+    */
+    constructor() {
+        const ret = wasm.chip8neo_new();
+        return Chip8Neo.__wrap(ret);
+    }
+    /**
+    * @param {Uint8Array} rom
+    */
+    load_rom_ws(rom) {
+        const ptr0 = passArray8ToWasm0(rom, wasm.__wbindgen_malloc);
+        const len0 = WASM_VECTOR_LEN;
+        wasm.chip8neo_load_rom_ws(this.ptr, ptr0, len0);
+    }
+    /**
+    */
+    reset_ws() {
+        wasm.chip8neo_reset_ws(this.ptr);
+    }
+    /**
+    */
+    reset_hard_ws() {
+        wasm.chip8neo_reset_hard_ws(this.ptr);
+    }
+    /**
+    */
+    clock_ws() {
+        wasm.chip8neo_clock_ws(this.ptr);
+    }
+}
+
+async function load(module, imports) {
+    if (typeof Response === 'function' && module instanceof Response) {
+        if (typeof WebAssembly.instantiateStreaming === 'function') {
+            try {
+                return await WebAssembly.instantiateStreaming(module, imports);
+
+            } catch (e) {
+                if (module.headers.get('Content-Type') != 'application/wasm') {
+                    console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
+
+                } else {
+                    throw e;
+                }
+            }
+        }
+
+        const bytes = await module.arrayBuffer();
+        return await WebAssembly.instantiate(bytes, imports);
+
+    } else {
+        const instance = await WebAssembly.instantiate(module, imports);
+
+        if (instance instanceof WebAssembly.Instance) {
+            return { instance, module };
+
+        } else {
+            return instance;
+        }
+    }
+}
+
+async function init(input) {
+    if (typeof input === 'undefined') {
+        input = new URL('chip_ahoyto_bg.wasm', import.meta.url);
+    }
+    const imports = {};
+    imports.wbg = {};
+    imports.wbg.__wbg_process_e56fd54cf6319b6c = function(arg0) {
+        const ret = getObject(arg0).process;
+        return addHeapObject(ret);
+    };
+    imports.wbg.__wbindgen_is_object = function(arg0) {
+        const val = getObject(arg0);
+        const ret = typeof(val) === 'object' && val !== null;
+        return ret;
+    };
+    imports.wbg.__wbg_versions_77e21455908dad33 = function(arg0) {
+        const ret = getObject(arg0).versions;
+        return addHeapObject(ret);
+    };
+    imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
+        takeObject(arg0);
+    };
+    imports.wbg.__wbg_node_0dd25d832e4785d5 = function(arg0) {
+        const ret = getObject(arg0).node;
+        return addHeapObject(ret);
+    };
+    imports.wbg.__wbindgen_is_string = function(arg0) {
+        const ret = typeof(getObject(arg0)) === 'string';
+        return ret;
+    };
+    imports.wbg.__wbg_static_accessor_NODE_MODULE_26b231378c1be7dd = function() {
+        const ret = module;
+        return addHeapObject(ret);
+    };
+    imports.wbg.__wbg_require_0db1598d9ccecb30 = function() { return handleError(function (arg0, arg1, arg2) {
+        const ret = getObject(arg0).require(getStringFromWasm0(arg1, arg2));
+        return addHeapObject(ret);
+    }, arguments) };
+    imports.wbg.__wbg_crypto_b95d7173266618a9 = function(arg0) {
+        const ret = getObject(arg0).crypto;
+        return addHeapObject(ret);
+    };
+    imports.wbg.__wbg_msCrypto_5a86d77a66230f81 = function(arg0) {
+        const ret = getObject(arg0).msCrypto;
+        return addHeapObject(ret);
+    };
+    imports.wbg.__wbg_getRandomValues_b14734aa289bc356 = function() { return handleError(function (arg0, arg1) {
+        getObject(arg0).getRandomValues(getObject(arg1));
+    }, arguments) };
+    imports.wbg.__wbg_randomFillSync_91e2b39becca6147 = function() { return handleError(function (arg0, arg1, arg2) {
+        getObject(arg0).randomFillSync(getArrayU8FromWasm0(arg1, arg2));
+    }, arguments) };
+    imports.wbg.__wbg_newnoargs_e23b458e372830de = function(arg0, arg1) {
+        const ret = new Function(getStringFromWasm0(arg0, arg1));
+        return addHeapObject(ret);
+    };
+    imports.wbg.__wbg_call_ae78342adc33730a = function() { return handleError(function (arg0, arg1) {
+        const ret = getObject(arg0).call(getObject(arg1));
+        return addHeapObject(ret);
+    }, arguments) };
+    imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
+        const ret = getObject(arg0);
+        return addHeapObject(ret);
+    };
+    imports.wbg.__wbg_self_99737b4dcdf6f0d8 = function() { return handleError(function () {
+        const ret = self.self;
+        return addHeapObject(ret);
+    }, arguments) };
+    imports.wbg.__wbg_window_9b61fbbf3564c4fb = function() { return handleError(function () {
+        const ret = window.window;
+        return addHeapObject(ret);
+    }, arguments) };
+    imports.wbg.__wbg_globalThis_8e275ef40caea3a3 = function() { return handleError(function () {
+        const ret = globalThis.globalThis;
+        return addHeapObject(ret);
+    }, arguments) };
+    imports.wbg.__wbg_global_5de1e0f82bddcd27 = function() { return handleError(function () {
+        const ret = global.global;
+        return addHeapObject(ret);
+    }, arguments) };
+    imports.wbg.__wbindgen_is_undefined = function(arg0) {
+        const ret = getObject(arg0) === undefined;
+        return ret;
+    };
+    imports.wbg.__wbg_buffer_7af23f65f6c64548 = function(arg0) {
+        const ret = getObject(arg0).buffer;
+        return addHeapObject(ret);
+    };
+    imports.wbg.__wbg_new_cc9018bd6f283b6f = function(arg0) {
+        const ret = new Uint8Array(getObject(arg0));
+        return addHeapObject(ret);
+    };
+    imports.wbg.__wbg_set_f25e869e4565d2a2 = function(arg0, arg1, arg2) {
+        getObject(arg0).set(getObject(arg1), arg2 >>> 0);
+    };
+    imports.wbg.__wbg_length_0acb1cf9bbaf8519 = function(arg0) {
+        const ret = getObject(arg0).length;
+        return ret;
+    };
+    imports.wbg.__wbg_newwithlength_8f0657faca9f1422 = function(arg0) {
+        const ret = new Uint8Array(arg0 >>> 0);
+        return addHeapObject(ret);
+    };
+    imports.wbg.__wbg_subarray_da527dbd24eafb6b = function(arg0, arg1, arg2) {
+        const ret = getObject(arg0).subarray(arg1 >>> 0, arg2 >>> 0);
+        return addHeapObject(ret);
+    };
+    imports.wbg.__wbindgen_throw = function(arg0, arg1) {
+        throw new Error(getStringFromWasm0(arg0, arg1));
+    };
+    imports.wbg.__wbindgen_memory = function() {
+        const ret = wasm.memory;
+        return addHeapObject(ret);
+    };
+
+    if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
+        input = fetch(input);
+    }
+
+
+
+    const { instance, module } = await load(await input, imports);
+
+    wasm = instance.exports;
+    init.__wbindgen_wasm_module = module;
+
+    return wasm;
+}
+
+export default init;
+
diff --git a/examples/web/chip_ahoyto_bg.wasm b/examples/web/chip_ahoyto_bg.wasm
new file mode 100644
index 0000000000000000000000000000000000000000..e5178df226f9cd406c380e432a15724c30a377ba
GIT binary patch
literal 37577
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%0D~j9KmoWS5C{a_c$1~Vz^#hm6i{XW?SMpXCptjF
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

literal 0
HcmV?d00001

diff --git a/examples/web/chip_ahoyto_bg.wasm.d.ts b/examples/web/chip_ahoyto_bg.wasm.d.ts
new file mode 100644
index 0000000..2f8c42c
--- /dev/null
+++ b/examples/web/chip_ahoyto_bg.wasm.d.ts
@@ -0,0 +1,13 @@
+/* tslint:disable */
+/* eslint-disable */
+export const memory: WebAssembly.Memory;
+export function __wbg_chip8neo_free(a: number): void;
+export function chip8neo_new(): number;
+export function chip8neo_load_rom_ws(a: number, b: number, c: number): void;
+export function chip8neo_reset_ws(a: number): void;
+export function chip8neo_reset_hard_ws(a: number): void;
+export function chip8neo_clock_ws(a: number): void;
+export function __wbg_chip8classic_free(a: number): void;
+export function chip8classic_new(): number;
+export function __wbindgen_malloc(a: number): number;
+export function __wbindgen_exn_store(a: number): void;
diff --git a/examples/web/index.html b/examples/web/index.html
new file mode 100644
index 0000000..b50d7ca
--- /dev/null
+++ b/examples/web/index.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>CHIP-Ahoyto</title>
+    </head>
+    <body>
+        <script type="module" src="./index.js"></script>
+    </body>
+</html>
diff --git a/examples/web/index.js b/examples/web/index.js
new file mode 100644
index 0000000..f35c253
--- /dev/null
+++ b/examples/web/index.js
@@ -0,0 +1,14 @@
+import { default as wasm, Chip8Neo } from "./chip_ahoyto.js";
+
+(async () => {
+    // initializes the WASM module, this is required
+    // so that the global symbols become available
+    await wasm();
+
+    console.info("LOADED");
+
+    const chip8 = new Chip8Neo();
+    chip8.clock_ws();
+
+    console.info("CLOCK");
+})();
diff --git a/src/chip8_neo.rs b/src/chip8_neo.rs
index fcf1a76..730a15a 100644
--- a/src/chip8_neo.rs
+++ b/src/chip8_neo.rs
@@ -75,6 +75,89 @@ impl Chip8 for Chip8Neo {
         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) {
         // fetches the current instruction and increments
         // the PC (program counter) accordingly
@@ -224,89 +307,6 @@ impl Chip8 for Chip8Neo {
         }
         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)]
@@ -364,6 +364,25 @@ 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 clock_ws(&mut self) {
+        self.clock()
+    }
+}
+
 impl Default for Chip8Neo {
     fn default() -> Chip8Neo {
         Chip8Neo::new()
-- 
GitLab