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
• (WIP) GBA slot add-ons
• and more are planned!

Download melonDS

If you're running into trouble: Howto/FAQ
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
Some news
A little update on the plans for upcoming melonDS versions.

Things have slowed down a bit since 0.7.3. I wanted to address some of the newer timing issues, but there's bigger trouble arising from this, I'll get to it.

Also, attempting to get things done(tm) in real life, which is another reason why it's slowing down.

Regardless, we're still alive and kicking.

For melonDS 0.7.4, I want to fix some interface issues, and finally add some interface for setting up online-mode wifi. There might be other fixes, but that release will hardly be a revolution.

0.8 will be, as promised, the hardware renderer and upscaling. I don't want to delay this any further, so instead I'm going to delay what will come next.

For 0.9, or something like that. We're running into timing issues that can't be addressed by simply tweaking our timing values for cached memory. Not without breaking other games. I am reluctant to using per-game hacks.

So, the last line before the dreaded "per-game hacks or full ARM9 cache emulation" situation: perfecting CPU timings. The current CPU timings are imperfect, making things run faster than their hardware counterpart, especially on the ARM9 side. The ARM9 is complex so working out its complete timings will take a while.

Also, there's been some changes to this site, and we're not done :)
melonDS 0.7.3
After another round of fixoring, we present you melonDS 0.7.3. So, what are the changes in this version? Mostly addressing the issues that popped up in 0.7.1/0.7.2, and improving the interface a bit.

Something that should have been done long ago, and has finally been done: the emulator's main loop was rewritten to use absolute timestamps to keep track of cycle counts. Overall, it's more reliable (far less chances of desyncs), more accurate, and also a bit faster, and the code is cleaner. So we win on all fronts.

This should fix the recent flickering issues, like that of Colour Cross.

The downside is that this breaks savestate compatibility with older melonDS versions.

In the same vein, there's another fix to GX timings. We knew that vertex timings were different when a vertex completed a polygon, but we just found out that timings also differ based on whether the polygon passes culling and clipping. This will help with games that need their display lists to be running fast enough.

To hopefully fix the saving issues, we built a new database, resulting of a mix between the Advanscene XML and savelist.bin from the R4 Wood firmware. For better detection, the new romlist.bin indexes games by their serial code rather than by the ROM's CRC32, which also means that it will work with hacked ROMs. This means you will need to make sure to replace romlist.bin with the newer one if you're extracting this melonDS release over an older one.

There's also a particular fix for Pokémon Mystery Dungeon - Explorers of Sky, which uses 128K EEPROM. It should now save properly.

However, note that the correct savefile size for this game is 128KB. If you have a savefile which is 256KB, the game will read it fine but fail to save to it (because that size is detected as FLASH memory and not EEPROM). You can fix this by opening your savefile in a hex editor and deleting the upper half of it. This is especially important if you use a savefile coming from DeSmuME as it will create a 256KB file.

We also have a neat little pile of UI improvements.

... read more
Some brighter news tho
Too many ideas.

Regarding the Colour Cross issue, I have an idea. It seems to stem from the GXSTAT busy flag, like, sometimes it's still set when it should be cleared because we aren't syncing the GX often enough.

I could go back to the old way (syncing it per-opcode), but I'm afraid this is going to be suboptimal. The better solution I have will require a bit of reworking how melonDS handles timing. As a bonus it would be more straightforward, easier to maintain and less error-prone.

I still have no idea about Spellbound though. I found that DMA timings can differ depending on how source/destination addresses are updated, but that doesn't apply in the Spellbound case. So, still no idea there.

I guess we can try releasing 0.7.3 after fixing Colour Cross, though.

I also have a few ideas for improving this site. A nice one to have would be an intro blurb before the blog posts, showing off melonDS and why it's awesome and you should totally download it, like the lolSNES site has.

Might also change the download page a bit, namely, to add downloadable extras like the latest romlist.bin or the dsbf_dump.nds copy that's been squatting the Kuribo64 uploader since forever.

Maybe even later, some form of compatibility list. Which will need some dedicated testers to fill it and keep it up to date.

If you have ideas how to improve the site, visually or technically, I'm open to all suggestions!

