4 Commits

27 changed files with 292 additions and 106 deletions

4
Cargo.lock generated
View File

@@ -498,7 +498,7 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
[[package]] [[package]]
name = "curlywas" name = "curlywas"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/exoticorn/curlywas.git?rev=cda3eb868bc1aaa837c4d36898d0e885ee8fce59#cda3eb868bc1aaa837c4d36898d0e885ee8fce59" source = "git+https://github.com/exoticorn/curlywas.git?rev=89638565#896385654ab2c089200920b6dea4abec641c88d6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"ariadne", "ariadne",
@@ -2312,7 +2312,7 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]] [[package]]
name = "uw8" name = "uw8"
version = "0.1.1" version = "0.1.2"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"curlywas", "curlywas",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "uw8" name = "uw8"
version = "0.1.1" version = "0.1.2"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -16,7 +16,7 @@ anyhow = "1"
minifb = { version = "0.20", default-features = false, features = ["x11"] } minifb = { version = "0.20", default-features = false, features = ["x11"] }
notify = "4" notify = "4"
pico-args = "0.4" pico-args = "0.4"
curlywas = { git = "https://github.com/exoticorn/curlywas.git", rev = "cda3eb868bc1aaa837c4d36898d0e885ee8fce59" } curlywas = { git = "https://github.com/exoticorn/curlywas.git", rev = "89638565" }
wat = "1" wat = "1"
uw8-tool = { path = "uw8-tool" } uw8-tool = { path = "uw8-tool" }
same-file = "1" same-file = "1"

View File

