22 Commits

Author SHA1 Message Date
BjoernSchilberg
9c0200155f Merge 937ccf60c9 into 09e4fcbf14 2023-08-12 00:25:07 +02:00
09e4fcbf14 add --scale option 2023-08-11 23:52:19 +02:00
dbeb242fb2 add support for br_table instruction when packing cart 2023-03-20 23:08:42 +01:00
BjoernSchilberg
937ccf60c9 Added a tinygo example. 2023-02-12 22:24:16 +01:00
4fe4bce0ad token env var has changed 2023-01-31 00:14:25 +01:00
fe86153562 use fixed version of zola-deploy-action 2023-01-31 00:01:07 +01:00
c9dadaca2e try add safe.directory 2023-01-30 09:48:57 +01:00
5dc3e281ce and again 2023-01-30 09:45:28 +01:00
ce3afb821f another attempt changing the owner to fix permission issue 2023-01-30 09:43:54 +01:00
2652a351ad remove chown again 2023-01-30 09:38:57 +01:00
9109722409 fix main.yml 2023-01-30 09:37:12 +01:00
f861c262a1 update ci actions, hopefully fix permission error 2023-01-30 09:15:09 +01:00
bbfb5eba49 add back event debouncing in file watcher 2023-01-30 00:09:25 +01:00
9e19ff1761 prepare for 0.2.2 release 2023-01-28 12:47:16 +01:00
5d85aeac09 call an exported start function if it exists 2023-01-28 12:31:16 +01:00
30eb953d5d remove test code that was accidentally committed 2023-01-28 11:37:05 +01:00
abdf780533 only open browser once cart has been compiled succesfully 2023-01-28 11:33:49 +01:00
fc05a54e2c fix control codes 4-6 as parameters to other control codes 2023-01-28 10:58:28 +01:00
b33099c828 update more dependencies 2023-01-28 02:11:25 +01:00
d478d3ad49 enable timeapi in winapi crate 2023-01-27 00:13:32 +01:00
502852e59a update uw8-window dependencies 2023-01-26 23:40:54 +01:00
5efa8b3465 first batch of dependency updates 2023-01-26 22:45:34 +01:00
36 changed files with 2571 additions and 1572 deletions

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 }}

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 }}

2360
Cargo.lock generated

File diff suppressed because it is too large Load Diff

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
@@ -11,21 +11,21 @@ native = ["wasmtime", "uw8-window", "cpal", "rubato" ]
browser = ["warp", "tokio", "tokio-stream", "webbrowser"] browser = ["warp", "tokio", "tokio-stream", "webbrowser"]
[dependencies] [dependencies]
wasmtime = { version = "0.37.0", optional = true } wasmtime = { version = "5.0.0", optional = true }
anyhow = "1" anyhow = "1"
env_logger = "0.9" 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 = "4" notify-debouncer-mini = { version = "0.2.1", default-features = false }
pico-args = "0.4" 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"
uw8-tool = { path = "uw8-tool" } uw8-tool = { path = "uw8-tool" }
same-file = "1" same-file = "1"
warp = { version = "0.3.2", optional = true } warp = { version = "0.3.3", optional = true }
tokio = { version = "1.17.0", features = ["sync", "rt"], optional = true } tokio = { version = "1.24.0", features = ["sync", "rt"], optional = true }
tokio-stream = { version = "0.1.8", features = ["sync"], optional = true } tokio-stream = { version = "0.1.11", features = ["sync"], optional = true }
webbrowser = { version = "0.6.0", optional = true } webbrowser = { version = "0.8.6", optional = true }
ansi_term = "0.12.1" ansi_term = "0.12.1"
cpal = { version = "0.14.1", optional = true } cpal = { version = "0.14.2", optional = true }
rubato = { version = "0.11.0", optional = true } rubato = { version = "0.12.0", optional = true }

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

6
examples/tinygo/build.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/bash
tinygo build -o cart.wasm -target target.json ./main.go
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

38
examples/tinygo/main.go Normal file
View File

@@ -0,0 +1,38 @@
package main
import (
"math"
"unsafe"
)
//go:wasm-module env
//export atan2
func atan2(x, y float32) float32
//go:wasm-module env
//export time
func time() float32
func sqrt(v float32) float32 {
return float32(math.Sqrt(float64(v)))
}
var FRAMEBUFFER = (*[320 * 240]byte)(unsafe.Pointer(uintptr(120)))
//export upd
func upd() {
var i int
for i < 320*240 {
t := time() * 63.0
x := float32(i%320 - 160)
y := float32(i/320 - 120)
d := float32(40000.0) / sqrt(x*x+y*y)
u := atan2(x, y) * 512.0 / 3.141
c := uint8((int(d+t*2.0) ^ int(u+t)) >> 4)
FRAMEBUFFER[i] = c
i++
}
}
func main() {
}

View File

@@ -0,0 +1,23 @@
{
"llvm-target": "wasm32--wasi",
"build-tags": [ "tinygo.wasm" ],
"goos": "js",
"goarch": "wasm",
"linker": "wasm-ld",
"libc": "wasi-libc",
"cflags": [
"--target=wasm32--wasi",
"--sysroot={root}/lib/wasi-libc/sysroot",
"-Oz"
],
"ldflags": [
"--no-entry",
"--export-all",
"--import-memory",
"--initial-memory=262144",
"--global-base=81920",
"-zstack-size=4096",
"--strip-all"
],
"wasm-abi": "js"
}

186
platform/Cargo.lock generated
View File

