14 Commits

28 changed files with 3557 additions and 3212 deletions

3249
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -11,21 +11,21 @@ native = ["wasmtime", "uw8-window", "cpal", "rubato" ]
browser = ["warp", "tokio", "tokio-stream", "webbrowser"]
[dependencies]
wasmtime = { version = "5.0.0", optional = true }
wasmtime = { version = "19.0.1", optional = true }
anyhow = "1"
env_logger = "0.10"
env_logger = "0.11.3"
log = "0.4"
uw8-window = { path = "uw8-window", optional = true }
notify-debouncer-mini = { version = "0.2.1", default-features = false }
notify-debouncer-mini = { version = "0.4.1", default-features = false }
pico-args = "0.5"
curlywas = { git = "https://github.com/exoticorn/curlywas.git", rev = "0e7ea50" }
wat = "1"
uw8-tool = { path = "uw8-tool" }
same-file = "1"
warp = { version = "0.3.3", optional = true }
tokio = { version = "1.24.0", features = ["sync", "rt"], optional = true }
tokio-stream = { version = "0.1.11", features = ["sync"], optional = true }
webbrowser = { version = "0.8.6", optional = true }
warp = { version = "0.3.6", optional = true }
tokio = { version = "1.37.0", features = ["sync", "rt"], optional = true }
tokio-stream = { version = "0.1.15", features = ["sync"], optional = true }
webbrowser = { version = "0.8.13", optional = true }
ansi_term = "0.12.1"
cpal = { version = "0.14.2", optional = true }
rubato = { version = "0.12.0", optional = true }
cpal = { version = "0.15.3", optional = true }
rubato = { version = "0.15.0", optional = true }

View File

@@ -0,0 +1,14 @@
include "../include/microw8-api.cwa"
export fn upd() {
printString(USER_MEM);
}
data USER_MEM {
// clear screen, switch to graphics text mode, text scale 4
i8(12, 5, 30, 4)
// text color, position, print two lines
i8(15, 86, 31, 8, 80) "Hello," i8(8, 8, 8, 8, 8, 10) "MicroW8!"
// print same two lines with different color and slight offset
i8(15, 47, 31, 10, 82) "Hello," i8(8, 8, 8, 8, 8, 10) "MicroW8!" i8(0)
}

View File

@@ -4,13 +4,13 @@ const SPRITE = 0x20000;
export fn upd() {
cls(0);
let t = time();
let t = time() / 2_f;
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;
let inline x = sin(t * -1.3 + i as f32 * (3.141 / 30_f)) * 180_f + 160_f;
let inline y = sin(t * 1.7 + i as f32 * (3.141 / 40_f)) * 140_f + 120_f;
blitSprite(SPRITE, 16, x as i32, y as i32, (i & 3) * 0x200 + 0x100);
branch_if (i +:= 1) < 100: spriteLoop;
}
}

View File

@@ -1,2 +1,2 @@
zig-cache/
zig-out/
/zig-cache/
/zig-out/

View File

