GameBoy illustration by Geoffrey Humbert.

Building Graphical Applications with Wasmer and WASI

Aaron Turner
Jan 17 · 4 min read

WebAssembly’s MVP brought a lot of really cool features for developers, and a lot of potential for applications to come! However, since the technology is still young, there are still a lot of features that are not quite ready yet. For example features like threads, interface types, etc… are currently proposals for the spec, but a lot of applications depend on these features. 🤔

Today, at Wasmer we are excited to give a sneak preview into an experimental feature we are working on: I/O devices! I/O devices creates special files that WebAssembly modules can read and write to, for drawing graphics and handling input.

I/O devices can be enabled by passing a flag to the Wasmer CLI, and is available as a package for Wasmer-JS. 🔌

Testing I/O Devices using our Debugging Wasm module.

Let’s take a step back and dive into how I/O devices can help the community today.

Finding what Features the Community can use, Today

We did some research on what people in the open source community are trying to build with WebAssembly, and we found that it was a lot of games! Sandspeil, WasmBoy, and Continuation Lab’s port of DOOM 3 are all amazing games built with WebAssembly. Games Engines like Unity, Gdevelop, and Construct 3 support outputting games for web browsers that use WebAssembly. 🎮

However, none of these games or engines support running the game standalone. For example, currently, you could not have a single Wasm Binary create and interface with Graphics and Input as you would still need additional code for the specific platform (like a web browser) in a different language.
Wasmer’s I/O devices allows developers to have a single Wasm Binary open a Window, write to a Frame Buffer, and read input events from a user. 💪

Let’s take a look at how I/O devices work and enable this functionality.

Building WASI Applications with Wasmer I/O devices

I/O devices work by creating virtual device files in the runtime filesystem, similar to a device file on a UNIX operating system. If a Wasm module uses the WASI bindings of reading/writing files, the runtime can react to the events and perform actions for the Wasm module. 😎

For example, I/O devices creates a/_wasmer/dev/fb0/fb file that contains a RGBA byte array of a buffer to be drawn. Which is similar to writing directly to a linux framebuffer! 🖼️

Since the API is essentially an abstraction over a normal Filesystem, and the current WASI spec, Wasmer I/O devices can be tried today, with any language / toolchain that supports WASI!

In fact, we even got a working standalone version of WasmBoy that can be tried with the Wasmer runtime! This works by using the io-devices-lib-assemblyscript package that we built. The package, and also a Rust crate for interacting with I/O Devices, can be found on our io-devices-lib repository.

WasmBoy is now available on WAPM, as WasmerBoy. You can install Wasmer and WAPM by following the instructions here. Then, Wasmerboy can be installed standalone by running: wapm install -g torch2424/wasmerboy . Then, by running wasmerboy --dir=my-dir my-dir/my-rom-file.gb . For example, we can run the MIT licensed Tobu Tobu Girl using WasmerBoy from WAPM:

You can download the Tobu Tobug Girl rom from this link

Showing WasmerBoy running from WAPM / Wasmer CLI

WasmerBoy also works on Wasmer-JS / WebAssembly.sh (on Desktop Chrome)! You can drag and drop the ROM file to WebAssembly.sh, which will add it to the filesystem. Then, you can run the same command: wasmerboy /tmp/my-rom-file.gb . Which will open a popup running WasmerBoy!

Showing WasmerBoy running from Wasmer-JS / WebAssembly.sh

Thank you!

We are SO excited to see the interest and projects that could come from this. We really hope this helps to grow the WebAssembly community, and help as a jumping board for spec authors when this eventually does get proposed for the WASI spec. 🙌

Again, we would like to re-iterate, this is an experimental feature, that is not standardized. I/O devices is meant for experimenting with building standalone WebAssembly modules as a sneak peek at the eventual future when there could be a standardized feature for this type of functionality in the WASI spec. As this idea is an important part of the web platform, as highlighted in Paul Lewis’ “Custom Web Shadow Elements, or Whatever…” talk.

To get started with I/O devices, the latest release of Wasmer has a new flag:
--enable-experimental-io-devices.

I/O devices has its own Wasmer-JS package, @wasmer/io-devices. The I/O devices package is utilized in the @wasmer/wasm-temrinal package, and WebAssembly.sh to support t I/O devices by default.

Then, you can try a Wasm Module that uses the I/O devices, such as WasmBoy on WAPM, or build a Wasm module in Rust or AssemblyScript using the experimental I/O Devices Lib. 🦀🚀

Thank YOU for reading this article! Feel free to open issues, send us ideas, or send us your cool projects! We are happy to help the community in any way we can! Cheers! 🍻

Wasmer

Universal WebAssembly runtime

Thanks to Mark McCaskey

Aaron Turner

Written by

Skate. Music. Video Games. Code. Developer / Developer Relations at Wasmer. All opinions expressed are my own. Please excuse the spelling, I am a lazy typist.

Wasmer

Wasmer

Universal WebAssembly runtime

More From Medium

More on Webassembly from Wasmer

More on Webassembly from Wasmer

Fuzz testing in WebAssembly VMs

37

More on Webassembly from Wasmer

More on Webassembly from Wasmer

Running WebAssembly on ARM

312

More on Programming from Wasmer

More on Programming from Wasmer

Wasienv: WASI Development Toolchain for C/C++

237

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade