I ported my Gameboy Color emulator to WebAssembly
djhworld.github.io
djhworld.github.io
I had JavaScript driving the UI interaction in my project, so to deal with locking, I let the browser control the framerate. Every requestAnimationFrame event, I compared the current time to the last frame I had drawn, and if it was time for the next, only then performed the logic to simulate the next frame. I still targeted 60 FPS, but this allowed the emulator to lag behind if the browser couldn't keep up, which seems to be a necessary compromise to maintain UI responsiveness.
You might give the requestAnimationFrame event model a try, and see if it helps with your keyboard issues. I remember having similar problems if I tried to let WASM drive the simulation directly, especially on weaker hardware.
Either way, that's nit picking all around. This is impressive stuff, and I hope you keep working on it!
Thanks for the tip about requestAnimationFrame (/u/knackers mentioned as well) I'll look into it! That's what's good about sharing this stuff - you learn something new!
I'll probably tinker with the project here and there, I want to implement another cartridge type that for some reason I left out, I found a ROM last night that wasn't supported and I think it's MBC2. But I don't intend for it to be a perfect emulator or anything, more just a sandbox to play around with. There are definitely better emulators out there that strive for accuracy.
The WebAssembly version uses the following HTML5 features:
- requestAnimationFrame for frame scheduling
- WebGL for rendering (emulator code creates a linear RGBA8 framebuffer, which is copied into a double-buffered WebGL texture, which is then rendered as a fullscreen rectangle)
- WebAudio with ScriptProcessorNode and 2048-samples output buffer size to 'render' the audio (at 44.1 kHz), technically ScriptProcessorNode is deprecated, it works surprisingly well though
- everything is running in the browser thread
- everything is written in C, no dynamic memory allocation, except at startup
I shot myself in the foot a bit when I saw the web worker thing working (ish!) and carried on down that path, so didn't really explore the other means with requestAnimationFrame etc
Will be definitely looking at it now though, it's good to know that everything can run on the browser thread!
BTW, I've never had performance problems with HTML Canvas, and I use setTimeout(), not requestAnimationFrame. The only thing I do every frame is putImageData() on a retained Uint32Array buffer. Maybe you could use the Chrome Performance devtools to figure out what is going on.
(otherwise) fantastic project, good PR for go too!
That would be fun.
Playing those old games like Uridium, Cauldron, Impossible Mission, Summer Games and Way of the exploding fist once again :)
Try reducing the frame rate lock (dropdown at the bottom) or hitting a few keys (e.g. arrow keys)