Getting somewhere
melonDS has progressed nicely since the last post. To give you an idea:

melonDS running the DS firmware

It's got some graphics capabilities, even though those are quite limited. Rotated/scaled sprites, like those used for the clock up there, gave me some trouble, but I eventually got it working.

Speaking of the clock, it's frozen in time. I had to implement the RTC to get the firmware to actually boot instead of constantly entering "please enter time/date" mode, but for now, I hardcoded the time/date. The RTC is real fun to work with btw-- DS software talks to it by bitbanging a GPIO register. From the emulator's point of view, you get a series of zeros and ones which you must put back together to get data you can work with.

I also implemented proper-ish support for the DS cart hardware. This is quite the fun too. There's an initialization sequence done by the BIOS, and two different encryption methods are used. The BIOS starts by retrieving the ROM header and chip ID, then switches to Key1-encrypted command mode and retrieves the secure area (a protected part of the ROM not readable via the normal read command), and finally switches to Key2-encrypted command mode, under which the game will operate.

It is also worth noting that on actual carts, the first 2KB of the secure area are Key1 encrypted. The first 8 bytes are a double-encrypted identifier (string 'encryObj') that is used by the BIOS to verify whether the decryption was successful. However, all the DS ROM dumps out there have that 2KB block decrypted. Thus, we need to re-encrypt it for it to be loaded successfully.

Getting Key1 to work took a while (and uncovered a bug in the CPU core). Key1 is based on Blowfish and is the most complicated encryption algorithm used. Key2 is based on a XOR stream generated from two 39-bit registers, but it can be ignored, it is entirely implemented in hardware.

The really hacky part in the current implementation is how cart DMA is implemented. Cart DMA basically works by automatically transferring a word from the cart data output register to memory as soon as there's data ready. The DMA engine doesn't know how long the transfer is, it only knows to wait until there's data available, transfer it, then repeat.

When you take the lazy approach of making cart reads return data instantly, you may run into trouble when implementing cart DMA properly. A read from the cart data output register would advance the read pointer, and if DMA is enabled, perform a DMA transfer, which would trigger another read, and so on until the recursion overflows the stack.

So instead, there's an entirely separate code path for cart DMA. Atleast until the transfer delays are emulated. Then again, I also envision optimizing common DMA transfers with special code paths avoiding a lot of address decoding work, like I did in blargSNES. Common DMA transfers would mostly be transfers to VRAM, palette memory or OAM, though. Optimizing cart DMA would only speed up loading times at best.

Noting that with all that, the firmware does detect the cartridge, the game title and icon show up fine... booting a game doesn't quite work yet, though.

Well, actually, the game tested (NSMB) does boot, but it hangs before doing anything visible. The twist is that it isn't quite stable, sometimes it behaves differently, but still hangs. This tends to indicate that either the timings are really bad, or there's some evil "out-of-bounds array write" type bug hiding somewhere.

The main loop/scheduler needs rewritten badly anyway. The current system is messy at best and incorrect in certain cases (fast timers would be a good example). I should use absolute 64bit timestamps instead of trying to keep track of cycle differences here and there.
So what's melonDS?
melonDS is a new emulator project. My goals for it are to do things right and fast. Time will tell how far we can get in that direction.

If you know me, I'm not new in the emulation scene. I'm responsible for lolSNES/blargSNES, among others. I'm not new in the DS scene either, I worked a lot on DeSmuME back in the days. Why I'm straying away from DeSmuME is not something I will get into here.

So here I am, writing my own emulator for the second time. The hardest part in starting an emulator project from zero is managing to build something that resembles an emulator. It takes a fair amount of work before you can start getting results.

To this day, melonDS has gotten over the initial stage and does give some results. Nothing actually works aside from the very simple ARMWrestler CPU test, but hey, it's a start. melonDS has a 'good enough' subset of the ARM instruction set implemented, as well as a few hardware features, so getting things to run is mostly a matter of implementing the rest of the DS hardware.

One thing I want to do is being able to boot from the BIOS, like an actual DS. I was unable to get it to work in DeSmuME back then, but manually loading a DS firmware and booting it (thus skipping the BIOS) did work.

The progress of melonDS in regard to this is encouraging. The BIOS loads the firmware into memory and boots it. The firmware gets to the point where it tries to use the IPC FIFO, which I haven't implemented yet. Interesting things ahead!

Of course, melonDS will later have the option to boot a game directly, like all the emulators out there do. But for the sake of accuracy, I want to be able to boot from the BIOS.

The holy grail would be wifi emulation, especially local multiplayer, which I could never get working in DeSmuME. Time will tell if that goal is achievable.
melonDS dev blog
I will use this blog to post about the development of melonDS, my DS emulator project. I expect it to be lots of fun.