Emulation is often seen as this suspect gray area of gaming that is tolerated but always on the edge. There's a lot of negativity and questions around the merit and purpose of emulation. In contrast to that narrative, the overwhelmingly positive reaction to some of the features added the last few months, including heartfelt reactions from users, make all of the challenges and struggles so much easier.
As we drift further from the heyday of the GameCube and Wii, we've been seeing a greater impact not only on the past generations of gamers, but the current one. It was heartwarming to see long-time users able to play Four Swords Adventures with their kids or friends across the world. The gratitude we received from users finally able to try previously hard-to-access features in their favorite games was so appreciated. We love these games and consoles the same as you, and we want to make sure that they live on.
Sometimes with all the negativity in emulation, it's refreshing to have something that makes both the developers and the users happy. And while we'd love to revel in past accomplishments, there's still so much more work to be done. We graciously thank everyone for their kind words over the past few months, and hope you continue to enjoy using Dolphin Emulator. With that said, it is about time that we get started with the June and July Progress Report.
If you really want something, sometimes you have to go and make it happen yourself. And that's exactly what bonta did. He wanted to play Four Swords Adventures on netplay with friends and was more than willing to put forth the work to make it happen. In the process he integrated mGBA into Dolphin, worked with endrift on protocol bugs, and even fixed issues in other games to try and make it perfect for everyone. The end result? Every single Game Boy Advance (GBA) to GameCube connectivity game works in Dolphin. If you want to learn more about the GBA connectivity feature and its history, we wrote a huge article on it and even made a video demonstration.
For a major feature that includes integrating another whole emulator, it has been an incredibly smooth launch. We haven't seen any major regressions, and we only broke the Ubuntu/Android buildbot for a couple of hours. However, after getting a taste of the Integrated GBA, users have been asking for more features regarding it. And we do admit, some aspects were purposefully kept simple in order to try and make sure everything went smoothly with the initial merge. Since then, several major features were added based on feedback from users and some things that we noticed ourselves.
First up, developers grossly underestimated how many people would want to use the e-Reader. Being such a fringe feature, we added support for dragging/dropping e-Reader cards onto the emulator but didn't add any indication that it works into the GUI. After seeing numerous complaints and confusion, pokechu22 implemented e-Reader controls into the GUI.
Bigger changes were also added by bonta, who brought forth a slew of new options based on feedback from the initial merge. Two of them have to do with how the GBA is displayed. First of all, we've added the much requested always on top option. This makes it so that no matter which window you click, your Integrated GBA will always be visible. Secondly, we've added the ability to remove the Integrated GBA's borders, which can make fitting things onto a single monitor much easier.
Beyond just displaying things, bonta also added interframe blending to the GUI. This is a feature of mGBA used to remove flickering and jumpiness in titles that rely on the ghosting behavior from GBA screens. Because the NES has more vertical resolution than the GBA, the GBA NES emulator in Animal Crossing and Nintendo Puzzle Collection will render one set of pixels and then another on alternating frames and let the ghosting blend them together.
In addition to all of that, bonta, leoetlino, and JMC47 collaborated to port the Final Fantasy Crystal Chronicles Connectivity Patch to the Japanese and PAL regions of Final Fantasy Crystal Chronicles. This is particularly important because the Japanese version has features and bugs not present in the other regions, which speedrunners use throughout their runs. Note that the connectivity patch fixes a bug in the ROM that Final Fantasy Crystal Chronicles sends to the GBA. The bug makes reestablishing a connection in levels very difficult when timings are too perfect.
As one final note, please remember that GBA connectivity features are currently handled through the GBA BIOS. As such, using the Integrated GBA requires the user to have a GBA BIOS. Because the GBA BIOS is a copyrighted piece of software, it cannot be included with Dolphin, much like the GameCube IPL and the console DSP-LLE ROM. While a free replacement may be possible, none exist at this time. Thankfully, there are plenty of resources on how to dump a GBA BIOS from various handhelds, or even with a Game Boy Advance, GameCube Link Cable, and a GameCube/Wii!
When we left our heroes last time...
Techjar removed the extra rounding and the games started working again. And now we know to never touch Bounding Box ever aga-
And now we rejoin them...
After barely holding out against the Bounding Box onslaught on the eve of the last Progress Report, developers regrouped and planned a counter-attack at the heart of the Bounding Box menace in the days following. These final battles didn't have the grandeur of the previous battles; Bounding Box had already expended most of its resources and was left with only a fraction of the issues. This time, Techjar would ride alone onto the frontline with almost no resistance. His goal? Make Bounding Box work perfectly on every graphics backend and render correctly at every internal resolution. In the last battle, the D3D11 and D3D12 fronts had already been won, but OpenGL and Vulkan were still up in the air.
So what devious plot had conspired to take down OpenGL? Well, OpenGL has a quirk compared to all of the other APIs in Dolphin: It has a lower left origin. Every other backend uses an upper left origin which makes OpenGL render inverted in comparison. By now, developers know to invert values for OpenGL and Techjar was already doing that, albeit a bit too late. The values were being inverted after the conversion to pixel quads, resulting in some improper rounding. If you remember from last time, Bounding Box rounds to two-by-two groups of pixels called Pixel Quads, and doing this correctly was one of the key fixes that helped improve Bounding Box behavior. So rounding to the Pixel Quads incorrectly was defeating the whole purpose of the change! Fixing this oversight ended the issues in OpenGL.
Vulkan was a bit more difficult to analyze. Through messing with the code and disabling various optimizations, Techjar ascertained that something was wrong with Subgroup Reduction. This is an optimization that helps GPUs parallelize atomic operations. Atomic operations are operations that can't get interrupted by another thread once they have started and ensure sequential consistency when all of the threads finish. This is important, because if multiple warps (essentially threads) are operating on the same pixel at the same time and we're also doing comparisons on said pixel through Shader Storage Buffer Objects (SSBOs), it's very easy to end up with inconsistency and race conditions. Atomic operations ensure the values are correct and updated at the right time.
For those of you that are still following, all of this comes at a cost. Atomic operations have a lot of overhead. Modern GPUs love to work with highly paralellized workloads and this ends up forcing it to complete threads one at a time. Unfortunately, it's also the fastest way to emulate Bounding Box correctly.
That's where Subgroup Reduction comes in. It allows the GPU to do multiple atomic operations across many pixels and only update the values at the end of a particular group's calculations. By being able to run multiple atomic operations at once, this can greatly speed up Bounding Box emulation. The issue was that Dolphin was telling the GPU that a subgroup was finished when helper threads were still running, meaning that incorrect Bounding Box values were being read and written. The fix was to simply was take into account helper threads when reporting that a subgroup was finished. Unfortunately, by fixing all of these quirks we also fixed one of the funniest game issues we've seen in a long time.
So now every backend was working, right? This should have been the end, but Bounding Box would not concede without a fight. In the final batch of testing, we found out that the damn punies were broken at higher resolutions again! If you played Paper Mario: The Thousand-Year Door in Dolphin back in the old days, these little annoying bugs were the absolute bane of your existence. The fact that they just work in modern builds is something we take for granted considering just how annoying of a problem they once presented. Users were desperate enough to even make custom texture packs specifically to fix the Punies in Dolphin because the glitch was so damaging and there was no work-around!
The problem was slightly different now: 1x internal resolution actually worked. It was only higher resolutions that had a problem with these changes. While he could have just told people to use lower resolutions, Techjar himself was not happy with this outcome. This saga was started by him; his original Bounding Box adjustments were the very ones that broke Ultimate Spider-Man and sent JMC47 on the warpath. He knew that he had to be the one to finally end it.
Techjar dug in and found out that increased pixel precision from running in higher resolutions was causing problems. When there are more pixels, Dolphin wasn't getting the same exact center that it was at native resolution. The solution? Simply ignore all of the extra pixels and only use the center pixels.
So now we're fairly confident that this should be the last of the Bounding Box issues. In preparation for the Progress Report, every single bounding box game was tested on every backend at every internal resolution. In fact, during our testing, we even found out that one of the seven titles listed to use Bounding Box doesn't actually use Bounding Box. Speed Challenge has been forcing it on in the INI for over a decade, yet it doesn't even touch the Bounding Box registers. The game doesn't actually run in Dolphin, but JMC47 was able to hack up a build that could get it in-game so we could test it out.
So now our list of Bounding Box games falls to five. Yes, five. Turns out one of the other Bounding Box games was just an erroneous duplicate of Disney's Hide & Sneak in a different region. The other four are Paper Mario: The Thousand-Year Door, Super Paper Mario, Ultimate Spider-Man, Disney's Magical Mirror.
Branch Following is a big JIT optimization that allows Dolphin to make longer code blocks by inlining code from branches. This results in increased CPU performance in most games. Both the x86-64 JIT and the AArch64 JIT have this feature, but users noticed that the AArch64 JIT was having some problems with it. After seeing multiple reports of users forcibly disabling Branch Following, JosJuice started investigating the problem and bought one of the most popular afflicted games: Need for Speed: Carbon.
The issue ended up being a rather convoluted one to debug. The broken games would set up a case where Dolphin could follow a call, but not the return. With the BLR optimization enabled, Dolphin needs the host link register for the return address. This is normally not a problem, but if register pressure was high enough, it could opt to use the link register for something else. Without the host link register being intact, Dolphin would jump to somewhere invalid and potentially crash. Once JosJuice knew what was wrong, it was a relatively easy fix to make sure Dolphin locks the link register so that it can't get overwritten when it is still needed.
While having Branch Following enabled makes Dolphin's AArch64 JIT faster, how much it affects your device will depend on what the particular game is bottlenecked on. On Dual Core, the device may be completely limited by the GPU thread and not see any benefit whatsoever. In other cases, Branch Following can result in tremendous performance increases. Either way, users no longer have to worry about turning Branch Following off just to make their favorite games run.
When Nintendo launched the GameCube, they might have miscalculated a bit on how much memory games would need for their saves. The original 59-block memory cards were only 4Mbit and could only store a handful of saves. They were also rather slow, which is problematic with how big saves would get with later games on the system. To no one's surprise, Nintendo released bigger, faster offerings with the 251 (16Mbit) and 1019 (64Mbit) block memory cards. These cards gave players much more breathing room and sped up savetimes in games that would write large save files. The only real downside to using them should have been the hard limit of 127 savefiles; as the file system could not handle anything beyond that even if you had empty blocks! Unfortunately, reality doesn't always line up with expectations.
Being that these memory card sizes are so insignificant for modern storage devices, Dolphin's developers thought it would be best for users if the emulator defaulted to using the biggest possible memory card: a 2043-block monster that was only released by third parties such as datel. Unfortunately, due to bugs in numerous games, they won't recognize anything beyond a 251-block memory card as a valid saving device, even on console! To combat this, Dolphin had a hidden setting called Memcard251, that could be put into the INI files to force a 251-block memory card.
This was a rather nifty solution that fixed saving issues in these games without inconveniencing users. It affected the GCI Folder feature, too! Instead of having the saves on a separate memory card, they're all stored in one place. The difference is that when the GCI folder is constructed into the memory card at boot, Dolphin simply constructs a smaller one. And it wasn't stupid about how it used the space it had; GCI folders knows to pull in the savefile of Pikmin when launching Melee, and the savefile from Super Mario Sunshine when launching Metal Gear Solid: The Twin Snakes.
So you're probably wondering why this change replaces Memcard251 with something else, right? Well, Nintendo themselves decided to throw us a curveball with the Japanese version of Pokemon Box. While trying to solve the infamous adventure mode crash, we ended up seeing a lot of complaints that the Japanese version didn't work, and would get stuck on the main menu with an unreadable error.
If you're familiar with Japanese, you already know what it's telling us. This game only works with 59-block memory cards. Not due to any kind of bug, but due to a rather odd design decision. Our best guess is that because the game came with a 59-block memory card, Nintendo really only wanted you using the game with that card. Unfortunately, this left us in a rather tricky situation. We couldn't just globally change Memcard251 to Memcard59; those memory cards were so small that some of the bugged games would completely fill them up alone. We needed to do some serious changes for this one game.
Rather than hacking something up or putting an exception in the code, Techjar bit the bullet and rewrote the Memcard251 option to support arbitrary sizes that could be set on a per-game basis. So now for this one game, Dolphin has made its memory card size code support arbitrary sizes. Thanks, Nintendo.
Note: 5 blocks and one file of each memory card are dedicated to system data, so a 59-block memory card really has 64 total blocks with five you can never access. In addition, more games have been marked to use smaller memory cards to prevent saving issues. This includes SSX Tricky and SpongeBob SquarePants: Creature from the Krusty Krab both being forced to use 251-block memory cards.
Gladius is an unfortunately difficult game to emulate. One of Dolphin's biggest weaknesses is that both its CPU and GPU timing pipelines aren't close to cycle accurate. And getting better is going to be really difficult, especially without breaking more games or destroying performance. If something like cache hits are emulated, suddenly our CPU pipeline will be far too slow without emulating one of the missing features to make the CPU faster. These timing issues can be seen throughout games with rather minor consequences in most cases.
Gladius is a game that simply relies on better CPU/GPU pipeline timings than Dolphin has, and that makes it challenging to emulate. Smurf3tte decided to try and figure out exactly what was going wrong and see if there was another way to fix it. Rather than trying to make Dolphin more accurate, Smurf3tte opted to try and make Gladius more tolerant of Dolphin's limitations and succeeded. They patched out the race condition that made Gladius so difficult to run and left developers with a difficult quandary: Should this game patch be merged and enabled by default?
This isn't the first time a patch was developed to work around a game limitation. However, in the other situations, Dolphin was dealing with behaviors and issues that it will likely never to be able to emulate. Resident Evil 2, Resident Evil 3, and Casper's Scare School: Spooky Sports Day are good examples of this. They all rely on CPU data cache behaviors due to game bugs, and Dolphin can't emulate that without sacrificing so much performance that it wouldn't be worth it fo the average user.
Gladius is different; it isn't really doing anything special. Someday, Dolphin should be accurate enough to emulate it. That's what made considering this patch so much different than the others. In the end, it came down to three key factors:
- Even with correct emulation, Dual Core would have never run this game.
- There's no guarantee Dolphin's timings will ever be good enough to handle this game.
- Smurf3tte reverse engineered the problem so that we now know what needs to be done to emulate it correctly.
Since you're reading about this in the Progress Report, it's obvious that developers opted to merge the patch and make the game immediately playable. This patch affects the NTSC version of the game and is enabled by default in the latest development builds. Our hope is that this patch won't be necessary down the line, but even if that day comes it will still be useful as an option for users on weaker machines that need to use Dual Core.
Dolphin's DVD timing model is a point of pride for the project. While it's impossible to be perfect simply due to the fact that there's so much variance even on real consoles, Dolphin's DVD read timings usually fall around where an original Wii would rate. Which makes sense, as a majority of the timing results come from a first generation Wii DVD drive. That's why we found it odd when speedrunners from the Pitfall community reached out to us and told us that they had to use older builds for testing due to DVD timing problems in modern builds. The report was that things weren't just a little off, they were incredibly wrong in Pitfall: The Lost Expedition and its Wii port.
Their bisect brought us to a DVD timing change in 4.0-9019 that was hardware tested to be correct. One of the dangers of hardware testing is that sometimes you don't test enough and make assumptions to fill in the gaps. Most of the time this is fine, but on console there are tons of weird edge-cases that can crop up. Investigation proved that it indeed was. 4.0-9019 changed Dolphin so that it now ignored the buffer when seeking backwards. While we knew the DVD drive cached the current block, JosJuice checked the DVD read patterns of Pitfall: The Lost Expedition and found out that it was reading one block backwards. Once they knew that was the issue, they tested the behavior on console and indeed discovered that the previously read block was still cached, resulting in Dolphin being much slower than real hardware in this case. JosJuice rectified the issue by letting Dolphin cache the previously read block instead of just the current one.
It turns out fixing Happy Feet came at an incredible cost. Near the beginning of the year, smurf3tte fixed up Dolphin's JIT to correctly translate effective addresses to physical addresses for the dcbx family of instructions.
The original bug goes back to 2015 when an optimization to dcbx was implemented by degasus. It was rather simple; since most dcbi/dcbf/dcbst instructions are essentially NOPs in Dolphin, we could inline the checks that were part of the C++ function and skip calling into C++ most of the time. This assumption falls apart in Happy Feet because it uses these instructions with ARAM addresses rather than what games typically use: addresses to MEM1, mapped with the default BAT. Addresses mapped to ARAM are problematic because simple masking can't actually be used to convert effective addresses to physical addresses, so actually determining the real addresses is necessary. Simple enough to fix, right? smurf3tte reverted the broken optimization and restored the behavior to how it once was. Sure, having to call out to C++ code to check the addresses would be slow, but there's no way games would rely on these instructions to the degree it'd matter, right?
Tons of games from Arc Rise Fantasia to Pokemon Colosseum relied on these instructions enough to see extreme performance losses on loading and transitions between areas. With Arc Rise Fantasia and A Boy and his Blob these stutters would frequently occur during regular gameplay making them difficult to enjoy.
JosJuice was pulled away from more interesting projects to address this regression before the next (this) Progress Report. They reintroduced degasus's optimization, but changed it to actually look up the correct addresses without jumping to C++ code. This restores performance in all of those games while still being able to support the rare case of Happy Feet.
Mere days before the release of Skyward Sword HD, Pokechu22 finally solved the last major emulation mystery in Skyward Sword for Wii. In Dolphin, when looking at the many maps, they would appear much flatter and duller than on console. The map never worked perfectly, and its current status goes all the way back to a major graphics pipeline rewrite dubbed tev-fixes-new in 2014. Since then, nothing has affected it and hadn't been much hope toward fixing it.
Pokechu22 figured that the best way to solve what was wrong was to bisect it to the exact commit within tev-fixes-new to figure out what part of the rewrite changed rendering. It wasn't a particularly easy task as many of these commits do not compile or produce broken shaders, meaning Pokechu22 had to manually compile and repair these builds in order to actually get an exact bisect. But through this process and studying fifologs, they uncovered how the map was dynamically rendered and figured out exactly why it was broken in Dolphin.
It turns out that this commit swapped the shifts used for "bump alpha" and the indirect offset; per libogc, the indirect offsets are the high bits and the bump alpha comes from the low bits. (This is further confounded by bump alpha being only 5 bits; in the most common ITF_8 case where bump alpha and the indirect offset are both from the same value, it seems like it does use the top 5 bits, though I haven't hardware tested it). The old code handled it mostly correctly, but because it was trying to implement bit manipulation using floats, it had various rounding issues (and was hard to understand).
If you care to know more about how the Skyward Sword map renders, Pokechu22 wrote a tremendously detailed examination of how it renders that will satiate even the most curious of minds. For the rest of us, this is one of the final oddities from tev-fixes-new. The other one, ironically enough, was in another Zelda game: The Legend of Zelda: Twilight Princess. Speaking of which...
The Legend of Zelda: Twilight Princess was a poster child of the now infamous tev-fixes-new graphics rewrite. It was one of the games that really showed off just how important integer math was for emulating the GameCube/Wii GPU, and why developers made the decision despite how unpopular it was at the time. There was just so many important scenes in the game marred by graphical glitches that, while the game was playable, it was a very different experience in Dolphin. It was even used in the header for the release article!
While tev-fixes-new was undeniably a net gain, it also caused a few regressions in rendering that we originally missed. Reported four years after the initial merge, it turns out that the skin and eyes on certain characters were misbehaving and the culprit was this massive set of changes. The easiest place to see these problems were in Zora's domain, where the Zora people showed very obvious defects.
So what exactly happened that could have eluded our sight for so many years? Well, it turns out this is a bit of a game bug. The game is supplying a texture scale value that is much higher than what it is actually using. However, when tested on the GameCube/Wii hardware, the scale value was being masked to something more reasonable. For example supplying a scale value of 47 is the same as supplying one of 15, resulting in a scale factor of 215-17 = 2-2. Correcting for this masking behavior fixes various blending issues throughout Twilight Princess.
While The Legend of Zelda: Twilight Princess may have been home to the most obvious bugs caused by this defect, Dolphin's FifoCI automated testing infrastructure also found that this change affected two other games. Firstly, Wind Waker saw some very minor rounding changes on some textures, but Sunshine had something more interesting show up.
That's right, the bubbles in Super Mario Sunshine are finally rendering correctly! All of these changes have been hardware verified with the hardware fifolog player. While it was left in disrepair for many years, Pokechu22 revived neobrain's's old project. One of the interesting things is that we thought the bubbles were fixed all the way back in 2014, because they were even more broken in floating point math.
Looking through the Pixel Processing Problems blog post, seeing just how much it fixed is outright stunning. But there's another side of things that re-reading the article will reveal if you're an avid reader of the blog: A lot of those games still had minor problems even in the featured screenshots showing off why tev-fixes-new was important! Still when compared to how Dolphin rendered before tev-fixes-new, it represents an important turning point in development philosophy that shifted where Dolphin was heading. And now with these last two changes from Pokechu22 all of the known regressions from tev-fixes-new are fixed, and that chapter of Dolphin can finally be put to rest.
Sometimes the best laid plans blow up in your face. For Billiard, this happened a couple of month ago when they tied Wii Remote reporting rate to whether the Wii Remote Speaker was enabled. Dolphin currently has a hack to duplicate Wii Remote Data when using Emulated Bluetooth. This is because we can't enter the 200 Hz Sniff Mode the same way as on a real Wii. Without running at true 200 Hz, audio gets extremely garbled, but Dolphin does its best by duplicating packets in the 100 Hz communication that we can get on standard Bluetooth stacks. If running at 100 Hz, games don't tend to report Wii Remote audio at all.
Unfortunately, a few games do not like this packet duplication whatsoever, including Sonic and the Secret Rings and Jett Rocket. In the worst case, certain motions would never read. In the best case? They were just harder to control than usual.
Billiard thought that by tying the duplication to an already existing option, we could easily fix this problem without impacting users. Since we needed the 200 Hz for Wii Remote audio, the idea was to tie the duplication to that setting. It was a good idea in theory and seemed to fix Sonic and the Secret Rings and Jett Rocket.
Then everything went sideways. Rampant reports of flickering pointers and broken motions in other games flooded the support forums and social media. And this wasn't just shovelware, Super Mario Galaxy was among the many titles that thought 100 Hz reporting was because of bad signal quality. In order to prevent signal quality from impacting gameplay, these games would disable the Wii Remote pointer, ignore motions, or try to disconnect and reconnect the Wii Remote. The only way to fix this would be to enable Wii Remote Audio to get the 200 Hz duplication enabled. For users that had no knowledge of what any of the technical details behind these options, it was a rather confusing solution. Most of them didn't want Wii Remote audio on in the first place because it sounded so bad because of the required duplication.
To rectify this problem, we've now separated packet duplication off into its own hidden setting. The idea is to keep this problem a silent process from the users and enable it on a per-game basis for games that we know are broken with packet duplication. The first two games where we've done this are the aforementioned Sonic and the Secret Rings and Jett Rocket but there are likely other games out in the wild that need this. If you run into a game where you're using a Real Wii Remote but can't get certain motions to work, try adding the setting RealWiiRemoteRepeatReports = False to the GameINI and let us know if it fixes it.
Note: Bluetooth Passthrough is able to successfully enter 200 Hz Sniff mode, and does not suffer from any of these issues.
Sometimes, the smallest of differences can create the biggest of issues. If you are a fan of The Sims 2: Castaway, Dolphin might seem like a match made in heaven. With CPU overclocking features, you can make the game run far better than it ever did on console thanks to its dynamic framerate and the various control options can make for a more comfortable playthrough. However, your vacation would go wrong roughly fifteen minutes in, as Dolphin would suddenly crash without warning just before first nightfall.
Having seen this issue reported several times, JMC47 reluctantly looked into it. Because these crashes had been described as random, that made it a rather annoying issue to reproduce. Spending a long time playing a single game with no idea how to trigger the problem can feel like a waste of time. But it had to be done. Thankfully, this crash wasn't random but was instead on a timer. After about 15 minutes, the game crashed just as the issue reports had described. Upon rerunning the test several times, he found that the crash happened at exactly the same time on the first night, making it fairly easy to predict when it was going to crash for examination. The address that the game spit out pointed to a potential DSP Accelerator issue, so he again roped leoetlino in to investigate.
One sanity test that leoetlino requested to be done was to make sure that the DSP-LLE didn't fix the issue. Though most of the DSP Accelerator code is similar between DSP-HLE and DSP-LLE, it would make debugging the issue so much easier if we had a working model we could examine. Shockingly enough, DSP-LLE did not crash! This meant the issue was most certainly somewhere in DSP-HLE, but where?
At that point, leoetlino dumped the same AXWii µcode (microcode) from another game and began reversing how it worked and what it was doing. He then compared data dumps and logs from The Sims 2: Castaway when running on DSP-HLE and DSP-LLE to try and look for differences. In order to get a leg up in examining the µcode, leoetlino reached out to delroth, the original writer of most of Dolphin's current AX-HLE implementation. Thankfully, delroth still had a lot of the debugging information and annotated disassembly from those days and helped leoetlino get a much clearer image of how the µcodes worked. And with all of this information and debugging, we were able to find a very silly oversight.
There is a field in Parameter Block (PB) Struct called "running" that is set to 0 or 1. DSP-LLE and DSP-HLE implemented this roughly the same, but with a key difference. DSP-LLE was checking if the value was set to 1 while DSP-HLE was checking to see if the value wasn't set to 0. This difference is negligible, as "running" should only ever be set to 0 or 1.
The keyword here is should. For some unknown reason, The Sims 2: Castaway doesn't always set "running" to 0 or 1. Sometimes it likes to set it to... 8. And because 8 is not equal to 0, DSP-HLE was continuing to play audio into invalid memory ranges. Since DSP-LLE was running the real µcode, it handled it correctly. The value of 8 does not equal 1, so it stopped running as it would on console. This was incredibly esay to fix, leoetlino did need to make sure that the other AX µcode's shared this behavior. Once that was verified, the fix was submitted and merged.
Finally, The Sims 2: Castaway can be put to rest. But that's not the complete end of this story. One game setting weird numbers to PBs wasn't enough. While looking through DSP-HLE issues to fix, flacs discovered that this change also fixes severe audio issues in Dinotopia: The Sunstone Odyssey when using DSP-HLE.
Note: is_stream was found to have the same problem and was also fixed. Currently we do not believe this affects any games...
5.0-14712 - DSP-HLE - Re-enable Low Pass Filter by flacs, original fix by MerryMage¶
This is a rather awkward situation where the original bug was actually fixed years ago. While repairing audio in Star Wars: Rogue Squadron II and Star Wars: Rogue Squadron III for DSP-HLE, MerryMage also added support for µcodes without the Low Pass Filter. This is because these games, along with others, used an early revision of the AX µcode that didn't yet support the Low Pass Filter. Back then, Dolphin's support for AX µcode revisions wasn't stellar and in order to account for differences in support, the Low Pass Filter was one of many features completely disabled when using DSP-HLE.
This oversight meant that even though the Low Pass Filter could have been re-enabled with no consequence back in 5.0-3260, no one did. Once flacs realized that all the work was done, all they had to do was make sure the games that didn't support it weren't broken. The entire process took a couple of hours, and now the Low Pass Filter is re-enabled in the latest builds!
For those that aren't audio engineers, a Low Pass Filter cuts off audio above a certain frequency, only letting lower-frequency signals pass. This allows games to create a muffled effect, and is commonly used when underwater. For example, Sonic Colors makes great use of the Low Pass Filter to give parts of stages a unique feel. Without the Low Pass Filter, many of the underwater stages simply sound flat.
Considering that most games support the Low Pass Filter, this will likely fix missing audio effects throughout a lot of games when using DSP-HLE. We've already confirmed Sonic Colors and Paper Mario: The Thousand-Year Door as having missing effects restored.
Re-enabling one disabled feature wasn't enough, so flacs moved onto another target: Polyphase Resampling. Polyphase Resampling is an efficient resampling algorithm from the early 2000s used to resample audio samples. It's not anything particularly interesting or unique to the GameCube or Wii, but Dolphin didn't bother emulating it when using the DSP-HLE option due to bugs in the HLE implementation. Unlike the Low Pass Filter, this wasn't something that flacs could simply enable and have work out of the box. Thankfully, the fix was actually dead simple and amounted to nothing more than a change to a single line.
Dolphin was incorrectly handling the maximum/minimum values, truncating them when all it had to do was clamp them. The question then becomes: What exactly does this fix? The one obvious title is Snowpack Park, as it was the game that prompted the investigation of Polyphase Resampling. As expected, fixing and re-enabling the feature caused the loud beeps in the game's music to disappear.
Investigating other DSP-HLE issues, testers also found out that Polyphase Resampling was used in music in two somewhat more popular games: Pokemon Colosseum and Pokemon XD: Gale of Darkness. Users had long been complaining about quavering in the music, but it wasn't nearly as obvious as the defect in Snowpack Park. If you want an iconic example of how polyphase resampling affects a game, that is much easier to hear in Super Smash Bros. Melee.
With the month winding down into its final days, flacs took on another feature missing from DSP-HLE. Dynamic Range Compression is a feature designed to prevent clipping in games if they play a sound too loud. While this worked in DSP-LLE, no one bothered implementing it in DSP-HLE, and it's easy to figure out why. In most games, it's pretty hard to hear much of a differences with the range compressor on or off. How does the compressor work on the GameCube and Wii? What better place to get the information than from the one who wrote support for it!
The compressor looks at one frame of audio (5 ms on the gamecube, 3 ms on the wii) and if at least one sample would be clipping when converted to the output format, it applies a volume ramp: a short single-frame attack phase, waits for the clipping to end, and then slowly increases the volume again. It might be worth noting that the 0x4e8a8b21 µcode doesn't have a compressor command, so for example melee is literally incapable of triggering the compressor code.
Thankfully, Pac-Man World Rally was known for playing overly loud sound effects and ended up in our sights. It worked as a perfect test case for making sure everything was working.
After implementing it, the game we've seen affected the most is Star Fox: Assault, because it will trigger the compressor constantly when enemies are exploding. This was the main difference in audio quality between DSP-HLE and DSP-LLE in the past! Now they sound virtually identical.
With an emulator as big as Dolphin, sometimes features fall into disrepair over time. With Real Wii Remotes on macOS, that definitely seemed to be the case. Doing even basic things like turning on Continuous Scanning or trying to shut down the emulator with a Real Wii Remote connected could cause the emulator to crash. In order to fix these problems, we needed someone familar with the macOS side of things to take a look. Enter OatmealDome, who has tons of experience working with Apple products and Dolphin.
It may not seem like much, but the attention they gave Real Wii Remotes for macOS fixed the major crashes and made things useable again. This isn't going to put the macOS experience on parity with the other operating systems due to the numerous limitations that Apple inflicts upon us, but it's definitely a step in the right direction, especially for those looking to try out the interesting M1 hardware with Wii games that play best with Wii Remotes!
In addition to all of the changes to the website, we saw some key changes and updates to Dolphin's infrastructure that should make things a little bit nicer for both us at the blog and those using the emulator. One of the most immediately visible things is that linking to Dolphin's blog will now generate proper previews and make for much more appealing links!
On the more useful side of things, OatmealDome has helped out with making the macOS auto updater a little less tempermental. There have been several phases to this, so you may need to manually update to get out of broken builds. Hopefully, the macOS updater should be working for the forseeable future and it shouldn't be necessary to manually update again once you have.