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
How far we have gone, and where we are going next
melonDS has been going for one year now.

Well, the repo was opened in May 2016, but the real work started in November 2016.

I didn't really know what I was in for, but hey, I wanted to have fun making something new. There wasn't much else in terms of goals, other than the famous goal of successfully emulating local wifi.

Of course, getting an emulator project going is initally a gruelling task, as it takes quite a bit of work before you can get interesting results. In the case of the DS, as I went with the goal of emulating the BIOS boot procedure, there was quite a lot to be done before the firmware would try to display things. In the case of melonDS, it took about 2.5 months to get there, but I don't consider it a good idea to look at durations. I was unemployed at the time (or rather, waiting to start that job), I'm a lazy fuck, and a couple vicious CPU bugs got in the way.

The first release of melonDS was a mere curiosity. It was inferior to the existing emulators. But that didn't matter, it was out there for the curious, and I was having fun with that project. The next releases would deliver quality.

The 3D renderer was my first attempt at a polygon rasterizer. I initially fumbled getting things like perspective correction working, but gradually gained more understanding of the process. Conducted tests to try understanding how the actual GPU did things and which shortcuts it took. And it has been an interesting ride.

I guess it turned out okay. This renderer has become the most accurate among all DS emulators. I thought, since the 2D renderer is going to be pixel-perfect, why not make 3D pixel-perfect too? I'm not there yet though, but the renderer is more than good enough for most games. Not good enough for the aging cart tests (which demand perfection to the pixel), but I put that on hold for a while.

On the other hand, the renderer code evolved as I discovered things, and is probably not as clean as it could be. In long term, it could benefit from a rewrite.


And this shit has been going on for one year now. Time flies, it's crazy.

... read more
melonDS 0.5, finally!
Yup, there it is.





It's a recurrent theme in my projects that UI shenanigans are something I have trouble with. It's not that hard to make a UI, but making it cross-platform is another deal entirely. I want to avoid ending up with a different, separate UI per platform.

In the end, I went with libui, which is small and lightweight. I modified it to fit my needs.

The decision took a while though, and is one of the reasons why the release took so long to happen. Other reasons being, well, real life. My previous job is over, and hello job hunting again.


So this release features a new UI. It's not too new, but it removes the unneeded windows. Menus and video output are in the same window now, and the console window (the black window that spews nonsense) will be absent from release builds.

You can also drag-drop ROMs onto the window to run them. It is also possible to run ROMs via command line, but ATM when doing so melonDS will attempt to look for BIOS/firmware/INI in the directory the ROM is in.

If you play with your keyboard, you will need to remap your input, as different key codes are used (raw scancodes vs SDL scancodes).

Other than that, there are not a whole lot of changes emulation-wise. A few fixes, and the addition of antialiasing, as mentioned in the previous post.

... read more
Antialiasing
This is indeed what has been worked on lately, so congrats to those who guessed right :P

As well as finding out that my edge slope functions weren't perfect. I tried, with moderate success, to make them more accurate, but they're still not perfect. So for now, I need to let it cool down. I decided I would make antialiasing 'good enough', then start working on the UI. Considering that there are other areas of the GPU that aren't perfect, like polygon clipping.

So here's a couple screenshots:



I picked cases where the result is quite visible. Antialiasing generally makes things look better, but whether it is that visible depends on what's being rendered.


Antialiasing may look like one of those minor details that are unimportant. But I consider it important to emulate, past the effect of making things look nicer: the way it works on the DS is very different from common antialiasing techniques. If you're into DS homebrew, you can't just turn on antialiasing to magically make things look better.

To begin with, antialiasing is applied to polygon edges based on their slopes, in order to make the edges look smoother. There is no antialiasing applied inside polygons or at intersections between two polygons.

Antialiasing also doesn't apply to translucent polygons. But actually, it's more complex than that -- the polygon fill rules depend on whether the individual pixel being rendered is translucent. So if a polygon has opaque and translucent pixels at its edges, the opaque parts will be antialiased and the translucent parts won't be.

The effect was shown in the following dasShiny screenshot. Note that dasShiny only has partial antialiasing support, it is only applied to Y-major edges.

... read more
Sneak peek
The 3D renderer is being worked on, and for example, this is in the works:



I'll let you guess ;)


Work is also being put into figuring out the exact GPU algorithms. What has been done so far is a double bonus: not only is the renderer more accurate, it's also faster as a result of doing less divisions per pixel. The GPU takes shortcuts, so figuring them out allows for this kind of double-bonus optimization.