@@ -15,9 +15,9 @@ See [here](https://exoticorn.github.io/microw8/) for more information and docs.
## Downloads ## Downloads
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.1.0/microw8-0.1.0-linux.tgz) * [Linux](https://github.com/exoticorn/microw8/releases/download/v0.1.2/microw8-0.1.2-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.1.0/microw8-0.1.0-macos.tgz) * [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.1.2/microw8-0.1.2-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.1.0/microw8-0.1.0-windows.zip) * [Windows](https://github.com/exoticorn/microw8/releases/download/v0.1.2/microw8-0.1.2-windows.zip)
The download includes The download includes
@@ -35,6 +35,7 @@ Runs <file> which can be a binary WebAssembly module, an `.uw8` cart, a wat (Web
Options: Options:
-b, --browser : Run in browser instead of using native runtime
-t, --timeout FRAMES : Sets the timeout in frames (1/60s) -t, --timeout FRAMES : Sets the timeout in frames (1/60s)
-w, --watch : Reloads the given file every time it changes on disk. -w, --watch : Reloads the given file every time it changes on disk.
-p, --pack : Pack the file into an .uw8 cart before running it and print the resulting size. -p, --pack : Pack the file into an .uw8 cart before running it and print the resulting size.

View File

@@ -1,4 +1,4 @@
include "microw8-api.cwa" include "../include/microw8-api.cwa"
export fn upd() { export fn upd() {
printString(0x20000); printString(0x20000);

View File

@@ -1,4 +1,4 @@
include "microw8-api.cwa" include "../include/microw8-api.cwa"
export fn upd() { export fn upd() {
cls(0); cls(0);

View File

@@ -1,4 +1,4 @@
include "microw8-api.cwa" include "../include/microw8-api.cwa"
global mut mode: i32 = 0; global mut mode: i32 = 0;

View File

@@ -1,4 +1,4 @@
include "microw8-api.cwa" include "../include/microw8-api.cwa"
export fn upd() { export fn upd() {
cls(0); cls(0);

View File

@@ -1,4 +1,4 @@
include "microw8-api.cwa" include "../include/microw8-api.cwa"
global mut pz: i32 = 4; global mut pz: i32 = 4;
global mut px: f32 = 2.0; global mut px: f32 = 2.0;

View File

@@ -1,4 +1,4 @@
include "microw8-api.cwa" include "../include/microw8-api.cwa"
export fn upd() { export fn upd() {
let x: i32; let x: i32;

View File

@@ -1,4 +1,4 @@
include "microw8-api.cwa" include "../include/microw8-api.cwa"
export fn upd() { export fn upd() {
let i: i32; let i: i32;

View File

@@ -1,4 +1,4 @@
include "microw8-api.cwa" include "../include/microw8-api.cwa"
export fn upd() { export fn upd() {
let i: i32; let i: i32;
@@ -9,7 +9,7 @@ export fn upd() {
let inline d = 40000 as f32 / sqrt(x * x + y * y); let inline d = 40000 as f32 / sqrt(x * x + y * y);
let inline u = atan2(x, y) * (512.0 / 3.141); let inline u = atan2(x, y) * (512.0 / 3.141);
let inline c = ((i32.trunc_sat_f32_s(d + t * 2 as f32) ^ i32.trunc_sat_f32_s(u + t)) & 255) >> 4; let inline c = ((i32.trunc_sat_f32_s(d + t * 2 as f32) ^ i32.trunc_sat_f32_s(u + t)) & 255) >> 4;
i?120 = c; i?FRAMEBUFFER = c;
branch_if (i := i + 1) < 320*240: pixels; branch_if (i := i + 1) < 320*240: pixels;
} }

View File

@@ -0,0 +1,52 @@
;; MicroW8 APIs, in WAT (Wasm Text) format
(import "env" "memory" (memory 4))
(import "env" "sin" (func $sin (param f32) (result f32)))
(import "env" "cos" (func $cos (param f32) (result f32)))
(import "env" "tan" (func $tan (param f32) (result f32)))
(import "env" "asin" (func $asin (param f32) (result f32)))
(import "env" "acos" (func $acos (param f32) (result f32)))
(import "env" "atan" (func $atan (param f32) (result f32)))
(import "env" "atan2" (func $atan2 (param f32) (param f32) (result f32)))
(import "env" "pow" (func $pow (param f32) (param f32) (result f32)))
(import "env" "log" (func $log (param f32) (result f32)))
(import "env" "fmod" (func $fmod (param f32) (param f32) (result f32)))
(import "env" "random" (func $random (result i32)))
(import "env" "randomf" (func $randomf (result f32)))
(import "env" "randomSeed" (func $randomSeed (param i32)))
(import "env" "cls" (func $cls (param i32)))
(import "env" "setPixel" (func $setPixel (param i32) (param i32) (param i32)))
(import "env" "getPixel" (func $getPixel (param i32) (param i32) (result i32)))
(import "env" "hline" (func $hline (param i32) (param i32) (param i32) (param i32)))
(import "env" "rectangle" (func $rectangle (param f32) (param f32) (param f32) (param f32) (param i32)))
(import "env" "circle" (func $circle (param f32) (param f32) (param f32) (param i32)))
(import "env" "line" (func $line (param f32) (param f32) (param f32) (param f32) (param i32)))
(import "env" "time" (func $time (result f32)))
(import "env" "isButtonPressed" (func $isButtonPressed (param i32) (result i32)))
(import "env" "isButtonTriggered" (func $isButtonTriggered (param i32) (result i32)))
(import "env" "printChar" (func $printChar (param i32)))
(import "env" "printString" (func $printString (param i32)))
(import "env" "printInt" (func $printInt (param i32)))
(import "env" "setTextColor" (func $setTextColor (param i32)))
(import "env" "setBackgroundColor" (func $setBackgroundColor (param i32)))
(import "env" "setCursorPosition" (func $setCursorPosition (param i32) (param i32)))
(import "env" "rectangle_outline" (func $rectangle_outline (param f32) (param f32) (param f32) (param f32) (param i32)))
(import "env" "circle_outline" (func $circle_outline (param f32) (param f32) (param f32) (param i32)))
(import "env" "exp" (func $exp (param f32) (result f32)))
;; to use defines, include this file with a preprocessor
;; like gpp (https://logological.org/gpp).
#define TIME_MS 0x40;
#define GAMEPAD 0x44;
#define FRAMEBUFFER 0x78;
#define PALETTE 0x13000;
#define FONT 0x13400;
#define USER_MEM 0x14000;
#define BUTTON_UP 0x0;
#define BUTTON_DOWN 0x1;
#define BUTTON_LEFT 0x2;
#define BUTTON_RIGHT 0x3;
#define BUTTON_A 0x4;
#define BUTTON_B 0x5;
#define BUTTON_X 0x6;
#define BUTTON_Y 0x7;

127
platform/Cargo.lock generated
View File

@@ -79,9 +79,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "chumsky" name = "chumsky"
version = "0.5.0" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2d3efff85e8572b1c3fa0127706af58c4fff8458f8d9436d54b1e97573c7a3f" checksum = "8d02796e4586c6c41aeb68eae9bfb4558a522c35f1430c14b40136c3706e09e4"
dependencies = [ dependencies = [
"ahash 0.3.8", "ahash 0.3.8",
] ]
@@ -146,14 +146,14 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]] [[package]]
name = "curlywas" name = "curlywas"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/exoticorn/curlywas.git?rev=196719b#196719b35ef377cb7e001554b27ac5de013dcf2b" source = "git+https://github.com/exoticorn/curlywas.git?rev=89638565#896385654ab2c089200920b6dea4abec641c88d6"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"ariadne", "ariadne",
"chumsky", "chumsky",
"pico-args", "pico-args",
"wasm-encoder", "wasm-encoder 0.10.0",
"wasmparser", "wasmparser 0.83.0",
] ]
[[package]] [[package]]
@@ -197,6 +197,21 @@ dependencies = [
"ahash 0.7.6", "ahash 0.7.6",
] ]
[[package]]
name = "heck"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
[[package]]
name = "id-arena"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@@ -227,6 +242,15 @@ dependencies = [
"rgb", "rgb",
] ]
[[package]]
name = "log"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.4.4" version = "0.4.4"
@@ -286,6 +310,24 @@ version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro2"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
dependencies = [
"proc-macro2",
]
[[package]] [[package]]
name = "rgb" name = "rgb"
version = "0.8.31" version = "0.8.31"
@@ -304,6 +346,17 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "syn"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]] [[package]]
name = "time" name = "time"
version = "0.1.43" version = "0.1.43"
@@ -323,6 +376,18 @@ dependencies = [
"crunchy", "crunchy",
] ]
[[package]]
name = "unicode-segmentation"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]] [[package]]
name = "upkr" name = "upkr"
version = "0.1.0" version = "0.1.0"
@@ -342,8 +407,9 @@ dependencies = [
"pbr", "pbr",
"pico-args", "pico-args",
"upkr", "upkr",
"wasm-encoder", "walrus",
"wasmparser", "wasm-encoder 0.8.0",
"wasmparser 0.81.0",
] ]
[[package]] [[package]]
@@ -352,6 +418,32 @@ version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
name = "walrus"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eb08e48cde54c05f363d984bb54ce374f49e242def9468d2e1b6c2372d291f8"
dependencies = [
"anyhow",
"id-arena",
"leb128",
"log",
"walrus-macro",
"wasmparser 0.77.0",
]
[[package]]
name = "walrus-macro"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6e5bd22c71e77d60140b0bd5be56155a37e5bd14e24f5f87298040d0cc40d7"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.10.2+wasi-snapshot-preview1" version = "0.10.2+wasi-snapshot-preview1"
@@ -367,12 +459,33 @@ dependencies = [
"leb128", "leb128",
] ]
[[package]]
name = "wasm-encoder"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa9d9bf45fc46f71c407837c9b30b1e874197f2dc357588430b21e5017d290ab"
dependencies = [
"leb128",
]
[[package]]
name = "wasmparser"
version = "0.77.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b35c86d22e720a07d954ebbed772d01180501afe7d03d464f413bb5f8914a8d6"
[[package]] [[package]]
name = "wasmparser" name = "wasmparser"
version = "0.81.0" version = "0.81.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98930446519f63d00a836efdc22f67766ceae8dbcc1571379f2bcabc6b2b9abc" checksum = "98930446519f63d00a836efdc22f67766ceae8dbcc1571379f2bcabc6b2b9abc"
[[package]]
name = "wasmparser"
version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a"
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"

View File

@@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
curlywas = { git="https://github.com/exoticorn/curlywas.git", rev="196719b" } curlywas = { git="https://github.com/exoticorn/curlywas.git", rev="89638565" }
uw8-tool = { path="../uw8-tool" } uw8-tool = { path="../uw8-tool" }
anyhow = "1" anyhow = "1"
lodepng = "3.4" lodepng = "3.4"

Binary file not shown.

Binary file not shown.

View File

@@ -12,15 +12,15 @@ fn main() -> Result<()> {
println!("Compiling loader module"); println!("Compiling loader module");
let loader = curlywas::compile_file("src/loader.cwa", curlywas::Options::default())?; let loader = curlywas::compile_file("src/loader.cwa", curlywas::Options::default())?;
File::create("bin/loader.wasm")?.write_all(&loader)?; File::create("bin/loader.wasm")?.write_all(&loader.wasm)?;
println!("Loader (including base module): {} bytes", loader.len()); println!("Loader (including base module): {} bytes", loader.wasm.len());
println!("Compiling platform module"); println!("Compiling platform module");
let platform = curlywas::compile_file("src/platform.cwa", curlywas::Options::default())?; let platform = curlywas::compile_file("src/platform.cwa", curlywas::Options::default())?;
println!("Compressing platform module"); println!("Compressing platform module");
let platform = uw8_tool::pack( let platform = uw8_tool::pack(
&platform, &platform.wasm,
&uw8_tool::PackConfig::default().with_compression_level(4), &uw8_tool::PackConfig::default().with_compression_level(4),
)?; )?;
File::create("bin/platform.uw8")?.write_all(&platform)?; File::create("bin/platform.uw8")?.write_all(&platform)?;

View File

@@ -256,6 +256,11 @@ export fn line(x1: f32, y1: f32, x2: f32, y2: f32, col: i32) {
p = y1; p = y1;
} }
if max_axis == 0 as f32 {
setPixel(x1 as i32, y1 as i32, col);
return;
}
let steps = floor(p + max_axis) as i32 - floor(p) as i32; let steps = floor(p + max_axis) as i32 - floor(p) as i32;
p = floor(p) + 0.5 - p; p = floor(p) + 0.5 - p;
if max_axis < 0 as f32 { if max_axis < 0 as f32 {
@@ -267,7 +272,7 @@ export fn line(x1: f32, y1: f32, x2: f32, y2: f32, col: i32) {
dy = dy / max_axis; dy = dy / max_axis;
let f = min(max_axis, max(0 as f32, p)); let f = min(max_axis, max(0 as f32, p));
setPixel((x1 + f * dx) as i32, (y1 + f * dy) as i32, col); setPixel(i32.trunc_sat_f32_s(x1 + f * dx), i32.trunc_sat_f32_s(y1 + f * dy), col);
if !steps { if !steps {
return; return;
@@ -280,7 +285,7 @@ export fn line(x1: f32, y1: f32, x2: f32, y2: f32, col: i32) {
loop pixels { loop pixels {
if steps := steps - 1 { if steps := steps - 1 {
setPixel(x1 as i32, y1 as i32, col); setPixel(i32.trunc_sat_f32_s(x1), i32.trunc_sat_f32_s(y1), col);
x1 = x1 + dx; x1 = x1 + dx;
y1 = y1 + dy; y1 = y1 + dy;
branch pixels; branch pixels;
@@ -288,7 +293,7 @@ export fn line(x1: f32, y1: f32, x2: f32, y2: f32, col: i32) {
} }
f = min(max_axis, p) - p; f = min(max_axis, p) - p;
setPixel((x1 + f * dx) as i32, (y1 + f * dy) as i32, col); setPixel(i32.trunc_sat_f32_s(x1 + f * dx), i32.trunc_sat_f32_s(y1 + f * dy), col);
} }
////////// //////////

View File

@@ -36,6 +36,8 @@ for dir in build/*; do
cp $example $dir/examples cp $example $dir/examples
done done
cp -r ../examples/include $dir/include
mkdir $dir/carts mkdir $dir/carts
for example in $dir/examples/*; do for example in $dir/examples/*; do
build/microw8-linux/uw8 pack -l 9 $example $dir/carts/$(basename ${example%.*}).uw8 build/microw8-linux/uw8 pack -l 9 $example $dir/carts/$(basename ${example%.*}).uw8

View File

@@ -15,11 +15,11 @@ The initial motivation behind MicroW8 was to explore whether there was a way to
* Gamepad input (D-Pad + 4 Buttons) * Gamepad input (D-Pad + 4 Buttons)
## Examples ## Examples
* [Fireworks](v0.1.1#AgwvgP+M59snqjl4CMKw5sqm1Zw9yJCbSviMjeLUdHus2a3yl/a99+uiBeqZgP/2jqSjrLjRk73COMM6OSLpsxK8ugT1kuk/q4hQUqqPpGozHoa0laulzGGcahzdfdJsYaK1sIdeIYS9M5PnJx/Wk9H+PvWEPy2Zvv7I6IW7Fg==) (127 bytes): Some fireworks to welcome 2022. * [Fireworks](v0.1.2#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 * [Skip Ahead](v0.1.2#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 * [OhNoAnotherTunnel](v0.1.2#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 * [Technotunnel](v0.1.2#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. * [Font & Palette](v0.1.2#At/p39+IBnj6ry1TRe7jzVy2A4tXgBvmoW2itzoyF2aM28pGy5QDiKxqrk8l9sbWZLtnAb+jgOfU+9QhpuyCAkhN6gPOU481IUL/df96vNe3h288Dqwhd3sfFpothIVFsMwRK72kW2hiR7zWsaXyy5pNmjR6BJk4piWx9ApT1ZwoUajhk6/zij6itq/FD1U3jj/J3MOwqZ2ef8Bv6ZPQlJIYVf62icGa69wS6SI1qBpIFiF14F8PcztRVbKIxLpT4ArCS6nz6FPnyUkqATGSBNPJ): Just a simple viewer for the default font and palette.
Examplers for older versions: Examplers for older versions:
@@ -29,6 +29,20 @@ Examplers for older versions:
## Versions ## Versions
### v0.1.2
* [Web runtime](v0.1.2)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.1.2/microw8-0.1.2-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.1.2/microw8-0.1.2-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.1.2/microw8-0.1.2-windows.zip)
Changes:
* add option to `uw8 run` to run the cart in the browser using the web runtime
* CurlyWas: implement `include` support
* CurlyWas: implement support for constants
* fix crash when trying to draw zero sized line
### v0.1.1 ### v0.1.1
* [Web runtime](v0.1.1) * [Web runtime](v0.1.1)

View File

@@ -284,7 +284,8 @@ Runs `<file>` which can be a binary WebAssembly module, an `.uw8` cart, a wat (W
Options: Options:
* `-t FRAMES`, `--timeout FRAMES` : Sets the timeout in frames (1/60s). If the start or update function runs longer than this it is forcibly interupted * `-b`, `--browser`: Run in browser instead of using native runtime
* `-t FRAMES`, `--timeout FRAMES`: Sets the timeout in frames (1/60s). If the start or update function runs longer than this it is forcibly interupted
and execution of the cart is stopped. Defaults to 30 (0.5s) and execution of the cart is stopped. Defaults to 30 (0.5s)
* `-w`, `--watch`: Reloads the given file every time it changes on disk. * `-w`, `--watch`: Reloads the given file every time it changes on disk.
* `-p`, `--pack`: Pack the file into an `.uw8` cart before running it and print the resulting size. * `-p`, `--pack`: Pack the file into an `.uw8` cart before running it and print the resulting size.

File diff suppressed because one or more lines are too long

View File

@@ -1,23 +1,38 @@
use anyhow::{bail, Result}; use anyhow::{anyhow, bail, Result};
use notify::{DebouncedEvent, Watcher, RecommendedWatcher}; use notify::{DebouncedEvent, RecommendedWatcher, Watcher};
use std::{ use std::{collections::BTreeSet, path::PathBuf, sync::mpsc, time::Duration};
collections::BTreeSet,
path::{Path, PathBuf},
sync::mpsc,
time::Duration,
};
pub struct FileWatcher { pub struct FileWatcher {
_watcher: RecommendedWatcher, watcher: RecommendedWatcher,
watched_files: BTreeSet<PathBuf>, watched_files: BTreeSet<PathBuf>,
directories: BTreeSet<PathBuf>,
rx: mpsc::Receiver<DebouncedEvent>, rx: mpsc::Receiver<DebouncedEvent>,
} }
pub struct FileWatcherBuilder(BTreeSet<PathBuf>);
impl FileWatcher { impl FileWatcher {
pub fn builder() -> FileWatcherBuilder { pub fn new() -> Result<FileWatcher> {
FileWatcherBuilder(BTreeSet::new()) let (tx, rx) = mpsc::channel();
let watcher = notify::watcher(tx, Duration::from_millis(100))?;
Ok(FileWatcher {
watcher,
watched_files: BTreeSet::new(),
directories: BTreeSet::new(),
rx,
})
}
pub fn add_file<P: Into<PathBuf>>(&mut self, path: P) -> Result<()> {
let path = path.into();
let parent = path.parent().ok_or_else(|| anyhow!("File has no parent"))?;
if !self.directories.contains(parent) {
self.watcher
.watch(parent, notify::RecursiveMode::NonRecursive)?;
self.directories.insert(parent.to_path_buf());
}
self.watched_files.insert(path);
Ok(())
} }
pub fn poll_changed_file(&self) -> Result<Option<PathBuf>> { pub fn poll_changed_file(&self) -> Result<Option<PathBuf>> {
@@ -38,33 +53,3 @@ impl FileWatcher {
Ok(None) Ok(None)
} }
} }
impl FileWatcherBuilder {
pub fn add_file<P: Into<PathBuf>>(&mut self, path: P) -> &mut Self {
self.0.insert(path.into());
self
}
pub fn build(self) -> Result<FileWatcher> {
let mut directories: BTreeSet<&Path> = BTreeSet::new();
for file in &self.0 {
if let Some(directory) = file.parent() {
directories.insert(directory);
}
}
let (tx, rx) = mpsc::channel();
let mut watcher = notify::watcher(tx, Duration::from_millis(100))?;
for directory in directories {
watcher.watch(directory, notify::RecursiveMode::NonRecursive)?;
}
Ok(FileWatcher {
_watcher: watcher,
watched_files: self.0,
rx,
})
}
}

View File

@@ -77,13 +77,7 @@ fn run(mut args: Arguments) -> Result<()> {
let filename = args.free_from_os_str::<PathBuf, bool>(|s| Ok(s.into()))?; let filename = args.free_from_os_str::<PathBuf, bool>(|s| Ok(s.into()))?;
let mut watcher = uw8::FileWatcher::builder(); let mut watcher = uw8::FileWatcher::new()?;
if watch_mode {
watcher.add_file(&filename);
}
let watcher = watcher.build()?;
use std::process::exit; use std::process::exit;
@@ -103,18 +97,26 @@ fn run(mut args: Arguments) -> Result<()> {
runtime.set_timeout(timeout); runtime.set_timeout(timeout);
} }
if let Err(err) = start_cart(&filename, &mut *runtime, &config) { let mut first_run = true;
eprintln!("Load error: {}", err);
if !watch_mode {
exit(1);
}
}
while runtime.is_open() { while runtime.is_open() {
if watcher.poll_changed_file()?.is_some() { if first_run || watcher.poll_changed_file()?.is_some() {
if let Err(err) = start_cart(&filename, &mut *runtime, &config) { match start_cart(&filename, &mut *runtime, &config) {
eprintln!("Load error: {}", err); Ok(dependencies) => {
if watch_mode {
for dep in dependencies {
watcher.add_file(dep)?;
}
}
}
Err(err) => {
eprintln!("Load error: {}", err);
if !watch_mode {
exit(1);
}
}
} }
first_run = false;
} }
if let Err(err) = runtime.run_frame() { if let Err(err) = runtime.run_frame() {
@@ -134,15 +136,25 @@ struct Config {
output_path: Option<PathBuf>, output_path: Option<PathBuf>,
} }
fn load_cart(filename: &Path, config: &Config) -> Result<Vec<u8>> { fn load_cart(filename: &Path, config: &Config) -> Result<(Vec<u8>, Vec<PathBuf>)> {
let mut dependencies = Vec::new();
let mut cart = match SourceType::of_file(filename)? { let mut cart = match SourceType::of_file(filename)? {
SourceType::Binary => { SourceType::Binary => {
let mut cart = vec![]; let mut cart = vec![];
File::open(filename)?.read_to_end(&mut cart)?; File::open(filename)?.read_to_end(&mut cart)?;
dependencies.push(filename.to_path_buf());
cart cart
} }
SourceType::Wat => wat::parse_file(filename)?, SourceType::Wat => {
SourceType::CurlyWas => curlywas::compile_file(filename, curlywas::Options::default())?, let cart = wat::parse_file(filename)?;
dependencies.push(filename.to_path_buf());
cart
}
SourceType::CurlyWas => {
let module = curlywas::compile_file(filename, curlywas::Options::default())?;
dependencies = module.dependencies;
module.wasm
}
}; };
if let Some(ref pack_config) = config.pack { if let Some(ref pack_config) = config.pack {
@@ -154,7 +166,7 @@ fn load_cart(filename: &Path, config: &Config) -> Result<Vec<u8>> {
File::create(path)?.write_all(&cart)?; File::create(path)?.write_all(&cart)?;
} }
Ok(cart) Ok((cart, dependencies))
} }
enum SourceType { enum SourceType {
@@ -193,14 +205,14 @@ impl SourceType {
} }
#[cfg(any(feature = "native", feature = "browser"))] #[cfg(any(feature = "native", feature = "browser"))]
fn start_cart(filename: &Path, runtime: &mut dyn Runtime, config: &Config) -> Result<()> { fn start_cart(filename: &Path, runtime: &mut dyn Runtime, config: &Config) -> Result<Vec<PathBuf>> {
let cart = load_cart(filename, config)?; let cart = load_cart(filename, config)?;
if let Err(err) = runtime.load(&cart) { if let Err(err) = runtime.load(&cart.0) {
eprintln!("Load error: {}", err); eprintln!("Load error: {}", err);
Err(err) Err(err)
} else { } else {
Ok(()) Ok(cart.1)
} }
} }
@@ -219,7 +231,7 @@ fn pack(mut args: Arguments) -> Result<()> {
let out_file = args.free_from_os_str::<PathBuf, bool>(|s| Ok(s.into()))?; let out_file = args.free_from_os_str::<PathBuf, bool>(|s| Ok(s.into()))?;
let cart = load_cart( let (cart, _) = load_cart(
&in_file, &in_file,
&Config { &Config {
pack: Some(pack_config), pack: Some(pack_config),
@@ -249,7 +261,7 @@ fn compile(mut args: Arguments) -> Result<()> {
let out_file = args.free_from_os_str::<PathBuf, bool>(|s| Ok(s.into()))?; let out_file = args.free_from_os_str::<PathBuf, bool>(|s| Ok(s.into()))?;
let module = curlywas::compile_file(in_file, options)?; let module = curlywas::compile_file(in_file, options)?;
File::create(out_file)?.write_all(&module)?; File::create(out_file)?.write_all(&module.wasm)?;
Ok(()) Ok(())
} }

File diff suppressed because one or more lines are too long

View File

@@ -10,7 +10,7 @@
</head> </head>
<body> <body>
<div id="uw8"> <div id="uw8">
<a href="https://exoticorn.github.io/microw8">MicroW8</a> 0.1.1 <a href="https://exoticorn.github.io/microw8">MicroW8</a> 0.1.2
</div> </div>
<div id="centered"> <div id="centered">
<canvas id="screen" width="320" height="240"> <canvas id="screen" width="320" height="240">