Mirai's Miscellaneous Misadventures
M4 / main.js
1let canvas = document.querySelector("canvas")
2let context = canvas.getContext("2d")
3
4let global = v =>
5{
6 if (typeof v === "number") return v
7 return v.value
8}
9
10let main = async () =>
11{
12 let stamp = (data, x, y, image) =>
13 {
14 let view = getView()
15 let width = view.getUint32(image, true)
16 let height = view.getUint32(image + 4, true)
17 context.rect(x - width / 2, y - height, width, height)
18 }
19
20 let imports = {env: {mirai_wasm_javascript_stamp: stamp}}
21 let module
22 try {module = await WebAssembly.instantiateStreaming(fetch("mimimi.wasm"), imports) }
23 catch (e) { module = await WebAssembly.instantiate(await (await fetch("mimimi.wasm")).arrayBuffer(), imports) }
24
25 let {instance: {exports}} = module
26
27 let {memory, __heap_base: base, __indirect_function_table: table} = exports
28 let {mirai_game_size, mirai_width, mirai_height} = exports
29 let {mirai_start, mirai_step, mirai_assets} = exports
30 let {mirai_wasm_stamp} = exports
31
32 let getView = () => new DataView(memory.buffer)
33
34 let view = getView()
35
36 let offset = global(base)
37 let size = view.getUint32(global(mirai_game_size), true)
38 let width = view.getUint32(global(mirai_width), true)
39 let height = view.getUint32(global(mirai_height), true)
40 canvas.width = width
41 canvas.height = height
42
43 let alloc = size =>
44 {
45 let view = getView()
46 let available = view.byteLength - offset
47
48 if (available < size)
49 memory.grow(Math.ceil((size - available) / 1024))
50
51 let result = offset
52 offset += size
53 return result
54 }
55
56 let game = alloc(size)
57 let engine = alloc(8)
58 let keys = alloc(1)
59
60 let f = table.grow(1)
61 getView().setUint32(engine + 4, f, true)
62 table.set(f, mirai_wasm_stamp)
63
64 mirai_start(game, engine)
65
66 let inputs = {ArrowLeft: 1, ArrowRight: 2}
67 let down = 0
68
69 addEventListener("keydown", ({code}) =>
70 {
71 let v = inputs[code]
72 if (v) down = down | v
73 })
74
75 addEventListener("keyup", ({code}) =>
76 {
77 let v = inputs[code]
78 if (v) down = down & ~v
79 v %= 0x100
80 })
81
82 /*
83 let image = new ImageData(width, height)
84 let {data} = image
85 for (let x = 0 ; x < width ; x++)
86 for (let y = 0 ; y < height ; y++)
87 data[(x + y * width) * 4 + 3] = 0xFF
88 */
89
90 view = getView()
91 let past = performance.now()
92 let step = () =>
93 {
94 context.beginPath()
95 context.rect(0, 0, width, height)
96 context.fillStyle = "#EEE"
97 context.fill()
98 context.beginPath()
99 view.setUint32(keys, down, true)
100 mirai_step(game, keys)
101 context.fillStyle = "#333"
102 context.fill()
103
104 let now = performance.now()
105 setTimeout(step, (100/3) + past - now)
106 past = now
107 }
108 step()
109}
110
111main()