For example:



The buttons have dents in their borders, that are also visible on hardware. Those are caused by interpolation quirks. Artificially perfect interpolation will make the buttons look "perfect".

It's a tiny detail that likely doesn't matter to a whole lot of gamers, but as I said, I like figuring out the logic behind what I'm observing :P

Besides, it can't be bad to have an accurate renderer. You never know when a homebrew dev or ROM hacker may run into GPU quirks, but they may find about those more easily if they can reproduce the quirks on an emulator.

... read more
Slowdown
So things have been quiet lately. My apologies for that, and I can assure you that melonDS isn't dead.


First thing is that real life is striking back. My current job is ending at the end of this month, and I need to finish their project (fresh new website) and put it live. Most of it is done already, but it takes time to check everything and ensure it's alright and looks nice and all. So this occupies my mind more.


I'm also busy with parts of the melonDS adventure that don't produce a whole lot of visual results. For one, I'm investigating interpolation, and once again we're into weird land.

Z interpolation, for example: the depth buffer is 24-bit, but in Z-buffering mode, interpolation suffers from precision loss at various stages. The output precision actually depends on the value range being interpolated over (the greater the difference, the bigger the precision loss).

W-buffering doesn't have these issues as it uses untransformed W values, and uses the regular perspective-correct interpolation path (while Z-buffering requires using special linear interpolation as transformed Z values are already linear into screen space).

Regular perspective-correct interpolation is weird too. It seems to apply correction to W values based on their first bit. I don't quite see what was intended there, if it was intended at all -- after all, it could just be a hardware glitch. But regardless, that causes slight differences that can have visible effects. It's generally a texture being one pixel off, so one would say it doesn't really matter, but I like figuring out the logic behind what I'm observing.


I also want to finally tackle the UI. melonDS has become a fairly solid emulator, but the current UI doesn't really reflect that.

I still haven't picked something to go with, though. I think I'll pick something lightweight, like byuu's hiro, and modify it to interoperate nicely with SDL. I'm not sure how well that can work across platforms, but ideally I would create a SDL window and add a menubar to it, rather than having two separate windows.


I'm also thinking about a buildbot type thing. People wouldn't have to wait for proper releases, but on the other hand, I fear it reduces or kills my incentive to do proper releases.
Why there is no 32-bit build of melonDS
The main reason is that I don't have an incentive to provide 32-bit builds. Most people already have 64-bit OSes.

That being said, melonDS can currently run on 32-bit platforms. It may be less performant, as the 3D renderer does a lot of 64-bit math, but it is still possible.

But if I ever decide to implement a JIT, for example, there will be no 32-bit version of it.


If you're stuck on a 32-bit OS for hardware reasons, your computer will not be fast enough to run melonDS at playable speeds.

melonDS will be optimized, it will run faster, but it will also tend towards more accuracy. So I can't tell how fast it will be in the end. But I highly doubt it will run well on a PC from 2004. Maybe it will, if a JIT is made, but that's not a high priority task.

If you are stuck on such hardware, NO$GBA is a better choice for you. Or NeonDS if you don't mind lacking sound. Or hell, the commonly mentioned method of running DraStic in an Android emulator -- those who bash DeSmuME at every turn claim it's fast.


Truth is, emulating the DS is not a walk in the park. People tend to assume it should be easy to emulate fast because the main CPU is clocked at a measly 66MHz. Let's see:

There are two CPUs. ARM9 and ARM7, 66MHz and 33MHz respectively. Which means you need to keep them more or less in sync. Each time you stop emulating one CPU to go emulate the other (or to emulate any other hardware) impacts performance negatively, but synchronizing too loosely (not enough) can cause games to break. So you need to find the right compromise.

The ARM7 generally handles tasks like audio playback, low-level wifi access, and accessing some other peripherals (power management, firmware FLASH...). All commercial games use the same ARM7 program, because Nintendo never provided another one or allowed game devs to write their own. This means that in theory the ARM7 could be emulated in HLE. In practice, this has never been attempted, unless DraStic happens to do it. It's also worth noting that it would be incompatible with homebrew, since they don't use Nintendo's ARM7 program.

... read more
melonDS 0.4 -- It's here, finally!


melonDS 0.4 was long awaited, and finally, it's here!

So here's a quick rundown of the changes since 0.3. I'm keeping the best for the end.


The infamous boxtest bug that plagued several games has finally been fixed. The bug generally resulted in missing graphics.