@@ -5,7 +5,11 @@ pub fn build(b: *std.build.Builder) void {
const lib = b.addSharedLibrary("cart", "main.zig", .unversioned);
lib.setBuildMode(mode);
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding, .cpu_features_add = std.Target.wasm.featureSet(&.{.nontrapping_fptoint}) });
lib.setTarget(.{
.cpu_arch = .wasm32,
.os_tag = .freestanding,
.cpu_features_add = std.Target.wasm.featureSet(&.{ .nontrapping_fptoint })
});
lib.import_memory = true;
lib.initial_memory = 262144;
lib.max_memory = 262144;
@@ -14,13 +18,19 @@ pub fn build(b: *std.build.Builder) void {
lib.install();
if (lib.install_step) |install_step| {
const run_filter_exports = b.addSystemCommand(&[_][]const u8{ "uw8", "filter-exports", "zig-out/lib/cart.wasm", "zig-out/lib/cart-filtered.wasm" });
const run_filter_exports = b.addSystemCommand(&[_][]const u8{
"uw8", "filter-exports", "zig-out/lib/cart.wasm", "zig-out/lib/cart-filtered.wasm"
});
run_filter_exports.step.dependOn(&install_step.step);
const run_wasm_opt = b.addSystemCommand(&[_][]const u8{ "wasm-opt", "--enable-nontrapping-float-to-int", "-Oz", "-o", "zig-out/cart.wasm", "zig-out/lib/cart-filtered.wasm" });
const run_wasm_opt = b.addSystemCommand(&[_][]const u8{
"wasm-opt", "-Oz", "-o", "zig-out/cart.wasm", "zig-out/lib/cart-filtered.wasm"
});
run_wasm_opt.step.dependOn(&run_filter_exports.step);
const run_uw8_pack = b.addSystemCommand(&[_][]const u8{ "uw8", "pack", "-l", "5", "zig-out/cart.wasm", "zig-out/cart.uw8" });
const run_uw8_pack = b.addSystemCommand(&[_][]const u8{
"uw8", "pack", "-l", "9", "zig-out/cart.wasm", "zig-out/cart.uw8"
});
run_uw8_pack.step.dependOn(&run_wasm_opt.step);
const make_opt = b.step("make_opt", "make size optimized cart");

View File

@@ -1,142 +0,0 @@
const uw8 = @import("uw8.zig");
var redBallSprite: [16 * 16]u8 = undefined;
var greenBallSprite: [16 * 16]u8 = undefined;
var blueBallSprite: [16 * 16]u8 = undefined;
var wallSprite: [24 * 24]u8 = undefined;
const SphereConfigStep = struct { size: u8, color: u8 };
// zig fmt: off
const redSphereConfig: [4]SphereConfigStep = .{
.{ .size = 0, .color = 0x3d },
.{ .size = 2, .color = 0x48 },
.{ .size = 6, .color = 0x65 },
.{ .size = 9, .color = 0x55 }
};
const greenSphereConfig: [4]SphereConfigStep = .{
.{ .size = 0, .color = 0x7d },
.{ .size = 2, .color = 0x88 },
.{ .size = 6, .color = 0x96 },
.{ .size = 9, .color = 0xa3 }
};
const blueSphereConfig: [4]SphereConfigStep = .{
.{ .size = 0, .color = 0x2e },
.{ .size = 2, .color = 0x19 },
.{ .size = 6, .color = 0x17 },
.{ .size = 9, .color = 0x24 }
};
const levelData: [14] *const [19]u8 = .{
"xxxxxxxxxxxxxxxxxxx",
"x x x x",
"x x xx x xx x x",
"x x xxx x xxx x x",
"x xx x x xx x",
"x xx xxxxx xx x",
"x x x x",
"x xx xx xxx xx xx x",
"x x xx xx x x",
"xx x x x x xx",
"x xx xxx xxx xx x",
"x xx x x xx x",
"x x x x x",
"xxxxxxxxxxxxxxxxxxx",
};
// zig fmt: on
export fn start() void {
blitSphere(&redBallSprite, &redSphereConfig);
blitSphere(&greenBallSprite, &greenSphereConfig);
blitSphere(&blueBallSprite, &blueSphereConfig);
createWallSprite();
}
fn blitSphere(sprite: [*]u8, config: []const SphereConfigStep) void {
for (config) |circle| {
uw8.circle(8, 8, 8, circle.color);
uw8.circle(5, 6, @intToFloat(f32, circle.size), 0);
uw8.grabSprite(sprite, 16, 0, 0, 0x100);
}
}
fn createWallSprite() void {
uw8.cls(0xe4);
var i: i32 = 0;
while (i < 50) : (i += 1) {
const x = uw8.randomf() * 16;
const y = uw8.randomf() * 16;
const radius = uw8.randomf() * 2 + 1;
const c = @intCast(u8, (uw8.random() & 3)) + 0x95;
var j: i32 = 0;
while (j < 9) : (j += 1) {
uw8.circle(x + @intToFloat(f32, @rem(j, 3) * 16), y + @intToFloat(f32, @divFloor(j, 3) * 16), radius, c);
}
}
uw8.grabSprite(&wallSprite, 16, 16, 16, 0);
}
export fn upd() void {
uw8.cls(0);
var y: usize = 0;
while (y < levelData.len) : (y += 1) {
var x: usize = 0;
while (x < levelData[y].len) : (x += 1) {
if (levelData[y][x] == 'x') {
uw8.blitSprite(&wallSprite, 16, 8 + @intCast(i32, x) * 16, @intCast(i32, y) * 16, 0);
}
}
}
updateEnemy(&enemies[0], &redBallSprite);
updateEnemy(&enemies[1], &greenBallSprite);
updateEnemy(&enemies[2], &blueBallSprite);
}
const EntityState = struct { x: i32, y: i32, dir: u2 };
var enemies: [3]EntityState = .{
.{ .x = 16, .y = 16, .dir = 1 },
.{ .x = 16 * 18, .y = 16, .dir = 3 },
.{ .x = 16, .y = 16 * 12, .dir = 1 },
};
fn updateEnemy(enemy: *EntityState, sprite: [*]u8) void {
switch (enemy.dir) {
0 => enemy.y -= 1,
1 => enemy.x += 1,
2 => enemy.y += 1,
3 => enemy.x -= 1,
}
if (((enemy.x | enemy.y) & 15) == 0) {
const tx = @intCast(usize, enemy.x) / 16;
const ty = @intCast(usize, enemy.y) / 16;
var dir = enemy.dir;
var count: u32 = 0;
if (enemy.dir != 2 and levelData[ty - 1][tx] == ' ') {
dir = 0;
count += 1;
}
if (enemy.dir != 3 and levelData[ty][tx + 1] == ' ') {
count += 1;
if (uw8.random() % count == 0) {
dir = 1;
}
}
if (enemy.dir != 0 and levelData[ty + 1][tx] == ' ') {
count += 1;
if (uw8.random() % count == 0) {
dir = 2;
}
}
if (enemy.dir != 1 and levelData[ty][tx - 1] == ' ') {
count += 1;
if (uw8.random() % count == 0) {
dir = 3;
}
}
enemy.dir = dir;
}
uw8.blitSprite(sprite, 16, 8 + enemy.x, enemy.y, 0x100);
}

View File

@@ -1,10 +0,0 @@
pub extern fn random() u32;
pub extern fn randomf() f32;
pub extern fn time() f32;
pub extern fn cls(color: u8) void;
pub extern fn circle(x: f32, y: f32, radiu: f32, color: u8) void;
pub extern fn blitSprite(spriteData: [*]u8, size: u32, x: i32, y: i32, ctrl: u32) void;
pub extern fn grabSprite(spriteData: [*]u8, size: u32, x: i32, y: i32, ctrl: u32) void;
pub extern fn printString(str: [*:0]u8) void;
pub extern fn printInt(value: i32) void;
pub extern fn printChar(char: u32) void;

View File

@@ -1,11 +1,11 @@
extern fn atan2(x: f32, y: f32) f32;
extern fn time() f32;
pub const FRAMEBUFFER: *[320 * 240]u8 = @intToPtr(*[320 * 240]u8, 120);
pub const FRAMEBUFFER: *[320*240]u8 = @intToPtr(*[320*240]u8, 120);
export fn upd() void {
var i: u32 = 0;
while (true) {
while(true) {
var t = time() * 63.0;
var x = @intToFloat(f32, (@intCast(i32, i % 320) - 160));
var y = @intToFloat(f32, (@intCast(i32, i / 320) - 120));
@@ -13,10 +13,8 @@ export fn upd() void {
var u = atan2(x, y) * 512.0 / 3.141;
var c = @intCast(u8, (@floatToInt(i32, d + t * 2.0) ^ @floatToInt(i32, u + t)) & 255) >> 4;
FRAMEBUFFER[i] = c;
FRAMEBUFFER[@as(usize, i)] = c;
i += 1;
if (i >= 320 * 240) {
break;
}
if(i >= 320*240) { break; }
}
}
}

View File

@@ -1,31 +0,0 @@
const std = @import("std");
pub fn build(b: *std.build.Builder) void {
const mode = std.builtin.Mode.ReleaseSmall;
const lib = b.addSharedLibrary("cart", "main.zig", .unversioned);
lib.setBuildMode(mode);
lib.setTarget(.{ .cpu_arch = .wasm32, .os_tag = .freestanding, .cpu_features_add = std.Target.wasm.featureSet(&.{.nontrapping_fptoint}) });
lib.import_memory = true;
lib.initial_memory = 262144;
lib.max_memory = 262144;
lib.global_base = 81920;
lib.stack_size = 8192;
lib.install();
if (lib.install_step) |install_step| {
const run_filter_exports = b.addSystemCommand(&[_][]const u8{ "uw8", "filter-exports", "zig-out/lib/cart.wasm", "zig-out/lib/cart-filtered.wasm" });
run_filter_exports.step.dependOn(&install_step.step);
const run_wasm_opt = b.addSystemCommand(&[_][]const u8{ "wasm-opt", "--enable-nontrapping-float-to-int", "-Oz", "-o", "zig-out/cart.wasm", "zig-out/lib/cart-filtered.wasm" });
run_wasm_opt.step.dependOn(&run_filter_exports.step);
const run_uw8_pack = b.addSystemCommand(&[_][]const u8{ "uw8", "pack", "-l", "9", "zig-out/cart.wasm", "zig-out/cart.uw8" });
run_uw8_pack.step.dependOn(&run_wasm_opt.step);
const make_opt = b.step("make_opt", "make size optimized cart");
make_opt.dependOn(&run_uw8_pack.step);
b.default_step = make_opt;
}
}

380
platform/Cargo.lock generated
View File

@@ -19,47 +19,54 @@ dependencies = [
[[package]]
name = "ahash"
version = "0.7.6"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"getrandom",
"cfg-if",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "anyhow"
version = "1.0.52"
version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3"
checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247"
[[package]]
name = "ariadne"
version = "0.1.3"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7080ae01b2f0c312065d4914cd0f0de045eb8832e9415b355106a6cff3073cb4"
checksum = "f1cb2a2046bea8ce5e875551f5772024882de0b540c7f93dfc5d6cf1ca8b030c"
dependencies = [
"yansi",
]
[[package]]
name = "autocfg"
version = "1.0.1"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
[[package]]
name = "bitflags"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "bytemuck"
version = "1.7.3"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f"
checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15"
[[package]]
name = "cc"
version = "1.0.72"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41"
[[package]]
name = "cdivsufsort"
@@ -88,54 +95,47 @@ dependencies = [
[[package]]
name = "const-random"
version = "0.1.13"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f590d95d011aa80b063ffe3253422ed5aa462af4e9867d43ce8337562bac77c4"
checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
dependencies = [
"const-random-macro",
"proc-macro-hack",
]
[[package]]
name = "const-random-macro"
version = "0.1.13"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "615f6e27d000a2bffbc7f2f6a8669179378fa27ee4d0a509e985dfc0a7defb40"
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
dependencies = [
"getrandom",
"lazy_static",
"proc-macro-hack",
"once_cell",
"tiny-keccak",
]
[[package]]
name = "crc32fast"
version = "1.3.2"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
dependencies = [
"cfg-if",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.1"
version = "0.5.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.5"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [
"cfg-if",
"lazy_static",
]
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
[[package]]
name = "crunchy"
@@ -157,53 +157,79 @@ dependencies = [
]
[[package]]
name = "fallible_collections"
version = "0.4.6"
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f57ccc32870366ae684be48b32a1a2e196f98a42a9b4361fe77e13fd4a34755"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "fallible-iterator"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]]
name = "fallible_collections"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a88c69768c0a15262df21899142bc6df9b9b823546d4b4b9a7bc2d6c448ec6fd"
dependencies = [
"hashbrown",
"hashbrown 0.13.2",
]
[[package]]
name = "flate2"
version = "1.0.25"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
dependencies = [
"crc32fast",
"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]]
name = "getrandom"
version = "0.2.3"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "gimli"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
dependencies = [
"fallible-iterator",
"indexmap 1.9.3",
"stable_deref_trait",
]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
dependencies = [
"ahash 0.7.6",
"ahash 0.8.11",
]
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
name = "heck"
version = "0.3.3"
@@ -220,31 +246,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
[[package]]
name = "idna"
version = "0.3.0"
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"unicode-bidi",
"unicode-normalization",
"autocfg",
"hashbrown 0.12.3",
]
[[package]]
name = "indexmap"
version = "1.9.2"
version = "2.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
dependencies = [
"autocfg",
"hashbrown",
"equivalent",
"hashbrown 0.14.3",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "leb128"
version = "0.2.5"
@@ -259,15 +279,15 @@ checksum = "478ee9e62aaeaf5b140bd4138753d1f109765488581444218d3ddda43234f3e8"
[[package]]
name = "libc"
version = "0.2.139"
version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "lodepng"
version = "3.7.2"
version = "3.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0ad39f75bbaa4b10bb6f2316543632a8046a5bcf9c785488d79720b21f044f8"
checksum = "a42d298694b14401847de29abd44adf278b42e989e516deac7b72018400002d8"
dependencies = [
"crc32fast",
"fallible_collections",
@@ -278,55 +298,45 @@ dependencies = [
[[package]]
name = "log"
version = "0.4.14"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "miniz_oxide"
version = "0.6.2"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
dependencies = [
"adler",
]
[[package]]
name = "num-traits"
version = "0.2.14"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
dependencies = [
"autocfg",
]
[[package]]
name = "once_cell"
version = "1.9.0"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "pbr"
version = "1.0.4"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff5751d87f7c00ae6403eb1fcbba229b9c76c9a30de8c1cf87182177b168cea2"
checksum = "ed5827dfa0d69b6c92493d6c38e633bbaa5937c153d0d7c28bf12313f8c6d514"
dependencies = [
"crossbeam-channel",
"libc",
"time",
"winapi",
]
[[package]]
name = "percent-encoding"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]]
name = "pico-args"
version = "0.4.2"
@@ -349,35 +359,29 @@ dependencies = [
"uw8-tool",
]
[[package]]
name = "proc-macro-hack"
version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro2"
version = "1.0.36"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
dependencies = [
"unicode-xid",
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.15"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rgb"
version = "0.8.34"
version = "0.8.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3603b7d71ca82644f79b5a06d1220e9a58ede60bd32255f698cb1af8838b8db3"
checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8"
dependencies = [
"bytemuck",
]
@@ -392,44 +396,57 @@ dependencies = [
]
[[package]]
name = "syn"
version = "1.0.86"
name = "semver"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.38"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.38"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "time"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
dependencies = [
"libc",
"winapi",
"syn 2.0.58",
]
[[package]]
@@ -442,46 +459,16 @@ dependencies = [
]
[[package]]
name = "tinyvec"
version = "1.6.0"
name = "unicode-ident"
version = "1.0.12"
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",
]
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-segmentation"
version = "1.9.0"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
[[package]]
name = "upkr"
@@ -494,17 +481,6 @@ dependencies = [
"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]]
name = "uw8-tool"
version = "0.1.0"
@@ -514,28 +490,30 @@ dependencies = [
"pico-args 0.5.0",
"upkr",
"walrus",
"wasm-encoder 0.22.0",
"wasmparser 0.99.0",
"wasm-encoder 0.201.0",
"wasmparser 0.201.0",
]
[[package]]
name = "version_check"
version = "0.9.3"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "walrus"
version = "0.19.0"
version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eb08e48cde54c05f363d984bb54ce374f49e242def9468d2e1b6c2372d291f8"
checksum = "2c03529cd0c4400a2449f640d2f27cd1b48c3065226d15e26d98e4429ab0adb7"
dependencies = [
"anyhow",
"gimli",
"id-arena",
"leb128",
"log",
"walrus-macro",
"wasmparser 0.77.0",
"wasm-encoder 0.29.0",
"wasmparser 0.80.2",
]
[[package]]
@@ -547,14 +525,14 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
"syn 1.0.109",
]
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-encoder"
@@ -567,18 +545,27 @@ dependencies = [
[[package]]
name = "wasm-encoder"
version = "0.22.0"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef126be0e14bdf355ac1a8b41afc89195289e5c7179f80118e3abddb472f0810"
checksum = "18c41dbd92eaebf3612a39be316540b8377c871cb9bde6b064af962984912881"
dependencies = [
"leb128",
]
[[package]]
name = "wasm-encoder"
version = "0.201.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9c7d2731df60006819b013f64ccc2019691deccf6e11a1804bc850cd6748f1a"
dependencies = [
"leb128",
]
[[package]]
name = "wasmparser"
version = "0.77.0"
version = "0.80.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b35c86d22e720a07d954ebbed772d01180501afe7d03d464f413bb5f8914a8d6"
checksum = "449167e2832691a1bff24cde28d2804e90e09586a448c8e76984792c44334a6b"
[[package]]
name = "wasmparser"
@@ -588,12 +575,13 @@ checksum = "718ed7c55c2add6548cca3ddd6383d738cd73b892df400e96b9aa876f0141d7a"
[[package]]
name = "wasmparser"
version = "0.99.0"
version = "0.201.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ef3b717afc67f848f412d4f02c127dd3e35a0eecd58c684580414df4fde01d3"
checksum = "84e5df6dba6c0d7fafc63a450f1738451ed7a0b52295d83e868218fa286bf708"
dependencies = [
"indexmap",
"url",
"bitflags",
"indexmap 2.2.6",
"semver",
]
[[package]]
@@ -620,6 +608,26 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "yansi"
version = "0.5.0"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fc79f4a1e39857fc00c3f662cbf2651c771f00e9c15fe2abc341806bd46bd71"
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
[[package]]
name = "zerocopy"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.58",
]

Binary file not shown.

View File

@@ -62,7 +62,6 @@ export fn sndGes(t: i32) -> f32 {
let phase = channelState!GesChannelState.Phase;
let inline pulseWidth = channelReg?1;
let phaseShift = (pulseWidth - 128) * 255;
let invPhaseInc = 1 as f32 / phaseInc as f32;
i = 0;
@@ -131,7 +130,7 @@ export fn sndGes(t: i32) -> f32 {
let phaseInc = (freq * (65536.0 / 44100.0)) as i32;
let phase = channelState!GesChannelState.Phase;
if modSrc > ch {
if modSrc < ch {
phase = phase - (phaseInc << 6);
}

View File

@@ -62,6 +62,7 @@ export fn cls(col: i32) {
textCursorX = 0;
textCursorY = 0;
outputChannel = 0;
textScale = 1;
memory.fill(120, col, 320*240);
}
@@ -447,6 +448,7 @@ global mut textCursorY = 0;
global mut textColor = 15;
global mut bgColor = 0;
global mut outputChannel = 0;
global mut textScale = 1;
export fn printChar(char: i32) {
loop chars {
@@ -458,6 +460,8 @@ export fn printChar(char: i32) {
global mut controlCodeLength = 0;
fn printSingleChar(char: i32) {
let charSize = 8 * textScale;
if outputChannel >= 2 & (char < 4 | char > 6) {
logChar(char);
return;
@@ -491,9 +495,9 @@ fn printSingleChar(char: i32) {
}
if char == 8 {
textCursorX = textCursorX - 8;
textCursorX = textCursorX - charSize;
if !outputChannel & textCursorX < 0 {
textCursorX = 320-8;
textCursorX = 320-charSize;
printSingleChar(11);
}
return;
@@ -503,34 +507,34 @@ fn printSingleChar(char: i32) {
if !outputChannel & textCursorX >= 320 {
printChar(0xd0a);
}
textCursorX = textCursorX + 8;
textCursorX = textCursorX + charSize;
return;
}
if char == 10 {
textCursorY = textCursorY + 8;
textCursorY = textCursorY + charSize;
if !outputChannel & textCursorY >= 240 {
textCursorY = 240 - 8;
textCursorY = 240 - charSize;
let i: i32;
loop scroll_copy {
i!120 = i!(120 + 320 * 8);
branch_if (i := i + 4) < 320 * (240 - 8): scroll_copy;
i!120 = (i + 320 * charSize)!120;
branch_if (i := i + 4) < 320 * (240 - charSize): scroll_copy;
}
rectangle(0 as f32, (240 - 8) as f32, 320 as f32, 8 as f32, bgColor);
rectangle(0 as f32, (240 - charSize) as f32, 320 as f32, charSize as f32, bgColor);
}
return;
}
if char == 11 {
textCursorY = textCursorY - 8;
textCursorY = textCursorY - charSize;
if !outputChannel & textCursorY < 0 {
textCursorY = 0;
let i = 320 * (240 - 8);
let i = 320 * (240 - charSize);
loop scroll_copy {
i!(116 + 320 * 8) = i!116;
(i + 320 * charSize)!116 = i!116;
branch_if (i := i - 4): scroll_copy;
}
rectangle(0 as f32, 0 as f32, 320 as f32, 8 as f32, bgColor);
rectangle(0 as f32, 0 as f32, 320 as f32, charSize as f32, bgColor);
}
return;
}
@@ -562,6 +566,12 @@ fn printSingleChar(char: i32) {
return;
}
if char == 30 {
let scale = 0x12d20?1;
textScale = select(scale > 0 & scale <= 16, scale, 1);
return;
}
if char == 31 {
textCursorX = 0x12d20?1 * (8 - outputChannel * 6);
textCursorY = 0x12d20?2 * (8 - outputChannel * 7);
@@ -584,7 +594,7 @@ data(0x12d00) {
1, 1, 1, 1, // 16-19,
1, 1, 1, 1, // 20-23,
1, 1, 1, 1, // 24-27,
1, 1, 1, 3 // 28-31
1, 1, 2, 3 // 28-31
)
}
@@ -593,26 +603,28 @@ fn drawChar(char: i32) {
printChar(0xd0a);
}
let charSize = 8 * textScale;
let y: i32;
loop rows {
let bits = (char * 8 + y)?0x13400;
let bits = (char * 8 + y / textScale)?0x13400;
let x = 0;
if outputChannel {
loop pixels {
if (bits := bits << 1) & 256 {
if (bits << (x / textScale)) & 128 {
setPixel(textCursorX + x, textCursorY + y, textColor);
}
branch_if (x := x + 1) < 8: pixels;
branch_if (x := x + 1) < charSize: pixels;
}
} else {
loop pixels {
setPixel(textCursorX + x, textCursorY + y, select((bits := bits << 1) & 256, textColor, bgColor));
branch_if (x := x + 1) < 8: pixels;
setPixel(textCursorX + x, textCursorY + y, select((bits << (x / textScale)) & 128, textColor, bgColor));
branch_if (x := x + 1) < charSize: pixels;
}
}
branch_if (y := y + 1) < 8: rows;
branch_if (y := y + 1) < charSize: rows;
}
textCursorX = textCursorX + 8;
textCursorX = textCursorX + charSize;
}
export fn printString(ptr: i32) {

View File

@@ -5,7 +5,7 @@ description = "Docs"
# Overview
MicroW8 loads WebAssembly modules with a maximum size of 256kb. You module needs to export
MicroW8 loads WebAssembly modules with a maximum size of 256kb. Your module needs to export
a function `fn upd()` which will be called once per frame.
After calling `upd` MicroW8 will display the 320x240 8bpp framebuffer located
at offset 120 in memory with the 32bpp palette located at 0x13000.
@@ -238,6 +238,13 @@ When printing characters only the foreground pixels are set, the background is "
Moving/printing past any border does not cause any special operation, the cursor just goes off-screen.
### Text scale
An integer text scale factor in the range 1x-16x can be set with control char 30. An attempt to
set a scale outside that range will reset the scale to 1x.
After startup and `cls` the scale is initialized to 1x.
### Control chars
Characters 0-31 are control characters and don't print by default. They take the next 0-2 following characters as parameters.
@@ -262,7 +269,8 @@ Avoid the reserved control chars, they are currently NOPs but their behavior can
| 15 | color | Set the text color |
| 16-23 | - | Reserved |
| 24 | - | Swap text/background colors |
| 25-30 | - | Reserved |
| 25-29 | - | Reserved |
| 30 | scale | Set text scale (1-16) |
| 31 | x, y | Set cursor position (*) |
(*) In graphics mode, the x coordinate is doubled when using control char 31 to be able to cover the whole screen with one byte.
@@ -271,7 +279,7 @@ Avoid the reserved control chars, they are currently NOPs but their behavior can
Control code 6 switches all text output (except codes 4 and 5 to switch output back to the screen) to the console. Where exactly this ends
up (if at all) is an implementation detail of the runtimes. The native dev-runtime writes the debug output to `stdout`, the web runtime to
the debug console using `console.log`. Both implementation buffer the output until they encounter a newline character (10) in the output stream.
the debug console using `console.log`. Both implementations buffer the output until they encounter a newline character (10) in the output stream.
There may be future runtimes that ignore the debug output completely.
@@ -626,4 +634,4 @@ Pressing F9 opens a download dialog with a screenshot.
## Devkit mode
Append `#devkit` to the web runtime url in order to switch to devkit mode. In devkit mode, standard web assembly modules
are loaded bypassing the loader, removing all size restrictions. At the same time, the memory limit is increased to 1GB.
are loaded bypassing the loader, removing all size restrictions. At the same time, the memory limit is increased to 1GB.

View File

@@ -16,16 +16,14 @@ pub struct FileWatcher {
impl FileWatcher {
pub fn new() -> Result<FileWatcher> {
let (tx, rx) = mpsc::channel();
let debouncer = new_debouncer(Duration::from_millis(100), None, move |res| match res {
let debouncer = new_debouncer(Duration::from_millis(100), 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}");
}
Err(err) => {
eprintln!("Error watching for file changes: {err}");
}
})?;
Ok(FileWatcher {

View File

@@ -7,7 +7,7 @@ use cpal::traits::*;
use rubato::Resampler;
use uw8_window::{Window, WindowConfig};
use wasmtime::{
Engine, GlobalType, Memory, MemoryType, Module, Mutability, Store, TypedFunc, ValType,
Engine, Func, GlobalType, Memory, MemoryType, Module, Mutability, Store, TypedFunc, ValType,
};
pub struct MicroW8 {
@@ -90,7 +90,7 @@ impl super::Runtime for MicroW8 {
let memory = wasmtime::Memory::new(&mut store, MemoryType::new(4, Some(4)))?;
let mut linker = wasmtime::Linker::new(&self.engine);
linker.define("env", "memory", memory)?;
linker.define(&store, "env", "memory", memory)?;
let loader_instance = linker.instantiate(&mut store, &self.loader_module)?;
let load_uw8 = loader_instance.get_typed_func::<i32, i32>(&mut store, "load_uw8")?;
@@ -181,12 +181,10 @@ impl super::Runtime for MicroW8 {
if let Some(mut instance) = self.instance.take() {
let time = (now - instance.start_time).as_millis() as i32;
let next_frame = {
let frame = (time as u32 as u64 * 6 / 100) as u32;
let cur_offset = (time as u32).wrapping_sub((frame as u64 * 100 / 6) as u32);
let next_time =
((frame as u64 + 1) * 100 / 6 + cur_offset.max(1).min(4) as u64) as u32;
let offset = next_time.wrapping_sub(time as u32);
now + Duration::from_millis(offset as u64)
let offset = ((time as u32 as i64 * 6) % 100 - 50) / 6;
let max = now + Duration::from_millis(17);
let next_center = now + Duration::from_millis((16 - offset) as u64);
next_center.min(max)
};
{
@@ -257,15 +255,12 @@ fn add_native_functions(
}
})?;
for i in 0..16 {
linker.define(
"env",
&format!("g_reserved{}", i),
wasmtime::Global::new(
&mut *store,
GlobalType::new(ValType::I32, Mutability::Const),
0.into(),
)?,
let global = wasmtime::Global::new(
&mut *store,
GlobalType::new(ValType::I32, Mutability::Const),
0.into(),
)?;
linker.define(&store, "env", &format!("g_reserved{}", i), global)?;
}
Ok(())
@@ -278,14 +273,18 @@ fn instantiate_platform(
) -> Result<wasmtime::Instance> {
let platform_instance = linker.instantiate(&mut *store, &platform_module)?;
for export in platform_instance.exports(&mut *store) {
linker.define(
"env",
export.name(),
export
.into_func()
.expect("platform surely only exports functions"),
)?;
let exports: Vec<(String, Func)> = platform_instance
.exports(&mut *store)
.map(|e| {
(
e.name().to_owned(),
e.into_func()
.expect("platform surely only exports functions"),
)
})
.collect();
for (name, func) in exports {
linker.define(&store, "env", &name, func)?;
}
Ok(platform_instance)
@@ -312,7 +311,7 @@ fn init_sound(
let memory = wasmtime::Memory::new(&mut store, MemoryType::new(4, Some(4)))?;
let mut linker = wasmtime::Linker::new(engine);
linker.define("env", "memory", memory)?;
linker.define(&store, "env", "memory", memory)?;
add_native_functions(&mut linker, &mut store)?;
let platform_instance = instantiate_platform(&mut linker, &mut store, platform_module)?;
@@ -329,23 +328,26 @@ fn init_sound(
let mut configs: Vec<_> = device
.supported_output_configs()?
.filter(|config| {
config.channels() == 2 && config.sample_format() == cpal::SampleFormat::F32
config.channels() == 2
&& (config.sample_format() == cpal::SampleFormat::F32
|| config.sample_format() == cpal::SampleFormat::I16)
})
.collect();
configs.sort_by_key(|config| {
let rate = 44100
.max(config.min_sample_rate().0)
.min(config.max_sample_rate().0);
if rate >= 44100 {
let prio = if rate >= 44100 {
rate - 44100
} else {
(44100 - rate) * 1000
}
};
prio + (config.sample_format() == cpal::SampleFormat::I16) as u32
});
let config = configs
.into_iter()
.next()
.ok_or_else(|| anyhow!("Could not find float output config"))?;
.ok_or_else(|| anyhow!("Could not find float or 16bit signed output config"))?;
let sample_rate = cpal::SampleRate(44100)
.max(config.min_sample_rate())
.min(config.max_sample_rate());
@@ -356,6 +358,7 @@ fn init_sound(
cpal::BufferSize::Fixed(256.max(min).min(max))
}
};
let sample_format = config.sample_format();
let config = cpal::StreamConfig {
buffer_size,
..config.config()
@@ -375,8 +378,8 @@ fn init_sound(
None
} else {
let rs = rubato::FftFixedIn::new(44100, sample_rate, 128, 1, 2)?;
let input_buffers = rs.input_buffer_allocate();
let output_buffers = rs.output_buffer_allocate();
let input_buffers = rs.input_buffer_allocate(true);
let output_buffers = rs.output_buffer_allocate(true);
Some(Resampler {
resampler: rs,
input_buffers,
@@ -388,96 +391,130 @@ fn init_sound(
let mut sample_index = 0;
let mut pending_updates: Vec<RegisterUpdate> = Vec::with_capacity(30);
let mut current_time = 0;
let stream = device.build_output_stream(
&config,
move |mut outer_buffer: &mut [f32], _| {
let mut first_update = true;
while let Ok(update) = rx.try_recv() {
if first_update {
current_time += update.time.wrapping_sub(current_time) / 8;
first_update = false;
}
pending_updates.push(update);
let mut callback = move |mut outer_buffer: &mut [f32], _: &_| {
let mut first_update = true;
while let Ok(update) = rx.try_recv() {
if first_update {
current_time += update.time.wrapping_sub(current_time) / 8;
first_update = false;
}
pending_updates.push(update);
}
while !outer_buffer.is_empty() {
store.set_epoch_deadline(30);
while pending_updates
.first()
.into_iter()
.any(|u| u.time.wrapping_sub(current_time) <= 0)
{
let update = pending_updates.remove(0);
memory.write(&mut store, 80, &update.data).unwrap();
}
while !outer_buffer.is_empty() {
store.set_epoch_deadline(30);
while pending_updates
.first()
.into_iter()
.any(|u| u.time.wrapping_sub(current_time) <= 0)
{
let update = pending_updates.remove(0);
memory.write(&mut store, 80, &update.data).unwrap();
}
let duration = if let Some(update) = pending_updates.first() {
((update.time.wrapping_sub(current_time) as usize) * sample_rate + 999) / 1000
} else {
outer_buffer.len()
};
let step_size = (duration.max(64) * 2).min(outer_buffer.len());
let duration = if let Some(update) = pending_updates.first() {
((update.time.wrapping_sub(current_time) as usize) * sample_rate + 999) / 1000
let mut buffer = &mut outer_buffer[..step_size];
{
let mem = memory.data_mut(&mut store);
mem[64..68].copy_from_slice(&current_time.to_le_bytes());
}
fn clamp_sample(s: f32) -> f32 {
if s.is_nan() {
0.0
} else {
outer_buffer.len()
};
let step_size = (duration.max(64) * 2).min(outer_buffer.len());
let mut buffer = &mut outer_buffer[..step_size];
{
let mem = memory.data_mut(&mut store);
mem[64..68].copy_from_slice(&current_time.to_le_bytes());
s.max(-1.0).min(1.0)
}
}
if let Some(ref mut resampler) = resampler {
while !buffer.is_empty() {
let copy_size = resampler.output_buffers[0]
.len()
.saturating_sub(resampler.output_index)
.min(buffer.len() / 2);
if copy_size == 0 {
resampler.input_buffers[0].clear();
resampler.input_buffers[1].clear();
for _ in 0..resampler.resampler.input_frames_next() {
resampler.input_buffers[0]
.push(snd.call(&mut store, (sample_index,)).unwrap_or(0.0));
resampler.input_buffers[1]
.push(snd.call(&mut store, (sample_index + 1,)).unwrap_or(0.0));
sample_index = sample_index.wrapping_add(2);
}
resampler
.resampler
.process_into_buffer(
&resampler.input_buffers,
&mut resampler.output_buffers,
None,
)
.unwrap();
resampler.output_index = 0;
} else {
for i in 0..copy_size {
buffer[i * 2] =
resampler.output_buffers[0][resampler.output_index + i];
buffer[i * 2 + 1] =
resampler.output_buffers[1][resampler.output_index + i];
}
resampler.output_index += copy_size;
buffer = &mut buffer[copy_size * 2..];
if let Some(ref mut resampler) = resampler {
while !buffer.is_empty() {
let copy_size = resampler.output_buffers[0]
.len()
.saturating_sub(resampler.output_index)
.min(buffer.len() / 2);
if copy_size == 0 {
resampler.input_buffers[0].clear();
resampler.input_buffers[1].clear();
for _ in 0..resampler.resampler.input_frames_next() {
resampler.input_buffers[0].push(clamp_sample(
snd.call(&mut store, (sample_index,)).unwrap_or(0.0),
));
resampler.input_buffers[1].push(clamp_sample(
snd.call(&mut store, (sample_index + 1,)).unwrap_or(0.0),
));
sample_index = sample_index.wrapping_add(2);
}
}
} else {
for v in buffer {
*v = snd.call(&mut store, (sample_index,)).unwrap_or(0.0);
sample_index = sample_index.wrapping_add(1);
resampler
.resampler
.process_into_buffer(
&resampler.input_buffers,
&mut resampler.output_buffers,
None,
)
.unwrap();
resampler.output_index = 0;
} else {
for i in 0..copy_size {
buffer[i * 2] = resampler.output_buffers[0][resampler.output_index + i];
buffer[i * 2 + 1] =
resampler.output_buffers[1][resampler.output_index + i];
}
resampler.output_index += copy_size;
buffer = &mut buffer[copy_size * 2..];
}
}
outer_buffer = &mut outer_buffer[step_size..];
current_time =
current_time.wrapping_add((step_size * 500 / sample_rate).max(1) as i32);
} else {
for v in buffer {
*v = clamp_sample(snd.call(&mut store, (sample_index,)).unwrap_or(0.0));
sample_index = sample_index.wrapping_add(1);
}
}
},
move |err| {
dbg!(err);
},
)?;
outer_buffer = &mut outer_buffer[step_size..];
current_time = current_time.wrapping_add((step_size * 500 / sample_rate).max(1) as i32);
}
};
let stream = if sample_format == cpal::SampleFormat::F32 {
device.build_output_stream(
&config,
callback,
move |err| {
dbg!(err);
},
None,
)?
} else {
device.build_output_stream(
&config,
move |mut buffer: &mut [i16], info| {
let mut float_buffer = [0f32; 256];
while !buffer.is_empty() {
let step_size = buffer.len().min(float_buffer.len());
let step_buffer = &mut float_buffer[..step_size];
callback(step_buffer, info);
for (dest, src) in buffer.iter_mut().take(step_size).zip(step_buffer.iter()) {
*dest = (src.max(-1.0).min(1.0) * 32767.0) as i16;
}
buffer = &mut buffer[step_size..];
}
},
move |err| {
dbg!(err);
},
None,
)?
};
Ok(Uw8Sound { stream, tx })
}

1
todo.txt Normal file
View File

@@ -0,0 +1 @@
* add support for 16bit sound (not just float)

268
uw8-tool/Cargo.lock generated
View File

@@ -4,21 +4,27 @@ version = 3
[[package]]
name = "anyhow"
version = "1.0.52"
version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3"
checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247"
[[package]]
name = "autocfg"
version = "1.0.1"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
[[package]]
name = "bitflags"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "cc"
version = "1.0.72"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41"
[[package]]
name = "cdivsufsort"
@@ -30,39 +36,42 @@ dependencies = [
"sacabase",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crossbeam-channel"
version = "0.5.1"
version = "0.5.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.5"
version = "0.8.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [
"cfg-if",
"lazy_static",
]
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
[[package]]
name = "form_urlencoded"
version = "1.1.0"
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "fallible-iterator"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]]
name = "gimli"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d"
dependencies = [
"percent-encoding",
"fallible-iterator",
"indexmap 1.9.3",
"stable_deref_trait",
]
[[package]]
@@ -71,6 +80,12 @@ version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
name = "heck"
version = "0.3.3"
@@ -87,31 +102,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
[[package]]
name = "idna"
version = "0.3.0"
name = "indexmap"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"unicode-bidi",
"unicode-normalization",
"autocfg",
"hashbrown 0.12.3",
]
[[package]]
name = "indexmap"
version = "1.9.2"
version = "2.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
dependencies = [
"autocfg",
"hashbrown",
"equivalent",
"hashbrown 0.14.3",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "leb128"
version = "0.2.5"
@@ -126,46 +135,36 @@ checksum = "478ee9e62aaeaf5b140bd4138753d1f109765488581444218d3ddda43234f3e8"
[[package]]
name = "libc"
version = "0.2.112"
version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "log"
version = "0.4.14"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "num-traits"
version = "0.2.14"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
dependencies = [
"autocfg",
]
[[package]]
name = "pbr"
version = "1.0.4"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff5751d87f7c00ae6403eb1fcbba229b9c76c9a30de8c1cf87182177b168cea2"
checksum = "ed5827dfa0d69b6c92493d6c38e633bbaa5937c153d0d7c28bf12313f8c6d514"
dependencies = [
"crossbeam-channel",
"libc",
"time",
"winapi",
]
[[package]]
name = "percent-encoding"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]]
name = "pico-args"
version = "0.5.0"
@@ -174,18 +173,18 @@ checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315"
[[package]]
name = "proc-macro2"
version = "1.0.36"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e"
dependencies = [
"unicode-xid",
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.14"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47aa80447ce4daf1717500037052af176af5d38cc3e571d9ec1c7353fc10c87d"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
dependencies = [
"proc-macro2",
]
@@ -200,88 +199,70 @@ dependencies = [
]
[[package]]
name = "syn"
version = "1.0.84"
name = "semver"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ecb2e6da8ee5eb9a61068762a32fa9619cc591ceb055b3687f4cd4051ec2e06b"
checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "thiserror"
version = "1.0.38"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.38"
version = "1.0.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.58",
]
[[package]]
name = "time"
version = "0.1.44"
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
"libc",
"wasi",
"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",
]
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-segmentation"
version = "1.8.0"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
[[package]]
name = "upkr"
@@ -294,17 +275,6 @@ dependencies = [
"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]]
name = "uw8-tool"
version = "0.1.0"
@@ -314,22 +284,24 @@ dependencies = [
"pico-args",
"upkr",
"walrus",
"wasm-encoder",
"wasmparser 0.99.0",
"wasm-encoder 0.201.0",
"wasmparser 0.201.0",
]
[[package]]
name = "walrus"
version = "0.19.0"
version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eb08e48cde54c05f363d984bb54ce374f49e242def9468d2e1b6c2372d291f8"
checksum = "2c03529cd0c4400a2449f640d2f27cd1b48c3065226d15e26d98e4429ab0adb7"
dependencies = [
"anyhow",
"gimli",
"id-arena",
"leb128",
"log",
"walrus-macro",
"wasmparser 0.77.0",
"wasm-encoder 0.29.0",
"wasmparser 0.80.2",
]
[[package]]
@@ -341,38 +313,42 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
"syn 1.0.109",
]
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
name = "wasm-encoder"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
checksum = "18c41dbd92eaebf3612a39be316540b8377c871cb9bde6b064af962984912881"
dependencies = [
"leb128",
]
[[package]]
name = "wasm-encoder"
version = "0.22.0"
version = "0.201.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef126be0e14bdf355ac1a8b41afc89195289e5c7179f80118e3abddb472f0810"
checksum = "b9c7d2731df60006819b013f64ccc2019691deccf6e11a1804bc850cd6748f1a"
dependencies = [
"leb128",
]
[[package]]
name = "wasmparser"
version = "0.77.0"
version = "0.80.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b35c86d22e720a07d954ebbed772d01180501afe7d03d464f413bb5f8914a8d6"
checksum = "449167e2832691a1bff24cde28d2804e90e09586a448c8e76984792c44334a6b"
[[package]]
name = "wasmparser"
version = "0.99.0"
version = "0.201.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ef3b717afc67f848f412d4f02c127dd3e35a0eecd58c684580414df4fde01d3"
checksum = "84e5df6dba6c0d7fafc63a450f1738451ed7a0b52295d83e868218fa286bf708"
dependencies = [
"indexmap",
"url",
"bitflags",
"indexmap 2.2.6",
"semver",
]
[[package]]

View File

@@ -6,10 +6,10 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
wasmparser = "0.99"
wasm-encoder = "0.22"
walrus = "0.19"
wasmparser = "0.201"
wasm-encoder = "0.201"
walrus = { version = "0.20.3", default-features = false }
anyhow = "1"
pico-args = "0.5"
upkr = { git = "https://github.com/exoticorn/upkr.git", rev = "080db40d0088bbee2bdf3c5c75288ac7853d6b7a" }
pbr = "1"
pbr = "1"

View File

@@ -8,7 +8,7 @@ pub fn filter_exports(in_path: &Path, out_path: &Path) -> Result<()> {
.exports
.iter()
.filter_map(|export| match export.name.as_str() {
"upd" | "snd" | "start" => None,
"start" | "upd" | "snd" => None,
_ => Some(export.id()),
})
.collect();

View File

@@ -490,7 +490,6 @@ impl<'a> ParsedModule<'a> {
element_section.active(
None,
&wasm_encoder::ConstExpr::i32_const(element.start_index as i32),
ValType::FuncRef,
wasm_encoder::Elements::Functions(&functions),
);
}
@@ -536,15 +535,18 @@ fn copy_section(module: &mut wasm_encoder::Module, data: &[u8]) -> Result<()> {
fn read_type_section(reader: TypeSectionReader) -> Result<Vec<base_module::FunctionType>> {
let mut function_types = vec![];
for type_def in reader {
match type_def? {
wasmparser::Type::Func(fnc) => {
if fnc.results().len() > 1 {
bail!("Multi-value not supported");
for rec_group in reader {
for sub_type in rec_group?.into_types() {
match sub_type.composite_type {
wasmparser::CompositeType::Func(fnc) => {
if fnc.results().len() > 1 {
bail!("Multi-value not supported");
}
let params = to_val_type_vec(fnc.params())?;
let result = to_val_type_vec(fnc.results())?.into_iter().next();
function_types.push(FunctionType { params, result });
}
let params = to_val_type_vec(fnc.params())?;
let result = to_val_type_vec(fnc.results())?.into_iter().next();
function_types.push(FunctionType { params, result });
_ => bail!("Only function types are supported"),
}
}
}
@@ -557,8 +559,8 @@ fn validate_table_section(reader: TableSectionReader) -> Result<()> {
bail!("Only up to one table supported");
}
let type_ = reader.into_iter().next().unwrap()?;
if type_.element_type != wasmparser::ValType::FuncRef {
let table = reader.into_iter().next().unwrap()?;
if !table.ty.element_type.is_func_ref() {
bail!("Only one funcref table is supported");
}
@@ -647,9 +649,12 @@ impl Element {
wasmparser::ElementItems::Functions(funcs_reader) => {
let start_index = if let wasmparser::ElementKind::Active {
offset_expr,
table_index: 0,
table_index,
} = element.kind
{
if table_index.map(|i| i > 0).unwrap_or(false) {
bail!("Only function table with index 0 is supported");
}
let mut init_reader = offset_expr.get_operators_reader();
if let wasmparser::Operator::I32Const { value: start_index } =
init_reader.read()?

2001
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
[dependencies]
winit = "0.27.5"
env_logger = "0.10"
winit = "0.29.15"
env_logger = "0.11.3"
log = "0.4"
pico-args = "0.5"
wgpu = "0.15"
pollster = "0.2.5"
bytemuck = { version = "1.13", features = [ "derive" ] }
wgpu = "0.19.3"
pollster = "0.3.0"
bytemuck = { version = "1.15", features = [ "derive" ] }
anyhow = "1"
minifb = { version = "0.23.0", default-features = false, features = ["x11"] }
minifb = { version = "0.25.0", default-features = false, features = ["x11"] }
winapi = { version = "0.3.9", features = [ "timeapi" ] }

View File

@@ -30,8 +30,8 @@ fn row_factor(offset: f32) -> f32 {
}
fn col_factor(offset: f32) -> f32 {
let offset = max(0.0, abs(offset) - 0.4);
return 1.0 / (1.0 + offset * offset * 16.0);
let o = max(0.0, abs(offset) - 0.4);
return 1.0 / (1.0 + o * o * 16.0);
}
fn sample_screen(tex_coords: vec2<f32>) -> vec4<f32> {

View File

@@ -1,16 +1,16 @@
use crate::{Input, WindowConfig, WindowImpl};
use anyhow::{anyhow, Result};
use std::{num::NonZeroU32, time::Instant};
use std::{sync::Arc, time::Instant};
use winit::{
dpi::PhysicalSize,
event::{Event, VirtualKeyCode, WindowEvent},
event::{Event, WindowEvent},
event_loop::{ControlFlow, EventLoop},
keyboard::{Key, KeyCode, NamedKey, PhysicalKey},
platform::pump_events::{EventLoopExtPumpEvents, PumpStatus},
window::{Fullscreen, WindowBuilder},
};
use winit::platform::run_return::EventLoopExtRunReturn;
mod crt;
mod fast_crt;
mod square;
@@ -21,7 +21,7 @@ use square::SquareFilter;
pub struct Window {
_instance: wgpu::Instance,
surface: wgpu::Surface,
surface: wgpu::Surface<'static>,
_adapter: wgpu::Adapter,
device: wgpu::Device,
queue: wgpu::Queue,
@@ -29,7 +29,7 @@ pub struct Window {
surface_config: wgpu::SurfaceConfiguration,
filter: Box<dyn Filter>,
event_loop: EventLoop<()>,
window: winit::window::Window,
window: Arc<winit::window::Window>,
gamepads: [u8; 4],
next_frame: Instant,
is_fullscreen: bool,
@@ -39,9 +39,12 @@ pub struct Window {
impl Window {
pub fn new(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()
.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_title("MicroW8")
.with_fullscreen(if window_config.fullscreen {
@@ -53,8 +56,10 @@ impl Window {
window.set_cursor_visible(false);
let window = Arc::new(window);
let instance = wgpu::Instance::new(Default::default());
let surface = unsafe { instance.create_surface(&window) }?;
let surface = instance.create_surface(window.clone())?;
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::LowPower,
@@ -72,7 +77,13 @@ impl Window {
let surface_config = wgpu::SurfaceConfiguration {
present_mode: wgpu::PresentMode::AutoNoVsync,
..surface.get_default_config(&adapter, window.inner_size().width, window.inner_size().height).expect("Surface incompatible with adapter")
..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(
@@ -110,88 +121,93 @@ impl Window {
impl WindowImpl for Window {
fn begin_frame(&mut self) -> Input {
let mut reset = false;
self.event_loop.run_return(|event, _, control_flow| {
*control_flow = ControlFlow::WaitUntil(self.next_frame);
let mut new_filter = None;
match event {
Event::WindowEvent { event, .. } => match event {
WindowEvent::Resized(new_size) => {
self.surface_config.width = new_size.width;
self.surface_config.height = new_size.height;
self.surface.configure(&self.device, &self.surface_config);
self.filter.resize(&self.queue, new_size);
}
WindowEvent::CloseRequested => {
self.is_open = false;
*control_flow = ControlFlow::Exit;
}
WindowEvent::KeyboardInput { input, .. } => {
fn gamepad_button(input: &winit::event::KeyboardInput) -> u8 {
match input.scancode {
44 => 16,
45 => 32,
30 => 64,
31 => 128,
_ => match input.virtual_keycode {
Some(VirtualKeyCode::Up) => 1,
Some(VirtualKeyCode::Down) => 2,
Some(VirtualKeyCode::Left) => 4,
Some(VirtualKeyCode::Right) => 8,
_ => 0,
},
}
self.event_loop
.set_control_flow(ControlFlow::WaitUntil(self.next_frame));
while self.is_open {
let timeout = self.next_frame.saturating_duration_since(Instant::now());
let status = self.event_loop.pump_events(Some(timeout), |event, elwt| {
let mut new_filter = None;
match event {
Event::WindowEvent { event, .. } => match event {
WindowEvent::Resized(new_size) => {
self.surface_config.width = new_size.width;
self.surface_config.height = new_size.height;
self.surface.configure(&self.device, &self.surface_config);
self.filter.resize(&self.queue, new_size);
}
if input.state == winit::event::ElementState::Pressed {
match input.virtual_keycode {
Some(VirtualKeyCode::Escape) => {
self.is_open = false;
*control_flow = ControlFlow::Exit;
WindowEvent::CloseRequested => {
elwt.exit();
}
WindowEvent::KeyboardInput { event, .. } => {
fn gamepad_button(input: &winit::event::KeyEvent) -> u8 {
match input.physical_key {
PhysicalKey::Code(KeyCode::KeyZ) => 16,
PhysicalKey::Code(KeyCode::KeyX) => 32,
PhysicalKey::Code(KeyCode::KeyA) => 64,
PhysicalKey::Code(KeyCode::KeyS) => 128,
_ => match input.logical_key {
Key::Named(NamedKey::ArrowUp) => 1,
Key::Named(NamedKey::ArrowDown) => 2,
Key::Named(NamedKey::ArrowLeft) => 4,
Key::Named(NamedKey::ArrowRight) => 8,
_ => 0,
},
}
Some(VirtualKeyCode::F) => {
let fullscreen = if self.window.fullscreen().is_some() {
None
} else {
Some(Fullscreen::Borderless(None))
};
self.is_fullscreen = fullscreen.is_some();
self.window.set_fullscreen(fullscreen);
}
Some(VirtualKeyCode::R) => reset = true,
Some(VirtualKeyCode::Key1) => new_filter = Some(1),
Some(VirtualKeyCode::Key2) => new_filter = Some(2),
Some(VirtualKeyCode::Key3) => new_filter = Some(3),
Some(VirtualKeyCode::Key4) => new_filter = Some(4),
Some(VirtualKeyCode::Key5) => new_filter = Some(5),
_ => (),
}
if event.state == winit::event::ElementState::Pressed {
match event.logical_key {
Key::Named(NamedKey::Escape) => {
elwt.exit();
}
Key::Character(ref c) => match c.as_str() {
"f" => {
let fullscreen = if self.window.fullscreen().is_some() {
None
} else {
Some(Fullscreen::Borderless(None))
};
self.is_fullscreen = fullscreen.is_some();
self.window.set_fullscreen(fullscreen);
}
"r" => reset = true,
"1" => new_filter = Some(1),
"2" => new_filter = Some(2),
"3" => new_filter = Some(3),
"4" => new_filter = Some(4),
"5" => new_filter = Some(5),
_ => (),
},
_ => (),
}
self.gamepads[0] |= gamepad_button(&input);
} else {
self.gamepads[0] &= !gamepad_button(&input);
self.gamepads[0] |= gamepad_button(&event);
} else {
self.gamepads[0] &= !gamepad_button(&event);
}
}
}
_ => (),
},
_ => (),
},
Event::RedrawEventsCleared => {
if Instant::now() >= self.next_frame
// workaround needed on Wayland until the next winit release
&& self.window.fullscreen().is_some() == self.is_fullscreen
{
*control_flow = ControlFlow::Exit
}
}
if let Some(new_filter) = new_filter {
self.filter = create_filter(
&self.device,
&self.palette_screen_mode.screen_view,
self.window.inner_size(),
self.surface_config.format,
new_filter,
);
}
});
match status {
PumpStatus::Exit(_) => self.is_open = false,
_ => (),
}
if let Some(new_filter) = new_filter {
self.filter = create_filter(
&self.device,
&self.palette_screen_mode.screen_view,
self.window.inner_size(),
self.surface_config.format,
new_filter,
);
if Instant::now() >= self.next_frame {
break;
}
});
}
Input {
gamepads: self.gamepads,
reset,
@@ -227,10 +243,12 @@ impl WindowImpl for Window {
b: 0.0,
a: 1.0,
}),
store: true,
store: wgpu::StoreOp::Store,
},
})],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
});
self.filter.render(&mut render_pass);
@@ -354,7 +372,7 @@ impl PaletteScreenMode {
format: wgpu::TextureFormat::R8Uint,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
label: None,
view_formats: &[]
view_formats: &[],
});
let palette_texture = device.create_texture(&wgpu::TextureDescriptor {
@@ -369,7 +387,7 @@ impl PaletteScreenMode {
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
label: None,
view_formats: &[]
view_formats: &[],
});
let screen_texture = device.create_texture(&wgpu::TextureDescriptor {
@@ -384,7 +402,7 @@ impl PaletteScreenMode {
format: wgpu::TextureFormat::Rgba8UnormSrgb,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::RENDER_ATTACHMENT,
label: None,
view_formats: &[]
view_formats: &[],
});
let framebuffer_texture_view =
@@ -491,7 +509,7 @@ impl PaletteScreenMode {
&bytemuck::cast_slice(pixels),
wgpu::ImageDataLayout {
offset: 0,
bytes_per_row: NonZeroU32::new(320),
bytes_per_row: Some(320),
rows_per_image: None,
},
wgpu::Extent3d {
@@ -513,7 +531,7 @@ impl PaletteScreenMode {
&bytemuck::cast_slice(palette),
wgpu::ImageDataLayout {
offset: 0,
bytes_per_row: NonZeroU32::new(256 * 4),
bytes_per_row: Some(256 * 4),
rows_per_image: None,
},
wgpu::Extent3d {
@@ -532,10 +550,12 @@ impl PaletteScreenMode {
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Load,
store: true,
store: wgpu::StoreOp::Store,
},
})],
depth_stencil_attachment: None,
timestamp_writes: None,
occlusion_query_set: None,
});
render_pass.set_pipeline(&self.pipeline);

View File

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

View File

@@ -274,7 +274,7 @@ export default function MicroW8(screen, config = {}) {
try {
let restart = false;
let nextFrame = 0;
let thisFrame;
if (!isPaused) {
let gamepads = navigator.getGamepads();
let gamepad = 0;
@@ -321,12 +321,13 @@ export default function MicroW8(screen, config = {}) {
}
canvasCtx.putImageData(imageData, 0, 0);
let thisFrame = Math.floor(time * 6 / 100);
let timeOffset = time - thisFrame * 100 / 6;
nextFrame = Math.ceil(startTime + (thisFrame + 1) * 100 / 6 + Math.min(4, timeOffset));
let timeOffset = ((time * 6) % 100 - 50) / 6;
thisFrame = startTime + time - timeOffset / 8;
} else {
thisFrame = Date.now();
}
let now = Date.now();
nextFrame = Math.max(nextFrame, now);
let nextFrame = Math.max(thisFrame + timePerFrame, now);
if (restart) {
runModule(currentData);