melonDS aims at providing fast and accurate Nintendo DS emulation. While it is still a work in progress, it has a pretty solid set of features:

• Nearly complete core (CPU, video, audio, ...)
• OpenGL renderer, 3D upscaling
• RTC, microphone, lid close/open
• Joystick support
• Savestates
• Various display position/sizing/rotation modes
• (WIP) Wifi: local multiplayer, online connectivity
• and more are planned!

Download melonDS

If you're running into trouble: Howto/FAQ

If you're feeling generous: melonDS Patreon

[DSi shito]

It doesn't get further than this though, but, considering the amount of work this required, between implementing the newfangled DSi hardware and fixing stupid bugs, this isn't a bad start. We can also thank Martin Korth and all the other comrades who have been paving the way and making this possible at all.

This is nowhere near ready for a release tho. It's an experimental branch in which I felt like playing around with things, attempting to boot a DSi firmware, and, well, this happened.

This also requires a bunch of data that have to be dumped from a DSi:

* NAND dump
* console ID
* RSA/Blowfish/AES keys

Those can be dumped from a DSi with unlaunch, but we will need a user-friendly way to do so.


There is also the issue that, well, this isn't completely clean and perfect.

... read more
melonDS 0.8.1
melonDS 0.8.1 is out, and that fixes some of the issues that were discovered in 0.8 (mostly stupid oversights, heh), but also adds a few other features and fixes. Let's see.

Edit- If fast forward doesn't work for you, it means one of two things: you're using OpenGL and your video driver is forcing vsync, or melonDS is just not running fast enough for fast-forward.

Input upgrade

The input code has been reworked to be more pleasant to deal with, especially with regards to adding hotkeys. In less nerdy terms, what does this mean?

It is now possible to map keys with modifiers, like Ctrl+Z or Shift+R or even combinations like Ctrl+Alt+Q. It is worth noting that during mapping, you should use left-hand Ctrl/Alt/Shift keys for these mappings. However, ingame, both sets of keys should work. This feature may not be too useful for DS input, but it should be more handy for hotkeys. It is also possible to delete a key mapping by pressing the Backspace key during the mapping process.

I have also been upgrading joystick support. You can now choose which joystick to use, and can map axes to buttons/hotkeys.

The twist to this is that I liked the old "axis maps to DS dpad" feature, and how it could be used alongside regular button/hat controls. I didn't want to lose the ability to use both, but I also wanted to make it, well, not a hardcoded mapping. So instead, you can map both a button/hat direction and an axis to each control. When mapping a joystick control, pressing a button/hat direction keeps the axis mapping intact, and vice-versa. You can delete both mappings by pressing Backspace during the mapping process.

The aforementioned axis support should also be able to support analog triggers, which are typically exposed as axis controls.

... read more
Defying all expectations
After a good while of working on the OpenGL renderer, fixing its issues for a 0.8.1 release, attempting to add some features, I figured I'd look at some of the old game issues. melonDS has reached a point where almost every known game bug is a timing issue, but not all of them are.

In particular, this issue: graphical glitches in iCarly - Groovy Foodie.

When it was posted, I didn't look much into it, thinking that was my topnotch software renderer acting up, and hastily giving it the '3D accuracy' label to put it on the backburner.

So I thought, hey, let's see if this is any different with the OpenGL renderer?

Which is where this bug started defying my expectations. Software or OpenGL, it didn't matter, the graphics looked the same. But, when I tested the game under DeSmuME and NO$GBA, they both exhibited the same bug.

Which is where I knew that we were in for an interesting ride. Typically, emulation bugs in melonDS are either specific to melonDS, meaning it's a flaw in my implementation, or they're shared with NO$GBA but not DeSmuME, which means that is some hardware behavior that was discovered by the DeSmuME team but did not yet make it into GBAtek. But with a bug that happens in every of these emulators, we know that we're stepping in uncharted territory.

So, as usual, we start by investigating how the game renders its graphics. The issue has nothing to do with 3D graphics at all, as it's not using the 3D engine. In particular, the glitched intro logo on the top screen is made of sprites, but looking at NO$GBA's sprite viewer shows there's something fishy behind this.

We only have a handful of the 16x16 sprites that make up the logo. Where's the rest?

... read more
Hotfix release
If you downloaded melonDS 0.8 before this post, please redownload it, we just pushed a hotfix release.

This should fix broken 3D rendering with OpenGL, namely for AMD/Intel GPU users.

Seems hotfix releases are a common theme with melonDS :P
melonDS 0.8
It's been awaited for so long, and finally, by popular request, here it is: melonDS 0.8, with OpenGL renderer and upscaling!

So, without further ado, let's discover all the details of this.

The OpenGL renderer

This renderer is an attempt at targeting a sweet spot of, say, 90% compatibility while being fast. If you have read the previous posts about the DS GPU and how quirky that thing is compared to your average GPU, you guess that perfect rendering with OpenGL isn't going to be possible, but we can do our best.

The current renderer supports most of the DS GPU features, but not all of them. There is room for improvement, but certain features will just not be implemented. For the games that happen to require those, we still have our old trusty, nearly pixel-perfect software renderer.

But, the OpenGL renderer opens the door to all sorts of graphical improvements. I have plans in mind for more features (namely, some form of texture filtering), but I will draw a line as to keep the codebase not too complex.


