From 5d41733142b36003b424c5ab0f5a360db253f389 Mon Sep 17 00:00:00 2001 From: Dennis Ranke Date: Fri, 4 Feb 2022 23:23:29 +0100 Subject: [PATCH 1/7] add download links to 0.1.1 --- site/content/_index.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/site/content/_index.md b/site/content/_index.md index c904583..732f72d 100644 --- a/site/content/_index.md +++ b/site/content/_index.md @@ -29,6 +29,24 @@ Examplers for older versions: ## Versions +### v0.1.1 + +* [Web runtime](v0.1.1) +* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.1.1/microw8-0.1.1-linux.tgz) +* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.1.1/microw8-0.1.1-macos.tgz) +* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.1.1/microw8-0.1.1-windows.zip) + +Changes: + +* implement more robust file watcher +* add basic video recording on F10 in web runtime +* add screenshot on F9 +* add watchdog to interrupt hanging update in native runtime +* add devkit mode to web runtime +* add unpack and compile commands to uw8 +* add support for table/element section in pack command +* disable wayland support (caused missing window decorations in gnome) + ### v0.1.0 * [Web runtime](v0.1.0) From f1493ebded70957360d590cd19a55e21cebac26b Mon Sep 17 00:00:00 2001 From: Dennis Ranke Date: Thu, 17 Feb 2022 23:27:57 +0100 Subject: [PATCH 2/7] Split core web runtime into separate js --- web/src/main.js | 316 ++------------------------------------------- web/src/microw8.js | 314 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 328 insertions(+), 302 deletions(-) create mode 100644 web/src/microw8.js diff --git a/web/src/main.js b/web/src/main.js index 423d076..536951d 100644 --- a/web/src/main.js +++ b/web/src/main.js @@ -1,5 +1,4 @@ -import loaderUrl from "data-url:../../platform/bin/loader.wasm"; -import platformUrl from "data-url:../../platform/bin/platform.uw8"; +import MicroW8 from './microw8.js'; function setMessage(size, error) { let html = size ? `${size} bytes` : 'Insert cart'; @@ -9,314 +8,27 @@ function setMessage(size, error) { document.getElementById('message').innerHTML = html; } -let screen = document.getElementById('screen'); -let canvasCtx = screen.getContext('2d'); -let imageData = canvasCtx.createImageData(320, 240); - -let devkitMode; - -let cancelFunction; - -let currentData; - -let U8 = (d) => new Uint8Array(d); -let U32 = (d) => new Uint32Array(d); - -let pad = 0; -let keyHandler = (e) => { - let isKeyDown = e.type == 'keydown'; - let mask; - switch (e.code) { - case 'ArrowUp': - mask = 1; - break; - case 'ArrowDown': - mask = 2; - break; - case 'ArrowLeft': - mask = 4; - break; - case 'ArrowRight': - mask = 8; - break; - case 'KeyZ': - mask = 16; - break; - case 'KeyX': - mask = 32; - break; - case 'KeyA': - mask = 64; - break; - case 'KeyS': - mask = 128; - break; - case 'KeyR': - if (isKeyDown) { - runModule(currentData, true); - } - break; - case 'F9': - if(isKeyDown) { - screen.toBlob(blob => { - downloadBlob(blob, '.png'); - }); - } - e.preventDefault(); - break; - case 'F10': - if(isKeyDown) { - recordVideo(); - } - e.preventDefault(); - break; - } - - if (isKeyDown) { - pad |= mask; - } else { - pad &= ~mask; - } -}; -window.onkeydown = keyHandler; -window.onkeyup = keyHandler; - -async function runModule(data, keepUrl) { - if (cancelFunction) { - cancelFunction(); - cancelFunction = null; - } - - let cartridgeSize = data.byteLength; - - setMessage(cartridgeSize); - if (cartridgeSize == 0) { - return; - } - - currentData = data; - - let newURL = window.location.pathname; - if (cartridgeSize <= 1024 && !keepUrl) { - let dataString = ''; - for (let byte of U8(data)) { - dataString += String.fromCharCode(byte); - } - newURL += '#' + btoa(dataString); - - if (newURL != window.location.pathname + window.location.hash) { - history.pushState(null, null, newURL); - } - } - - screen.width = screen.width; - - try { - let memSize = { initial: 4 }; - if(!devkitMode) { - memSize.maximum = 4; - } - let memory = new WebAssembly.Memory({ initial: 4, maximum: devkitMode ? 16 : 4 }); - let memU8 = U8(memory.buffer); - - let importObject = { - env: { - memory - }, - }; - - let loader; - - let loadModuleData = (data) => { - if (loader && (!devkitMode || U8(data)[0] != 0)) { - memU8.set(U8(data)); - let length = loader.exports.load_uw8(data.byteLength); - data = new ArrayBuffer(length); - U8(data).set(memU8.slice(0, length)); - } - return data; - } - - let instantiate = async (data) => (await WebAssembly.instantiate(data, importObject)).instance; - - let loadModuleURL = async (url) => instantiate(loadModuleData(await (await fetch(url)).arrayBuffer())); - - loader = await loadModuleURL(loaderUrl); - - for (let n of ['acos', 'asin', 'atan', 'atan2', 'cos', 'exp', 'log', 'sin', 'tan', 'pow']) { - importObject.env[n] = Math[n]; - } - - for (let i = 9; i < 64; ++i) { - importObject.env['reserved' + i] = () => { }; - } - - for (let i = 0; i < 16; ++i) { - importObject.env['g_reserved' + i] = 0; - } - - data = loadModuleData(data); - - let platform_instance = await loadModuleURL(platformUrl); - - for (let name in platform_instance.exports) { - importObject.env[name] = platform_instance.exports[name] - } - - let instance = await instantiate(data); - - let buffer = U32(imageData.data.buffer); - - let startTime = Date.now(); - - let keepRunning = true; - cancelFunction = () => keepRunning = false; - - const timePerFrame = 1000 / 60; - let nextFrame = startTime; - - function mainloop() { - if (!keepRunning) { - return; - } - - try { - let now = Date.now(); - let restart = false; - if (now >= nextFrame) { - let gamepads = navigator.getGamepads(); - let gamepad = 0; - for (let i = 0; i < 4; ++i) { - let pad = gamepads[i]; - if (!pad) { - continue; - } - for (let j = 0; j < 8; ++j) { - let buttonIdx = (j + 12) % 16; - if (pad.buttons.length > buttonIdx && pad.buttons[buttonIdx].pressed) { - gamepad |= 1 << (i * 8 + j); - } - } - if (pad.axes.length > 1) { - for (let j = 0; j < 4; ++j) { - let v = pad.axes[1 - (j >> 1)]; - if (((j & 1) ? v : -v) > 0.5) { - gamepad |= 1 << (i * 8 + j); - } - } - } - if (pad.buttons.length > 9 && pad.buttons[9].pressed) { - restart = true; - } - } - - let u32Mem = U32(memory.buffer); - u32Mem[16] = now - startTime; - u32Mem[17] = pad | gamepad; - instance.exports.upd(); - platform_instance.exports.endFrame(); - - let palette = U32(memory.buffer.slice(0x13000, 0x13000 + 1024)); - for (let i = 0; i < 320 * 240; ++i) { - buffer[i] = palette[memU8[i + 120]] | 0xff000000; - } - canvasCtx.putImageData(imageData, 0, 0); - nextFrame = Math.max(nextFrame + timePerFrame, now); - } - - if (restart) { - runModule(currentData); - } else { - window.requestAnimationFrame(mainloop); - } - } catch (err) { - setMessage(cartridgeSize, err.toString()); - } - } - - mainloop(); - } catch (err) { - setMessage(cartridgeSize, err.toString()); - } -} - -function downloadBlob(blob, ext) { - let a = document.createElement('a'); - a.href = URL.createObjectURL(blob); - a.download = 'microw8_' + new Date().toISOString() + ext; - a.click(); - URL.revokeObjectURL(a.href); -} - -let videoRecorder; -let videoStartTime; -function recordVideo() { - if(videoRecorder) { - videoRecorder.stop(); - videoRecorder = null; - return; - } - - videoRecorder = new MediaRecorder(screen.captureStream(), { - mimeType: 'video/webm', - videoBitsPerSecond: 25000000 - }); - - let chunks = []; - videoRecorder.ondataavailable = e => { - chunks.push(e.data); - }; - - let timer = document.getElementById("timer"); - timer.hidden = false; - timer.innerText = "00:00"; - - videoRecorder.onstop = () => { - timer.hidden = true; - downloadBlob(new Blob(chunks, {type: 'video/webm'}), '.webm'); - }; - - videoRecorder.start(); - videoStartTime = Date.now(); - - function updateTimer() { - if(!videoStartTime) { - return; - } - - let duration = Math.floor((Date.now() - videoStartTime) / 1000); - timer.innerText = Math.floor(duration / 60).toString().padStart(2, '0') + ':' + (duration % 60).toString().padStart(2, '0'); - - setTimeout(updateTimer, 1000); - } - - setTimeout(updateTimer, 1000); -} - -async function runModuleFromURL(url, keepUrl) { - let response = await fetch(url); - let type = response.headers.get('Content-Type'); - if(type && type.includes('html')) { - throw false; - } - runModule(await response.arrayBuffer(), keepUrl || devkitMode); -} +let uw8 = MicroW8(document.getElementById('screen'), { + setMessage, + keyboardElement: window, + timerElement: document.getElementById("timer"), +}); function runModuleFromHash() { let hash = window.location.hash.slice(1); if(hash == 'devkit') { - devkitMode = true; + uw8.setDevkitMode(true); return; } - devkitMode = false; + uw8.setDevkitMode(false); if (hash.length > 0) { if (hash.startsWith("url=")) { - runModuleFromURL(hash.slice(4), true); + uw8.runModuleFromURL(hash.slice(4), true); } else { - runModuleFromURL('data:;base64,' + hash); + uw8.runModuleFromURL('data:;base64,' + hash); } } else { - runModule(new ArrayBuffer(0)); + uw8.runModule(new ArrayBuffer(0)); } } @@ -331,7 +43,7 @@ let setupLoad = () => { fileInput.accept = '.wasm,.uw8,application/wasm'; fileInput.onchange = () => { if (fileInput.files.length > 0) { - runModuleFromURL(URL.createObjectURL(fileInput.files[0])); + uw8.runModuleFromURL(URL.createObjectURL(fileInput.files[0])); } }; fileInput.click(); @@ -345,7 +57,7 @@ let setupLoad = () => { let files = e.dataTransfer && e.dataTransfer.files; if(files && files.length == 1) { e.preventDefault(); - runModuleFromURL(URL.createObjectURL(e.dataTransfer.files[0])); + uw8.runModuleFromURL(URL.createObjectURL(e.dataTransfer.files[0])); } } @@ -367,7 +79,7 @@ if(location.hash.length != 0) { url += 'cart.uw8'; } try { - await runModuleFromURL(url, true); + await uw8.runModuleFromURL(url, true); } catch(e) { setupLoad(); } diff --git a/web/src/microw8.js b/web/src/microw8.js new file mode 100644 index 0000000..801367d --- /dev/null +++ b/web/src/microw8.js @@ -0,0 +1,314 @@ +import loaderUrl from "data-url:../../platform/bin/loader.wasm"; +import platformUrl from "data-url:../../platform/bin/platform.uw8"; + +export default function MicroW8(screen, config) { + let canvasCtx = screen.getContext('2d'); + let imageData = canvasCtx.createImageData(320, 240); + + let devkitMode = config.devkitMode; + + let cancelFunction; + + let currentData; + + let U8 = (d) => new Uint8Array(d); + let U32 = (d) => new Uint32Array(d); + + let pad = 0; + let keyboardElement = config.keyboardElement == undefined ? screen : config.keyboardElement; + if(keyboardElement) { + let keyHandler = (e) => { + let isKeyDown = e.type == 'keydown'; + let mask; + switch (e.code) { + case 'ArrowUp': + mask = 1; + break; + case 'ArrowDown': + mask = 2; + break; + case 'ArrowLeft': + mask = 4; + break; + case 'ArrowRight': + mask = 8; + break; + case 'KeyZ': + mask = 16; + break; + case 'KeyX': + mask = 32; + break; + case 'KeyA': + mask = 64; + break; + case 'KeyS': + mask = 128; + break; + case 'KeyR': + if (isKeyDown) { + runModule(currentData, true); + } + break; + case 'F9': + if(isKeyDown) { + screen.toBlob(blob => { + downloadBlob(blob, '.png'); + }); + } + e.preventDefault(); + break; + case 'F10': + if(isKeyDown) { + recordVideo(); + } + e.preventDefault(); + break; + } + + if (isKeyDown) { + pad |= mask; + } else { + pad &= ~mask; + } + }; + + keyboardElement.onkeydown = keyHandler; + keyboardElement.onkeyup = keyHandler; + } + + async function runModule(data, keepUrl) { + if (cancelFunction) { + cancelFunction(); + cancelFunction = null; + } + + let cartridgeSize = data.byteLength; + + config.setMessage(cartridgeSize); + if (cartridgeSize == 0) { + return; + } + + currentData = data; + + let newURL = window.location.pathname; + if (cartridgeSize <= 1024 && !keepUrl) { + let dataString = ''; + for (let byte of U8(data)) { + dataString += String.fromCharCode(byte); + } + newURL += '#' + btoa(dataString); + + if (newURL != window.location.pathname + window.location.hash) { + history.pushState(null, null, newURL); + } + } + + screen.width = screen.width; + + try { + let memSize = { initial: 4 }; + if(!devkitMode) { + memSize.maximum = 4; + } + let memory = new WebAssembly.Memory({ initial: 4, maximum: devkitMode ? 16 : 4 }); + let memU8 = U8(memory.buffer); + + let importObject = { + env: { + memory + }, + }; + + let loader; + + let loadModuleData = (data) => { + if (loader && (!devkitMode || U8(data)[0] != 0)) { + memU8.set(U8(data)); + let length = loader.exports.load_uw8(data.byteLength); + data = new ArrayBuffer(length); + U8(data).set(memU8.slice(0, length)); + } + return data; + } + + let instantiate = async (data) => (await WebAssembly.instantiate(data, importObject)).instance; + + let loadModuleURL = async (url) => instantiate(loadModuleData(await (await fetch(url)).arrayBuffer())); + + loader = await loadModuleURL(loaderUrl); + + for (let n of ['acos', 'asin', 'atan', 'atan2', 'cos', 'exp', 'log', 'sin', 'tan', 'pow']) { + importObject.env[n] = Math[n]; + } + + for (let i = 9; i < 64; ++i) { + importObject.env['reserved' + i] = () => { }; + } + + for (let i = 0; i < 16; ++i) { + importObject.env['g_reserved' + i] = 0; + } + + data = loadModuleData(data); + + let platform_instance = await loadModuleURL(platformUrl); + + for (let name in platform_instance.exports) { + importObject.env[name] = platform_instance.exports[name] + } + + let instance = await instantiate(data); + + let buffer = U32(imageData.data.buffer); + + let startTime = Date.now(); + + let keepRunning = true; + cancelFunction = () => keepRunning = false; + + const timePerFrame = 1000 / 60; + let nextFrame = startTime; + + function mainloop() { + if (!keepRunning) { + return; + } + + try { + let now = Date.now(); + let restart = false; + if (now >= nextFrame) { + let gamepads = navigator.getGamepads(); + let gamepad = 0; + for (let i = 0; i < 4; ++i) { + let pad = gamepads[i]; + if (!pad) { + continue; + } + for (let j = 0; j < 8; ++j) { + let buttonIdx = (j + 12) % 16; + if (pad.buttons.length > buttonIdx && pad.buttons[buttonIdx].pressed) { + gamepad |= 1 << (i * 8 + j); + } + } + if (pad.axes.length > 1) { + for (let j = 0; j < 4; ++j) { + let v = pad.axes[1 - (j >> 1)]; + if (((j & 1) ? v : -v) > 0.5) { + gamepad |= 1 << (i * 8 + j); + } + } + } + if (pad.buttons.length > 9 && pad.buttons[9].pressed) { + restart = true; + } + } + + let u32Mem = U32(memory.buffer); + u32Mem[16] = now - startTime; + u32Mem[17] = pad | gamepad; + instance.exports.upd(); + platform_instance.exports.endFrame(); + + let palette = U32(memory.buffer.slice(0x13000, 0x13000 + 1024)); + for (let i = 0; i < 320 * 240; ++i) { + buffer[i] = palette[memU8[i + 120]] | 0xff000000; + } + canvasCtx.putImageData(imageData, 0, 0); + nextFrame = Math.max(nextFrame + timePerFrame, now); + } + + if (restart) { + runModule(currentData); + } else { + window.requestAnimationFrame(mainloop); + } + } catch (err) { + config.setMessage(cartridgeSize, err.toString()); + } + } + + mainloop(); + } catch (err) { + config.setMessage(cartridgeSize, err.toString()); + } + } + + function downloadBlob(blob, ext) { + let a = document.createElement('a'); + a.href = URL.createObjectURL(blob); + a.download = 'microw8_' + new Date().toISOString() + ext; + a.click(); + URL.revokeObjectURL(a.href); + } + + let videoRecorder; + let videoStartTime; + function recordVideo() { + if(videoRecorder) { + videoRecorder.stop(); + videoRecorder = null; + return; + } + + videoRecorder = new MediaRecorder(screen.captureStream(), { + mimeType: 'video/webm', + videoBitsPerSecond: 25000000 + }); + + let chunks = []; + videoRecorder.ondataavailable = e => { + chunks.push(e.data); + }; + + let timer = config.timerElement; + if(timer) { + timer.hidden = false; + timer.innerText = "00:00"; + } + + videoRecorder.onstop = () => { + if(timer) { + timer.hidden = true; + } + downloadBlob(new Blob(chunks, {type: 'video/webm'}), '.webm'); + }; + + videoRecorder.start(); + videoStartTime = Date.now(); + + function updateTimer() { + if(!videoStartTime) { + return; + } + + if(timer) { + let duration = Math.floor((Date.now() - videoStartTime) / 1000); + timer.innerText = Math.floor(duration / 60).toString().padStart(2, '0') + ':' + (duration % 60).toString().padStart(2, '0'); + } + + setTimeout(updateTimer, 1000); + } + + setTimeout(updateTimer, 1000); + } + + async function runModuleFromURL(url, keepUrl) { + let response = await fetch(url); + let type = response.headers.get('Content-Type'); + if(type && type.includes('html')) { + throw false; + } + runModule(await response.arrayBuffer(), keepUrl || devkitMode); + } + + return { + runModule, + runModuleFromURL, + setDevkitMode: (m) => devkitMode = m, + }; +} + +this.uw8 = MicroW8; \ No newline at end of file From 4c75ba2e44097b5892e750cd7fa8306f8995a37f Mon Sep 17 00:00:00 2001 From: Dennis Ranke Date: Sat, 19 Feb 2022 16:21:02 +0100 Subject: [PATCH 3/7] start implementing run --browser --- Cargo.lock | 873 ++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 5 +- src/lib.rs | 2 + src/main.rs | 100 +++-- src/run_web.rs | 34 ++ web/src/microw8.js | 4 +- web/src/run-web.html | 14 + web/src/run-web.js | 10 + 8 files changed, 993 insertions(+), 49 deletions(-) create mode 100644 src/run_web.rs create mode 100644 web/src/run-web.html create mode 100644 web/src/run-web.js diff --git a/Cargo.lock b/Cargo.lock index d1fe1c7..4f4c7a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -153,12 +153,43 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +dependencies = [ + "generic-array", +] + +[[package]] +name = "buf_redux" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f" +dependencies = [ + "memchr", + "safemem", +] + [[package]] name = "bumpalo" version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + [[package]] name = "cc" version = "1.0.72" @@ -178,6 +209,12 @@ dependencies = [ "sacabase", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cexpr" version = "0.4.0" @@ -228,7 +265,7 @@ dependencies = [ "ansi_term", "atty", "bitflags", - "strsim", + "strsim 0.8.0", "textwrap", "unicode-width", "vec_map", @@ -243,6 +280,16 @@ dependencies = [ "cc", ] +[[package]] +name = "combine" +version = "4.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b727aacc797f9fc28e355d21f34709ac4fc9adecfe470ad07b8f4464f53062" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "const-random" version = "0.1.13" @@ -432,6 +479,16 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-common" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "cty" version = "0.2.2" @@ -451,6 +508,41 @@ dependencies = [ "wasmparser 0.81.0", ] +[[package]] +name = "darling" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0d720b8683f8dd83c65155f0530560cba68cd2bf395f6513a483caee57ff7f4" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a340f241d2ceed1deb47ae36c4144b2707ec7dd0b649f894cb39bb595986324" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c41b3b7352feb3211a0d743dc5700a4e3b60f51bd2b368892d1e0f9a95f44b" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "digest" version = "0.9.0" @@ -460,6 +552,16 @@ dependencies = [ "generic-array", ] +[[package]] +name = "digest" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +dependencies = [ + "block-buffer 0.10.2", + "crypto-common", +] + [[package]] name = "directories-next" version = "2.0.0" @@ -549,6 +651,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + [[package]] name = "file-per-thread-logger" version = "0.1.4" @@ -583,6 +694,22 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +dependencies = [ + "matches", + "percent-encoding", +] + [[package]] name = "fsevent" version = "0.4.0" @@ -618,6 +745,48 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +[[package]] +name = "futures-channel" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-core", + "futures-sink", + "futures-task", + "pin-project-lite", + "pin-utils", + "slab", +] + [[package]] name = "generic-array" version = "0.14.5" @@ -662,12 +831,56 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +[[package]] +name = "h2" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +[[package]] +name = "headers" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cff78e5788be1e0ab65b04d306b2ed5092c815ec97ec70f4ebd5aee158aa55d" +dependencies = [ + "base64", + "bitflags", + "bytes", + "headers-core", + "http", + "httpdate", + "mime", + "sha-1 0.10.0", +] + +[[package]] +name = "headers-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +dependencies = [ + "http", +] + [[package]] name = "heck" version = "0.3.3" @@ -686,6 +899,40 @@ dependencies = [ "libc", ] +[[package]] +name = "http" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + [[package]] name = "humantime" version = "1.3.0" @@ -701,12 +948,53 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "hyper" +version = "0.14.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "043f0e083e9901b6cc658a77d1eb86f4fc650bbb977a4337dd63192826aa85dd" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + [[package]] name = "id-arena" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "indexmap" version = "1.8.0" @@ -738,6 +1026,15 @@ dependencies = [ "libc", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "iovec" version = "0.1.4" @@ -756,6 +1053,32 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + +[[package]] +name = "jni" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + [[package]] name = "jobserver" version = "0.1.24" @@ -804,9 +1127,9 @@ checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" [[package]] name = "libc" -version = "0.2.113" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eef78b64d87775463c549fbd80e19249ef436ea3bf1de2a1eb7e717ec7fab1e9" +checksum = "06e509672465a0504304aa87f9f176f2b2b716ed8fb105ebe5c02dc6dce96a94" [[package]] name = "libloading" @@ -836,6 +1159,12 @@ dependencies = [ "libc", ] +[[package]] +name = "matches" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" + [[package]] name = "memchr" version = "2.4.1" @@ -851,6 +1180,22 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mime" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" + +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "minifb" version = "0.20.0" @@ -889,12 +1234,25 @@ dependencies = [ "kernel32-sys", "libc", "log", - "miow", + "miow 0.2.2", "net2", "slab", "winapi 0.2.8", ] +[[package]] +name = "mio" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba272f85fa0b41fc91872be579b3bbe0f56b792aa361a380eb669469f68dafb2" +dependencies = [ + "libc", + "log", + "miow 0.3.7", + "ntapi", + "winapi 0.3.9", +] + [[package]] name = "mio-extras" version = "2.0.6" @@ -903,7 +1261,7 @@ checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" dependencies = [ "lazycell", "log", - "mio", + "mio 0.6.23", "slab", ] @@ -919,12 +1277,95 @@ dependencies = [ "ws2_32-sys", ] +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "more-asserts" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" +[[package]] +name = "multipart" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00dec633863867f29cb39df64a397cdf4a6354708ddd7759f70c7fb51c5f9182" +dependencies = [ + "buf_redux", + "httparse", + "log", + "mime", + "mime_guess", + "quick-error", + "rand", + "safemem", + "tempfile", + "twoway", +] + +[[package]] +name = "ndk" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2032c77e030ddee34a6787a64166008da93f6a352b629261d0fee232b8742dd4" +dependencies = [ + "bitflags", + "jni-sys", + "ndk-sys", + "num_enum", + "thiserror", +] + +[[package]] +name = "ndk-context" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e3c5cc68637e21fe8f077f6a1c9e0b9ca495bb74895226b476310f613325884" + +[[package]] +name = "ndk-glue" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9ffb7443daba48349d545028777ca98853b018b4c16624aa01223bc29e078da" +dependencies = [ + "lazy_static", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-macro", + "ndk-sys", +] + +[[package]] +name = "ndk-macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c" +dependencies = [ + "darling", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ndk-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e5a6ae77c8ee183dcbbba6150e2e6b9f3f4196a7666c02a715a95692ec1fa97" +dependencies = [ + "jni-sys", +] + [[package]] name = "net2" version = "0.2.37" @@ -958,12 +1399,21 @@ dependencies = [ "fsevent-sys", "inotify", "libc", - "mio", + "mio 0.6.23", "mio-extras", "walkdir", "winapi 0.3.9", ] +[[package]] +name = "ntapi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28774a7fd2fbb4f0babd8237ce554b73af68021b5f695a3cebd6c59bac0980f" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "num-traits" version = "0.2.14" @@ -983,6 +1433,27 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "720d3ea1055e4e4574c0c0b0f8c3fd4f24c4cdaf465948206dea090b57b526ad" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d992b768490d7fe0d8586d9b5745f6c49f557da6d81dc982b1d167ad4edbb21" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "object" version = "0.26.2" @@ -1048,12 +1519,50 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" + [[package]] name = "pico-args" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" +[[package]] +name = "pin-project" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "pkg-config" version = "0.3.24" @@ -1066,6 +1575,16 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +[[package]] +name = "proc-macro-crate" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dada8c9981fcf32929c3c0f0cd796a9284aca335565227ed88c83babb1d43dc" +dependencies = [ + "thiserror", + "toml", +] + [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -1248,6 +1767,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -1260,6 +1788,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "ryu" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" + [[package]] name = "sacabase" version = "2.0.0" @@ -1269,6 +1803,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + [[package]] name = "same-file" version = "1.0.6" @@ -1278,6 +1818,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + [[package]] name = "scopeguard" version = "1.1.0" @@ -1332,16 +1878,63 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_json" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha-1" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha-1" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.10.3", +] + [[package]] name = "sha2" version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "cfg-if 1.0.0", "cpufeatures", - "digest", + "digest 0.9.0", "opaque-debug", ] @@ -1363,6 +1956,16 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +[[package]] +name = "socket2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +dependencies = [ + "libc", + "winapi 0.3.9", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1375,6 +1978,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "syn" version = "1.0.86" @@ -1403,6 +2012,20 @@ version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9bffcddbc2458fa3e6058414599e3c838a022abae82e5c67b4f7f80298d5bff" +[[package]] +name = "tempfile" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +dependencies = [ + "cfg-if 1.0.0", + "fastrand", + "libc", + "redox_syscall", + "remove_dir_all", + "winapi 0.3.9", +] + [[package]] name = "termcolor" version = "1.1.2" @@ -1460,6 +2083,74 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinyvec" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" + +[[package]] +name = "tokio" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee" +dependencies = [ + "bytes", + "libc", + "memchr", + "mio 0.8.0", + "pin-project-lite", + "socket2", + "winapi 0.3.9", +] + +[[package]] +name = "tokio-stream" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "511de3f85caf1c98983545490c3d09685fa8eb634e57eec22bb4db271f46cbd8" +dependencies = [ + "futures-util", + "log", + "pin-project", + "tokio", + "tungstenite", +] + +[[package]] +name = "tokio-util" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "log", + "pin-project-lite", + "tokio", +] + [[package]] name = "toml" version = "0.5.8" @@ -1469,12 +2160,97 @@ dependencies = [ "serde", ] +[[package]] +name = "tower-service" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" + +[[package]] +name = "tracing" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6c650a8ef0cd2dd93736f033d21cbd1224c5a967aa0c258d00fcf7dafef9b9f" +dependencies = [ + "cfg-if 1.0.0", + "log", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03cfcb51380632a72d3111cb8d3447a8d908e577d31beeac006f836383d29a23" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "try-lock" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" + +[[package]] +name = "tungstenite" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0b2d8558abd2e276b0a8df5c05a2ec762609344191e5fd23e292c910e9165b5" +dependencies = [ + "base64", + "byteorder", + "bytes", + "http", + "httparse", + "log", + "rand", + "sha-1 0.9.8", + "thiserror", + "url", + "utf-8", +] + +[[package]] +name = "twoway" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" +dependencies = [ + "memchr", +] + [[package]] name = "typenum" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" + +[[package]] +name = "unicode-normalization" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-segmentation" version = "1.8.0" @@ -1515,6 +2291,24 @@ dependencies = [ "pico-args", ] +[[package]] +name = "url" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +dependencies = [ + "form_urlencoded", + "idna", + "matches", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "uw8" version = "0.1.1" @@ -1525,9 +2319,12 @@ dependencies = [ "notify", "pico-args", "same-file", + "tokio", "uw8-tool", + "warp", "wasmtime", "wat", + "webbrowser", ] [[package]] @@ -1598,6 +2395,46 @@ dependencies = [ "syn", ] +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + +[[package]] +name = "warp" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cef4e1e9114a4b7f1ac799f16ce71c14de5778500c5450ec6b7b920c55b587e" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "headers", + "http", + "hyper", + "log", + "mime", + "mime_guess", + "multipart", + "percent-encoding", + "pin-project", + "scoped-tls", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-stream", + "tokio-tungstenite", + "tokio-util", + "tower-service", + "tracing", +] + [[package]] name = "wasi" version = "0.10.2+wasi-snapshot-preview1" @@ -1885,6 +2722,20 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webbrowser" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9c28b6b6a78440b02647358625e3febc90724126480b9da6a967b5f674b3554" +dependencies = [ + "jni", + "ndk-glue", + "url", + "web-sys", + "widestring", + "winapi 0.3.9", +] + [[package]] name = "which" version = "3.1.1" @@ -1894,6 +2745,12 @@ dependencies = [ "libc", ] +[[package]] +name = "widestring" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17882f045410753661207383517a6f62ec3dbeb6a4ed2acce01f0728238d1983" + [[package]] name = "winapi" version = "0.2.8" diff --git a/Cargo.toml b/Cargo.toml index 42f0780..8dc4e2e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,4 +14,7 @@ pico-args = "0.4" curlywas = { git = "https://github.com/exoticorn/curlywas.git", rev = "196719b" } wat = "1" uw8-tool = { path = "uw8-tool" } -same-file = "1" \ No newline at end of file +same-file = "1" +warp = "0.3.2" +tokio = { version = "1.17.0", features = ["sync", "rt"] } +webbrowser = "0.6.0" \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 6d6417f..cd1816f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,8 +11,10 @@ use wasmtime::{ }; mod filewatcher; +mod run_web; pub use filewatcher::FileWatcher; +pub use run_web::RunWebServer; static GAMEPAD_KEYS: &'static [Key] = &[ Key::Up, diff --git a/src/main.rs b/src/main.rs index dc19e3c..c5a1359 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ use std::fs::File; use std::io::prelude::*; use std::process; +use std::time::Duration; use std::{ path::{Path, PathBuf}, process::exit, @@ -8,7 +9,7 @@ use std::{ use anyhow::Result; use pico_args::Arguments; -use uw8::{FileWatcher, MicroW8}; +use uw8::{FileWatcher, MicroW8, RunWebServer}; fn main() -> Result<()> { let mut args = Arguments::from_env(); @@ -65,42 +66,61 @@ fn run(mut args: Arguments) -> Result<()> { config.output_path = Some(path); } + let run_browser = args.contains(["-b", "--browser"]); + let filename = args.free_from_os_str::(|s| Ok(s.into()))?; - let mut uw8 = MicroW8::new()?; + if !run_browser { + let mut uw8 = MicroW8::new()?; - if let Some(timeout) = timeout { - uw8.set_timeout(timeout); - } - - let mut watcher = FileWatcher::builder(); - - if watch_mode { - watcher.add_file(&filename); - } - - let watcher = watcher.build()?; - - if let Err(err) = start_cart(&filename, &mut uw8, &config) { - eprintln!("Load error: {}", err); - if !watch_mode { - exit(1); - } - } - - while uw8.is_open() { - if watcher.poll_changed_file()?.is_some() { - if let Err(err) = start_cart(&filename, &mut uw8, &config) { - eprintln!("Load error: {}", err); - } + if let Some(timeout) = timeout { + uw8.set_timeout(timeout); } - if let Err(err) = uw8.run_frame() { - eprintln!("Runtime error: {}", err); + let mut watcher = FileWatcher::builder(); + + if watch_mode { + watcher.add_file(&filename); + } + + let watcher = watcher.build()?; + + if let Err(err) = start_cart(&filename, &mut uw8, &config) { + eprintln!("Load error: {}", err); if !watch_mode { exit(1); } } + + while uw8.is_open() { + if watcher.poll_changed_file()?.is_some() { + if let Err(err) = start_cart(&filename, &mut uw8, &config) { + eprintln!("Load error: {}", err); + } + } + + if let Err(err) = uw8.run_frame() { + eprintln!("Runtime error: {}", err); + if !watch_mode { + exit(1); + } + } + } + } else { + let mut server = RunWebServer::new(); + match load_cart(&filename, &config) { + Ok(cart) => server.load_module(&cart)?, + Err(err) => { + eprintln!("Load error: {}", err); + if !watch_mode { + exit(1); + } + } + } + + loop { + std::thread::sleep(Duration::from_millis(100)); + } } Ok(()) @@ -112,7 +132,7 @@ struct Config { output_path: Option, } -fn load_cart(filename: &Path, pack: &Option) -> Result> { +fn load_cart(filename: &Path, config: &Config) -> Result> { let mut cart = vec![]; File::open(filename)?.read_to_end(&mut cart)?; @@ -125,20 +145,20 @@ fn load_cart(filename: &Path, pack: &Option) -> Result Result<()> { - let cart = load_cart(filename, &config.pack)?; - - if let Some(ref path) = config.output_path { - File::create(path)?.write_all(&cart)?; - } + let cart = load_cart(filename, config)?; if let Err(err) = uw8.load_from_memory(&cart) { eprintln!("Load error: {}", err); @@ -163,7 +183,13 @@ fn pack(mut args: Arguments) -> Result<()> { let out_file = args.free_from_os_str::(|s| Ok(s.into()))?; - let cart = load_cart(&in_file, &Some(pack_config))?; + let cart = load_cart( + &in_file, + &Config { + pack: Some(pack_config), + output_path: None, + }, + )?; File::create(out_file)?.write_all(&cart)?; @@ -173,7 +199,7 @@ fn pack(mut args: Arguments) -> Result<()> { fn unpack(mut args: Arguments) -> Result<()> { let in_file = args.free_from_os_str::(|s| Ok(s.into()))?; let out_file = args.free_from_os_str::(|s| Ok(s.into()))?; - + uw8_tool::unpack_file(&in_file, &out_file).into() } diff --git a/src/run_web.rs b/src/run_web.rs new file mode 100644 index 0000000..4144930 --- /dev/null +++ b/src/run_web.rs @@ -0,0 +1,34 @@ +use anyhow::Result; +use std::thread; +use warp::{http::Response, Filter}; + +pub struct RunWebServer {} + +impl RunWebServer { + pub fn new() -> RunWebServer { + thread::spawn(move || { + let rt = tokio::runtime::Builder::new_current_thread() + .enable_io() + .build() + .expect("Failed to create tokio runtime"); + rt.block_on(async { + let html = warp::path::end().map(|| { + Response::builder() + .header("Content-Type", "text/html") + .body(include_str!("run-web.html")) + }); + + let server_future = warp::serve(html).bind(([127, 0, 0, 1], 3030)); + println!("Point browser at 127.0.0.1:3030"); + let _ = webbrowser::open("http://127.0.0.1:3030"); + server_future.await + }); + }); + + RunWebServer {} + } + + pub fn load_module(&mut self, module_data: &[u8]) -> Result<()> { + Ok(()) + } +} diff --git a/web/src/microw8.js b/web/src/microw8.js index 801367d..1b4556f 100644 --- a/web/src/microw8.js +++ b/web/src/microw8.js @@ -1,7 +1,7 @@ import loaderUrl from "data-url:../../platform/bin/loader.wasm"; import platformUrl from "data-url:../../platform/bin/platform.uw8"; -export default function MicroW8(screen, config) { +export default function MicroW8(screen, config = {}) { let canvasCtx = screen.getContext('2d'); let imageData = canvasCtx.createImageData(320, 240); @@ -310,5 +310,3 @@ export default function MicroW8(screen, config) { setDevkitMode: (m) => devkitMode = m, }; } - -this.uw8 = MicroW8; \ No newline at end of file diff --git a/web/src/run-web.html b/web/src/run-web.html new file mode 100644 index 0000000..666cf0e --- /dev/null +++ b/web/src/run-web.html @@ -0,0 +1,14 @@ + + + + + uw8-run + + + + + + + \ No newline at end of file diff --git a/web/src/run-web.js b/web/src/run-web.js new file mode 100644 index 0000000..f93a4f3 --- /dev/null +++ b/web/src/run-web.js @@ -0,0 +1,10 @@ +import MicroW8 from './microw8.js'; + +let uw8 = MicroW8(document.getElementById('screen')); +let events = new EventSource('events'); +events.onmessage = event => { + console.log(event.data); + if(event.data == 'L') { + uw8.runModuleFromURL('cart'); + } +}; \ No newline at end of file From 266493ca1c1dc7ff53bcfe3e50a13e61a38c8d69 Mon Sep 17 00:00:00 2001 From: Dennis Ranke Date: Sat, 19 Feb 2022 23:58:13 +0100 Subject: [PATCH 4/7] run --browser is working (very unpolished) --- examples/curlywas/technotunnel.cwa | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/examples/curlywas/technotunnel.cwa b/examples/curlywas/technotunnel.cwa index fc28f69..785b373 100644 --- a/examples/curlywas/technotunnel.cwa +++ b/examples/curlywas/technotunnel.cwa @@ -1,25 +1,29 @@ import "env.memory" memory(4); import "env.sin" fn sin(f32) -> f32; import "env.time" fn time() -> f32; +import "env.setPixel" fn setPixel(i32, i32, i32); export fn upd() { - let i: i32; + let x: i32; + let y: i32; loop screen { let inline t = time() / 2 as f32; - let lazy o = sin(t) * 0.8; - let lazy q = (i % 320) as f32 - 160.1; - let lazy w = (i / 320 - 120) as f32; + let lazy o = sin(t) * 0.75; + let inline q = x as f32 - 160.5; + let inline w = (y - 120) as f32; let lazy r = sqrt(q*q + w*w); let lazy z = q / r; let lazy s = z * o + sqrt(z * z * o * o + 1 as f32 - o * o); - let lazy q2 = (z * s - o) * 10 as f32 + t; - let lazy w2 = w / r * s * 10 as f32 + t; - let lazy s2 = s * 100 as f32 / r; - i?120 = max( + let inline q2 = (z * s - o) * 10 as f32 + t; + let inline w2 = w / r * s * 10 as f32 + t; + let inline s2 = s * 100 as f32 / r; + let inline color = max( 0 as f32, ((q2 as i32 ^ w2 as i32 & ((s2 + time()) * 10 as f32) as i32) & 5) as f32 * (4 as f32 - s2) as f32 ) as i32 - 32; - branch_if (i := i + 1) < 320*240: screen + setPixel(x, y, color); + branch_if x := (x + 1) % 320: screen; + branch_if y := (y + 1) % 320: screen; } } \ No newline at end of file From c56196bd2efd5c8f2c178d0eae9119e2b05fae25 Mon Sep 17 00:00:00 2001 From: Dennis Ranke Date: Sun, 20 Feb 2022 18:26:57 +0100 Subject: [PATCH 5/7] actual run --browser instead of just optimized technotunnel --- Cargo.lock | 2 ++ Cargo.toml | 1 + src/main.rs | 24 ++++++++++++++++-------- src/run_web.rs | 44 +++++++++++++++++++++++++++++++++++++++----- web/src/microw8.js | 7 +++++++ web/src/run-web.js | 5 +++-- 6 files changed, 68 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4f4c7a0..0059edf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2122,6 +2122,7 @@ dependencies = [ "futures-core", "pin-project-lite", "tokio", + "tokio-util", ] [[package]] @@ -2320,6 +2321,7 @@ dependencies = [ "pico-args", "same-file", "tokio", + "tokio-stream", "uw8-tool", "warp", "wasmtime", diff --git a/Cargo.toml b/Cargo.toml index 8dc4e2e..3672d07 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,4 +17,5 @@ uw8-tool = { path = "uw8-tool" } same-file = "1" warp = "0.3.2" tokio = { version = "1.17.0", features = ["sync", "rt"] } +tokio-stream = { version = "0.1.8", features = ["sync"] } webbrowser = "0.6.0" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c5a1359..743990e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -70,6 +70,14 @@ fn run(mut args: Arguments) -> Result<()> { let filename = args.free_from_os_str::(|s| Ok(s.into()))?; + let mut watcher = FileWatcher::builder(); + + if watch_mode { + watcher.add_file(&filename); + } + + let watcher = watcher.build()?; + if !run_browser { let mut uw8 = MicroW8::new()?; @@ -77,14 +85,6 @@ fn run(mut args: Arguments) -> Result<()> { uw8.set_timeout(timeout); } - let mut watcher = FileWatcher::builder(); - - if watch_mode { - watcher.add_file(&filename); - } - - let watcher = watcher.build()?; - if let Err(err) = start_cart(&filename, &mut uw8, &config) { eprintln!("Load error: {}", err); if !watch_mode { @@ -119,6 +119,14 @@ fn run(mut args: Arguments) -> Result<()> { } loop { + if watcher.poll_changed_file()?.is_some() { + match load_cart(&filename, &config) { + Ok(cart) => server.load_module(&cart)?, + Err(err) => { + eprintln!("Load error: {}", err); + } + } + } std::thread::sleep(Duration::from_millis(100)); } } diff --git a/src/run_web.rs b/src/run_web.rs index 4144930..c029dbe 100644 --- a/src/run_web.rs +++ b/src/run_web.rs @@ -1,14 +1,28 @@ use anyhow::Result; -use std::thread; +use std::{ + sync::{Arc, Mutex}, + thread, +}; +use tokio::sync::broadcast; +use tokio_stream::{wrappers::BroadcastStream, Stream, StreamExt}; use warp::{http::Response, Filter}; -pub struct RunWebServer {} +pub struct RunWebServer { + cart: Arc>>, + tx: broadcast::Sender<()>, +} impl RunWebServer { pub fn new() -> RunWebServer { + let cart = Arc::new(Mutex::new(Vec::new())); + let (tx, _) = broadcast::channel(1); + + let server_cart = cart.clone(); + let server_tx = tx.clone(); thread::spawn(move || { let rt = tokio::runtime::Builder::new_current_thread() .enable_io() + .enable_time() .build() .expect("Failed to create tokio runtime"); rt.block_on(async { @@ -18,17 +32,37 @@ impl RunWebServer { .body(include_str!("run-web.html")) }); - let server_future = warp::serve(html).bind(([127, 0, 0, 1], 3030)); + let cart = warp::path("cart") + .map(move || server_cart.lock().map_or(Vec::new(), |c| c.clone())); + + let events = warp::path("events").and(warp::get()).map(move || { + fn event_stream( + tx: &broadcast::Sender<()>, + ) -> impl Stream> + { + BroadcastStream::new(tx.subscribe()) + .map(|_| Ok(warp::sse::Event::default().data("L"))) + } + warp::sse::reply(warp::sse::keep_alive().stream(event_stream(&server_tx))) + }); + + let server_future = + warp::serve(html.or(cart).or(events)).bind(([127, 0, 0, 1], 3030)); println!("Point browser at 127.0.0.1:3030"); - let _ = webbrowser::open("http://127.0.0.1:3030"); + let _ignore_result = webbrowser::open("http://127.0.0.1:3030"); server_future.await }); }); - RunWebServer {} + RunWebServer { cart, tx } } pub fn load_module(&mut self, module_data: &[u8]) -> Result<()> { + if let Ok(mut lock) = self.cart.lock() { + lock.clear(); + lock.extend_from_slice(module_data); + } + let _ignore_result = self.tx.send(()); Ok(()) } } diff --git a/web/src/microw8.js b/web/src/microw8.js index 1b4556f..26f347c 100644 --- a/web/src/microw8.js +++ b/web/src/microw8.js @@ -2,6 +2,13 @@ import loaderUrl from "data-url:../../platform/bin/loader.wasm"; import platformUrl from "data-url:../../platform/bin/platform.uw8"; export default function MicroW8(screen, config = {}) { + if(!config.setMessage) { + config.setMessage = (s, e) => { + if(e) { + console.log('error: ' + e); + } + } + } let canvasCtx = screen.getContext('2d'); let imageData = canvasCtx.createImageData(320, 240); diff --git a/web/src/run-web.js b/web/src/run-web.js index f93a4f3..89817fd 100644 --- a/web/src/run-web.js +++ b/web/src/run-web.js @@ -5,6 +5,7 @@ let events = new EventSource('events'); events.onmessage = event => { console.log(event.data); if(event.data == 'L') { - uw8.runModuleFromURL('cart'); + uw8.runModuleFromURL('cart', true); } -}; \ No newline at end of file +}; +uw8.runModuleFromURL('cart', true); From 90467f7c5beeec1bca36193850dc6c93085f459b Mon Sep 17 00:00:00 2001 From: Dennis Ranke Date: Sun, 20 Feb 2022 23:54:28 +0100 Subject: [PATCH 6/7] add some more polish to web runner --- src/run-web.html | 1 + web/build-run-web | 2 ++ web/src/run-web.css | 46 ++++++++++++++++++++++++++++++++++++++++++++ web/src/run-web.html | 6 +++++- web/src/run-web.js | 10 +++++++++- 5 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 src/run-web.html create mode 100755 web/build-run-web create mode 100644 web/src/run-web.css diff --git a/src/run-web.html b/src/run-web.html new file mode 100644 index 0000000..7d86e72 --- /dev/null +++ b/src/run-web.html @@ -0,0 +1 @@ +uw8-run
\ No newline at end of file diff --git a/web/build-run-web b/web/build-run-web new file mode 100755 index 0000000..cc0cc6d --- /dev/null +++ b/web/build-run-web @@ -0,0 +1,2 @@ +#!/bin/bash +rm -rf .parcel-cache && yarn parcel build src/run-web.html && cp dist/run-web.html ../src/ diff --git a/web/src/run-web.css b/web/src/run-web.css new file mode 100644 index 0000000..ca6d48e --- /dev/null +++ b/web/src/run-web.css @@ -0,0 +1,46 @@ +html, body, canvas { + padding: 0; + margin: 0; + background-color: #202024; +} + +html { + height: 100%; +} + +body { + height: 100%; + display: grid; + grid-template-rows: 1fr; +} + +#screen { + align-self: center; + justify-self: center; + image-rendering: pixelated; + border: 4px solid #303040; +} + +#message { + position: absolute; + width: calc(100% - 16px); + background-color: rgba(0, 0, 0, 0.4); + color: #c64; + padding: 8px; + font: bold 12pt sans-serif; + z-index: 2; +} + +@media (min-width: 648px) and (min-height: 488px) { + #screen { + width: 640px; + height: 480px; + } +} + +@media (min-width: 968px) and (min-height: 728px) { + #screen { + width: 960px; + height: 720px; + } +} diff --git a/web/src/run-web.html b/web/src/run-web.html index 666cf0e..9799736 100644 --- a/web/src/run-web.html +++ b/web/src/run-web.html @@ -3,10 +3,14 @@ uw8-run + - + +