Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4de01d3ae6 | ||
|
9532db042f | ||
|
e5b2921ff3 | ||
|
72c4884faf | ||
|
f609315495 | ||
|
9d4f7205db |
2
.github/workflows/deploy.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
echo '========== Installing gulp & dependencies =========='
|
||||
sudo apt-get update && sudo apt-get install graphicsmagick
|
||||
sudo apt-get install graphicsmagick
|
||||
- name: Build
|
||||
env:
|
||||
TENANT: 'citra'
|
||||
|
@@ -49,7 +49,7 @@ function getRelease(v, count = 5) {
|
||||
|
||||
let env_icon = "/images/icons/file.png";
|
||||
if (is_windows) env_icon = "/images/icons/windows.png";
|
||||
else if (asset.name.includes("macos"))
|
||||
else if (asset.name.includes("osx"))
|
||||
env_icon = "/images/icons/apple.png";
|
||||
else if (asset.name.includes("linux"))
|
||||
env_icon = "/images/icons/linux.png";
|
||||
|
@@ -27,9 +27,9 @@ The Citra updater provides a easy interface to install, update and manage Citra.
|
||||
Unknown platform - Citra is <b>only supported</b> on 64-bit versions of Windows, macOS, Linux, and Android 8 (Oreo) or above.
|
||||
If you are running one of these, choose one of the options below.
|
||||
</div>
|
||||
<a href="https://github.com/citra-emu/citra-web/releases/download/2.0/citra-setup-windows.exe" class="btn btn-lg btn-primary dl-updater-button" id="dl-windows-x64">Download for Windows x64</a>
|
||||
<a href="https://github.com/citra-emu/citra-web/releases/download/2.0/citra-setup-mac.dmg" class="btn btn-lg btn-primary dl-updater-button" id="dl-mac-x64">Download for macOS Universal</a>
|
||||
<a href="https://github.com/citra-emu/citra-web/releases/download/2.0/citra-setup-linux" class="btn btn-lg btn-primary dl-updater-button" id="dl-linux-x64">Download for Linux x64</a>
|
||||
<a href="https://github.com/citra-emu/citra-web/releases/download/1.0/citra-setup-windows.exe" class="btn btn-lg btn-primary dl-updater-button" id="dl-windows-x64">Download for Windows x64</a>
|
||||
<a href="https://github.com/citra-emu/citra-web/releases/download/1.0/citra-setup-mac.dmg" class="btn btn-lg btn-primary dl-updater-button" id="dl-mac-x64">Download for Mac x64</a>
|
||||
<a href="https://flathub.org/apps/details/org.citra_emu.citra" class="btn btn-lg btn-primary dl-updater-button" id="dl-linux-x64">Download for Linux x64</a>
|
||||
<a href='https://play.google.com/store/apps/details?id=org.citra.citra_emu' class="dl-updater-button" id="dl-android-x64"><img style="width:275px" alt='Get it on Google Play' src='https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png'/></a>
|
||||
|
||||
<br />
|
||||
@@ -100,9 +100,9 @@ Hi! We see that you have JavaScript disabled. Unfortunately, this means that we
|
||||
prepare a updater for you, nor are we able to show you the latest archives of Citra either. Here are a few
|
||||
links to get you started however:<br />
|
||||
<br />
|
||||
<a href="https://github.com/citra-emu/citra-web/releases/download/2.0/citra-setup-windows.exe">Windows x64 Installer</a><br />
|
||||
<a href="https://github.com/citra-emu/citra-web/releases/download/2.0/citra-setup-mac.dmg">macOS Universal Installer</a><br />
|
||||
<a href="https://github.com/citra-emu/citra-web/releases/download/2.0/citra-setup-linux">Download for Linux x64</a><br />
|
||||
<a href="https://github.com/citra-emu/citra-web/releases/download/1.0/citra-setup-windows.exe">Windows x64 Installer</a><br />
|
||||
<a href="https://github.com/citra-emu/citra-web/releases/download/1.0/citra-setup-mac.dmg">Mac x64 Installer</a><br />
|
||||
<a href="https://flathub.org/apps/details/org.citra_emu.citra">Download for Linux x64</a><br />
|
||||
<a href="https://play.google.com/store/apps/details?id=org.citra.citra_emu">Download for Android</a><br />
|
||||
<a href="https://github.com/citra-emu/citra-nightly/releases">Nightly Builds</a><br />
|
||||
<a href="https://github.com/citra-emu/citra-canary/releases">Canary Builds</a> <br />
|
||||
|
@@ -138,11 +138,7 @@ Then, turn on the Use Custom Texture option in Graphics -> Enhancements and you
|
||||
|
||||
The following are previews of some awesome texture pack projects by the community. They aren't finished yet, but stay tuned! You can also check out the `#mods-and-texture-packs` channel on the Citra Discord server.
|
||||
|
||||
{{< single-title-imgs-compare
|
||||
"Left: Custom Textures, Right: Original"
|
||||
"./texturepack-post.png"
|
||||
"./normal-post.png"
|
||||
>}}
|
||||
{{< juxtapose id="ec2bf8ba-a025-11ea-a7cb-0edaf8f81e27" >}}
|
||||
|
||||
Click [here](https://cdn.knightlab.com/libs/juxtapose/latest/embed/index.html?uid=ec2bf8ba-a025-11ea-a7cb-0edaf8f81e27) to see a larger version of the above juxtapose.
|
||||
|
||||
@@ -157,11 +153,7 @@ Along with the change, Breadfish64 has brought in several high quality upscaling
|
||||
Seeing that some of these shaders don't work that well with Citra, he even wrote one himself, and [it works really great](https://www.youtube.com/watch?v=8epkdJ4OhQ0)!
|
||||
Try it out and see how it looks.
|
||||
|
||||
{{< single-title-imgs-compare
|
||||
"Left: unfiltered, Right: ScaleForce"
|
||||
"./unfiltered.png"
|
||||
"./levelup.png"
|
||||
>}}
|
||||
{{< juxtapose id="5435de18-8d65-11ea-a879-0edaf8f81e27" >}}
|
||||
|
||||
Click [here](https://cdn.knightlab.com/libs/juxtapose/latest/embed/index.html?uid=5435de18-8d65-11ea-a879-0edaf8f81e27) to see a larger version of the above juxtapose.
|
||||
|
||||
@@ -690,5 +682,3 @@ There are always many more ways to improve, and contributions are always welcome
|
||||
If you'd like to contribute, hop in our [Discord](https://citra-emu.org/discord) or IRC (freenode #citra-dev). If you can't contribute code, consider subscribing on [Patreon](https://patreon.com/citraemu)!
|
||||
|
||||
We are also looking for blog post writers! Reach out to us on [Discord](https://citra-emu.org/discord) if you are interested.
|
||||
|
||||
{{< imgs-compare-include-end >}}
|
||||
|
Before Width: | Height: | Size: 8.4 MiB |
Before Width: | Height: | Size: 2.3 MiB |
Before Width: | Height: | Size: 2.5 MiB |
Before Width: | Height: | Size: 5.9 MiB |
Before Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 164 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 167 KiB |
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 179 KiB |
Before Width: | Height: | Size: 699 KiB |
Before Width: | Height: | Size: 605 KiB |
Before Width: | Height: | Size: 560 KiB |
Before Width: | Height: | Size: 1.1 MiB |
@@ -1,320 +0,0 @@
|
||||
+++
|
||||
date = "2024-02-20T20:00:00+01:00"
|
||||
title = "Citra Progress Report 2023 H2"
|
||||
tags = [ "progress-report" ]
|
||||
author = "emufan_4568"
|
||||
coauthor = "PabloMK7"
|
||||
forum = 1013527
|
||||
+++
|
||||
|
||||
Welcome readers, and happy (belated) new year!
|
||||
We hope you all had a brilliant 2023, just as we did. The past year saw a boom in development across all areas of 3DS emulation for Citra, which we're super thrilled to share. From networking changes, to HOME Menu compatibility updates, to graphics enhancements, we've got it all!
|
||||
So strap in - and get ready for the very best of what we cooked up in the latter half of the last year.
|
||||
|
||||
# Contents
|
||||
1. [Emulation]({{< relref "#emulation" >}})
|
||||
1. [Networking]({{< relref "#networking" >}})
|
||||
1. [Amiibo]({{< relref "#amiibo" >}})
|
||||
1. [Graphics]({{< relref "#graphics" >}})
|
||||
1. [Audio]({{< relref "#audio" >}})
|
||||
1. [Conclusion]({{< relref "#conclusion" >}})
|
||||
|
||||
# Emulation
|
||||
|
||||
There has been a lot of progress as of late in achieving full system emulation. Just last year, HOME Menu emulation became a reality, unlocking a whole new world of applications that needed care and attention. The work never ends, does it?
|
||||
|
||||
Last time we mentioned that, while launching games from the HOME Menu worked, suspending or re-launching titles was generally hit-or-miss, with some titles crashing outright. This was because Citra was not cleaning up kernel objects correctly on process shutdown. Games, deservedly, expect a clean environment when they are launched and any operating system worth its salt is responsible for that. A process in HorizonOS, the operating system that runs on the Nintendo 3DS, is conceptually quite similar to the concept of a process in modern operating systems. It has its own address space, child threads, and is responsible for babysitting any kernel objects created by those threads.
|
||||
|
||||
Given that we are talking about this in a progress report, it’s safe to say that's a problem no more! [Steveice10](https://github.com/Steveice10/FBI) [turned](https://github.com/citra-emu/citra/pull/6680) a few nobs here and there and made sure that exiting a kernel process releases all the memory it owns and stops its child threads as well.
|
||||
|
||||
Steveice10 continued with the HOME Menu streak, implementing some additional service commands in the APT module and adding a power button to complete another crucial part of HOME Menu functionality: powering down the console. Whenever the HOME Menu is launched, pressing `V` on the keyboard will trigger the familiar screen.
|
||||
|
||||
{{< figure src="sleep.png"
|
||||
title="Same as pressing the power button on the 3DS!" >}}
|
||||
|
||||
While this might be the only user facing change of Steveice10's `APT` work, there's still more that was done. Symbol discoveries from Fire Emblem Fates gave Steveice10 the opportunity to rename a bunch of methods to match the official function names used by Nintendo. New 3DS capabilities were also hooked up to the kernel so that `APT` can more accurately report the capabilities of the emulated console variant.
|
||||
|
||||
Naming things is hard, especially when the thing you are naming isn't well understood. However, some retail games may contain, by accident, valuable debug information, including [symbolic](https://en.wikipedia.org/wiki/Debug_symbol) for services and the OS. These discoveries always help better clarify the service interface and can especially help when documenting unexplored areas. To nobody's surprise, the symbols from the same game also prompted developer [SachinVin](https://github.com/SachinVin) to adjust member variable names in the `DSP` service in a similar manner.
|
||||
|
||||
Speaking of the devil, uh- the DSP, Steveice10 stubbed binary requests `SaveState` and `LoadState` that are used by the AAC decoder to implement DSP sleep and wake behaviour accordingly. With this change, games like Pokémon X and Tales of the Abyss can now suspend to the HOME Menu without crashing, with the catch being that the game audio is lost as this isn't a full implementation. We have started taking steps to improve our audio emulation, something that will take time and a lot of effort, but we think will be worth it in the end.
|
||||
|
||||
{{< mp4 src="aac_suspend.mp4" title="No more crashing" >}}
|
||||
|
||||
Aside from tackling crashes, Steveice10 also improved the stability of the HOME Menu by adjusting various services to use correct session limits, stubbing numerous service calls used by the HOME Menu and fixing incorrect logic in the microphone service that was responsible for a random freeze that could happen in the HOME Menu, most easily reproduced by pausing emulation for a while and resuming.
|
||||
|
||||
A different problem that wasn't strictly a regression, but more of an annoyance, was centred around configuration blocks. During our efforts to make the HOME Menu functional, the list of configuration blocks was amended many times according to the needs of the HOME Menu and the effort to bring Citra up to date with the new configuration blocks noted on [3dbrew](https://www.3dbrew.org/wiki/Main_Page).
|
||||
|
||||
However, these changes required users to manually remove their config save file for the new Citra version to regenerate it appropriately. So, users upgrading from old Citra versions would still experience the same crashes all over again. To end this confusion, Steveice10 reworked the configuration block system to create missing blocks on the fly. Essentially, Citra will upgrade the config save for you automatically. Neat!
|
||||
|
||||
Finally, Steveice10 optimised the Y2R decoding process, which shaved about 0.1ms of decoding time on a modern desktop computer and worked around a bug that prevented Danball Senki Wars from booting. The game, possibly due to a bug in its own code, was calling a service function `Y2R_StartConversion` multiple times on the same data. Citra did not account for this and the function would work on invalid data the second time around. Yet more evidence that the creativity of game devs is truly endless, and this certainly will not be the last of such cases.
|
||||
|
||||
{{< figure src="danball.png"
|
||||
title="That looks like snow alright" >}}
|
||||
|
||||
# Networking
|
||||
|
||||
One cannot achieve full system emulation without looking at the network features of the 3DS.
|
||||
|
||||
On this beautiful console, network functionality is served by three system services. The first and most important one, named `SOC`, provides a raw socket interface pretty similar to the [POSIX standard](https://en.wikipedia.org/wiki/POSIX) - in which sockets are endpoints of communication between two applications over the network and are the foundation of the modern internet. The second one, named `SSL`, provides a layer of security over sockets. And finally, the last one, named `HTTPC`, allows games to perform HTTP requests without having to worry about implementing their own HTTP details.
|
||||
|
||||
As you may have noticed, there is a clear dependency between the three main network related system modules. `HTTPC` requires `SSL` to work, in order to be able to serve HTTPS requests, and `SSL` requires `SOC` to work, in order to make socket operations possible at all.
|
||||
***Side note: the chain of dependencies doesn’t end here, as `SOC` depends on yet another system module, `NWM`, which implements the Wi-Fi chip driver. However, this is not relevant for Citra, which doesn’t emulate the details of the Wi-Fi chip***
|
||||
Luckily for us, the deepest link in the chain, the `SOC` service, provides an interface pretty similar to the POSIX standard, which is supported natively by most operating systems. This makes fully implementing the `SOC` service easier… or so we thought…
|
||||
_(Windows, I’m totally not looking at you)_
|
||||
|
||||
While not covered in previous progress reports, the road into fully implementing the `SOC` service started back in Q3 2022 thanks to contributor [PabloMK7](https://github.com/PabloMK7). The first batch of fixes addressed differences in the flags passed to the poll function, among other things, which were causing Windows to return an error and making socket communications impossible. Thanks to this fix, the network functionality of many homebrew apps that used libcurl, and didn’t depend on the unimplemented `SSL` or `HTTPC` modules, started working!
|
||||
|
||||
{{< figure src="ctgp7.png"
|
||||
title="CTGP-7 is able to self update" >}}
|
||||
|
||||
Long-time Citra developer [FearlessTobi](https://github.com/FearlessTobi) also joined in on the network fun, this time setting his sights on the New 3DS browser (SKATER). A CRO (the 3DS equivalent of .dll files) adjustment by Steveice10 was all that it took to make the application boot, but it wouldn't be very functional without the ability to surf the web, would it?
|
||||
|
||||
In order to connect online, the browser talks to the `HTTPC` service, which is responsible for sending and receiving HTTP requests. While the internet browser doesn’t use the `HTTPC` module to make HTTP requests, it has its own HTTP and SSL stack, it still uses the service to apply other configurations. FearlessTobi implemented some missing service functions which, thankfully, made the browser happy and allowed it to load web pages successfully. Note that with this change, you still cannot watch video content on the browser as that requires the currently unimplemented [MVD service](https://www.3dbrew.org/wiki/MVD_Services).
|
||||
|
||||
{{< sidebyside "image" ""
|
||||
"skater1.png=Google on a 13 year old console? Sign me up!"
|
||||
"skater2.png=You can read this progress report... from Citra??">}}
|
||||
|
||||
As you can imagine, with the New 3DS browser fixed up, it was really a matter of time until the Old 3DS browser (SPIDER) got the same treatment. First time contributor and [Pretendo Network](https://pretendo.network/) developer [DaniElectra](https://github.com/DaniElectra) jumped in by fixing a small error in FearlessTobi’s contribution and stubbing `GetConnectingProxyEnable`, thus bringing its older sibling up to speed.
|
||||
|
||||
Now, coming back to online multiplayer, PabloMK7 was facing a small issue with some newer games that had updated network libraries. One of those games was Animal Crossing: New Leaf. While it was possible for a person on Citra to visit a town hosted by a 3DS (as shown in the following post), it was only possible for a person on a 3DS to visit a town hosted by Citra if both devices were inside the same network.
|
||||
|
||||
{{< figure src="resetti.png"
|
||||
title="Mr. Resetti, I’d appreciate it if you were more descriptive..." >}}
|
||||
|
||||
After several weeks of research, dumping network traffic, and getting assistance from developer m4xw, the issue was tracked down to a missing implementation detail in the SOC module. It turned out the game was setting the packet TTL (time to live) value to 0. This value tells routers in the network how many more “jumps” a packet can do before being dropped, and in most operating systems, setting the TTL to 0 simply disables it from jumping to more than one router (hence why the issue didn’t happen if both devices were on the same network) However, on the 3DS, the value of 0 has a special meaning: “set the TTL to the default value: 64”. After this detail was fixed, the game started working perfectly online.
|
||||
|
||||
At the same time, PabloMK7 discovered a major inaccuracy in the `SOC` service. But to describe it, we have to talk a bit more about sockets. Sockets have two ways of operation: blocking and non-blocking. Those modes tell the operating system how the socket should behave when a read operation is performed, but with no data available. In blocking mode, the program execution is paused until data is received, at which point execution is resumed automatically. In non-blocking mode, the read function immediately returns with an error indicating that no data was received and that the operation would block (EWOULDBLOCK).
|
||||
|
||||
It was noticed that the way sockets were handled changed over time. In older games, the code was constantly checking for incoming data using a combination of poll and non-blocking sockets, but in newer games, it spawned a new thread that would simply try to receive data on a blocking socket. If there was no data available, this would cause this new thread to block, but it didn’t matter as the rest of the game threads can move on and do other things in the meantime (such as sending data through the socket). Once the blocking socket receives some data, the network thread is unblocked and the data is processed according to the game’s needs.
|
||||
|
||||
However, this pattern presents a problem in Citra: we don’t have real multithread support! Instead of having an emulation thread per game thread, a single emulation thread is used that periodically switches execution between the game threads, emulating the thread scheduler of the 3DS. This approach has many benefits. It ensures the emulator maintains high timing accuracy with minimal desync, while also making execution deterministic. That means that when launching any particular application, one can expect the emulator to behave the exact same way, timing-wise, on each run, instead of relying on scheduler details of the host operating system. However, this design choice has a weakness: if a game thread performs a blocking operation, it will also block the emulation thread, hanging the entire emulator.
|
||||
|
||||
Solving this issue in Citra requires tapping into making Citra multithreaded, to run each game thread in a dedicated host thread to mimic the way hardware works. However, the benefits of this approach aren't clear aside from this particular weakness,implementing it requires an almost complete kernel rewrite to make it multithread ready and would sacrifice a lot of emulation accuracy.
|
||||
|
||||
Faced with this conundrum, PabloMK7 needed to find a way to offload the socket operations from the main emulation thread without intrusive changes to the existing kernel and service code. His answer was adding a new function, RunAsync, that can execute any blocking code in a separate host thread while putting the requester game thread to sleep. This allows the emulated scheduler to select a new game thread to run so that the game can continue doing work. Eventually, when the blocking code finishes, the game thread is resumed and the received socket data is finally processed, ensuring the service can work correctly when used in such a manner.
|
||||
|
||||
Another applet that received its well-deserved spa treatment is the Friend List applet. While it has been possible to boot it for quite some time by enabling the `LLE FRD` service module, the HLE implementation was simply lacking too much to boot it. To shrink the gap between implementations, FearlessTobi stubbed several `FRD` functions to prevent it from crashing. However we still recommend using the LLE service whenever `FRD` is required until further improvements to the HLE implementation are made.
|
||||
|
||||
{{< figure src="frd.png"
|
||||
title="Time to go out and make new friends!" >}}
|
||||
|
||||
PabloMK7 later amended FearlessTobi's previous `HTTPC` work by implementing another large chunk of the HLE service. This entails that many more online applications are able to function correctly. For example, the homebrew file manager [FBI](https://github.com/Steveice10/FBI) (not the one you may be thinking of), can now install remote applications, the Pokémon Sun and Moon demo can communicate with the legality check server, the Internet Browser can check its own version, and more!
|
||||
|
||||
# Amiibo
|
||||
|
||||
That's right! We've got not one, but two guest celebrity appearances in this article! You might know [german77](https://github.com/german77) from his work on the Switch HID service and, of course, amiibo for the [yuzu emulator](https://yuzu-emu.org/).
|
||||
|
||||
With that in mind, it was a pleasant surprise when he offered to port the yuzu amiibo implementation to Citra. After all, amiibo is a common interface and it's well known that the Switch service is quite similar to its 3DS counterpart. So after spending a bit of time reverse engineering the 3DS service, combined with his existing knowledge, the first time contributor added [amiibo encryption and appdata](https://github.com/citra-emu/citra/pull/6340) that promised to fix all games that had issues with amiibos, an enticing proposition indeed. The new service was also tested against hardware to ensure all was well and good.
|
||||
|
||||
{{< figure src="amiibo_test.png"
|
||||
title="Can't escape hardware testing in emulator development" >}}
|
||||
|
||||
After the PR was merged, german77 [updated](https://github.com/citra-emu/citra/pull/6672) the service to use the official names from Nintendo using the symbol discoveries we talked about earlier.
|
||||
|
||||
It's now time to bring in the problem child of the story: **Chibi-Robo! Zip Lash**. A game of [questionable](https://www.youtube.com/watch?v=Pi6LM1EASMg) quality, it proved to be quite the stress test for the new amiibo implementation. A user [first reported](https://github.com/citra-emu/citra/issues/6667) that the game attempted to read the amiibo immediately, not giving them any time to load their dump. german77 [promptly addressed](https://github.com/citra-emu/citra/pull/6671) the issue by automatically starting adapter communication when games scan for amiibo. But, sadly, this wasn't enough. The next day the same user [mentioned](https://github.com/citra-emu/citra/issues/6681) that while an amiibo could be selected, after a very short time, the game would give an error message.
|
||||
|
||||
german77 investigated that issue as well and found that Chibi-Robo! Zip Lash has a built-in delay after mounting the amiibo tag to ensure the tag is ready to pull data from. The existing implementation removed the tag too soon, so the game didn't get the chance to read any data from it. For this problem, [german77 made](https://github.com/citra-emu/citra/pull/6687) it so that the time counter would be reset, given that the tag is constantly being used. This means it would not be removed while the game is actively using it. While at it, he also [fixed](https://github.com/citra-emu/citra/pull/6868) a few small errors in the service and increased the amiibo detection timeout, which fixed loading amiibo's on Hey! Pikmin.
|
||||
|
||||
While the original PR by german77 required dumping the amiibo secrets separately to a `key_retail.bin` file to support encrypted Amiibo, this is no longer the case. Thanks to his future-proof GodMode9 key dumping script, Steveice10 removed that limitation by using the [existing secrets infrastructure for amiibo encryption](https://github.com/citra-emu/citra/pull/6652). This means that if you followed our new [AES key dumping guide](https://citra-emu.org/wiki/aes-keys/) to setup the HOME Menu, you are also ready to use your amiibo without any additional setup!
|
||||
|
||||
With the more accurate NFC service implementation, Steveice10 also set his sights on emulating the amiibo settings applet, which is used for first time amiibo registration. To do this, he [implemented](https://github.com/citra-emu/citra/pull/6821) saving the current framebuffers to specific VRAM locations in the `SaveVramSysArea` service function of the `GSP` module and updated the `APT` framebuffer capture for system applets to use these VRAM locations for capturing.
|
||||
|
||||
{{< mp4 src="amiibo.mp4" title="Registering an Amiibo, simple stuff" >}}
|
||||
|
||||
# Graphics
|
||||
### *or the number of ways PICA200 can shoot you in the foot*
|
||||
|
||||
|
||||
Amidst all the shiny new OpenGL features and Vulkan performance improvements, the software renderer tends to get overlooked and only used for brief testing on systems without a dedicated GPU to do all the heavy lifting. Even then, this use case is not quite as relevant these days as Citra can now be used with lavapipe, a mature software rasterizer for the Vulkan API.
|
||||
|
||||
Our software renderer has been crucial to the past and future development of Citra and, thus, a worthwhile piece of code to maintain and evolve. Originally crafted by the now [Mikage](https://mikage.app/) developer [neobrain](https://github.com/neobrain/), it has served as a measure of accuracy for the hardware renderers to match, with lots of GPU features such as shadow mapping first having been tested on it before trickling down to the hardware renders.
|
||||
|
||||
However, most of the its structure had remained the same over the years and differed from the hardware renderers in style. It relied on global state, which made it difficult to eliminate that from other parts of the `video_core` project, and had different namespace naming conventions compared to the hardware renderers. With these points in mind, [GPUCode](https://github.com/GPUCode) set out to refactor the software renderer to bring its code closer to the standards of the rest of the codebase nowadays. For the end user not much will change, but the code is tidier, cleaner, and more easily maintainable. Always a plus! Not only that, a performance bottleneck relating to memory access was discovered during this effort, and patched, resulting in a noticeable performance boost when using the software renderer!
|
||||
|
||||
Speaking of performance improvements, GPUCode contributed another change to the software renderer that was strictly aimed to improve performance. By processing scanlines in parallel, using multiple threads, performance has almost been doubled in most cases! Of course, that still doesn't make it full speed, since we are talking about a difference of 1 FPS and 2 FPS, but making better use of the system's resources will prove beneficial for future endeavours.
|
||||
|
||||
As for said future, only one word suffices. **“Full speed software rendering!”**. Well... that was four words. But you get the gist! Having a software renderer fast enough to perform at full speed will make testing with it immensely easier and is a challenge in optimization we are willing to take on.
|
||||
|
||||
Continuing on the trend of *topics-the-average-user-won't-really-care-but-are-interesting-regardless*, the shader interpreter also got some love this time around. Fun fact, up until recently it was used as a fallback for Android devices when using geometry shaders, or for draw calls that failed to get hardware accelerated *for whatever reason*. However, as you’ll find out later in the article, we prepared something special for all you Android users in this regard.
|
||||
|
||||
The first change was implementing a bunch of control flow edge cases and missing instructions, like `break` and `breakc`. The aforementioned instructions have actually been in the shader JIT for years, and are used in shaders from games like Steel Diver: Sub Wars and Gunman Clive. There are cases where the shader JIT fails, and using the Interpreter as a means of debugging can be greatly beneficial. Case in point, the aforementioned Steel Diver: Sub Wars.
|
||||
|
||||
{{< figure src="steel.png"
|
||||
title="I wouldn't want to be in that vessel if I were you" >}}
|
||||
|
||||
The game suffers from quite a peculiar case of freezing syndrome when a torpedo hits another submarine, with the added benefit that it consumes all the user's RAM before crashing. Great... GPUCode found that the game utilises geometry shaders for this collision animation and that the JIT was failing quite spectacularly in trying to execute them. Switching to the interpreter didn't fare much better, being greeted with multiple warnings about the unimplemented instructions. Taking the time to bring the interpreter up to date ensures the game is now playable with the slower backend. More debugging awaits.
|
||||
|
||||
On that same topic, let's talk about something new. While testing Super Mario 3D Land on macOS, Steveice10 encountered a crash when entering the demo level. The crash would only manifest with hardware shaders disabled which meant that, being an arm64 system, the shader backend in use was the interpreter. After some fiddling around, Steveice10 concluded the game was accessing out of bounds uniforms, which the interpreter had no checks or protections against. It also wasn't the only game that tricked Citra like that either. So an interesting question was raised: what happens when games perform these seemingly invalid reads?
|
||||
|
||||
There is only one source of truth for these questions, the console itself. And that's exactly where Steveice10 started looking. After running a bunch of hardware tests with various configurations and parameters, he managed to replicate the exact way the hardware behaves, improving the accuracy of the interpreter and fixing the crashes in the process. The improvements have also been ported to the GLSL backend and x86 shader JIT so everyone can be happy!
|
||||
With the above out of the way, it’s finally time to get into the more fancy graphical fixes.
|
||||
|
||||
## Chapter 1 - or... How colour theory is actually tricky
|
||||
|
||||
Go! Go! Kokopolo - Harmonious Forest Revenge is a 3DS port of a DSiWare title available exclusively as a 3DS North American physical release. The physical release happened last year on September 16th 2022, cementing it as part of the dying breath of the 3DS ecosystem. Normally games released this late into a console’s lifespan tend to be quick cash grabs made with existing engines like Unity, which do work well on Citra. However this case was different, as the game exhibited peculiar discolouration in its tiled graphics that made it quite disorienting to play.
|
||||
|
||||
The problem was also exclusive to the hardware renderers, with the software renderer having correct output, albeit at unplayable frame rates. This fact made GPUCode confident that it wouldn’t be hard to track down the issue by figuring out which part of the rendering pipeline was causing the divergent pixel values. And this hypothesis was indeed correct! The issue was quickly found to be from the lighting LUT sampling helpers, where the coordinate to sample from was just a few pixels off compared to the software implementation. These LUTs are simple buffers used by the fixed function lighting unit for its various operation, yet it appears the game is ~~ab~~using them as a sort of colour palette. This means that even the tiniest differences in sampling can cause incorrect colours to be used. Adjusting the hardware renderers to match the software behaviour was enough to correct all the rendering problems in this game and others, such as 3D Fantasy Zone II.
|
||||
|
||||
{{< single-title-imgs-compare
|
||||
"Left: Before, Right: After"
|
||||
"./gogo1.png"
|
||||
"./gogo2.png"
|
||||
>}}
|
||||
|
||||
{{< single-title-imgs-compare
|
||||
"Left: Before, Right: After"
|
||||
"./fantasy1.png"
|
||||
"./fantasy2.png"
|
||||
>}}
|
||||
|
||||
We mentioned before how useful having a software renderer can be for fixing graphical bugs and we hope the previous case shed some light into the why. But just in case, let’s go over another related bugfix.
|
||||
|
||||
After refactoring the software renderer, GPUCode experienced every developer’s worst fear… a regression!! The game in question was Kirby’s Blowout Blast, where the sky lost its proper colour and became grey instead of blue. The hardware renderers have had this problem for years, but the software renderer was unaffected up until this change. Treating this as an opportunity to also tackle the hardware renderer problems, GPUCode sifted through the pull request changes to pinpoint what went wrong. And the problem was… an uninitialized variable? You heard that right, zero-initialising a vector variable (combiner_output) broke the game.
|
||||
|
||||
{{< figure src="bad_code.png"
|
||||
title="You ruined everything!" >}}
|
||||
|
||||
To explain how this is possible, we need a quick introduction to TEV, the system the 3DS uses to render graphics on the screen - even with the lack of pixel shaders. The **T**exture **E**n**V**ironment consists of 6 stages of colour and alpha combining. Colour combiners take three input colour values from some source (e.g. interpolated vertex colour, texture colour, previous stage, etc), perform some very simple operations on each of them (e.g inversion) and then calculate the output colour by combining them with some basic arithmetic (e.g addition, multiplication, lerping). Alpha combiners can be configured separately but work in the same manner.
|
||||
|
||||
The important bit here is that any TEV stage can use the output of the previous stage as its input. Kirby's Blowout Blast was multiplying the sky colour with the previous stage result to figure out the final colour… in the first stage. How do you get the previous stage colour, when there is no previous stage?!
|
||||
|
||||
By leaving the vector that holds the output of the current TEV stage uninitialized, holding a possibly non-zero undetermined value, it was accidentally preserving the blue sky colour, while the hardware renderers were initialising this value to zero. After doing a few hardware tests and being pointed to relevant documentation by Steveice10, GPUCode determined that using the previous stage as input in the first stage is a special case and results in the vertex colour being given. Implementing this simple observation fixed the sky problems in Kirby's Blowout Blast, solved certain maps where the ground was not rendered in Fire Emblem Awakening and, surprisingly, brought back the missing eyebrows in Puyo Puyo Chronicle.
|
||||
|
||||
{{< single-title-imgs-compare
|
||||
"I wish I got a gold medal here as well"
|
||||
"./kirby1.png"
|
||||
"./kirby2.png"
|
||||
>}}
|
||||
|
||||
{{< single-title-imgs-compare
|
||||
"Left: Before, Right: After"
|
||||
"./brow1.png"
|
||||
"./brow2.png"
|
||||
>}}
|
||||
|
||||
## Chapter 2 - The nightmares of precision
|
||||
|
||||
Missing graphics can be caused by a variety of reasons, not all of which are related to the fragment stage. Precision related bugs are the bane of emulation, especially when the guest system has lower precision than the host. Case in point, the PICA is a wonderful blend of non-standard floating point types. You get 24-bit floats for most rendering operations, 20-bit floats, 16-bit floats, even a bunch of fixed point formats for miscellaneous registers. It would be strange for Citra not to exhibit at least some precision related glitches. An example is in Rune Factory 4, where lakes in dungeons will refuse to render on Citra due to depth precision differences between the host GPU and console.
|
||||
|
||||
{{< figure src="rune.png"
|
||||
title="Using small workarounds, rendering can be fixed, but it's not a proper solution nor can it be integrated into upstream yet" >}}
|
||||
|
||||
While this specific issue is for future us to solve, there are other cases we can talk about. Picross 3D Round 2 was notorious for having missing pictures in puzzles which made it cumbersome to select levels to play. In Rabbids: Travel in Time 3D, the top screen was cut in half during the intro cinematic. The Riki Densetsu series of games also exhibited a similar problem, but with the character sprites that were cut in half when facing a specific direction. All these problems had one thing in common. And that... was clip planes. That information was known even before GPUCode decided to look into the issue, as people quickly found that most of these games were regressed by the original PR from [wwylele](https://github.com/wwylele) that implemented user defined PICA clip planes.
|
||||
|
||||
What is happening here is that the missing 2D elements are being rendered with a z value extremely close to clip plane 0 and, thus, getting erroneously clipped by the host GPU. The 3DS GPU does not have the required precision to express these tiny depth values and they are likely rounded to zero as a result, avoiding the clipping problems.
|
||||
|
||||
{{< sidebyside "image" ""
|
||||
"picross1.png=Am I supposed to play blindfolded?"
|
||||
"fight1.png=To whom am I referring to, really?">}}
|
||||
|
||||
The only entirely correct solution to this problem would be to emulate the target floating point number in software, which is the only way to perfectly match the console results. However, in practice, this is extremely impractical. Not only would the code become much more complex, but also much slower to boot. So GPUCode picked the next best option: defining a small epsilon value around clip plane zero to flush these depth values to zero, thereby avoiding the clipping. The epsilon value was selected based on the affected games and hardware experimentation.
|
||||
|
||||
As a side note, if you’ve used Citra before you’ve likely come across the `Accurate Multiplication` setting in the `Emulation` > `Graphics` > `Advanced` tab. If you thought that setting may be related, you are correct. The general recommendation for that is to leave it disabled unless a specific game requires it. As the helpful tooltip will also tell you, the setting exists because of differences in behaviour of floating point multiplication between your computer and the 3DS. Differences that are *very* expensive to account for.
|
||||
|
||||
## Chapter... hey, what is blending doing here?
|
||||
|
||||
That's quite the interesting one... Blending is a term you’ve probably heard before, that refers to a commonly used technique to achieve transparency between objects. The idea is simple: take the colour of the existing background and the colour of the object being rendered, combine them with a simple arithmetic operation and write the final result to the framebuffer. This is fast and works wonders, assuming the rendered geometry has been sorted based on view distance from the camera. That might also be why blending is one of the last remaining fixed function components of fragment processing in modern GPUs. Though things do get messy when the hardware you are emulating has different blending behaviour compared to the host, as one has little control over fixed-function hardware.
|
||||
|
||||
This whole discussion about blending started due to an old issue Pokémon Mystery Dungeon: Gates to Infinity had, where staircases weren’t turning transparent when Pokémon were interacting with them. Citra developer [Subv](https://github.com/Subv) first looked into the issue and found it was caused by an inaccurate MIN/MAX blending mode handling. The 3DS will multiply the colours with constants, called blend factors, before comparing them, which is something that desktop GPUs will not do. Achieving this behaviour with OpenGL at the time was deemed extremely hard and the case was left unclosed.
|
||||
|
||||
6 years later, GPUCode revisited the issue and attempted to solve it using modern tools and available extensions. For NVIDIA and AMD users, there are dedicated OpenGL extensions that allow us to change this blending behaviour, namely `GL_NV_blend_minmax_factor` and `GL_AMD_blend_minmax_factor`. Enabling these extensions is by far the easiest way to achieve the desired behaviour, however the obvious downside is that these have no support outside of their respective vendors (and outside of Windows in AMDs case), which means they will not suffice for everyone.
|
||||
|
||||
{{< single-title-imgs-compare
|
||||
"Left: Before, Right: After"
|
||||
"./pokemon1.png"
|
||||
"./pokemon2.png"
|
||||
>}}
|
||||
|
||||
The main challenge with emulating blending is accessing the existing framebuffer colour to perform the necessary calculations with the incoming fragment colour. For Android, this is rather easy. However, where framebuffer fetches extensions for programmable blending are ubiquitous and cost very little due to the tiled architecture of mobile GPUs. For them, Citra will detect when emulation is necessary, disable the host blending, and perform the blending operations in the fragment shader with these extensions.
|
||||
|
||||
What about the rest of the desktop ecosystem, though? Luckily for us, Intel iGPUs support the framebuffer fetch extension, which means the system we developed for Android can effectively be reused for them as well. Reusing code is always neat-o. Lastly, for Linux users running the open source RADV driver, we can use a similar approach but instead of simply fetching the framebuffer contents from the shader, we have to attach the framebuffer as a texture and rely on `ARB_texture_barrier` to get defined behaviour. We hope all these methods combined will cover all platforms Citra can be used for so that everyone, regardless of their environment, can experience accurate rendering.
|
||||
|
||||
The results speak for themselves, Pokémon Mystery Dungeon: Gates to Infinity now renders correctly, and, surprisingly, the Shin Megami Tensei games also had their transparency during battles fixed. This is definitely a pleasant surprise, as these games are very popular and the community has been asking for a fix for a long time now. So we're happy that this endeavour coincidentally fixed this issue as well! For now, this change remains OpenGL only, with plans to also implement it for Vulkan in the future.
|
||||
|
||||
{{< single-title-imgs-compare
|
||||
"Battle in style!"
|
||||
"./shin1.png"
|
||||
"./shin2.png"
|
||||
>}}
|
||||
|
||||
Not stopping there, GPUCode delivered another graphical fix. This time for Weapon Shop de Omasse, where the intro cinematic would not display properly. Turns out, the game does not properly initialise the register used for forming the output vertex from shader registers. Turning to hardware testing, GPUCode found the default that Citra used in this case was incorrect and changing it to match the testing results fixed the rendering issues.
|
||||
|
||||
{{< figure src="shop.png"
|
||||
title="The one time seeing a Level 5 intro made me happy" >}}
|
||||
|
||||
You want more? Really? Sure then, let’s travel to the magical realm of texture caching and check out some improvements or ahem..
|
||||
|
||||
## Chapter 3 - The final boss was the texture cache all along
|
||||
|
||||
In the previous progress report, we already went into great detail about the numerous texture cache refactors that enabled exciting features, such as adding a new graphics backend. However there were yet more problems to fix as we later found. Firstly, GPUCode fixed a long-standing regression dating way back to the summer of 2022, where unaligned texture downloads would not be handled correctly. This mainly affected Metroid Prime: Federation Force, but could also affect any other game that performed unaligned texture downloads. Interestingly the game went through multiple stages of breakage, with the screen first being shifted to the right, and then shifted a little bit down, before being fixed entirely in the end. Unfortunately, it’s still as slow as molasses because the texture cache cannot accelerate display transfers from fill surfaces. When that is addressed, we expect the game to run flawlessly.
|
||||
|
||||
{{< sidebyside "image" ""
|
||||
"metroid1.png=A little bit to the left..."
|
||||
"metroid2.png=A little bit to the top...">}}
|
||||
|
||||
Secondly, and the last graphical fix we will take a look at today (we do need to leave some for the next progress report, after all), GPUCode fixed another long standing set of graphical corruptions that plagued both Pac-Man Party 3D and Tales of the Abyss. The latter seems to be a divisive remake for people, with many comparing the PS2 and 3DS versions extensively. Not like you could play either game on Citra anyway, as both screens would either be black with the hardware renderers or very misaligned in the case of the software renderer.
|
||||
It was obvious the bug would be anything but simple to track down. However a familiar name, Subv, first looked into these games and provided a nice starting point: both games perform strange address calculations in their display transfer routines. Armed with that information, GPUCode opened Tales of Abyss in a decompiler and set out to discover what exactly the games were doing. And, with a little effort, the offending code was found. It was triggered only when the games were using specific display transfer parameters. Pac-Man Party 3D and Tales of the Abyss both made use of those.
|
||||
|
||||
{{< figure src="pacman1.png"
|
||||
title="Honey, spacetime is warping again" >}}
|
||||
|
||||
But the question was, "why?". These two games are the only ones reported to exhibit this misalignment. Were they trying to workaround hardware quirks when doing transfers with the specific parameters? As you know by now, these questions can only be answered by testing, *testing*, and even more testing. Luckily for us, this hypothesis proved to be correct, as the console results did not match what Citra was doing. The solution was also surprisingly straightforward: take the output address and transform it the opposite way the game does when using the same display transfer parameters. This not only fixed rendering but also emulated the broken rendering that the hardware exhibits. Fun fact, the weirdness doesn't end for the case of the Tales of the Abyss. The game also triggered a bunch of edge cases in Citra's geometry shader implementation that made it crash in the first battle. At the time of writing these edge cases have already been hardware tested and implemented, which makes the game fully playable. We'll talk about those next time around, though.
|
||||
|
||||
{{< sidebyside "image" ""
|
||||
"pacman2.png=Can I have a cookie too please?"
|
||||
"tales_goofy.png=I bet he's excited to relive the adventure on Citra">}}
|
||||
|
||||
## End of story, shader lessons learned
|
||||
|
||||
While this marks the end of the graphical fixes, there are still more graphical additions to cover. With the inclusion of Apple Silicon support this year, a feat that required changes to almost every part of the codebase, Citra has expanded its arm64 support greatly. As part of that effort, regular contributor [Wunkolo](https://github.com/Wunkolo) stepped up to make a whole new shader JIT backend targeting the ARM architecture. Both [merryhime](https://github.com/merryhime) and [JosJuice](https://github.com/JosJuice) chimed in and provided valuable feedback, so a big thanks goes out to them as well. The new backend will be enabled by default on arm64 platforms, resulting in about double the performance on most games with hardware shaders disabled.
|
||||
|
||||
{{< single-title-imgs-compare
|
||||
"The difference is real"
|
||||
"./mario1.jpg"
|
||||
"./mario2.jpg"
|
||||
>}}
|
||||
|
||||
The benefit of improving shader JIT performance might not be immediately obvious, when hardware shaders exist and have great performance on the vast majority of devices. However, there are rare situations where hardware shaders cannot be used, causing the emulator to fallback to the software implementation as a means of maintaining accuracy. One such case is geometry shaders, which are very difficult to emulate on the host GPU due to 3DS hardware quirks. Games that make heavy use of these shaders will see a noticeable performance boost with this addition. As an example, the Monster Hunter games use geometry shaders to render the grass, leading to the slow shader interpreter having to handle all those draw calls, causing a significant slowdown. Now, these areas run at full speed with no issues!
|
||||
|
||||
{{< figure src="hunter_grass.png"
|
||||
title="Perfect place for hide and seek" >}}
|
||||
|
||||
Wunkolo not only added a brand new shader backend, but also improved the existing x86 JIT by implementing additional optimizations using Intel AVX and AVX512 instruction sets. Processors that support these instruction sets will see a small, but noticeable, performance uplift.
|
||||
|
||||
They say history repeats itself... and our shader problems sure do so as well. It was well known for a while that Citra generated an excessive amount of shaders for many games. Even repetitive actions like opening a door in Luigi's Mansion Dark Moon would generate new shaders and cause stutter. The Vulkan backend helped to alleviate most of the stuttering with a clever combination of parallel shader compilation and driver queries, but the shader generation still occurred. For many mobile devices specifically, the shader cache would grow too large, causing the device to run out of memory and crash. That's a big no-no for sure.
|
||||
|
||||
{{< figure src="many_shaders.png"
|
||||
title="How many thousands is that again?" >}}
|
||||
|
||||
It's hard to believe any game would intentionally require that many shaders. Most likely there was some shader duplication going on that made Citra do unnecessary work. What we couldn't envision was in how many areas this duplication was manifesting.
|
||||
|
||||
Contributor [m4wx](https://github.com/m4xw) first [noticed](https://github.com/citra-emu/citra/pull/6895) something peculiar: Citra would always take into consideration the PICA lighting state when generating fragment shaders, even when lighting was disabled completely. Changing lighting parameters shouldn't matter much when the feature is disabled, yet Citra would generate new shaders each time. By masking out parameters when their respective feature is disabled, the amount of generated shaders has been greatly reduced, without any behavioural changes.
|
||||
|
||||
Based on this observation by m4wx, GPUCode expanded upon it, by masking out even more unnecessary parameters, this time in the TEV shader generation. This mainly affected the title screen of The Legend of Zelda: A Link Between Worlds, which generated dozens of duplicate shaders. With that change the number of shaders being compiled was halved once more. The final change regarding shader compilation was done on the OpenGL backend. As a remnant of old OpenGL versions, Citra would specify the uniform interface for every compiled shader, even though that never practically changed. This interface describes what data the fragment shader receives from the vertex shader and what data from the CPU. Utilising `ARB_explicit_uniform_location` afforded by the OpenGL version upgrade to 4.3, Citra no longer has to do this, further reducing the amount of work done per shader.
|
||||
|
||||
# Audio
|
||||
|
||||
Developer SachinVin [refactored](https://github.com/citra-emu/citra/pull/7026) DSP interrupt handling, which makes the implementation easier to use and unit test.
|
||||
|
||||
Steveice10 also landed a bunch of audio improvements, one of which specifically benefits Android users. Since Android phones often vary in performance, Citra employs a dynamic approach to audio stretching on said platform, where it is automatically enabled or disabled depending on whether the game is running at full speed or not. This ensures that no jarring audio cut-offs occur during gameplay. However, many users noted that audio stretching noticeably lowered the final audio quality and would exhibit strange speedups and slowdowns at random times.
|
||||
|
||||
To make a long story short, when the time stretcher is turned off, audio samples would be flushed from it into the output before proceeding with regular audio. If the amount of audio in the stretcher was too large for the output buffer, Citra would leave sample data behind in the stretcher. Then, when the stretcher is enabled again, the leftover audio from the past would be played, leading to a desync in audio playback. To solve this, Steveice10 ensured that the time stretcher [clears the remaining data](https://github.com/citra-emu/citra/pull/7081) after flushing to the output as much as possible.
|
||||
|
||||
A significant rework was also done to the AAC decoder infrastructure by the same developer. Because the AAC codec used by 3DS games was patented, Citra could not bundle a library to decode it. Rather, it needed to rely on the host operating system facilities, which can vary widely on quality and features. For example, the Windows WMF AAC decoder is riddled with bugs from having too [low volume](https://www.djuced.com/kb/my-m4a-and-aac-files-volume-are-too-low-on-windows-11-update-22h2/), producing [incorrect audio waveforms](https://forum.blackmagicdesign.com/viewtopic.php?f=21&t=169250#p897900) and, more relevant for us, [causing audio desync](https://github.com/citra-emu/citra/issues/5932) in rhythm games such as Rhythm Heaven Megamix.
|
||||
|
||||
As it turns out though, the patent for AAC-LC, the codec used by the 3DS specifically, has been considered expired for many years. Other groups like [Fedora's legal team](https://bugzilla.redhat.com/show_bug.cgi?id=1501522#c112) and [Flatpak maintainers](https://gitlab.com/freedesktop-sdk/freedesktop-sdk/-/merge_requests/293#note_87343708) have also concluded that the patents for AAC-LC have expired and can be considered free for use. With this information, Steveice10 stripped out the various AAC decoder implementations and replaced them with one universal bundled decoder, trimmed down to include only the relevant codec. This makes Citra's support of AAC no longer require on specific external dependencies, like in the case of Linux. It also makes it consistent across different platforms instead of having varying latency and quality depending on the supported backend. Further work on improving AAC support can be performed on this one backend for all platforms as needed.
|
||||
|
||||
{{< mp4 src="moosic.mp4" title="The beat is addicting... your writer needs a little practise though" >}}
|
||||
|
||||
That said, our HLE audio emulation is not perfect. For example, Virtual Console games have [distorted](https://github.com/citra-emu/citra/issues/2552) or no audio at all, some other games have [missing](https://github.com/citra-emu/citra/issues/5663) audio as well. To combat this, we have begun efforts to improve the performance of our LLE audio backend so it can serve as a viable alternative for those problematic cases. Developer SachinVin has started work on a Ghidra [plugin](https://github.com/SachinVin/TeakLite-SLEIGH) for the Teak architecture, which is used by the 3DS DSP. This will allow us to more easily understand the inner workings of the firmware used to drive the DSP. With the aid of this tool, GPUCode wrote a prototype JIT compiler for the DSP. Early tests have shown an impressive 2x performance boost over the reference interpreter. We will probably have more to say on the matter in a few months time.
|
||||
|
||||
# Conclusion
|
||||
|
||||
Anddd finally, we're done. Another year, another amazing set of changes that brings us ever closer to fully capturing the experience of using this wonderful handheld console. Development has been progressing at lightning speeds this past year and into 2024, which we are very proud of and gives us more interesting content to talk about in progress reports. Same as before, big props to the Citra community, the developers, and all the people that keep the project alive and well!
|
||||
|
||||
If you want to support this project, we have a [Patreon](https://www.patreon.com/citraemu)! Donations to the Patreon go directly to our team to assist with obtaining hardware for testing and keeping our servers up and running. Donations are not required, but are greatly appreciated!
|
||||
|
||||
If you are looking to contribute to Citra or just want to get involved with our community, you can find us on our [Discord server](https://discord.com/invite/FAXfZV9) or on our IRC channel (#citra @ [Libera.Chat](https://libera.chat/)).
|
||||
|
||||
{{< imgs-compare-include-end >}}
|
Before Width: | Height: | Size: 1.4 MiB |
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 436 KiB |
Before Width: | Height: | Size: 444 KiB |
Before Width: | Height: | Size: 145 KiB |
Before Width: | Height: | Size: 161 KiB |
Before Width: | Height: | Size: 163 KiB |
Before Width: | Height: | Size: 105 KiB |
Before Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 1.2 MiB |
Before Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 725 KiB |
Before Width: | Height: | Size: 763 KiB |
Before Width: | Height: | Size: 739 KiB |
Before Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 1.2 MiB |
@@ -92,11 +92,8 @@ Nearest Neighbour is a texture filter which is particularly effective at making
|
||||
|
||||
All of these texture filters, including our shiny new Nearest Neighbour texture filter, can be found in `Emulation -> Configure -> Graphics -> Renderer` in Citra! (`Citra -> Preferences` on MacOS)
|
||||
|
||||
{{< single-title-imgs-compare
|
||||
"Left: unfiltered, Right: Nearest Neighbour"
|
||||
"./linear.png"
|
||||
"./nn.png"
|
||||
>}}
|
||||
<style>.juxtapose-35vh { display:block; margin:auto; width:100%; height:35vh; }</style>
|
||||
{{< juxtapose id="cc0544e8-aba2-11ed-b5bd-6595d9b17862" class="juxtapose-35vh" >}}
|
||||
|
||||
## Better Support for Picture-in-Picture Custom Layouts ([#6247](https://github.com/citra-emu/citra/pull/6247)) by [SomeDudeOnDiscord](https://github.com/SomeDudeOnDiscord)
|
||||
|
||||
@@ -415,5 +412,3 @@ If you are looking to contribute to Citra or just want to get involved with our
|
||||
Additionally, we’re still looking for writers! If you are interested in being a writer of these blog posts, please reach out to us on [Discord](https://discord.com/invite/FAXfZV9).
|
||||
|
||||
Thank you for reading and keep your eyes peeled here, there is more to come in the future!
|
||||
|
||||
{{< imgs-compare-include-end >}}
|
||||
|
Before Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 313 KiB |
Before Width: | Height: | Size: 235 KiB |
Before Width: | Height: | Size: 436 KiB |
BIN
site/content/entry/citra-progress-report-2023-q2/discord.png
Normal file
After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 1.8 MiB |
Before Width: | Height: | Size: 1.1 MiB |
@@ -1,14 +1,13 @@
|
||||
+++
|
||||
date = "2023-07-18T20:00:00+01:00"
|
||||
date = "2023-06-26T00:00:00+01:00"
|
||||
title = "Citra Progress Report 2023 Q2"
|
||||
tags = [ "progress-report" ]
|
||||
author = "autumnburra"
|
||||
coauthor = "emufan_4568"
|
||||
forum = 845615
|
||||
+++
|
||||
|
||||
Doesn't it feel like it was just yesterday when Citra released its first progress report in years? It certainly was exciting, finally reaching a point of having tangible progress and being able to share it with everyone!
|
||||
As we said in the [previous progress report](https://citra-emu.org/entry/citra-progress-report-2023-q1/), Citra is alive and well, and as a result, we have even more Citra improvements to talk about. So, dear reader, it's time for another progress report which is sure to excite you!
|
||||
Didn’t it feel like it was only yesterday when Citra released its first progress report in years? It certainly was exciting, finally reaching a point of having tangible progress and being able to share it with everyone!
|
||||
As we said in the [previous progress report](https://citra-emu.org/entry/citra-progress-report-2023-q1/), Citra is alive and well, and as a result, we have a lot more new Citra improvements to talk to you about. So, dear reader, it's time for another progress report which will be sure to excite you!
|
||||
|
||||
# Contents
|
||||
1. [Home Menu]({{< relref "#home-menu" >}})
|
||||
@@ -19,21 +18,36 @@ As we said in the [previous progress report](https://citra-emu.org/entry/citra-p
|
||||
1. [Miscellaneous]({{< relref "#miscellaneous" >}})
|
||||
1. [Conclusion]({{< relref "#conclusion" >}})
|
||||
|
||||
# HOME Menu
|
||||
# Home Menu
|
||||
|
||||
The hallmark of the 3DS, and any Nintendo console in fact, is the HOME Menu.
|
||||
With each console generation carrying a unique aesthetic, it’s no surprise that so many people hold it near and dear to their hearts. The soothing music, pleasing visuals, and the nostalgia alone are plenty of reasons to want to emulate it alongside the actual games. It’s also very important for the preservation of the 3DS, something that the recent closure of the Nintendo eShop for the 3DS and Wii U has made abundantly clear.
|
||||
|
||||
However, there was a small problem in fulfilling this dream: it didn’t actually work in Citra…
|
||||
|
||||
To cut a long story short, there were a lot of problems that needed to be overcome. The HOME menu in Citra had always been plagued with problems. You couldn't launch system applets or regular titles from it, the themes didn't work, the setup would often softlock (preventing users from completing it), and a bunch more issues meant that the HOME menu was far from usable.
|
||||
To cut a long story short, there were a lot of problems that needed to be overcome. The HOME menu in Citra had always been plagued with problems. You couldn't launch system applets or regular titles from it, the themes didn't work, the setup would often softlock (preventing users from completing it), and a bunch more issues meant that the home menu was far from usable.
|
||||
Something had to change, and fast. Citra needed to expand and find that special developer with the ability to undertake such a massive effort.
|
||||
|
||||
Enter [Steveice10](https://github.com/Steveice10), the author of [FBI](https://github.com/Steveice10/FBI), legendary title manager for the 3DS. A staple homebrew app of a modded 3DS. With their extensive knowledge of the 3DS operating system and all of its inner workings, they joined the Citra team in order to tackle this issue once and for all.
|
||||
|
||||
### Add option to configure to download system files from Nintendo Update Service ([#6269](https://github.com/citra-emu/citra/pull/6269), [#6356](https://github.com/citra-emu/citra/pull/6356)) by [Steveice10](https://github.com/Steveice10) and [B3n30](https://github.com/B3n30)
|
||||
### Add Config block enums documented by 3dbrew ([#6206](https://github.com/citra-emu/citra/pull/6206)) by [SachinVin](https://github.com/SachinVin)
|
||||
|
||||
With the goal of making the HOME menu fully accessible in mind, Steveice10’s work began. However, before any accuracy improvements could be made, there was the matter of the accessibility of the HOME Menu. Dumping the 3DS System NAND for use in Citra was, relatively speaking, a cumbersome process.
|
||||
Upon opening a 3DS for the first time, you will be met with a handy setup guide before being able to access anything else on the system. Needless to say, it’s also the first thing you will encounter when booting the HOME Menu on Citra.
|
||||
Unfortunately, it has also been plagued with issues ever since the beginning of the emulator’s life. Attempting to load the most important and well known feature of the 3DS setup guide, the Nintendo 3DS User Agreement, would cause the emulator to freeze, thus preventing anyone from actually completing it!
|
||||
|
||||
{{< gifv src="eula-broken.mp4" title="" >}}
|
||||
|
||||
It wasn't until recently that the cause of this freeze was really understood. As it turns out, the settings app preloads the software keyboard applet for later use. When the Nintendo 3DS User Agreement is launched, it is supposed to close this preloaded applet, so that it can load the EULA applet instead.
|
||||
However, due to a combination of missing logic to provide applets with the correct ‘slot’ (Application, Library Applet, System Applet, or Home Menu), and the command to close an applet not being implemented, the settings app was unaware that the keyboard applet remained loaded.
|
||||
|
||||
By implementing the additional state management required for applets, the accuracy of Citra’s applet manager has been improved tremendously, bringing it closer to the real APT behavior of the 3DS.
|
||||
This means that the old workarounds required to get the HOME Menu to boot are no longer required! Not only that, but launching system applets now also works perfectly.
|
||||
|
||||
{{< gifv src="eula.mp4" title="" >}}
|
||||
|
||||
## Add option to configure to download system files from Nintendo Update Service ([#6269](https://github.com/citra-emu/citra/pull/6269), [#6356](https://github.com/citra-emu/citra/pull/6356)) by [Steveice10](https://github.com/Steveice10) and [B3n30](https://github.com/B3n30)
|
||||
|
||||
With the goal of making the HOME menu fully accessible in mind, Steveice10’s work began. However, before any progress on accuracy improvements could be made, there was the matter of accessibility of the HOME Menu. Dumping the System NAND for use in Citra was, relatively speaking, a cumbersome process.
|
||||
|
||||
Building off of the past work of another Citra developer, B3N30, these PRs add the ability to download the 3DS system files from Nintendo servers directly from Citra’s GUI! This requires you to dump the necessary keys from your console, the process for which is detailed in our [AES Keys guide.](https://citra-emu.org/wiki/aes-keys/)
|
||||
|
||||
@@ -44,19 +58,19 @@ Alongside these download options, there is also a setting to select what region
|
||||
Do note that you still can dump all of the necessary data to use the HOME menu in Citra straight from your 3DS using [threeSD](https://github.com/zhaowenlan1779/threeSD/wiki/Quickstart-Guide), this is just an easier way of doing so!
|
||||
|
||||
{{< figure src="download.png"
|
||||
title="A simple way to download all the system files you need for Citra." >}}
|
||||
title="" >}}
|
||||
|
||||
### Implement PrepareToStartApplication, StartApplication, and WakeupApplication ([#6280](https://github.com/citra-emu/citra/pull/6280)) by [Steveice10](https://github.com/Steveice10) and [Subv](https://github.com/Subv/)
|
||||
|
||||
With the accessibility issue resolved, Steveice10 could now begin working on making the HOME menu more usable in Citra.
|
||||
Continuing on the trend of reviving abandoned projects from the past, this PR implements some important APT service calls used by the HOME Menu in order to start applications. Originally the work of Subv, it addresses one of the longest standing issues with HOME Menu emulation, which was that attempting to launch anything from it would result in an instant crash.
|
||||
Continuing on the trend of reviving abandoned projects from the past, this PR implements some important APT service calls used by the HOME Menu in order to start applications. Originally the work of Subv, a Citra developer who is currently not working on the project. It addresses one of the longest standing issues with HOME Menu emulation, which was that attempting to launch anything from it would result in an instant crash.
|
||||
|
||||
The implementation had been left untouched and neglected for years, until Steveice10 cleaned up the code and finally got it merged into Citra.
|
||||
The implementation had been left untouched and neglected for years, until Steveice10 cleaned up the code and got it finally merged into Citra.
|
||||
|
||||
The benefits aren’t limited to just the HOME Menu, however. While these functions are mainly used by the HOME Menu, this doesn’t mean that games can’t take advantage of them either. A notable example is Teenage Mutant Ninja Turtles: Master Splinter’s Training Pack, which attempts to shut itself down in order to launch its games, causing an unexpected crash. Now it’s fully playable!
|
||||
|
||||
{{< figure src="tmnt.png"
|
||||
title="We're happy to finally see you, Michelangelo!" >}}
|
||||
title="" >}}
|
||||
|
||||
### Fully stub nim:u service. ([#6290](https://github.com/citra-emu/citra/pull/6290)) by [Steveice10](https://github.com/Steveice10)
|
||||
|
||||
@@ -66,85 +80,59 @@ Without this service properly implemented, Citra would exhibit strange glitches,
|
||||
Citra did, in fact, have a portion of this module semi-implemented in the past, but it wasn’t exactly put to good use. Back in 2017, Citra developer Subv added the [CheckForSysUpdateEvent syscall](https://github.com/citra-emu/citra/pull/2974), which allowed the HOME Menu to boot.
|
||||
However, doing anything other than just looking at the pretty background would softlock the emulator. One of the caveats of this addition was that the LLE NIM applet, used for handling title installations as mentioned above, needed to be enabled from the debugging menu, which wasn’t very user-friendly or obvious.
|
||||
|
||||
To address this issue, Steveice10 implemented stubs for the nim:u service based on their own reverse engineering work of the 3DS.
|
||||
{{< figure src="lle.png"
|
||||
title="" >}}
|
||||
|
||||
To address this issue, Steveice10 implemented full stubs for the nim:u service based on their own reverse engineering work of the 3DS.
|
||||
All the information they uncovered has been added to [3dbrew](https://www.3dbrew.org/wiki/NIM_Services) to contribute to the ongoing effort to better understand the 3DS’s operating system. Feel free to take a look if you’re interested in the dark arts of HLE emulator development!
|
||||
|
||||
The result of all of this? All of the aforementioned issues have disappeared and it is now possible to launch apps without enabling LLE NIM, as the HLE stubs are accurate enough to satisfy the HOME Menu!
|
||||
The result of all of this? All of the aforementioned issues have disappeared and it is now possible to launch apps without enabling LLE NIM, as the HLE stubs are accurate enough to satisfy the Home Menu!
|
||||
|
||||
{{< sidebyside "image" ""
|
||||
"broken.png=Where is everything..?"
|
||||
"working.png=Oh! My games are here!" >}}
|
||||
"broken.png=filler"
|
||||
"working.png=filler" >}}
|
||||
|
||||
### Return installed titles in GetNumTickets and GetTicketList stubs. ([#6292](https://github.com/citra-emu/citra/pull/6292)) by [Steveice10](https://github.com/Steveice10)
|
||||
|
||||
When games are installed to the 3DS, they come with a ticket that provides the console with the rights and encryption keys to launch it. Citra doesn’t care about these tickets, so it usually discards them when installing a CIA file. However, the HOME Menu uses two commands, GetNumTickets and GetTicketList, to determine what titles are installed on the system when populating the application grid. Since we have no tickets, none of your installed titles would appear on the HOME Menu.
|
||||
What’s the point of being able to access the HOME Menu if I can’t launch my games?
|
||||
|
||||
Instead of returning an empty list of tickets, we can pretend that any installed CIA has a ticket. That way the HOME Menu will discover and display games correctly.
|
||||
Instead of returning an empty list of tickets, we can pretend that any installed CIA has a ticket. That way the home menu will discover and display games correctly.
|
||||
|
||||
{{< mp4 src="open.mp4" title="It's just like unwrapping a gift on Christmas!" >}}
|
||||
{{< gifv src="open.mp4" title="" >}}
|
||||
|
||||
Currently, only .cia (CTR Importable Archive) installed titles are detected by the HOME Menu. If you would like to try this out in Citra yourself, make sure your games are dumped as .cia files and installed into Citra via `File > Install CIA…`. Other files, such as .3ds and .cxi, still need to be launched from the Citra game list as normal.
|
||||
|
||||
### Implement additional applet state management ([#6303](https://github.com/citra-emu/citra/pull/6303)) by [Steveice10](https://github.com/Steveice10)
|
||||
## Fix HLE applet pre-start lifecycle ([#6362](https://github.com/citra-emu/citra/pull/6362)) by [Steveice10](https://github.com/Steveice10)
|
||||
|
||||
Upon booting a 3DS for the first time, you will be met with a handy setup guide before being able to access anything else on the system. Needless to say, it’s also the first thing you will encounter when booting the HOME Menu in Citra.
|
||||
Unfortunately, it has also been riddled with issues ever since the beginning of the emulator’s life. Attempting to load the most important and well-known feature of the 3DS setup guide, the Nintendo 3DS User Agreement, would cause the emulator to freeze, thus preventing anyone from actually completing it!
|
||||
|
||||
{{< mp4 src="eula-broken.mp4" title="Well... that isn't supposed to happen." >}}
|
||||
|
||||
It wasn't until recently that the cause of this freeze was really understood. As it turns out, the settings app preloads the software keyboard applet for later use. When the Nintendo 3DS User Agreement is launched, it is supposed to close this preloaded applet, so that it can load the EULA applet instead.
|
||||
However, due to a combination of missing logic to provide applets with the correct ‘slot’ (Application, Library Applet, System Applet, or HOME Menu), and the command to close an applet not being implemented, the settings app was unaware that the keyboard applet remained loaded.
|
||||
|
||||
By implementing the additional state management required for applets, the accuracy of Citra’s applet manager has been improved tremendously, bringing it closer to the real [APT](https://www.3dbrew.org/wiki/NS_and_APT_Services) behavior of the 3DS.
|
||||
This means that the old workarounds required to get the HOME Menu to boot are no longer required! Not only that, but launching system applets now also works perfectly.
|
||||
|
||||
{{< mp4 src="eula.mp4" title="Now you have another EULA you can skip-I mean, thoroughly read!" >}}
|
||||
|
||||
### Add Config block enums documented by 3dbrew ([#6206](https://github.com/citra-emu/citra/pull/6206)) by [SachinVin](https://github.com/SachinVin)
|
||||
|
||||
Even if one managed to bypass the broken EULA, completing the HOME menu setup still wasn't possible! Upon reaching the Parental Controls setup screen, the emulator would warn the user of a fatal error, with the only options being either continuing, which would freeze Citra, or aborting entirely. This was the last piece of the puzzle to make the setup screen fully usable and it had to be resolved.
|
||||
|
||||
Following the advice given by the popup and looking at the generated log files, developer SachinVin spotted some configuration blocks Citra was missing and were being accessed by the setup screen. Adding those missing [configs](https://www.3dbrew.org/wiki/Config_Savegame) fixed opening the Settings applet and, combined with the improved applet state management, allowed the system setup to be completed.
|
||||
|
||||
### Implement app management support (suspend, resume, close, etc) ([#6322](https://github.com/citra-emu/citra/pull/6322)) by [Steveice10](https://github.com/Steveice10)
|
||||
|
||||
So far, we’ve discussed using the HOME Menu, launching games and applets from it, and completing the system setup process. However, it feels as though we’re forgetting about something…
|
||||
So far, we’ve discussed using the HOME Menu, launching games and applets from it and completing the system setup process. Though, it feels as though we’re forgetting about something…
|
||||
|
||||
Oh! Doesn’t the 3DS let you exit out of apps and back into the HOME Menu, what about that? Well, fear not, we’ve got you all covered.
|
||||
By implementing support for most application management commands and home button notifications, operations such as suspending, resuming, and closing applications from the HOME Menu are now supported in Citra!
|
||||
By implementing support for most application management commands and home button notifications, operations such as suspending, resuming, and closing applications from the HOME Menu are now fully supported in Citra!
|
||||
|
||||
In addition, the GSP module is now able to capture the screen framebuffers, which correctly emulates the effect when suspending applications. All in all, with these changes you can easily boot the HOME menu and use it to launch system applets and games, suspend or close them, and then launch another game or applet!
|
||||
In addition, the GSP module is now able to capture the screen framebuffers, which correctly emulates the effect when suspending applications. All in all, with these changes you can easily boot the HOME menu and use it to launch system applets and games, suspend or close them, and then launch another game or applet!
|
||||
|
||||
{{< youtube g1ZXWpl7_2M >}}
|
||||
{{< youtube BxQsn1wzNvE >}}
|
||||
|
||||
Exploring the `File` menu will also yield a pleasant surprise: there’s now a dedicated “Boot Home Menu” option in the GUI for Citra. This will both automatically detect the correct HOME Menu application, and adjust your region setting based on the firmware region that you’re attempting to launch. In the past, the HOME Menu was entirely hidden from the game list, forcing potential users to go on a wild goose chase inside the NAND folder in an attempt to find the correct application file for their corresponding region.
|
||||
*video is a placeholder for now until we get the actual videos uploaded*
|
||||
|
||||
Exploring the `File` menu will also yield a pleasant surprise: there’s now a dedicated “Boot Home Menu” option in the GUI for Citra. This will both automatically detect the correct home menu application, and adjust your region setting based on the firmware region that you’re attempting to launch. In the past, the HOME Menu was entirely hidden from the game list, forcing potential users to go on a wild goose chase inside the NAND folder in an attempt to find the correct application file for their corresponding region.
|
||||
You can now say goodbye to wasting time trying to find the correct app name, as Citra will take care of that for you!
|
||||
|
||||
{{< figure src="boot.png"
|
||||
title="Hey, there's even a way to launch the region you want!" >}}
|
||||
title="" >}}
|
||||
|
||||
But this doesn’t mean that our work is done, far from it. Steveice10 has added a very early approximation of DSP sleep, so that apps will not hang while trying to sleep the DSP when suspending titles. However, some games, such as Pokémon X, may still get stuck on this or exhibit annoying audio artifacts in the process.
|
||||
Additionally, some titles (e.g. Super Mario 3D Land) can crash if you try to close them from the HOME menu. This is because some services, required for cleaning up kernel resources, are unimplemented currently. Most built-in titles, such as Mii Maker or Nintendo 3DS Sound, should work fine, however. Our experimental Canary builds contain some fixes for these aforementioned issues. These fixes still need more testing before being merged into Nightly though, so we encourage you to give it a try and report any bugs you come across!
|
||||
But this doesn’t mean that our work is done, far from it. Steveice10 has added a very early approximation of DSP sleep, so that apps will not just hang while trying to sleep the DSP when suspending. However, some games, such as Pokemon X, may still get stuck on this or exhibit annoying audio artifacts in the process.
|
||||
Some apps (e.g. Super Mario 3D Land) may also crash if you try to close them from the HOME menu, due to some services needed for cleaning up kernel resources that are currently not implemented. Most built-in titles, such as Mii Maker or 3DS Sound, should work fine, but DSP sleep still needs more work in order to make it accurate enough for most games and system applets.
|
||||
|
||||
### Fix HLE applet pre-start lifecycle ([#6362](https://github.com/citra-emu/citra/pull/6362)) by [Steveice10](https://github.com/Steveice10)
|
||||
|
||||
After the aformentioned APT improvements had been merged, we started receiving reports of certain games, such as Bravely Second: End Layer, [crashing](https://github.com/citra-emu/citra/issues/6361). This game, as well as others, crashed when the Mii selection dialog was activated. In the absence of system files, Citra will use an open source replacement for Miis. But, after setting up the HOME menu, there's no need to use the replacement and the native 3DS selection will be shown instead. Any Miis you create through Mii Maker will be available in the games you play! However, none of that would be relevant, if the native selection always crashed, right? So, Steveice10 investigated the issue and discovered that the now more accurate applet handling had exposed further inaccuracies. More specifically, problems arose when CancelLibraryApplet was called on an applet that hadn't started yet, as it would fail to receive the cancellation message and de-register itself.
|
||||
|
||||
"What's the fix?" you might ask. Firstly, Steveice ensured that the applet update event starts immediately on creation. Then he implemented a distinction between running and active applets to determine what the update event should do each cycle. This fixed the crashing issues, not only in Bravely Second, but in Super Mario 3D Land as well. Enjoy selecting your Miis!
|
||||
|
||||
{{< mp4 src="mii.mp4" title="Wow! An actual Mii selector!" >}}
|
||||
|
||||
### Add stub for ns:c service ([#6409](https://github.com/citra-emu/citra/pull/6409)) by [Steveice10](https://github.com/Steveice10)
|
||||
## Skip address range checks for privileged memory (un)map ([#6407](https://github.com/citra-emu/citra/pull/6407)) by [Steveice10](https://github.com/Steveice10)
|
||||
|
||||
The ns:c service was introduced with firmware version 5.0.0-11, and appears to be used only by the Instruction Manual applet for triggering SD/Game Card removal errors when ejecting the media that the manual is stored on.
|
||||
By implementing a stub for the aforementioned service, the instruction manual now works on Citra!
|
||||
|
||||
{{< figure src="manual.png"
|
||||
title="Very important for the preservation of the 3DS." >}}
|
||||
|
||||
### Skip address range checks for privileged memory (un)map ([#6407](https://github.com/citra-emu/citra/pull/6407)) by [Steveice10](https://github.com/Steveice10)
|
||||
|
||||
title="" >}}
|
||||
|
||||
Another corner of the HOME Menu that never quite worked was the Internet Browser applet, which would mysteriously cause the execution to break, alongside a healthy dose of memory errors.
|
||||
|
||||
```
|
||||
@@ -155,23 +143,21 @@ Another corner of the HOME Menu that never quite worked was the Internet Browser
|
||||
[ 19.449282] HW.Memory <Error> core/memory.cpp:Read:469: unmapped Read32 @ 0x000000C8 at PC 0x0028117C
|
||||
```
|
||||
|
||||
These errors occured because Citra’s code for loading CROs (relocatable code, similar to DLLs on Windows) did not allow parts of the internet browser’s code to be mapped into memory.
|
||||
By inspecting the kernel through disassembly, Steveice10 determined that the address range checks that Citra used for maps/unmaps were not actually used when mapping privileged executable memory, such as in this case. Thus, skipping these checks for the privileged case allowed the Internet Browser applet to load properly.
|
||||
These errors occur because Citra’s code for loading CROs (relocatable code, similar to DLLs on Windows) did not allow parts of the internet browser’s code to be mapped into memory.
|
||||
By inspecting the kernel through disassembly, Steveice10 determined that the address range checks that Citra used for maps/unmaps were not actually used when mapping privileged executable memory, such as this case. Thus, skipping these checks for the privileged case allowed the Internet Browser applet to load properly.
|
||||
|
||||
Do note that this is **not** fully functional in Citra at the moment. You will **not** be able to browse the web from inside Citra using the Internet Browser.
|
||||
|
||||
{{< figure src="browser.png"
|
||||
title="I wonder what the bookmarks include..." >}}
|
||||
|
||||
And there you have it! All the changes we have made in Citra to majorly improve the functionality of the HOME Menu. Of course, not everything is perfect just yet, but we are working hard to ensure that this vital part of the 3DS experience is preserved through Citra. There will be more updates in the future on this, keep an eye out if you're interested.
|
||||
title="" >}}
|
||||
|
||||
# Android
|
||||
|
||||
### Storage Access Framework ([#6313](https://github.com/citra-emu/citra/pull/6313)) by [hank121314](https://github.com/hank121314)
|
||||
## Storage Access Framework ([#6313](https://github.com/citra-emu/citra/pull/6313)) by [hank121314](https://github.com/hank121314)
|
||||
|
||||
Oh boy, where to even begin with this one…
|
||||
|
||||
Storage Access Framework, which is often abbreviated to SAF, is Google’s method of implementing scoped storage. On its own, the idea has merit; with scoped storage, apps can't see all of your files or access any data from other apps, meaning you don’t have to worry about any of your personal data being stolen by bad actors.
|
||||
Storage Access Framework, which is often abbreviated to SAF, is Google’s method of implementing scoped storage. On its own the idea has merit; with scoped storage, apps can't see all of your files or access any data from other apps, meaning you don’t have to worry about any of your personal data being stolen by malicious individuals.
|
||||
This implementation of that idea though, is absolute garbage. When using SAF, apps cannot access files outside of their data directory without using so-called “content URIs” for addressing them.
|
||||
Citra, however, being a native C++ program, assumes that files can be addressed with paths that are delimited by slashes and can be stored as strings. Updating the entire codebase to use these URIs would be a massive undertaking for little benefit.
|
||||
|
||||
@@ -198,60 +184,54 @@ As Android is an ever evolving operating system, there are many technologies tha
|
||||
|
||||
Android TV support for Citra was planned in the past, but due to a lack of testers and developers, it had to unfortunately be scrapped. Thankfully, with time and effort, we are able to provide support for launching Citra on an Android TV as we initially hoped!
|
||||
|
||||
### Citra Android theme overhaul! ([#6332](https://github.com/citra-emu/citra/pull/6332) [#6335](https://github.com/citra-emu/citra/pull/6335), [#6351](https://github.com/citra-emu/citra/pull/6351), [#6355](https://github.com/citra-emu/citra/pull/6355), [#6349](https://github.com/citra-emu/citra/pull/6349)) by [t895](https://github.com/t895)
|
||||
## Citra Android theme overhaul! ([#6332](https://github.com/citra-emu/citra/pull/6332) [#6335](https://github.com/citra-emu/citra/pull/6335), [#6351](https://github.com/citra-emu/citra/pull/6351), [#6355](https://github.com/citra-emu/citra/pull/6355), [#6349](https://github.com/citra-emu/citra/pull/6349)) by [t895](https://github.com/t895)
|
||||
|
||||
As mentioned in the previous progress report, we are looking to modernize Citra in many ways and get it up to speed with other emulators. This also includes modernization of the Android app!
|
||||
To give the app’s theming a breath of fresh air, t895, developer for the Android apps of the emulators Dolphin and yuzu, has stepped up to this task.
|
||||
|
||||
Starting off with how the app responds to touch navigation, t895 ported over a [PR from Dolphin](https://github.com/dolphin-emu/dolphin/pull/11327) which aimed to upgrade the UI animations to something a bit more modern, and also helps with how fast you can get around the app! This change, although it looks small, greatly improves the user experience of Citra.
|
||||
Starting off with how the app responds to touch navigation, t895 ported over a [PR from Dolphin](https://github.com/dolphin-emu/dolphin/pull/11327) which aimed to upgrade the UI animations to something a bit more modern, and also helps with how fast you can get around the app! This change, although it looks small, helps the user experience of Citra greatly, even if it isn’t noticeable to many.
|
||||
|
||||
Next up on the list of changes is starting the migration of the UI to the Material 3 system, introduced in Android 12. [Material 3](https://m3.material.io/) is the latest design system from Google, giving developers the tools and inspiration needed to create a beautiful looking app.
|
||||
As humans, we are all about aesthetically pleasing design, and this migration proves just that for the Citra app. This change includes upgrades to the layout of the app, the themes, icons, colors, and so many more changes just to make it squeaky clean!
|
||||
As humans, we are all about aesthetically pleasing design, and this migration proves just that for the Citra app. This change includes upgrades to the layout of the app, the themes, icons, the general colors that the Citra app uses and so many more changes just to make it squeaky clean!
|
||||
|
||||
Next, we’re turning our focus towards the app icon for Citra. Beginning with Android 13, but being supported by devices running API level 26 (Android 8) or newer, apps have the option to enable the use of themed icons on the home screen. This means that the app icon will match the theme of the phone the best it can, to match the general aesthetic of the phone. For example, with themed icons, Citra will be able to tell if your phone is in light mode or dark mode, and change its icon design accordingly. A neat little change, but one that will help Citra blend in nicely with the rest of the phone if you choose so.
|
||||
Next we’re turning our focus towards the app icon for Citra. Beginning with Android 13, but being supported by devices running API level 26 (Android 8) or newer, apps have the option to enable the use of themed icons on the home screen. This means that the app icon will match the theme of the phone the best it can, to match the general aesthetic of the phone. For example, with themed icons, Citra will be able to tell if your phone is in light mode or dark mode, and change its icon design accordingly. A neat little change, but one that will help Citra blend in nicely with the rest of the phone if you choose that.
|
||||
|
||||
Not long to go now… splash screens! Introduced in Android 12, but being supported by devices running API level 23 (Android 6) or newer, splash screens bring a nifty little Citra logo that pops up when you open the app to let you know it is launching correctly and to smoothly transition you from the rest of the phone into Citra to fully immerse yourself in the joy that is 3DS emulation!
|
||||
|
||||
And finally, edge-to-edge display. No longer do you need to worry about that pesky navigation bar at the bottom of your phone getting in the way. Citra now renders right to the edge of your screen, giving you a full display of your favorite games.
|
||||
And finally, edge-to-edge display. No longer do you need to worry about that pesky system bar at the bottom of your phone getting in the way. Citra now displays the gameplay right to the edge of your screen, giving you a full display of your favorite games.
|
||||
|
||||
All of these changes add up into one big overhaul of our UI, bringing the freshest look right to your device! We have more planned for our UI on Android in the future, so keep an eye out here and we’ll update you when we can!
|
||||
|
||||
{{< sidebyside "image" ""
|
||||
"themeb4.jpg=Old"
|
||||
"themenew.jpg=New" >}}
|
||||
"themeb4.jpg=filler"
|
||||
"themenew.jpg=filler" >}}
|
||||
|
||||
### Avoid reopening files every time a shader needs to be written. ([#6344](https://github.com/citra-emu/citra/pull/6344)) by [SachinVin](https://github.com/SachinVin)
|
||||
|
||||
Shader stutter is pretty annoying, no matter how you put it. Citra has always had issues with it, mainly because we are at the mercy of the OpenGL driver. Most drivers do end up taking their sweet time when compiling shaders, however after merging the new SAF implementation, it became much-much worse than before, with individual stutters reaching a mind-boggling 5 seconds even on powerful hardware.
|
||||
Shader stutter is pretty annoying, no matter how you put it. Not to mention that Citra has always had issues with it, mainly because we are at the mercy of the OpenGL driver. Most drivers do end up taking their sweet time when compiling shaders, however after merging the new SAF implementation, it somehow became much-much worse than before, with stutter reaching a mind-boggling 5 seconds even on powerful hardware.
|
||||
So what gives?
|
||||
|
||||
As it turns out, our disk shader cache opens the cache file every time a new shader is generated in order to serialize it. That’s fine and dandy over on Citra Desktop, where ignoring the characteristics of the storage medium, file access is relatively fast. It also reduces the chance of shader cache corruption when Citra crashes or is terminated abnormally, which is really important for any emulator. But with SAF added to the mix, the overhead of that method just became too much to bear.
|
||||
As it turns out, our disk shader cache opens the cache file every time a new shader is generated in order to serialize it. That’s okay over on desktop Citra, where ignoring the characteristics of the storage medium, file access is relatively fast. It also reduces the chance of shader cache corruption when Citra crashes or is terminated abnormally, which is really important for any emulator. But with SAF added to the mix, the overhead of that method just became too much to bear.
|
||||
|
||||
In the end, the solution came from developer SachinVin, who rewrote the disk cache to only open the file once at the beginning of the emulation session.
|
||||
|
||||
### Turn GameInfo into a class ([#6494](https://github.com/citra-emu/citra/pull/6494)) by [JosJuice](https://github.com/JosJuice)
|
||||
|
||||
SAF strikes again! The slowness of file operations negatively impacted the user experience by making the game list incredibly slow to load. For users who only have a small handful of games in their game list, this wasn't particularly noticeable. However, for anyone with a large enough game library, the loading speed became unbearable.
|
||||
|
||||
The only way to alleviate this issue is to limit file access as much as possible, and that's what was done with this PR. Utilizing their android expertise from their work over at Dolphin, JosJuice managed to speed up the process by centralizing game information queries to a single class, instead of having separate file access calls for fetching the TitleID, title name, game icon, etc. This ended up saving a bunch of time that was wasted on opening the same file multiple times.
|
||||
|
||||
### Open cheats by long pressing game in game list ([#6491](https://github.com/citra-emu/citra/pull/6491)) by [JosJuice](https://github.com/JosJuice)
|
||||
|
||||
Normally to edit a cheat for a game, you’d have to edit it whilst the game was running. This was fine if the cheat codes were working, but what if they were causing the game to crash? You’d have no way of disabling them unless you crawled through the hell that is the Android file manager.
|
||||
|
||||
A simple fix to this, based off of a similar addition to Citra Desktop that we’ll get to later, involves enabling cheat code editing by long pressing the game in the main menu of Citra. This allows users to modify cheat codes directly from Citra, regardless of whether a game is running or not. The previous method of adding cheat codes in Citra still remains.
|
||||
A simple fix to this, based off of a similar addition to Citra Desktop that we’ll get to later, involves enabling cheat code editing by long pressing the game in the main menu of Citra. This allows users to modify cheat codes directly from Citra, regardless of whether a game is running or not. The previous way of adding cheat codes to Citra still remains.
|
||||
|
||||
### Offload CIA installation to background thread ([#6508](https://github.com/citra-emu/citra/pull/6508)) by [SachinVin](https://github.com/SachinVin)
|
||||
|
||||
With the addition of SAF, some things in Citra Android slowed down a lot, to no fault of our own. That’s just how SAF works, sadly.
|
||||
One of these is the installation of CIA (CTR Importable Archive) files. These are mainly used to install games, update files, and DLC files. With the installation of these being so much slower than previous Citra builds without SAF, Android believes that the app has frozen and forces it to crash due to the installation running on the UI thread.
|
||||
One of these is the installation of CIA (CTR Importable Archive) files. These are mainly used to install games, update files and DLC files. With the installation of these being so much slower than previous Citra builds without SAF, Android believes that the app has frozen and forces it to crash, due to the installation running on the UI thread.
|
||||
|
||||
By offloading CIA installations to the background thread instead, we now prevent Android from accidentally terminating Citra prematurely. But, how are you, as a user, meant to know if your installation is actually working?
|
||||
|
||||
This is where the new notification progress bar comes into play. This convenient progress bar notification allows you to monitor your CIA installation, even when Citra is minimized! It also will notify you if the installation has been successful or if it has failed, which is handy to know.
|
||||
This is where the new notification progress bar comes into play. We’ve added a convenient progression bar as a notification for you to monitor your CIA installation, even when Citra is minimized! It also will notify you if the installation has been successful or if it has failed, which is handy to know.
|
||||
|
||||
{{< figure src="ciainstall.jpg"
|
||||
title="Installing updates and DLC has never been easier!" >}}
|
||||
title="" >}}
|
||||
|
||||
# macOS
|
||||
|
||||
@@ -266,19 +246,19 @@ This ensures that the camera will resume again after the emulation is paused, re
|
||||
### Fix global settings being inaccessible on macOS ([#6235](https://github.com/citra-emu/citra/pull/6235)) by [Steveice10](https://github.com/Steveice10)
|
||||
|
||||
As we mentioned earlier on, we recently added per-game settings to Citra! However, in the beginning, they also broke the global settings! This was a big deal, as the main way to configure your Citra instance was now lost.
|
||||
Fortunately, the fix was relatively simple; manually specifying the roles for the key menu actions, such as About and Preferences, instead of relying on the default Qt heuristics. With this, the global settings are once again accessible!
|
||||
Fortunately, the fix was relatively simple; manually specifying the roles for the key menu actions such as About and Preferences instead of relying on the default Qt heuristics. With this, the global settings are once again accessible!
|
||||
|
||||
### Generate universal macOS build ([#6240](https://github.com/citra-emu/citra/pull/6240), [#6321](https://github.com/citra-emu/citra/pull/6321)) by [Steveice10](https://github.com/Steveice10)
|
||||
## Generate universal macOS build ([#6240](https://github.com/citra-emu/citra/pull/6240), [#6321](https://github.com/citra-emu/citra/pull/6321)) by [Steveice10](https://github.com/Steveice10)
|
||||
|
||||
Somewhat recently, Apple released a new processor for their devices utilizing the ARM architecture, named Apple silicon (M1/M2). Citra’s x86_64 macOS builds technically worked with these new devices through Rosetta 2, in the sense that your game would launch, but it would also result in game bugs; freezing and crashing pretty frequently.
|
||||
Building it natively for ARM was often a solution, a solution inaccessible to the average user, unfortunately. An official Citra build was needed for users running those Apple silicon devices.
|
||||
|
||||
However, as you may be aware, Apple does not support OpenGL 4.3, which presented us with a big issue. Apple officially only supports Metal, their own proprietary graphics API, adding support for which would require a lot of work. So, how are we going to get Apple silicon devices to run on Citra when macOS isn’t even a supported platform?
|
||||
Banking off of the fact that we have a new Vulkan graphics backend quickly making its way into Citra (have we mentioned that yet?), we can utilize MoltenVK, a mature translation layer that converts Vulkan API calls to appropriate Metal ones. With this solution in mind, Steveice10 got to work implementing a universal macOS build for Citra that covers both x86_64 and arm64.
|
||||
However, as you may be aware, Apple does not support OpenGL 4.3, which is what Citra uses now. This presented us with a lot more issues. How are we going to get Apple silicon devices to run on Citra when macOS isn’t even a supported platform?
|
||||
Banking off of the fact that we have a new Vulkan graphics backend quickly making its way into Citra (have we mentioned that yet?), Steveice10 got to work implementing a universal macOS build for Citra that covers both x86_64 and arm64.
|
||||
|
||||
Initially, Citra was set up to build a universal app for both architectures all at once. However, due to a new library introduced with Vulkan not supporting multi-arch building correctly, we had to change approaches. Instead, we now build for x86_64 and ARM separately and combine the app at the end, giving us the same result without having to worry about adapting build scripts for multi-arch.
|
||||
However, due to a new library introduced with Vulkan not supporting multi-arch building correctly, we had to quickly change how we build for both x86_64 and arm64 within the CI for Citra (continuous integration) just to ensure that these new arm64 builds actually worked!
|
||||
|
||||
The PR is currently not usable in the latest Nightly, as it is dependent on Vulkan being merged into Citra. It is, however, available to use in Canary. If you have an Apple silicon device and want to use Citra, please switch to the latest experimental Canary release, downloadable through our installer.
|
||||
The PR is currently not usable in the latest Nightly, as it is dependent on Vulkan being merged into Citra. It is, however, available to use in Canary. If you have an Apple silicon device and want to use Citra, please switch to the latest experimental Canary release, downloadable through our [installer](https://citra-emu.org/download/).
|
||||
|
||||
### Bump macOS target to 11 (Big Sur) ([#6325](https://github.com/citra-emu/citra/pull/6325)) by [Steveice10](https://github.com/Steveice10)
|
||||
|
||||
@@ -287,95 +267,70 @@ By upgrading our macOS target to 11 (Big Sur), we can ensure that all features u
|
||||
|
||||
# Graphics
|
||||
|
||||
### Prepare frontend for multiple graphics APIs ([#6347](https://github.com/citra-emu/citra/pull/6347)) by [GPUCode](https://github.com/GPUCode)
|
||||
|
||||
For being the first PR in our attempt to move away from OpenGL, this one is quite mundane on the surface compared to the other ones. However, it lays the foundations to allow Citra to support multiple rendering backends by abstracting key rendering functionality into common classes.
|
||||
|
||||
A neat result of that effort is that the Software renderer no longer depends on OpenGL hardware acceleration for presentation. This means Citra can technically run on systems without a GPU using the Software renderer. Additionally, the Software renderer has been turned into a Graphics API, so it’s much more obvious when it’s being used. Before, in order to enable Software rendering, one had to disable the Hardware Renderer option, which wasn’t really made obvious to the user. Now, we’ve added a handy little drop down to choose which Graphics API you’d like to use!
|
||||
|
||||
### Rasterizer cache refactor ([#6375](https://github.com/citra-emu/citra/pull/6375)) by [GPUCode](https://github.com/GPUCode)
|
||||
|
||||
Looking at the name of the PR, it’s not immediately obvious what this PR aims to achieve. What it does is rework several important aspects of GPU emulation that had remained untouched for years.
|
||||
One of these is that it greatly simplifies texture uploading and downloading, the methods for which had quickly grown to be complex and hard to understand over the years. This was most notably seen when using custom textures combined with texture filters, where the code would just fail, resulting in some pretty messed up looking textures. But more on that later. To summarize, this code is now much simpler and more optimized!
|
||||
|
||||
Another pain point of the old cache was mipmap handling. A mipmap is a sequence of textures, each of which is a progressively lower resolution representation of the same image. Many 3DS games use mipmaps in order to make graphics look cleaner at a distance.
|
||||
Citra’s problem was that the old cache considered them as separate textures, requiring an expensive tree-like structure to maintain and properly sync them. In addition to this, every surface allocated an excessive amount of mipmaps which increased memory usage, especially when texture filtering was used.
|
||||
|
||||
By having surfaces own the entire mipmap range, the cache can directly upload and use mipmaps without needing to sync them. This reduces the amount of surfaces cached and, in turn, the lookup overhead. So these changes not only make mipmaps faster, they also fixed a few games that didn’t work correctly before, most notably the homebrew port of the game Portal, which displayed nothing but a blue void when using the hardware renderer.
|
||||
|
||||
All of these changes are indeed quite nice, but what’s especially interesting are the OpenGL specific optimizations.
|
||||
After a bit of profiling, GPUCode found that the backend was handling certain operations inefficiently, which really hurt performance on less-than-stellar drivers, such as Android phones utilizing a Mali GPU. By taking the time to correct some of these, the performance of these GPUs have been significantly increased by at least 40%! Even better, the annoying graphical flickering that could be observed on some lower-end Mali devices has now disappeared as well.
|
||||
|
||||
{{< sidebyside "image" ""
|
||||
"portalbroke.png=Before..."
|
||||
"portalfix.png=And after!" >}}
|
||||
|
||||
### HP Bar Fix for some games ([#6334](https://github.com/citra-emu/citra/pull/6334)) by [Polar-Zero](https://github.com/Polar-Zero)
|
||||
|
||||
Question time! Have you heard of something called texture tiling? If you are a graphics developer, you probably have. The rest of us, not so much. As a concept, it’s actually pretty simple: you take an image and chop it into smaller NxN squares of pixels. Such an arrangement can be beneficial for graphics hardware for multiple reasons, so it’s no surprise that the 3DS also makes use of this feature to speed up texture processing. More specifically, we should mention that the tile size is 8x8.
|
||||
In many many video games, players rely on a HP bar to determine how much health their character has left. This is important in fighting games, for example Metal Max 4, to tell the player if they’re going to die soon or not!
|
||||
Imagine the horror Citra users came across when in some games, like the aforementioned JRPG, the HP bar just did not display correctly! How were you meant to tell if you needed to heal or retreat?
|
||||
|
||||
With this information, it wouldn’t be wrong to assume that texture dimensions must be a multiple of 8, otherwise dividing it into tiles wouldn’t really make sense. And in general this assumption holds true, the vast majority of games respect this limitation in their textures. Until they don’t…
|
||||
|
||||
Now we get to the fun part: what happens if the texture is smaller than a tile? Being confronted with that question, Citra developer [wwylele](https://github.com/wwylele) came to the conclusion, after some tests, that such a configuration was not supported by the PICA GPU the 3DS uses. Due to this, the original code that handled these textures was promptly removed when [support for mipmaps](https://github.com/citra-emu/citra/pull/3910) was implemented. Said removal caused [unexpected issues](https://github.com/citra-emu/citra/issues/5139) however, when health bars of all things suddenly went missing in some games. Imagine the horror Citra users came across when in those games the HP bar just did not display correctly! How were you meant to tell if you needed to heal or retreat?
|
||||
|
||||
This issue was again brought to our attention when first time contributor, Polar-Star, opened a pull request reimplementing the code that was removed. With this change, HP bars are fixed and because this bug negatively affected core gameplay of certain games, we opted to accept this change. We are still investigating this issue to figure out the proper hardware behavior in this case, though we suspect it’s not too far off from this.
|
||||
This being an issue since late 2020, first time contributor Polar-Star set out to fix this once and for all. By allowing the rasterizer cache control over 4x4 and 8x4 textures properly, HP bars are finally fixed and give the player to view their stats once again!
|
||||
|
||||
{{< figure src="hpbar.png"
|
||||
title="Left: Broken, Right: Fixed" >}}
|
||||
title="" >}}
|
||||
|
||||
### Fix distance vector used when calculating lighting distance attenuation. ([#6366](https://github.com/citra-emu/citra/pull/6366)) by [Steveice10](https://github.com/Steveice10)
|
||||
## Fix distance vector used when calculating lighting distance attenuation. ([#6366](https://github.com/citra-emu/citra/pull/6366)) by [Steveice10](https://github.com/Steveice10)
|
||||
|
||||
Citra is often referred to as the “Pokémon emulator”, and you wouldn’t be too wrong to assume that. Pokémon games have, by far, been the most popular for the 3DS platform, and this translates over to Citra as well.
|
||||
Citra is often referred to as the “Pokémon emulator”, and you wouldn’t be too wrong to assume that. The Pokémon games have, by far, been the most popular for the 3DS platform, and this translates over to Citra as well.
|
||||
So naturally, when something breaks in the game, it tends to get [overreported](https://github.com/search?q=repo%3Acitra-emu%2Fcitra+pokemon&type=issues&p=2). This is one of those issues that has plagued Pokémon X/Y for a while, so one would assume the solution is quite sophisticated. Right?
|
||||
|
||||
This issue, strangely enough, just made all the backgrounds in some key cutscenes completely black! The [GitHub issue](https://github.com/citra-emu/citra/issues/4499) for this glitch was first opened in 2018, but at the time it wasn’t really known what was causing it. What’s more, the black backgrounds persisted even when using the Software renderer, which is Citra’s most accurate (and slowest) rendering option.
|
||||
Given this information, it was most likely a fundamental accuracy issue, which deterred a lot of people from looking into it due to the difficulty of fixing such a thing.
|
||||
|
||||
Fast forward a year and [hamish-milne](https://github.com/hamish-milne), the mastermind behind one of the most popular features on Citra, save states, attempted to find the cause of this glitch that had eluded many. After poking around for a while, they determined the problem laid in the fragment lighting emulation code.
|
||||
Fast forward a year and hamish-milne, the mastermind behind one of the most popular features on Citra, save states, attempted to find the cause of this glitch that had eluded many. After poking around for a while, they determined the problem laid in the fragment lighting emulation code.
|
||||
For those who aren’t aware, PICA, the 3DS’s GPU, does not support programmable pixel shaders like more modern systems. This means that Citra must generate a host fragment shader to emulate the fixed function pipeline the GPU exposes. What they ended up discovering is that changing how LUT indices are generated for the distance attenuation feature fixed the background lighting. The issue was finally solved!
|
||||
|
||||
{{< figure src="discord.png"
|
||||
title="" >}}
|
||||
|
||||
Unfortunately, this wasn’t the end. After performing some tests, Citra developer [wwylele](https://github.com/wwylele) determined that the solution was not accurate to the hardware and could potentially break games. Due to this, the proposed solution could not be accepted into the codebase.
|
||||
Unfortunately, this wasn’t the end. After performing some tests, Citra developer [wwylele](https://github.com/wwylele) determined that the solution was not accurate to the hardware and thus could not be accepted into the codebase.
|
||||
|
||||
{{< sidebyside "image" ""
|
||||
"lut3ds.png=3DS"
|
||||
"lutnew.png=Citra" >}}
|
||||
|
||||
"lut3ds.png=filler"
|
||||
"lutnew.png=filler" >}}
|
||||
|
||||
And after that, the issue was yet again abandoned throughout Citra’s developer drought. Until recently.
|
||||
Steveice10 picked up the issue and after writing a couple of basic hardware tests, came to the conclusion that the bug was different from what everyone had believed. It turns out that Citra always used the view vector when distance attenuation was enabled, something that doesn’t really make sense for directional light, which is usually a directional vector rather than a concrete position. By correcting the code to use the correct length, it not only fixed the background issue, but improved the lighting accuracy in general!
|
||||
|
||||
{{< sidebyside "image" ""
|
||||
"xybefore.png=Um, where did the Earth go?!"
|
||||
"xynew.png=Finally, the world is back!" >}}
|
||||
"xybefore.png=filler"
|
||||
"xynew.png=filler" >}}
|
||||
|
||||
### Custom textures rewrite ([#6452](https://github.com/citra-emu/citra/pull/6452)) by [GPUCode](https://github.com/GPUCode)
|
||||
## Custom textures rewrite ([#6452](https://github.com/citra-emu/citra/pull/6452)) by [GPUCode](https://github.com/GPUCode)
|
||||
|
||||
We’ve all been there: controller is properly connected and ready at hand (or keyboard if you prefer, we don’t judge), your favorite game is dumped, set up and ready to be experienced on a shiny new computer, devoid of the limitations imposed by the original hardware. You launch it and… it looks so pixelated and blurry.
|
||||
What gives?
|
||||
|
||||
Fortunately, emulators have your back and provide many options that increase fidelity. Resolution scaling, anti-aliasing, and texture filtering can enhance the experience greatly. Having these options is especially important in Citra due to how the 3DS screens are known for their low resolution, compared to modern HD screens.
|
||||
Fortunately, emulators have your back and provide many options that increase fidelity. Resolution scaling, anti-aliasing and texture filtering can enhance the experience greatly. Having these options is especially important in Citra due to how the 3DS screens are known for their low resolution, compared to modern HD screens.
|
||||
|
||||
Often, though, cranking up the resolution isn’t enough. Due to VRAM limitations, textures in 3DS games can look blurry and lack detail when viewed outside of the confines of the console itself. The aforementioned texture filtering feature is useful for upscaling these in-game textures, to make them look better, but the results vary between filters and aren’t always perfect.
|
||||
As such, Citra allows for custom textures to be used as well, a feature [first added](https://github.com/citra-emu/citra/pull/4868) back in 2019 from developer [khang06](https://github.com/khang06). Since then, many custom texture packs have surfaced, made by talented artists. We are grateful to our community that made this all possible!
|
||||
|
||||
The implementation wasn’t without its faults, though. It only supported the .png file format, which forces a choice between hefty file sizes or long decompression times. The loading stutter could be mitigated by using the preload textures option, but that requires a ton of RAM and would often freeze Citra without any indication of progress. Another limitation of the previous system was that mipmaps were unsupported.
|
||||
The implementation wasn’t without its faults, though. It only supported the .png file format, which forces a choice between hefty file sizes or long decompression times. The loading stutter could be mitigated by using the preload textures option, but that requires a ton of RAM and often would freeze Citra without any indication of progress. Another limitation of the previous system was that mipmaps were unsupported.
|
||||
This actually made sense from a developer standpoint at the time, since it avoided graphical glitches from missing mipmaps that manifest as black textures at a distance, and made texture replacement an easier process overall. However this hidden abstraction made the code more complex and prevented pack creators from providing their own mipmaps in cases where such a thing was desirable.
|
||||
|
||||
Most important, however, was the notorious texture filter incompatibility with custom textures, one of the most well known Citra bugs ever! Being first uncovered by a rasterizer cache change made by developer [BreadFish64](https://github.com/citra-emu/citra/pull/5710), the bug would result in messed up textures over time, making the game slowly unplayable.
|
||||
One might say, "That's easy then! Why not just revert the PR that caused it?"
|
||||
|
||||
Well, the change in question is actually quite desirable: it removes fully invalid textures from the cache, in order to speed up lookups and performance. It was briefly mentioned in our [previous progress report](https://citra-emu.org/entry/citra-progress-report-2023-q1/), go read it if you haven’t already!
|
||||
Well the change in question is actually quite desirable: it removes fully invalid textures from the cache, in order to speed up lookups and performance. It was briefly mentioned in our [previous progress report](https://citra-emu.org/entry/citra-progress-report-2023-q1/), go read it if you haven’t already!
|
||||
|
||||
{{< figure src="mmbroke.png"
|
||||
title="Did someone turn off the lights?" >}}
|
||||
(insert picture)
|
||||
|
||||
Another thing to consider is the hashing algorithm being used to identify the textures. Up until this point Citra used the deswizzled and decoded texture data as it was the most convenient option at the time. Said approach presents issues though when other graphics APIs enter the picture, namely Vulkan. As a low-level API, Vulkan accurately reports the host GPUs capabilities, meaning that certain formats Citra expects might not be natively supported, requiring conversions to work. Such conversions break the previously trusted hashing, which could lead to missing textures.
|
||||
|
||||
With the hopes of fixing the aforementioned issues, GPUCode embarked on a journey of fully rewriting the custom textures implementation. The result is a greatly improved system with a bunch of cool new features, like support for compressed formats such as BC7/BC5/ASTC and their container file formats DDS/KTX. By using these formats, the size of a texture pack can be decreased significantly while also maintaining decent image quality. Note that the BCn formats are unsupported on Android devices. So, if a creator wants to target mobile, we recommend either sticking to png, or having an alternative ASTC version of the pack.
|
||||
With the hopes of fixing the aforementioned issues, GPUCode embarked on a journey of fully rewriting the custom textures implementation. The result is a greatly improved system with a bunch of cool new features, like support for compressed formats like BC7/BC5/ASTC and their container file formats DDS/KTX. By using these formats, the size of a texture pack can be decreased significantly while also maintaining decent image quality. Note that the BCn formats are unsupported on Android devices. So, if a creator wants to target mobile, we recommend either sticking to png, or having an alternative ASTC version of the pack.
|
||||
|
||||
Async texture loading is also supported to mitigate loading stutters, which are especially noticeable on Android with the recent SAF implementation we mentioned before. We’ve also added a new hotkey to toggle between normal and HD textures without restarting the game, which is especially useful for demonstration purposes. Oh, and the icing on the cake: texture filtering with custom textures should now work as expected!
|
||||
|
||||
{{< figure src="mmfix.png"
|
||||
title="Ahhh, much better." >}}
|
||||
(insert picture)
|
||||
|
||||
Alongside this new implementation, a new method of hashing textures has been introduced, which not only guarantees compatibility with any graphics API Citra currently supports or might add in the future, but is also much faster, as it requires less input data than before. Of course, we understand the utmost importance of maintaining compatibility with existing packs, so loading the older hashing format is still fully supported. Although we recommend that new packs be created with the new format so they can benefit from the above improvements.
|
||||
|
||||
@@ -383,91 +338,54 @@ The introduction of the new hash has made it necessary to distinguish between ne
|
||||
|
||||
And before ending this segment, we have to talk about one more thing… Remember how the goal of custom textures is to enhance the respective beyond the limits of the original console? In the interest of achieving that goal we have added another feature to the custom textures implementation which we are sure pack creators will love: custom normal maps. Normal maps are very widely used in computer graphics to give the illusion of detail without the cost of rendering more polygons. Pretty neat right? You’ve most likely played a game that uses normal maps.
|
||||
|
||||
{{< figure src="normalstair.jpg"
|
||||
title="The power of normal maps is real!" >}}
|
||||
(insert picture)
|
||||
|
||||
Needless to say, 3DS games also use normal maps to increase detail of certain objects. The low available VRAM however limits their usage considerably. Imagine how much better games could look if they used normal maps for most textures instead of a select few? Well, wonder no longer! Custom normal maps are now a reality! Simply adding the .norm prefix before the file extension is enough to make use of this great new feature.
|
||||
By taking advantage of the fixed-function nature of the PICA200, we can easily apply the normal map to any scene that enables fragment lighting, which is the only requirement for it to work. Attempting to use custom normal maps on scenes without lighting will print an error in the log, so watch out for that when trying it out.
|
||||
|
||||
{{< mp4 src="brickwall.mp4" >}}
|
||||
|
||||
We would like to credit [Nerrel](https://www.youtube.com/@Nerrel) for providing us with this awesome demonstration of how normal maps can enhance games like The Legend of Zelda: Majora's Mask 3D. They have started working on incorporating this feature in their [MM3DHD](https://github.com/DeathWrench/MM3DHD) project and we are definitely excited to see the results of this endeavour.
|
||||
|
||||
### Textures loading screen ([#6478](https://github.com/citra-emu/citra/pull/6478)) by [luc-git](https://github.com/luc-git)
|
||||
|
||||
Using preloaded custom textures is usually quite taxing on the system RAM, especially if you don’t have much to begin with. Loading can be very slow and, at times, even freeze your entire PC!
|
||||
|
||||
By adding a loading screen, you can now track the progression of your preloaded custom textures as your game boots. It also works as an indicator to let your PC know that the app has not frozen, and to not enter it into a “not responding” state. Additionally, this solves the issue of Citra’s inability to be stopped whilst preloading custom textures, which is handy if you need to stop it for any reason whatsoever.
|
||||
|
||||
### Rasterizer cache refactor v2 ([#6479](https://github.com/citra-emu/citra/pull/6479)) by [GPUCode](https://github.com/GPUCode)
|
||||
## Add MMPX texture filter ([#6564](https://github.com/citra-emu/citra/pull/6564)) by [stuken](https://github.com/stuken)
|
||||
|
||||
It's a given that all great movies get a sequel. And because the first refactor was so good, we decided to make a second one! Well, not quite, but we promise this one is worthwhile too. More specifically, it contained the last pieces needed to fully abstract the video core from OpenGL, fixed a handful of regressions from the first one, and even provided some performance improvements.
|
||||
|
||||
Due to the large amount of changes introduced by the previous PR, it was natural for some regressions to slip through the cracks. As we learned the hard way, messing with many parts of the GPU emulation at the same time can result in strange bugs. For example, players of Digimon World Re:Digitize: Decode [reported](https://github.com/citra-emu/citra/issues/6481) that some models went missing after the merge, which was caused by an erroneous change to the OpenGL viewport.
|
||||
|
||||
{{< sidebyside "image" ""
|
||||
"digimonbroke.png=Where are you little monster?"
|
||||
"digimonfix.png=Oh, here!" >}}
|
||||
|
||||
Next, let's talk about Disney. Not the company, but a pretty obscure game they made for the Nintendo 3DS called Disney Art Academy, where you get to draw Mickey Mouse and his friends using the touchscreen and stylus. Given that the core gameplay mechanics require use of the touchscreen and stylus, not many people choose to emulate this title. So we were surprised when a bug report came in, stating that the game had become completely broken after the first refactor.
|
||||
|
||||
{{< figure src="disneybroke.png"
|
||||
title="This will haunt our dreams..." >}}
|
||||
|
||||
After some digging, GPUCode found out that the new mipmap implementation was the culprit that robbed Mickey of his face. To go into more detail, texture downloads were not adjusted to account for multi-level surfaces and thus readbacks of these surfaces did not function correctly. Rendering and reading back from multi-level surfaces is quite unusual and not something we often see in games. Regardless, we are happy it was reported to us so that we could promptly fix it!
|
||||
|
||||
{{< figure src="disneyfix.png"
|
||||
title="Mickey got his face back!" >}}
|
||||
|
||||
Alright, what about the performance improvement then? Indeed, by changing the data structure used to store surfaces, Citra is now able to cache and search for them more quickly and efficiently. The old interval map was ditched in favour of a simple page table. Memory locality has also been improved by taking [inspiration](https://github.com/citra-emu/citra/blob/master/src/common/slot_vector.h) from [yuzu](https://yuzu-emu.org/)'s texture cache. All in all, this change should yield a couple of extra frames in games that perform many cache operations and especially in cases where interval map lookups would [slow](https://github.com/citra-emu/citra/pull/5183) things down.
|
||||
|
||||
### Add MMPX texture filter ([#6564](https://github.com/citra-emu/citra/pull/6564)) by [stuken](https://github.com/stuken)
|
||||
|
||||
What's better than 5 texture filters? Well, how about 6! Introducing the MMPX texture filter, implemented by first time contributor, [stuken](https://github.com/stuken).
|
||||
What's better than 5 texture filters? Well, what about 6! Introducing the MMPX texture filter, implemented by first time contributor, [stuken](https://github.com/stuken).
|
||||
MMPX is a texture filter centered around the preservation of those classic pixel art styles we typically see in 8- and 16-bit era video games. Sprites, fonts, you name it, it’s been given a sweet pixel art style with this new texture filter!
|
||||
|
||||
This new texture filter can be enabled in `Emulation -> Configure -> Graphics -> Renderer` (`Citra -> Preferences` on macOS).
|
||||
|
||||
{{< single-title-imgs-compare
|
||||
"Left: unfiltered, Right: MMPX"
|
||||
"./none.png"
|
||||
"./mmpx.png"
|
||||
>}}
|
||||
{{< juxtapose id="e103936e-1122-11ee-b5bd-6595d9b17862" >}}
|
||||
|
||||
# Audio
|
||||
|
||||
### Implement OpenAL backend ([#6450](https://github.com/citra-emu/citra/pull/6450)) by [Steveice10](https://github.com/Steveice10)
|
||||
## Implement OpenAL backend ([#6450](https://github.com/citra-emu/citra/pull/6450)) by [Steveice10](https://github.com/Steveice10)
|
||||
|
||||
OpenAL, or in Citra's case a variant of OpenAL, OpenAL Soft, is an audio API designed for efficient rendering of multichannel audio.
|
||||
OpenAL is an audio API designed for efficient rendering of multichannel three-dimensional positional audio. Basically, this API adds realism back to game audio by simulating attenuation and material densities. Attenuation is the degradation of sound over distance in a real world setting, due to factors such as room acoustics and alike, while material density relates to how sounds interact with different materials in a given space.
|
||||
|
||||
It supports a wide variety of a platforms and can now be used in case Cubeb, our default audio backend, fails for any reason. To get this working in Citra, though, a few things had to be changed first.
|
||||
In Citra, however, we do not use this for positional audio. It is there just in case Cubeb, our default audio backend, fails for any reason. To get this working in Citra, though, a few things had to be changed first.
|
||||
|
||||
Before this PR, the input audio settings UI assumed that only the Cubeb backend would be used, and, unlike output, did not have a proper selector for other options. The input UI was edited to allow “Real Device (OpenAL)” to be selected, along with “Real Device (Cubeb)” as before.
|
||||
By changing these UI options, along with internal code cleanup to make managing output and input devices more consistent, we can improve Citra’s portability as a whole. We also use OpenAL Soft, as it supports iOS, while Cubeb does not.
|
||||
Citra uses an implementation of OpenAL called OpenAL Soft. By changing these UI options, along with internal code cleanup to make managing output and input devices more consistent, we can improve Citra’s portability as a whole. We also use OpenAL Soft, as it supports iOS, while Cubeb does not.
|
||||
|
||||
### Implement Apple AudioToolbox AAC decoder ([#6510](https://github.com/citra-emu/citra/pull/6510)) by [Steveice10](https://github.com/Steveice10)
|
||||
|
||||
Apple devices, like Macs and iPhones, use a framework called AudioToolbox to provide interfaces for recording, playback, and stream parsing. This framework can be used to encode and decode different audio formats, such as AAC.
|
||||
AAC audio might be something you’re already familiar with in Citra. It was a big reason as to why Pokémon X and Y couldn’t be played properly for many many years. But thankfully, that hasn’t been an issue for a while now!
|
||||
Apple devices, like Macs and iPhones, use a framework called AudioToolbox to provide interfaces for recording, playback, and stream parsing. This framework can be used to encode and decode different audio formats, such as AAC
|
||||
AAC audio might be something you’re already familiar with in Citra. It was a big reason as to why Pokemon X and Y couldn’t be played properly for many many years. But thankfully, that hasn’t been an issue for a while now!
|
||||
|
||||
By implementing an AAC decoder backend using the AudioToolbox library, we are able to eliminate the FFmpeg dependency on macOS. And, yes, Pokémon X and Y still work on macOS with this change.
|
||||
By implementing an AAC decoder backend using the AudioToolbox library, we are able to eliminate the FFmpeg dependency on macOS. And, yes, Pokemon X and Y still work on macOS with this change.
|
||||
|
||||
### Dynamically load fdk-aac and FFmpeg at runtime ([#6570](https://github.com/citra-emu/citra/pull/6570)) by [Steveice10](https://github.com/Steveice10)
|
||||
|
||||
This PR allows Citra to dynamically load the fdk-aac and FFmpeg libraries. These are difficult to distribute due to licensing reasons, but necessary to support features like AAC audio on Linux.
|
||||
This PR introduces a cross-platform library loading utility, as Citra supports many different platforms, as well as dynamically loading both fdk-aac and FFmpeg.
|
||||
|
||||
This also allows for the Linux AppImages (Yeah, we have those now. More on those later!) to use AAC decoding, so long as the required libraries are already installed on the system. As mentioned just above, Pokémon X and Y rely on AAC audio for the game to have any audio in the first place, and now this works on the AppImages too!
|
||||
This allows for the Linux AppImages (Yeah, we have those now. More on those later!) to use AAC decoding, so long as the required libraries are already installed on the system. As mentioned just above, Pokemon X and Y rely on AAC audio for the game to have any audio in the first place, and now this works on the AppImages too!
|
||||
|
||||
However, this change also has an implication for those who use the built-in video dumper. To use the video dumper, you’ll now have to install FFmpeg yourself, from either their official website or via your package manager of choice.
|
||||
However, this change also has an implication for those who use the built-in video dumper. To use the video dumper, you’ll now have to install FFmpeg yourself, from either their official website or via your package manager of choice
|
||||
|
||||
# Miscellaneous
|
||||
|
||||
### Migrate to Qt6 ([#6418](https://github.com/citra-emu/citra/pull/6418),[#6435](https://github.com/citra-emu/citra/pull/6435),[#6682](https://github.com/citra-emu/citra/pull/6435)) by [Steveice10](https://github.com/Steveice10)
|
||||
|
||||
Out with the old and in with the new! Citra has now migrated to Qt6, which brings with it many benefits such as improved [HiDPI support](https://doc.qt.io/qt-6/highdpi.html#conceptual-model), reworked [multimedia libraries](https://doc.qt.io/qt-6/qtmultimedia-changes-qt6.html), as well as better [styling support for Windows](https://www.qt.io/blog/dark-mode-on-windows-11-with-qt-6.5). Needless to say, quite a few changes were needed to be able to support this new version, with the camera implementation being one of the most challenging parts due to the aforementioned multimedia changes. As a result of this change, it's important to mention that, alongside other projects like [Dolphin](https://el.dolphin-emu.org/blog/2022/07/07/dolphin-progress-report-may-and-june-2022/?cr=el), Citra has now dropped support for Windows 7, Windows 8, and 8.1, with Windows 10 becoming the minimum required version. A dwindling user base, combined with security concerns due to lack of regular security updates, have contributed to our decision to make the jump to Qt6, and drop support for these operating systems to focus on their more modern successors.
|
||||
|
||||
The changes don't stop there. With the introduction of Qt6, Steveice10 also completely reworked the way Qt dependencies are handled. Instead of needing to manually build and package Qt releases on our [ext-windows-bin](https://github.com/citra-emu/ext-windows-bin), Citra's build system now uses [aqtinstaller](https://github.com/miurahr/aqtinstall), which automatically downloads prebuilt binaries directly from Qt's servers. An added bonus is that we also get more flexibility when it comes to upgrading or adding new Qt libraries!
|
||||
|
||||
### Move CPU speed slider to debug tab and Report Compatibility to help menu ([#6250](https://github.com/citra-emu/citra/pull/6250)) by [FearlessTobi](https://github.com/FearlessTobi)
|
||||
|
||||
One of the more common issues our Citra support team comes across is users configuring the CPU Clock Speed slider to be either insanely high or low causing their games to freeze. As changing the CPU Clock Speed is very unstable, a warning about this exact issue is given in the UI to deter people from changing it, but that hasn’t stopped some users from messing with this setting anyways, nor some misinformed content creators from recommending their viewers play with it
|
||||
@@ -485,27 +403,27 @@ This PR adds a simple popup to explain to the user that GBA Virtual Console ROMs
|
||||
|
||||
Recently added to Citra, the per-game settings bring a new way to configure the settings of Citra on a game-by-game basis. However, not all settings were added with this in one go, as we were unsure which settings most users would find relevant to have here.
|
||||
|
||||
After hearing your feedback, we decided to add most of the graphical enhancement options to the per-game settings. This includes features such as the resolution upscaling, custom textures, texture filters, and the options for the screen layout. This way, you have many more ways to customize your games to your heart's content, without having to change the global settings around every time you swap games!
|
||||
After hearing your feedback, we decided to add most of the graphical enhancement options to the per-game settings. This includes features such as the resolution upscaling, custom textures, texture filters and the options for the screen layout. This way, you have many more ways to customize your games to your heart's desires, without having to change settings around for each individual game!
|
||||
|
||||
On top of this, we also moved the cheats section to the per-game settings instead of being in the global settings. By being available in the per-game settings, cheats can be managed more easily, and are now configurable when a game is not running.
|
||||
On top of this, we also moved the cheats section to the per-game settings instead of being in the global settings. By being available in the per-game settings, cheats are able to be managed more easily for each game they are for, and are now configurable when a game is not running.
|
||||
|
||||
{{< figure src="cheats.png"
|
||||
title="Look, Ma! New settings!" >}}
|
||||
title="" >}}
|
||||
|
||||
### Add consolidated GodMode9 key dumping script ([#6396](https://github.com/citra-emu/citra/pull/6396)) by [Steveice10](https://github.com/Steveice10)
|
||||
## Add consolidated GodMode9 key dumping script ([#6396](https://github.com/citra-emu/citra/pull/6396)) by [Steveice10](https://github.com/Steveice10)
|
||||
|
||||
Something a bit different here… we’ve made our own GodMode9 dumping script!
|
||||
|
||||
If you’re somehow unaware, GodMode9 is a homebrew full-access file browser for the 3DS, allowing you access to pretty much everything on the console. This app is vital for playing games in Citra, as you must use this to dump your games, updates, DLC, and anything else you may want from your 3DS. GodMode9 can utilize dumping scripts to easily dump a bunch of things at once that the user may want, such as how ThreeSD works.
|
||||
If you’re somehow unaware, GodMode9 is a homebrew full access file browser for the 3DS, allowing you access to pretty much everything on the console. This app is vital for playing games on Citra, as you must use this to dump your games, updates, DLC and anything else you may want from your 3DS. GodMode9 can utilize dumping scripts to easily dump a bunch of things at once that the user may want, such as how the infamous ThreeSD works.
|
||||
|
||||
This script is used to dump all the keys needed for Citra into one file, which simplifies things a lot. In the past, you would have to dump many different files such as `Boot9`, `Sector0x96`, and `NATIVE_FIRM` just to get encrypted games running on Citra.
|
||||
Now, with the new system file download option through the Nintendo Update Service (NUS) in Citra, which relies on encryption keys in order to be used, it was a good time to find a way to streamline this dumping process once and for all.
|
||||
This script is used to dump all the keys needed for Citra into one file, which simplifies things a lot. In the past, you would have to dump many different files such as `Boot9`, `Sector0x96` and `NATIVE_FIRM` just to get encrypted games running on Citra.
|
||||
Now with the new system file download option through the Nintendo Update Service (NUS) in Citra, which relies on encryption keys in order to be used, it is best time to find a way to streamline this dumping process for once and for all.
|
||||
|
||||
This new dumping script loosely follows the existing aes_keys.txt format which is supported by Citra, but adds a few new secrets that will be needed for things such as encrypted Amiibo support. This ensures that whatever is needed for use in Citra will be dumped with ease using this script.
|
||||
|
||||
The download link and instructions for using this dumping script can be found on our [AES keys guide](https://citra-emu.org/wiki/aes-keys/). We hope that this will help make your Citra setup experience just that little bit smoother!
|
||||
|
||||
### Add Citra AppImage builds ([#6404](https://github.com/citra-emu/citra/pull/6404)) by [TGP17](https://github.com/TGP17)
|
||||
## Add Citra AppImage builds ([#6404](https://github.com/citra-emu/citra/pull/6404)) by [TGP17](https://github.com/TGP17)
|
||||
|
||||
An AppImage is a format for distributing portable software on Linux in a compact and simple way. AppImages don’t require any outside installation, and can just be run as is. This makes it very easy to use different programs on Linux, especially to those who are new to the operating system, as using the CLI can be intimidating or just plain time consuming.
|
||||
|
||||
@@ -517,40 +435,38 @@ Nowadays, Citra’s development has come a long way to where an AppImage is a fe
|
||||
Carrying on with the theme of common errors from users… broken save states…
|
||||
Pretty much every Citra user has seen this at some point. You save your game using save states, update Citra and… what? My save is now broken? How did this happen?
|
||||
|
||||
To give a short summary of what happens, save states don’t just save your game, they save the entire state of Citra. Kinda in the name there. When an update is pushed to Citra that changes the state, the previous save states become invalid. This is why it is so important that you do not rely on save states to save your game progression and that you frequently save in-game.
|
||||
To give a short summary of what happens, save states don’t just save your game, they save the entire state of Citra. Kinda in the name there. When an update to Citra that changes the state happens, the previous save states become invalid. This is why it is so important that you do not rely on save states to save your game progression and that you always save in-game.
|
||||
|
||||
Unfortunately, many people do not realize this. Which causes a lot of distress at lost progression and a lot of frustration fiddling around with older builds to get the saves working again. Simple solution? Warn the people of what might happen when using save states. At the very least, this might help people to not lose their progress.
|
||||
Unfortunately, many people do not realize this. Which causes a lot of distress at lost progression and a lot of frustration fiddling around with older builds to get the saves working again. Simple solution? Warn the people of what might happen when using save states. At least that will help people to not lose their progress… right…?
|
||||
|
||||
{{< figure src="savestate.png"
|
||||
title="Don't skip this, it's important!" >}}
|
||||
title="" >}}
|
||||
|
||||
### yuzu ports by [Morph1984](https://github.com/Morph1984) and [FearlessTobi](https://github.com/FearlessTobi)
|
||||
## yuzu ports by [Morph1984](https://github.com/Morph1984) and [FearlessTobi](https://github.com/FearlessTobi)
|
||||
|
||||
### Enable High DPI fixes for Qt >= 5.14 ([#6262](https://github.com/citra-emu/citra/pull/6262)) originally by [Morph1984](https://github.com/Morph1984)
|
||||
|
||||
On higher DPI monitors, any information window, such as the game compatibility reporting tool, would be scaled incorrectly, resulting in massive text size that could not be read due to it getting cut off.
|
||||
On higher DPI monitors, any information window, such as the game compatibility reporting tool, would be scaled incorrectly, resulting in massive text size that could not be read due to it cutting off.
|
||||
By utilizing Qt’s new high DPI application attributes for scaling a window, paired with a heuristic to select an integer scale value dependent on the current screen resolution, the scaling issue that has plagued Citra for four and a half years is finally resolved!
|
||||
|
||||
### Port multiplayer related PRs from yuzu ([#6319](https://github.com/citra-emu/citra/pull/6319)) originally by [SoRadGaming](https://github.com/SoRadGaming) and [unfamiliarplace](https://github.com/unfamiliarplace)
|
||||
|
||||
Just a few multiplayer additions here for ease when playing multiplayer in Citra with your friends!
|
||||
Just a few multiplayer additions here for ease when playing multiplayer on Citra with your friends!
|
||||
|
||||
First off, we have support for hostnames and IPv6 when using Direct Connect! Direct Connect is used to, well, directly connect to someone without having to search through the multiplayer lobby or if they’re hosting unlisted! In the past, the only way to connect to an unlisted room was via an IP address.
|
||||
This wasn't ideal, as it requires knowing the exact IP address in order to connect. With this change, it allows for Citra to use a domain address, as well as IPv6, as an input method to connect to a multiplayer server.
|
||||
First off, we have support for hostnames and IPv6 when using Direct Connect! Direct Connect is used to, well, directly connect to someone without having to search through the multiplayer lobby, or if they’re hosting unlisted! In the past, the only way to connect to an unlisted room was via an IP address.
|
||||
This isn’t ideal, as it requires knowing the exact IP address to type in to connect. With this change, it allows for Citra to use a domain address, as well as IPv6, as an input method to connect to a multiplayer server.
|
||||
|
||||
And then we have an option to tidy up the multiplayer lobby a bit more, a toggle to hide empty rooms! Sick of shifting through each room manually to see if there is anyone to play with? Fret not, with a simple click of this button, you will be shown rooms that have at least one other person to play with!
|
||||
And then we have something to clean up the multiplayer lobby a little bit more, a toggle to hide empty rooms! Sick of shifting through each room manually to see if there is anyone to play with? Fret not, with a simple click of this button and you will be shown rooms that have at least one other person in to play with!
|
||||
|
||||
Both of these additions help make the multiplayer experience in Citra just that little bit better and allow you to enjoy playing with ease, which we all love.
|
||||
|
||||
# Conclusion
|
||||
|
||||
Well, that’s a wrap! It has been an incredible couple of months for Citra development. We are definitely picking up speed, the likes of which we have not seen here for years, and as promised, the progress reports are continuing.
|
||||
A massive thanks goes out to the Citra community, especially the developers. None of these achievements would have been possible without all of the people involved here keeping this emulator afloat. These reports give us the opportunity to showcase the talented people working on this project, so you best believe they’re going to be long!
|
||||
Well, that’s a wrap! It has been an incredible couple of months for Citra development. We are definitely picking up speed, the likes of which we have not seen here for years, and as promised, the reports are continuing.
|
||||
A massive thanks goes out to the Citra community, especially the developers. None of this shown here would have been possible without all of the people involved here keeping this emulator afloat. These reports give us the opportunity to showcase the talented people working on this project, so you best believe they’re going to be long!
|
||||
|
||||
If you want to support this project, we have a [Patreon](https://www.patreon.com/citraemu)! Donations to the Patreon go directly to our team to assist with obtaining hardware for testing and keeping our servers up and running. Donations are not required, but are greatly appreciated!
|
||||
|
||||
If you are looking to contribute to Citra or just want to get involved with our community, you can find us on our [Discord server](https://discord.com/invite/FAXfZV9) or on our IRC channel (#citra @ [Libera.Chat](https://libera.chat/)).
|
||||
|
||||
To those of you who made it to the end, thanks for reading! We have many more exciting things to tell you all about in the future, so stay tuned!
|
||||
|
||||
{{< imgs-compare-include-end >}}
|
||||
To those of you who made it until the end, thanks for reading! We have many more exciting things to talk to you all about in the future, so stay tuned!
|
BIN
site/content/entry/citra-progress-report-2023-q2/lle.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 111 KiB After Width: | Height: | Size: 598 KiB |
Before Width: | Height: | Size: 140 KiB |
Before Width: | Height: | Size: 701 KiB |
Before Width: | Height: | Size: 540 KiB |
Before Width: | Height: | Size: 501 KiB |
Before Width: | Height: | Size: 438 KiB |
Before Width: | Height: | Size: 100 KiB |
Before Width: | Height: | Size: 472 KiB |
BIN
site/content/entry/citra-progress-report-2023-q2/showcase.mp4
Normal file
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 213 KiB After Width: | Height: | Size: 1.9 MiB |
@@ -1,114 +0,0 @@
|
||||
+++
|
||||
date = "2023-09-15T22:00:00+01:00"
|
||||
title = "The Vulkan-o erupts - Citra Vulkan is here!"
|
||||
tags = [ "feature-update" ]
|
||||
author = "autumnburra"
|
||||
coauthor = "sleepingsnake"
|
||||
forum = 897225
|
||||
+++
|
||||
|
||||
Hey there, Citra fans! (We haven't used that one for a while, have we?)
|
||||
|
||||
You've all wanted it and we've heard your cries and pleas. Vulkan has arrived and is here to stay, available now in the latest Citra release!
|
||||
|
||||
# Why Vulkan?
|
||||
|
||||
Since the dawn of time — well, since Citra's creation — many, *many* users have requested we add support for the [Vulkan Graphics API](https://en.wikipedia.org/wiki/Vulkan.); providing better performance in many cases and better support on devices, especially Android. There's a lot to love, but oh boy, was it ever a challenge!
|
||||
|
||||
{{< sidebyside "image" ""
|
||||
"sm3dlogl.png=OpenGL on Intel Core i3-1005G1. FPS: 75 Speed: 125%"
|
||||
"sm3dlvk.png=Vulkan on Intel Core i3-1005G1.FPS: 115 Speed: 193%" >}}
|
||||
|
||||
Vulkan support is also becoming a standard feature across many emulators, such as [Dolphin](https://dolphin-emu.org/), [Ryujinx](https://ryujinx.org/), [RPCS3](https://rpcs3.net/), [yuzu](https://yuzu-emu.org/), and many others.
|
||||
As we've mentioned before, Citra is heading into the modern age. OpenGL is considered an ageing graphics API, with buggy and slow drivers, and performance bottlenecks. A modern graphics API like Vulkan is perfect for our vision of the New™️ Citra.
|
||||
|
||||
If you haven't read it already, we have posted a detailed teaser about Vulkan in Citra in our [2020 Q2 ~ 2023 Q1 Progress Report](https://citra-emu.org/entry/citra-progress-report-2023-q1/#surprise-announcement).
|
||||
We thoroughly recommend you give that a read, as it's a really good recap of the development of Vulkan at the time of writing.
|
||||
|
||||
# Where to get Vulkan
|
||||
|
||||
If you'd rather jump straight into the action, Citra with the Vulkan renderer can be found in the latest Nightly release, either as a [standalone build](https://github.com/citra-emu/citra-nightly/releases) or from our [installer](https://citra-emu.org/download/).
|
||||
|
||||
# What to expect
|
||||
|
||||
As with anything to do with emulation, nothing is ever perfect. Things are always evolving and changing, and this is no different.
|
||||
|
||||
## Android
|
||||
|
||||
Attention Android users! We have not forgotten about you! We are still here, making your gaming experience on mobile even better!
|
||||
|
||||
A very large number of Citra users currently use a phone with a Mali GPU. This isn't something specific to Citra users, the majority of phones currently on the market have them! Especially with Samsung phones, if you live anywhere in the world apart from the United States or China, there's a high chance you'll get one with a Mali GPU.
|
||||
|
||||
Sadly, these GPUs tend to have rather poor OpenGL ES drivers, so Citra's performance on them generally left a lot to be desired and bordered on unplayable for most 3DS titles. Performance improved significantly for these devices after some of the initial [rasterizer cache refactor](https://github.com/citra-emu/citra/pull/6375) work on our graphics backend was done, making many less demanding titles capable of reaching 100% emulation speed. However, many titles were still running short of full speed.
|
||||
|
||||
Now, these concerns can be laid to rest! Mali's vastly better Vulkan drivers allow for better, and smoother, gameplay when using Citra's Vulkan backend. You can now easily go beyond 100% emulation speed on most, if not all, games. And with the addition of asynchronous shader compilation, in-game stutter due to shaders building is greatly reduced, leaving you with a more seamless gameplay experience.
|
||||
|
||||
{{< mp4 src="glesvk.mp4" title="Just look at the difference!" >}}
|
||||
|
||||
If we could rewind to the terrible OpenGL ES drivers on Mali GPUs we mentioned before for a moment; another caveat of these drivers is the amount of bugs in them. This would cause graphical glitches in games, from characters being the wrong colors, to entire landscapes being rendered incorrectly.
|
||||
Of course, this would affect the gameplay just as much as poor performance would. Who wants to play a game if it doesn't even look right?
|
||||
Thankfully, this is another area of concern that has been fixed by the Citra Vulkan backend on Android.
|
||||
|
||||
Bringing us back to the first ever game Citra launched, The Legend of Zelda: Ocarina of Time 3D is one such game that has graphical glitches caused by the Mali OpenGL ES drivers fixed with Vulkan:
|
||||
|
||||
{{< mp4 src="oot3d.mp4" title="We've been waiting for you, Hero of Time." >}}
|
||||
|
||||
## macOS
|
||||
|
||||
Great news for macOS (Apple Silicon and Intel) users! Citra once again fully supports macOS devices!
|
||||
|
||||
"Well, what does that have to do with Vulkan?" one might ask...
|
||||
|
||||
The answer is a bit complicated.
|
||||
Citra used to require only OpenGL 3.3 in order to run, which macOS still technically supports. However, after many revisions of our graphics backend, that requirement was upped to at least OpenGL 4.3. Unlike all other major operating systems, Apple decided to deprecate OpenGL support. This means that macOS does not support anything beyond OpenGL 4.1, which doesn't meet Citra's new requirements. As such, Citra could no longer run on macOS.
|
||||
|
||||
"Does macOS support Vulkan then?" another might ask...
|
||||
|
||||
Sadly, the answer to that is a "no". Apple, in their infinite wisdom, decided to create a proprietary graphics API called "Metal", and wants all apps to use that instead. However, that would require us to create a graphics backend that is only relevant for macOS, and no other platform. Given Citra's cross-platform nature, that wouldn't be ideal. There is a solution though: [MoltenVK](https://github.com/KhronosGroup/MoltenVK). This is a translation layer that translates Vulkan calls into Metal calls. Through this translation, Citra can run on macOS once again!
|
||||
|
||||
To use Vulkan, go to `Citra > Preferences > Graphics > Advanced tab` and set the Graphics API option to `Vulkan`. Additionally, the long-standing white/grey-screen bug, that required you to resize your Citra window in order to see anything being rendered, has been fixed with this API!
|
||||
|
||||
## AMD
|
||||
|
||||
There is another group of users that will benefit greatly from Vulkan. Namely, Windows users with older AMD GPUs.
|
||||
|
||||
A while back, AMD massively improved their notoriously bad OpenGL drivers. This improvement saw those AMD GPU users, who were struggling to hit 100% emulation speed before, suddenly achieving up to 10 times that emulation speed. Whilst this was incredible news for AMD users, there was a caveat to this: only GCN 4.0 GPUs and newer received these improved drivers. For anyone using an older AMD GPU architecture, they are still stuck on the old, and really bad, OpenGL drivers.
|
||||
|
||||
Luckily for them, the Vulkan drivers on those GPUs are still pretty good! As such, they'll no longer have to deal with sub-par performance, and can even compete with the new kids in performance!
|
||||
|
||||
# What NOT to expect
|
||||
|
||||
Keep in mind that Vulkan is a very new, and very big, addition to Citra. There are bound to be many bugs and glitches that slipped through the cracks. However, we've tried to make sure that what renders properly in OpenGL, renders properly in Vulkan. If you find a title where that isn't the case, please do let us know! With your testing and reports, we'll keep working to improve our Vulkan backend!
|
||||
|
||||
Some quick notes:
|
||||
|
||||
- Do not expect Vulkan to fix old emulation bugs that are not related to graphics or rendering.
|
||||
|
||||
- Do not expect Vulkan to render games correctly that our OpenGL backend does not render correctly. Aside from OpenGL or Vulkan driver bugs, switching between the APIs shouldn't show any visual difference. If that _is_ the case for you, please report this to us!
|
||||
|
||||
- Do not expect Vulkan to be an improvement over OpenGL in every aspect, on every device. Whilst Vulkan provides better performance than OpenGL in most cases, that is not always the case.
|
||||
|
||||
- As of writing, Vulkan does not have full feature parity with our OpenGL backend. We will list some of the missing features below.
|
||||
|
||||
- Whilst Vulkan currently has a disk pipeline cache, as well as runtime shader caching, an actual Disk Shader Cache for it is not yet implemented. As such, you may still experience some shader stutter at the start of each session until that is properly implemented.
|
||||
|
||||
- Recording your gameplay using Video Dumping is not yet implemented.
|
||||
|
||||
- Texture Filtering and Post-Processing Shaders are not yet implemented.
|
||||
|
||||
As always, if you need support with anything, head to our [Discord server](https://discord.gg/FAXfZV9) or our [community forums](https://community.citra-emu.org/).
|
||||
|
||||
# Requirements
|
||||
|
||||
As with our OpenGL backend, we have minimum hardware requirements for running Vulkan.
|
||||
|
||||
Any device that supports Vulkan 1.1 or above will work with our Vulkan backend. Be it macOS, AMD, or Android. As long as your device supports this, you’re good to go!
|
||||
However, there is an exception for Adreno 5xx devices on Android, as these GPUs do not work with our Vulkan implementation at this time. We'll be working to fix this with future updates, so keep your eyes peeled!
|
||||
|
||||
# What's next?
|
||||
|
||||
As mentioned, our Vulkan backend does not yet have full feature parity with our OpenGL backend. Once that parity is achieved, we plan on giving you a much more technical article about the entire Vulkan backend, sure to satisfy the curious among you.
|
||||
|
||||
We hope this release excites you about the future of Citra as much as it excites us.
|
||||
Our greatest gratitude goes out to the countless developers involved in bringing Vulkan to Citra, but especially to [GPUCode](https://github.com/GPUCode). Without him, none of this would ever have been possible.
|
||||
We also express thanks to [Steveice10](https://github.com/Steveice10), who helped on the macOS side of things for the Vulkan release, and to [BreadFish64](https://github.com/BreadFish64) for his expertise with Vulkan from his previous attempt to bring Vulkan to Citra.
|
Before Width: | Height: | Size: 729 KiB |
Before Width: | Height: | Size: 751 KiB |
@@ -2,6 +2,6 @@
|
||||
title = "Help"
|
||||
+++
|
||||
|
||||
User documentation on how to use Citra and frequently asked questions can be found here. Information for developers can be found on the [wiki](https://citra-emu.org/wiki/faq/).
|
||||
User documentation on how to use Citra and frequently asked questions can be found here. Information for developers can be found on the [developer wiki](https://citra-emu.org/wiki/faq/).
|
||||
|
||||
If you would like more information on a subject, or you're having trouble, support is offered in our [Discord server](https://citra-emu.org/discord/).
|
||||
|
@@ -3,54 +3,18 @@ title = "Custom Textures"
|
||||
description = "Custom texture features for displaying custom graphics packs."
|
||||
+++
|
||||
|
||||
Citra has the ability to dump game textures and load custom texture packs. Game textures will be dumped as **`.png`** files. Texture packs may contain either **`.png`**, **`.dds`** or **`.ktx`** files. Supported compression formats include **`BCn`** and the various **`ASTC`** block variations.
|
||||
Citra has the ability to dump game textures and load custom texture packs. Currently, only **`.PNG`** files are supported, but it is expected that more formats will come in the future.
|
||||
|
||||
## Instructions for dumping textures
|
||||
|
||||
* Open `Emulation > Configure...` in Citra's menu and go to `Graphics > Enhancements`.
|
||||
* Enable **`Dump textures`** and click **`OK`**.
|
||||
* Now open a game of your choice, and start playing. As you keep playing, the textures used by the game will be dumped as **`.png`** files.
|
||||
* Now open a game of your choice, and start playing. As you keep playing, the textures used by the game will be dumped as **`.PNG`** files.
|
||||
- Right-click on your game in the games list and select **`Open Texture Dump Location`** to open the dump folder.
|
||||
- The dump folder will contain a template **`pack.json`** file, that is used for configuration options. This file **must** be copied in the load folder.
|
||||
|
||||
## Instructions for replacing textures
|
||||
|
||||
* Right-click on your game in the games list and select **`Open Custom Texture Location`** to open the folder where custom textures will be loaded from.
|
||||
* Place your custom texture **`.png`** files in the folder.
|
||||
* Place your custom texture **`.PNG`** files in the folder.
|
||||
* In `Emulation > Configure... > Graphics > Enhancements`, enable **`Use Custom Textures`** and click **`OK`**.
|
||||
- Additionally, if you want your custom textures to be pre-loaded to RAM, enable **`Preload Custom Textures`** as well. This will help improve the performance but will also increase memory usage.
|
||||
|
||||
## Texture dumping
|
||||
|
||||
Citra will dump textures when they are used by the game and uploaded from the guest VRAM to the host memory. Dumped textures may only have power-of-two dimensions in order to avoid dumping host framebuffers.
|
||||
|
||||
The texture dumper will write a template **`pack.json`** file in the dump directory, which should be copied in the `load` folder when testing the texture pack. By default, textures will be dumped using the new hashing method. If a texture pack exists in the load folder, the dumper will use the same hashing method as that pack. Regardless of the hashing method, packs should still load correctly on any recent build of Citra. For any concerns regarding pack compatibility, possible breakages or feature requests please contact us either on [GitHub](https://github.com/citra-emu/citra/issues/) or on our [Discord server](https://citra-emu.org/discord/), as this is still a very new feature.
|
||||
|
||||
The filename of dumped textures is comprised of various information about the guest texture. For example, the filename **"tex1_256x256_543624189C94B105_12_mip0.png"** includes the guest texture dimensions **256x256**, the texture hash **543624189C94B105**, the guest pixel format **12** and the mipmap level of the texture **mip0**
|
||||
|
||||
## Pack configuration
|
||||
|
||||
The custom textures rework introduced a new json configuration file for texture packs, which is used to distinguish between old and new packs. It contains information about the pack such as name, author, as well as other configuration options like the used hash format, automatic mipmap generation and control for texture flipping. The latter two options are **unsupported** when compressed texture formats are used.
|
||||
|
||||
The new hashing option is recommended for new texture packs and is enabled by default. Advantages include faster hashing, as it requires less input data compared to the old hash and better compatibility between graphics APIs. In order to maintain compatibility with existing packs, loading the older hashing format is still fully supported. Usage of the old hash occurs either when the pack.json file does not exist in the texture pack load folder, or the **`use_new_hash`** option is disabled.
|
||||
|
||||
The configuration file also allows for hash mappings, which means textures can have arbitrary filenames that don't strictly adhere to the dumper naming guidelines. For example:
|
||||
|
||||
```
|
||||
"textures" : {
|
||||
"114BFC385ED72F15" : "logo.png"
|
||||
"22B8C43233F640AE" : "sky.png"
|
||||
}
|
||||
```
|
||||
|
||||
## Normal maps
|
||||
|
||||
The new custom texture system supports custom normal maps. This feature allows creators to add additional details to objects that would not be possible with only diffuse maps.
|
||||
|
||||
Normal maps have the same filename as their diffuse counterpart, with an added **`.norm`** prefix before the file extension. For example the normal map for dumped texture **texture.png** will be named **texture.norm.png**. This applies for all supported file types and for hash mappings.
|
||||
|
||||
There are limitations to when custom normal maps may be used. Most notably, the scene must enable fragment lighting. In the absence of lighting normal maps will **not** function and show the following error in the log:
|
||||
|
||||
```
|
||||
[ 24.086113] Render.OpenGL <Warning> video_core\renderer_opengl\gl_rasterizer.cpp:OpenGL::RasterizerOpenGL::BindMaterial:598: Custom normal map used but scene has no light enabled
|
||||
```
|
@@ -15,6 +15,5 @@
|
||||
"flTobi": {"key": "flTobi", "name": "FearlessTobi", "avatar": "https://community.citra-emu.org/user_avatar/community.citra-emu.org/fltobi/120/1390_2.png"},
|
||||
"autumnburra": {"key": "autumnburra", "name": "autumnburra", "avatar": "https://community.citra-emu.org/user_avatar/community.citra-emu.org/autumnburra/120/273091_2.png"},
|
||||
"sleepingsnake": {"key": "sleepingsnake", "name": "SleepingSnake", "avatar": "https://community.citra-emu.org/user_avatar/community.citra-emu.org/sleepingsnake/120/123364_2.png"},
|
||||
"emufan_4568": {"key": "emufan_4568", "name": "GPUCode", "avatar": "https://community.citra-emu.org/user_avatar/community.citra-emu.org/emufan_4568/120/298317_2.png"},
|
||||
"PabloMK7": {"key": "PabloMK7", "name": "PabloMK7", "avatar": "https://avatars.githubusercontent.com/u/10946643?v=4"}
|
||||
"emufan_4568": {"key": "emufan_4568", "name": "GPUCode", "avatar": "https://community.citra-emu.org/user_avatar/community.citra-emu.org/emufan_4568/120/298317_2.png"}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 682 KiB |
@@ -79,7 +79,7 @@
|
||||
<h1>Documentation</h1>
|
||||
<a href="/help/">Help Documents</a>
|
||||
<a href="/game/">Compatibility</a>
|
||||
<a href="/wiki/home/">Wiki</a>
|
||||
<a href="/wiki/home/">Dev Wiki</a>
|
||||
<a href="/wiki/faq/">FAQ</a>
|
||||
</div>
|
||||
|
||||
|
@@ -18,7 +18,7 @@
|
||||
<li class="index-3"><a href="/help/" title="Help">Help</a></li>
|
||||
<li class="index-4"><a href="/wiki/faq/" title="Frequently Asked Questions">FAQ</a></li>
|
||||
<li class="index-5"><a href="/game/" title="Game Compatibility">Compatibility</a></li>
|
||||
<li class="index-6"><a href="/wiki/home/" title="Wiki Homepage">Wiki</a></li>
|
||||
<li class="index-6"><a href="/wiki/home/" title="Wiki Homepage">Dev Wiki</a></li>
|
||||
|
||||
<li class="index-7 dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"
|
||||
@@ -27,9 +27,9 @@
|
||||
</a>
|
||||
|
||||
<ul class="dropdown-menu">
|
||||
<li class="index-1 first"><a href="/rules/" title="Community Rules">Rules</a></li>
|
||||
<li class="index-1 first"><a href="/rules/" title="">Rules</a></li>
|
||||
<li class="index-2"><a href="https://community.citra-emu.org/" title="Forums">Community Forums</a></li>
|
||||
<li class="index-3 last"><a href="/discord/" title="Discord Server">Discord Chat</a></li>
|
||||
<li class="index-3 last"><a href="/discord/" title="Discord Channel">Discord Chat</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<ul class="dropdown-menu">
|
||||
<li class="index-1 first"><a href="/screenshots/" title="Screenshots">Screenshots</a></li>
|
||||
<li class="index-2 last"><a href="https://www.youtube.com/channel/UC_dcdgzuapBtAY4ol3x-90Q"
|
||||
title="YouTube Channel">Videos</a></li>
|
||||
title="Youtube Channel">Videos</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
@@ -1,2 +0,0 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/juxtaposejs@1.1.6/build/js/juxtapose.min.js"></script>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/juxtaposejs@1.1.6/build/css/juxtapose.css">
|
@@ -0,0 +1,2 @@
|
||||
<iframe src="https://cdn.knightlab.com/libs/juxtapose/latest/embed/index.html?uid={{ .Get "id" }}"
|
||||
{{ if .Get "class" }}class="{{ .Get "class" }}"{{ else }}style="display:block; margin:auto; width:100%; height:45vh;" {{ end }}frameborder="0"></iframe>
|
@@ -1,15 +0,0 @@
|
||||
<figure>
|
||||
<div style="position: relative; padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden;">
|
||||
<video preload="auto" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;" controls>
|
||||
<source src="{{ .Get "src" }}" type="video/mp4">
|
||||
Your browser doesn't support mp4 video. :(
|
||||
</video>
|
||||
</div>
|
||||
{{ with .Get "title" }}
|
||||
<figcaption>
|
||||
<h4>
|
||||
{{ . }}
|
||||
</h4>
|
||||
</figcaption>
|
||||
{{ end }}
|
||||
</figure>
|
@@ -1,30 +0,0 @@
|
||||
{{ $title := .Get 0 }}
|
||||
{{ $originals := (.Page.Resources.ByType "image") }}
|
||||
<div class="columns is-bottom-marginless">
|
||||
<div class="column is-bottom-paddingless juxtapose">
|
||||
{{ range $param := last 2 .Params }}
|
||||
<!-- image -->
|
||||
{{ $items := split $param "|" }}
|
||||
{{ $src := (index $items 0) }}
|
||||
{{ $subtitle := (index $items 1) }}
|
||||
{{ $split_src := split $src "." }}
|
||||
{{ $extension := index $split_src (sub (len $split_src) 1) }}
|
||||
{{- if eq $extension "png" -}}
|
||||
{{ $original := $originals.GetMatch (printf "*%s" (path.Base $src)) }}
|
||||
{{ $resized_width := math.Min $original.Width 1024 }}
|
||||
{{ $resized := $original.Resize (print $resized_width "x q90 jpg" ) }}
|
||||
<img src="{{ $resized.Permalink }}" alt="{{ $title }}">
|
||||
{{- else -}}
|
||||
<img src="{{ $src }}" alt="{{ $title }}">
|
||||
{{- end -}}
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ with "title" }}
|
||||
<figcaption>
|
||||
<h4 style="text-align: center">
|
||||
{{ $title }}
|
||||
</h4>
|
||||
</figcaption>
|
||||
{{ end }}
|
@@ -1,4 +1,17 @@
|
||||
{{ define "main" }}
|
||||
<div class="alert alert-warning">
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<strong>Read First!</strong>
|
||||
</div>
|
||||
<div class="col-md-10">
|
||||
<p>The below wiki article is based on user submitted content.<br>
|
||||
Please verify <strong>all</strong> hyperlinks and terminal commands below!</p>
|
||||
See a mistake? Want to contribute? <a href="https://github.com/citra-emu/citra/wiki/{{ .File.BaseFileName }}/_edit/">Edit this article on Github</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>{{ .Title }}</h1>
|
||||
{{ .Content }}
|
||||
{{ end }}
|
||||
|