diff --git a/build/plugins/wasmPlugin.ts b/build/plugins/wasmPlugin.ts index c9ca265..d15fd28 100644 --- a/build/plugins/wasmPlugin.ts +++ b/build/plugins/wasmPlugin.ts @@ -107,7 +107,6 @@ async function instantiate(url: string) { initial: 32, }); const table = new WebAssembly.Table({ initial: 16, element: 'anyfunc' }); - let data = new DataView(memory.buffer); const decoder = new TextDecoder(); let buf = ''; let errBuf = ''; @@ -115,12 +114,14 @@ async function instantiate(url: string) { env: { memory, __indirect_function_table: table }, wasi_snapshot_preview1: new Proxy({ random_get: (ptr: number, length: number) => { + const data = new DataView(memory.buffer); for (let i = 0; i < length; i++) { data.setUint8(ptr + i, Math.random() * 256); } }, fd_write: (fd: number, iovsPtr: number, iovsLength: number, bytesWrittenPtr: number) => { const iovs = new Uint32Array(memory.buffer, iovsPtr, iovsLength * 2); + const data = new DataView(memory.buffer); if (fd === 1 || fd === 2) { let text = ""; let totalBytesWritten = 0; @@ -159,7 +160,7 @@ async function instantiate(url: string) { ...instance.exports, memory, table, - get data() { return data; }, + get data() { return new DataView(memory.buffer); }, }; } diff --git a/src/common/display/canvas.ts b/src/common/display/canvas.ts index 44516da..ae065b7 100644 --- a/src/common/display/canvas.ts +++ b/src/common/display/canvas.ts @@ -34,7 +34,7 @@ interface WasmModule { frame?: () => void; } -export function createWasmCanvas(module: WasmModule, width: number, height: number) { +export function createWasmCanvas(module: WasmModule, width: number = 0, height: number = 0) { const pointer = module.init?.(width, height); if (pointer) { diff --git a/src/games/life/index.ts b/src/games/life/index.ts index 10f417d..f2acecc 100644 --- a/src/games/life/index.ts +++ b/src/games/life/index.ts @@ -1,37 +1,26 @@ -import { createCanvas, loadImageData } from "@common/display/canvas"; +import { createWasmCanvas } from "@common/display/canvas"; import life from "./life.c"; +import { gameLoop } from "@common/game"; -let context: CanvasRenderingContext2D | null; -let imageData: ImageData; +export default gameLoop( + () => { + const canvas = createWasmCanvas(life); + const ctx = canvas.getContext('2d'); -export default function main() { - const imageDataPtr = life.initField(); - imageData = loadImageData(life.data, imageDataPtr); + if (!ctx) { + throw new Error("Failed to create canvas context"); + } - const canvas = createCanvas(imageData.width, imageData.height); - context = canvas.getContext('2d'); + return { + canvas, ctx, + sum: 0, count: 0, + }; + }, + (dt, state) => { + state.sum += dt * 1000; + state.count++; - console.log(life, imageData); - - requestAnimationFrame(loop); -} - -let sum = 0; -let count = 0; - -async function loop() { - const start = performance.now(); - - life.step(); - - context?.putImageData(imageData, 0, 0); - context?.clearRect(0, 0, 35, 15); - - const end = performance.now(); - - sum += end - start; - count++; - - context?.fillText(`${(sum / count).toFixed(1)} ms`, 2, 10); - requestAnimationFrame(loop); -} \ No newline at end of file + state.ctx.clearRect(0, 0, 35, 15); + state.ctx.fillText(`${(state.sum / state.count).toFixed(1)} ms`, 2, 10); + } +); diff --git a/src/games/life/life.c b/src/games/life/life.c index efb6097..d375fd9 100644 --- a/src/games/life/life.c +++ b/src/games/life/life.c @@ -12,7 +12,7 @@ static image_data_t image_data; static int count_neighbours(int x, int y); -EXPORT(step) void step(void) { +EXPORT(frame) void frame(void) { for (int y = 0; y < HEIGHT; y++) { for (int x = 0; x < WIDTH; x++) { int count = count_neighbours(x, y); @@ -59,7 +59,7 @@ static int count_neighbours(int x, int y) { return count; } -EXPORT(initField) image_data_t* init_field(void) { +EXPORT(init) image_data_t* init(void) { field = malloc(WIDTH * HEIGHT); next_field = malloc(WIDTH * HEIGHT); image_data = image_create(WIDTH, HEIGHT); diff --git a/src/games/playground/awoo.cpp b/src/games/playground/awoo.cpp index ed88372..fa43515 100644 --- a/src/games/playground/awoo.cpp +++ b/src/games/playground/awoo.cpp @@ -1,7 +1,7 @@ #include #include -#include #include +#include #include #include #include @@ -78,8 +78,8 @@ constexpr bit bit::nor(const bit& a, const bit& b) { } uint64_t awoo() { - bit a {1, "a"}; - bit b {1, "b"}; + bit a{1, "a"}; + bit b{1, "b"}; auto [sum, carry] = a + b; @@ -91,4 +91,4 @@ uint64_t awoo() { EXPORT(play) void play() { auto awoo = std::format("{2} {1}{0}!\n", 23, "C++", "Hello"); std::puts(awoo.c_str()); -} \ No newline at end of file +} diff --git a/src/games/sandstorm/index.tsx b/src/games/sandstorm/index.tsx deleted file mode 100644 index 2653cc4..0000000 --- a/src/games/sandstorm/index.tsx +++ /dev/null @@ -1,110 +0,0 @@ - -import { createCanvas, getPixelInt, setPixel } from '@common/display/canvas'; -import { gameLoop } from '@common/game'; -import Input from '@common/input'; - -const sandWidth = 128; - -const setup = () => { - const canvas = createCanvas(window.innerWidth >> 2, window.innerHeight >> 2); - const ctx = canvas.getContext('2d'); - if (!ctx) { - throw new Error('Failed to get canvas context'); - } - document.body.style.backgroundColor = '#eee'; - - const imageData = initData(); - - return { - canvas, - ctx, - imageData, - }; -}; - -const initData = () => { - const imageData = new ImageData(sandWidth, sandWidth); - - for (let x = 0; x < imageData.width; x++) { - for (let y = 0; y < imageData.height; y++) { - const index = (y * imageData.width + x) * 4; - imageData.data[index + 0] = Math.random() < 0.3 ? 255 : 0; - imageData.data[index + 1] = Math.random() < 0.3 ? 255 : 0; - imageData.data[index + 2] = Math.random() < 0.3 ? 255 : 0; - imageData.data[index + 3] = 255; - } - } - - return imageData; -} - -const emptyColor = 0x000000FF; -const isEmpty = (pixel: number) => (pixel >> 8) === 0; - -type State = ReturnType; - -const frame = async (dt: number, state: State): Promise => { - const { canvas, ctx } = state; - - if (Input.isPressed(Input.KeyCode.SPACE)) { - state.imageData = initData(); - } - - const imageData = state.imageData; - - for (let y = imageData.height - 2; y >= 0; y--) { - const direction = Math.random() < 0.5 ? 1 : -1; - let startX, endX; - if (direction > 0) { - startX = 0; - endX = imageData.width; - } else { - startX = imageData.width - 1; - endX = -1; - } - for (let x = startX; x != endX; x += direction) { - const pixel = getPixelInt(imageData, x, y); - if (isEmpty(pixel)) continue; - - const pixelBelow = getPixelInt(imageData, x, y + 1); - if (isEmpty(pixelBelow)) { - setPixel(imageData, x, y, emptyColor); - setPixel(imageData, x, y + 1, pixel); - continue; - } - - let leftEmpty = false; - let rightEmpty = false; - - if (x > 0) { - const pixelLeft = getPixelInt(imageData, x - 1, y + 1); - leftEmpty = isEmpty(pixelLeft); - } - if (x < imageData.width - 1) { - const pixelRight = getPixelInt(imageData, x + 1, y + 1); - rightEmpty = isEmpty(pixelRight); - } - - const selector = Math.random() < 0.5; - const selectedLeft = (leftEmpty && rightEmpty && selector) || (leftEmpty && !rightEmpty); - const selectedRight = (leftEmpty && rightEmpty && !selector) || (!leftEmpty && rightEmpty); - - if (selectedLeft) { - setPixel(imageData, x, y, emptyColor); - setPixel(imageData, x - 1, y + 1, pixel); - } else if (selectedRight) { - setPixel(imageData, x, y, emptyColor); - setPixel(imageData, x + 1, y + 1, pixel); - } - } - } - - ctx.clearRect(0, 0, canvas.width, canvas.height); - ctx.putImageData(imageData, (canvas.width - sandWidth) / 2, (canvas.height - sandWidth) / 2); - - return { - ...state, - }; -}; - -export default gameLoop(setup, frame); \ No newline at end of file