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
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
BLARGRARAAAAAAA
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:



where:
- 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
OpenGL progress


So this is where we are today. Our GL renderer is a lot more capable, even though it's still unfinished.

Here's a little TODO list:

* shadows
* handling DISPCNT
* texture blending modes (decal/toon/highlight)
* edgemarking, fog
* clear bitmap
* higher res rendering
* OpenGL init under Linux/etc
* switch between GL and software renderer

I first want to clean things up so that I can release a beta version, though. The idea would be to see how the renderer fares 'in the real world', so the actual proper 0.8 release doesn't end up being a major disappointment.

The current renderer requires OpenGL 4.3. Which might exclude old hardware and, well, Macs.

At the end of the development process, the requirements will be adjusted. The current renderer will likelly have its requirements lowered as far as it can go without losing accuracy.

Depending on demand, there might be alternate GL renderers, supporting older GL versions but sacrificing some accuracy (they will render certain cases wrong and that will not be fixed).

See ya in a while!
Doing the time warp


This looks a lot like another screenshot, from two years ago:



So why am I posting this now? Well the answer is simple, we're going back in time and preparing a new melonDS release that is roughly equivalent to 0.1.

-

Joke aside, there are some key differences between those screenshots:

* newer one has proper clipping at screen edges
* both lack Z-buffering, but newer one is different, likely because the older one didn't have Y-sorting
* newer one is using OpenGL

So, yeah, that's the long-awaited OpenGL renderer. Like the good ol' software renderer in its time, it's taking its baby steps, and barely beginning to render something, but I'm working on it, so in a while it will become awesome :P

This renderer will aim for reasonable accuracy. As a result, it will require a pretty recent OpenGL version, and compatible hardware. It's set to OpenGL 4.3 currently, but I will adjust the minimum requirement once the renderer is finished.

... read more
melonDS 0.7.4
Arisotura finally stopped being lazy, among other things, so here we go, we present you melonDS 0.7.4.


This release is hardly going to be revolutionary though, but I had to get it out before starting work on the hardware renderer.


The highlight of this release is the upgrade to the online wifi feature. Two main points there:

1. Under direct mode, you can finally choose which network adapter will be used by libpcap. The wifi settings dialog also shows their MAC and IP as to help you ensure you're picking the right adapter.

2. Indirect mode, which, as mentioned before, works without libpcap and on any connection. However, it's in alpha stages and it's a gross hack in general, so you can feel free to try it out, but don't expect miracles.

As usual, direct mode requires libpcap and an ethernet connection, and that you run melonDS with admin/superuser privileges.


Other than that, there are a few little fixes to the SDL audio code. melonDS now only emits sound when running something, so it shouldn't emit obnoxious noises when starting anymore. Also, it no longer crashes if you use WAV microphone input with a file that has multiple channels.


And other little things.


Now, full steam ahead towards 0.8! Or not quite. I also need to finish the redesign for this site, among other things.

... read more
Immediate plans
Indirect mode is still flaky, but it's good enough for a beta release. I only have to polish a couple details and it'll be good for a 0.7.4 release, so, expect that release soon.




I also wanted to fix one of the issues with local multiplayer: when more than two players are involved, clients receive replies sent by other clients, which they shouldn't receive, and this likely contributes to it shitting itself big time.

But alas, this will be more complicated than anticipated. This is also the main reason why local multiplayer pretty much stagnated after melonDS gained its "wifi emulator" reputation back in 2017: emulating local MP is a large pile of issues that are all interconnected. Wifi emulation in melonDS is more or less a pile of hacks, and it works, but it's full of issues. Some stem from incomplete understanding of the DS wifi hardware (after 15 years. welp), but most of them are timing issues.

(which are also why I'm pretty much pessimistic about ever connecting melonDS to a real DS)

Local multiplayer 'a la Nintendo' works on a host-client scheme detailed here. Long story short, the host polls the clients at a regular, small interval (for example, every 4ms for Pictochat). Dealing with the sheer amount of packets transferred is in itself a challenge.

But that's not all. When the host sends its packet, each client is given a window within which it should send its response. Miss your window and it's considered a failure.

This works well with actual DSes because they're all running at the same speed, so the timings are reliable.

With melonDS, it's another story. We get lag inherent to the platform on which we're running: the network stack, thread scheduling, etc... Running multiple DSes in one melonDS instance might help alleviate these lag sources, but it wouldn't be a perfect solution either (it would likely be running the DSes on separate threads).

... read more
Getting somewhere, finally


Finally, ClIRC is cooperating!

This took a bit of hackery to get around the limitations we face when working with plain old BSD sockets. Namely, how we're handling TCP acks for now.

Regardless, it's finally working without exploding! Well, I don't know about things like altWFC. But ClIRC is working about as well as when using direct mode.

We'll be polishing this and testing it with things like altWFC. You can expect a release real soon.

(also, a side effect of using sockets is that closing melonDS terminates connections correctly, which is nice for testing)