A lot closer to a finished product
Even if still very far.

After a while, melonDS finally boots commercial games. Among my small game library, the compatibility rate is encouraging, even. Here are a few screenshots, for example:

Getting there took a while of implementing new features, but also bashing my head against obscure bugs that often turn out to come from silly little things.

As an example, a bug that prevented games from booting.

On ARMv4/v5, the LDR opcode has the particularity that if you read from an address that isn't word-aligned, it aligns the address, and rotates the word it read so that the LSB is the byte pointed by the original address. In melonDS, it was implemented the following way:

u32 val = ROR(cpu->DataRead32(offset), ((offset&0x3)<<3));

At first glance, looks alright, doesn't it? Except ROR() is a macro, defined as follows:

#define ROR(x, n) (((x) >> (n)) | ((x) << (32-(n))))

This basically ends up calling cpu->DataRead32() twice. This isn't a big deal when reading from RAM, it only wastes some CPU time, but the bug goes unnoticed. However, it has nasty side-effects when reading from I/O registers like the IPC FIFO.

Next up, aside from GPU-related work, were features like touchscreen or save memory.

Touchscreen emulation isn't too hard. Saves are a little more involved. In itself, it's nothing big, the save memory is an EEPROM or Flash chip accessed over a dedicated SPI bus. The issue is how to determine the correct memory type. The ROM header doesn't contain that information, so we must guess it. The current implementation waits for the game to start writing to the save memory and tries to determine the memory type from the length of the longest write. The idea is to guess the memory page size, from which the memory type and size can be inferred. If a save file is already present, those variables are inferred from the file's size.

With that covered, games can do something more interesting than sitting on a "failed to erase data" screen.

So far, this is what I have tested:

New Super Mario Bros: non-3D minigames playable, freezes when going ingame
Super Mario 64 DS, Rayman Raving Rabbids 2, Meteos demo: "playable", but no 3D graphics
Mario Slam Basketball, Rayman DS: get stuck trying to do a GX FIFO DMA
Mario & Sonic at the Olympic Games, Mario Kart DS: freeze when trying to display 3D graphics
Super Princess Peach: playable, 3D effects missing
Worms 2 Open Warfare: seems to work, but menus invisible -- this game is all 3D

It appears that there are now two main immediate directions for melonDS: UI and 3D support.

The UI part will need some thinking to pick the best framework. The current UI is something I quickly threw together using the Win32 APIs so I could see graphics, but for the "final" product, I want something cross-platform. An idea is to provide a quick SDL-based interface and a more complete Qt interface. I don't like some aspects of Qt, but regardless, it's a possible candidate, and a powerful one.

A decent UI would also support things like selecting a ROM file instead of hardcoding the filename, choosing a save memory type should autodetection fail, choosing whether to boot from the BIOS or from the game directly, all those things.

3D support is going to be required to get further into emulating games at this point. Past the obvious reason that they can be unplayable without 3D graphics, some require the hardware support to get further.

The 3D GPU has a FIFO for sending commands to it, called GX FIFO. It can be set to trigger an IRQ when it gets empty or less than half-full. Some games wait for the IRQ before sending more commands, some others use DMA to send their command lists automatically. Without proper support, these games would just hang.

The most bizarre game is probably Super Mario 64 DS. It does enable the GX FIFO IRQ at times, but never waits for it -- instead polling the GXSTAT register with the following code:

0205A390                 LDR     R12, =0x4000600
0205A394                 LDR     R4, [R12]
0205A398                 AND     R4, R4, #0x7000000
0205A39C                 MOV     R4, R4, LSR#24
0205A3A0                 ANDS    R4, R4, #2
0205A3A4                 BEQ     #0x0205A394

This is basically an inefficient way of checking whether bit 25 of GXSTAT (0x04000600) is set.

((GXSTAT & 0x0700000) >> 24) & 0x2

Could have as well been:

GXSTAT & 0x02000000

Why it doesn't just wait for the GX FIFO IRQ is a mystery (waiting for an IRQ lets the CPU go idle and saves power, unlike this kind of busy loop).

Stay tuned for more reports of the melonDS adventure!
SonicBlader says:
Feb 7th 2017
I heard about this now from /r/emulation

This is great! Another DS Emulator! I am looking forward to its progress. Good luck! :D
StapleButter says:
Feb 7th 2017
Thanks :P
Jibutan says:
Feb 8th 2017
have you look at using andlabs/libui ? is a simple gui frame work with cross compatibility and is very smaller than qt
StapleButter says:
Feb 10th 2017
Thanks for the tip! I'll look into it.
Anonymous says:
Feb 11th 2017
Really impressive for something so new. Do you have plans for a publicly editable compatibility list?

StapleButter says:
Feb 13th 2017
Probably in the future, yeah.
Post a comment