Mirai's Miscellaneous Misadventures
M15 / main.js
let canvas = document.querySelector("canvas")
let context = canvas.getContext("2d")
let global = v =>
{
if (typeof v === "number") return v
return v.value
}
let main = async () =>
{
let stamp = (data, x, y, image) =>
{
let i = (image - assets) / 12
context.drawImage(images[i], x, y)
}
let imports = {env: {mirai_wasm_javascript_stamp: stamp}}
let module
try { module = await WebAssembly.instantiateStreaming(fetch("mimimi.wasm"), imports) }
catch (e) { module = await WebAssembly.instantiate(await (await fetch("mimimi.wasm")).arrayBuffer(), imports) }
let {instance: {exports}} = module
let {memory, __heap_base: base, __indirect_function_table: table} = exports
let {mirai_game_size, mirai_width, mirai_height} = exports
let {mirai_start, mirai_step, mirai_assets} = exports
let {mirai_wasm_stamp} = exports
let getView = () => new DataView(memory.buffer)
let view = getView()
let offset = global(base)
let size = view.getUint32(global(mirai_game_size), true)
let width = view.getUint32(global(mirai_width), true)
let height = view.getUint32(global(mirai_height), true)
canvas.width = width
canvas.height = height
let alloc = size =>
{
let view = getView()
let available = view.byteLength - offset
if (available < size)
memory.grow(Math.ceil((size - available) / 1024))
let result = offset
offset += size
return result
}
let game = alloc(size)
let engine = alloc(8)
let keys = alloc(1)
let f = table.grow(1)
getView().setUint32(engine + 4, f, true)
table.set(f, mirai_wasm_stamp)
let inputs = {ArrowLeft: 1, ArrowRight: 2}
let down = 0
addEventListener("keydown", ({code}) =>
{
let v = inputs[code]
if (v) down = down | v
})
addEventListener("keyup", ({code}) =>
{
let v = inputs[code]
if (v) down = down & ~v
down %= 0x100
})
let tap = 0
addEventListener("pointerdown", ({x, y, button}) =>
{
if (button !== 0) return
if (x < innerWidth / 2)
tap = tap | 1
else
tap = tap | 2
})
addEventListener("pointerup", () => tap = 0)
let images = []
let assets = mirai_assets()
let asset = assets
view = getView()
let xterm = [0x00, 0x5F, 0x87, 0xAF, 0xD7, 0xFF]
while (true)
{
let width = view.getUint32(asset, true)
let height = view.getUint32(asset + 4, true)
let colors = view.getUint32(asset + 8, true)
if (width === 0) break
asset += 12
let image = new ImageData(width, height)
let {data} = image
for (let x = 0 ; x < width ; x++)
for (let y = 0 ; y < height ; y++)
{
let o = x + y * width
let color = view.getUint8(colors + o)
if (color !== 0)
{
color -= 16
let r = xterm[Math.floor(color / 36) % 6]
let g = xterm[Math.floor(color / 6) % 6]
let b = xterm[color % 6]
data[o * 4 + 0] = r
data[o * 4 + 1] = g
data[o * 4 + 2] = b
data[o * 4 + 3] = 0xFF
}
}
let canvas = document.createElement("canvas")
let ctx = canvas.getContext("2d")
canvas.width = image.width
canvas.height = image.height
ctx.putImageData(image, 0, 0)
images.push(canvas)
}
mirai_start(game, engine)
view = getView()
let past = performance.now()
context.fillStyle = "#EEE"
let step = () =>
{
context.beginPath()
context.rect(0, 0, width, height)
context.fill()
view.setUint32(keys, down|tap, true)
mirai_step(game, keys)
let now = performance.now()
setTimeout(step, (100/3) + past - now)
past = now
}
step()
}
main()