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
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)
Change in plans
Indirect mode was already down to a level where it was dissecting TCP/UDP headers and keeping track of TCP sockets and all.

So I figured I would just rewrite it to use regular sockets instead of libpcap. There will be a lot less issues getting things to work this way, and this has the significant advantage that it doesn't require libpcap, and likely can work without requiring admin privileges.

The downside is that we have less control this way, as all the low-level TCP/IP details are handled by the host OS, so some things might break, but I'm confident that this will work just fine for the most typical uses, which involve standard TCP connections.

Anyway, I have DHCP, ARP and DNS covered. I started work on TCP, it's now able to initiate a connection to a server. Now I need to get the actual data exchange working.

I'm also unsure this can work for any use case where the DS is used as a server, but for now we don't have to care about that. And there's always direct mode.
Updatez0rz
Uninspired title is uninspired. Anyway, two things for this post.


1. Coming-out, sorta.

I am, well... nonbinary, likely some flavor of girl.

I'm a bit sick of the constant assumption that internet users are male by default, or that 'there are no girls on the internet'. Other genders, trans or not, are here too.

If you don't know, you can either ask or use gender-neutral prounous, it's still better than perpetrating the 'masculine by default' norm.


2. Network shito

The issue I mentioned with the DS receiving packets addressed to the host, also happens the other way around, ie the host receives traffic addressed to the DS. This might be the cause for the lag I observed.

Still thinking of a workaround to this. May need to read about network routing and all.


That's all folks!
Indirect mode progress
After a while of dealing with the silly issues like failing to properly compute checksums, indirect mode is finally showing some promising results.

The idea is that outgoing network traffic is altered to make it look like it's coming from the host machine, so that it will get past wifi access points without trouble. In return, incoming traffic is addressed to the host machine, so I first took the easy path of redirecting all traffic to the emulated DS regardless.

Bad idea tho.

This caused all connections on the host machine to die constantly. Reason is that on the DS, the sgIP stack is receiving TCP traffic it did not initiate (because those are destined to the host), and interfering with these connections, likely just trying to kill what it perceives as bogus connections.

To work around this, we have to keep track of TCP sockets. Examining the flags in the TCP header, we know when a connection begins, and can know to only redirect incoming traffic if the source IP and source/destination ports match an existing socket.

Basically, NAT.

This gave promising results with ClIRC, but for some reason there's quite some lag on messages sent from ClIRC, which I don't remember being that laggy.

The current implementation will be limited to TCP and UDP, but for uses like AltWFC, this should be enough. For more advanced shito, there's always direct mode, which I think can be made to work on a wifi connection with some hackery.
Full steam ahead!
You might have noticed the beginning of another coding streak. Is an awesome feature being coded? You'd be right.

One of the main reasons why coding is going at this weird pace, besides the recent surge in local political activity and moving to a betterer apartment, is, well, how I achieve work. Whenever big-ish changes are required (designing something new, redesigning something...), I need time to think about it, and sometimes just do something else entirely for a long while. Until I go 'fuck it' and just code the damn thing.

So, I started coding the damn thing.



The "bind socket to any address" setting for local wifi has been moved to this spanking new wifi settings dialog.

There's also the new UI for setting up online mode, so you can, you know, pick a network adapter, etc.

That's why it took a while btw. It displays adapter information such as MAC, IP, DNS servers, which aren't provided by stock libpcap. So I had to use the Win32 API to retrieve those (and I have yet to code the Linux equivalent). We also get more meaningful adapter names this way, instead of having them all be named 'Microsoft'.

Then, there is the 'direct mode' thingablarg. What's that for?

Direct mode is basically the old way of forwarding network traffic: directly passing packets from/to libpcap. While this is the most straightforward and less likely to shit itself, it has the downside that it requires an ethernet connection. Reason is that under this mode, melonDS is seen as an entirely separate device on the network, with its own MAC address and all. On an ethernet connection, you can just use promiscuous mode to retrieve the packets sent to melonDS. But wifi is a different affair. Devices need to be associated to the access point. As that isn't the case for melonDS, its packets are just thrown away.

... read more