diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6ab52c8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + // "go.lintTool": "golint" + "go.toolsEnvVars": { + "GOOS": "wasip1", + "GOARCH": "wasm" + } +} \ No newline at end of file diff --git a/crates/editor/src/go_builder.rs b/crates/editor/src/go_builder.rs index da392ae..f35bd6a 100644 --- a/crates/editor/src/go_builder.rs +++ b/crates/editor/src/go_builder.rs @@ -3,8 +3,7 @@ use std::{fs::File, io::Read, path::{Path, PathBuf}, process::Command}; use viperid::VResult; pub struct GoBuilder { - project_directory: PathBuf, - entry_point: PathBuf + project_directory: PathBuf } impl GoBuilder { @@ -27,15 +26,9 @@ impl GoBuilder { anyhow::bail!("project directory must exist: {}", project_directory.to_string_lossy()) } - let entry_point = project_directory.join("main.go"); - if !entry_point.exists() { - anyhow::bail!("entry point must exist: {}", entry_point.to_string_lossy()) - } - // OK, we should be able to do things with Go without any errors Ok(GoBuilder { project_directory: PathBuf::from(project_directory), - entry_point }) } @@ -47,24 +40,17 @@ impl GoBuilder { self.project_directory.to_string_lossy() ); } - if !self.entry_point.exists() { - anyhow::bail!( - "entry point disappeared: {}", - self.entry_point.to_string_lossy() - ); - } - let project_directory = &self.project_directory; - let entry_point = &self.entry_point; - let build_directory = project_directory.join("build"); + let build_directory = self.project_directory.join("build"); let wasm_name = build_directory.join("game.wasm"); let mut child = Command::new("go") - .args(["build", "-o"]).arg(&wasm_name) + .arg("-C").arg(self.project_directory.clone()) + .args(["build", "-o"]).arg("build/game.wasm") .env("GOOS", "wasip1") .env("GOARCH", "wasm") .arg("-trimpath") - .arg(entry_point) + .arg(".") .spawn()?; let status = child.wait()?; if !status.success() { diff --git a/crates/editor/src/main.rs b/crates/editor/src/main.rs index c60d67e..4966ab2 100644 --- a/crates/editor/src/main.rs +++ b/crates/editor/src/main.rs @@ -1,6 +1,7 @@ use std::path::PathBuf; -use viperid::{Device, VResult}; +use player::HOSTED_DEVICE; +use viperid::VResult; use crate::go_builder::GoBuilder; @@ -10,11 +11,10 @@ fn main() -> VResult<()> { let builder = GoBuilder::new( &PathBuf::from("example_project"))?; let wasm = builder.build()?; - let device = Device::new(); - let mut executor = player::Executor::new(device.share(), &wasm)?; + let mut executor = player::Executor::new(&wasm)?; - minifb_host::host(device, || { + minifb_host::host(HOSTED_DEVICE.with(|d| d.share()), || { executor.update(); executor.get_error()?; Ok(()) diff --git a/crates/player/src/engine_api.rs b/crates/player/src/engine_api.rs index 3461fdc..a20a949 100644 --- a/crates/player/src/engine_api.rs +++ b/crates/player/src/engine_api.rs @@ -1,9 +1,9 @@ use std::fmt::Display; use viperid::VResult; -use wasmi::{core::{HostError, Trap}, Caller, Extern, Linker}; +use wasmi::{core::{HostError, Trap}, Caller, Linker}; -use crate::executor::ExecutorState; +use crate::{executor::ExecutorState, HOSTED_DEVICE}; pub(crate) fn integrate(linker: &mut Linker) -> VResult<()> { linker.func_wrap("viperid", "Pset", pset)?; @@ -13,14 +13,11 @@ pub(crate) fn integrate(linker: &mut Linker) -> VResult<()> { Ok(()) } -fn pset(mut caller: Caller, x: i32, y: i32, color: i32) -> Result<(), Trap> { - let memory = match caller.get_export("memory") { - Some(Extern::Memory(m)) => m, - _ => return Err(wasmi::core::Trap::new(String::from("missing required memory export"))), - }; - let(_, ctx) = memory.data_and_store_mut(&mut caller); - ctx.device.shared.screen.pset(x, y, (color & 0xff) as u8); - Ok(()) +fn pset(mut _caller: Caller, x: i32, y: i32, color: i32) -> Result<(), Trap> { + HOSTED_DEVICE.with(|dev| { + dev.shared.screen.pset(x, y, (color & 0xff) as u8); + Ok(()) + }) } fn yield_frame(_caller: Caller) -> Result<(), Trap> { diff --git a/crates/player/src/executor.rs b/crates/player/src/executor.rs index 9e6a2c3..6de2564 100644 --- a/crates/player/src/executor.rs +++ b/crates/player/src/executor.rs @@ -1,6 +1,6 @@ use std::mem; -use viperid::{Device, VResult}; +use viperid::VResult; use wasmi::{core::Trap, Engine, Linker, Module, Store, TypedFunc, TypedResumableCall, TypedResumableInvocation}; use crate::{engine_api::{self, YieldFrame}, wasi::{self, StockWasi}}; @@ -12,14 +12,12 @@ pub struct Executor { pub(crate) struct ExecutorState { wasi: wasi::StockWasi, - pub(crate) device: Device } impl ExecutorState { - fn new(device: Device) -> Self { + fn new() -> Self { ExecutorState { wasi: StockWasi::new(), - device } } @@ -27,12 +25,12 @@ impl ExecutorState { impl Executor { - pub fn new(device: Device, wasm: &[u8]) -> VResult { + pub fn new(wasm: &[u8]) -> VResult { let engine = Engine::default(); let module = Module::new(&engine, wasm)?; - let mut store = Store::new(&engine, ExecutorState::new(device)); + let mut store = Store::new(&engine, ExecutorState::new()); let mut linker = >::new(&engine); wasi::integrate(&mut linker, |hs| &mut hs.wasi)?; diff --git a/crates/player/src/hosted_device.rs b/crates/player/src/hosted_device.rs new file mode 100644 index 0000000..1d883ec --- /dev/null +++ b/crates/player/src/hosted_device.rs @@ -0,0 +1,7 @@ +use std::thread_local; + +use viperid::Device; + +thread_local! { + pub static HOSTED_DEVICE: Device = Device::new(); +} \ No newline at end of file diff --git a/crates/player/src/lib.rs b/crates/player/src/lib.rs index 70a82d6..da134b6 100644 --- a/crates/player/src/lib.rs +++ b/crates/player/src/lib.rs @@ -1,5 +1,7 @@ mod engine_api; mod executor; mod wasi; +mod hosted_device; -pub use executor::Executor; \ No newline at end of file +pub use executor::Executor; +pub use hosted_device::HOSTED_DEVICE; \ No newline at end of file diff --git a/crates/player/src/wasi/implementation.rs b/crates/player/src/wasi/implementation.rs index 1441572..a96404d 100644 --- a/crates/player/src/wasi/implementation.rs +++ b/crates/player/src/wasi/implementation.rs @@ -1,5 +1,3 @@ -use std::time::SystemTime; - use wasmi::core::Trap; use super::MinimalPreview1; diff --git a/crates/web_runner/src/main.rs b/crates/web_runner/src/main.rs index 5c683ca..3dd46c3 100644 --- a/crates/web_runner/src/main.rs +++ b/crates/web_runner/src/main.rs @@ -3,6 +3,7 @@ use std::rc::Rc; use error_iter::ErrorIter as _; use log::error; use pixels::{Pixels, SurfaceTexture}; +use player::HOSTED_DEVICE; use viperid::{Device, VResult, SCREEN_H, SCREEN_W}; // https://github.com/parasyte/pixels/blob/main/examples/minimal-web/src/main.rs use winit::{dpi::LogicalSize, event::Event, event_loop::{ControlFlow, EventLoop}, window::WindowBuilder}; @@ -15,12 +16,11 @@ fn main() { async fn run() { let wasm = include_bytes!("../../../example_project/build/game.wasm"); - let device = Device::new(); let mut executor = - player::Executor::new(device.share(), wasm) + player::Executor::new(wasm) .expect("should have been able to create executor"); - host(device, move || { + host(HOSTED_DEVICE.with(|d| d.share()), move || { executor.update(); executor.get_error()?; Ok(()) diff --git a/example_project/go.work b/example_project/go.work index b777406..2285867 100644 --- a/example_project/go.work +++ b/example_project/go.work @@ -1 +1,3 @@ go 1.21.5 + +use . \ No newline at end of file diff --git a/example_project/main.go b/example_project/main.go index 18ad9aa..f1f5175 100644 --- a/example_project/main.go +++ b/example_project/main.go @@ -1,14 +1,16 @@ package main +import "example_project/viperid" + func main() { t := 0 for { for y := 0; y < 120; y++ { for x := 0; x < 160; x++ { - Pset( - int32(x), - int32(y), - int32((x+y+t)%64), + viperid.Pset( + x, + y, + (x+y+t)%64, ) } } @@ -17,15 +19,7 @@ func main() { /* debug.PrintStack() */ - YieldFrame() + viperid.YieldFrame() t += 1 } } - -//go:wasmimport viperid Pset -//go:noescape -func Pset(x int32, y int32, color int32) - -//go:wasmimport viperid YieldFrame -//go:noescape -func YieldFrame() diff --git a/example_project/viperid/exports.go b/example_project/viperid/exports.go new file mode 100644 index 0000000..0f895eb --- /dev/null +++ b/example_project/viperid/exports.go @@ -0,0 +1,13 @@ +package viperid + +func YieldFrame() { + yieldFrame() +} + +func Pset(x int, y int, color int) { + pset(int32(x), int32(y), int32(color)) +} + +func Pget(x int, y int) int { + return int(pget(int32(x), int32(y))) +} diff --git a/example_project/viperid/imports.go b/example_project/viperid/imports.go new file mode 100644 index 0000000..1041e33 --- /dev/null +++ b/example_project/viperid/imports.go @@ -0,0 +1,15 @@ +//lint:file-ignore U1000 Ignore all unused code, it's generated + +package viperid + +//go:wasmimport viperid YieldFrame +//go:noescape +func yieldFrame() + +//go:wasmimport viperid Pset +//go:noescape +func pset(x int32, y int32, color int32) + +//go:wasmimport viperid Pget +//go:noescape +func pget(x int32, y int32) int32