Having fun with DSP HLE
If you pay attention to the melonDS repo, you might have noticed the new branch: dsp_hle.

And this branch is starting to see some results...



These screenshots might not look too impressive at first glance, but pay closer attention to the framerates. Those would be more like 4 FPS with DSP LLE.

Also, we still haven't fixed the timing issue which affects the DSi sound app -- I had to hack the cache timings to get it to run, and I haven't committed that. We'll fix this in a better way, I promise.


So, how does this all work?

CasualPokePlayer has done research on the different DSP ucodes in existence. So far, three main classes have been identified:

• AAC SDK: provides an AAC decoder. The DSi sound app uses an early version of this ucode. It is also found in a couple other titles.

• Graphics SDK: provides functions for scaling bitmaps and converting YUV pictures to 15-bit RGB.

• G711 SDK: provides a G711 (A-law and ยต-law) codec.

All ucodes also share basic audio functionality, allowing them to play simple sounds (for example, a camera shutter sound) and record microphone input. They are fairly simple, but emulating them in melonDS will require some reworking of the audio system.

It's not like this DSP is used to its fullest here, but hey, it's something.


I first started working on the graphics ucode, which is used in Let's Golf. It's used to scale down the camera picture from 144x144 to 48x48 -- you can see it in the screenshot above.

There's always something satisfying to reverse-engineering things and figuring out how they work. I even wrote a little test homebrew that loads a graphics SDK ucode and tests all the aspects of the bitmap scaling command (and another one for the yuv2rgb command). I even went as far as to work out the scaling algorithms so I could replicate them to the pixel. I also added delays to roughly simulate how long the graphics commands would take on hardware.

The way the scaling command works is a bit peculiar. You give it the size of your source bitmap, then you give it a rectangle within said bitmap, and X/Y scaling factors. Then it takes the specified rectangle of the source bitmap and scales it using the factors.

You can also specify a filtering mode. Nearest neighbor, bilinear and bicubic are supported. Nothing special to say about them, other than the fact bicubic uses somewhat atypical equations.

However, there's also a fourth filtering mode: one-third. This mode does what it says on the tin: it ignores the provided X/Y scaling factors, and scales the provided bitmap down to one third of its original size. The way it works is fairly simple: for every 3x3 block of source pixels, it averages the 8 outer pixels' values and uses that as the destination value. This also means that it requires that the source dimensions be multiples of 3.

Interestingly, the example of Let's Golf would be a perfect candidate for one-third scaling, but they chose bicubic instead.


After this, I felt like looking at the DSi sound app.

The AAC ucode doesn't use the pipe to receive commands. That's why it was working in LLE, despite the bugs that broke the pipe. Instead, commands and parameters are just sent through the CMD1 register. Also, the decoded sound data isn't sent to the audio output directly, but transferred to ARM9 RAM. Hence why the DSi sound app was somehow functional (albeit very slow).

My first step was to figure out what the command parameters mean and what kind of data is sent to the AAC ucode, so I could understand how to use it. I didn't exactly feel like replicating an entire AAC decoder in my HLE implementation, so I went with faad2 instead.

This has been the occasion for me to learn about AAC, MP4 files and such. I even modified Gericom's DSiDsp homebrew to work with the DSi AAC ucode, turning it into the worst MP4 audio player ever.

DSiDsp is an example of AAC decoding, but it's made to work with the 3DS AAC ucode. Besides the differences in the communication protocol and how memory is accessed, they also don't quite take in the same kind of data. The 3DS ucode takes AAC frames with ADTS headers. ADTS is a possible transport layer for AAC audio, where each frame gets a small header specifying the sampling frequency, channel configuration, and other parameters. All fine and dandy.

The DSi AAC ucode, however, doesn't take ADTS or ADIF headers, just raw AAC frames. The sampling frequency and channel configuration are specified in the parameters for the decoder command.

So I had to figure out how to make this work nicely with faad2. I also ran into an issue where the DSi sound app will first send an all-zero AAC frame before sending the correct data, which seems to be a bug in the sound app itself. The AAC ucode doesn't seem to be affected by this (it just returns an error code), but third-party AAC decoders don't like it. faad2 gets put into a bogus state where no further frames can be decoded. fdk-aac barfs over the memory in a seemingly random way, eventually causing a crash. So I had to hack around the issue and ignore all-zero frames.

So melonDS decodes AAC audio now. It's still rough around the edges, but it's pretty neat.


Now I guess the final step would be to reverse-engineer and implement the G711 ucode.

As for LLE options for DSP emulation, some sort of recompiler (JIT or otherwise) would be the way to go. I was thinking about how such a thing might work, but I've never written that sort of thing before. It could be the occasion to learn about this. It would be worthwhile if someone out there is trying to develop for the DSP, but as far as commercial titles are concerned, HLE should cover all the needs, all while being way more efficient.


The AV codec stuff is also adjacent to something else that's on my mind. It's not related to the DSP, but it's something I want to experiment with eventually. If it pans out, I'll let you guys know!
Klauserus says:
Jul 31st 2025
you're having fun again. very cool. keep up the good work
LEGO_Vince says:
Jul 31st 2025
Always fascinating stuff. Even if I don't understand it.
ari32 says:
Aug 3rd 2025
huh. how many of these little undiscovered quirks still remain in the DS do you reckon?
rikku says:
Aug 4th 2025
Your work is amazing! Thank you for sharing this project with the public, it is very much appreciated.

Also thank you for preparing all the information and your progress. The least thing I can do at the moment is, to say "hi :)".

Have a great day and get well soon/stay well ... now! :D
Yaroslav says:
Aug 15th 2025
Welcome to Melon DS!
Dirtz says:
Sep 5th 2025
My emulator keeps cutting off every time I chose a rom. Can some one please help me
I am using a chrome book I followed every step and still no progress
RebelYT says:
Oct 14th 2025
Hey sorry for bothering you can yall add PlayStation 2, Xbox, Xbox 360 and GameCube emulators in delta please bc this app is amazing
Arisotura says:
Oct 15th 2025
we aren't responsible for Delta, it's a frontend project
Roon says:
Mar 11th 2026
Is there any way to "hack the cache timing" ourselves via debug (or maybe a cheat code) to be able to play around with DSi Sound?
Post a comment
Name:
DO NOT TOUCH