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
New melonDS feature: GBA connectivity
Hi everyone, I'm a new contributor to melonDS, Chagall on IRC and rzumer on GitHub. Being a fan of the melonDS project, I wanted to contribute something to it, and my most wanted missing feature being GBA connectivity, I spent a few weeks on and off implementing it.

This feature is mostly used in DS games to grant bonuses to players who own specific GBA titles. For example, inserting a GBA Ace Attorney game and launching the DS version will unlock all cases in the remake. Some games go further and read/write save data from/to the GBA cartridge (as in Pokémon games), or in one case polls its I/O port (Lunar Knights/Boktai DS).

All these features are now integrated in the master branch of the melonDS git repository. As far as I'm aware, this makes melonDS the first emulator to support solar sensor emulation in Lunar Knights. The video below demonstrates using the Solar Sensor item in Boktai DS with Bokura no Taiyou in the GBA slot.



Of course, you can also send your pocket monsters from GBA to DS, as demonstrated in this video:



As on real hardware, the GBA save file is modified during migration as the Pokémon are moved to the DS game:



Thanks to endrift of mGBA for the solar sensor emulation code that I used as a primary reference, and to DeSmuME authors for the GBA cartridge Flash save read/write logic that helped a lot with supporting the Pokémon games. Martin Korth's GBATEK document was also a great general reference.

... read more
Sorry for the silence lately
Shit's happening IRL.

Well, if you know me, you know that:

* I tend to only be able to focus on one big thing at once
* I am a trans girl

About the second point, I'm wanting to 'finish' my transition. There isn't a specific point where a gender transition can be considered finished; when your transition is finished depends on your criteria.

For me, that means I'm currently putting together the paperwork to get my name changed. Not the most difficult part, but anything involving paperwork tends to drain my energy, so you guess how that goes.

And it's not over, next comes getting my gender marker changed, and that one is more difficult (surprise).

Finishing my transition also means a few other things, like finally working on my voice or taking some time to figure out my style and build a better wardrobe.

There's also the whole bit where my job ends in about one month, and for now I don't quite know what I'll do next.


Sorry for the lack of activity wrt melonDS, but hopefully that will pick up again soon.

I began adapting the 4xBRZ filter shader to the OpenGL renderer a while ago, which is giving decent results, but I need to finish it (namely adding the 3D layer to it). I'm experimenting with ways to filter the 2D elements when the 3D layer is being upscaled.
melonDS wishes you a merry Christmas!
Not quite Christmas yet, but whatever. Soon enough time itself will stop existing, so these considerations are futile.

We're also past melonDS's third birthday. Time flies, it's crazy.

So what's new on that front? Well, not a lot, alas. I want to improve the OpenGL renderer, but for now, I started working on things, hit a roadblock as to how to do certain things, and, surprise, lost motivation. So until I get that back, there won't be a whole lot happening.

Also, Christmas might be more or less of a shitshow, as I'm trying to make it to my hometown to see my family whom I haven't seen in ages. I'm eagerly waiting for that, but it's not going to be that simple. Remember the general strike from Dec 5? Lo and behold, it's still going, and the train I had booked was cancelled due to it. I booked a bus instead, which is going to be a lot of fun (11-hour trip during the night, in conditions where I can hardly sleep). Besides, the crazy Macron government is indirectly pushing these bus drivers to drive as long as possible without rest (mostly to make up for the strike), by passing a bill to remove the requirement for breaks every 2h, thus completely disregarding security for the sake of profit. So, if I happen to die in a bus crash, you know who to blame.

Anyway, back to OpenGL. So, what I wanted to do:

1. Taking care of dual-screen 3D, and more generally any case where display capture is used. Currently, 3D frames that go through display capture end up downscaled back to 256x192, obviously because they need to fit in VRAM, and anything that uses them expects them to be that resolution.

There are ways to address that for the common use cases, though. As long as a captured frame isn't accessed by the CPU, it is possible to bypass VRAM entirely and instead use something like an OpenGL texture, without causing any visible problems. Sure, it's not too accurate to how the DS works, but neither is the general idea of upscaling. I am fine with this as long as we keep the accurate pathway (basically, the software renderer).

Anyway, the issue there is that I have to envision all the possible use cases. And for example, one possibility is to capture to a VRAM bank, with capture blending set to blend between the frame being rendered and a previous frame sitting in a VRAM bank (which may be the same bank we are capturing to).

I could always start with a simple use case (like dual-screen 3D). The issue is that I always feel the need to envision the whole scope of the project, all the use cases etc, because I fear that if I start building something for one use case, it may later prove unsuitable for other uses cases, and cause me to have to start again from scratch.

... read more
JIT beta builds and introducing myself
After all so much time has passed, it's finally time to do a release of JIT beta builds!

As Arisotura has stated in her last post, there's now another head working on melonDS. I'm Generic on IRC and RSDuck on Github.

For some reason I started messing with DeSmuME a bit more than a year ago, trying to write a JIT recompiler targetting ARM64, to improve performance on the Switch. After many struggles something working came to be, but it missed it's original goal of being fast for several reasons (see the link if you're interested).

After recovering from the disappointment I put my hopes into melonDS, but since it lacked any JIT compiler (besides the abandoned attempt by Arisotura herself) I wanted to start with a x64 recompiler. Skip forward a bit and the JIT started take on form. After taking everything apart and putting things more cleanly back together around the beginning of last summer things only got better, with most instructions being recompiled and the opening of the pull request on Github, which later got merged.

At this time the ARM64 backend was started this time avoiding my previous mistakes. With autumn it reached a similar level of completion as the x64 backend while both backends received some optimisations. Until this point we were catching up to DeSmuME but at this point started to surpass it. Here is where I want to thank all developers of open source emlulators whose dynarec I was eable to look into and especially the developers of the JIT of Dolphin. We're not only using their code emitter but they also gave me some great advice on IRC!

With some further optimisations of the 2D GPU emulation using ARM NEON instructions, most 2D games already run at fullspeed on the Switch, while most 3D games run at fullspeed with overclocking. The ARM64 JIT and the GPU optimisations are currently located in my own fork and are distributed by me in binary form on Gbatemp in an admittedly chaotic way.

I am very grateful to Arisotura for creating the emulator in the first place, as well as trusting in me and my work. For the future the already mentioned GPU optimisations are my current focus. I'm currently rewriting the old ARM NEON optimisations to be more clean and adding some additional ones which hopefully increase the performance a bit more. The logical step following would be a NEON 3D GPU backend. I have some more plans lying around, e.g. there is still one major JIT optimisation we're missing out on (fastmem).

So but now enough storytelling, here are the builds:

Note:

... read more
Status update II
Couple things.


First of all, things have been a bit shitshow-y, and involved a few bursts of depression, but, finally, it's there, I have my apartment now. I'm not quite finished settling here, but that's a big relief for now. Plus, the place is fairly nice! Except for the wall sockets being upside-down, but, eh.


Next, I'm being sucky at delivering a JIT beta. Thing is, unlike the DSi branch which was hacked together by me, the JIT branch is Generic's work, so I will need to take a while and get familiar with it.

In the meantime, I figured I would let Generic handle things himself. I gave him access to this blog and all, so he will be able to post a beta build, which he said he would do tomorrow.

I figure the best way to work with this long-term is to work as a duo. I'm less skilled on things like fast CPU emulation, and more skilled on other parts of emulation, so other people like Generic can complement me nicely there and together we can deliver an excellent product.

And, holy fucking shit, reconciling the JIT and DSi branches is something I'm totally looking forward to. At this point, the DSi branch already has several conflicts with the master branch (it's based off 0.8.1, so yeah), and, no idea about the JIT branch.


Immediately tho, I'm going to improve the OpenGL renderer. This means reorganizing some of the code so it's easier to work with, fixing some longstanding issues like the case of dual-screen 3D, and adding some filtering.

You can follow the progress in the appropriately named blackmagic_II branch.


Hell, even writing this post is taking me forever.