@@ -110,9 +110,9 @@ dependencies = [
[[package]] [[package]]
name = "crc32fast" name = "crc32fast"
version = "1.3.0" version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836" checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
] ]
@@ -151,32 +151,39 @@ dependencies = [
"anyhow", "anyhow",
"ariadne", "ariadne",
"chumsky", "chumsky",
"pico-args", "pico-args 0.4.2",
"wasm-encoder 0.10.0", "wasm-encoder 0.10.0",
"wasmparser 0.83.0", "wasmparser 0.83.0",
] ]
[[package]] [[package]]
name = "fallible_collections" name = "fallible_collections"
version = "0.4.4" version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52db5973b6a19247baf19b30f41c23a1bfffc2e9ce0a5db2f60e3cd5dc8895f7" checksum = "3f57ccc32870366ae684be48b32a1a2e196f98a42a9b4361fe77e13fd4a34755"
dependencies = [ dependencies = [
"hashbrown", "hashbrown",
] ]
[[package]] [[package]]
name = "flate2" name = "flate2"
version = "1.0.22" version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
dependencies = [ dependencies = [
"cfg-if",
"crc32fast", "crc32fast",
"libc",
"miniz_oxide", "miniz_oxide",
] ]
[[package]]
name = "form_urlencoded"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
dependencies = [
"percent-encoding",
]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.3" version = "0.2.3"
@@ -190,9 +197,9 @@ dependencies = [
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.11.2" version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [ dependencies = [
"ahash 0.7.6", "ahash 0.7.6",
] ]
@@ -212,6 +219,26 @@ version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
[[package]]
name = "idna"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "indexmap"
version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@@ -225,17 +252,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
[[package]] [[package]]
name = "libc" name = "lexopt"
version = "0.2.112" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" checksum = "478ee9e62aaeaf5b140bd4138753d1f109765488581444218d3ddda43234f3e8"
[[package]]
name = "libc"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]] [[package]]
name = "lodepng" name = "lodepng"
version = "3.4.7" version = "3.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24844d5c0b922ddd52fb5bf0964a4c7f8e799a946ec01bb463771eb04fc1a323" checksum = "f0ad39f75bbaa4b10bb6f2316543632a8046a5bcf9c785488d79720b21f044f8"
dependencies = [ dependencies = [
"crc32fast",
"fallible_collections", "fallible_collections",
"flate2", "flate2",
"libc", "libc",
@@ -253,12 +287,11 @@ dependencies = [
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.4.4" version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [ dependencies = [
"adler", "adler",
"autocfg",
] ]
[[package]] [[package]]
@@ -288,12 +321,24 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "percent-encoding"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]] [[package]]
name = "pico-args" name = "pico-args"
version = "0.4.2" version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468"
[[package]]
name = "pico-args"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
[[package]] [[package]]
name = "platform" name = "platform"
version = "0.1.0" version = "0.1.0"
@@ -330,9 +375,9 @@ dependencies = [
[[package]] [[package]]
name = "rgb" name = "rgb"
version = "0.8.31" version = "0.8.34"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a374af9a0e5fdcdd98c1c7b64f05004f9ea2555b6c75f211daa81268a3c50f1" checksum = "3603b7d71ca82644f79b5a06d1220e9a58ede60bd32255f698cb1af8838b8db3"
dependencies = [ dependencies = [
"bytemuck", "bytemuck",
] ]
@@ -357,6 +402,26 @@ dependencies = [
"unicode-xid", "unicode-xid",
] ]
[[package]]
name = "thiserror"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "time" name = "time"
version = "0.1.43" version = "0.1.43"
@@ -376,6 +441,36 @@ dependencies = [
"crunchy", "crunchy",
] ]
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
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 = "unicode-bidi"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"
[[package]]
name = "unicode-normalization"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [
"tinyvec",
]
[[package]] [[package]]
name = "unicode-segmentation" name = "unicode-segmentation"
version = "1.9.0" version = "1.9.0"
@@ -390,13 +485,24 @@ checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]] [[package]]
name = "upkr" name = "upkr"
version = "0.1.0" version = "0.2.1"
source = "git+https://github.com/exoticorn/upkr.git?rev=d93aec186c9fb91d962c488682a2db125c61306c#d93aec186c9fb91d962c488682a2db125c61306c" source = "git+https://github.com/exoticorn/upkr.git?rev=080db40d0088bbee2bdf3c5c75288ac7853d6b7a#080db40d0088bbee2bdf3c5c75288ac7853d6b7a"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cdivsufsort", "cdivsufsort",
"pbr", "lexopt",
"pico-args", "thiserror",
]
[[package]]
name = "url"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
] ]
[[package]] [[package]]
@@ -405,11 +511,11 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"pbr", "pbr",
"pico-args", "pico-args 0.5.0",
"upkr", "upkr",
"walrus", "walrus",
"wasm-encoder 0.8.0", "wasm-encoder 0.22.0",
"wasmparser 0.81.0", "wasmparser 0.99.0",
] ]
[[package]] [[package]]
@@ -452,18 +558,18 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]] [[package]]
name = "wasm-encoder" name = "wasm-encoder"
version = "0.8.0" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db0c351632e46cc06a58a696a6c11e4cf90cad4b9f8f07a0b59128d616c29bb0" checksum = "aa9d9bf45fc46f71c407837c9b30b1e874197f2dc357588430b21e5017d290ab"
dependencies = [ dependencies = [
"leb128", "leb128",
] ]
[[package]] [[package]]
name = "wasm-encoder" name = "wasm-encoder"
version = "0.10.0" version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa9d9bf45fc46f71c407837c9b30b1e874197f2dc357588430b21e5017d290ab" checksum = "ef126be0e14bdf355ac1a8b41afc89195289e5c7179f80118e3abddb472f0810"
dependencies = [ dependencies = [
"leb128", "leb128",
] ]
@@ -474,18 +580,22 @@ version = "0.77.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b35c86d22e720a07d954ebbed772d01180501afe7d03d464f413bb5f8914a8d6" checksum = "b35c86d22e720a07d954ebbed772d01180501afe7d03d464f413bb5f8914a8d6"
[[package]]
name = "wasmparser"
version = "0.81.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98930446519f63d00a836efdc22f67766ceae8dbcc1571379f2bcabc6b2b9abc"
[[package]] [[package]]
name = "wasmparser" name = "wasmparser"
version = "0.83.0" version = "0.83.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a" checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a"
[[package]]
name = "wasmparser"
version = "0.99.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ef3b717afc67f848f412d4f02c127dd3e35a0eecd58c684580414df4fde01d3"
dependencies = [
"indexmap",
"url",
]
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"

View File

@@ -9,4 +9,4 @@ edition = "2021"
curlywas = { git="https://github.com/exoticorn/curlywas.git", rev="0e7ea50" } curlywas = { git="https://github.com/exoticorn/curlywas.git", rev="0e7ea50" }
uw8-tool = { path="../uw8-tool" } uw8-tool = { path="../uw8-tool" }
anyhow = "1" anyhow = "1"
lodepng = "3.4" lodepng = "3.7.2"

Binary file not shown.

View File

