diff --git a/Cargo.lock b/Cargo.lock index 0a9216e..d1fe1c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1517,7 +1517,7 @@ dependencies = [ [[package]] name = "uw8" -version = "0.1.0" +version = "0.1.1" dependencies = [ "anyhow", "curlywas", diff --git a/Cargo.toml b/Cargo.toml index 4b0710d..42f0780 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "uw8" -version = "0.1.0" +version = "0.1.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/README.md b/README.md index 8edf3f5..47f8415 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,21 @@ Options: -l LEVEL, --level LEVEL : Compression level (0-9). Higher compression levels are really slow. +uw8 unpack + +Unpacks a MicroW8 module into a standard WebAssembly module. + + +uw8 compile [] + +Compiles a CurlyWas source file to a standard WebAssembly module. Most useful together with +the --debug option to get a module that works well in the Chrome debugger. + +Options: + +-d, --debug : Generate a name section to help debugging + + uw8 filter-exports Reads a binary WebAssembly module, removes all exports not used by the MicroW8 platform + everything that is unreachable without those exports and writes the resulting module to . diff --git a/examples/c/build.sh b/examples/c/build.sh index 93d1d22..61bbe37 100755 --- a/examples/c/build.sh +++ b/examples/c/build.sh @@ -1,6 +1,6 @@ #!/bin/bash -clang -O2 -Wno-incompatible-library-redeclaration --no-standard-libraries -ffast-math -Xclang -target-feature -Xclang +nontrapping-fptoint -Wl,--no-entry -Wl,--export-all -Wl,--import-memory -Wl,--initial-memory=262144 -Wl,-zstack-size=90000 -o cart.wasm cart.c --target=wasm32 && \ +clang -O2 -Wno-incompatible-library-redeclaration --no-standard-libraries -ffast-math -Xclang -target-feature -Xclang +nontrapping-fptoint -Wl,--no-entry,--export-all,--import-memory,--initial-memory=262144,--global-base=81920,-zstack-size=4096 -o cart.wasm cart.c --target=wasm32 && \ uw8 filter-exports cart.wasm cart.wasm && \ wasm-opt -Oz --fast-math --strip-producers -o cart.wasm cart.wasm && \ uw8 pack -l 9 cart.wasm cart.uw8 \ No newline at end of file diff --git a/site/content/_index.md b/site/content/_index.md index ca72c44..c904583 100644 --- a/site/content/_index.md +++ b/site/content/_index.md @@ -15,11 +15,14 @@ The initial motivation behind MicroW8 was to explore whether there was a way to * Gamepad input (D-Pad + 4 Buttons) ## Examples -* [Fireworks](v0.1pre5#AgwvgP+M59snqjl4CMKw5sqm1Zw9yJCbSviMjeLUdHus2a3yl/a99+uiBeqZgP/2jqSjrLjRk73COMM6OSLpsxK8ugT1kuk/q4hQUqqPpGozHoa0laulzGGcahzdfdJsYaK1sIdeIYS9M5PnJx/Wk9H+PvWEPy2Zvv7I6IW7Fg==) (127 bytes): Some fireworks to welcome 2022. -* [Skip Ahead](v0.1pre5#AgyfpZ80wkW28kiUZ9VIK4v+RPnVxqjK1dz2BcDoNyQPsS2g4OgEzkTe6jyoAfFOmqKrS8SM2aRljBal9mjNn8i4fP9eBK+RehQKxxGtJa9FqftvqEnh3ez1YaYxqj7jgTdzJ/WAYVmKMovBT1myrX3FamqKSOgMsNedLhVTLAhQup3sNcYEjGNo8b0HZ5+AgMgCwYRGCe//XQOMAaAAzqDILgmpEZ/43RKHcQpHEQwbURfNQJpadJe2sz3q5FlQnTGXQ9oSMokidhlC+aR/IpNHieuBGLhFZ2GfnwVQ0geBbQpTPA==) (229 bytes): A port of my [TIC-80 256byte game](http://tic80.com/play?cart=1735) from LoveByte'21 -* [OhNoAnotherTunnel](v0.1pre4#Ag95rdCB5Ww5NofyQaKF4P1mrNRso4azgiem4hK99Gh8OMzSpFq3NsNDo7O7pqln10D11l9uXr/ritw7OEzKwbEfCdvaRnS2Z0Kz0iDEZt/gIqOdvFmxsL1MjPQ4XInPbUJpQUonhQq29oP2omFabnQxn0bzoK7mZjcwc5GetHG+hGajkJcRr8oOnjfCol8RD+ha33GYtPnut+GLe4ktzf5UxZwGs6oT9qqC61lRDakN) (177 bytes): A port of my [entry](http://tic80.com/play?cart=1871) in the Outline'21 bytebattle final -* [Technotunnel](v0.1pre4#AqL8HeK1M9dn2nWNIF5vaq/Vh64pMt5nJIFoFKpBMPUsGtDtpqjo1JbT9LzPhAxCqJ7Yh4TA6oTGd4xhLowf+cWZMY73+7AZmfXJJsBi4cej/hH+4wlAgxFIrnOYnr/18IpnZbsHf0eGm1BhahX74+cVR0TRmNQmYC7GhCNS3mv/3MJn74lCj7t28aBJPjEZhP9fGXdG2u5Egh/Tjdg=) (158 bytes): A port of my [entry](https://tic80.com/play?cart=1873) in the Outline'21 bytebattle quater final -* [Font & Palette](v0.1pre4#AgKaeeOuwg5gCKvFIeiitEwMpUI2rymEcu+DDB1vMu9uBoufvUxIr4Y5p4Jj2ukoNO4PE7QS5cN1ZyDMCRfSzYIGZxKlN2J6NKEWK7KVPk9wVUgn1Ip+hsMinWgEO8ETKfPuHoIa4kjI+ULFOMad7vd3rt/lh1Vy9w+R2MXG/7T61d3c7C6KY+eQNS0eW3ys4iU8R6SycuWZuuZ2Sg3Qxp826s+Kt+2qBojpzNOSoyFqyrVyYMTKEkSl0BZOj59Cs1hPm5bq0F1MmVhGAzMhW9V4YeAe): Just a simple viewer for the default font and palette. +* [Fireworks](v0.1.1#AgwvgP+M59snqjl4CMKw5sqm1Zw9yJCbSviMjeLUdHus2a3yl/a99+uiBeqZgP/2jqSjrLjRk73COMM6OSLpsxK8ugT1kuk/q4hQUqqPpGozHoa0laulzGGcahzdfdJsYaK1sIdeIYS9M5PnJx/Wk9H+PvWEPy2Zvv7I6IW7Fg==) (127 bytes): Some fireworks to welcome 2022. +* [Skip Ahead](v0.1.1#AgyfpZ80wkW28kiUZ9VIK4v+RPnVxqjK1dz2BcDoNyQPsS2g4OgEzkTe6jyoAfFOmqKrS8SM2aRljBal9mjNn8i4fP9eBK+RehQKxxGtJa9FqftvqEnh3ez1YaYxqj7jgTdzJ/WAYVmKMovBT1myrX3FamqKSOgMsNedLhVTLAhQup3sNcYEjGNo8b0HZ5+AgMgCwYRGCe//XQOMAaAAzqDILgmpEZ/43RKHcQpHEQwbURfNQJpadJe2sz3q5FlQnTGXQ9oSMokidhlC+aR/IpNHieuBGLhFZ2GfnwVQ0geBbQpTPA==) (229 bytes): A port of my [TIC-80 256byte game](http://tic80.com/play?cart=1735) from LoveByte'21 +* [OhNoAnotherTunnel](v0.1.1#AgPP1oEFvPzY/rBZwTumtYn37zeMFgpir1Bkn91jsNcp26VzoUpkAOOJTtnzVBfW+/dGnnIdbq/irBUJztY5wuua80DORTYZndgdwZHcSk15ajc4nyO0g1A6kGWyW56oZk0iPYJA9WtUmoj0Plvy1CGwIZrMe57X7QZcdqc3u6zjTA41Tpiqi9vnO3xbhi8o594Vx0XPXwVzpYq1ZCTYenfAGaXKkDmAFJqiVIsiCg==) (175 bytes): A port of my [entry](http://tic80.com/play?cart=1871) in the Outline'21 bytebattle final +* [Technotunnel](v0.1.1#AhPXpq894LaUhp5+HQf39f39/Jc8g5zUrBSc0uyKh36ivskczhY84h55zL8gWpkdvKuRQI+KIt80isKzh8jkM8nILcx0RUvyk8yjE8TgNsgkcORVI0RY5k3qE4ySjaycxa2DVZH61UWZuLsCouuwT7I80TbmmetQSbMywJ/avrrCZIAH0UzQfvOiCJNG48NI0FFY1vjB7a7dcp8Uqg==) (157 bytes): A port of my [entry](https://tic80.com/play?cart=1873) in the Outline'21 bytebattle quater final +* [Font & Palette](v0.1.1#At/p39+IBnj6ry1TRe7jzVy2A4tXgBvmoW2itzoyF2aM28pGy5QDiKxqrk8l9sbWZLtnAb+jgOfU+9QhpuyCAkhN6gPOU481IUL/df96vNe3h288Dqwhd3sfFpothIVFsMwRK72kW2hiR7zWsaXyy5pNmjR6BJk4piWx9ApT1ZwoUajhk6/zij6itq/FD1U3jj/J3MOwqZ2ef8Bv6ZPQlJIYVf62icGa69wS6SI1qBpIFiF14F8PcztRVbKIxLpT4ArCS6nz6FPnyUkqATGSBNPJ): Just a simple viewer for the default font and palette. + +Examplers for older versions: + * [Technotunnel B/W](v0.1pre2#AQrDAQHAAQIBfwp9A0AgAUEAsiABQcACb7JDmhkgQ5MiBCAEIASUIAFBwAJtQfgAa7IiBSAFlJKRIgaVIgcgByAAskHQD7KVIgIQAEPNzEw/lCIDlCAHIAeUIAOUIAOUQQGykiADIAOUk5GSIgiUIAOTQQqylCACkiIJqCAFIAaVIAiUQQqylCACkiIKqHMgCEEyspQgBpUiCyACkkEUspSocUEFcbJBArIgC5OUQRaylJeoOgB4IAFBAWoiAUGA2ARIDQALCw==) (199 bytes uncompressed): A port of my [entry](https://tic80.com/play?cart=1873) in the Outline'21 bytebattle quater final (older MicroW8 version with monochrome palette) * [XorScroll](v0.1pre2#AQovAS0BAX8DQCABIAFBwAJvIABBCm1qIAFBwAJtczoAeCABQQFqIgFBgNgESA0ACws=) (50 bytes uncompressed): A simple scrolling XOR pattern. Fun fact: This is the pre-loaded effect when entering a bytebattle. * [CircleWorm](v0.1pre2#AQp7AXkCAX8CfUEgEA0DQCABskEEspUiAkECspUgALJBiCeylSIDQQWylJIQAEEBspJBoAGylCACQQOylSADQQSylJIQAEEBspJB+ACylCADQRGylCACQQKylJIQAEECspJBELKUIAFBAmxBP2oQEiABQQFqIgFBP0gNAAsL) (126 bytes uncompressed): Just a test for the circle fill function. diff --git a/site/content/docs.md b/site/content/docs.md index dd48010..205e9a8 100644 --- a/site/content/docs.md +++ b/site/content/docs.md @@ -105,7 +105,7 @@ as a cheap random-access PRNG (aka noise function). ## Graphics -The default palette can be seen [here](../v0.1pre4#AgKaeeOuwg5gCKvFIeiitEwMpUI2rymEcu+DDB1vMu9uBoufvUxIr4Y5p4Jj2ukoNO4PE7QS5cN1ZyDMCRfSzYIGZxKlN2J6NKEWK7KVPk9wVUgn1Ip+hsMinWgEO8ETKfPuHoIa4kjI+ULFOMad7vd3rt/lh1Vy9w+R2MXG/7T61d3c7C6KY+eQNS0eW3ys4iU8R6SycuWZuuZ2Sg3Qxp826s+Kt+2qBojpzNOSoyFqyrVyYMTKEkSl0BZOj59Cs1hPm5bq0F1MmVhGAzMhW9V4YeAe). (Press Z on the keyboard to switch to palette.) +The default palette can be seen [here](../v0.1.0#At/p39+IBnj6ry1TRe7jzVy2A4tXgBvmoW2itzoyF2aM28pGy5QDiKxqrk8l9sbWZLtnAb+jgOfU+9QhpuyCAkhN6gPOU481IUL/df96vNe3h288Dqwhd3sfFpothIVFsMwRK72kW2hiR7zWsaXyy5pNmjR6BJk4piWx9ApT1ZwoUajhk6/zij6itq/FD1U3jj/J3MOwqZ2ef8Bv6ZPQlJIYVf62icGa69wS6SI1qBpIFiF14F8PcztRVbKIxLpT4ArCS6nz6FPnyUkqATGSBNPJ). (Press Z on the keyboard to switch to palette.) The palette can be changed by writing 32bit rgba colors to addresses 0x13000-0x13400. @@ -192,7 +192,7 @@ The integer time in milliseconds can also be read at address 0x40. ## Text output -The default font can be seen [here](../v0.1pre4#AgKaeeOuwg5gCKvFIeiitEwMpUI2rymEcu+DDB1vMu9uBoufvUxIr4Y5p4Jj2ukoNO4PE7QS5cN1ZyDMCRfSzYIGZxKlN2J6NKEWK7KVPk9wVUgn1Ip+hsMinWgEO8ETKfPuHoIa4kjI+ULFOMad7vd3rt/lh1Vy9w+R2MXG/7T61d3c7C6KY+eQNS0eW3ys4iU8R6SycuWZuuZ2Sg3Qxp826s+Kt+2qBojpzNOSoyFqyrVyYMTKEkSl0BZOj59Cs1hPm5bq0F1MmVhGAzMhW9V4YeAe). +The default font can be seen [here](../v0.1.0#At/p39+IBnj6ry1TRe7jzVy2A4tXgBvmoW2itzoyF2aM28pGy5QDiKxqrk8l9sbWZLtnAb+jgOfU+9QhpuyCAkhN6gPOU481IUL/df96vNe3h288Dqwhd3sfFpothIVFsMwRK72kW2hiR7zWsaXyy5pNmjR6BJk4piWx9ApT1ZwoUajhk6/zij6itq/FD1U3jj/J3MOwqZ2ef8Bv6ZPQlJIYVf62icGa69wS6SI1qBpIFiF14F8PcztRVbKIxLpT4ArCS6nz6FPnyUkqATGSBNPJ). The font can be changed by writing 1bpp 8x8 characters to addresses 0x13400-0x13c00. @@ -305,6 +305,27 @@ Options: * `-u`, `--uncompressed`: Use the uncompressed `uw8` format for packing. * `-l LEVEL`, `--level LEVEL`: Compression level (0-9). Higher compression levels are really slow. +## `uw8 unpack` + +Usage: + +`uw8 unpack ` + +Unpacks a MicroW8 module into a standard WebAssembly module. + +## `uw8 compile` + +Usage: + +`uw8 compile [] ` + +Compiles a [CurlyWas](https://github.com/exoticorn/curlywas) source file to a standard WebAssembly module. Most useful together with +the `--debug` option to get a module that works well in the Chrome debugger. + +Options: + +* `-d`, `--debug`: Generate a name section to help debugging + ## `uw8 filter-exports` Usage: @@ -393,7 +414,12 @@ using a [custom LZ compression scheme](https://github.com/exoticorn/upkr). # The web runtime -[...] +Load carts into the web runtime either by using the "Load cart..." button, or by dragging the file +onto the screen area. + +## Input + +For input, you can either use a standard gamepad or keyboard. On a keyboard use the arrow keys and the keys Z, X, A and S to emulate the A, B, X and Y buttons. ## Video recording @@ -409,4 +435,9 @@ ffmpeg -i IN.webm -vf "scale=960:720:flags=neighbor,pad=1280:720:160:0" -r 60 OU ## Screenshot -Pressing F9 opens a download dialog with a screenshot. \ No newline at end of file +Pressing F9 opens a download dialog with a screenshot. + +## Devkit mode + +Append `#devkit` to the web runtime url in order to switch to devkit mode. In devkit mode, standard web assembly modules +are loaded bypassing the loader, removing all size restrictions. At the same time, the memory limit is increased to 1GB. \ No newline at end of file diff --git a/site/static/v0.1.1/index.html b/site/static/v0.1.1/index.html new file mode 100644 index 0000000..03cc5e1 --- /dev/null +++ b/site/static/v0.1.1/index.html @@ -0,0 +1 @@ +MicroW8
MicroW8 0.1.1
\ No newline at end of file diff --git a/site/templates/index.html b/site/templates/index.html index e38b2f5..9218dba 100644 --- a/site/templates/index.html +++ b/site/templates/index.html @@ -4,7 +4,7 @@

A WebAssembly based fantasy console

- + diff --git a/src/main.rs b/src/main.rs index e620e17..dc19e3c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,8 @@ fn main() -> Result<()> { } Some("run") => run(args), Some("pack") => pack(args), + Some("unpack") => unpack(args), + Some("compile") => compile(args), Some("filter-exports") => filter_exports(args), Some("help") | None => { println!("uw8 {}", env!("CARGO_PKG_VERSION")); @@ -27,6 +29,8 @@ fn main() -> Result<()> { println!("Usage:"); println!(" uw8 run [-t/--timeout ] [-w/--watch] [-p/--pack] [-u/--uncompressed] [-l/--level] [-o/--output ] "); println!(" uw8 pack [-u/--uncompressed] [-l/--level] "); + println!(" uw8 unpack "); + println!(" uw8 compile [-d/--debug] "); println!(" uw8 filter-exports "); Ok(()) } @@ -166,6 +170,28 @@ fn pack(mut args: Arguments) -> Result<()> { Ok(()) } +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() +} + +fn compile(mut args: Arguments) -> Result<()> { + let mut options = curlywas::Options::default(); + if args.contains(["-d", "--debug"]) { + options = options.with_debug(); + } + + let in_file = args.free_from_os_str::(|s| Ok(s.into()))?; + let out_file = args.free_from_os_str::(|s| Ok(s.into()))?; + + let module = curlywas::compile_file(in_file, options)?; + File::create(out_file)?.write_all(&module)?; + + Ok(()) +} + fn filter_exports(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()))?; diff --git a/web/src/index.html b/web/src/index.html index aaa6141..f6407ec 100644 --- a/web/src/index.html +++ b/web/src/index.html @@ -10,7 +10,7 @@
- MicroW8 0.1.0 + MicroW8 0.1.1
diff --git a/web/src/main.js b/web/src/main.js index 80cf704..423d076 100644 --- a/web/src/main.js +++ b/web/src/main.js @@ -13,6 +13,8 @@ let screen = document.getElementById('screen'); let canvasCtx = screen.getContext('2d'); let imageData = canvasCtx.createImageData(320, 240); +let devkitMode; + let cancelFunction; let currentData; @@ -51,7 +53,7 @@ let keyHandler = (e) => { break; case 'KeyR': if (isKeyDown) { - runModule(currentData); + runModule(currentData, true); } break; case 'F9': @@ -110,7 +112,11 @@ async function runModule(data, keepUrl) { screen.width = screen.width; try { - let memory = new WebAssembly.Memory({ initial: 4, maximum: 4 }); + 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 = { @@ -122,7 +128,7 @@ async function runModule(data, keepUrl) { let loader; let loadModuleData = (data) => { - if (U8(data)[0] != 0) { + if (loader && (!devkitMode || U8(data)[0] != 0)) { memU8.set(U8(data)); let length = loader.exports.load_uw8(data.byteLength); data = new ArrayBuffer(length); @@ -293,11 +299,16 @@ async function runModuleFromURL(url, keepUrl) { if(type && type.includes('html')) { throw false; } - runModule(await response.arrayBuffer(), keepUrl); + runModule(await response.arrayBuffer(), keepUrl || devkitMode); } function runModuleFromHash() { let hash = window.location.hash.slice(1); + if(hash == 'devkit') { + devkitMode = true; + return; + } + devkitMode = false; if (hash.length > 0) { if (hash.startsWith("url=")) { runModuleFromURL(hash.slice(4), true);