Progress Report March 2022

Progress Report March 2022

Here we are once more at the end of Q1 and progressing steadily toward the halfway mark of 2022! This month saw improvements to almost every aspect of Ryujinx, a new console is loose which got the emulation community all of a flutter and some killer new releases that, guess what, ran on day one!

Before all that though check out our patreon goals and progress toward them:

Patreon Goals:

Amiibo Emulation

Merged into the main build in March 2021.

While compatibility is close to being perfect, there are still some improvements to come for Amiibo which can be tracked on the associated Github issue here: https://github.com/Ryujinx/Ryujinx/issues/2122

Custom User Profiles

Merged into the main build in April 2021.

Vulkan GPU Backend - still in progress

A public test build is delivered and is available here!

ARB Shaders - Goal reached in April 2021.

Work is ongoing alongside Vulkan, please wait a little while longer until we are able to deliver this update into a state we are happy with.

ARB shaders will further reduce stuttering on the first run by improving the shader compilation speed on NVIDIA GPUs using the OpenGL API.

$2000/month - Texture Packs / Replacement Capabilities - almost there!

This will facilitate the replacement of in-game graphics textures which enables custom texture enhancements, alternate controller button graphics, and more.

ETA once the goal is sustained: ~3-4 weeks

$2500/month - One full-time developer - Almost there!

This amount of monthly donations will allow the project's founder, gdkchan, to work full-time on developing Ryujinx. All our contributors currently only work on the project in their spare time!

$5000/month - Additional full-time developer - Not yet met

This amount of monthly donations will allow an additional Ryujinx team developer to work full-time on the project.

Alright. Let’s go!

GPU:

Since the initial release of Pokémon Legends Arceus there was always a thorn in our side when it came to AMD and Intel GPU’s. While on the latest drivers the game ran great for them using our experimental Vulkan build, the same could not be said if any user was unfortunate enough to use OpenGL instead. NPC’s and Pokémon alike would be invisible or have various graphical glitches which we’ve come to expect of those vendors. Rendering an image involves using not one, but multiple shader stages which then sequentially form a pipeline in order to show you your elemental animals. If a shader stage needs a vector element from a previous stage that that stage did not provide, then we start to run into problems as the contents are technically ‘undefined’. On Nvidia this wasn’t a problem as those inputs are always consistent across stages, but for other vendors it broke things… a lot of things.

The fix from gdkchan makes changes to the shader translator to explicitly initialize vector elements that are used by the next stage, but might not be written on the current one. The effect is that while performance may be still be poor for AMD, the graphical output is correct.

There were a couple of edge cases to clean up here, as while this was a fairly small change, the shader translator is used in every single game, every single time an image is drawn. Initializing indexed inputs used on next shader stage and not initializing geometry shader passthrough attributes were therefore addressed in order to prevent regressions in a number of titles, including Game Builder Garage (again…) and WarioWare: Get it Together!

When Brilliant Diamond and Shining Pearl were turned loose upon the world in all their gen 4 glory, users couldn’t help but notice the game took… a while… to… boot………………….

This problem is actually two-fold (and if all goes to plan a future progress report will explain the second half of the issue), but this report will focus on the first of these fixes.

Some games have a buffer usage pattern where it uses small adjacent buffers with increasing addresses. Right now this causes a new buffer to be created each time, merging the existing overlapping buffers. It’s effectively resizing the same buffer over and over, page by page which is very inefficient. The fix therefore simply allows the buffers to expand at a rate of 1.5x which, while possibly using a bit more memory, massively cuts down on the buffer creation bottleneck.

Other games benefit from this including Super Mario Galaxy, which notoriously had an extremely laggy title screen for the first minute or so, before apparently randomly jumping up to 60fps.

Before:

After:

Galaxy also got some more love in the form of the S8D24 texture format being implemented. This is used for starbit interactions throughout the game and so was a brick-wall against actually being playable from start to finish. Galaxy isn’t out of the woods yet but this was a major step in the right direction.

Before:

After:

The modern internet age is very firmly upon us and our users wish to record, stream and otherwise broadcast their gameplay around the world. There was a small snag however: most capture programs such as OBS or even simple overlay programs like RTSS make a lot of assumptions on how a program will present frames, which do not always turn out to be correct. Especially when the presentation method isn’t what most native games would consider ‘normal’.

By explicitly providing capture software and overlays the information about the framebuffer and viewports riperiperi managed to mitigate most of these issues!

Ryujinx was the first Switch emulator to implement NVDEC video decoding back in 2018, but the implementation still isn’t perfect and the root of one of these limitations is actually in extremely old technology. If you were born after the new millennium, then there is a chance you never had the delightful experience of dealing with interlaced video! Video resolutions are usually stated in such formats as ‘720p’, ‘1080p’ etc. and this ‘p’ stands for progressive scan. What some of the younger audience may not know or remember is that formats like ‘480i’ and ‘1080i’ also used to exist and the ‘i’ here stands for interlaced. Progressive scan draws each line of the video one after another to construct a whole frame, while interlaced video only constructs every other line of the image in a single frame; this was a useful compromise to send less data over the air before digital signals, but can result in visual artifacts depending on your deinterlacing method.

While I’m sure this is very interesting, a lot of you will be wondering what this has to do with the Switch, a console made in 2017 which is well beyond the times when progressive scan took the spotlight. As it turns out some games like to go for that authentic feel in retro-styled videos that actually do make use of interlaced video! NVDEC does support interlaced footage but our implementation, on top of FFmpeg, did not and was thus corrected this month. FFmpeg now provides us with the full progressive scan frame from which we can extract the even and odd fields to then reconstruct the original interlaced image, from here there are a couple of options to then deinterlace it back down to progressive scan so that it displays correctly on modern displays. BOB and Weave both produce artifacting in low and high motion scenes respectively (see the example below):

Weave:

BOB:

Therefore ‘Motion adaptive’ deinterlacing is used to try and mitigate the flaws of both methods and provide a more stable and artifact free final image. This allows games such as Layton's Mystery Journey to show its cutscenes in their full form!

To wrap up March’s GPU section, gdkchan once more struck a home run by fixing an issue that plagued almost every guest OpenGL game on the Switch. By ‘guest OpenGL’ here we refer to the rendering API the Switch itself uses to display the game, not the API that Ryujinx is using to emulate this. The Switch is capable of using its own NVN proprietary API (for most first party titles), Vulkan (notably used in 3D All-Stars and games like Hades) but also OpenGL. However a lot of OpenGL games had glaring, but very similar visual issues:

Zombies Ate My Neighbors and Ghoul Patrol

Putt-Putt Travels Through Time

Cartoon Network: Battle Crashers

Digimon Story Cyber Sleuth: Complete Edition

Snack World

As is apparent, the problem in all of these titles looks to be the same and that holds true for the fix! It turns out the Tegra's OpenGL driver has a bit of a quirk when copying data from block linear textures. This behavior is now fully emulated in order to fix the texture corruption issues these games exhibited.

CPU:

Improvements to the CPU recompiler continued in full-force this month with merryhime retaining the crown.

Aside from raw instruction implementations and fixes, the recompiler is now forced to exit on trapping instructions to ensure no code after these are executed, and a small fix to some kernel threading functions was applied to more closely match hardware. To finish up, the order in which some memory barriers had been arranged was changed to align with conventional theory. No games should be affected here but these changes should make Ryujinx more resilient as an emulator and a better resource for many enthusiasts.

Audio, Kernel and Services:

Thog started strong in March, fixing a bug in the audio renderer which was causing a couple of games to crash on-boot such as ‘Mononoke Slashdown’ (which now heads in-game) and Paper Mario: Origami King, which used to experience random crashes while in-game. Both of these issues should now be a thing of the past!