@@ -372,16 +372,7 @@ export fn printChar(char: i32) {
global mut controlCodeLength = 0; global mut controlCodeLength = 0;
fn printSingleChar(char: i32) { fn printSingleChar(char: i32) {
if char >= 4 & char <= 6 { if outputChannel >= 2 & (char < 4 | char > 6) {
outputChannel = char - 4;
if !outputChannel {
textCursorX = 0;
textCursorY = 0;
}
return;
}
if outputChannel >= 2 {
logChar(char); logChar(char);
return; return;
} }
@@ -399,6 +390,15 @@ fn printSingleChar(char: i32) {
return; return;
} }
if char >= 4 & char <= 6 {
outputChannel = char - 4;
if !outputChannel {
textCursorX = 0;
textCursorY = 0;
}
return;
}
if char == 7 { if char == 7 {
80?0 = 80?0 ^ 2; 80?0 = 80?0 ^ 2;
return; return;

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)

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
``` ```

File diff suppressed because one or more lines are too long

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>

View File

@@ -1,9 +1,13 @@
use anyhow::{anyhow, bail, Result}; use anyhow::{anyhow, bail, Result};
use notify::{DebouncedEvent, RecommendedWatcher, Watcher}; use notify_debouncer_mini::{
new_debouncer,
notify::{self, RecommendedWatcher},
DebouncedEvent, DebouncedEventKind, Debouncer,
};
use std::{collections::BTreeSet, path::PathBuf, sync::mpsc, time::Duration}; 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<DebouncedEvent>, rx: mpsc::Receiver<DebouncedEvent>,
@@ -12,9 +16,20 @@ pub struct FileWatcher {
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::watcher(tx, Duration::from_millis(100))?; let debouncer = new_debouncer(Duration::from_millis(100), None, move |res| match res {
Ok(events) => {
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,
@@ -26,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());
} }
@@ -36,16 +52,18 @@ impl FileWatcher {
} }
pub fn poll_changed_file(&self) -> Result<Option<PathBuf>> { pub fn poll_changed_file(&self) -> Result<Option<PathBuf>> {
let event = self.rx.try_recv(); match self.rx.try_recv() {
match event { Ok(event) => match event.kind {
Ok(DebouncedEvent::Create(path) | DebouncedEvent::Write(path)) => { DebouncedEventKind::Any => {
let handle = same_file::Handle::from_path(&path)?; let handle = same_file::Handle::from_path(&event.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(path)); return Ok(Some(event.path));
}
} }
} }
} _ => (),
},
Err(mpsc::TryRecvError::Disconnected) => bail!("File watcher disconnected"), Err(mpsc::TryRecvError::Disconnected) => bail!("File watcher disconnected"),
_ => (), _ => (),
} }

File diff suppressed because one or more lines are too long

View File

@@ -93,7 +93,7 @@ impl super::Runtime for MicroW8 {
linker.define("env", "memory", memory)?; linker.define("env", "memory", memory)?;
let loader_instance = linker.instantiate(&mut store, &self.loader_module)?; let loader_instance = linker.instantiate(&mut store, &self.loader_module)?;
let load_uw8 = loader_instance.get_typed_func::<i32, i32, _>(&mut store, "load_uw8")?; let load_uw8 = loader_instance.get_typed_func::<i32, i32>(&mut store, "load_uw8")?;
let platform_data = include_bytes!("../platform/bin/platform.uw8"); let platform_data = include_bytes!("../platform/bin/platform.uw8");
memory.data_mut(&mut store)[..platform_data.len()].copy_from_slice(platform_data); memory.data_mut(&mut store)[..platform_data.len()].copy_from_slice(platform_data);
@@ -131,8 +131,12 @@ impl super::Runtime for MicroW8 {
} }
let instance = linker.instantiate(&mut store, &module)?; let instance = linker.instantiate(&mut store, &module)?;
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)
@@ -313,8 +317,8 @@ fn init_sound(
let instance = linker.instantiate(&mut store, module)?; let instance = linker.instantiate(&mut store, module)?;
let snd = instance let snd = instance
.get_typed_func::<(i32,), f32, _>(&mut store, "snd") .get_typed_func::<(i32,), f32>(&mut store, "snd")
.or_else(|_| platform_instance.get_typed_func::<(i32,), f32, _>(&mut store, "sndGes"))?; .or_else(|_| platform_instance.get_typed_func::<(i32,), f32>(&mut store, "sndGes"))?;
let host = cpal::default_host(); let host = cpal::default_host();
let device = host let device = host

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()
} }
} }

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
test.wasm

Binary file not shown.

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
test/start_fn.cwa Normal file
View File

@@ -0,0 +1,5 @@
include "../examples/include/microw8-api.cwa"
export fn start() {
printChar('Test');
}

13
test/text_modes.cwa Normal file
View File

@@ -0,0 +1,13 @@
include "../examples/include/microw8-api.cwa"
export fn upd() {
printString(USER_MEM);
}
data USER_MEM {
i8(12, 31, 5, 6) "Text mode"
i8(5, 31, 4, 5) "Graphics mode"
i8(6) "Console output\nSecond line\n"
i8(4, 31, 4, 12) "Back to text mode"
i8(0)
}

136
uw8-tool/Cargo.lock generated
View File

@@ -56,6 +56,21 @@ dependencies = [
"lazy_static", "lazy_static",
] ]
[[package]]
name = "form_urlencoded"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
dependencies = [
"percent-encoding",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.3.3" version = "0.3.3"
@@ -71,6 +86,26 @@ version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
[[package]]
name = "idna"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
dependencies = [
"unicode-bidi",
"unicode-normalization",
]
[[package]]
name = "indexmap"
version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@@ -83,6 +118,12 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
[[package]]
name = "lexopt"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478ee9e62aaeaf5b140bd4138753d1f109765488581444218d3ddda43234f3e8"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.112" version = "0.2.112"
@@ -120,10 +161,16 @@ dependencies = [
] ]
[[package]] [[package]]
name = "pico-args" name = "percent-encoding"
version = "0.4.2" version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]]
name = "pico-args"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
@@ -163,6 +210,26 @@ dependencies = [
"unicode-xid", "unicode-xid",
] ]
[[package]]
name = "thiserror"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "time" name = "time"
version = "0.1.44" version = "0.1.44"
@@ -174,6 +241,36 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "tinyvec"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
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 = "unicode-bidi"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"
[[package]]
name = "unicode-normalization"
version = "0.1.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
dependencies = [
"tinyvec",
]
[[package]] [[package]]
name = "unicode-segmentation" name = "unicode-segmentation"
version = "1.8.0" version = "1.8.0"
@@ -188,13 +285,24 @@ checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]] [[package]]
name = "upkr" name = "upkr"
version = "0.1.0" version = "0.2.1"
source = "git+https://github.com/exoticorn/upkr.git?rev=d93aec186c9fb91d962c488682a2db125c61306c#d93aec186c9fb91d962c488682a2db125c61306c" source = "git+https://github.com/exoticorn/upkr.git?rev=080db40d0088bbee2bdf3c5c75288ac7853d6b7a#080db40d0088bbee2bdf3c5c75288ac7853d6b7a"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cdivsufsort", "cdivsufsort",
"pbr", "lexopt",
"pico-args", "thiserror",
]
[[package]]
name = "url"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
dependencies = [
"form_urlencoded",
"idna",
"percent-encoding",
] ]
[[package]] [[package]]
@@ -207,7 +315,7 @@ dependencies = [
"upkr", "upkr",
"walrus", "walrus",
"wasm-encoder", "wasm-encoder",
"wasmparser 0.81.0", "wasmparser 0.99.0",
] ]
[[package]] [[package]]
@@ -244,9 +352,9 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]] [[package]]
name = "wasm-encoder" name = "wasm-encoder"
version = "0.8.0" version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db0c351632e46cc06a58a696a6c11e4cf90cad4b9f8f07a0b59128d616c29bb0" checksum = "ef126be0e14bdf355ac1a8b41afc89195289e5c7179f80118e3abddb472f0810"
dependencies = [ dependencies = [
"leb128", "leb128",
] ]
@@ -259,9 +367,13 @@ checksum = "b35c86d22e720a07d954ebbed772d01180501afe7d03d464f413bb5f8914a8d6"
[[package]] [[package]]
name = "wasmparser" name = "wasmparser"
version = "0.81.0" version = "0.99.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98930446519f63d00a836efdc22f67766ceae8dbcc1571379f2bcabc6b2b9abc" checksum = "9ef3b717afc67f848f412d4f02c127dd3e35a0eecd58c684580414df4fde01d3"
dependencies = [
"indexmap",
"url",
]
[[package]] [[package]]
name = "winapi" name = "winapi"

