Hello everyone to the summer (or winter, for those on the southern half of this Earth) edition of Citra’s progress reports. Although not very many large changes have been made, many fixes have focused on accuracy improvements and implementing some of the sorely needed user experience features.
Before we go further into this, our Patreon poll results are out. We asked our patrons, which feature they would like to see us work on next and they delivered. Here are the results and as you will see, some of these have been considered and already implemented.
To get access to such exclusives in the future and to support this project, consider becoming a patron. Now, enough appetizing, have your entrée:
Let’s start with a simple but sweet one — you can now assign hotkeys to
pausing, unpausing, and toggling speed limiting. By default, you can pause with
F4 and toggle speed limiting with Ctrl+Z.
But, of course, you can bind these actions to other keys in Citra’s
The property for pausing is
for speed toggling it is
You can now configure Citra to search multiple directories for games and apps! This allow you to keep titles across different folders, and if you have any launchable titles installed into Citra’s virtual SD card or NAND, they’ll also show up in their own section so you can boot them from the game list.
If you are one of the lucky few with a 3D TV or monitor attached to your computer, stereoscopic 3D support has just been added to Citra! You can enable it by heading to Emulation → Configure… → Graphics → Layout, ticking the Enable Stereoscopic 3D checkbox, and changing the screen layout to Side by Side.
For the longest time, many games were unplayable or needed workarounds on Citra due to them needing the software keyboard applet. The reason being that whenever they would try to open it, Citra didn’t implement it, and so would simply tell the game that the user entered “Citra” and tapped OK, without actually prompting. But now, thanks to zhaowenlan1779 and jroweboy, it now has fully functional software keyboard emulation!
Whenever a game requests it, Citra will pause the game and pull up a text box that you can fill in like any other prompt.
Many Nintendo 3DS games require the use of system archives, which contain things like fonts, a bad word list, and assets for Miis. Because these are copyrighted, Citra could not include them, and users had to dump a copy from their consoles, which was a generally tedious and error-prone process.
Now, B3n30 has created open source alternative fonts and a bad word list that can be used in games instead of the official archives. And, because these are open source, they are now included with Citra. If a game requires either archive, and you haven’t dumped them yet, it’ll automatically give the game the alternative archives. This is a step forward to Citra becoming a full-fledged HLE 3DS emulator.
Shadow mapping is a way to quickly apply shadows to 3D scenes. It first renders the scene without any lighting, texture, or colour information, with a virtual camera from where the light source begins. Then, from that rendering the depth map is extracted. That is then applied as a texture to the darkened scene, making areas of it directly visible from the light source appear more brightly lit.
The PICA200 (the GPU inside the 3DS) and OpenGL both implement this in different ways, particularly in two important areas:
The first is that PICA200 supports a variant called “soft shadows”, where the depth map is blurred before being applied to the scene. This results in shadows that seem less jagged and sharp, making the light source feel more diffuse and evenly spread out throughout the scene. OpenGL doesn’t support this at all.
The second is that the PICA200 stores depth maps intended for shadow mapping as plain textures in the RGBA8 format. A lot of games exploit this in order to quickly convert other types of textures from an internal format to RGBA8. But, OpenGL stores these maps in a format internal to that graphics card, like any other map. (RGBA8 or 8bit RGBA is a texture format, which is the combination of an RGB (red green blue) color model with an extra 4th alpha channel.)
The first point isn’t as significant, since the softness can be ignored on OpenGL, resulting in a very fast (but inaccurate) shadow mapping. Because games rarely use soft shadows, this can be ignored relatively safely.
The second point though, because games use it very often, it has to be implemented accurately. The naïve way would be to simply convert internal textures to RGBA8 manually, but this would slow rendering down to a crawl. The smart way would be to try and trick the graphics card driver into performing a similar conversion, but such an attempt exposed a lot of issues, leading to instability.
After some very hard work by wwylele, both problems were solved with a single solution. OpenGL supports an extension called Image Load/Store, which allows shaders to read and write to any texture directly. Using this, he created a shader that could accurately implement both soft shadows, and convert the depth map from its internal format to RGBA8 very quickly.
Unfortunately, because Image Load/Store is an optional extension, not every OpenGL 3.3 graphics card will support it. In these cases, Citra will simply ignore shadow maps, making the rendering inaccurate but usable. Image Load/Store became a mandatory part of OpenGL in version 4.2, so every graphics card that complies with OpenGL 4.2 is guaranteed to work correctly. Citra only requires a minimum compliance to OpenGL 3.3, but OpenGL 4.2 compliance may lead to more accurate rendering.
cubeb is an audio library (developed by
the Mozilla Foundation) that’s cross-platform, and most importantly fast.
Reports from Dolphin’s blog
showed that it ran at a third of the latency of their OpenAL backend. And now,
thanks to the work done by darkf and some fixes
from MerryMage, Citra can now benefit from that
same low latency audio that Dolphin and Mozilla Firefox have. This will lead to
significantly less distortion and stuttering in your games. Just remember to
enable it in the configuration menu by setting
Output Engine as
You can now configure the volume level of Citra directly from the configuration window. This allows you to set an individual volume level for Citra without having to manually set it in your operating system settings.
Rich Presence allows you to leverage the totally boring “Now Playing” section in a Discord user’s profile. This feature lets users show off when they are playing their favorite games on Citra. This has been a common feature request from many users, and since many other emulators have already implemented this, it made sense to implement it here as well.
Discord Rich Presence works by creating a local connection with Citra and your Discord App. It does not connect to (or) send any data to Discord servers. This option is user configurable, so you can choose to show or not to show rich presence in your discord status. Just head out to Emulation → Configure… → Web → Discord Presence and check / uncheck “Show current game in your Discord status”.
The majority of support requests we get are mostly due to users accidentally enabling or disabling some settings. But now with this feature, we have default values for all our settings. This ensures that in case of any new settings changes, majority of the users (who haven’t customized those settings) will now have the new default value automatically.
You can now directly use your encrypted game dumps in Citra, without having to
decrypt them. This requires that the user provide their keys via a text file
Currently all known encryption methods are implemented except for the Seed crypto. Seed crypto is used in newer eshop games, which essentially uses an additional title-unique key that is stored outside of the ROM.
Scripting is an extremely useful feature which allows us to do things like debugging emulator internals, reverse engineering 3DS game internals, Tool-Assisted-Speedrunning (TAS), and the ability to manipulate memory in games. A cheat-like interface could be implemented through this (though, not specifically Gameshark / AR codes).
Users can make their own scripts or use publicly available scripts to gain power over things like game screen display, inputs, and memory. Scripts can also be used to read or modify the internal game state. EverOddish wrote some scripts that can read internal stats of the Pokémon and automatically update image files for your current party. This feature is very useful for streamers who might want to display game information on their streams.
Movie - game input recording and playback (#2882, #3922) by danzel and zhaowenlan1779
This feature, not to be confused with video/audio recording, implements a way to record game inputs and play them back. Every time the hardware reads an input device (buttons, touch screen, accelerometer, gyroscope, c-stick) the emulator copies (when recording) or replaces (when playing) the values. Once playback has finished, we release control of inputs so that the user can take control.
For this, danzel heavily took inspiration from dolphin’s system and zhaowenlan1779
wrote the UI for this feature. This method results in
.ctm (Citra TAS movie)
files which are playble in Citra. To play a game’s
.ctm file you would need
to have the game and also manually set Citra’s system time to the same starting
value as in the
.ctm. This feature makes debugging bugs in games much easier,
as it doesn’t require us to go through the whole process again.
Whenever a game requested time information, Citra always used your PC’s system time. This method had a couple of issues - for example, if you were playing a game at 200% speed for 2 hours. As its running at twice the max speed, playing for 2 hours in real-time should reflect 4 hours simulated time. But, due to Citra sending your PC’s time to games, it wasn’t happening.
Also, players might want to set Citra’s time to a specific value to ensure consistency with TAS or with RNG(random number generator) or for getting time specific game events. Earlier you had to modify your PC’s system time to achieve this but thanks to B3N30, you can now just set it in Citra’s configuration window.
For a long time, Citra didn’t support controller hot plugging. This meant that if by chance your controller disconnected Citra would fail to detect it after re-connection, unless you restarted the emulator. This caused a lot of frustration among users who preferred playing with controllers.
Hot plugging (also called hot swapping) is the ability to add and remove devices to a computer system while the computer is running and have the operating system automatically recognize the change.
Thanks to the efforts of B3N30 and jroweboy (who researched SDL controller configuration), Citra now doesn’t fail to detect your controllers in case of a disconnection. However, due to heavy rework of the existing input configuration code, this requires users to reconfigure their controllers after updating Citra.
UDP client to provide motion & touch controls (#4049, #4059) by jroweboy and zhaowenlan1779
Citra’s previous motion controls were a bit uncomfortable to use. You had to use your mouse’s right-click and drag to tilt the screen, but it was often hard to figure out where to move the cursor to get the kind of tilt we want.
Using a real device for motion controls is simply much more intuitive and will be an all around better experience for users. As such, jroweboy set out to implement cemuhook motion/touch protocol which adds the ability for users to connect several different devices to citra to send direct motion and touch data to citra.
Cemuhook is a very popular plugin developed by rajkosto for Cemu - the Wii U emulator. This protocol was chosen simply because of the fact that there aren’t many alternatives and this already has good device support. Moreover, as it uses UDP, it works on just about anything with a network stack and allows the server to even be a remote network device (useful for Android motion support). zhaowenlan1779 wrote the UI for this feature, to make it easily accessible and configurable by all users.
Apart from the above mentioned ones, we have also had a lot of minor optimizations and bug fixes ported from yuzu. We’ve made changes to our authentication system to use JWT (JSON web tokens), added a background color selector, made GDB stub improvements, and many more.
Thank you to everyone for pouring your blood and sweat into this project. Citra needs contributors like you to stay alive and become the best it can be.