Also, today's Dec 5, and it's the general strike day. Seeing how successful it was, if they manage to keep going at this rate (and they totally intend to keep going), president Macron is going to have a hard time. But, this also means that certain things may be delayed, or whatever, so we'll see.
Status update
Not much to say these days, sorry about it.


Couple things though.


On melonDS, things are going to be mostly on hold until I manage to get a proper apartment and am all settled in and all. But, two things. First, Generic said that the JIT branch is ready for a beta release, so I'll be doing that. Second, as a next direction to take the project, I'm thinking about adding support for AR cheat codes.

I'll also be trying to fix the remaining issues with the OpenGL renderer, but some are going to be tricky. Also, things related to this renderer: I need to come up with a not-too-hacky solution for dual-screen 3D and upscaling, and to add support for filtering in OpenGL mode (including xBRZ or something of that ilk).


But, blegh. The apartment. I visited one a while ago, now I'm going to have to put together the paperwork and hope it isn't too late. There are other apartments I can try, but, hey, I liked that one. So, here's hoping.


Oh also, this is Nov 17, birthday of the yellow vest movement. French protest movement that started one year ago, was originally against a gas tax raise but turned radical and against precarity in general, which seems to be a common theme these days (thinking about Hong Kong, Chile, ...). Despite the fact that the movement as it is will not bring revolution, it seems to want to never end... (what kind of protest movement lasts one whole year?)

But we can see that it's having an effect on protests in general, they turn more radical now. Like recently, a student from Lyon set himself on fire out of despair after being thrown into precarity. Had that happened two years ago for example, nobody would have cared, it'd just have been "another depressive sicko attempts suicide, film at eleven". But instead, this sparked several student-led protests and blockades, including one that broke into the Ministère de l'Enseignement Supérieur.

Dec 5 is going to be the general strike, too. I first thought that would be lame, as most of these attempts were a while back, but, now, within the different context, this looks like it's going to be quite something. May also cause some trouble on my end, but, we'll see.

Anyway, happy birthday to the yellow vests. I've been following the movement closely, and even taking part in it, as it gave me hope when I was at the worst of depression, so this means a lot to me.
When things turn out unexpectedly simple
As I said in the previous post, melonDSi can't boot any DSi-enabled cart. I'd been banging my head against the problem for a long while, attempting to work out how the launcher on the ARM9 worked and why it was failing, but went nowhere. The code is a pain to track, relying on all sorts of threads and callbacks and things.

Shows that taking a break does wonders.

Just yesterday, I idly looked at that bug again. Reproduced the freeze, then pressed F11 (debug key printing some status to the console) a few times to see if I could see a pattern. The ARM9 seemed to exhibit typical 'idle thread' behavior; the ARM7 however, seemed to get stuck in a loop. A quick glance at my IDB of the firmware code confirmed this:

AES wait routine

If you aren't fluent in ARM assembly, this function waits for the AES engine to finish whatever crypto operation it is doing, by checking the busy flag in AES_CNT.

But, in our case, the ARM7 got stuck inside this because, somehow, said busy flag remained set forever.

Some logging of AES operations shown that, while loading the game, the firmware would start a decrypt operation with a block count of zero. melonDSi didn't check for that case, and instead waited for data input that would never come (heh), causing the busy flag to remain set forever. You guess how this goes.

After quickly fixing this bug, I tried loading a cart game again. It still froze on a white screen, but the logs showed it was getting further. In particular:

UNIMPLEMENTED ARM9 NDMA3 START MODE 04, 04100010->021153A0 LEN=1 BLK=1 CNT=A4044000

That meant the game was actually booting, and attempting to load its data, using NDMA ('new DMA' implemented in the DSi) for whatever reason. NDMA start mode 04 is for cart slot DMA, which is triggered every time a data word is transferred from the cart.

... read more
melonDSi beta release
Apologies for the silent month. Things are shaking up here irl, as I'm starting that job, and looking for a new apartment, which is a bit of a shitshow.

Anyway, here we go: we present you melonDSi, in unfinished beta glory. The JIT beta will follow, but I first want to ensure Generic is comfortable with it.

