Timing renovation, ep 3: the new GX timings
So, this is it. GX timings are covered.

After days of feeding specific command lists to the geometry engine, measuring how long they take to run, and trying to figure out the logic behind it, we finally did it. And implemented it in melonDS.

Have yet to write a post to get into that in detail, but that will go on the board.

I believe it was definitely worth it.

Looking at history, it is apparent that first-gen DS emulators have run into issues caused by display lists taking too long to execute, despite following the timings given by GBAtek. When measuring their timings, we can guess that they went for the easier solution and lowered their per-command timings. Nothing bad with that, if it gets games running, and gets them running at better speeds on lower-end platforms, but that ain't accurate.

In a less "accuracy horseman" note, we'll quote byuu's article on accuracy, again:

If you do not get the timing perfect, you will end up playing a perpetual game of whack-a-mole. Fixing one game to break two others, fixing them to break yet two more. Fixing them to break the initial game once again. You need only look at the changelogs over the past fifteen years to verify this.

You might not end up needing absolute perfection there, but history has shown that, if you don't have the basic logic down, hacking around timing issues can only get you so far.

A prime example may well be Burnout Legends, which JMC47 mentioned in his blog post The next generation of DS emulators. The game seems to have built-in frameskipping or slowdown compensation, but it's not working correctly on emulators, resulting in random slowdowns or speedups.

I haven't looked into this game in detail, though, so I don't know for sure what it's doing.

But a possibility would be that the game knows ahead of time how long its 3D scene will take to render. This is possible if you have measured your individual display lists by running them on hardware, and gave them metadata indicating their time cost. From there, if you know which objects are going to be shown, you know how long the scene will take to render. You can then use that knowledge to keep your game logic in sync even if you're dropping frames, so the game doesn't appear to run slower.

But of course, if your emulator's GX timings don't match the hardware's, this falls apart. And if a game is doing that kind of thing, no amount of hodgepodging GX timings will fix it if you haven't gotten the logic right.

Anyway, I tested Burnout Legends with the new GX timings, but I could hardly judge whether it was correct as the framerate dips below 60FPS on my PC. So I asked JMC47, who gave it a try and said that the game is now running as it should.

Coming back to our problem games, those that overflow the GXFIFO. Super Mario 64 DS, and also Rayman Raving Rabbids 2. SM64DS was the worst offender, with more than 10000 stall cycles per frame, against a ~1800 cycle average for Rayman RR2.

None of the other games I tested overflowed the FIFO. They're generally somewhat well-programmed, and use the adequate DMA mode which avoids overflows.

After the timing renovation, these two games still overflow the FIFO, but much less. The stall cycles were nearly halved in SM64DS and the reduction in Rayman RR2 is tenfolds.

I guess this is how they work. What was less nice was that Rayman RR2 got regular music streaming issues from the stalls. So, quickly, we fire up a new hardware test, and find out that GXFIFO stalls don't halt the ARM7. Once this is addressed, the audio issues are gone.

So, in the end, this first part of the timing renovation turns out rather well.

Now it's time to get to the more daunting part: the general timings. Mostly memory access timings. I have these down already, so it's mostly a matter of implementing them in a way that doesn't slow things down.

And, regarding what I said above, I hope that I don't run into that kind of problems. Implementing the ARM9 caches is possible, but has a performance cost. So, if I hack around this, the game code would likely just end up running too fast. If this causes problems, we will have to hack around them, or propose ARM9 cache emulation as an option.

We'll see what we can do there. Apparently, the current timings are not that bad, but some things are running too slow, as Who Wants To Be A Millionaire has shown. The other issue is that, well, the current code for timings is a gross hack.

Love and waffles!
bajol says:
Nov 26th 2018
interesting article, also byuu's one.
in my opinion, accuracy is important only to a point. is there something that a, say, 1ghz emulator that can run pong at at full speed cant do that DICE can? I mean is there any noticeable difference?
in the case of that speedy gonzales game, there is a patch that fixes that issue, is it worth having a much heavier emulator just to fix some issues that one game may have, and that can be simply hacked around like that?!
extherian says:
Nov 26th 2018
I believe that the Nintendo DS is one of those consoles where the games are very sensitive to CPU timings. There are many games that either don't work at all with the Dynamic Recompiler, or require the block size to be less than a certain number in order to work. For example, in DeSmuME the intro to Final Fantasy III won't play with the Dynamic Recompiler turned on, and the game will never finish booting.

Not only that, but the "Advanced Bus-Level Timing" option, which is supposedly more accurate, actually breaks some games even as it fixes others. So it's not really more accurate, it's just broken in a different way to the standard timing option. This scenario is exactly what StapleButter was warning against in this post.

Currently the biggest shortcoming of melonDS isn't the lack of a dynarec or hardware renderer, it's that many basic features like microphone input and save file autodetection are only half-working or not implemented at all. I can't play many of my favourite games because melonDS not only fails to create a save file, but won't read save files I exported as .SAV from DeSmuME either. Hopefully other contributors will fix these issues while StapleButter tackles the really hard stuff.
Sorer says:
Nov 29th 2018
"in DeSmuME the intro to Final Fantasy III won't play with the Dynamic Recompiler turned on"
This is also true if you use nds-bootstrap (DSimenu++ or whatever its called now) on a DSi/3DS.
Someone told me its a cart timing issue.
poudink says:
Nov 30th 2018
it's still called nds-bootstrap. dsimenu++/twloader/twilight menu are just frontends for nds-bootstrap.
Post a comment