wasmboy
๐ฎ๐พ๐น๏ธ Gameboy Emulator Library written in Web Assembly using AssemblyScript, Demos in Preact and Svelte ๐ฎ๐พ๐น๏ธ
Project is still < 1.0.0. Most games are playable, but the emulator is still not very accurate. Expect bugs.
Talk given at WebAssembly SF March 28th, 2019
Table of Contents
- Features
- Usage
- In-Game Screenshots
- Demo Applications
- Tests
- Contributing
- Notable Projects
- Special Thanks
- Resources
Features
- Emulates the Gameboy / Gameboy Color ๐ฎ๐พ๐น๏ธ
- Outputs graphics to a scalable / responsive HTML5 canvas ๐ผ๏ธ, and audio through the Web Audio API ๐
- Support for In-game saves, and save states ๐พ
- Configurable options to increase performance for low(er) end devices ๐ฅ
- Importable into other projects as a dependency โป๏ธ
- Built with Web Assembly ๐ธ๏ธ
- Uses Web Workers for parallelized rendering ๐ ๏ธ
- Keyboard and gamepad input support using responsive gamepad โจ๏ธ ๐ฎ
- Debugger with a value table (I/O map), Tile Data visualizer, and Background Map with Scroll Indicators ๐
- Runs in both Browser and Node ๐
Usage
Project is still < 1.0.0. Most games are playable, but the emulator is still not very accurate. Expect bugs.
Simply install through npm:
npm install --save wasmboy
Documentation for the project can be found on the WasmBoy Wiki.
Supported Platforms
Try to test and aim for support on all major browsers (Chrome, Firefox, and Safari). Also, Node support works with the headless
option in the WasmBoy config, and using the Worker Threads --experimental-worker
flag.
In-Game Screenshots
Gameboy Support
Gameboy Color Support
Demo Applications
Debugger
A full debugger meant for analyzing the internals of the gameboy. Great for HomeBrew Gameboy Development, or using as a reference point for building your own GameBoy emulator. See the gif at the top of the README for an example.
Features
- Support of all Gameboy Components: CPU, PPU (Graphics), APU (Audio), Memory, Interrupts, and Timers. ๐ฎ
- Per cycle state of each Game Boy components data, internal registers, and relevant memory addresses. ๐
- Loaded ROM Information and parsing of the Cartridge Header. ๐พ
- CPU Control options. Stepping per opcode, and breakpoints. ๐ง
- Graphics Background Map, with border for current "camera" location with respect to scroll registers. ๐ผ๏ธ
- Graphics Tile Data, to display the loaded tiles currently loaded across all VRAM Banks. ๐จ
- WasmBoy Control options. Play, Pause, Save State, and Load State. โฏ๏ธ ๐
- Ability to log the entire WasmBoy Library Object and Memory to the DevTools Console. ๐ฅ๏ธ
- Highly productive "Docker" layout, with snapping of widgets onto sections of the screen and tab support. โ
- Saved Layouts between sessions. ๐
- Help widget with tips on how to be effective in the debugger. ๐
Mobile Demo
For UI/UX reasons, on mobile the debugger is simply a web app for testing the lib. This is useful for testing a ROM on the go. For playing games, I would suggest VaporBoy. Below is an example of the mobile demo:
Anaytics / Privacy
Analytics is used on this application simply for performance monitoring, and tracking popularity of the applications. The following events are sent, with nothing more than the event name. The analytics provider used is Google Analytics.
- Whenever a new ROM is loaded, and played for the first time.
- Whether attempting to load a ROM was successful.
- Whenever a state is saved.
- Whenever a state is loaded.
- Whenever custom WasmBoy options are applied.
- Whenever the Google Drive option is selected.
- Whenever the mobile demo is manually reloaded.
Benchmark
Since WasmBoy is built in AssemblyScript, it can also run it's core through the Typescript compiler if we mock out some of the WebAssembly interface. The benchmarking tool was built as a way to compare WebAssembly performance to Javascript / ES6 performance, after compiling the core to both WebAssembly and Javascript. It includes detailed stats, live running output, and multiple graphs. Also great for comparing the performance of devices that run WasmBoy.
Example
Anaytics / Privacy
Analytics is used on this application simply for performance monitoring, and tracking popularity of the application. The following events are sent, with nothing more than the event name. The analytics provider used is Google Analytics.
- Whenever a new ROM is loaded from the particular source.
- Whenever the benchmark is ran.
- Whenever results are rendered for the benchmark.
Iframe Embed
An Iframe embeddable version of WasmBoy. Simply provide information through URL Query Params, and embed a ROM on your website! Great for embedding your HomeBrew Game Boy / Game Boy Color games on your website, (WordPress) blog, and game hosting services such as itch.io.
Example
Example Tobu Tobu Girl, Homebrew Hub Iframe
Usage
Add an iframe to your website like the following:
<iframe title="WasmBoy Iframe Embed" width="160" height="144" allowfullscreen="true" src="https://wasmboy.app/iframe/?[QUERY_PARAMS_GO_HERE]"> </iframe>
The iframe is configured by adding URL Query Params. The configuration params are:
rom-url
- (Required) The URL to the.gb
or.gbc
ROM that will be loaded, fetched, and played.rom-name
- The name of the ROM being played.play-poster
- The URL to the image shown at the intial "click to play", play poster.
Please ensure all assets that are being loaded by the iframe embed, such as ROMs and images, will work with CORS. The WasmBoy Iframe Embed will take the full width and height (100%) of it's iframe container. Thus, it will be up to your styling to ensure the iframe preserves the GameBoy 160x144 resolution.
Anaytics / Privacy
Analytics is used on this application simply for performance monitoring, and tracking popularity of the application. The analytics provider used is Google Analytics. Only basic user visit data is recorded / used.
Tests
These are all currently known passing tests (by me), there may be more test roms out there that pass. Some tests may not pass, and that can either be because of the component it is testing is actually incorrect, or another component that the test is testing is not yet implemented, or is incorrect (e.g a lot of mooneye tests rely on Serial Interrupts, which this emulator has yet to implement). Feel free to open an issue or PR to add any more passing tests to this list ๐ . The test names are listed from left to right, top to bottom.
Blarrg
Repo with all blargg's tests and source
cpu_instrs, instr_timing, mem_timing, mem_timing-2, halt_bug, cgb_sound
Mooneye
Timing
div_write, rapid_toggle, tim00, tim00_div_trigger, tim01, tim01_div_trigger, tim10, tim10_div_trigger, tim11, tim11_div_trigger, tima_reload, tima_write_reloading, tma_write_reloading
Halt
halt_ime0_ei, halt_ime0_nointr_timing, halt_ime1_timing
Contributing
Feel free to fork and submit PRs! Opening an issue is reccomended before starting any development, as a discussion would be nice on the idea / feature before writing code. Any help is much appreciated, and would be a ton of fun!
Installation
Just your standard node app. Install Node with nvm, git clone
the project, and npm install
, and you should be good to go!
CLI Commands / Npm Scripts
The project contains three different elements.
- The
core
orwasm
which is the web assembly module for wasmboy written in AssemblyScript. - The
lib
which is the importable library of wasmboy that can be used in other projects, that adds a top level API to thecore
. - The
demo
, which is a collection of different apps that are used for demoing purposes of thelib
andcore
.
Most of the build process in this project is done using Rollup.js. Each element / component of the project is configured in its own rollup.*.js
file, and are then all used within the standard rollup.config.js
file by the rollup CLI. Also, The core
wasm uses the AssemblyScript compiler CLI tool.
Commands for each part of the project will be prepended with their element name and a colon, e.g debugger:[command here]
.
Common command parts are:
dev
/watch
- How the project should be served and developed with tools like reloading.build
- Make production builds of the component / element of the project.
Commands not prepended with a colon are meant for easily building on all of the different parts as a whole.
Not all commands are documented, only ones relevant to making changes to the library for contributions. *
represents the category of commands, and is not an actual command.
# Command to serve the project, and watch the debugger, wasm, and lib for changes
# Uses concurrently: https://github.com/kimmobrunfeldt/concurrently
# Concurrently helps cleanup the output and organizes watchers on commands that require concurrent tools
# Serve the general project for development (Watches the core, lib, and debugger)
npm run start
# Same as npm start
npm run dev
# Same as npm start
npm run watch
# Build everything to be ready to be pushed to npm or released
npm run build
# Linting commands used during precommit an tests
npm run prettier:*
# Commands for building/serving the core, offers commands for building with the Assemblyscript Compiler (WASM) or Typescript (JS)
npm run core:*
# Commands for building/serving the JS lib
npm run lib:*
# Run tests in `test/accuracy/test.js`
npm run test
# Run tests in `test/performance/test.js`
npm run test:performance
# All commands for testing, and are test related
npm run test:*
# Commands for the building / serving the debugger
npm run debugger:*
# Commands for building / serving the benchmark tool
npm run benchmark:*
# Commands for building / serving all available apps in wasmboy
npm run demo:*
Using the gh-pages for debugger/demo deployment onto gh-pages.
Notable Projects
-
VaporBoy - PWA for playing ROMs with WasmBoy!
-
wasmboy-rs - Wasmboy Compiled to Rust, for native executables and additional cool features!
-
wasmboy.py - Wasmboy running in Python!
Special Thanks
-
awesome gb-dev communitty, too many rad dudes to name!
-
dcodeIO for building and fixing bugs with AssemblyScript. And for being awesome!
-
r/emudev, especially to binjimint for helping me sooooo much!
-
mooneye GB Thank you Gekkio for all the contributions to the communitty, and all the awesome tests!
-
Blargg. Wherever you may be, thank you for all the awesome tests!
Resources
-
Talk given at WebAssembly SF March 28th, 2019, general Wasm / AssemblyScript introduction, overview of WasmBoy and how it works.
-
awesome gbdev for reference material, and getting help from the awesome discord community
-
node-gameboy, binjigb, gomeboycolor for comparison for when I'm REALLY stuck.