import wasmInit, { NesWasm, KeyState } from "nes-wasm"; const keymap: { [key: string]: number } = { ['a']: 7, ['b']: 6, [' ']: 5, ['Enter']: 4, ['ArrowUp']: 3, ['ArrowDown']: 2, ['ArrowLeft']: 1, ['ArrowRight']: 0, }; export class BrowserNes { nes: NesWasm; mem: WebAssembly.Memory; ctx: CanvasRenderingContext2D; frame_buffer: Uint8ClampedArray; frame_ready: boolean; keyboard: KeyState[]; killed: boolean; constructor(ctx: CanvasRenderingContext2D, mem: WebAssembly.Memory, bincart: Uint8Array) { this.nes = NesWasm.new(this, bincart); this.ctx = ctx; this.mem = mem; this.frame_buffer = undefined; this.frame_ready = false; this.keyboard = new Array(8).fill(KeyState.None); document.addEventListener('keydown', (ev) => { let btn = keymap[ev.key]; if (btn != null) { this.keyboard[btn] = KeyState.Pressed; } }) document.addEventListener('keyup', (ev) => { let btn = keymap[ev.key]; if (btn != null) { this.keyboard[btn] = KeyState.Released; console.log(this.keyboard); // LOL setTimeout(() => { this.keyboard[btn] = KeyState.None; }, 20); } }) } poll_keyboard(ptr: number) { let state = new Uint8ClampedArray(this.mem.buffer, ptr, 8); state.set(this.keyboard) } on_frame_ready(frame_ptr: number, len: number) { if (!this.frame_buffer) { this.frame_buffer = new Uint8ClampedArray(this.mem.buffer, frame_ptr, len); } this.ctx.putImageData(new ImageData(this.frame_buffer, 256, 240), 0, 0); this.frame_ready = true; } loop() { const inner = () => { this.frame_ready = false; while (!this.frame_ready) { this.nes.tick(); } if (!this.killed) { requestAnimationFrame(inner); } } requestAnimationFrame(inner); } kill() { this.killed = true; } } const ctx = document.getElementById('c').getContext('2d'); const wasm = await wasmInit(); let instance = new BrowserNes(ctx, wasm.memory, []); // empty bin == nestest instance.loop(); document.getElementById('file').addEventListener('change', (input: any) => { const file: File = input.target.files[0] const reader = new FileReader() reader.onload = async () => { if (instance != null) { instance.kill(); instance = null; } const bincart = new Uint8Array(reader.result) instance = new BrowserNes(ctx, wasm.memory, bincart); instance.loop(); } reader.onerror = () => { alert(reader.error) } if (file) { reader.readAsArrayBuffer(file) } })