17 Commits

27 changed files with 260 additions and 67 deletions
+3 -3
View File
@@ -30,9 +30,9 @@ jobs:
run: sudo apt-get install -y libxkbcommon-dev libasound2-dev run: sudo apt-get install -y libxkbcommon-dev libasound2-dev
if: matrix.os == 'ubuntu-latest' if: matrix.os == 'ubuntu-latest'
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Cache build dirs - name: Cache build dirs
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: | path: |
~/.cargo/bin/ ~/.cargo/bin/
@@ -44,7 +44,7 @@ jobs:
- name: Build - name: Build
run: cargo build --release --verbose run: cargo build --release --verbose
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v3
with: with:
name: uw8-${{ matrix.build }} name: uw8-${{ matrix.build }}
path: target/release/${{ matrix.exe }} path: target/release/${{ matrix.exe }}
+3 -3
View File
@@ -8,12 +8,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: checkout - name: checkout
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: build_and_deploy - name: build_and_deploy
uses: shalzz/zola-deploy-action@v0.14.1 uses: shalzz/zola-deploy-action@70a101a14bbdeed13e7a42a9ed06b35c9e9e826e
env: env:
# Target branch # Target branch
PAGES_BRANCH: gh-pages PAGES_BRANCH: gh-pages
BUILD_DIR: site BUILD_DIR: site
# Provide personal access token # Provide personal access token
TOKEN: $GITHUB_ACTOR:${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Generated
+11 -2
View File
@@ -2069,6 +2069,15 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "notify-debouncer-mini"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e23e9fa24f094b143c1eb61f90ac6457de87be6987bc70746e0179f7dbc9007b"
dependencies = [
"notify",
]
[[package]] [[package]]
name = "num-complex" name = "num-complex"
version = "0.4.3" version = "0.4.3"
@@ -3374,7 +3383,7 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]] [[package]]
name = "uw8" name = "uw8"
version = "0.2.1" version = "0.2.2"
dependencies = [ dependencies = [
"ansi_term", "ansi_term",
"anyhow", "anyhow",
@@ -3382,7 +3391,7 @@ dependencies = [
"curlywas", "curlywas",
"env_logger", "env_logger",
"log", "log",
"notify", "notify-debouncer-mini",
"pico-args 0.5.0", "pico-args 0.5.0",
"rubato", "rubato",
"same-file", "same-file",
+2 -2
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "uw8" name = "uw8"
version = "0.2.1" version = "0.2.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"
env_logger = "0.10" env_logger = "0.10"
log = "0.4" log = "0.4"
uw8-window = { path = "uw8-window", optional = true } uw8-window = { path = "uw8-window", optional = true }
notify = "5" notify-debouncer-mini = { version = "0.2.1", default-features = false }
pico-args = "0.5" pico-args = "0.5"
curlywas = { git = "https://github.com/exoticorn/curlywas.git", rev = "0e7ea50" } curlywas = { git = "https://github.com/exoticorn/curlywas.git", rev = "0e7ea50" }
wat = "1" wat = "1"
+3 -3
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.2/microw8-0.1.2-linux.tgz) * [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.2/microw8-0.2.2-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.1.2/microw8-0.1.2-macos.tgz) * [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.2/microw8-0.2.2-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.1.2/microw8-0.1.2-windows.zip) * [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.2/microw8-0.2.2-windows.zip)
The download includes The download includes
+21
View File
@@ -0,0 +1,21 @@
include "../include/microw8-api.cwa"
const SPRITE = 0x20000;
export fn upd() {
cls(0);
let t = time();
let i: i32;
loop spriteLoop {
let inline x = sin(t * -1.3 + i as f32 / 8_f) * 180_f + 160_f;
let inline y = sin(t * 1.7 + i as f32 / 9_f) * 140_f + 120_f;
blitSprite(SPRITE, 16, x as i32, y as i32, 0x100);
branch_if (i +:= 1) < 200: spriteLoop;
}
}
start fn start() {
printChar('OO');
circle(8_f, 8_f, 6_f, 75);
grabSprite(SPRITE, 16, 0, 0, 0);
}
+4 -2
View File
@@ -30,11 +30,13 @@ import "env.printInt" fn printInt(i32);
import "env.setTextColor" fn setTextColor(i32); import "env.setTextColor" fn setTextColor(i32);
import "env.setBackgroundColor" fn setBackgroundColor(i32); import "env.setBackgroundColor" fn setBackgroundColor(i32);
import "env.setCursorPosition" fn setCursorPosition(i32, i32); import "env.setCursorPosition" fn setCursorPosition(i32, i32);
import "env.rectangle_outline" fn rectangle_outline(f32, f32, f32, f32, i32); import "env.rectangleOutline" fn rectangleOutline(f32, f32, f32, f32, i32);
import "env.circle_outline" fn circle_outline(f32, f32, f32, i32); import "env.circleOutline" fn circleOutline(f32, f32, f32, i32);
import "env.exp" fn exp(f32) -> f32; import "env.exp" fn exp(f32) -> f32;
import "env.playNote" fn playNote(i32, i32); import "env.playNote" fn playNote(i32, i32);
import "env.sndGes" fn sndGes(i32) -> f32; import "env.sndGes" fn sndGes(i32) -> f32;
import "env.blitSprite" fn blitSprite(i32, i32, i32, i32, i32);
import "env.grabSprite" fn grabSprite(i32, i32, i32, i32, i32);
const TIME_MS = 0x40; const TIME_MS = 0x40;
const GAMEPAD = 0x44; const GAMEPAD = 0x44;
+4 -2
View File
@@ -30,11 +30,13 @@
(import "env" "setTextColor" (func $setTextColor (param i32))) (import "env" "setTextColor" (func $setTextColor (param i32)))
(import "env" "setBackgroundColor" (func $setBackgroundColor (param i32))) (import "env" "setBackgroundColor" (func $setBackgroundColor (param i32)))
(import "env" "setCursorPosition" (func $setCursorPosition (param i32) (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" "rectangleOutline" (func $rectangleOutline (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" "circleOutline" (func $circleOutline (param f32) (param f32) (param f32) (param i32)))
(import "env" "exp" (func $exp (param f32) (result f32))) (import "env" "exp" (func $exp (param f32) (result f32)))
(import "env" "playNote" (func $playNote (param i32) (param i32))) (import "env" "playNote" (func $playNote (param i32) (param i32)))
(import "env" "sndGes" (func $sndGes (param i32) (result f32))) (import "env" "sndGes" (func $sndGes (param i32) (result f32)))
(import "env" "blitSprite" (func $blitSprite (param i32) (param i32) (param i32) (param i32) (param i32)))
(import "env" "grabSprite" (func $grabSprite (param i32) (param i32) (param i32) (param i32) (param i32)))
;; to use defines, include this file with a preprocessor ;; to use defines, include this file with a preprocessor
;; like gpp (https://logological.org/gpp). ;; like gpp (https://logological.org/gpp).
Binary file not shown.
Binary file not shown.
+88 -2
View File
@@ -171,7 +171,7 @@ export fn rectangle(x: f32, y: f32, w: f32, h: f32, col: i32) {
} }
} }
export fn rectangle_outline(x: f32, y: f32, w: f32, h: f32, col: i32) { export fn rectangleOutline(x: f32, y: f32, w: f32, h: f32, col: i32) {
let xl = nearest(x) as i32; let xl = nearest(x) as i32;
let xr = nearest(x + w) as i32; let xr = nearest(x + w) as i32;
let yt = nearest(y) as i32; let yt = nearest(y) as i32;
@@ -212,7 +212,7 @@ export fn circle(cx: f32, cy: f32, radius: f32, col: i32) {
} }
} }
export fn circle_outline(cx: f32, cy: f32, radius: f32, col: i32) { export fn circleOutline(cx: f32, cy: f32, radius: f32, col: i32) {
let prev_w: f32; let prev_w: f32;
let y = clamp(nearest(cy - radius) as i32, -1, 241); let y = clamp(nearest(cy - radius) as i32, -1, 241);
let maxY = clamp(nearest(cy + radius) as i32, -1, 241); let maxY = clamp(nearest(cy + radius) as i32, -1, 241);
@@ -352,6 +352,92 @@ export fn line(x1: f32, y1: f32, x2: f32, y2: f32, col: i32) {
setPixel(i32.trunc_sat_f32_s(x1 + f * dx), i32.trunc_sat_f32_s(y1 + f * dy), col); setPixel(i32.trunc_sat_f32_s(x1 + f * dx), i32.trunc_sat_f32_s(y1 + f * dy), col);
} }
export fn blitSprite(sprite: i32, size: i32, x: i32, y: i32, control: i32) {
let lazy width = size & 65535;
let lazy height = select(size >> 16, size >> 16, width);
let lazy x0 = select(x < 0, -x, 0);
let lazy x1 = select(x + width > 320, 320 - x, width);
let lazy y0 = select(y < 0, -y, 0);
let lazy y1 = select(y + height > 240, 240 - y, height);
let lazy numRows = y1 - y0;
let lazy numCols = x1 - x0;
if numRows <= 0 | numCols <= 0 {
return;
}
let trans = (control & 511) - 256;
let lazy flip_x = 1 - ((control >> 8) & 2);
let lazy flip_y = 1 - ((control >> 9) & 2);
if flip_x < 0 {
sprite += width - 1;
}
if flip_y < 0 {
sprite += (height - 1) * width;
}
let spriteRow = sprite + x0 * flip_x + y0 * flip_y * width;
let screenRow = x + x0 + (y + y0) * 320;
loop yloop {
let lx = 0;
loop xloop {
let lazy col = (spriteRow + lx * flip_x)?0;
if col != trans {
(screenRow + lx)?120 = col;
}
branch_if (lx +:= 1) < numCols: xloop;
}
spriteRow += width * flip_y;
screenRow += 320;
branch_if numRows -:= 1: yloop;
}
}
export fn grabSprite(sprite: i32, size: i32, x: i32, y: i32, control: i32) {
let lazy width = size & 65535;
let lazy height = select(size >> 16, size >> 16, width);
let lazy x0 = select(x < 0, -x, 0);
let lazy x1 = select(x + width > 320, 320 - x, width);
let lazy y0 = select(y < 0, -y, 0);
let lazy y1 = select(y + height > 240, 240 - y, height);
let lazy numRows = y1 - y0;
let lazy numCols = x1 - x0;
if numRows <= 0 | numCols <= 0 {
return;
}
let trans = (control & 511) - 256;
let lazy flip_x = 1 - ((control >> 8) & 2);
let lazy flip_y = 1 - ((control >> 9) & 2);
if flip_x < 0 {
sprite += width - 1;
}
if flip_y < 0 {
sprite += (height - 1) * width;
}
let spriteRow = sprite + x0 * flip_x + y0 * flip_y * width;
let screenRow = x + x0 + (y + y0) * 320;
loop yloop {
let lx = 0;
loop xloop {
let lazy col = (screenRow + lx)?120;
if col != trans {
(spriteRow + lx * flip_x)?0 = col;
}
branch_if (lx +:= 1) < numCols: xloop;
}
spriteRow += width * flip_y;
screenRow += 320;
branch_if numRows -:= 1: yloop;
}
}
////////// //////////
// TEXT // // TEXT //
////////// //////////
+16
View File
@@ -14,6 +14,8 @@ The initial motivation behind MicroW8 was to explore whether there was a way to
* Memory: 256KB * Memory: 256KB
* Gamepad input (D-Pad + 4 Buttons) * Gamepad input (D-Pad + 4 Buttons)
For detailed [documentation see here](docs).
## Examples ## Examples
* [Skip Ahead](v0.2.0#AgVfq24KI2Ok2o8qVtPYj27fSuGnfeSKgbOkIOsaEQMov8TDYQ6UjdjwkZrYcM1i9alo4/+Bhm1PRFEa0YHJlJAk/PGoc2K41rejv9ZSqJqIHNjr7cappqhOR2jT+jk+0b0+U6hO+geRCTP2aufWs7L+f/Z27NFY8LKlqPSv+C6Rd6+ohoKi6sYl5Kcrlf1cyTinV7jTTnmbcXWVDBA5rRKxAGMUTDS8rHxqSztRITOaQVP1pSdYgi/BDdOJOxSOIkeaId84S+Ycls5na7EgwSfVIpgqF+tcfkUecb8t2mQrXA7pyKrh/wzHn5N6Oe5aOgmzY2YpTIct) (249 bytes): A port of my [TIC-80 256byte game](http://tic80.com/play?cart=1735) from LoveByte'21, now with sound * [Skip Ahead](v0.2.0#AgVfq24KI2Ok2o8qVtPYj27fSuGnfeSKgbOkIOsaEQMov8TDYQ6UjdjwkZrYcM1i9alo4/+Bhm1PRFEa0YHJlJAk/PGoc2K41rejv9ZSqJqIHNjr7cappqhOR2jT+jk+0b0+U6hO+geRCTP2aufWs7L+f/Z27NFY8LKlqPSv+C6Rd6+ohoKi6sYl5Kcrlf1cyTinV7jTTnmbcXWVDBA5rRKxAGMUTDS8rHxqSztRITOaQVP1pSdYgi/BDdOJOxSOIkeaId84S+Ycls5na7EgwSfVIpgqF+tcfkUecb8t2mQrXA7pyKrh/wzHn5N6Oe5aOgmzY2YpTIct) (249 bytes): A port of my [TIC-80 256byte game](http://tic80.com/play?cart=1735) from LoveByte'21, now with sound
* [Fireworks](v0.2.0#AgwvgP+M59snqjl4CMKw5sqm1Zw9yJCbSviMjeLUdHus2a3yl/a99+uiBeqZgP/2jqSjrLjRk73COMM6OSLpsxK8ugT1kuk/q4hQUqqPpGozHoa0laulzGGcahzdfdJsYaK1sIdeIYS9M5PnJx/Wk9H+PvWEPy2Zvv7I6IW7Fg==) (127 bytes): Some fireworks to welcome 2022. * [Fireworks](v0.2.0#AgwvgP+M59snqjl4CMKw5sqm1Zw9yJCbSviMjeLUdHus2a3yl/a99+uiBeqZgP/2jqSjrLjRk73COMM6OSLpsxK8ugT1kuk/q4hQUqqPpGozHoa0laulzGGcahzdfdJsYaK1sIdeIYS9M5PnJx/Wk9H+PvWEPy2Zvv7I6IW7Fg==) (127 bytes): Some fireworks to welcome 2022.
@@ -29,6 +31,20 @@ Examplers for older versions:
## Versions ## Versions
### v0.2.2
* [Web runtime](v0.2.2)
* [Linux](https://github.com/exoticorn/microw8/releases/download/v0.2.2/microw8-0.2.2-linux.tgz)
* [MacOS](https://github.com/exoticorn/microw8/releases/download/v0.2.2/microw8-0.2.2-macos.tgz)
* [Windows](https://github.com/exoticorn/microw8/releases/download/v0.2.2/microw8-0.2.2-windows.zip)
Changes:
* call `start` function after loading cart if the cart exports one
* fix `sndGes` having the wrong name and not being included in the auto imports
* fix control codes 4-6 (change text output mode) being invoked when used as parameters in other control sequences
* only open browser window once a cart was compiled sucessfully when running with `-b`
### v0.2.1 ### v0.2.1
* [Web runtime](v0.2.1) * [Web runtime](v0.2.1)
+20 -2
View File
@@ -12,6 +12,9 @@ at offset 120 in memory with the 32bpp palette located at 0x13000.
The memory has to be imported as `env` `memory` and has a maximum size of 256kb (4 pages). The memory has to be imported as `env` `memory` and has a maximum size of 256kb (4 pages).
If the module exports a function called `start`, it will be called once after the module is
loaded.
# Memory map # Memory map
``` ```
@@ -143,13 +146,13 @@ Fills the circle at `cx, cy` and with `radius` with the given color index.
(Sets all pixels where the pixel center lies inside the circle.) (Sets all pixels where the pixel center lies inside the circle.)
### fn rectangle_outline(x: f32, y: f32, w: f32, h: f32, color: i32) ### fn rectangleOutline(x: f32, y: f32, w: f32, h: f32, color: i32)
Draws a one pixel outline on the inside of the given rectangle. Draws a one pixel outline on the inside of the given rectangle.
(Draws the outermost pixels that are still inside the rectangle area.) (Draws the outermost pixels that are still inside the rectangle area.)
### fn circle_outline(cx: f32, cy: f32, radius: f32, color: i32) ### fn circleOutline(cx: f32, cy: f32, radius: f32, color: i32)
Draws a one pixel outline on the inside of the given circle. Draws a one pixel outline on the inside of the given circle.
@@ -159,6 +162,21 @@ Draws a one pixel outline on the inside of the given circle.
Draws a line from `x1,y1` to `x2,y2` in the given color index. Draws a line from `x1,y1` to `x2,y2` in the given color index.
### fn blitSprite(spriteData: i32, size: i32, x: i32, y: i32, control: i32)
Copies the pixel data at `spriteData` onto the screen at `x`, `y`. The size of the sprite is passed as `width | (height << 16)`.
If the height is given as 0, the sprite is is treated as square (width x width).
The control parameter controls masking and flipping of the sprite:
* bits 0-7: color mask index
* bit 8: switch on masked blit (pixel with color mask index are treated as transparent)
* bit 9: flip sprite x
* bit 10: flip sprite y
### fn grabSprite(spriteData: i32, size: i32, x: i32, y: i32, control: i32)
Copies the pixel data on the screen at `x`, `y` to `spriteData`. Parameters are exactly the same as `blitSprite`.
## Input ## Input
MicroW8 provides input from a gamepad with one D-Pad and 4 buttons, or a keyboard emulation thereof. MicroW8 provides input from a gamepad with one D-Pad and 4 buttons, or a keyboard emulation thereof.
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -4,7 +4,7 @@
<section> <section>
<h1 class="text-center heading-text">A WebAssembly based fantasy console</h1> <h1 class="text-center heading-text">A WebAssembly based fantasy console</h1>
</section> </section>
<a href="v0.2.1"> <a href="v0.2.2">
<img class="demonstration-gif" style="width:640px;height:480px;image-rendering:pixelated" src="img/technotunnel.png"></img> <img class="demonstration-gif" style="width:640px;height:480px;image-rendering:pixelated" src="img/technotunnel.png"></img>
</a> </a>
</div> </div>
+27 -16
View File
@@ -1,23 +1,35 @@
use anyhow::{anyhow, bail, Result}; use anyhow::{anyhow, bail, Result};
use notify::{Event, EventKind, RecommendedWatcher, Watcher}; use notify_debouncer_mini::{
use std::{collections::BTreeSet, path::PathBuf, sync::mpsc}; new_debouncer,
notify::{self, RecommendedWatcher},
DebouncedEvent, DebouncedEventKind, Debouncer,
};
use std::{collections::BTreeSet, path::PathBuf, sync::mpsc, time::Duration};
pub struct FileWatcher { pub struct FileWatcher {
watcher: RecommendedWatcher, debouncer: Debouncer<RecommendedWatcher>,
watched_files: BTreeSet<PathBuf>, watched_files: BTreeSet<PathBuf>,
directories: BTreeSet<PathBuf>, directories: BTreeSet<PathBuf>,
rx: mpsc::Receiver<Event>, rx: mpsc::Receiver<DebouncedEvent>,
} }
impl FileWatcher { impl FileWatcher {
pub fn new() -> Result<FileWatcher> { pub fn new() -> Result<FileWatcher> {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let watcher = notify::recommended_watcher(move |res| match res { let debouncer = new_debouncer(Duration::from_millis(100), None, move |res| match res {
Ok(event) => _ = tx.send(event), Ok(events) => {
Err(err) => eprintln!("Error watching for file changes: {err}"), for event in events {
let _ = tx.send(event);
}
}
Err(errs) => {
for err in errs {
eprintln!("Error watching for file changes: {err}");
}
}
})?; })?;
Ok(FileWatcher { Ok(FileWatcher {
watcher, debouncer,
watched_files: BTreeSet::new(), watched_files: BTreeSet::new(),
directories: BTreeSet::new(), directories: BTreeSet::new(),
rx, rx,
@@ -29,7 +41,8 @@ impl FileWatcher {
let parent = path.parent().ok_or_else(|| anyhow!("File has no parent"))?; let parent = path.parent().ok_or_else(|| anyhow!("File has no parent"))?;
if !self.directories.contains(parent) { if !self.directories.contains(parent) {
self.watcher self.debouncer
.watcher()
.watch(parent, notify::RecursiveMode::NonRecursive)?; .watch(parent, notify::RecursiveMode::NonRecursive)?;
self.directories.insert(parent.to_path_buf()); self.directories.insert(parent.to_path_buf());
} }
@@ -41,13 +54,11 @@ impl FileWatcher {
pub fn poll_changed_file(&self) -> Result<Option<PathBuf>> { pub fn poll_changed_file(&self) -> Result<Option<PathBuf>> {
match self.rx.try_recv() { match self.rx.try_recv() {
Ok(event) => match event.kind { Ok(event) => match event.kind {
EventKind::Create(_) | EventKind::Modify(_) => { DebouncedEventKind::Any => {
for path in event.paths { let handle = same_file::Handle::from_path(&event.path)?;
let handle = same_file::Handle::from_path(&path)?; for file in &self.watched_files {
for file in &self.watched_files { if handle == same_file::Handle::from_path(file)? {
if handle == same_file::Handle::from_path(file)? { return Ok(Some(event.path));
return Ok(Some(path));
}
} }
} }
} }
+1 -1
View File
File diff suppressed because one or more lines are too long
+4
View File
@@ -134,6 +134,10 @@ impl super::Runtime for MicroW8 {
let end_frame = platform_instance.get_typed_func::<(), ()>(&mut store, "endFrame")?; let end_frame = platform_instance.get_typed_func::<(), ()>(&mut store, "endFrame")?;
let update = instance.get_typed_func::<(), ()>(&mut store, "upd").ok(); let update = instance.get_typed_func::<(), ()>(&mut store, "upd").ok();
if let Some(start) = instance.get_typed_func::<(), ()>(&mut store, "start").ok() {
start.call(&mut store, ())?;
}
let (sound_tx, stream) = if self.disable_audio { let (sound_tx, stream) = if self.disable_audio {
(None, None) (None, None)
} else { } else {
+17 -9
View File
@@ -11,6 +11,7 @@ use warp::{http::Response, Filter};
pub struct RunWebServer { pub struct RunWebServer {
cart: Arc<Mutex<Vec<u8>>>, cart: Arc<Mutex<Vec<u8>>>,
tx: broadcast::Sender<()>, tx: broadcast::Sender<()>,
socket_addr: SocketAddr,
} }
impl RunWebServer { impl RunWebServer {
@@ -18,8 +19,13 @@ impl RunWebServer {
let cart = Arc::new(Mutex::new(Vec::new())); let cart = Arc::new(Mutex::new(Vec::new()));
let (tx, _) = broadcast::channel(1); let (tx, _) = broadcast::channel(1);
let socket_addr = "127.0.0.1:3030"
.parse::<SocketAddr>()
.expect("Failed to parse socket address");
let server_cart = cart.clone(); let server_cart = cart.clone();
let server_tx = tx.clone(); let server_tx = tx.clone();
let server_addr = socket_addr.clone();
thread::spawn(move || { thread::spawn(move || {
let rt = tokio::runtime::Builder::new_current_thread() let rt = tokio::runtime::Builder::new_current_thread()
.enable_io() .enable_io()
@@ -47,24 +53,26 @@ impl RunWebServer {
warp::sse::reply(warp::sse::keep_alive().stream(event_stream(&server_tx))) warp::sse::reply(warp::sse::keep_alive().stream(event_stream(&server_tx)))
}); });
let socket_addr = "127.0.0.1:3030" let server_future = warp::serve(html.or(cart).or(events)).bind(server_addr);
.parse::<SocketAddr>()
.expect("Failed to parse socket address");
let server_future = warp::serve(html.or(cart).or(events)).bind(socket_addr);
println!("Point browser at http://{}", socket_addr);
let _ignore_result = webbrowser::open(&format!("http://{}", socket_addr));
server_future.await server_future.await
}); });
}); });
RunWebServer { cart, tx } RunWebServer {
cart,
tx,
socket_addr,
}
} }
} }
impl super::Runtime for RunWebServer { impl super::Runtime for RunWebServer {
fn load(&mut self, module_data: &[u8]) -> Result<()> { fn load(&mut self, module_data: &[u8]) -> Result<()> {
if let Ok(mut lock) = self.cart.lock() { if let Ok(mut lock) = self.cart.lock() {
if lock.is_empty() && !module_data.is_empty() {
println!("Point browser at http://{}", self.socket_addr);
let _ignore_result = webbrowser::open(&format!("http://{}", self.socket_addr));
}
lock.clear(); lock.clear();
lock.extend_from_slice(module_data); lock.extend_from_slice(module_data);
} }
@@ -86,4 +94,4 @@ impl Default for RunWebServer {
fn default() -> RunWebServer { fn default() -> RunWebServer {
RunWebServer::new() RunWebServer::new()
} }
} }
-13
View File
@@ -1,13 +0,0 @@
import "env.memory" memory(4);
import "env.printString" fn print(i32);
export fn upd() {
}
start fn start() {
print(0);
}
data 0 {
"Press " i8(0xe0) " and " i8(0xe1) " to adjust, " i8(0xcc) " to commit." i8(0)
}
BIN
View File
Binary file not shown.
+3 -2
View File
@@ -2,17 +2,18 @@ import "env.memory" memory(4);
import "env.pow" fn pow(f32, f32) -> f32; import "env.pow" fn pow(f32, f32) -> f32;
import "env.sin" fn sin(f32) -> f32; import "env.sin" fn sin(f32) -> f32;
import "env.cls" fn cls(i32); import "env.cls" fn cls(i32);
import "env.exp" fn exp(f32) -> f32;
import "env.rectangle" fn rectangle(f32, f32, f32, f32, i32); import "env.rectangle" fn rectangle(f32, f32, f32, f32, i32);
include "../platform/src/ges.cwa" include "../platform/src/ges.cwa"
export fn snd(t: i32) -> f32 { export fn snd(t: i32) -> f32 {
gesSnd(t) sndGes(t)
} }
export fn upd() { export fn upd() {
80?0 = 32!32 / 200 & 2 | 0x41; 80?0 = 32!32 / 200 & 2 | 0x41;
80?3 = (32!32 / 400)%7*12/7 + 40; 80?3 = (32!32 / 400)%8*12/7 + 40;
let pulse = (32!32 * 256 / 2000) & 511; let pulse = (32!32 * 256 / 2000) & 511;
if pulse >= 256 { if pulse >= 256 {
pulse = 511 - pulse; pulse = 511 - pulse;
+5
View File
@@ -0,0 +1,5 @@
include "../examples/include/microw8-api.cwa"
export fn start() {
printChar('Test');
}
+17 -2
View File
@@ -152,14 +152,14 @@ impl BaseModule {
add_function( add_function(
&mut functions, &mut functions,
&type_map, &type_map,
"rectangle_outline", "rectangleOutline",
&[F32, F32, F32, F32, I32], &[F32, F32, F32, F32, I32],
None, None,
); );
add_function( add_function(
&mut functions, &mut functions,
&type_map, &type_map,
"circle_outline", "circleOutline",
&[F32, F32, F32, I32], &[F32, F32, F32, I32],
None, None,
); );
@@ -169,6 +169,21 @@ impl BaseModule {
add_function(&mut functions, &type_map, "playNote", &[I32, I32], None); add_function(&mut functions, &type_map, "playNote", &[I32, I32], None);
add_function(&mut functions, &type_map, "sndGes", &[I32], Some(F32)); add_function(&mut functions, &type_map, "sndGes", &[I32], Some(F32));
add_function(
&mut functions,
&type_map,
"blitSprite",
&[I32, I32, I32, I32, I32],
None,
);
add_function(
&mut functions,
&type_map,
"grabSprite",
&[I32, I32, I32, I32, I32],
None,
);
for i in functions.len()..64 { for i in functions.len()..64 {
add_function( add_function(
&mut functions, &mut functions,
+4 -1
View File
@@ -767,7 +767,10 @@ fn remap_function(
De::End => En::End, De::End => En::End,
De::Br { relative_depth } => En::Br(relative_depth), De::Br { relative_depth } => En::Br(relative_depth),
De::BrIf { relative_depth } => En::BrIf(relative_depth), De::BrIf { relative_depth } => En::BrIf(relative_depth),
De::BrTable { .. } => todo!(), De::BrTable { targets } => En::BrTable(
targets.targets().collect::<Result<Vec<u32>, _>>()?.into(),
targets.default(),
),
De::Return => En::Return, De::Return => En::Return,
De::Call { function_index } => En::Call( De::Call { function_index } => En::Call(
*function_map *function_map
+1 -1
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.2.1 <a href="https://exoticorn.github.io/microw8">MicroW8</a> 0.2.2
</div> </div>
<div id="centered"> <div id="centered">
<canvas class="screen" id="screen" width="320" height="240"> <canvas class="screen" id="screen" width="320" height="240">
+4
View File
@@ -263,6 +263,10 @@ export default function MicroW8(screen, config = {}) {
window.addEventListener('blur', () => updateVisibility(false), { signal: abortController.signal }); window.addEventListener('blur', () => updateVisibility(false), { signal: abortController.signal });
updateVisibility(document.hasFocus()); updateVisibility(document.hasFocus());
if (instance.exports.start) {
instance.exports.start();
}
function mainloop() { function mainloop() {
if (!keepRunning) { if (!keepRunning) {
return; return;