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, ...)
• JIT recompiler for fast emulation
• OpenGL renderer, 3D upscaling
• RTC, microphone, lid close/open
• Joystick support
• Savestates
• Various display position/sizing/rotation modes
• (WIP) Wifi: local multiplayer, online connectivity
• (WIP) DSi emulation
• DLDI
• (WIP) GBA slot add-ons
• and more are planned!







Download melonDS

If you're running into trouble: Howto/FAQ
Hardware renderer progress
Hey hey, little status update! I've been having fun lately.



The hardware renderer has been progressing nicely lately. It's always exciting when you're able to assemble the various parts you've been working on into something coherent, and it suddenly starts looking a lot like a finished product. It's no longer just something I'm looking at in RenderDoc.

Those screenshots were taken with 4x upscaling (click them for full-size versions). The last one demonstrates hi-res rotscale in action. Not bad, I dare say.

It's not done yet, though, so I'll go over what remains to be done.


Mosaic

Shouldn't be very difficult to add.

Except for, you know, sprite mosaic. I don't really know yet how I'll handle that one. The way it works is intuitive if you're processing pixels left-to-right within a scanline, but this isn't how a modern GPU works.


Display capture

... read more
Hardware rendering, the fun
This whole thing I'm working on gives me flashbacks from blargSNES. The goal and constraints are different, though. We weren't doing upscaling on the 3DS, but also, we had no fragment shaders, so we were much more limited in what we could do.

Anyway, these days, I'm waist-deep into OpenGL. I'm determined to go further than my original approach to upscaling, and it's a lot of fun too.

I might as well talk more about that approach, and what its limitations are.

First, let's talk about how 2D layers are composited on the DS.

