Hi, three months have passed since our last progress report, and now it's time for a new one. Our team has made a lot of interesting improvements that have helped Ryujinx render a lot of games, and go in-game in many of them. So, let's see what's new.

Introducing ANGEL

One of the main problems that Ryujinx had was GPU emulation. Compatibility slowly improved over time, but it was not possible to get very far on many games, mainly because GPU emulation was too slow, and had too many bugs. This caused a lot of graphical glitches on more taxing games, or even just a black screen with no rendering at all. After finishing the JIT rewrite that was discussed in our last progress report, gdkchan started working on better GPU emulation.

His new work became Another NVIDIA GPU Emulation Library, or ANGEL for short (Ryujinx#789).

The more complicated 3D games require GPU emulation with more complex features. The old GPU emulator was missing support for these features, causing it to not work well with these games.

One of these complex features is texture views. A texture view is, to put it simply, a sub-region of a larger texture. For example, let's say that you have a cubemap texture, a kind of texture that represents the 6 faces of a cube. With texture views, we can create a "sub-texture" for each one of those 6 faces, and do whatever we want with them. A potential use for this is rendering to 6 2D textures at a time, with each texture being one face of a cubemap, and then sampling from the cubemap using a shader. At the API level, this is simple to do. However, the GPU does not know that each one of those 2D textures are actually supposed to form a cubemap, since the GPU works with texture addresses directly. Evidently, a naive texture caching approach wouldn't work in this case. The GPU emulator must be able to identify sub-textures for a larger texture so that, like in our example, it would notice that the 6 2D textures fit perfectly inside the larger cubemap texture. Thus, when creating the new texture, it can copy the data from the smaller textures.

Another one of these complex features is buffers. They are not as complicated to handle as textures, but things like a shader writing to a buffer later being used as a vertex buffer on a draw call is not uncommon. Which brings us to the next topic. On NVIDIA, shaders can use something called global memory, which allows them direct access to the GPU address space. The old GPU emulator didn’t support it, causing problems such as missing text in many games. There are also some more extreme examples, such as Team Sonic Racing, which uses them to do model animation transforms Without support for global memory access, it wouldn't render any animated models at all. All of these issues have since been fixed with ANGEL.

There were also a lot of other smaller improvements and fixes. More shader instructions are now supported, fixing many bugs. The shader translator was made a bit smarter, and can now perform a few more optimizations based on code pattern matching that may allow some shaders to work on GPUs without support for NVIDIA specific intrinsics. Compute shaders are also now supported. Without them, some games wouldn't even render anything at all.

If you’d like to see the final result after all of these improvements, you can check the screenshots below, which showcase games that previously didn't work at all or had a lot of graphical glitches due to GPU emulation issues.

There's still a lot of work to be done in terms of fixes, missing features, and performance improvements, so stay tuned for the next report! Unfortunately, gdkchan will probably spend some time away from the GPU, as there are other things that also needs his attention. The good news is that as part of the GPU rewrite, we're also adding documentation covering most of the code, so it should be easy for anyone to get involved and help improve Ryujinx even more. That person could even be you!

HLE

Since the release of firmware version 9.x this fall, newly released games require a minimum of version 8.x to launch, so we’ve had to update some things in our HLE implementation. Thog worked hard on the time service implementation, updating it to be accurate to the latest Switch firmware (Ryujinx#783). You can now get accurate time in Ryujinx, so take a look at your played time in save menus! As with many improvements, this has also allowed even more games to boot and go in-game.

Thog has also updated nvservices, the Switch’s customized NVIDIA driver, and optimized it to get everything more accurate and easier to be updated. This allowed almost all recent games to boot, like The Legend of Zelda: Link's Awakening, which now shows a loading screen, and allowing Super Nintendo Entertainment System, to boot into the main menu (Ryujinx#800).

One of our main issues in our HOS emulation is the lack of Applets support. The Switch firmware uses Applets for the on-screen keyboard, error pop-ups, user selection, and web browser and controller selection, etc... which a lot of games need to work properly. jD has implemented basic support for user selection (playerSelect), which now selects the default user automatically, although it only has support for one user for now Ryujinx#804. He also implemented a stubbed Keyboard Applet (swkbd), which automatically returns the text "Ryujinx" to avoid blocking games that requires you to input text from going in-game, like for games that have name selection screens such as Pokémon Sword/Shield and DELTARUNE (Ryujinx#826, Ryujinx#839).

In order to support more games, Ac_K implemented many new service calls (Ryujinx#761, Ryujinx#829, Ryujinx#830, and more...), which has helped Pokémon Let's Go Pikachu/Eevee, Pokémon Sword/Shield, Cadence Of Hyrule, and many other games to boot further.

To help maintain an accurate and organized project, Ac_K has also refactored all service folders (Ryujinx#771) in accordance with firmware 9.x, as well as fixing other miscellaneous bugs, alongside Thog.

What would Ryujinx be without LibHac? Moosehunter updated it to match Nintendo's APIs more closely, and to return correct result codes instead of just giving error message, which is needed for better HOS emulation (Ryujinx#792).

CPU

LDj3SNuD has implemented a few new instructions, and optimized some others, which are needed by games that didn't boot before. For example, Super Nintendo Entertainment System can now load games (Ryujinx#782, Ryujinx#797, Ryujinx#815, Ryujinx#819, Ryujinx#841).

In some specific cases, our current JIT implementation could cause an out of memory error. Gdkchan fixed this by adding a limitation of maximum instructions in a function, this fixes Harvest Moon. (Ryujinx#843).

GUI

Xpl0itR has continued his work on the GUI, and made some changes to the aesthetics. For example, he added a progress bar that shows the progress when loading the game list. He made some functional changes too, like having the game list load asynchronously to prevent the GUI from freezing while waiting for all games to be loaded, enabling column sorting, and adding a favourites column (Ryujinx#757).

License

Since our emulator is written from scratch, we write a huge amount of code and reverse engineer a lot of Switch games and system services. We needed to find a license that allows for some minimum level of protection for contributors work, while also not stopping any open source projects from using parts of our code. This is why, with all developers in agreement, we’ve made the major decision to switch from the Unlicense to the MIT License.
This doesn't change anything for the end-user. It only gives credit to contributors for their code, ensures that their code will be protected, and helps open the door for new contributors.

.NET Core 3.0

Towards the end of September 2019, Microsoft released .NET Core 3.0. In order to be more up-to-date, LDj3SNuD updated Ryujinx to .NET Core 3.0 (Ryujinx#784), as well as doing some cleanup to the code and fixing a CPU instruction. This has deprecated our previous CPU emulator, ChocolArm64 (Ryujinx/ChocolArm64).

You can find many more screenshots and videos of the games affected by the new changes on our discord server.

If you want to support us, then donate to our Patreon.

That's a wrap. Feel free to share this blog post with your friends.

(Videos included with permission from LeafNation)