From b471138b5a681ad11447853873e113b4e545b69f 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 16:57:42 +0100 Subject: [PATCH] feat: support for keys in wasm --- examples/web/chip_ahoyto.d.ts | 10 +++ examples/web/chip_ahoyto.js | 12 ++++ examples/web/chip_ahoyto_bg.wasm | Bin 36474 -> 36751 bytes examples/web/chip_ahoyto_bg.wasm.d.ts | 2 + examples/web/index.js | 85 +++++++++++++++++++++----- src/chip8_neo.rs | 8 +++ 6 files changed, 103 insertions(+), 14 deletions(-) diff --git a/examples/web/chip_ahoyto.d.ts b/examples/web/chip_ahoyto.d.ts index f7ec932..77a84e7 100644 --- a/examples/web/chip_ahoyto.d.ts +++ b/examples/web/chip_ahoyto.d.ts @@ -38,6 +38,14 @@ export class Chip8Neo { /** */ clock_st_ws(): void; +/** +* @param {number} key +*/ + key_press_ws(key: number): void; +/** +* @param {number} key +*/ + key_lift_ws(key: number): void; } export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; @@ -53,6 +61,8 @@ export interface InitOutput { readonly chip8neo_clock_ws: (a: number) => void; readonly chip8neo_clock_dt_ws: (a: number) => void; readonly chip8neo_clock_st_ws: (a: number) => void; + readonly chip8neo_key_press_ws: (a: number, b: number) => void; + readonly chip8neo_key_lift_ws: (a: number, b: number) => void; readonly __wbg_chip8classic_free: (a: number) => void; readonly chip8classic_new: () => number; readonly __wbindgen_malloc: (a: number) => number; diff --git a/examples/web/chip_ahoyto.js b/examples/web/chip_ahoyto.js index f66794c..c83bdce 100644 --- a/examples/web/chip_ahoyto.js +++ b/examples/web/chip_ahoyto.js @@ -180,6 +180,18 @@ export class Chip8Neo { clock_st_ws() { wasm.chip8neo_clock_st_ws(this.ptr); } + /** + * @param {number} key + */ + key_press_ws(key) { + wasm.chip8neo_key_press_ws(this.ptr, key); + } + /** + * @param {number} key + */ + key_lift_ws(key) { + wasm.chip8neo_key_lift_ws(this.ptr, key); + } } async function load(module, imports) { diff --git a/examples/web/chip_ahoyto_bg.wasm b/examples/web/chip_ahoyto_bg.wasm index 863046d35e007e90f80b2f3235a5beb152ce8643..8ebcfa0bd0912d5f934cf9ea18f88daeb2dd8275 100644 GIT binary patch delta 3207 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 F1OQDd(!T%z delta 2944 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 diff --git a/examples/web/chip_ahoyto_bg.wasm.d.ts b/examples/web/chip_ahoyto_bg.wasm.d.ts index 20b6672..d5813e8 100644 --- a/examples/web/chip_ahoyto_bg.wasm.d.ts +++ b/examples/web/chip_ahoyto_bg.wasm.d.ts @@ -10,6 +10,8 @@ export function chip8neo_vram_ws(a: number, b: number): void; export function chip8neo_clock_ws(a: number): void; export function chip8neo_clock_dt_ws(a: number): void; export function chip8neo_clock_st_ws(a: number): void; +export function chip8neo_key_press_ws(a: number, b: number): void; +export function chip8neo_key_lift_ws(a: number, b: number): void; export function __wbg_chip8classic_free(a: number): void; export function chip8classic_new(): number; export function __wbindgen_malloc(a: number): number; diff --git a/examples/web/index.js b/examples/web/index.js index 65ad984..4ba8e46 100644 --- a/examples/web/index.js +++ b/examples/web/index.js @@ -6,10 +6,29 @@ import { const PIXEL_SET_COLOR = 0x50cb93ff; const PIXEL_UNSET_COLOR = 0x1b1a17ff; -const LOGIC_HZ = 480; +let LOGIC_HZ = 480; const TIMER_HZ = 60; const VISUAL_HZ = 60; +const KEYS = { + "1": 0x01, + "2": 0x02, + "3": 0x03, + "4": 0x0c, + "q": 0x04, + "w": 0x05, + "e": 0x06, + "r": 0x0d, + "a": 0x07, + "s": 0x08, + "d": 0x09, + "f": 0x0e, + "z": 0x0a, + "x": 0x00, + "c": 0x0b, + "v": 0x0f +} + const ROM = "res/roms/pong.ch8"; const state = { @@ -27,9 +46,10 @@ const state = { // so that the global symbols become available await wasm(); - // initializes the canvas sub-sytem - initCanvas(); - registerDrop(); + // initializes the complete set of sub-systems + // and registers the event handlers + init(); + register(); // loads the ROM data and converts it into the // target u8 array bufffer @@ -69,14 +89,19 @@ const state = { } })(); +const register = () => { + registerDrop(); + registerKeys(); +} + const registerDrop = () => { - document.addEventListener("drop", async (e) => { - e.preventDefault(); - e.stopPropagation(); + document.addEventListener("drop", async (event) => { + event.preventDefault(); + event.stopPropagation(); - if (!e.dataTransfer.files) return; + if (!event.dataTransfer.files) return; - const file = e.dataTransfer.files[0]; + const file = event.dataTransfer.files[0]; const arrayBuffer = await file.arrayBuffer(); const data = new Uint8Array(arrayBuffer); @@ -84,12 +109,44 @@ const registerDrop = () => { state.chip8.reset_hard_ws(); state.chip8.load_rom_ws(data); }); - document.addEventListener("dragover", async (e) => { - e.preventDefault(); - e.stopPropagation(); + document.addEventListener("dragover", async (event) => { + event.preventDefault(); + event.stopPropagation(); console.info("draging over"); }); +}; + +const registerKeys = () => { + document.addEventListener("keydown", (event) => { + const keyCode = KEYS[event.key]; + if (keyCode) { + state.chip8.key_press_ws(keyCode); + return; + } + + switch(event.key) { + case "+": + LOGIC_HZ += 60; + break; + + case "-": + LOGIC_HZ += 60; + break; + } + }); + + document.addEventListener("keyup", (event) => { + const keyCode = KEYS[event.key]; + if (keyCode) { + state.chip8.key_lift_ws(keyCode); + return; + } + }); +} + +const init = () => { + initCanvas(); } const initCanvas = () => { @@ -108,7 +165,7 @@ const initCanvas = () => { state.image = state.canvasCtx.createImageData(state.canvas.width, state.canvas.height); state.videoBuff = new DataView(state.image.data.buffer); -} +}; const updateCanvas = (pixels) => { for (let i = 0; i < pixels.length; i++) { @@ -116,4 +173,4 @@ const updateCanvas = (pixels) => { } state.canvasCtx.putImageData(state.image, 0, 0); state.canvasScaledCtx.drawImage(state.canvas, 0, 0); -} +}; diff --git a/src/chip8_neo.rs b/src/chip8_neo.rs index 17a7c82..fa81ef5 100644 --- a/src/chip8_neo.rs +++ b/src/chip8_neo.rs @@ -393,6 +393,14 @@ impl Chip8Neo { 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 { -- GitLab