diff --git a/examples/web/chip_ahoyto.d.ts b/examples/web/chip_ahoyto.d.ts index 629da9d741decc70f5468e51671bcb730da43d7f..f8874e8f2084f3913c19ce763be8d86303dcf0b4 100644 --- a/examples/web/chip_ahoyto.d.ts +++ b/examples/web/chip_ahoyto.d.ts @@ -26,6 +26,10 @@ export class Chip8Neo { */ reset_hard_ws(): void; /** +* @returns {Uint8Array} +*/ + vram_ws(): Uint8Array; +/** */ clock_ws(): void; } @@ -41,8 +45,11 @@ export interface InitOutput { 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_vram_ws: (a: number, b: number) => void; readonly chip8neo_clock_ws: (a: number) => void; readonly __wbindgen_malloc: (a: number) => number; + readonly __wbindgen_add_to_stack_pointer: (a: number) => number; + readonly __wbindgen_free: (a: number, b: number) => void; readonly __wbindgen_exn_store: (a: number) => void; } diff --git a/examples/web/chip_ahoyto.js b/examples/web/chip_ahoyto.js index ef9c5a44897074ec59a0b63e0399c7157973a2b9..a1dfc0901badade7479d9329847a6eed07de7d37 100644 --- a/examples/web/chip_ahoyto.js +++ b/examples/web/chip_ahoyto.js @@ -67,6 +67,18 @@ function passArray8ToWasm0(arg, malloc) { return ptr; } +let cachedInt32Memory0; +function getInt32Memory0() { + if (cachedInt32Memory0.byteLength === 0) { + cachedInt32Memory0 = new Int32Array(wasm.memory.buffer); + } + return cachedInt32Memory0; +} + +function getArrayU8FromWasm0(ptr, len) { + return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len); +} + function logError(f, args) { try { return f.apply(this, args); @@ -90,10 +102,6 @@ function handleError(f, args) { wasm.__wbindgen_exn_store(addHeapObject(e)); } } - -function getArrayU8FromWasm0(ptr, len) { - return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len); -} /** */ export class Chip8Classic { @@ -176,6 +184,24 @@ export class Chip8Neo { wasm.chip8neo_reset_hard_ws(this.ptr); } /** + * @returns {Uint8Array} + */ + vram_ws() { + try { + if (this.ptr == 0) throw new Error('Attempt to use a moved value'); + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + _assertNum(this.ptr); + wasm.chip8neo_vram_ws(retptr, this.ptr); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var v0 = getArrayU8FromWasm0(r0, r1).slice(); + wasm.__wbindgen_free(r0, r1 * 1); + return v0; + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + } + } + /** */ clock_ws() { if (this.ptr == 0) throw new Error('Attempt to use a moved value'); @@ -341,6 +367,7 @@ function initMemory(imports, maybe_memory) { function finalizeInit(instance, module) { wasm = instance.exports; init.__wbindgen_wasm_module = module; + cachedInt32Memory0 = new Int32Array(wasm.memory.buffer); cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); diff --git a/examples/web/chip_ahoyto_bg.wasm b/examples/web/chip_ahoyto_bg.wasm index 43dfb96327c653b8664d889c35069827ad856c3a..21dabefd9e3d00745f8db9023d32a4039529a271 100644 Binary files a/examples/web/chip_ahoyto_bg.wasm and b/examples/web/chip_ahoyto_bg.wasm differ diff --git a/examples/web/chip_ahoyto_bg.wasm.d.ts b/examples/web/chip_ahoyto_bg.wasm.d.ts index 9d1e41adf98ea2f3081aef369b886c0407c178fb..9677a6dc6a64da20c3020c8f5e8ee5249c0899d7 100644 --- a/examples/web/chip_ahoyto_bg.wasm.d.ts +++ b/examples/web/chip_ahoyto_bg.wasm.d.ts @@ -8,6 +8,9 @@ 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_vram_ws(a: number, b: number): void; export function chip8neo_clock_ws(a: number): void; export function __wbindgen_malloc(a: number): number; +export function __wbindgen_add_to_stack_pointer(a: number): number; +export function __wbindgen_free(a: number, b: number): void; export function __wbindgen_exn_store(a: number): void; diff --git a/examples/web/index.html b/examples/web/index.html index b50d7ca094ab34a9da9f5c4a71fb09587700089e..ca1964d732444776f6b1d2aba1e0a0323a6a2c52 100644 --- a/examples/web/index.html +++ b/examples/web/index.html @@ -4,6 +4,7 @@ <title>CHIP-Ahoyto</title> </head> <body> + <canvas id="chip-canvas" width="960" height="480"></canvas> <script type="module" src="./index.js"></script> </body> </html> diff --git a/examples/web/index.js b/examples/web/index.js index 5dab7bfe9e4c8774b35e30b8fc3bcdd40acffcb8..a164b80a09e9032a60b4dd6dcde20eb56bf3f30e 100644 --- a/examples/web/index.js +++ b/examples/web/index.js @@ -1,4 +1,19 @@ -import { default as wasm, Chip8Neo } from "./chip_ahoyto.js"; +import { + default as wasm, + Chip8Neo +} from "./chip_ahoyto.js"; + +const PIXEL_SET_COLOR = 0x50cb93ff; +const PIXEL_UNSET_COLOR = 0x1b1a17ff; + +const state = { + canvas: null, + canvasScaled: null, + canvasCtx: null, + canvasScaledCtx: null, + image: null, + videoBuff: null +}; (async () => { // initializes the WASM module, this is required @@ -7,8 +22,10 @@ import { default as wasm, Chip8Neo } from "./chip_ahoyto.js"; const ROM = "roms/ibm_logo.ch8"; - console.info("LOADED"); + console.info("System Loaded!"); + // loads the ROM data and converts it into the + // target u8 array bufffer const response = await fetch(ROM); const blob = await response.blob(); const arrayBuffer = await blob.arrayBuffer(); @@ -19,7 +36,43 @@ import { default as wasm, Chip8Neo } from "./chip_ahoyto.js"; chip8.reset_hard_ws(); chip8.load_rom_ws(data); - console.info(`Loaded ${ROM}`); + console.info(`ROM Loaded ${ROM}`); - chip8.clock_ws(); + initCanvas(); + + while (true) { + chip8.clock_ws(); + updateCanvas(chip8.vram_ws()); + + // hack + await new Promise((resolve, reject) => { + setTimeout(resolve, 100); + }) + } })(); + +const initCanvas = () => { + // initializes the off-screen canvas that is going to be + // used in the drawing proces + state.canvas = document.createElement("canvas"); + state.canvas.width = 64; + state.canvas.height = 32; + state.canvasCtx = state.canvas.getContext("2d"); + + state.canvasScaled = document.getElementById("chip-canvas"); + state.canvasScaledCtx = state.canvasScaled.getContext("2d"); + + state.canvasScaledCtx.scale(state.canvasScaled.width / state.canvas.width, state.canvasScaled.height / state.canvas.height); + state.canvasScaledCtx.imageSmoothingEnabled = false; + + 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++) { + state.videoBuff.setUint32(i * 4, pixels[i] ? PIXEL_SET_COLOR : PIXEL_UNSET_COLOR); + } + 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 730a15ae5418c2ca4ddef11e3a09dd10ce59b383..0b01cfafe72de6cf60095fd69c6832b25e87be80 100644 --- a/src/chip8_neo.rs +++ b/src/chip8_neo.rs @@ -378,6 +378,10 @@ impl Chip8Neo { self.reset_hard() } + pub fn vram_ws(&self) -> Vec<u8> { + self.vram() + } + pub fn clock_ws(&mut self) { self.clock() }