The OpenGL renderer is enabled by default, but you can go to the video settings dialog to configure it. Namely, this renderer supports increasing the internal resolution to up to 8x the native resolution.

... read more
Getting there!

OpenGL output under Linux! About fucking time.

Was it a ride to get there, though.

As I explained in a previous post, the first attempts with a GtkGLArea were a trainwreck. GtkGLArea is nice and all, but it's really limited in how much control you have over rendering, compared to, say, the Windows equivalent (get a GL context for any HWND and do whatever you want).

For one, GtkGLArea provides no control over its GL context, other than "make context current now". No way to unset the current GL context, which is important in melonDS. Even though all the rendering is done in the emu thread, we do need to unset the GL context at times, because when changing video settings we do reconfiguration from the UI thread, and said reconfiguration involves GL calls.

But, well. You may already know that GTK isn't thread-safe. As such, GtkGLArea really isn't designed to be used outside of the UI thread, or outside of one particular way. So, unless we rewrote melonDS's rendering system, this would have never worked. Besides, the emu thread is distinct from the UI thread for a reason -- I'm reluctant to having any work that may affect emulation done on something as uncertain as the UI thread.

So, I began researching.

And, now, the melonDS company proudly presents the result of all that research: the DIY GL area.

Basically, I decided to directly use GDK's GL context API to get the level of control I needed. With this, you don't need a specific widget type, you can create a GL context from any GdkWindow (which you obtain from any realized GTK widget). You can then use the function gdk_cairo_draw_from_gl() to draw your OpenGL output to the widget.

... read more
The final step: getting it all to work under Linux
Well, yeah, or almost. It works, and is nearly clean, but only under Windows, because I didn't code the required support for GTK.

And I'm not getting into the Mac side, which I will have to get into eventually. Getting OSX working in a VM and managing to do things under an environment I'm completely unfamiliar with is going to be a whole pile of fun, I can feel it already.

Anyway, back on topic, and get ready for a big moment of 'fuck technology'.

So, I happily went and booted under Linux, getting ready to code shit and expecting to have it working without too much trouble. Just spawn a GtkGLArea and you're good to go, right?

Haha. You're cute.

I'm not getting into the hours wasted by fighting ass-obscure issues that, in the end, mostly translated to 'you need to update your distro'. When all that was done, PoroCYon had already started working on the GTK-side code, so I just grabbed their pull request. With a bit of work, I finally got OpenGL going.

Yeah, except it's a total and complete fucking trainwreck.

Basically, it's not rendering anything. When resizing the window, I can sometimes get a nearly-complete static picture with more or less distortion, as if it was reading random video memory, but it will inevitably crash at some point.

Because, of course.

... read more
OpenGL renderer: requirements and details
OpenGL rendering in melonDS will require OpenGL 3.1 as a minimum.

I think that given the reports I got in this thread, this puts us at a sweet spot. Certain features (like accurate shadow support) may require higher OpenGL versions, but the 3.1 baseline allows us to support a large part of user platforms/setups, including Macs.

Technically, OpenGL 3.1 is the lowest we can go with the current renderer setup. Any lower would require partially rewriting it to get around the limitations.

There is also more chance of eventually porting this to OpenGL ES, which might open the way for Android or PSVita ports that don't run at crapoed-snail speeds.

I'm sorry for the toaster-rocking folks out there who are stuck on lower OpenGL versions. We are still keeping the software renderer and the old Direct2D-based window drawing code, so you aren't completely left out. Besides, there are still other emulators (DeSmuME, NO$GBA) supporting older OpenGL versions.


We will be using OpenGL to draw the DS framebuffer to the window. This mode will be an option when using the software renderer, and forcibly enabled when using the OpenGL renderer (they work faster together).

This may eventually allow for features like fancypants postprocessing shaders. Not for melonDS 0.8, but eventually, later on.

Upscaling will also be restricted to the OpenGL renderer. It makes little sense with the software renderer as that one cannot do upscaling, and the performance would likely be subpar if it tried.
The DS GPU interpolation
I said a while back that I'd be writing about how the DS GPU interpolates vertex attributes when drawing polygons, so, here we go.

As explained in our previous technical post, vertex attributes are interpolated twice: once along the polygon edges, and once along the scanline being drawn.

The details of how those are interpolated is where the meat is. A typical 3D rasterizer will perform perspective-correct interpolation, which is meant to take perspective distortion into account when drawing a polygon that has been projected to 2D screen space. There are early rasterizers that use different interpolation types, for example, the Playstation does affine texture mapping.

In the case of the DS, it does perspective-correct texture mapping and shading.

The basics

This is the canonical formula for perspective-correct interpolation over a given span:

- x is the position within the span, units don't matter (as long as they're consistent with xmax)
- xmax is the length of the span
- A0 and A1 are the attributes at each end of the span
- W0 and W1 are the associated W coordinates
- Ax is the interpolated attribute at position x

Rasterizers implement this formula in one way or another. For example, it is typical for software rasterizers to start by dividing all vertex attributes by W, so those can be interpolated linearly, then divide them by the W reciprocal to recover the correct values for each pixel. I don't know much about how typical GPUs implement this.

... read more