Uninitialized canvas display

This commit is contained in:
2023-02-01 20:31:06 -06:00
parent 910e4b856b
commit 5259d6ee8c
7 changed files with 46 additions and 4 deletions
+8
View File
@@ -10,7 +10,15 @@ crate-type = ["cdylib"]
[dependencies] [dependencies]
vcore = { path = "../vcore" } vcore = { path = "../vcore" }
vgfx = { path = "../vgfx" }
vasm_core = { path = "../vasm_core" } vasm_core = { path = "../vasm_core" }
wasm-bindgen = "0.2" wasm-bindgen = "0.2"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.4" serde-wasm-bindgen = "0.4"
[dependencies.web-sys]
version = "0.3.4"
features = [
'CanvasRenderingContext2d',
'ImageData',
]
+17
View File
@@ -0,0 +1,17 @@
import React, { useState, useCallback, useEffect, useRef } from 'react'
import { WasmCPU } from '../pkg/vweb.js'
export default function({}) {
const canvas = useRef(null)
const [ctx, setCtx] = useState(null)
const [cpu, _setCpu] = useState(new WasmCPU())
useEffect(() => {
const c = canvas.current.getContext('2d')
setCtx(c)
cpu.draw_frame(c)
}, [canvas.current])
return (
<canvas ref={canvas} width={640} height={480}></canvas>
)
}
+13 -1
View File
@@ -2,7 +2,10 @@ use wasm_bindgen::prelude::*;
use vcore::{CPU, Word}; use vcore::{CPU, Word};
use vcore::memory::{PeekPoke, PeekPokeExt}; use vcore::memory::{PeekPoke, PeekPokeExt};
use vasm_core::parse_error::AssembleError; use vasm_core::parse_error::AssembleError;
use vgfx::display;
use serde::{ Deserialize, Serialize }; use serde::{ Deserialize, Serialize };
use wasm_bindgen::Clamped;
use web_sys::{CanvasRenderingContext2d, ImageData};
#[wasm_bindgen] #[wasm_bindgen]
pub struct NovaForth; pub struct NovaForth;
@@ -65,7 +68,9 @@ pub fn source_map(snippet: String) -> JsValue {
impl WasmCPU { impl WasmCPU {
#[wasm_bindgen(constructor)] #[wasm_bindgen(constructor)]
pub fn new() -> WasmCPU { pub fn new() -> WasmCPU {
WasmCPU(CPU::new_random()) let mut cpu = WasmCPU(CPU::new_random());
display::init_gfx(&mut cpu.0);
cpu
} }
pub fn push_data(&mut self, data: i32) { pub fn push_data(&mut self, data: i32) {
@@ -157,4 +162,11 @@ impl WasmCPU {
pub fn tick(&mut self) { pub fn tick(&mut self) {
self.0.tick() 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)
}
} }
+2 -2
View File
@@ -9,13 +9,13 @@ body {
grid-area: 2 / 2 / 3 / 3; grid-area: 2 / 2 / 3 / 3;
} }
.main .snippet { .main .snippet, .main .display {
display: grid; display: grid;
grid-template-rows: auto; grid-template-rows: auto;
grid-template-columns: 1fr auto 1fr; grid-template-columns: 1fr auto 1fr;
} }
.snippet .snippetEmulator { .main .snippet .snippetEmulator, .main .display canvas {
grid-area: 1 / 2 / 2 / 3; grid-area: 1 / 2 / 2 / 3;
} }
+1 -1
View File
@@ -21,7 +21,7 @@ export default function({ children, width = 20 }) {
const onChangeSrc = useCallback((e) => setSrc(e.target.value), []) // Callback for the textarea const onChangeSrc = useCallback((e) => setSrc(e.target.value), []) // Callback for the textarea
const [binary, setBinary] = useState(null) // The assembled binary const [binary, setBinary] = useState(null) // The assembled binary
const [sourceMap, setSourceMap] = useState(null) // A map from byte address to line number const [sourceMap, setSourceMap] = useState(null) // A map from byte address to line number
const [cpu, setCpu] = useState(new WasmCPU()) // The actual CPU emulator itself const [cpu, _setCpu] = useState(new WasmCPU()) // The actual CPU emulator itself
const [activeLine, setActiveLine] = useState(null) // The (0-based) index of the const [activeLine, setActiveLine] = useState(null) // The (0-based) index of the
// Update which line is highlighted. This should be called in most button callbacks. // Update which line is highlighted. This should be called in most button callbacks.
+1
View File
@@ -15,6 +15,7 @@
Quisque tristique diam et purus sagittis, posuere pharetra orci egestas. Praesent imperdiet sapien vel fermentum Quisque tristique diam et purus sagittis, posuere pharetra orci egestas. Praesent imperdiet sapien vel fermentum
pulvinar. Nulla ac tortor laoreet, fringilla tellus nec, ullamcorper mi. pulvinar. Nulla ac tortor laoreet, fringilla tellus nec, ullamcorper mi.
</p> </p>
<div class="display"></div>
<div class="snippet" data-width="30"> <div class="snippet" data-width="30">
<pre> <pre>
.org 0x400 .org 0x400
+4
View File
@@ -1,6 +1,7 @@
import { createRoot } from 'react-dom/client' import { createRoot } from 'react-dom/client'
import React from 'react' import React from 'react'
import SnippetEmulator from './snippet_emulator' import SnippetEmulator from './snippet_emulator'
import EmulatorDisplay from './emulator_display'
import init, { WasmCPU, assemble_snippet } from '../pkg/vweb.js' import init, { WasmCPU, assemble_snippet } from '../pkg/vweb.js'
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
@@ -9,5 +10,8 @@ document.addEventListener('DOMContentLoaded', () => {
const props = { children: el.innerText, width: el.getAttribute('data-width') } const props = { children: el.innerText, width: el.getAttribute('data-width') }
createRoot(el).render(React.createElement(SnippetEmulator, props)) createRoot(el).render(React.createElement(SnippetEmulator, props))
}) })
document.querySelectorAll('.display').forEach((el) => {
createRoot(el).render(React.createElement(EmulatorDisplay, {}))
})
}) })
}) })