Development Update 8: Bug fixes and speedups
It's this time of the month again! If you haven't seen yet, I uploaded a new gameplay video showing off Cave Story 3D earlier this month. But of course I didn't stop there, and in fact this month we got another title working in Mikage.
Steel Diver: Sub Wars enters its title screen
Steel Diver: Sub Wars now reaches the title screen! Other than many small fixes, I uncovered two major bugs:
- When emulating IPC requests, Mikage considered it an error when a game provided a zero-sized buffer. After all, if you're asking the system to do work, why would you request no data to be returned? Well, it turns out game programmers sometimes just don't mind, so that's precisely what they did. It took some creativity to find a clean way of supporting zero-sized buffers, but these games now won't error out anymore.
- During startup, Steel Diver requests a memory transfer ("DMA") from a seemingly unknown memory address. It turns out this was a bug in the GSP emulation, where DMAs were assumed to refer to memory with process-agnostic virtual-to-physical address mapping. By referring to the game's own memory space instead, the input memory address is recognized properly and hence the DMA runs through just fine now. Ironically, Citra got this wrong too: They implemented what was easiest and eventually concluded it was incorrect behavior, leaving a note in the source code suggesting to move to the wrong behavior in the future.
As you can guess, these issues by no means only affected Steel Diver. I'll have more news next month about other titles :)
GPU texture combiner scalers
The Legend of Zelda: Ocarina of Time 3D and Nano Assault EX got a nice update to their visuals: You might have noticed various objects to look a bit dull or boring compared to how they look on hardware. And indeed, this was because Mikage didn't implement a feature called texture combiner scalers!
Adding support for this feature luckily wasn't too difficult and the games now look fantastic. See for yourself:
New CPU Interpreter dispatcher
This is actually the preparation for another big feature, but implementing it went hand-in-hand with replacing some ugly logic with a much neater approach that also happens to improve performance a little.
C++ metaprogramming comes in handy again: Instead of going through the cumbersome process of decoding ARM instructions manually, there is now a simple table that describes the various ARM opcodes, and we have the C++ compiler conveniently generate a lookup table from that:
A quick benchmark on the CPU-heavy yeti3DS application yielded a 19% framerate improvement, which is a nice side effect for a change that wasn't even geared towards optimization!
USAT emulation fix
While working on the new dispatcher, I stumbled upon the cause of a long-standing bug that had been haunting me for a while: The incorrect rendering of the walls in yeti3DS!
It turns out the interpreter decoded the argument to the USAT instruction incorrectly. It's one of those things that's super easy to overlook when glancing over the source code - until you double-check against the ARM manuals and realize the decoding logic has been wrong all along.
With all the fixes recently and so many new games being close to fully functional, it's finally time to make Mikage produce more than just a beautiful slide-show. I'll been working on this behind the scenes for a while now, and you'll see the first fruits of that work next month.
Stay tuned ;)