After the long-winded build up over the last months, we're finally seeing some work on the emulator core itself again. Lo and behold, there's progress on support for more games, and a new alpha release on the horizon!
New titles going in-game: Nano Assault and Bravely Default!
I already teased Bravely Default back in July when it started booting. With the upcoming alpha release, it will get past the intro screens and let you create a new save game and even play the game! There’s a small catch: None of the 3D graphics get rendered right now… Granted, maybe calling that “playable” is a stretch even for emulation ;)
There’s another title that’s fairing better though, which I haven’t mentioned so far even though it’s been doing “something” for a while now: Nano Assault!
Nano Assault works remarkably well already: Not only can you create save files and watch the game’s intro cutscene, but you can actually play the first two levels too! I'm very happy with this result, especially since it's one of the graphically more complex games. Not all effects are rendering perfectly due to missing features, so that's a good hint as to what to implement next.
With the news out of the way, let’s see what work was involved to get Mikage up to the task.
By far the biggest work item was the RenderTargetCache: This is the part in Mikage that matches raw framebuffer data in emulated memory with fast render targets used on the phone GPU. This sort of cache is critical for getting any performance benefits out of hardware (Vulkan) rendering over software, and getting it right is essential to bug-free emulation without rendering glitches. In fact, Citra still struggles with this today, so it was important to me to address this early on.
Thanks to the work I put into the testing framework, it wasn’t too stressful to come up with a reliable rewrite of this component. As a result, not only is the RenderTargetCache itself much more readable, but I was also able to resolve various compatibility issues: Nano Assault picked up an old render target previously, causing it to crash shortly after due to an invalid viewport setup. The both_screens homebrew example now renders the bottom screen as you’d expect.
Finally, the RenderTargetCache revamp removes the need for many annoying workarounds that harmed performance. Of course, the bottleneck is still largely CPU emulation, so don't expect this to do miracles to your frame rate yet. But at least the GPU won’t hold us back anymore now either.
OpenLinkFile implementation and SelfNCCH archive tests
Link files are used to open a second "view" onto an already opened file, which is a feature that many games - notably Bravely Default and Nano Assault - use internally. Implementing this feature posed a bit of a challenge: I didn’t know what things games were allowed to do with them specifically, and so supporting link files could’ve required either a minor adjustment or a costly rewrite.
Once again, the testing framework came to the rescue though. Link files are only supported in the SelfNCCH archive, so writing tests for them was straightforward. In the process, I also ported the existing FS tests to the SelfNCCH archive (previously having only covered the save file archives).
Long story short: Having tested link files on actual hardware, I can now confidently say that a simple tweak is enough to support them properly. Basing this on a scientific research process feels much better than taking a leap of faith and crossing fingers nothing will break because of it!
Change default key bindings
Did you know you can use Mikage with USB keyboards? In fact, this feature had been present since the initial release. The four 3DS keys A, B, X, and Y are mapped to the keyboard keys A, S, Z, and X, respectively. This is a bit awkward though: If you look at the physical button layout used by the 3DS, you'll notice for example the keyboard's "S" is on the top row, whereas in the physical layout on the 3DS it's at the very bottom!
This was particularly noticeable in Nano Assault, where you fire bullets by pressing any of the four buttons, and each button will shoot in a different direction. Suffice to say it was rather confusing if you pressed a top key on your keyboard, yet you would fire bullets backwards!
One thing the old button layout got right is the button order in clockwise direction: On the 3DS this is ABYX, and on the keyboard it's ASXZ. If you hold the 3DS in your hands, the X and Y buttons require your fingers to reach out ever so slightly more though - hence so should their keyboard mappings! As a result, I chose Mikage's new default mapping to be ABYX->XZAS.
This may sound a little abstract - so just give it a try! You'll notice it feels much more natural than before.
A new Alpha Release
It's been a while! But with the fruits of the hard work starting to show, it's finally time for a new alpha build. I hope to publish this on the weekend, but certainly before the end of November. Stay tuned :)
This post was originally posted on 19 November 2019 for patrons, and released publicly on 19 December 2019.