... read more
Happy new year from melonDS

This year is not starting too well. I implemented an instruction cache in melonDS, and what are the results? Absolutely none whatsoever (other than being a bit slower). It achieved as much as farting in the wind. The problem games I previously mentioned are still giving me the finger.

My motivation is utterly sapped.


We hope this year will be better for you.
Updated romlist.bin
The database was rebuilt, this time from a mishmash of the Advanscene and Wood databases. It should be a lot better.

In the near future, the database will be changed to identify ROMs by game code rather than CRC, so it will also work with hacked ROMs and whatnot. But for melonDS 0.7.2 or 0.7.1, you can get this updated database.

-> Download here <-

Just overwrite your existing romlist.bin with this and you're good to go!

Remember, if your game is still failing to save, you may need to delete the savefile.
World of shit
I've been looking at another 'timing renovation victim' issue: dual-screen 3D shitting itself in Colour Cross.

The game draws all its animated background tiles/etc separately, giving each its own transforms. It sends unpacked GXFIFO commands and doesn't use DMA. All in all, not very efficient, but probably not a bad way to do it given what they're doing.

Anyway, the game expects to take a certain time to draw each screen (for the bottom screen, it spans two frames). If the code runs too slow or too fast, it shits itself. Given how geometry is sent, GX timings don't affect this.

It doesn't have to be precise, but there's a window within which this has to fall, so we can't make it absurdly fast or absurdly slow and hope to fix it.

On the other hand, we have the Spellbound issue which I mentioned in the previous post. There, the code has to be running slow enough, I can't see any other way out. Both DMA and GX timings are correct there. I could always try dumping the display list and running it on hardware within the same conditions to see how it goes, but I'm sure the issue is with code timings.

So I guess this is it. No amount of hodgepodging timings will get us out of this, as I feared. And I really want to avoid 'solutions' like game-specific hacks or 'toggle this timing setting and see if it fixes your game'.

So, we have to emulate the ARM9 instruction cache.

On the plus side, since code fetches are mostly sequential, this shouldn't be a big performance penalty. The cache can be checked only upon branches and on cache line boundaries (on the DS, that is every 32 bytes). The ARM9 caches have 4-way associativity, which means a measly 4 cache lines to check before we know whether the current address is cached. So I believe we can afford to emulate it without killing performance.

The data cache would be the one killing performance; because data accesses are far less predictable, the cache would have to be checked upon every memory access. For now, it appears we can get away with not emulating it, so let's pray.

... read more
Short break
Much needed to avoid burnout these days.

Especially when it seems that all you're throwing at the wall is pointless. That sure deals a blow to motivation.

I picked one of the available Advanscene databases for savemem type detection, not knowing what all the available ones mean and what the differences are. Well, this one seems to be a Swiss cheese, full of errors and missing games.

If you have any ideas for a better database (like, what the fuck are the differences between all the Advanscene ones), I'd love to hear about it. Among the suggestions are that of using AKAIO's database, so I might look into that.

Also, a possibility to consider: detecting ROMs by game code rather than by CRC.

We're getting more timing renovation victims, and this time they're goddamn real. They all seem to be the same thing, missing/corrupted geometry. I don't know about all the games, but I looked into one of them (Spellbound), and it looks, well, not very good. The developers coded their own software version of GXFIFO DMA (the base idea is to transfer a fixed-size chunk of display list data every time the GXFIFO is less than half-full), which works by relying on the GXFIFO IRQ set to trigger when it's less than half-full.

However, the way this is coded expects that by the time a DMA transfer is finished, the GXFIFO will already be less than half-full, so the next chunk will be started immediately. Of course, there's a point in melonDS where that doesn't happen, causing the game to think the transfer has completed, and send a SWAP_BUFFERS command in the middle of the display list, which works as well as you'd expect.

Something's up with our timings. I hope we don't need to emulate the ARM9 caches.

And the goddamn input config dialog under Linux. I have no fucking idea why that would crash. I can't reproduce the crash. It's working just fine under my setup (Ubuntu 16.04). I can't even tell if we're just hitting some obscure GTK bug.

... read more