Update
I had a few bugs in my implementation. After fixing those, the timings I got were closer to what it should have been. Too fast, but way too fast.

Anyway, I had issues with my test app too. One of the memory buffers it accesses was in main RAM instead of DTCM; fixing that oversight gave me more realistic timings. In reality, the Millionaire issue was what I first thought-- on hardware, the FMV decoder completes in 146 scanlines, and I was being too slow.

So, obviously, fixing the timings made it fast enough that the glitch was entirely gone. But, aside from that, we were back to square one: running too fast and the issues it causes everywhere. Rayman DS is a good test for that, and it was shitting itself big time, so... yeah.

If we raise the cached memory timings to 2 cycles, as some sort of average between cache hits and cache misses, we get closer to the real thing. Still a bit too fast, but this time Rayman DS is running normally.


However...


The new timing logic, coupled with PU emulation, is a pretty noticeable speed hit.

We can keep the PU logic for a potential future 'homebrew developer' build, that would also have several features to warn against typical DS pitfalls. For example, some form of cache emulation and/or warning about things like DMA without flushing/invalidating caches, 8-bit accesses to VRAM, etc...

If there is demand for such a build, that is.

As far as regular gamers are concerned, we can go for a faster compromise that would run most of the shit (really most of it) well. It wouldn't run things like GBA emulators that make extensive use of the PU, but... eh.

All the commercial games around use the same PU settings. We can say as much about libnds homebrew, its settings are a little different (for example, putting the DTCM at 0x0B000000 instead of the typical 0x027E0000), but nothing terrible there. All the differences we can observe are essentially in where the DTCM goes.

Since the DTCM is already handled separately (in CP15.cpp), we can handle its timings separately, and use a coarse table for the rest of the memory regions, like we did before. All while retaining enough of the new timing model that melonDS's timing characteristics would be much closer to the real thing.

As explained before, it's near impossible to perfectly emulate ARM9 timings due to the sheer complexity of the architecture and the way it's implemented in the DS, so if we can get 'close enough', might as well do it without wasting too much performance over it.
extherian says:
Dec 7th 2018
I'll have to admit to being entirely ignorant as to what the PU is. Googling "Nintendo DS PU" got me nothing. Is it just short for "processing unit"?

Shonumi ran into many performance issues when testing DS functionality with GBE+, especially with pipeline stalls. I'm sure you're familiar with their work already, but I thought I'd mention it anyway just in case.

I think aiming for homebrew compatibility is going a little too far. Not even Dolphin, the gold standard for emulators, offers full compatibility with Wii homebrew. Being able to run GBA games, on the other hand, would be cool. But according to Shonumi the 2D engines of DS and GBA aren't as simular to each other as they may appear at first glance, so that would be something for the far future. I think most people would be content just to be able to run games without adjusting JIT block size constantly to stop things crashing.

As far as third-party code goes, it might be an interesting idea to put up a "to-do list" for trivial things that aren't related to the emulation core. Hotkey support, for example, which we need for microphone support. If someone implemented it in a messy way, it wouldn't be that big a deal to just tear it out and do it again later, since it won't affect how games run. I think for small things like that it would be worth considering outside contributions. I'd love to start using melonDS right now, but autosave detection and input support isn't complete enough for me to finish any of my games using it.
StapleButter says:
Dec 7th 2018
Protection Unit, also Memory Protection Unit (MPU). Basically handles read/write/execute access permissions for memory as well as whether they can be cached.

As for melonDS development, well...

Addressing save type detection is on the short-term TODO list. The current code is a trainwreck, I'll just throw it out and use a database. Microphone is also on that list.
Post a comment
Name:
DO NOT FILL