Kept you waiting, huh? This summer we had our longest break since we started writing these Progress Reports. Some other obligations came up and a bit of a lull in development gave us the opportunity to postpone things for an extra month. As it turned out, pushing things back might have been a bad idea, as the floodgates opened and now there's a gigantic backlog spanning three months to get through! To put things into perspective, since our last Progress Report, the last Nintendo Wii games were released, Dolphin Android had a huge user experience overhaul, and Nintendo's very own GameCube and Wii emulator hit the Switch with Super Mario 3D All Stars.
So without further delay, let's start getting through the backlog. This one is a bit of a doozy.
The Android User Experience Overhaul¶
Dolphin on Android isn't always the smoothest experience. From the fact that most mobile hardware targets efficiency over power, to the fact that Dolphin's Touch GUI lacks a lot of features present in Dolphin on desktop computers. Things we take for granted on other operating systems were simply missing from Android. The unworkable config system Dolphin used on Android made it impossible to even change emulator settings while a game was running! Over the summer, JosJuice has been chipping away and we're happy to say that the latest Play Store release and development builds finally take advantage of our layered config system!
The biggest change is that you can now directly change settings while emulation is running, much like Dolphin's desktop interface. This finally allows Android users to try things like pushing the resolution to see how high it can go before it affects performance, or quickly enabling/disabling hacks to try to find the perfect balance, all without stopping emulation! You might notice the GUI itself has had a bit of a rework, too. Now instead of a drag down menu, hitting the back button will open up a much more robust side menu. While this works better in general, it also allows Android devices that lack a touchscreen to access the menu, such as chromebooks. This menu is the same menu that Android TV Dolphin users have already been using, however it's now been overhauled to support these new features!
Beyond that, Ebola16 and JosJuice have been doing a ton of work on the rest of the Android GUI. Together, they've repaired things such as the touch/motion pointer not working in some instances, GameCube Adapter detection being spotty, touch layouts getting reset or not saving properly, added missing settings to the menus, and much more. These changes are rather minor in isolation, but together make a much smoother experience overall.
We have one last major addition to Android. In this case, it's a bit easier to show than tell.
That's right, JosJuice hooked up Dolphin's conversion and compression tools to Dolphin Android! If space is at a premium, you can now compress your disc images into formats suitable for Dolphin without the need for a desktop computer or external software! While Dolphin Android could already take advantage compressed formats, such as Dolphin's new RVZ format, users finally get the power to do everything directly from their mobile device.
Now that we're done with Android, here's a big one that currently only affects our desktop users. This major change is only for JIT64, Dolphin's PPC to x86-64 recompiler. However, unlike most changes to the JIT, this isn't an optimization for raw performance nor is it a fix to increase compatibility. Rather, this change targets a specific shortcoming in order to provide a much smoother experience in afflicted games. In this case, we're talking about games that can overflow Dolphin's JIT cache. In order to explain what's going on, let's talk a bit about how Dolphin's JIT works and why it needs a cache.
When Dolphin encounters a piece of PPC code for the first time, it has to translate it into something the host CPU can actually execute. Once it's translated, Dolphin's JITs record these translated instructions to a cache so that if the same PPC code is encountered again, it can skip translation and just execute the already translated code.
...However, that's not the end of this story. Dolphin's x86-64 JIT has never been completely rebuilt from the ground up, so it retains many "oldisms" dating all the way back to when Dolphin was first created. That's not to say that it's bad, Dolphin's JIT was designed to be simple and fast. That core design has allowed tons of innovation and crazy optimizations over the years. There are some catches, however. For example, the JIT was more or less designed to just pile more and more translated game code into the JIT cache with no way to prune or manage that memory. If it somehow filled completely, it would simply overflow and flush everything out of the cache before starting over from scratch. This resulted in a sizeable stutter as all of the cached code was lost and Dolphin had to translate everything once again.
Fortunately for us, this doesn't occur in a majority of games as they don't ever use enough code to overfill the JIT cache. That isn't to say there aren't ways for a game to fill the JIT cache, and over the years we've run into many cases that do. The following titles take advantage of techniques that allow them to blow our cache out of the water, flushing over and over again throughout a play session. And remember, with every overflow has an associated hard stutter. It's one of the final white whales of stutter within Dolphin.
The Classic - Loading New Code Off the Disc¶
This is one of the earliest examples Dolphin developers would have run into. Though it was primarily seen in the Metroid Prime series, many games loaded additional code off of the disc along with new areas. Even though the player is traveling between areas that have the same enemies, textures, and effects, the game is loading into new areas of RAM each time, so Dolphin's JIT considers each bit of code "new" and just piles it all into the cache. With the Metroid Prime games endlessly loading and unloading as you traverse the world, it's not hard to see how it would eventually overflow a static cache. In fact, with the right pathing, you can do so in under ten minutes!
The MMU - Swapping Code Into and Out of ARAM¶
This is actually the same problem as loading code off of the disc, except instead of the disc, the code is stored in audio RAM. While it is called audio RAM, as that was the primary intended use of this external ram chip, through Direct Memory Access (DMA) you can store and load whatever you want from it. Considering the GameCube had a paltry 24MB of MEM1 and a rather massive 16MB of ARAM, it was very common for developers to borrow a bit of ARAM for their own needs. Code loaded from ARAM into MEM1 would be recognized as new code by Dolphin's JIT, even if it was swapped in before. This is primarily seen in games like Metal Gear Solid: The Twin Snakes and True Crime: New York City, but it was possible in any title that programmed the MMU.
Using Metal Gear Solid: The Twin Snakes as an example, this game would load new enemy routines out of ARAM when you go into alert mode after being spotted. Even if these enemy routines had been loaded before, their RAM addresses wouldn't be consistent and Dolphin would treat the loaded code as new code each time it translated it. Usually getting spotted just one or two times was enough for Dolphin's JIT cache to run out. True Crime: New York City on the other hand is a special case. Of normal games, it does the most swapping in and out of ARAM that we've seen.
As an extra note. Yes, Star Wars: Rogue Squadron 2 and 3 also do a lot of ARAM transfers and will overflow the code cache. It's just barely worth mentioning because they have so many other problems still.
The JITception - Nintendo 64 Virtual Console Games¶
Jitting a JIT generates a lot of dynamic code. A lot. If you were playing The Legend of Zelda: Ocarina of Time on N64 Virtual Console, it wasn't uncommon for Dolphin to have to clear the JIT Cache three to four times a minute. These stutters would essentially render the game unplayable as it'd hitch too often to really do anything. Considering that these games came out late into Dolphin's development and didn't really run well in Dolphin until 2014, these games didn't get a fair look. Even when reports of the constant stuttering did come in, they weren't a huge priority for most normal people. In recent years, people generating randomizers have the ability to output them as wads that can be run on Wii, and thus Dolphin, resulting in an uptick in reports of rampant stutters.
The thing to remember with all of this is that all of these cases are exceptions and make up a tiny portion of Dolphin's library. Even when developers found these cases, the stutters weren't really considered an issue so much as a consequence of how Dolphin emulated things. It wasn't exactly a good behavior, but fixing it permanently pretty much meant rethinking the JIT and there were several other impossible problems like shader generation that meant stuttering like this would never really be a major issue!
...Yet here we are, with JIT cache flush stuttering being the main source of random stutter left in the emulator.
Making Better Use of Space¶
The main problem at hand was that Dolphin's JIT simply wasn't designed to handle a game generating its own code. By constantly appending new code to the end of the JIT cache, the cache would eventually fill up and flush again and again without any reprieve. Some desperate users even modified Dolphin to have a 2GB JIT cache as a way of alleviating the problem. While it's true, a bigger JIT cache did reduce how often the JIT cache flushes happened, it did not eliminate it completely and did result in longer stutters when they did happen. What AdmiralCurtiss did was look at the problem from the perspective of the what Dolphin's JIT could do and how we could make it work without a total redesign. His solution? Keep track of what PPC code the game is invalidating and mark it as "free space" in the JIT cache. When adding new code to the cache, Dolphin can use this space for new code instead of continuously writing more and more to the end of the cache until it fills up.
This clever addition alleviates the main cause of stutter and is enough to never see a full JIT cache flush period in most titles. However, this method isn't perfect. If a game just loads or generates enough code, it's actually still possible to fill the cache even with this new feature. This is because of a new problem: fragmentation. Even if the cache has free space, it's possible for all of the memory to be scattered about in tiny blocks that aren't big enough for when the game wants to shove a big block into cache! Dolphin is also relying on the game to actually invalidate things correctly. If a game is poorly coded (True Crime: New York City), buggy (True Crime: New York City), or has extremely poor memory management (True Crime: New York City), it's entirely possible to overflow Dolphin's JIT cache despite this addition.
Even in the cases where games do still run into JIT cache flushing, the flushes are much less common. In The Legend of Zelda: Ocarina of Time (VC), it reduces cache flushes from multiple times a minute to maybe once or twice an hour at most during normal gameplay. For people that play games that dynamically generate code, this change is quite literally game changing. ...Sorry.
Note: Due to an unknown bug while emulating True Crime: New York City, it's very likely you won't be able to actually play far enough in Dolphin to see the improvements. Standing on destructable scenery slowly pollutes the physics engine with NaNs, which eventually causes the game to crash. To get through to the intro and make it into the city segments where the game is improved by the new code, you'll need to abuse a glitch in the game that allows the character to pretty much pass through any wall.
When Nintendo released their GameCube Controller Adapter for Wii U, it was an exciting moment for Dolphin users and developers alike. An official, standardized adapter that can connect GameCube Controllers to our computers over USB? Sign us up! Since then, GameCube Controller Passthrough via Wii U and Switch adapters has become a very popular feature in Dolphin. It's no hassle and provides accurate, low latency inputs for games. However, in recent times, we've seen a worrying tend taking hold with third party adapters.
Newer models of third party adapters no longer seemed to work with Dolphin. While we could recommend Nintendo's adapter or the Mayflash 4 port that we confirmed worked for Passthrough, these newer third party adapters were cheaper and becoming more common every time we looked. As the questions and requests for support mounted from social media and issue reports, it was clear that this was a problem that wasn't going to go away any time soon. However there was a light at the end of the tunnel - Billiard bought an adapter with the problem to follow up on a suggestion on how to fix it. After adjusting Dolphin's adapter connection code slightly, he was able to make it work happily with both official adapters and these newer third party adapters. Everything was merged and things were going to be great!
...Of course, it couldn't be that easy right? Fixing the Nyko style adapters broke Mayflash's adapters, which was a bit of a problem as they are very common among our users and developers had been recommending them as a cost effective alternative that worked for Dolphin. In order to get both kinds third party adapters working happily we had to hack things up a bit, but everything seems to be fine for now. Oddly enough, throughout all of these minor connection changes, Nintendo's adapters never stopped working. Go figure.
Note: This fix for connectivity is only for Desktop Dolphin. Android Dolphin uses a different codepath and it is unknown if it requires further adjustment.
This is a quality of life change that should allow making texture packs a little bit easier. In order to only dump the textures you want to update, Dolphin now has the option to skip dumping mipmaps. Outside of specific mipmap effects, dumping mipmaps is effectively useless for HD Texture creation, so being able to disable mipmap dumping will allow texture pack creators to skip sorting through tons of needless mipmaps from the actual full textures. When making a texture pack, there are already a lot of tedious steps that go into dumping and organizing textures, so every little thing that the emulator can do to make things easier adds up. While it was possible to delete all the mipmaps manually with searches or automatically with scripts, now Dolphin can simply avoid dumping them!
We've traveled a long road. At this point, the Wii is 14 years old, twice replaced by the Wii U in 2012 and the Nintendo Switch in 2017. While Dolphin was just a GameCube emulator when the Wii was announced and released, it wasn't too long after that developers began targeting what was essentially a super charged GameCube with innovative motion controls. The Wii's announcement and similarities to the GameCube breathed new life into Dolphin, and gave the project new challenges, new goals, and a longer tail of active development than anyone could have anticipated. Even with its popularity, we couldn't have imagined the Wii having new games released 14 years after its launch. Even the yearly Just Dance, were unbelievable, releasing on Wii after they discontinued the Wii U version.
But finally, it all seemed to come to an end earlier this year when Nintendo ended disc manufacturing for the Wii. For the aging console, this was a death sentence. Online distribution had long been shutdown, without discs, there was no other avenue for official releases. The library was set, and the curtain, had dropped.
Except the Wii would not go quietly into the night! With the help of Nintendo of Europe, developer vblank managed to squeeze out two last very limited run releases before disc manufacturing was shutdown permanently. It was so tight in fact, the games are PAL exclusives because all other presses were already dismantled. And so, we have the final FINAL official Wii titles: Shakedown: Hawaii and Retro City Rampage DX.
Throughout the years, new releases meant new challenges for Dolphin. Developers were constantly discovering new optimizations, abusing Wii features in interesting ways, implementing anti-piracy that would incidentally trip up Dolphin, and sometimes just being so generally incompetent with their code that it's hard to emulate through the power of spaghetti. What challenges would the final two retail Wii games present?
None. Dolphin was more than up to the task of emulating these last two titles. The only adjustment we had to make was one we make for a lot of games: Dolphin's texture cache accuracy needed to be set to safe for certain menus to render correctly. chungy made quick work of the issue and the games now run flawlessly.
And so, with these final two games, the Wii's official library should be well and truly set.
FreeBSD support in Dolphin is one of those magical things that sometimes happens with Open Source. Despite having our smallest userbase among "supported" operating systems, FreeBSD continues to receive support and maintenance, from FreeBSD users to keep it running! And since FreeBSD support is noninvasive to the rest of the project, we can just leave it be and let the ones who know it best take care of our FreeBSD support. That passion is examplified this month by kit-ty-kate extending Dolphin's AArch64 JIT to FreeBSD. We don't entirely know if there are many Dolphin users that overlap with FreeBSD ARM users, but if there is, Dolphin is ready and working!
5.0-12530 - Add Patches to Disable Save Protection on Pokemon Colosseum and Pokemon XD by AdmiralCurtiss¶
In the previous Progress Report, we mentioned that both Pokemon Colosseum and Pokemon XD had extra save protection. While it ended up that a bug was causing most games to think that the memory card had changed after savestates, it turns out that these games were broken by design.
In order to prevent the duplication of Pokemon, these games have purposeful checks to make sure the savegame has not been tampered with or modified. If it detects anything wrong, it'll simply refuse to save, almost the same as the "bug" shown in other games. Mixing savestates with normal game saves can easily trigger this anti-duplication protection, leaving users stuck to savestates and a particular build of Dolphin for all eternity.
This is technically accurate emulation for these specific games, but it's really not a fun situation for anyone. In order to try to make things less complicated on our users, AdmiralCurtiss dug into their games and ripped out their save protection. We now provide a nice game patch that you can enable directly in the Game Properties menu if you wish to play the games without these restrictions. If you've already triggered the bug in older builds of Dolphin, these patches can be copied into any build and function all the same. With these patches enabled, the anti-duplication code will not function and you should be able to save even if you've triggered it in the past.
Dolphin has a relatively advanced timing model for simulating disc loading times. It takes into account the length of various commands, simulates Constant Angular Velocity, meaning data toward the outside of the disc is read faster than data on the inside, and much more in order to try to provide reasonable loadtimes that match that of a typical console.
When the DVD drive does various commands, Dolphin has long had a constant called Command Latency. This simulates how long it takes the drive to process a command. Unfortunately, when adjusting Command Latency to better reflect the results of hardware tests, Ed, Edd n Eddy: The MisEdventures stopped working. Reverting hardware verified numbers to fix a game seemed hacky, so the game remained broken as the cause of the issue went unknown.
Finally, after several years, the answer was finally found. In order to fix this issue, we've split up Command Latency into two different constants. Our general Command Latency is now Minimum Command Latency, meaning it's the smallest processing time a command can take. We've added a new latency for read commands called Read Command Latency. This latency is slightly longer than Minimum Command Latency in order to reflect hardware tests that read commands take longer to process than other commands. This very slight change fixes a hang at the beginning of Ed, Edd n Eddy: The MisEdventures.
Note: While testing this change, we discovered that Ed, Edd n Eddy: The MisEdventures has icache issues later in the game. Enabling MMU emulation may alter timings enough to make the game playable past various icache crashes.
5.0-12656 - Massive Game INI Update by A lot of people¶
Usually we don't feature INI updates in Progress Reports unless there is something especially notable in them. There are a lot of changes compiled into this INI update and most of them are simply small adjustments to default performance and accuracy settings to make the game immediately playable. However, a few of these changes stand up above and beyond typical INI changes and deserve to be talked about in more detail.
Fix MVP Baseball 2004 and MVP Baseball 2005 Flickering Graphics¶
Originally reported seven years ago by our own JMC47, MVP Baseball 2004 and 2005 have had flickering 2D graphics that make the games difficult to play at the very best. While the underlying 3D graphics look fine, the seemingly random flickering of UI elements could obscure gameplay or make simply navigating into the game difficult.
So you're probably wondering how an INI update fixed this. It turns out the games' code had a minor mistake, creating a class of game bug that doesn't appear on native hardware but rears its head when we try to emulate it. A race condition.
The GameCube and Wii render with "vertex index buffers" (an index buffer for vertex data used on the CPU while building a draw call, not to be confused with the GPU's vertex buffer). Much like how compression squeezes down duplicate data in a file, vertex index buffers allow a CPU to notice shared vertices within an object and merge them so the GPU doesn't have to render a vertex multiple times. This is just a straight up efficiency improvement and has been a long term staple of 3D rendering. Keep this in mind.
When rendering a quad for 2D elements, MVP Baseball does everything pretty normally. It sets up the quad, writes to the vertex index buffer, and sets up the texture. Nothing fancy, it's just a quad. However, before finishing the draw call by flushing to the GPU, the game writes 0 to the vertex buffer index. That's our race condition. Upon reading this change the GPU will immediately render whatever happens to be in the first slot of the index, so if the GPU is busy rendering then is suddenly redirected to index 0, it will send data to the wrong places and UVs go nuts and things start getting bad. On the GameCube, this never presents a problem, since the ArtX programmable fixed function pipeline renders the quad so fast that it doesn't even see the index change. However, as an emulator, we have shaders, APIs, operating systems, and all manner of things to deal with. In Dolphin, the redirection will always reach the GPU at some varied point during the rendering process, leading to randomly incorrect UVs and vertex data when rendering 2D elements - flickering. And since this is a race condition, there is absolutely no way for us to address this in Dolphin, this has to be addressed by a game patch.
Thankfully, all of this was discovered by hthh, who dug into the game's code, isolated the bug, and also provided patches for both titles! This simple patch inserts a flush to the GPU before the index buffer change in the draw call, preventing the issue from ever occuring. And with that, MVP Baseball 2004 and 2005 are flicker free!
Fix Monster Hunter Tri Bloom Disabled Patch¶
So, we can't really explain how this happened. We can only explain why it became an issue more recently. Upon the unification of VideoCommon we finally removed a default setting that partially disabled the bloom effect in Monster Hunter Tri thanks to optimizations and an offset fix. This effect is accomplished in a different way than most games; while the bloom is done on the GPU, the actual check for what gets bloomed and how much happens on the CPU by use of EFB pokes. This looks just fine on hardware or at 1x Native, but when raising the internal resolution in Dolphin, it makes the game look very wrong.
By default, this is how Mon Hun Tri looks in Dolphin. The CPU controlled bloom doesn't scale to higher resolutions. Worse yet, it is 1/10 of 1x Native, so it is VERY blocky.
The only option was to disable CPU EFB access, but you'd get this - overbloom. The game thinks every pixel is "bloomed" and thus, there is no longer a "bloom" at all, just this over brightening.
Here is 1x Native, demonstrating the original look of the bloom. ...This game is blurrier than we remembered.
With optimizations and some recent fixes, Dolphin can finally emulate the effect correctly in the latest development builds. However, that's precisely what annoyed users; they preferred disabling this bloom effect and using their own. This wasn't a problem - Dolphin also shipped with a game patch that would disable the bloom. Except, by the time this was actually possible, the game patches didn't actually work. For one of these patches, the reason is quite simple. For the other... we, uh... yeah. See if you can spot the problem.
Let's talk about the PAL code first since it actually makes sense. 5.0-540 and the work surrounding the improvements to memory emulation it brought meant that these addresses wouldn't work. Fixing them was simple, we just needed to make them actually use the GameCube/Wii's virtual memory addresses instead of the physical ones.
Now the NTSC code... is an action replay code that got copied into the patches section. It never actually worked. The "04" at the beginning of 0x04056FF4 is not an address, as much as a description of the code saying that it is four bytes. Fixing it was admittedly just as simple though, as the rest of line is the address.
Admittedly, Monster Hunter Tri without the bloom at all doesn't look right either. The game was built to use the bloom effect to brighten the image, so without it it looks dark and lifeless. However, the Wii doesn't support HDRI whatsoever, so there's nothing the game is doing that can't be recreated by external post processing software. Thus by disabling the game's bloom entirely, a user can then use ReShade or like injectors to add their own bloom, and recreate the original look of the game at higher resolutions!
Dolphin's Advanced Input Configuration Pane is very powerful and allows you to do a lot of crazy things with key and controller combinations. But, using that pane can be quite the pain if you don't know what you're doing. So in order to ease up on the discomfort, Billiard has expanded Dolphin's standard input configuration dialogue! This means you can now setup button combinations directly in the main configuration page without having to dive into the mass of logic that is advanced configuration.
As an added bonus, Billiard has added a new set of expressions to handle hotkey modifiers. This makes them display more cleanly and be setup without needing complicated logic. Also note that this can be done with controllers as well, so if you want to map an upward swing to require both a joystick direction and a button, you can!
A few things happened over the last few months that led to a rather interesting change. Perhaps the bigger news in all of this is that Techjar added our first built-in controller profile. The profile is specifically for when users connect Wii Remotes with MotionPlus to Dolphin's emulated controller interface. When you connect a real Wii Remote and select this profile, everything will be automatically mapped correctly, including Pointer Simulation so that you can use your real Wii Remote without a sensor bar!
However, Billiard wasn't entirely happy without how pointer simulation was behaving and began to dig into the Wii Remotes for more answers. However, Dolphin's numbers on the infrared camera seemed to line up with Wiibrew.org and there was nothing to the contrary.
The IR camera has an effective field of view is about 33 degrees horizontally and 23 degrees vertically (as measured on one unit).
Still unhappy with the performance of the emulated pointer, Billiard remeasured this data from a Real Wii Remote. To his surprise, the numbers actually comes out to 42 degrees horizontally by 31.5 degrees vertically. Plugging these numbers into gyroscope simulation of infrared made emulated pointer feel much closer to the real thing.
While he was in the neighborhood, Billiard also made a few other adjustments to the defaults. One of which was was a constant problem with emulated Wii Remotes in general...
In order to make sure Wii Remotes can reach all of the screen, the default values for how far the Wii Remote Pointer can go were adjusted. This should make it so most, if not all, workable with emulated pointer without further adjustment.