mirror of
https://github.com/exoticorn/microw8.git
synced 2026-01-20 11:16:42 +01:00
move native microw8 code into object to prepare for file watch
This commit is contained in:
227
Cargo.lock
generated
227
Cargo.lock
generated
@@ -32,7 +32,7 @@ version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -49,7 +49,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"winapi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -385,7 +385,7 @@ checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"winapi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -443,7 +443,7 @@ checksum = "fa68f2fb9cae9d37c9b2b3584aba698a2e97f72d7aef7b9f7aa71d8b54ce46fe"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
"winapi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -481,7 +481,7 @@ dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"winapi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -496,6 +496,41 @@ dependencies = [
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fsevent"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"fsevent-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fsevent-sys"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-zircon"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"fuchsia-zircon-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fuchsia-zircon-sys"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.4"
|
||||
@@ -575,6 +610,35 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inotify"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"inotify-sys",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inotify-sys"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iovec"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.1"
|
||||
@@ -602,6 +666,16 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
dependencies = [
|
||||
"winapi 0.2.8",
|
||||
"winapi-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
@@ -633,7 +707,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0cf036d15402bea3c5d4de17b3fce76b3e4a56ebc1f577be0e7a72f7c607cf0"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"winapi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -682,7 +756,7 @@ dependencies = [
|
||||
"wayland-client",
|
||||
"wayland-cursor",
|
||||
"wayland-protocols",
|
||||
"winapi",
|
||||
"winapi 0.3.9",
|
||||
"x11-dl",
|
||||
"xkb",
|
||||
"xkbcommon-sys",
|
||||
@@ -704,12 +778,66 @@ dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.6.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"fuchsia-zircon",
|
||||
"fuchsia-zircon-sys",
|
||||
"iovec",
|
||||
"kernel32-sys",
|
||||
"libc",
|
||||
"log",
|
||||
"miow",
|
||||
"net2",
|
||||
"slab",
|
||||
"winapi 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio-extras"
|
||||
version = "2.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19"
|
||||
dependencies = [
|
||||
"lazycell",
|
||||
"log",
|
||||
"mio",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miow"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
|
||||
dependencies = [
|
||||
"kernel32-sys",
|
||||
"net2",
|
||||
"winapi 0.2.8",
|
||||
"ws2_32-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "more-asserts"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238"
|
||||
|
||||
[[package]]
|
||||
name = "net2"
|
||||
version = "0.2.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"libc",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.20.2"
|
||||
@@ -744,6 +872,24 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify"
|
||||
version = "4.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae03c8c853dba7bfd23e571ff0cff7bc9dceb40a4cd684cd1681824183f45257"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"filetime",
|
||||
"fsevent",
|
||||
"fsevent-sys",
|
||||
"inotify",
|
||||
"libc",
|
||||
"mio",
|
||||
"mio-extras",
|
||||
"walkdir",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.0"
|
||||
@@ -988,7 +1134,7 @@ dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
"mach",
|
||||
"winapi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -997,7 +1143,7 @@ version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1012,6 +1158,15 @@ version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
@@ -1085,6 +1240,12 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.7.0"
|
||||
@@ -1142,7 +1303,7 @@ dependencies = [
|
||||
"rand",
|
||||
"redox_syscall",
|
||||
"remove_dir_all",
|
||||
"winapi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1227,6 +1388,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"minifb",
|
||||
"notify",
|
||||
"wasmtime",
|
||||
]
|
||||
|
||||
@@ -1248,6 +1410,17 @@ version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
|
||||
dependencies = [
|
||||
"same-file",
|
||||
"winapi 0.3.9",
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.2+wasi-snapshot-preview1"
|
||||
@@ -1345,7 +1518,7 @@ dependencies = [
|
||||
"wasmtime-jit",
|
||||
"wasmtime-runtime",
|
||||
"wat",
|
||||
"winapi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1365,7 +1538,7 @@ dependencies = [
|
||||
"serde",
|
||||
"sha2",
|
||||
"toml",
|
||||
"winapi",
|
||||
"winapi 0.3.9",
|
||||
"zstd",
|
||||
]
|
||||
|
||||
@@ -1419,7 +1592,7 @@ checksum = "8779dd78755a248512233df4f6eaa6ba075c41bea2085fec750ed2926897bf95"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"winapi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1444,7 +1617,7 @@ dependencies = [
|
||||
"wasmparser",
|
||||
"wasmtime-environ",
|
||||
"wasmtime-runtime",
|
||||
"winapi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1469,7 +1642,7 @@ dependencies = [
|
||||
"thiserror",
|
||||
"wasmtime-environ",
|
||||
"wasmtime-fiber",
|
||||
"winapi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1591,6 +1764,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
@@ -1601,6 +1780,12 @@ dependencies = [
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-build"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
@@ -1613,7 +1798,7 @@ version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1622,6 +1807,16 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "ws2_32-sys"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
|
||||
dependencies = [
|
||||
"winapi 0.2.8",
|
||||
"winapi-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11-dl"
|
||||
version = "2.19.1"
|
||||
|
||||
@@ -9,3 +9,4 @@ edition = "2021"
|
||||
wasmtime = "0.30"
|
||||
anyhow = "1"
|
||||
minifb = "0.19"
|
||||
notify = "4"
|
||||
@@ -113,4 +113,5 @@ start fn setup() {
|
||||
(i*4)!(120+320*256) = i * 0x10101;
|
||||
branch_if (i := i + 1) < 256: colors
|
||||
}
|
||||
randomSeed(random());
|
||||
}
|
||||
129
src/main.rs
129
src/main.rs
@@ -1,136 +1,19 @@
|
||||
use std::io::prelude::*;
|
||||
use std::{fs::File, time::Instant};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use minifb::{Key, Window, WindowOptions};
|
||||
use wasmtime::{GlobalType, MemoryType, Mutability, ValType};
|
||||
use microw8::MicroW8;
|
||||
|
||||
struct Loader {
|
||||
store: wasmtime::Store<()>,
|
||||
memory: wasmtime::Memory,
|
||||
instance: wasmtime::Instance,
|
||||
}
|
||||
|
||||
impl Loader {
|
||||
fn new(engine: &wasmtime::Engine) -> Result<Loader> {
|
||||
let module = wasmtime::Module::new(engine, include_bytes!("../platform/loader.wasm"))?;
|
||||
let mut store = wasmtime::Store::new(engine, ());
|
||||
|
||||
let mut linker = wasmtime::Linker::new(engine);
|
||||
let memory = wasmtime::Memory::new(&mut store, MemoryType::new(9, Some(9)))?;
|
||||
linker.define("env", "memory", memory.clone())?;
|
||||
|
||||
let instance = linker.instantiate(&mut store, &module)?;
|
||||
Ok(Loader {
|
||||
store,
|
||||
memory,
|
||||
instance,
|
||||
})
|
||||
}
|
||||
|
||||
fn load(&mut self, module_data: &[u8]) -> Result<Vec<u8>> {
|
||||
let memory = self.memory.data_mut(&mut self.store);
|
||||
|
||||
let base_start = module_data.len();
|
||||
memory[..base_start].copy_from_slice(module_data);
|
||||
|
||||
let base_module = include_bytes!("../uw8-tool/base1.wasm");
|
||||
let base_end = base_start + base_module.len();
|
||||
memory[base_start..base_end].copy_from_slice(base_module);
|
||||
|
||||
let load_uw8 = self
|
||||
.instance
|
||||
.get_typed_func::<(i32, i32, i32, i32), i32, _>(&mut self.store, "load_uw8")?;
|
||||
let end_offset = load_uw8.call(
|
||||
&mut self.store,
|
||||
(0, base_start as i32, base_start as i32, base_end as i32),
|
||||
)? as u32 as usize;
|
||||
|
||||
Ok(self.memory.data(&self.store)[base_end..end_offset].to_vec())
|
||||
}
|
||||
}
|
||||
mod microw8;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let filename = std::env::args()
|
||||
.nth(1)
|
||||
.ok_or_else(|| anyhow!("Missing .uw8 file path"))?;
|
||||
let mut uw8_module = vec![];
|
||||
File::open(filename)?.read_to_end(&mut uw8_module)?;
|
||||
|
||||
let engine = wasmtime::Engine::default();
|
||||
let mut uw8 = MicroW8::new()?;
|
||||
|
||||
let mut loader = Loader::new(&engine)?;
|
||||
uw8.load_from_file(filename)?;
|
||||
|
||||
let platform_module =
|
||||
wasmtime::Module::new(&engine, include_bytes!("../platform/platform.wasm"))?;
|
||||
|
||||
let module = wasmtime::Module::new(&engine, loader.load(&uw8_module)?)?;
|
||||
|
||||
let mut store = wasmtime::Store::new(&engine, ());
|
||||
let memory = wasmtime::Memory::new(&mut store, MemoryType::new(4, Some(4)))?;
|
||||
|
||||
let mut linker = wasmtime::Linker::new(&engine);
|
||||
linker.define("env", "memory", memory.clone())?;
|
||||
linker.func_wrap("env", "acos", |v: f32| v.acos())?;
|
||||
linker.func_wrap("env", "asin", |v: f32| v.asin())?;
|
||||
linker.func_wrap("env", "atan", |v: f32| v.atan())?;
|
||||
linker.func_wrap("env", "atan2", |x: f32, y: f32| x.atan2(y))?;
|
||||
linker.func_wrap("env", "cos", |v: f32| v.cos())?;
|
||||
linker.func_wrap("env", "exp", |v: f32| v.exp())?;
|
||||
linker.func_wrap("env", "log", |v: f32| v.ln())?;
|
||||
linker.func_wrap("env", "sin", |v: f32| v.sin())?;
|
||||
linker.func_wrap("env", "tan", |v: f32| v.tan())?;
|
||||
linker.func_wrap("env", "pow", |a: f32, b: f32| a.powf(b))?;
|
||||
for i in 9..64 {
|
||||
linker.func_wrap("env", &format!("reserved{}", i), || {})?;
|
||||
}
|
||||
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 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 instance = linker.instantiate(&mut store, &module)?;
|
||||
let tic = instance.get_typed_func::<i32, (), _>(&mut store, "tic")?;
|
||||
|
||||
let mut buffer = vec![0u32; 320 * 256];
|
||||
let mut window = Window::new("MicroW8", 320, 256, WindowOptions::default())?;
|
||||
window.limit_update_rate(Some(std::time::Duration::from_micros(16666)));
|
||||
|
||||
let start_time = Instant::now();
|
||||
|
||||
while window.is_open() && !window.is_key_down(Key::Escape) {
|
||||
tic.call(&mut store, start_time.elapsed().as_millis() as i32)?;
|
||||
|
||||
let framebuffer = &memory.data(&store)[120..];
|
||||
let palette = &framebuffer[320 * 256..];
|
||||
for i in 0..320 * 256 {
|
||||
let offset = framebuffer[i] as usize * 4;
|
||||
buffer[i] = 0xff000000
|
||||
| ((palette[offset + 2] as u32) << 16)
|
||||
| ((palette[offset + 1] as u32) << 8)
|
||||
| palette[offset] as u32;
|
||||
}
|
||||
|
||||
window.update_with_buffer(&buffer, 320, 256)?;
|
||||
while uw8.is_open() {
|
||||
uw8.run_frame()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
198
src/microw8.rs
Normal file
198
src/microw8.rs
Normal file
@@ -0,0 +1,198 @@
|
||||
use std::io::prelude::*;
|
||||
use std::path::Path;
|
||||
use std::{fs::File, time::Instant};
|
||||
|
||||
use anyhow::Result;
|
||||
use minifb::{Key, Window, WindowOptions};
|
||||
use wasmtime::{
|
||||
Engine, GlobalType, Memory, MemoryType, Module, Mutability, Store, TypedFunc, ValType,
|
||||
};
|
||||
|
||||
pub struct MicroW8 {
|
||||
engine: Engine,
|
||||
loader: Loader,
|
||||
platform_module: Module,
|
||||
window: Window,
|
||||
window_buffer: Vec<u32>,
|
||||
instance: Option<UW8Instance>,
|
||||
}
|
||||
|
||||
struct UW8Instance {
|
||||
store: Store<()>,
|
||||
memory: Memory,
|
||||
tic: TypedFunc<i32, ()>,
|
||||
start_time: Instant,
|
||||
}
|
||||
|
||||
impl MicroW8 {
|
||||
pub fn new() -> Result<MicroW8> {
|
||||
let engine = wasmtime::Engine::default();
|
||||
|
||||
let loader = Loader::new(&engine)?;
|
||||
|
||||
let platform_module =
|
||||
wasmtime::Module::new(&engine, include_bytes!("../platform/platform.wasm"))?;
|
||||
|
||||
let mut window = Window::new("MicroW8", 320, 240, WindowOptions::default())?;
|
||||
window.limit_update_rate(Some(std::time::Duration::from_micros(16666)));
|
||||
|
||||
Ok(MicroW8 {
|
||||
engine,
|
||||
loader,
|
||||
platform_module,
|
||||
window,
|
||||
window_buffer: vec![0u32; 320 * 240],
|
||||
instance: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_open(&self) -> bool {
|
||||
self.window.is_open() && !self.window.is_key_down(Key::Escape)
|
||||
}
|
||||
|
||||
fn reset(&mut self) {
|
||||
self.instance = None;
|
||||
for v in &mut self.window_buffer {
|
||||
*v = 0;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_from_file<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
|
||||
self.reset();
|
||||
|
||||
let mut module = vec![];
|
||||
File::open(path)?.read_to_end(&mut module)?;
|
||||
self.load_from_memory(&module)
|
||||
}
|
||||
|
||||
pub fn load_from_memory(&mut self, module: &[u8]) -> Result<()> {
|
||||
self.reset();
|
||||
|
||||
let module = wasmtime::Module::new(&self.engine, self.loader.load(module)?)?;
|
||||
|
||||
let mut store = wasmtime::Store::new(&self.engine, ());
|
||||
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.clone())?;
|
||||
linker.func_wrap("env", "acos", |v: f32| v.acos())?;
|
||||
linker.func_wrap("env", "asin", |v: f32| v.asin())?;
|
||||
linker.func_wrap("env", "atan", |v: f32| v.atan())?;
|
||||
linker.func_wrap("env", "atan2", |x: f32, y: f32| x.atan2(y))?;
|
||||
linker.func_wrap("env", "cos", |v: f32| v.cos())?;
|
||||
linker.func_wrap("env", "exp", |v: f32| v.exp())?;
|
||||
linker.func_wrap("env", "log", |v: f32| v.ln())?;
|
||||
linker.func_wrap("env", "sin", |v: f32| v.sin())?;
|
||||
linker.func_wrap("env", "tan", |v: f32| v.tan())?;
|
||||
linker.func_wrap("env", "pow", |a: f32, b: f32| a.powf(b))?;
|
||||
for i in 9..64 {
|
||||
linker.func_wrap("env", &format!("reserved{}", i), || {})?;
|
||||
}
|
||||
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 platform_instance = linker.instantiate(&mut store, &self.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 instance = linker.instantiate(&mut store, &module)?;
|
||||
let tic = instance.get_typed_func::<i32, (), _>(&mut store, "tic")?;
|
||||
|
||||
self.instance = Some(UW8Instance {
|
||||
store,
|
||||
memory,
|
||||
tic,
|
||||
start_time: Instant::now(),
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_frame(&mut self) -> Result<()> {
|
||||
if let Some(mut instance) = self.instance.take() {
|
||||
instance.tic.call(
|
||||
&mut instance.store,
|
||||
instance.start_time.elapsed().as_millis() as i32,
|
||||
)?;
|
||||
|
||||
let framebuffer = &instance.memory.data(&instance.store)[120..];
|
||||
let palette = &framebuffer[320 * 256..];
|
||||
for i in 0..320 * 240 {
|
||||
let offset = framebuffer[i] as usize * 4;
|
||||
self.window_buffer[i] = 0xff000000
|
||||
| ((palette[offset + 2] as u32) << 16)
|
||||
| ((palette[offset + 1] as u32) << 8)
|
||||
| palette[offset] as u32;
|
||||
}
|
||||
|
||||
self.instance = Some(instance);
|
||||
}
|
||||
|
||||
self.window
|
||||
.update_with_buffer(&self.window_buffer, 320, 240)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct Loader {
|
||||
store: wasmtime::Store<()>,
|
||||
memory: wasmtime::Memory,
|
||||
instance: wasmtime::Instance,
|
||||
}
|
||||
|
||||
impl Loader {
|
||||
fn new(engine: &wasmtime::Engine) -> Result<Loader> {
|
||||
let module = wasmtime::Module::new(engine, include_bytes!("../platform/loader.wasm"))?;
|
||||
let mut store = wasmtime::Store::new(engine, ());
|
||||
|
||||
let mut linker = wasmtime::Linker::new(engine);
|
||||
let memory = wasmtime::Memory::new(&mut store, MemoryType::new(9, Some(9)))?;
|
||||
linker.define("env", "memory", memory.clone())?;
|
||||
|
||||
let instance = linker.instantiate(&mut store, &module)?;
|
||||
Ok(Loader {
|
||||
store,
|
||||
memory,
|
||||
instance,
|
||||
})
|
||||
}
|
||||
|
||||
fn load(&mut self, module_data: &[u8]) -> Result<Vec<u8>> {
|
||||
let memory = self.memory.data_mut(&mut self.store);
|
||||
|
||||
let base_start = module_data.len();
|
||||
memory[..base_start].copy_from_slice(module_data);
|
||||
|
||||
let base_module = include_bytes!("../uw8-tool/base1.wasm");
|
||||
let base_end = base_start + base_module.len();
|
||||
memory[base_start..base_end].copy_from_slice(base_module);
|
||||
|
||||
let load_uw8 = self
|
||||
.instance
|
||||
.get_typed_func::<(i32, i32, i32, i32), i32, _>(&mut self.store, "load_uw8")?;
|
||||
let end_offset = load_uw8.call(
|
||||
&mut self.store,
|
||||
(0, base_start as i32, base_start as i32, base_end as i32),
|
||||
)? as u32 as usize;
|
||||
|
||||
Ok(self.memory.data(&self.store)[base_end..end_offset].to_vec())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user