View File

@@ -6,10 +6,10 @@ 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]
wasmparser = "0.81" wasmparser = "0.99"
wasm-encoder = "0.8" wasm-encoder = "0.22"
walrus = "0.19" walrus = "0.19"
anyhow = "1" anyhow = "1"
pico-args = "0.4" pico-args = "0.5"
upkr = { git = "https://github.com/exoticorn/upkr.git", rev = "d93aec186c9fb91d962c488682a2db125c61306c" } upkr = { git = "https://github.com/exoticorn/upkr.git", rev = "080db40d0088bbee2bdf3c5c75288ac7853d6b7a" }
pbr = "1" pbr = "1"

View File

@@ -3,7 +3,7 @@ use std::{collections::HashMap, fs::File, path::Path};
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use std::io::prelude::*; use std::io::prelude::*;
use wasm_encoder::{ use wasm_encoder::{
CodeSection, EntityType, Export, ExportSection, Function, FunctionSection, ImportSection, CodeSection, EntityType, ExportKind, ExportSection, Function, FunctionSection, ImportSection,
Instruction, MemoryType, Module, TypeSection, ValType, Instruction, MemoryType, Module, TypeSection, ValType,
}; };
use ValType::*; use ValType::*;
@@ -218,13 +218,13 @@ impl BaseModule {
let mut imports = ImportSection::new(); let mut imports = ImportSection::new();
for (module, name, type_) in &self.function_imports { for (module, name, type_) in &self.function_imports {
imports.import(*module, Some(name.as_str()), EntityType::Function(*type_)); imports.import(*module, name.as_str(), EntityType::Function(*type_));
} }
for (module, name, import) in &self.global_imports { for (module, name, import) in &self.global_imports {
imports.import( imports.import(
*module, *module,
Some(name.as_str()), name.as_str(),
EntityType::Global(wasm_encoder::GlobalType { EntityType::Global(wasm_encoder::GlobalType {
val_type: import.type_, val_type: import.type_,
mutable: import.mutable, mutable: import.mutable,
@@ -234,11 +234,12 @@ impl BaseModule {
imports.import( imports.import(
"env", "env",
Some("memory"), "memory",
MemoryType { MemoryType {
minimum: self.memory as u64, minimum: self.memory as u64,
maximum: None, maximum: None,
memory64: false, memory64: false,
shared: false,
}, },
); );
@@ -259,7 +260,7 @@ impl BaseModule {
let mut exports = ExportSection::new(); let mut exports = ExportSection::new();
for (name, fnc) in &self.exports { for (name, fnc) in &self.exports {
exports.export(*name, Export::Function(*fnc)); exports.export(*name, ExportKind::Func, *fnc);
} }
module.section(&exports); module.section(&exports);
@@ -287,7 +288,7 @@ impl BaseModule {
pub fn create_binary(path: &Path) -> Result<()> { pub fn create_binary(path: &Path) -> Result<()> {
let base1 = BaseModule::for_format_version(1)?.to_wasm(); let base1 = BaseModule::for_format_version(1)?.to_wasm();
let data = upkr::pack(&base1, 4, false, None); let data = upkr::pack(&base1, 4, &upkr::Config::default(), None);
File::create(path)?.write_all(&data)?; File::create(path)?.write_all(&data)?;
Ok(()) Ok(())
} }

View File

@@ -10,7 +10,7 @@ use std::{
use wasm_encoder as enc; use wasm_encoder as enc;
use wasmparser::{ use wasmparser::{
BinaryReader, ExportSectionReader, ExternalKind, FunctionBody, FunctionSectionReader, BinaryReader, ExportSectionReader, ExternalKind, FunctionBody, FunctionSectionReader,
ImportSectionEntryType, ImportSectionReader, TableSectionReader, TypeSectionReader, ImportSectionReader, TableSectionReader, TypeRef, TypeSectionReader,
}; };
pub struct PackConfig { pub struct PackConfig {
@@ -63,7 +63,7 @@ pub fn pack(data: &[u8], config: &PackConfig) -> Result<Vec<u8>> {
uw8.extend_from_slice(&upkr::pack( uw8.extend_from_slice(&upkr::pack(
&result[8..], &result[8..],
level, level,
false, &upkr::Config::default(),
Some(&mut |pos| { Some(&mut |pos| {
pb.set(pos as u64); pb.set(pos as u64);
}), }),
@@ -90,7 +90,10 @@ pub fn unpack(data: Vec<u8>) -> Result<Vec<u8>> {
let (version, data) = match data[0] { let (version, data) = match data[0] {
0 => return Ok(data), 0 => return Ok(data),
1 => (1, data[1..].to_vec()), 1 => (1, data[1..].to_vec()),
2 => (1, upkr::unpack(&data[1..], false)), 2 => (
1,
upkr::unpack(&data[1..], &upkr::Config::default(), 4 * 1024 * 1024)?,
),
other => bail!("Uknown format version {}", other), other => bail!("Uknown format version {}", other),
}; };
@@ -133,8 +136,8 @@ pub fn unpack(data: Vec<u8>) -> Result<Vec<u8>> {
Ok(dest) Ok(dest)
} }
fn to_val_type(type_: &wasmparser::Type) -> Result<ValType> { fn to_val_type(type_: &wasmparser::ValType) -> Result<ValType> {
use wasmparser::Type::*; use wasmparser::ValType::*;
Ok(match *type_ { Ok(match *type_ {
I32 => ValType::I32, I32 => ValType::I32,
I64 => ValType::I64, I64 => ValType::I64,
@@ -144,7 +147,7 @@ fn to_val_type(type_: &wasmparser::Type) -> Result<ValType> {
}) })
} }
fn to_val_type_vec(types: &[wasmparser::Type]) -> Result<Vec<ValType>> { fn to_val_type_vec(types: &[wasmparser::ValType]) -> Result<Vec<ValType>> {
types.into_iter().map(to_val_type).collect() types.into_iter().map(to_val_type).collect()
} }
@@ -202,7 +205,7 @@ impl<'a> ParsedModule<'a> {
import_section = Some(Section::new(range, ImportSection::parse(reader)?)); import_section = Some(Section::new(range, ImportSection::parse(reader)?));
} }
Payload::GlobalSection(reader) => { Payload::GlobalSection(reader) => {
global_section = Some(Section::new(range, reader.get_count())); global_section = Some(Section::new(range, reader.count()));
} }
Payload::FunctionSection(reader) => { Payload::FunctionSection(reader) => {
function_section = Some(Section::new(range, read_function_section(reader)?)); function_section = Some(Section::new(range, read_function_section(reader)?));
@@ -221,21 +224,21 @@ impl<'a> ParsedModule<'a> {
table_section = Some(Section::new(range, ())); table_section = Some(Section::new(range, ()));
} }
Payload::MemorySection(reader) => { Payload::MemorySection(reader) => {
if reader.get_count() != 0 { if reader.count() != 0 {
bail!("Found non-empty MemorySection. Memory has to be imported!"); bail!("Found non-empty MemorySection. Memory has to be imported!");
} }
} }
Payload::ElementSection(mut reader) => { Payload::ElementSection(reader) => {
let mut elements = Vec::with_capacity(reader.get_count() as usize); let mut elements = Vec::with_capacity(reader.count() as usize);
for _ in 0..reader.get_count() { for element in reader {
elements.push(Element::parse(reader.read()?)?); elements.push(Element::parse(element?)?);
} }
element_section = Some(elements); element_section = Some(elements);
} }
Payload::CodeSectionStart { .. } => (), Payload::CodeSectionStart { .. } => (),
Payload::CodeSectionEntry(body) => function_bodies.push(body), Payload::CodeSectionEntry(body) => function_bodies.push(body),
Payload::CustomSection { .. } => (), Payload::CustomSection { .. } => (),
Payload::End => break, Payload::End(..) => break,
other => bail!("Unsupported section: {:?}", other), other => bail!("Unsupported section: {:?}", other),
} }
@@ -463,7 +466,7 @@ impl<'a> ParsedModule<'a> {
{ {
let mut export_section = enc::ExportSection::new(); let mut export_section = enc::ExportSection::new();
for (name, fnc) in my_exports { for (name, fnc) in my_exports {
export_section.export(&name, enc::Export::Function(fnc)); export_section.export(&name, enc::ExportKind::Func, fnc);
} }
module.section(&export_section); module.section(&export_section);
} }
@@ -486,7 +489,7 @@ impl<'a> ParsedModule<'a> {
} }
element_section.active( element_section.active(
None, None,
&wasm_encoder::Instruction::I32Const(element.start_index as i32), &wasm_encoder::ConstExpr::i32_const(element.start_index as i32),
ValType::FuncRef, ValType::FuncRef,
wasm_encoder::Elements::Functions(&functions), wasm_encoder::Elements::Functions(&functions),
); );
@@ -535,28 +538,27 @@ fn read_type_section(reader: TypeSectionReader) -> Result<Vec<base_module::Funct
for type_def in reader { for type_def in reader {
match type_def? { match type_def? {
wasmparser::TypeDef::Func(fnc) => { wasmparser::Type::Func(fnc) => {
if fnc.returns.len() > 1 { if fnc.results().len() > 1 {
bail!("Multi-value not supported"); bail!("Multi-value not supported");
} }
let params = to_val_type_vec(&fnc.params)?; let params = to_val_type_vec(fnc.params())?;
let result = to_val_type_vec(&fnc.returns)?.into_iter().next(); let result = to_val_type_vec(fnc.results())?.into_iter().next();
function_types.push(FunctionType { params, result }); function_types.push(FunctionType { params, result });
} }
t => bail!("Unsupported type def {:?}", t),
} }
} }
Ok(function_types) Ok(function_types)
} }
fn validate_table_section(mut reader: TableSectionReader) -> Result<()> { fn validate_table_section(reader: TableSectionReader) -> Result<()> {
if reader.get_count() != 1 { if reader.count() != 1 {
bail!("Only up to one table supported"); bail!("Only up to one table supported");
} }
let type_ = reader.read()?; let type_ = reader.into_iter().next().unwrap()?;
if type_.element_type != wasmparser::Type::FuncRef { if type_.element_type != wasmparser::ValType::FuncRef {
bail!("Only one funcref table is supported"); bail!("Only one funcref table is supported");
} }
@@ -590,45 +592,38 @@ impl ImportSection {
for import in reader { for import in reader {
let import = import?; let import = import?;
if let Some(field) = import.field { match import.ty {
match import.ty { TypeRef::Func(type_) => {
ImportSectionEntryType::Function(type_) => { functions.push(FunctionImport {
functions.push(FunctionImport { module: import.module.to_string(),
module: import.module.to_string(), field: import.name.to_string(),
field: field.to_string(), type_,
type_, });
});
}
ImportSectionEntryType::Memory(mem) => {
if import.module != "env" || field != "memory" {
bail!(
"Wrong name of memory import {}.{}, should be env.memory",
import.module,
field
);
}
if mem.memory64 || mem.shared {
bail!("Wrong memory import options: {:?}", import.ty);
}
memory = mem.maximum.unwrap_or(mem.initial) as u32;
}
ImportSectionEntryType::Global(glbl) => {
globals.push(GlobalImport {
module: import.module.to_string(),
field: field.to_string(),
type_: GlobalType {
type_: to_val_type(&glbl.content_type)?,
mutable: glbl.mutable,
},
});
}
_ => bail!("Unsupported import item {:?}", import.ty),
} }
} else { TypeRef::Memory(mem) => {
bail!( if import.module != "env" || import.name != "memory" {
"Found import without field, only module '{}'", bail!(
import.module "Wrong name of memory import {}.{}, should be env.memory",
); import.module,
import.name
);
}
if mem.memory64 || mem.shared {
bail!("Wrong memory import options: {:?}", import.ty);
}
memory = mem.maximum.unwrap_or(mem.initial) as u32;
}
TypeRef::Global(glbl) => {
globals.push(GlobalImport {
module: import.module.to_string(),
field: import.name.to_string(),
type_: GlobalType {
type_: to_val_type(&glbl.content_type)?,
mutable: glbl.mutable,
},
});
}
_ => bail!("Unsupported import item {:?}", import.ty),
} }
} }
@@ -648,40 +643,37 @@ struct Element {
impl Element { impl Element {
fn parse(element: wasmparser::Element) -> Result<Element> { fn parse(element: wasmparser::Element) -> Result<Element> {
if element.ty != wasmparser::Type::FuncRef { match element.items {
bail!("Table element type is not FuncRef"); wasmparser::ElementItems::Functions(funcs_reader) => {
} let start_index = if let wasmparser::ElementKind::Active {
offset_expr,
table_index: 0,
} = element.kind
{
let mut init_reader = offset_expr.get_operators_reader();
if let wasmparser::Operator::I32Const { value: start_index } =
init_reader.read()?
{
start_index as u32
} else {
bail!("Table element start index is not a integer constant");
}
} else {
bail!("Unsupported table element kind");
};
let start_index = if let wasmparser::ElementKind::Active { let mut functions = Vec::with_capacity(funcs_reader.count() as usize);
init_expr, for index in funcs_reader {
table_index: 0, functions.push(index?);
} = element.kind }
{
let mut init_reader = init_expr.get_operators_reader(); Ok(Element {
if let wasmparser::Operator::I32Const { value: start_index } = init_reader.read()? { start_index,
start_index as u32 functions,
} else { })
bail!("Table element start index is not a integer constant");
}
} else {
bail!("Unsupported table element kind");
};
let mut items_reader = element.items.get_items_reader()?;
let mut functions = Vec::with_capacity(items_reader.get_count() as usize);
for _ in 0..items_reader.get_count() {
if let wasmparser::ElementItem::Func(index) = items_reader.read()? {
functions.push(index);
} else {
bail!("Table element item is not a function");
} }
_ => bail!("Table element type is not FuncRef"),
} }
Ok(Element {
start_index,
functions,
})
} }
} }
@@ -712,8 +704,8 @@ fn read_export_section(reader: ExportSectionReader) -> Result<Vec<(String, u32)>
for export in reader { for export in reader {
let export = export?; let export = export?;
match export.kind { match export.kind {
ExternalKind::Function => { ExternalKind::Func => {
function_exports.push((export.field.to_string(), export.index)); function_exports.push((export.name.to_string(), export.index));
} }
_ => (), // just ignore all other kinds since MicroW8 doesn't expect any exports other than functions _ => (), // just ignore all other kinds since MicroW8 doesn't expect any exports other than functions
} }
@@ -734,13 +726,11 @@ fn remap_function(
} }
let mut function = enc::Function::new(locals); let mut function = enc::Function::new(locals);
let block_type = |ty: wasmparser::TypeOrFuncType| -> Result<enc::BlockType> { let block_type = |ty: wasmparser::BlockType| -> Result<enc::BlockType> {
Ok(match ty { Ok(match ty {
wasmparser::TypeOrFuncType::Type(wasmparser::Type::EmptyBlockType) => { wasmparser::BlockType::Empty => enc::BlockType::Empty,
enc::BlockType::Empty wasmparser::BlockType::Type(ty) => enc::BlockType::Result(to_val_type(&ty)?),
} wasmparser::BlockType::FuncType(ty) => enc::BlockType::FunctionType(
wasmparser::TypeOrFuncType::Type(ty) => enc::BlockType::Result(to_val_type(&ty)?),
wasmparser::TypeOrFuncType::FuncType(ty) => enc::BlockType::FunctionType(
*type_map *type_map
.get(&ty) .get(&ty)
.ok_or_else(|| anyhow!("Function type index out of range: {}", ty))?, .ok_or_else(|| anyhow!("Function type index out of range: {}", ty))?,
@@ -754,7 +744,7 @@ fn remap_function(
.ok_or_else(|| anyhow!("Global index out of range: {}", idx))?) .ok_or_else(|| anyhow!("Global index out of range: {}", idx))?)
}; };
fn mem(m: wasmparser::MemoryImmediate) -> enc::MemArg { fn mem(m: wasmparser::MemArg) -> enc::MemArg {
enc::MemArg { enc::MemArg {
offset: m.offset, offset: m.offset,
align: m.align as u32, align: m.align as u32,
@@ -769,24 +759,31 @@ fn remap_function(
function.instruction(&match op? { function.instruction(&match op? {
De::Unreachable => En::Unreachable, De::Unreachable => En::Unreachable,
De::Nop => En::Nop, De::Nop => En::Nop,
De::Block { ty } => En::Block(block_type(ty)?), De::Block { blockty } => En::Block(block_type(blockty)?),
De::Loop { ty } => En::Loop(block_type(ty)?), De::Loop { blockty } => En::Loop(block_type(blockty)?),
De::If { ty } => En::If(block_type(ty)?), De::If { blockty } => En::If(block_type(blockty)?),
De::Else => En::Else, De::Else => En::Else,
De::Try { .. } | De::Catch { .. } | De::Throw { .. } | De::Rethrow { .. } => todo!(), De::Try { .. } | De::Catch { .. } | De::Throw { .. } | De::Rethrow { .. } => todo!(),
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
.get(&function_index) .get(&function_index)
.ok_or_else(|| anyhow!("Function index out of range: {}", function_index))?, .ok_or_else(|| anyhow!("Function index out of range: {}", function_index))?,
), ),
De::CallIndirect { index, table_index } => En::CallIndirect { De::CallIndirect {
type_index,
table_index,
table_byte: _, // what is this supposed to be?
} => En::CallIndirect {
ty: *type_map ty: *type_map
.get(&index) .get(&type_index)
.ok_or_else(|| anyhow!("Unknown function type in call indirect"))?, .ok_or_else(|| anyhow!("Unknown function type in call indirect"))?,
table: table_index, table: table_index,
}, },
@@ -806,16 +803,16 @@ fn remap_function(
De::I64Load { memarg } => En::I64Load(mem(memarg)), De::I64Load { memarg } => En::I64Load(mem(memarg)),
De::F32Load { memarg } => En::F32Load(mem(memarg)), De::F32Load { memarg } => En::F32Load(mem(memarg)),
De::F64Load { memarg } => En::F64Load(mem(memarg)), De::F64Load { memarg } => En::F64Load(mem(memarg)),
De::I32Load8S { memarg } => En::I32Load8_S(mem(memarg)), De::I32Load8S { memarg } => En::I32Load8S(mem(memarg)),
De::I32Load8U { memarg } => En::I32Load8_U(mem(memarg)), De::I32Load8U { memarg } => En::I32Load8U(mem(memarg)),
De::I32Load16S { memarg } => En::I32Load16_S(mem(memarg)), De::I32Load16S { memarg } => En::I32Load16S(mem(memarg)),
De::I32Load16U { memarg } => En::I32Load16_U(mem(memarg)), De::I32Load16U { memarg } => En::I32Load16U(mem(memarg)),
De::I64Load8S { memarg } => En::I64Load8_S(mem(memarg)), De::I64Load8S { memarg } => En::I64Load8S(mem(memarg)),
De::I64Load8U { memarg } => En::I64Load8_U(mem(memarg)), De::I64Load8U { memarg } => En::I64Load8U(mem(memarg)),
De::I64Load16S { memarg } => En::I64Load16_S(mem(memarg)), De::I64Load16S { memarg } => En::I64Load16S(mem(memarg)),
De::I64Load16U { memarg } => En::I64Load16_U(mem(memarg)), De::I64Load16U { memarg } => En::I64Load16U(mem(memarg)),
De::I64Load32S { memarg } => En::I64Load32_S(mem(memarg)), De::I64Load32S { memarg } => En::I64Load32S(mem(memarg)),
De::I64Load32U { memarg } => En::I64Load32_U(mem(memarg)), De::I64Load32U { memarg } => En::I64Load32U(mem(memarg)),
De::I32Store { memarg } => En::I32Store(mem(memarg)), De::I32Store { memarg } => En::I32Store(mem(memarg)),
De::I64Store { memarg } => En::I64Store(mem(memarg)), De::I64Store { memarg } => En::I64Store(mem(memarg)),
De::F32Store { memarg } => En::F32Store(mem(memarg)), De::F32Store { memarg } => En::F32Store(mem(memarg)),
@@ -834,7 +831,7 @@ fn remap_function(
De::RefNull { .. } | De::RefIsNull { .. } | De::RefFunc { .. } => todo!(), De::RefNull { .. } | De::RefIsNull { .. } | De::RefFunc { .. } => todo!(),
De::I32Eqz => En::I32Eqz, De::I32Eqz => En::I32Eqz,
De::I32Eq => En::I32Eq, De::I32Eq => En::I32Eq,
De::I32Ne => En::I32Neq, De::I32Ne => En::I32Ne,
De::I32LtS => En::I32LtS, De::I32LtS => En::I32LtS,
De::I32LtU => En::I32LtU, De::I32LtU => En::I32LtU,
De::I32GtS => En::I32GtS, De::I32GtS => En::I32GtS,
@@ -845,7 +842,7 @@ fn remap_function(
De::I32GeU => En::I32GeU, De::I32GeU => En::I32GeU,
De::I64Eqz => En::I64Eqz, De::I64Eqz => En::I64Eqz,
De::I64Eq => En::I64Eq, De::I64Eq => En::I64Eq,
De::I64Ne => En::I64Neq, De::I64Ne => En::I64Ne,
De::I64LtS => En::I64LtS, De::I64LtS => En::I64LtS,
De::I64LtU => En::I64LtU, De::I64LtU => En::I64LtU,
De::I64GtS => En::I64GtS, De::I64GtS => En::I64GtS,
@@ -855,13 +852,13 @@ fn remap_function(
De::I64GeS => En::I64GeS, De::I64GeS => En::I64GeS,
De::I64GeU => En::I64GeU, De::I64GeU => En::I64GeU,
De::F32Eq => En::F32Eq, De::F32Eq => En::F32Eq,
De::F32Ne => En::F32Neq, De::F32Ne => En::F32Ne,
De::F32Lt => En::F32Lt, De::F32Lt => En::F32Lt,
De::F32Gt => En::F32Gt, De::F32Gt => En::F32Gt,
De::F32Le => En::F32Le, De::F32Le => En::F32Le,
De::F32Ge => En::F32Ge, De::F32Ge => En::F32Ge,
De::F64Eq => En::F64Eq, De::F64Eq => En::F64Eq,
De::F64Ne => En::F64Neq, De::F64Ne => En::F64Ne,
De::F64Lt => En::F64Lt, De::F64Lt => En::F64Lt,
De::F64Gt => En::F64Gt, De::F64Gt => En::F64Gt,
De::F64Le => En::F64Le, De::F64Le => En::F64Le,
@@ -968,7 +965,7 @@ fn remap_function(
De::I64TruncSatF32U => En::I64TruncSatF32U, De::I64TruncSatF32U => En::I64TruncSatF32U,
De::I64TruncSatF64S => En::I64TruncSatF64S, De::I64TruncSatF64S => En::I64TruncSatF64S,
De::I64TruncSatF64U => En::I64TruncSatF64U, De::I64TruncSatF64U => En::I64TruncSatF64U,
De::MemoryCopy { src, dst } => En::MemoryCopy { src, dst }, De::MemoryCopy { src_mem, dst_mem } => En::MemoryCopy { src_mem, dst_mem },
De::MemoryFill { mem } => En::MemoryFill(mem), De::MemoryFill { mem } => En::MemoryFill(mem),
other => bail!("Unsupported instruction {:?}", other), other => bail!("Unsupported instruction {:?}", other),
}); });

844
uw8-window/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -6,13 +6,13 @@ 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]
winit = "0.26.1" winit = "0.27.5"
env_logger = "0.9" env_logger = "0.10"
log = "0.4" log = "0.4"
pico-args = "0.4" pico-args = "0.5"
wgpu = "0.13.1" wgpu = "0.15"
pollster = "0.2" pollster = "0.2.5"
bytemuck = { version = "1.4", features = [ "derive" ] } bytemuck = { version = "1.13", features = [ "derive" ] }
anyhow = "1" anyhow = "1"
minifb = { version = "0.23.0", default-features = false, features = ["x11"] } minifb = { version = "0.23.0", default-features = false, features = ["x11"] }
winapi = "0.3.9" winapi = { version = "0.3.9", features = [ "timeapi" ] }

View File

@@ -36,36 +36,36 @@ fn sample_pixel(coords: vec2<i32>, offset: vec4<f32>) -> vec3<f32> {
@fragment @fragment
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> { fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
let pixel = floor(in.tex_coords); let pixelf = floor(in.tex_coords);
let o = vec2<f32>(0.5) - (in.tex_coords - pixel); let o = vec2<f32>(0.5) - (in.tex_coords - pixelf);
let pixel = vec2<i32>(pixel); let pixel = vec2<i32>(pixelf);
let offset_x = o.xxxx + vec4<f32>(-0.125, 0.375, 0.125, -0.375) * uniforms.texture_scale.z; let offset_x = o.xxxx + vec4<f32>(-0.125, 0.375, 0.125, -0.375) * uniforms.texture_scale.z;
let offset_y = o.yyyy + vec4<f32>(-0.375, -0.125, 0.375, 0.125) * uniforms.texture_scale.z; let offset_y = o.yyyy + vec4<f32>(-0.375, -0.125, 0.375, 0.125) * uniforms.texture_scale.z;
let offset_x0 = max(abs(offset_x + vec4<f32>(-1.0)) - vec4<f32>(0.5), vec4<f32>(0.0)); var offset_x0 = max(abs(offset_x + vec4<f32>(-1.0)) - vec4<f32>(0.5), vec4<f32>(0.0));
let offset_x1 = max(abs(offset_x) - vec4<f32>(0.5), vec4<f32>(0.0)); var offset_x1 = max(abs(offset_x) - vec4<f32>(0.5), vec4<f32>(0.0));
let offset_x2 = max(abs(offset_x + vec4<f32>(1.0)) - vec4<f32>(0.5), vec4<f32>(0.0)); var offset_x2 = max(abs(offset_x + vec4<f32>(1.0)) - vec4<f32>(0.5), vec4<f32>(0.0));
let offset_x0 = offset_x0 * offset_x0; offset_x0 = offset_x0 * offset_x0;
let offset_x1 = offset_x1 * offset_x1; offset_x1 = offset_x1 * offset_x1;
let offset_x2 = offset_x2 * offset_x2; offset_x2 = offset_x2 * offset_x2;
let offset_yr = offset_y + vec4<f32>(-1.0); var offset_yr = offset_y + vec4<f32>(-1.0);
let offset_yr = vec4<f32>(0.02) + offset_yr * offset_yr; offset_yr = vec4<f32>(0.02) + offset_yr * offset_yr;
var acc = sample_pixel(pixel + vec2<i32>(-1, -1), offset_x0 + offset_yr); var acc = sample_pixel(pixel + vec2<i32>(-1, -1), offset_x0 + offset_yr);
acc = acc + sample_pixel(pixel + vec2<i32>(0, -1), offset_x1 + offset_yr); acc = acc + sample_pixel(pixel + vec2<i32>(0, -1), offset_x1 + offset_yr);
acc = acc + sample_pixel(pixel + vec2<i32>(1, -1), offset_x2 + offset_yr); acc = acc + sample_pixel(pixel + vec2<i32>(1, -1), offset_x2 + offset_yr);
let offset_yr = vec4<f32>(0.02) + offset_y * offset_y; offset_yr = vec4<f32>(0.02) + offset_y * offset_y;
acc = acc + sample_pixel(pixel + vec2<i32>(-1, 0), offset_x0 + offset_yr); acc = acc + sample_pixel(pixel + vec2<i32>(-1, 0), offset_x0 + offset_yr);
acc = acc + sample_pixel(pixel, offset_x1 + offset_yr); acc = acc + sample_pixel(pixel, offset_x1 + offset_yr);
acc = acc + sample_pixel(pixel + vec2<i32>(1, 0), offset_x2 + offset_yr); acc = acc + sample_pixel(pixel + vec2<i32>(1, 0), offset_x2 + offset_yr);
let offset_yr = offset_y + vec4<f32>(1.0); offset_yr = offset_y + vec4<f32>(1.0);
let offset_yr = vec4<f32>(0.02) + offset_yr * offset_yr; offset_yr = vec4<f32>(0.02) + offset_yr * offset_yr;
acc = acc + sample_pixel(pixel + vec2<i32>(-1, 1), offset_x0 + offset_yr); acc = acc + sample_pixel(pixel + vec2<i32>(-1, 1), offset_x0 + offset_yr);
acc = acc + sample_pixel(pixel + vec2<i32>(0, 1), offset_x1 + offset_yr); acc = acc + sample_pixel(pixel + vec2<i32>(0, 1), offset_x1 + offset_yr);

View File

@@ -41,7 +41,10 @@ impl Window {
async fn create(window_config: WindowConfig) -> Result<Window> { async fn create(window_config: WindowConfig) -> Result<Window> {
let event_loop = EventLoop::new(); let event_loop = EventLoop::new();
let window = WindowBuilder::new() let window = WindowBuilder::new()
.with_inner_size(PhysicalSize::new(640u32, 480)) .with_inner_size(PhysicalSize::new(
(320. * window_config.scale).round() as u32,
(240. * window_config.scale).round() as u32,
))
.with_min_inner_size(PhysicalSize::new(320u32, 240)) .with_min_inner_size(PhysicalSize::new(320u32, 240))
.with_title("MicroW8") .with_title("MicroW8")
.with_fullscreen(if window_config.fullscreen { .with_fullscreen(if window_config.fullscreen {
@@ -53,8 +56,8 @@ impl Window {
window.set_cursor_visible(false); window.set_cursor_visible(false);
let instance = wgpu::Instance::new(wgpu::Backends::all()); let instance = wgpu::Instance::new(Default::default());
let surface = unsafe { instance.create_surface(&window) }; let surface = unsafe { instance.create_surface(&window) }?;
let adapter = instance let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions { .request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::LowPower, power_preference: wgpu::PowerPreference::LowPower,
@@ -71,11 +74,14 @@ impl Window {
let palette_screen_mode = PaletteScreenMode::new(&device); let palette_screen_mode = PaletteScreenMode::new(&device);
let surface_config = wgpu::SurfaceConfiguration { let surface_config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface.get_supported_formats(&adapter)[0],
width: window.inner_size().width,
height: window.inner_size().height,
present_mode: wgpu::PresentMode::AutoNoVsync, present_mode: wgpu::PresentMode::AutoNoVsync,
..surface
.get_default_config(
&adapter,
window.inner_size().width,
window.inner_size().height,
)
.expect("Surface incompatible with adapter")
}; };
let filter: Box<dyn Filter> = create_filter( let filter: Box<dyn Filter> = create_filter(
@@ -357,6 +363,7 @@ impl PaletteScreenMode {
format: wgpu::TextureFormat::R8Uint, format: wgpu::TextureFormat::R8Uint,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
label: None, label: None,
view_formats: &[],
}); });
let palette_texture = device.create_texture(&wgpu::TextureDescriptor { let palette_texture = device.create_texture(&wgpu::TextureDescriptor {
@@ -371,6 +378,7 @@ impl PaletteScreenMode {
format: wgpu::TextureFormat::Rgba8UnormSrgb, format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
label: None, label: None,
view_formats: &[],
}); });
let screen_texture = device.create_texture(&wgpu::TextureDescriptor { let screen_texture = device.create_texture(&wgpu::TextureDescriptor {
@@ -385,6 +393,7 @@ impl PaletteScreenMode {
format: wgpu::TextureFormat::Rgba8UnormSrgb, format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::RENDER_ATTACHMENT, usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::RENDER_ATTACHMENT,
label: None, label: None,
view_formats: &[],
}); });
let framebuffer_texture_view = let framebuffer_texture_view =

View File

@@ -15,7 +15,7 @@ struct FpsCounter {
} }
impl Window { impl Window {
pub fn new(config: WindowConfig) -> Result<Window> { pub fn new(mut config: WindowConfig) -> Result<Window> {
let fps_counter = if config.fps_counter { let fps_counter = if config.fps_counter {
Some(FpsCounter { Some(FpsCounter {
start: Instant::now(), start: Instant::now(),
@@ -24,6 +24,7 @@ impl Window {
} else { } else {
None None
}; };
config.scale = config.scale.max(1.).min(20.);
if config.enable_gpu { if config.enable_gpu {
match gpu::Window::new(config) { match gpu::Window::new(config) {
Ok(window) => { Ok(window) => {
@@ -71,6 +72,7 @@ pub struct WindowConfig {
filter: u32, filter: u32,
fullscreen: bool, fullscreen: bool,
fps_counter: bool, fps_counter: bool,
scale: f32,
} }
impl Default for WindowConfig { impl Default for WindowConfig {
@@ -80,6 +82,7 @@ impl Default for WindowConfig {
filter: 5, filter: 5,
fullscreen: false, fullscreen: false,
fps_counter: false, fps_counter: false,
scale: 2.,
} }
} }
} }
@@ -102,6 +105,10 @@ impl WindowConfig {
} }
self.fullscreen = args.contains("--fullscreen"); self.fullscreen = args.contains("--fullscreen");
self.fps_counter = args.contains("--fps"); self.fps_counter = args.contains("--fps");
self.scale = args
.opt_value_from_str("--scale")
.unwrap()
.unwrap_or(self.scale);
} }
} }

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">

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;