Sometimes issues are simple... sometimes not
You might have noticed that one of my goals for the 1.0 release is to get DSi mode in melonDS up to par with DS mode. Not just in the sense of running DSi games faithfully: a good reproduction of the DSi environment is also useful to would-be homebrewers.

However, the road to DSi emulation is paved with all sorts of challenges. One example of a fun issue that had been reported a while ago: the DSi menu would freeze after the health/safety screen if any pictures were stored that could be displayed on the top screen. The issue was another unimplemented AES feature, and was fixed in melonDS 0.9.3.

Sometimes I wish all issues were this simple. I felt like looking at another of the known DSi-mode issues: the fact that we currently don't implement the RAM size register in SCFG_EXT9. The RAM size register is mainly used to restrict the accessible main RAM to 4MB before launching a DS game. In theory, not a very difficult thing to implement. In practice, however, there is an issue that kept us from enabling that feature: when it's enabled, the DSi launcher crashes when launching a DS game, while they would otherwise run fine (albeit with the full 16MB RAM instead of the 4MB they might expect).

As explained in GBAtek, nocash ran into the same issue:
SCFG_EXT9.bit14-15 affect the Main RAM mapping on <both> ARM9 and ARM7 side (that, at least AFTER games have been booted, however, there's a special case DURING boot process: For NDS games, the firmware switches to 4MB mode on ARM9 side, whilst ARM7 is still relocating memory from the 16MB area at the same time - unknown how that is working exactly, maybe ARM7 isn't affected by SCFG_EXT9 setting until ARM7 has configured/disabled its own SCFG_EXT7 register).

The basic process of the loader is as follows: the ARM9 syncs with the ARM7 via IPCSYNC, then both CPUs run through lists of memory areas to copy or clear, then the ARM9 changes the main RAM size if required. However, while the ARM7 has a bunch of regions in main RAM to clear, the ARM9 is given empty copy/clear lists, and all it has to do is clear its DTCM, which is quickly done. As a result, the ARM9 changes the main RAM size while the ARM7 is still clearing regions, causing it to overwrite the ARM9's code, and you guess how this goes: kaboom.

Yet, the same code works fine on hardware.

I had already experimented with the RAM size register, to try and find out if there's anything fancy about it, but there's nothing special at all. The RAM size gets changed instantly on both sides, and there's nothing fancy about memory mapping either. Oh and the ARM9 caches are disabled when the loader is running, so they don't come into play here.

So I made a homebrew that reproduced the loader code: same ASM code, same memory regions, same everything. My first tests were to see if there was any kind of secret register altering main RAM mapping somehow, but there was none. Then, another test determined that, infact, on hardware, the RAM size change isn't applied until the ARM7 has cleared all its memory regions.

We then added code to measure how long each side takes to complete its tasks, and it turns out that the ARM9 takes much longer than expected. The ARM9 code is running in main RAM, and the ARM7 has a bunch of main RAM regions to copy and clear: as EXMEMCNT is set to give priority over main RAM to the ARM7, the concurrent accesses are slowing down the ARM9. A lot.

This is some shitty news.

First of all, this is probably not an isolated case: the same sort of thing can also affect timing in games, although probably on a lesser scale.

Secondly, there is no way to correctly emulate this sort of thing without a cycle-accurate emulator. Given the current performance characteristics of DS emulation, and the sheer complexity of DS timings, cycle accuracy can be considered off-limits. In this particular case, the best we could do would be some kind of estimation for a cycle penalty if several concurrent main RAM accesses are detected within a given timeslice (that's the thing, there's no real way to determine whether they are actually concurrent, due to how we run things).

Oh well.
poudink says:
Sep 6th 2021
This sounds tricky indeed. Best of luck finding a decent fix.
Mjbjenkins says:
Sep 7th 2021
Not sure where to put a comment like this, but is a Mute button hotkey possible? I feel like something like that would be very useful for people who want to fast forward their games but not hear a fast forward version of the music/sounds from the game.

Idk if anything like this currently exists already, I can't find anything on MelonDS 0.9.3. Only a volume slider in the Audio Settings.
Jerma Star Wars says:
Sep 7th 2021
I think you sound lovely, and I admire your dev work. We should talk!
kevincrans says:
Sep 15th 2021
To decrease cpu usage, thus increase performance, I recommend using the 4194304hz gameboy clock instead and only applied executing the arm7 instructions exclusive to the boot code, leave the arm7 sound alone. After that, the clock should disable itself, until similar arm7 code is executed.

You can also try running arm7 on a less busy real core.
Akmaj says:
Sep 22nd 2021
I'm glad there's still someone working on DS emu! I was having hard nostalgia after seeing love+ reference in a game I was playing, then went to desmume but realized the last release was 6 years ago, luckily someone on reddit posted a link to this site, was pleasantly surprise to see you guys are still active. Thank you and keep up the good work!
A dragon says:
Sep 22nd 2021
If you've hit a dead end because of the BIOS file, maybe you should consider reverse engineering them to try to get the emulator to run without them. Even if you can't get fix that issue, it would be nice to not need external BIOS to run games. Anyway, there is something else I thought about. I've heard about something about PCs moving from X86 to Arm or RISK 5. Do you think that would make any difference?
Rayyan says:
Sep 23rd 2021
I don't think it's about the BIOS files, and it has already been reverse-engineered by DraStic (iirc).
About PCs moving to ARM64, we already have ARM64 support for Linux and macOS.
>=[ says:
Sep 25th 2021
You wouldn't expect code written in 2006-2008 to be dependent on the hardware's timing to work properly, like some DOS era CPU software, but here we are... great job nintendo.
Generic aka RSDuck says:
Sep 26th 2021
well the code we're talking about is about as hardware specific if not more than most DOS software. It might even be possible that they knew about the timing issue but left it in. It's not like they're going to bring out a DSi with faster main RAM.
Some Guy says:
Sep 28th 2021
I'm not very technically minded but I love this project since the DS was basically my childhood. I don't know how to help or say anything useful here, but I am just going to say how wonderful the emu is and what a nostalgia trip it's been. I never owned a Dsi or a 3ds, so sorry.
Guest says:
Oct 5th 2021
I'm curious, however when on MelonDS in Linux, what is considered more stable, for local wireless and/or online? Using direct mode with PCap or indirect mode with Slirp?
Generic aka RSDuck says:
Oct 6th 2021
wfc via indirect mode is usually seen as the most stable and robust option.
Guest says:
Oct 6th 2021
Thanks @Generic aka RSDuck, I understand that this is also applicable to Linux?
And how about local wireless? Though I understand that this is notoriously unstable either way?
Rayyan says:
Oct 6th 2021
libslirp is the easiest and quite reliable for WFC.
Local wireless is a different story though, it has tight timings and really depends on your computer.

libslirp/pcap are only for WFC, not for local wireless.
poudink says:
Oct 6th 2021
[quote]wfc via indirect mode is usually seen as the most stable and robust option.[/quote]
Wait, really? What reason is there to keep direct mode around, then, if it's less stable and harder to set up?
Post a comment