diff --git a/vweb/src/emulator_display.jsx b/vweb/src/emulator_display.jsx index 57bf35b..b9e7d47 100644 --- a/vweb/src/emulator_display.jsx +++ b/vweb/src/emulator_display.jsx @@ -1,16 +1,25 @@ -import React, { useState, useCallback, useEffect, useRef } from 'react' -import { WasmCPU } from '../pkg/vweb.js' +import React, { useCallback, useEffect, useRef } from 'react' +import { WasmCPU, Display } from '../pkg/vweb.js' export default function({}) { const canvas = useRef(null) - const [ctx, setCtx] = useState(null) - const [cpu, _setCpu] = useState(new WasmCPU()) + const cpu = useRef(new WasmCPU()) + const ctx = useRef(null) + const display = useRef(null) + const request = useRef(null) + + const drawFrame = useCallback(() => { + display.current.draw(cpu.current, ctx.current) + request.current = requestAnimationFrame(drawFrame) + }, []) useEffect(() => { - const c = canvas.current.getContext('2d') - setCtx(c) - cpu.draw_frame(c) + ctx.current = canvas.current.getContext('2d') + display.current = new Display() + request.current = requestAnimationFrame(drawFrame) + return () => cancelAnimationFrame(request.current) }, [canvas.current]) + return ( ) diff --git a/vweb/src/lib.rs b/vweb/src/lib.rs index 9cb4f79..6d9d306 100644 --- a/vweb/src/lib.rs +++ b/vweb/src/lib.rs @@ -25,6 +25,10 @@ impl NovaForth { #[wasm_bindgen] pub struct WasmCPU(CPU); +// This has to contain a Box or else it'll use up all the wasm_bindgen stack space +#[wasm_bindgen] +pub struct Display(Box<[u8; 640 * 480 * 4]>); + #[wasm_bindgen(inspectable, getter_with_clone)] #[derive(Serialize, Deserialize)] pub struct JsVasmError { @@ -68,9 +72,9 @@ pub fn source_map(snippet: String) -> JsValue { impl WasmCPU { #[wasm_bindgen(constructor)] pub fn new() -> WasmCPU { - let mut cpu = WasmCPU(CPU::new_random()); - display::init_gfx(&mut cpu.0); - cpu + let mut cpu = CPU::new_random(); + display::init_gfx(&mut cpu); + WasmCPU(cpu) } pub fn push_data(&mut self, data: i32) { @@ -162,11 +166,20 @@ impl WasmCPU { pub fn tick(&mut self) { self.0.tick() } - - pub fn draw_frame(&self, ctx: &CanvasRenderingContext2d) -> Result<(), JsValue> { - let mut buf = [0u8; 640 * 480 * 4]; - display::draw(&self.0, &mut buf); - let image_data = ImageData::new_with_u8_clamped_array(Clamped(&buf), 640)?; - ctx.put_image_data(&image_data, 0.0, 0.0) - } } + +#[wasm_bindgen] +impl Display { + #[wasm_bindgen(constructor)] + pub fn new() -> Display { + Display([0u8; 640 * 480 * 4].into()) + } + + pub fn draw(&mut self, cpu: &WasmCPU, ctx: &CanvasRenderingContext2d) -> Result<(), JsValue> { + display::draw(&cpu.0, self.0.as_mut()); + let image_data = ImageData::new_with_u8_clamped_array(Clamped(self.0.as_mut()), 640)?; + ctx.put_image_data(&image_data, 0.0, 0.0); + Ok(()) + + } +} \ No newline at end of file