This is awesome! Very nicely done. I hear a few problems with the audio emulation, (mostly clicks that shouldn't be there) but it's been a long while since I had my head wrapped around Gameboy emulation. I'm not sure I know what's going wrong exactly.
I love how Rust+WASM is an enabler for showing off applications like this which would traditionally be restricted to a desktop environment. Here's my own, an NES emulator, using wasm-bindgen for the translation but otherwise a similar setup:
It's so cool to work on a bit of homebrew, then be able to share a link with someone and have it "just work" in their browser. No weird tools, no shady sites, just my game and their feedback.
> I hear a few problems with the audio emulation, (mostly clicks that shouldn't be there)
Almost anything WASM+Audio seems to do that in browsers today, unless you're really really careful about what you're doing and leverage multiple threads. I think the issue is mostly around single-thread contexts, where it has to switch between playing audio and other things.
I hit the very same issue myself with Bevy not too long time ago, and tracking this issue which has some further links if you wanna go down a rabbit-hole: https://github.com/bevyengine/bevy/issues/4078
What I've found is that essentially WebAudio has such a terrible performance that the audio buffers need to be at minimum 100ms. And if you have a bad frame or any jank in your RAF is likely to glitch at least occasionally.
Compare this to when running natively 20ms audio buffers are fine.
I've settled on a design where I run all the audio graphs and audio decoding in a separate thread and then queue the audio buffers for the main JS thread to pick up and make the WebAudio calls. The same has to be done for the graphics (WebGL) as well. This can be major paradigm shift if the initial design has been done around doing stuff independently on the background. On the web.. no can do.
Bonus tip, if you're planning to use the OpenAL implementation that Emscripten provides my only advice is.. don't.
i combed through quite a few hobbyist gb emulators while writing mine and found audio to be pretty rarely finished or finished without issues. not sure if it's the same for NES
Audio is *surprisingly* tricky on both platforms. NES has DPCM, which cheerfully interrupts the CPU and causes untold issues with controller reading. Gameboy has envelopes that are semi-required with phase-resets, and a wave channel which you in theory cannot write new samples to, and developer hacks to work around both. Both systems have various hardware revisions that have subtly different behavior, and a handful of games that will break on that specific model. It's fun!
It's also more involved to verify operation. Graphics are easier to "measure" and compare. Sound is also much more timing-dependent, e.g. when timers are running on their own all the time. It's disconcerting when sound is slightly off in games.
I love how Rust+WASM is an enabler for showing off applications like this which would traditionally be restricted to a desktop environment. Here's my own, an NES emulator, using wasm-bindgen for the translation but otherwise a similar setup:
https://rustico.reploid.cafe/?cartridge=patreon/tactus-v0.7-...
It's so cool to work on a bit of homebrew, then be able to share a link with someone and have it "just work" in their browser. No weird tools, no shady sites, just my game and their feedback.