clownmdemu - The Greatest Mega Drive Emulator Ever (Someday)

Clownacy

Member
Messages
6
Since September last year, I've been working on-and-off on a Mega Drive emulator. It's not even close to being complete, but when will it ever be? So I figure that I might as well release it now, because there will always be some feature left to be implemented, or some game that doesn't work right. Waiting for it to be 'ready' is a fool's errand.

clownmdemu!
You'll never guess what the name's short for! :‎D

screenshot-minimal.png


screenshot-debug.png



I haven't done a whole lot of testing with this, but it does appear to work with Sonic 1, 2, 3, & Knuckles, Puyo Puyo, and ROM-hacks like Sonic 2 Recreation. Sonic 3 is a little glitchy at the moment.

The basic hardware of the Mega Drive is emulated, but not to completion: things like the YM2612's SSG-EG and LFO are missing, as well as support for the VDP's Window Plane and the 68k's instruction cycle durations. Basically, games that do run in the emulator may be missing certain effects. Other games just don't boot, like Combat Cars and Micro Machines. If you want to see exactly which features are and aren't currently emulated, there's a list here.

As you can see, the emulator comes with some debugging utilities. I figure that they'll come in handy for ROM-hack development, or even just finding out how a game works internally. For example, did you know that Sonic 3's Data Select menu uses Plane B for the foreground and Plane A for the background, rather than the other way around like it usually is?

Why
I've been programming for the Mega Drive since late 2012. That's almost 10 years ago! I know practically everything there is to know about how games use the Mega Drive hardware, which means that I know everything that would have to be done in order to run those games on other platforms.

I figured that writing an emulator would be a good way to put that knowledge to the test.

Code
Unlike some other Mega Drive emulators, this one has been created entirely from scratch: no MAME or Gens code here! In fact, I think that the codebase is what makes this emulator unique: it's written in...
  • Rust? No, that's gross and bad and you should be ashamed for suggesting it. :mad:
  • C++20? Eww, no, not that overcomplicated mess.
  • Go? JavaScript? D? Python? Swift? Leave this thread now.
  • C89...? Yep, that's the one!
...You might be thinking 'Hey, that's not unique at all!', but here's the thing: my emulator is written in portable C89. What's the difference? Well, many other C projects make mistakes like using fixed-size integer types like 'uint32_t' for no reason whatsoever (they aren't even guaranteed by the C standard to exist, breaking compatibility with platforms where they don't), treating 'int' like it's always a 32-bit type (breaking compatibility with platforms where 'int' isn't 32-bit), and using logic that only works on little-endian architectures (breaking compatibility with platforms with big-endian CPUs). These projects will only work on certain platforms, while my emulator should theoretically run on any platform that you can compile C for, so long as the RAM requirements are met. Additionally, being written in strict C89 means that the emulator can be built with vintage compilers for ancient platforms (16-bit DOS port, anyone?).

Another novel feature is that the emulator is separated into two components: the core and the frontend. The core contains all of the emulation logic, while the frontend contains all of the platform-dependent code for reading input and presenting the video and audio to the user. Yes, I do intend to eventually leverage this to create a libretro core.

Another major feature of the emulator's code is that it avoids global state: all of the emulator's subsystems access their state through a struct pointer which is passed as a parameter to every function. This is essentially 'proto-C++' object-oriented C. On top of allowing multiple states to be used (thus theoretically allowing multiple Mega Drives to be emulated at once), this also makes for incredibly efficient rewind support. In fact, both rewinding and save states are entirely features of the frontend: they have been completely abstracted away from the emulation core itself.

You can read more about the quirks of clownmdemu's code in its README.

Goal
My goal with clownmdemu is not to create the most accurate Mega Drive emulator, nor is it to create the fastest. Rather, mine aims for an in-between: to make an emulator that produces 'correct' behaviour externally while being as efficient as possible internally. External accuracy, yes - internal accuracy, no. An example of this is how the FM and PSG are updated: rather than do so once every clock tick as a real Mega Drive would, the emulator only updates the FM and PSG when the 68k or Z80 attempt to access them, doing so in bulk until they have 'caught up' with the rest of the system.

Download
But what's the use in describing the emulator here? You can try it for yourself: here's a link to where you can download v0.1. Its EXE is 32-bit, and should work on versions of Windows as far back as Windows XP. If you're compiling it yourself on Linux, then that should be simple enough: the build script is CMake, and it depends on the FreeType and SDL2 libraries. Naturally, you can find the latest source code here.

Usage
The controls are currently hardcoded, but aren't hard to change if you edit the frontend's source code. You can find a list of key bindings in the emulator's README. Notably, you can quick-save with F5, quick-load with F9, fast-forward with the space key, and rewind with the R key.

Development
Since starting this emulator, I've been documenting its development on my blog. So far there have been 8 posts, which I'll list here:
I'll try to cross-post future posts here, so that anyone who's interested in this emulator can stay up-to-date with its development.
 
Last edited:
Top