The boxtest feature of the DS lets you determine whether a given box is within the view volume. Several games use it to avoid submitting geometry that would end up completely offscreen. A prime example would be Nanostray, which uses it for everything, including 2D menu elements that are always visible.

Technically, you send XYZ coordinates and sizes to the GPU, which calculates the box vertices from that. The box faces are then transformed and clipped like regular geometry, and the test returns true if any geometry makes it through the process (which would mean that it appears onscreen). This also means that the result will be false if the view volume is entirely contained within the box.

I had no idea where the bug was, as melonDS did all that correctly, and some tests with the libnds BoxTest sample revealed nothing. It turned out that the issue lied within the initial calculation of the box coordinates. When melonDS calculated, say, "X + width", it did so with 32-bit precision. However, the hardware calculates it with 16-bit precision, so if the result overflows, it just gets truncated. And, surprise, games tend to rely on that behavior. Getting it wrong means you end up testing a different box, and getting different results. Hence the bug.


There have been various other improvements to the 3D renderer. Things have been revised to be closer to the hardware.

As a result, the Pokémon games look nicer, they don't have those random black dots/lines all over the place anymore. The horrendous Z-fighting observed in Black/White is also gone.

... read more
Nightmare in viewport street
And another bug bites the dust... a quite old one, by the way.

Namely, it was reported two months ago in issue #18: missing character models in Homie Rollerz's character select screen. Actually, if you look closely, you can see they were there, but they got compressed to one scanline at the top, which was caused by a bug in the viewport transform.

In 3D graphics terms, the viewport defines how normalized device coordinates of polygons are transformed to screen coordinates, which can be used to render the polygons.

Most games specify a standard fullscreen viewport, but there are games that pull tricks. Homie Rollerz is one of them, the character select screen uses a 'bad' viewport. But, unlike high-level graphics APIs, the DS has no concept of bad viewport. You can input whatever viewport coordinates, it doesn't reject them or correct them.

So how does it behave? Well, if you've been following this, you surely know that the DS looks normal and friendly on the surface, but if you look deeper, you find out that everything is weird and quirky. Viewports are no exception.

That's why the bug stayed unfixed for so long. GBAtek doesn't document these cases, so it's a matter of running hardware tests, observing results, and doing it again and again until you figure out the logic.


For example, here's a test: the viewport is set to range from 64,0 to 128,192. Nothing special there.

shitty triangle

Now, we change the viewport to range from 192,0 to 128,192, which results in a width of -64 (which, by the way, OpenGL would reject). One would say that such a viewport results in graphics getting mirrored, like this:

... read more
To make it clear
There is no Patreon version of melonDS. There will never be such a version.

Donating doesn't entitle you to anything. Not donating doesn't make you miss out on anything. You get the same package in all cases.


(this post used to be directed towards a particular news post, but it has since been corrected, so I will leave this here as a general note)


While it's nice that there are emu sites spreading the news, it is really better when they do some basic research and fact checking instead of posting mere assumptions that only cause confusion.


Thank you.
Opening to the outer world
If you have followed melonDS from the beginning, you'd know that wifi was one of the goals. And well, it's getting there.


The first melonDS release, 0.1, already included some wifi code, but it was a very minimalistic stub. The point was merely to allow games to get past wifi initialization successfully. And it even failed at that due to a bug.

Chocolate waffles to you if you can locate the bug, by the way ;)

But well, at that stage, the focus wasn't much on wifi.


It was eventually fixed in 0.2, and some functionality was added, but it still didn't do much at all. Games finally got past wifi initialization, but that was about it.

It wasn't until 0.3 that some serious work was done. With the emulator core getting more robust, I could try going for the wifi quest again. Not that 0.3 went far at all -- it merely allowed players to see eachother, but it wasn't possible to actually connect. But it was something, and infrastructure for sending and receiving packets was in place and working, as well as a good chunk of the wifi hardware functionality.


You may already know how it went back in the DeSmuME days. As far as local multiplayer was concerned, I kept hitting a wall. Couldn't get it working, no matter how hard I tried. WFC is a separate issue.

It didn't help drive motivation knowing that my work was doomed to stay locked behind a permanent EXPERIMENTAL_WIFI wall, requiring a custom wifi-enabled build, and that the DeSmuME team's public attitude is to sweep wifi under the carpet and pretend it doesn't exist, but the main issue was the lack of documentation as far as local multiplayer is concerned.


The DS wifi hardware isn't a simple, standard transceiver. It is a custom, proprietary wifi system made by Nintendo for their purposes. It has special features to assist local multiplay communication at a fast rate.

... read more