diff --git a/Cargo.lock b/Cargo.lock index 0059edf..957e1a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -238,9 +238,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chumsky" -version = "0.5.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2d3efff85e8572b1c3fa0127706af58c4fff8458f8d9436d54b1e97573c7a3f" +checksum = "8d02796e4586c6c41aeb68eae9bfb4558a522c35f1430c14b40136c3706e09e4" dependencies = [ "ahash", ] @@ -498,14 +498,14 @@ checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" [[package]] name = "curlywas" version = "0.1.0" -source = "git+https://github.com/exoticorn/curlywas.git?rev=196719b#196719b35ef377cb7e001554b27ac5de013dcf2b" +source = "git+https://github.com/exoticorn/curlywas.git?rev=cda3eb868bc1aaa837c4d36898d0e885ee8fce59#cda3eb868bc1aaa837c4d36898d0e885ee8fce59" dependencies = [ "anyhow", "ariadne", "chumsky", "pico-args", - "wasm-encoder", - "wasmparser 0.81.0", + "wasm-encoder 0.10.0", + "wasmparser 0.83.0", ] [[package]] @@ -2338,7 +2338,7 @@ dependencies = [ "pico-args", "upkr", "walrus", - "wasm-encoder", + "wasm-encoder 0.8.0", "wasmparser 0.81.0", ] @@ -2506,6 +2506,15 @@ dependencies = [ "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" @@ -2524,6 +2533,12 @@ version = "0.81.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98930446519f63d00a836efdc22f67766ceae8dbcc1571379f2bcabc6b2b9abc" +[[package]] +name = "wasmparser" +version = "0.83.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a" + [[package]] name = "wasmtime" version = "0.30.0" diff --git a/Cargo.toml b/Cargo.toml index 4195385..df4789c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ anyhow = "1" minifb = { version = "0.20", default-features = false, features = ["x11"] } notify = "4" pico-args = "0.4" -curlywas = { git = "https://github.com/exoticorn/curlywas.git", rev = "196719b" } +curlywas = { git = "https://github.com/exoticorn/curlywas.git", rev = "cda3eb868bc1aaa837c4d36898d0e885ee8fce59" } wat = "1" uw8-tool = { path = "uw8-tool" } same-file = "1" diff --git a/examples/curlywas/control.cwa b/examples/curlywas/control.cwa index e9202b5..50afdf8 100644 --- a/examples/curlywas/control.cwa +++ b/examples/curlywas/control.cwa @@ -1,5 +1,4 @@ -import "env.memory" memory(4); -import "env.printString" fn printString(i32); +include "microw8-api.cwa" export fn upd() { printString(0x20000); diff --git a/examples/curlywas/fireworks.cwa b/examples/curlywas/fireworks.cwa index 3976171..7d008ca 100644 --- a/examples/curlywas/fireworks.cwa +++ b/examples/curlywas/fireworks.cwa @@ -1,11 +1,4 @@ -import "env.time" fn time() -> f32; -import "env.circle" fn circle(f32, f32, f32, i32); -import "env.cls" fn cls(i32); -import "env.randomSeed" fn seed(i32); -import "env.randomf" fn randomf() -> f32; -import "env.sin" fn sin(f32) -> f32; -import "env.cos" fn cos(f32) -> f32; -import "env.fmod" fn fmod(f32, f32) -> f32; +include "microw8-api.cwa" export fn upd() { cls(0); @@ -15,10 +8,10 @@ export fn upd() { let inline rocket = i #>> 9; let lazy local_time = fmod(time() + rocket as f32 / 5 as f32, 2 as f32); let lazy rocket = rocket + nearest(time() - local_time) as i32 * 10; - seed(rocket); + randomSeed(rocket); let inline x = randomf() * 645 as f32; let y = randomf() * 133 as f32; - let lazy angle = { seed(i); randomf() } * 44 as f32; + let lazy angle = { randomSeed(i); randomf() } * 44 as f32; let inline dx = sin(angle); let inline dy = cos(angle); let lazy dist = local_time * (randomf() * 44 as f32); diff --git a/examples/curlywas/font_palette.cwa b/examples/curlywas/font_palette.cwa index 7cb199a..67dc94e 100644 --- a/examples/curlywas/font_palette.cwa +++ b/examples/curlywas/font_palette.cwa @@ -1,38 +1,30 @@ -import "env.memory" memory(4); - -import "env.cls" fn cls(i32); -import "env.printString" fn printString(i32); -import "env.printChar" fn printChar(i32); -import "env.setCursorPosition" fn setCursor(i32, i32); -import "env.setTextColor" fn setTextColor(i32); -import "env.line" fn line(f32, f32, f32, f32, i32); -import "env.isButtonTriggered" fn triggered(i32) -> i32; +include "microw8-api.cwa" global mut mode: i32 = 0; export fn upd() { cls(0); - if triggered(4) { + if isButtonTriggered(BUTTON_A) { mode = !mode; } setTextColor(15); - printString(mode * 0x20000); + printString(mode * USER_MEM); let y: i32; loop y { line(0 as f32, (y * 9 + 39) as f32, (14+16*9) as f32, (y * 9 + 39) as f32, 1); line((y * 9 + 15) as f32, 24 as f32, (y * 9 + 15) as f32, (38+16*9) as f32, 1); setTextColor(15); - setCursor(y * 9 + 16, 24); + setCursorPosition(y * 9 + 16, 24); let lazy hexChar = select(y < 10, y + 48, y + 87); printChar(hexChar); - setCursor(0, y * 9 + 24+16); + setCursorPosition(0, y * 9 + 24+16); printChar(hexChar); let x = 0; loop x { - setCursor(x * 9 + 16, y * 9 + 24+16); + setCursorPosition(x * 9 + 16, y * 9 + 24+16); setTextColor(select(mode, x + y * 16, -9)); if y >= 2 | mode { printChar(select(mode, 0xa4, x + y * 16)); @@ -47,6 +39,6 @@ data 0 { "Default font: (press " i8(0xcc) " for palette)" i8(5, 0) } -data 0x20000 { +data USER_MEM { "Default palette: (press " i8(0xcc) " for font)" i8(5, 0) } \ No newline at end of file diff --git a/examples/curlywas/line.cwa b/examples/curlywas/line.cwa index e1240d6..2a80bdf 100644 --- a/examples/curlywas/line.cwa +++ b/examples/curlywas/line.cwa @@ -1,10 +1,4 @@ -import "env.memory" memory(4); - -import "env.cls" fn cls(i32); -import "env.time" fn time() -> f32; -import "env.line" fn line(f32, f32, f32, f32, i32); -import "env.sin" fn sin(f32) -> f32; -import "env.cos" fn cos(f32) -> f32; +include "microw8-api.cwa" export fn upd() { cls(0); diff --git a/examples/curlywas/microw8-api.cwa b/examples/curlywas/microw8-api.cwa new file mode 100644 index 0000000..5d50279 --- /dev/null +++ b/examples/curlywas/microw8-api.cwa @@ -0,0 +1,50 @@ +// MicroW8 APIs, to be `include`d in CurlyWas sources +import "env.memory" memory(4); + +import "env.sin" fn sin(f32) -> f32; +import "env.cos" fn cos(f32) -> f32; +import "env.tan" fn tan(f32) -> f32; +import "env.asin" fn asin(f32) -> f32; +import "env.acos" fn acos(f32) -> f32; +import "env.atan" fn atan(f32) -> f32; +import "env.atan2" fn atan2(f32, f32) -> f32; +import "env.pow" fn pow(f32, f32) -> f32; +import "env.log" fn log(f32) -> f32; +import "env.fmod" fn fmod(f32, f32) -> f32; +import "env.random" fn random() -> i32; +import "env.randomf" fn randomf() -> f32; +import "env.randomSeed" fn randomSeed(i32); +import "env.cls" fn cls(i32); +import "env.setPixel" fn setPixel(i32, i32, i32); +import "env.getPixel" fn getPixel(i32, i32) -> i32; +import "env.hline" fn hline(i32, i32, i32, i32); +import "env.rectangle" fn rectangle(f32, f32, f32, f32, i32); +import "env.circle" fn circle(f32, f32, f32, i32); +import "env.line" fn line(f32, f32, f32, f32, i32); +import "env.time" fn time() -> f32; +import "env.isButtonPressed" fn isButtonPressed(i32) -> i32; +import "env.isButtonTriggered" fn isButtonTriggered(i32) -> i32; +import "env.printChar" fn printChar(i32); +import "env.printString" fn printString(i32); +import "env.printInt" fn printInt(i32); +import "env.setTextColor" fn setTextColor(i32); +import "env.setBackgroundColor" fn setBackgroundColor(i32); +import "env.setCursorPosition" fn setCursorPosition(i32, i32); +import "env.rectangle_outline" fn rectangle_outline(f32, f32, f32, f32, i32); +import "env.circle_outline" fn circle_outline(f32, f32, f32, i32); +import "env.exp" fn exp(f32) -> f32; + +const TIME_MS = 0x40; +const GAMEPAD = 0x44; +const FRAMEBUFFER = 0x78; +const PALETTE = 0x13000; +const FONT = 0x13400; +const USER_MEM = 0x14000; +const BUTTON_UP = 0x0; +const BUTTON_DOWN = 0x1; +const BUTTON_LEFT = 0x2; +const BUTTON_RIGHT = 0x3; +const BUTTON_A = 0x4; +const BUTTON_B = 0x5; +const BUTTON_X = 0x6; +const BUTTON_Y = 0x7; diff --git a/examples/curlywas/skipahead.cwa b/examples/curlywas/skipahead.cwa index 215f161..8241dec 100644 --- a/examples/curlywas/skipahead.cwa +++ b/examples/curlywas/skipahead.cwa @@ -1,12 +1,4 @@ -import "env.memory" memory(4); - -import "env.rectangle" fn rect(f32, f32, f32, f32, i32); -import "env.circle" fn circle(f32, f32, f32, i32); -import "env.isButtonPressed" fn btn(i32) -> i32; -import "env.random" fn random() -> i32; -import "env.randomSeed" fn randomSeed(i32); -import "env.cls" fn cls(i32); -import "env.printInt" fn printInt(i32); +include "microw8-api.cwa" global mut pz: i32 = 4; global mut px: f32 = 2.0; @@ -19,7 +11,7 @@ export fn upd() { let inline zero = 0.0; let lazy control_speed = 0.03125; - s = s + 0.1875 - (f + control_speed) * btn(4 <| cls(4)) as f32; + s = s + 0.1875 - (f + control_speed) * isButtonPressed(4 <| cls(4)) as f32; f = f * 0.5625; printInt(pz); @@ -33,8 +25,8 @@ export fn upd() { let inline c = (z & 1) * -2; let inline yf = y as f32; - rect(rx, yf, rw, yf / 6 as f32, c + 1); - rect(rx, yf, rw, 1 as f32, c - 4); + rectangle(rx, yf, rw, yf / 6 as f32, c + 1); + rectangle(rx, yf, rw, 1 as f32, c - 4); if y == 180 & py > zero { if x > w | x < zero { @@ -51,7 +43,7 @@ export fn upd() { circle(160 as f32, 160 as f32 + py, 22 as f32, -28); circle((160 - 6) as f32, (160 - 6) as f32 + py, 6 as f32, -26); - px = px + (btn(3) - btn(2)) as f32 * control_speed; + px = px + (isButtonPressed(3) - isButtonPressed(2)) as f32 * control_speed; py = py + s; pz = pz + 1; } diff --git a/examples/curlywas/technotunnel.cwa b/examples/curlywas/technotunnel.cwa index 785b373..f391aa9 100644 --- a/examples/curlywas/technotunnel.cwa +++ b/examples/curlywas/technotunnel.cwa @@ -1,7 +1,4 @@ -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); +include "microw8-api.cwa" export fn upd() { let x: i32; diff --git a/examples/curlywas/trainride.cwa b/examples/curlywas/trainride.cwa index f0bf567..db1ea0b 100644 --- a/examples/curlywas/trainride.cwa +++ b/examples/curlywas/trainride.cwa @@ -1,7 +1,4 @@ -import "env.memory" memory(2); - -import "env.fmod" fn fmod(f32, f32) -> f32; -import "env.time" fn time() -> f32; +include "microw8-api.cwa" export fn upd() { let i: i32; diff --git a/examples/curlywas/tunnel.cwa b/examples/curlywas/tunnel.cwa index 33a85aa..e25a4b0 100644 --- a/examples/curlywas/tunnel.cwa +++ b/examples/curlywas/tunnel.cwa @@ -1,7 +1,4 @@ -import "env.memory" memory(4); - -import "env.atan2" fn atan2(f32, f32) -> f32; -import "env.time" fn time() -> f32; +include "microw8-api.cwa" export fn upd() { let i: i32; diff --git a/src/main.rs b/src/main.rs index 3a6e185..b4f86a7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -135,17 +135,15 @@ struct Config { } fn load_cart(filename: &Path, config: &Config) -> Result> { - let mut cart = vec![]; - File::open(filename)?.read_to_end(&mut cart)?; - - if cart[0] >= 10 { - let src = String::from_utf8(cart)?; - cart = if src.chars().find(|c| !c.is_whitespace()) == Some('(') { - wat::parse_str(src)? - } else { - curlywas::compile_str(&src, filename, curlywas::Options::default())? - }; - } + let mut cart = match SourceType::of_file(filename)? { + SourceType::Binary => { + let mut cart = vec![]; + File::open(filename)?.read_to_end(&mut cart)?; + cart + } + SourceType::Wat => wat::parse_file(filename)?, + SourceType::CurlyWas => curlywas::compile_file(filename, curlywas::Options::default())?, + }; if let Some(ref pack_config) = config.pack { cart = uw8_tool::pack(&cart, pack_config)?; @@ -159,6 +157,41 @@ fn load_cart(filename: &Path, config: &Config) -> Result> { Ok(cart) } +enum SourceType { + Binary, + Wat, + CurlyWas, +} + +impl SourceType { + fn of_file(filename: &Path) -> Result { + if let Some(extension) = filename.extension() { + if extension == "uw8" || extension == "wasm" { + return Ok(SourceType::Binary); + } else if extension == "wat" || extension == "wast" { + return Ok(SourceType::Wat); + } else if extension == "cwa" { + return Ok(SourceType::CurlyWas); + } + } + + let mut cart = vec![]; + File::open(filename)?.read_to_end(&mut cart)?; + + let ty = if cart[0] < 10 { + SourceType::Binary + } else { + let src = String::from_utf8(cart)?; + if src.chars().find(|&c| !c.is_whitespace() && c != ';') == Some('(') { + SourceType::Wat + } else { + SourceType::CurlyWas + } + }; + Ok(ty) + } +} + #[cfg(any(feature = "native", feature = "browser"))] fn start_cart(filename: &Path, runtime: &mut dyn Runtime, config: &Config) -> Result<()> { let cart = load_cart(filename, config)?; diff --git a/uw8-tool/src/base_module.rs b/uw8-tool/src/base_module.rs index c8ac048..c9c042f 100644 --- a/uw8-tool/src/base_module.rs +++ b/uw8-tool/src/base_module.rs @@ -291,7 +291,7 @@ impl BaseModule { pub fn write_as_cwa>(&self, path: P) -> Result<()> { fn inner(mut file: File, base: &BaseModule) -> Result<()> { - writeln!(file, ";; MicroW8 APIs, to be `include`d in CurlyWas sources")?; + writeln!(file, "// MicroW8 APIs, to be `include`d in CurlyWas sources")?; writeln!(file, "import \"env.memory\" memory({});", base.memory)?; writeln!(file)?; for &(module, ref name, type_id) in &base.function_imports {