Animal Crossing: New Horizons continues its warpath to add endless new service dependencies with every update and 2.0.5 was no different. Ac_K once more descended into the trenches and implemented the ‘OLSC: GetSaveDataBackupSetting’ service, which was introduced in firmware version 10.0.0. This allows Animal Crossing to boot if you have a valid save file and user profile attached to it… until the next update!

A second service implementation this month was only made necessary just recently, when a lot of Ryujinx’s networking infrastructure was rewritten. With the “Guest Internet Access” setting enabled, Splatoon 2 would fail to launch, and it turns out for all this hassle it’s basically just trying to check what time it is! ‘IEnsureNetworkClockAvailabilityService’ was thus partially implemented (we don’t actually contact Nintendo for the time!) and Splatoon 2 is non-the-wiser! The game can now be booted once more when this setting is enabled.

A small fix to the closing process of the emulator was made to mitigate NullReferenceExceptions when closing Ryujinx or stopping emulation and a limit to the number of events the ‘GetDisplayVSyncEvent’ service could signal was added; the latter of which allows  .hack//G.U. Last Recode to achieve playable framerates with logging enabled, as previously the VsyncEvent signal would be triggering multiple times and spamming the logger.

On the topic of massive slowdowns, anyone who’s played Fire Emblem: Three Houses on Ryujinx will know that while most of the game runs extremely well, there is a single outlier. And that outlier isn’t crazily animated battle sequences or scenes with 20 NPC’s on screen, it’s the calendar…

Yes that’s right, this one section of the game can bring Ryujinx to its figurative knees with a staggeringly swift 15 FPS on our systems. The culprit you may ask? Once again it’s those pesky network services that seem to be infecting every game on the planet these days. At a simple level, the slowdown is caused when Ryujinx is constantly asking your PC what the local IP and other network info is, the game asks for this info and Ryujinx simply tries to give it the info it needs… every frame. The solution that first-time contributor JumpmanSr proposed here is to cache local network information provided by the host system and only update this when the network configuration actually changes. This way Ryujinx can give the game all the correct information without having to go through the expensive cycle of asking the host system every single time. The FPS improvement here is dramatic and finally resolves one of the last outstanding issues with this game!

MISC:

As one reddit user (who will remain anonymous) so graciously pointed out after last month's progress report: “ctr+f Steam Deck: 0, lame” this month we will give a mention to the Steam Deck (already 2 results). While not the most powerful portable machine you can buy, it has truly captured a lot of people’s hearts and minds, including a couple of the development team who may receive their own sometime in Q2/Q3.

With this in mind Ryujinx became only the second .NET 6 application in the world to go on a diet and flatpak itself! Thog here putting in a lot of work behind the scenes to prepare Ryujinx’s infrastructure for this format, which for .NET applications is actually far from trivial. Either way Linux users can now find us on FlatHub and worry not about falling behind as our build-bot will auto-update the FlatPak too!

Onto some more GUI related adjustments, a feature that has been so highly requested that it’s had not one but three separate pull requests filed is the ability to hide the console logging window! Anyone who doesn’t wish to be plagued with the anxiety of seeing all the magic happening behind the curtain can now simply uncheck the “Show Log Console” box in options and never look back! This option is only available on Windows as Linux can already hide the console via CL arguments.

Another first-time contributor darko1979 implemented a new option to rotate the emulated analog sticks by 90 degrees, which should make games that utilize sideways Joycons such as Super Mario Party much more accessible. Use this setting in conjunction with axis inversion to achieve the desired stick rotation!

To wrap up we’ll head into a quick-fire round of small additions or fixes:

Closing Words:

You! You are finally awake? You were trying to run Ryujinx with Vulkan, right? You should wait for the next progress report my friend!

That's all we have for you this month.  We'd like to thank everyone for their continued support as we pass the Switch's 5th birthday! In just half a decade we’ve already come so far and it’s majorly thanks to everyone who has backed this project over that time; this level of growth wouldn’t have been possible without you! As usual if you’re interested in emulation and know some C#, we’re always delighted to see new code contributors and if not simply giving us feedback, opening issues on github or just reporting compatibility goes a long way!

Until next month!