The end goal will be to merge this with regular melonDS once it's in a better state, but, for now, we're providing it for the curious folks.


How to use melonDSi

BE SURE TO READ THIS BEFORE USING MELONDSI. You are using a beta release, provided with zero polishing and with a debug console. I expect that you know what you are doing to atleast some extent.

melonDSi will require several files to be dumped from a DSi. It's a bit messy right now, but we hope to come up with more user-friendly solutions in the future.

So, if you have a DSi, you might want to install unlaunch on it.

A quick rundown of the files melonDSi requires:

* bios9.bin / bios7.bin: DS-mode BIOS images. Those are the same as the ones from a DS. They shouldn't be required to get DSi software running, but melonDSi will refuse to start if they aren't present.

... read more
2D accuracy: it's a rabbit hole too
Yeah. I've been wanting to fix mosaic support in melonDS, and, well, got sidetracked (I know I still have to release the JIT and DSi betas).

Anyway, mosaic is a typical feature of old consoles with 2D engines, including the DS. It basically applies a pixelation effect to graphics, as shown here:



The basic idea is that the screen is split in a grid, whose dimensions are variable (configured by register 0x0400x04C on the DS). For each 'cell' in the grid, all the pixels are colored the same as the first (top-left) pixel. In reality, it's a bit more complex, as on the DS the effect can be applied per-layer and per-sprite, and you can even specify different grid sizes for BG layers and sprites, but fundamentally it's more or less the same thing, it pixelates shit.

Sounds simple enough, right?

It's a bit tricky to implement when you're trying to write a performant renderer, though. Which is more or less why blargSNES never supported it.

As far as melonDS is concerned, mosaic was implemented in version 0.5, but (among other silly bugs) it never worked quite right as far as sprites were concerned, especially when those use rotation/scaling. But, at the time, I didn't do much past the original implementation, mostly because I don't know of a lot of games that use the mosaic effect. The lack of test cases meant it stayed supbar.

Until, well, now.

First thing to do is to write some test cases for sprite mosaic. BG mosaic seems quite simple, even though I would still have to probe it extensively for edge cases, but sprite mosaic is a bit more oddball, as seen here:

... read more
melonDS 0.8.3
About fucking time, I guess.


So what does this release bring? Well, we have been trying to address the issues present in previous 0.8.x releases (or sometimes even older releases, heh).


For example, I fixed the bug that was introduced with the new support for Ctrl+K type hotkeys. Basically, using Shift/Ctrl/etc as regular keys mapped to buttons was no longer possible. So, support for key mappings with modifiers was restricted to hotkeys. Meaning that using right Shift as R (as done by the default key mapping) should no longer cause input problems.


I have been trying to fix the issues we had with the framerate limiter and audio output, too, with moderate success. As I haven't been able to come up with a one-size-fits-all fix, there are now three different sync modes you can use, individually or together:

* Limit framerate: the oldschool framerate limiter. Although this is a revamped version that tries to average over several frames, reducing the likelihood of limiting too aggressively on certain games that internally run at 30FPS and are otherwise able to run fullspeed.

* Audio sync: synchronizes emulation to the audio output system. Seems to result in a bit more fluctuation in the framerate, but should prevent any audio stuttering.

* VSync (in the video settings dialog): synchronizes video output to your monitor's refresh rate. This only works with OpenGL, and currently only works under Windows (OpenGL support under Linux still needs more love). Also, DS games/programs may alter their framerate by messing with VCount, which VSync would be ill-equipped to deal with (unlike the two other sync methods).

I think most of the audio issues came from not properly syncing, which resulted in semi-regular overflows or underflows in the SPU FIFO, causing stuttering. The current audio output system cannot be precise enough to prevent those, as it works with small audio frames.

Speaking of which, I have also been revising it to use a more standard output frequency, in case some bad audio driver doesn't appreciate the previous frequency of 47340Hz. Now, it will attempt to run at 48000Hz, but it also allows SDL to specify another frequency if needed.

... read more