There are 6 basic layers: BG0, BG1, BG2, BG3, sprites (OBJ) and backdrop. Sprites are pre-rendered and treated as a flat layer (which means you can't blend a sprite with another sprite). Backdrop is a fixed color (entry 0 of the standard palette), which basically fills any space not occupied by another layer.

For each pixel, the PPU keeps track of the two topmost layers, based on priority orders.

Then, you have the BLDCNT register, which lets you choose a color effect to be applied (blending or fade effects), and the target layers it may apply to. For blending, the "1st target" is the topmost pixel, and the "2nd target" is the pixel underneath. If the layers both pixels belong to are adequately selected in BLDCNT, they will be blended together, using the coefficients in the BLDALPHA register. Fade effects work in a similar fashion, except since they only apply to the topmost pixel, there's no "2nd target".

Then you also have the window feature, which can exclude not only individual layers from a given region, but can also disable color effects. There are also a few special cases: semi-transparent sprites, bitmap sprites, and the 3D layer. Those all ignore the color effect and 1st target selections in BLDCNT, as well as the window settings.

In melonDS, the 2D renderer renders all layers according to their priority order, and keeps track of the last two values for each pixel: when writing a pixel, the previous value is pushed down to a secondary buffer. This way, at the end, the two buffers can be composited together to form the final video frame.

... read more
melonDS 1.1 is out!
As promised, here is the new release: melonDS 1.1.

So, what's new in this release?

EDIT - there was an issue with the release builds that had been posted, so if your JIT option is greyed out and you're not using a x64 Mac, please redownload the release.


DSP HLE

This is going to be a big change for DSi gamers out there.

If you've been playing DSi titles in melonDS, you may have noticed that sometimes they run very slow. Single-digit framerates. Wouldn't be a big deal if melonDS was always this slow, but obviously, it generally performs much better, so this sticks out like a sore thumb.

This is because those titles use the DSi's DSP. What is the DSP, you ask? A specific-purpose (read: weird) processor that doesn't actually do much besides being very annoying and resource-intensive to emulate. They use it for such tasks as downscaling pictures or playing a camera shutter sound when you take a picture.

With help from CasualPokePlayer, we were able to figure out the 3 main classes of DSP ucodes those games use, determine their functionality, and implement HLE equivalents in melonDS. Thus, those wonderful DSP features can be emulated without utterly wrecking performance.

DSP HLE is a setting, which you will find in the emulation settings dialog, DSi-mode tab. It is enabled by default.

... read more
Hi-res display capture: we're getting there!
Sneak peek of the blackmagic3 branch:


(click them for full-res versions)

Those are both dual-screen 3D scenes, but notice how both screens are nice and smooth and hi-res.

Now, how far along are we actually with this?

As I said in the previous post, this is an improved version of the old renderer, which was based on a simple but limited approach. At the time, it was easy enough to hack that on top of the existing 2D engine. But now, we're reaching the limits of what is possible with this approach. So, consider this a first step. The second step will be to build a proper OpenGL-powered 2D engine, which will open up more crazy possibilities as far as graphical enhancements go.

I don't know if this first step will make it in melonDS 1.1, or if it will be for 1.2. Turns out, this is already a big undertaking.

I added code to keep track of which VRAM blocks are used for display captures. It's not quite finished, it's missing some details, like freeing capture buffers that are no longer in use, or syncing them with emulated VRAM if the CPU tries to access VRAM.

It also needs extensive testing and optimization. For this first iteration, for once, I tried to actually build something that works, rather than spend too much time trying to imagine the perfect design. So, basically, it works, but it's inefficient... Of course, the sheer complexity of VRAM mapping on the DS doesn't help at all. Do you remember? You can make the VRAM banks overlap!

So, yeah. Even if we end up making a new renderer, all this effort won't go to waste: we will have the required apparatus for hi-res display capture.

... read more
Display capture: oh, the fun!
This is going to be a juicy technical post related to what I'm working on at the moment.

Basically, if you've used 3D upscaling in melonDS, you know that there are games where it doesn't work. For example, games that display 3D graphics on both screens: they will flicker between the high-resolution picture and a low-resolution version. Or in other instances, it might just not work at all, and all you get is low-res graphics.

It's linked to the way the DS video hardware works. There are two 2D tile engines, but there is only one 3D engine. The output from that 3D engine is sent to the main 2D engine, where it is treated as BG0. You can also change which screen each 2D engine is connected to. But you can only render 3D graphics on one screen.

So how do those games render 3D graphics on both screens?

This is where display capture comes in. The principle is as follows: you render a 3D scene to the top screen, all while capturing that frame to, say, VRAM bank B. On the next frame, you switch screens and render a 3D scene to the bottom screen. Meanwhile, the top screen will display the previously captured frame from VRAM bank B, and the frame you're rendering will get captured to VRAM bank C. On the next frame, you render 3D graphics to the top screen again, and the bottom screen displays the capture from VRAM bank C. And so on.

This way, you're effectively rendering 3D graphics to both screens, albeit at 30 FPS. This is a typical use case for display capture, but not the only possiblity.

Display capture can receive input from two sources: source A, which is either the main 2D engine output or the raw 3D engine output, and source B, which is either a VRAM bank or the main memory display FIFO. Then you can either select source A, or source B, or blend the two together. The result from this will be written to the selected output VRAM bank. You can also choose to capture the entire screen or a region of it (128x128, 256x64 or 256x128).

All in all, quite an interesting feature. You can use it to do motion blur effects in hardware, or even to render graphics to a texture. Some games even do software processing on captured frames to apply custom effects. It is also used by the aging cart to verify the video hardware: it renders a scene and checksums the captured output.

For example, here's a demo of render-to-texture I just put together, based on the libnds examples:

... read more
Happy birthday melonDS!
Those of you who know your melonDS lore know that today is a special day. melonDS is 9 years old!



...hey, I don't control this. 9 is brown. I don't make the rules.

Anyway, yeah. 9 years of melonDS. That's quite the achievement. Sometimes I don't realize it has been so long...

-

As far as I'm concerned, there hasn't been a lot -- 2025 has had a real shitty start for me. A lot of stuff came forward that has been really rough.

On the flip side, it has also been the occasion to get a fresh start. I was told about IFS therapy in March, and I was able to get started. It has been intense, but so far it has been way more effective than previous attempts at therapy.

I'm hopeful for 2026 to be a better year. I'm also going to hopefully get started with a new job which is looking pretty cool, so that's nice too.

-

... read more
The joys of programming
There have been reports of melonDS 1.0 crashing at random when running multiple instances. This is kind of a problem, especially when local multiplayer is one of melonDS's selling points.

So I went and tried to reproduce it. I could get the 1.0 and 1.0RC builds to crash just by having two instances open, even if they weren't running anything. But I couldn't get my dev build to crash. I thought, great, one of those cursed bugs that don't manifest when you try to debug them. I think our team knows all about this.

Not having too many choices, I took the 1.0 release build and started hacking away at it with a hex editor. Basic idea being, if it crashes with no ROM loaded, the emulator core isn't the culprit, and there aren't that many places to look. So I could nop out function calls until it stopped crashing.

In the end, I ended up rediscovering a bug that I had already fixed.

The SDL joystick API isn't thread-safe. When running multiple emulator instances in 1.0, this API will get called from several different threads, since each instance gets its own emulation thread. I had already addressed this 2.5 months ago, by adding adequate locking.

I guess at the time of 1.0, it slipped through the cracks due to its random nature, as with many threading-related bugs.

Regardless, if you know your melonDS lore, you know what is coming soon. There will be a new release which will include this fix, among other fun shit. In the meantime, you can use the nightly builds.
Sneak peek
Just showing off some of what I've been working on lately:



This is adjacent to something else I want to work on, but it's also been in the popular request list, since having to manually enter cheat codes into melonDS isn't very convenient: would be much easier to just import them from an existing cheat code database, like the R4 cheat database (also known as usrcheat.dat).

It's also something I've long thought of doing. I had looked at usrcheat.dat and figured the format wasn't very complicated. It was just, you know, actually making myself do it... typical ADHD stuff. But lately I felt like giving it a look. I first wrote a quick PHP parser to make sure I'd gotten the usrcheat.dat format right, then started implementing it into melonDS.

For now, it's in a separate branch, because it's still quite buggy and unfinished, but it's getting there.

The main goal is complete, which is, it parses usrcheat.dat, extracts the relevant entries, and imports them into your game's cheat file. By default, it only shows the game entry which matches your game by checksum, which is largely guaranteed to be the correct one. However, if none is found, it shows all the game entries that match by game code.

It also shows a bunch of information about the codes and lets you choose which ones you want to import. By default, all of them will be imported.

This part is mostly done, besides some minor UI/layout bugs.

The rest is adding new functionality to the existing cheat code editor. I modified the melonDS cheat file format (the .mch files) to add support for the extra information usrcheat.dat provides, all while keeping it backwards compatible, so older .mch files will still load just fine. But, of course, I also need to expose that in the UI somehow.

... read more
Not much to say lately...
Yeah...

I guess real life matters don't really help. Atleast, my mental health is genuinely improving, so there's that.

But as far as my projects are concerned, this seems to be one of those times where I just don't feel like coding. Well, not quite, I have been committing some stuff to melonDS... just not anything that would be worthy of a juicy blog post. I also had another project: porting my old SNES emulator to the WiiU gamepad. I got it to a point where it runs and displays some graphics, but for now I don't seem motivated to continue working on it...

But I still have some ideas for melonDS.

One idea I had a while ago: using the WFC connection presets to store settings for different altWFC servers. For example, using connection 1 for Wiimmfi, connection 2 for Kaeru, etc... and melonDS would provide some way of switching between them. I don't know how really useful it would be, or how feasible it would be wrt patching requirements, but it could be interesting.

Another idea would be RTCom support. Basically RTCom is a protocol that is used on the 3DS in DS mode to add support for analog sticks and such. It involves game patches and ARM11-side patches to forward input data to RTC registers. The annoying aspect of this is that each game seems to have its own ARM11-side patch, and I don't really look forward to implementing a whole ARM11 interpreter just for this.

But maybe input enhancements, be it RTCom stuff or niche GBA slot addons, would make a good use case for Lua scripting, or some kind of plugin system... I don't know.

There are other big ideas, of course. The planned UI redesign, the netplay stuff, website changes, ...

Oh well.
Fix for macOS builds
Not a lot to talk about these days, as far as melonDS is concerned. I have some ideas, some big, some less big, but I'm also being my usual ADHD self.

Anyway, there have been complaints about the macOS builds we distribute: they're distributed as nested zip files.

Apparently, those people aren't great fans of Russian dolls...

The issue is caused by the way our macOS CI works. I'd have to ask Nadia, but I think there isn't really an easy fix for this. So the builds available on Github will have to stay nested.

However, since I control this site's server, I can fix the issue here. So now, all the macOS builds on the melonDS site have been fixed, they're no longer nested. Similarly, new builds should also be fixed as they're uploaded. Let us know if anything goes wrong with this.