move native microw8 code into object to prepare for file watch

This commit is contained in:
2021-11-14 14:43:02 +01:00
parent 294b9f5634
commit bce7d82dae
5 changed files with 418 additions and 140 deletions

227
Cargo.lock generated
View File

@@ -32,7 +32,7 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [ dependencies = [
"winapi", "winapi 0.3.9",
] ]
[[package]] [[package]]
@@ -49,7 +49,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [ dependencies = [
"hermit-abi", "hermit-abi",
"libc", "libc",
"winapi", "winapi 0.3.9",
] ]
[[package]] [[package]]
@@ -385,7 +385,7 @@ checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
dependencies = [ dependencies = [
"libc", "libc",
"redox_users", "redox_users",
"winapi", "winapi 0.3.9",
] ]
[[package]] [[package]]
@@ -443,7 +443,7 @@ checksum = "fa68f2fb9cae9d37c9b2b3584aba698a2e97f72d7aef7b9f7aa71d8b54ce46fe"
dependencies = [ dependencies = [
"errno-dragonfly", "errno-dragonfly",
"libc", "libc",
"winapi", "winapi 0.3.9",
] ]
[[package]] [[package]]
@@ -481,7 +481,7 @@ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"libc", "libc",
"redox_syscall", "redox_syscall",
"winapi", "winapi 0.3.9",
] ]
[[package]] [[package]]
@@ -496,6 +496,41 @@ dependencies = [
"miniz_oxide", "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]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.14.4" version = "0.14.4"
@@ -575,6 +610,35 @@ dependencies = [
"serde", "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]] [[package]]
name = "itertools" name = "itertools"
version = "0.10.1" version = "0.10.1"
@@ -602,6 +666,16 @@ dependencies = [
"wasm-bindgen", "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]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@@ -633,7 +707,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0cf036d15402bea3c5d4de17b3fce76b3e4a56ebc1f577be0e7a72f7c607cf0" checksum = "c0cf036d15402bea3c5d4de17b3fce76b3e4a56ebc1f577be0e7a72f7c607cf0"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"winapi", "winapi 0.3.9",
] ]
[[package]] [[package]]
@@ -682,7 +756,7 @@ dependencies = [
"wayland-client", "wayland-client",
"wayland-cursor", "wayland-cursor",
"wayland-protocols", "wayland-protocols",
"winapi", "winapi 0.3.9",
"x11-dl", "x11-dl",
"xkb", "xkb",
"xkbcommon-sys", "xkbcommon-sys",
@@ -704,12 +778,66 @@ dependencies = [
"autocfg", "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]] [[package]]
name = "more-asserts" name = "more-asserts"
version = "0.2.1" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0debeb9fcf88823ea64d64e4a815ab1643f33127d995978e099942ce38f25238" 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]] [[package]]
name = "nix" name = "nix"
version = "0.20.2" version = "0.20.2"
@@ -744,6 +872,24 @@ dependencies = [
"version_check", "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]] [[package]]
name = "num_cpus" name = "num_cpus"
version = "1.13.0" version = "1.13.0"
@@ -988,7 +1134,7 @@ dependencies = [
"bitflags", "bitflags",
"libc", "libc",
"mach", "mach",
"winapi", "winapi 0.3.9",
] ]
[[package]] [[package]]
@@ -997,7 +1143,7 @@ version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [ dependencies = [
"winapi", "winapi 0.3.9",
] ]
[[package]] [[package]]
@@ -1012,6 +1158,15 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" 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]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.1.0" version = "1.1.0"
@@ -1085,6 +1240,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
[[package]]
name = "slab"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.7.0" version = "1.7.0"
@@ -1142,7 +1303,7 @@ dependencies = [
"rand", "rand",
"redox_syscall", "redox_syscall",
"remove_dir_all", "remove_dir_all",
"winapi", "winapi 0.3.9",
] ]
[[package]] [[package]]
@@ -1227,6 +1388,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"minifb", "minifb",
"notify",
"wasmtime", "wasmtime",
] ]
@@ -1248,6 +1410,17 @@ version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" 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]] [[package]]
name = "wasi" name = "wasi"
version = "0.10.2+wasi-snapshot-preview1" version = "0.10.2+wasi-snapshot-preview1"
@@ -1345,7 +1518,7 @@ dependencies = [
"wasmtime-jit", "wasmtime-jit",
"wasmtime-runtime", "wasmtime-runtime",
"wat", "wat",
"winapi", "winapi 0.3.9",
] ]
[[package]] [[package]]
@@ -1365,7 +1538,7 @@ dependencies = [
"serde", "serde",
"sha2", "sha2",
"toml", "toml",
"winapi", "winapi 0.3.9",
"zstd", "zstd",
] ]
@@ -1419,7 +1592,7 @@ checksum = "8779dd78755a248512233df4f6eaa6ba075c41bea2085fec750ed2926897bf95"
dependencies = [ dependencies = [
"cc", "cc",
"libc", "libc",
"winapi", "winapi 0.3.9",
] ]
[[package]] [[package]]
@@ -1444,7 +1617,7 @@ dependencies = [
"wasmparser", "wasmparser",
"wasmtime-environ", "wasmtime-environ",
"wasmtime-runtime", "wasmtime-runtime",
"winapi", "winapi 0.3.9",
] ]
[[package]] [[package]]
@@ -1469,7 +1642,7 @@ dependencies = [
"thiserror", "thiserror",
"wasmtime-environ", "wasmtime-environ",
"wasmtime-fiber", "wasmtime-fiber",
"winapi", "winapi 0.3.9",
] ]
[[package]] [[package]]
@@ -1591,6 +1764,12 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"
@@ -1601,6 +1780,12 @@ dependencies = [
"winapi-x86_64-pc-windows-gnu", "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]] [[package]]
name = "winapi-i686-pc-windows-gnu" name = "winapi-i686-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"
@@ -1613,7 +1798,7 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [ dependencies = [
"winapi", "winapi 0.3.9",
] ]
[[package]] [[package]]
@@ -1622,6 +1807,16 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 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]] [[package]]
name = "x11-dl" name = "x11-dl"
version = "2.19.1" version = "2.19.1"

View File

@@ -9,3 +9,4 @@ edition = "2021"
wasmtime = "0.30" wasmtime = "0.30"
anyhow = "1" anyhow = "1"
minifb = "0.19" minifb = "0.19"
notify = "4"

View File

@@ -113,4 +113,5 @@ start fn setup() {
(i*4)!(120+320*256) = i * 0x10101; (i*4)!(120+320*256) = i * 0x10101;
branch_if (i := i + 1) < 256: colors branch_if (i := i + 1) < 256: colors
} }
randomSeed(random());
} }

View File

@@ -1,136 +1,19 @@
use std::io::prelude::*;
use std::{fs::File, time::Instant};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use minifb::{Key, Window, WindowOptions}; use microw8::MicroW8;
use wasmtime::{GlobalType, MemoryType, Mutability, ValType};
struct Loader { mod microw8;
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())
}
}
fn main() -> Result<()> { fn main() -> Result<()> {
let filename = std::env::args() let filename = std::env::args()
.nth(1) .nth(1)
.ok_or_else(|| anyhow!("Missing .uw8 file path"))?; .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 = while uw8.is_open() {
wasmtime::Module::new(&engine, include_bytes!("../platform/platform.wasm"))?; uw8.run_frame()?;
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)?;
} }
Ok(()) Ok(())

198
src/microw8.rs Normal file
View 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())
}
}