While my situation is being sorted out, I will make a post about an idea I had a while ago: attempting HLE for DS emulation.

All the existing DS emulators, as far as I'm aware, are essentially LLE. DS games are mostly self-contained and run on the bare metal, relying on the small BIOSes for basic functions like interrupt waits, decompression, etc.

Some emulators, like DeSmuME, are able to HLE the BIOS calls, basically replicating them inside the emulator. The main advantage to this is that the emulator doesn't require a proper BIOS dump to run games, but there is no other real benefit from this. BIOS calls aren't critical enough that HLEing them might boost performance significantly.

What I've been experimenting with melonHLE goes further: HLEing the ARM7.

It may seem feasible if you consider that Nintendo never allowed game developers to write their own ARM7 binaries. This means that, in theory, all commercial games out there will have one of the few possible ARM7 binary versions. It also means that the ARM7 is limited to taking care of utility tasks, while all the game logic is running on the ARM9.

In practice, how does it work?

The ARM9 communicates with the ARM7 via the IPC hardware (IPCSYNC and the IPC FIFO), and some shared memory areas. When the game boots, there is a IPCSYNC handshake, then the ARM7 exposes a bunch of services that are accessed via the IPC FIFO. The services serve to provide access to the ARM7-side hardware: sound, wifi, touchscreen controller, PMIC, firmware memory, etc. Most of these services are fairly simple, with sound and wifi being by far the most complex ones.

So I've been experimenting with this in a private repo. So far, I've implemented enough of the utility services to get some games to boot, and observe a few things:

* There is a substantial speed gain from HLEing the ARM7. If this proves to be viable in the long run (despite the problems I will get to later), it may be an option for low-end platforms.

* Even if not, I still find it quite interesting to reverse-engineer the ARM7 binary and figure out how things work.

* Super Mario 64 DS has an earlier version of the sound engine, where some of the commands are different.

* Super Princess Peach has a completely different sound engine.

* Mario Kart DS's ARM7 binary has an extra service, which is used to assist loading code to ARM7 VRAM. Nothing we really need to worry about here.

* Aside from that, the smaller utility services seem to be pretty identical across games. However, I haven't started looking into wifi.

Now, the problems to this approach:

* Obviously, this only works for commercial games. It may be possible to support most homebrew by implementing libnds's default ARM7 binary, but anything with a custom ARM7 binary won't work.

* It is far less accurate than the current LLE approach. Given the ARM7's average workload, it may not matter to most games, but there's still the potential for timing issues (which stem from bad game programming).

* I have tried a few games, but I don't know how much variation there is across the entire DS library, and how I should go about identifying the different possible ARM7 binaries. This is going to be the main determining factor for whether ARM7 HLE is viable: how much code complexity is required to attain decent compatibility?

Also, I might want to avoid getting sidetracked too much. I want to finish implementing netplay, once my apartment is less of a mess.
melonJYC says:
Jun 8th 2023
@^.^ I don’t think frameskip is available, but where can I find it?
v19930312 says:
Jun 9th 2023
Regarding identifying ARM7 binaries: you probably already figured this out, but the answer is most likely to maintain a list of their hashes and identify varying features based on that - that's what dolphin does for its HLE audio microcode detection. If hash is not a known one and HLE is enabled show a suggestion to report this and switch to LLE.
Post a comment