This is a very nice write up of not only Ocaml but also gameboy emulator implementation. Great job and thank you to the author!
As an aside I’ve always thought it would be awesome to create a single page app with an assembler editor and assembler/linker/loader to enable doing gameboy homebrew in the browser. I think it would be a great, accessible embedded development teaching opportunity.
I know it’s a long shot, but does anyone know of a tutorial for the sound of a game boy emulator? Most of these tutorials never cover that piece and when I try it on my own I find it hard to properly implement or even understand the reference material well enough to implement on my own.
Beautiful write-up! Thanks for sharing this. I want to write a game boy emulator in Rust and your blogpost really inspired me to kick this off. I’m bookmarking this.
Cool. The demo runs way too fast, though. The throttle checkbox doesn't really change it. Unchecking it, if anything, makes it run slower. It runs at 240 fps with throttle and at 180 fps without. With the throttle checbox active one second are already about four seconds in the emulator. I suspect this is related to the screen refresh rate, which is 240Hz in my case.
Would anyone here assert that there's any particular programming language that's better for writing emulators, virtual machines, bytecode interpreters, etc?
Where, when I say "better", I'm not so much talking about getting results that are particularly efficient/performant; nor in making fewer implementation errors... but more in terms of the experience of implementing an emulator in this particular language, being more rewarding, intuitive, and/or teaching you more about both emulators and the language.
I ask because I know that this sort of language exists in other domains. Erlang, for example, is particularly rewarding to implement a "soft-realtime nine-nines-of-uptime distributed system" in. The language, its execution semantics, its runtime, and its core libraries, were all co-designed to address this particular problem domain. Using Erlang "for what it's for" can thus teach you a lot about distributed systems (due to the language/runtime/etc guiding your hand toward its own idiomatic answers to distributed-systems problems — which usually are "best practice" solutions in theory as well); and can lead you to a much-deeper understanding of Erlang (exploring all its corners, discovering all the places where the language designers considered the problems you'd be having and set you up for success) than you'd get by trying to use it to solve problems in some other domain.
Is there a language like that... but where the "problem domain" that the language's designers were targeting, was "describing machines in code"?
Ocaml is really good for this, and is usually "fast enough" for most things. When you REALLY need speed, there is the oxcaml project by jane street that gets you all sorts of perf improvements and close to C speed, while still having a GC for things not critical for raw speed.
> Would anyone here assert that there's any particular programming language that's better for writing emulators, virtual machines, bytecode interpreters, etc?
No, absolutely not. Emulation is super easy to implement in any language with arrays (constant-time lookup of arbitrary indices) and bit operations. At least before considering JIT.
And even functional languages have arrays and bitwise operations.
I would argue that systems languages (C, C++, Rust, and Zig standout) are the most “fulfilling” (in my experience).
The reason being that the methodologies are far more orthogonal. A uint8 directly represents a byte in memory, doing a memcpy is equivalent to a blit, etc. You spend far less time trying to wrangle a JavaScript Number type into acting like a byte/word/etc for a bitshift operation for a simple ADC. A very simple example that you’ll run into in the first day of writing a js emulator.
That all being said, if the language can paint to some surface and has the memory size to handle the machine you’re emulating, they’re all roughly equivalent. So the answer becomes “whichever language you’re most comfortable with is the one writing an emulator in is most enjoyable”.
12 comments
[ 2.8 ms ] story [ 28.5 ms ] threadAs an aside I’ve always thought it would be awesome to create a single page app with an assembler editor and assembler/linker/loader to enable doing gameboy homebrew in the browser. I think it would be a great, accessible embedded development teaching opportunity.
I wanna compare a CHIP 8 or NES emulator or port CAMLBOY to WASM using ocaml-wasm
Needs a (2022).
Where, when I say "better", I'm not so much talking about getting results that are particularly efficient/performant; nor in making fewer implementation errors... but more in terms of the experience of implementing an emulator in this particular language, being more rewarding, intuitive, and/or teaching you more about both emulators and the language.
I ask because I know that this sort of language exists in other domains. Erlang, for example, is particularly rewarding to implement a "soft-realtime nine-nines-of-uptime distributed system" in. The language, its execution semantics, its runtime, and its core libraries, were all co-designed to address this particular problem domain. Using Erlang "for what it's for" can thus teach you a lot about distributed systems (due to the language/runtime/etc guiding your hand toward its own idiomatic answers to distributed-systems problems — which usually are "best practice" solutions in theory as well); and can lead you to a much-deeper understanding of Erlang (exploring all its corners, discovering all the places where the language designers considered the problems you'd be having and set you up for success) than you'd get by trying to use it to solve problems in some other domain.
Is there a language like that... but where the "problem domain" that the language's designers were targeting, was "describing machines in code"?
No, absolutely not. Emulation is super easy to implement in any language with arrays (constant-time lookup of arbitrary indices) and bit operations. At least before considering JIT.
And even functional languages have arrays and bitwise operations.
The reason being that the methodologies are far more orthogonal. A uint8 directly represents a byte in memory, doing a memcpy is equivalent to a blit, etc. You spend far less time trying to wrangle a JavaScript Number type into acting like a byte/word/etc for a bitshift operation for a simple ADC. A very simple example that you’ll run into in the first day of writing a js emulator.
That all being said, if the language can paint to some surface and has the memory size to handle the machine you’re emulating, they’re all roughly equivalent. So the answer becomes “whichever language you’re most comfortable with is the one writing an emulator in is most enjoyable”.