One of the most interesting challenges of developing an emulator is that both the target hardware and most of the target software start out as black boxes. As often mentioned within emulation circles, the first step to developing an emulator for a console is getting unsigned code running on real hardware. While running unsigned code on the GameCube can be a bit of a pain, requiring custom hardware or a mixture of the broadband adapter and certain games, the Wii has one of the most robust homebrew environments of any console. Just about anyone can download devkitpro, write their own homebrew, and run it on the Wii.
The truth is that Dolphin is mostly used as an emulator for retail games, but it can also be a useful step for testing homebrew and hacks. After all, when running in Dolphin, users can pause execution, dump RAM, and poke memory without the need for a USB Gecko. While the golden age of Wii homebrew has long passed, several game hacks are still under active development and the Wii remains one of the easiest game consoles to jump into and develop software. Because homebrew can rely on behaviors that games wouldn't ever want to do, even the simplest of projects can stumble into emulator bugs.
Developers kind enough to make their homebrew open source give Dolphin developers an interesting way of debugging issues. It's one of the rare cases where the software being debugged isn't a black box! This greatly cuts down how much effort and expertise is needed to debug what is happening in an issue - instead of mapping out what a game is doing through assembly, we can just look at the source code! Users who write tests that break Dolphin and provide source code give us a much easier look than trying to reverse-engineer what closed source software is doing.
This month, two bugs were discovered that, to our knowledge, do not affect any retail software! Thanks to homebrew projects, these bugs are now a thing of the past. In addition to that, Dolphin on Android has seen a myriad of improvements since our article earlier this month, and netplay saw some new features to make setting up games easier along with a new mode to reduce latency in three/four player matches!
Dolphin Android Quality of Life Improvements and Fixes by mahdihijazi and zackhow¶
The past few months have been exciting for Android users as several developers have taken up the challenge of stabilizing and fixing up the sometimes maligned Android version of Dolphin.
Users following Dolphin on Android may have noticed that a lot of those annoying things about using Dolphin on Android are being fixed. While some features are more noticeable than others, it's safe to say new users will appreciate sane default touch controls instead of all of the controls clumped in the corner, and actually working per-game settings menus. These are just two examples, but a multitude of bigger and smaller changes have greatly enhanced the user experience.
There have been tons of minor changes designed to make using Dolphin on Android better for those trying it out. There are some things that are just an unfortunate reality - today's phones are not strong enough to run most of Dolphin's library. On the other hand, a lot of the minor annoyances with setting up and using Dolphin, are under our control and we can continue to making them better. Since The State of Dolphin on Android Article earlier this month, mahdihijazi and zackhow have continued to add many necessary features for a smoother experience.
In particular, zackhow has been working hard on improving setting up and using Dolphin's various control schemes easier. There are a myriad of commits throughout the month fixing issues throughout the controller configuration process. On the touchscreen front, on top of adding in the default layouts, zackhow has also renovated the onscreen dpad to work more like joysticks, so you can move your thumb around it to change the directions your pressing instead of being locked into one direction per push. Needless to say, if you're trying to setup emulated Wii Remotes, make sure you've updated to the latest version in the Play Store or our download page - there were many critical bugs that could cause crashes, non-responsive controls, and other issues that are of no fault of the user!
Other notable Android contributions have been provided by Riking and weihuoya. Riking went through the trouble of reformatting the Android code to follow Dolphin's code guidelines and weihuoya submitted a fix to prevent flickering when changing screens in the Android GUI.
Last, but not least, Dolphin on Android can now optionally provide usage statistics. Considering how eager some Android users are to tell us about their experience, we're hoping to use these statistics to help identify issues users are running into and much more going forward. Just as on the desktop version of Dolphin, this data collection is 100% optional and users must opt-in in order for it to activate. When updating to the latest version of the app from the Play Store, you should get a notice asking for permission. If you say no, you'll never be bothered with it again. If you change your mind, you can always turn it off or on in the Configuration menu.
While these are two very different fixes, they came about the same way - homebrew executables were failing on Dolphin's Just-in-Time (JIT) recompiler. The first of which is actually a very amusing bug that was reported by CryZe92. They were compiling Wii homebrew applications/romhacks in Rust with LLVM, and Dolphin's JIT was not handling those executables well at all, with annoying crashes and failures. While they did discover that the JIT would work if LLVM optimizations were disabled, that was not an ideal solution.
In order to help us solve the bug, they compiled a very simple executable that printed out the message "Hello" when run correctly. On Dolphin's interpreter, everything worked correctly. On Dolphin's JIT, the text was misinterpreted into unprintable characters giving us this:
With the reporter having already done a lot of the work to isolate the bug, delroth was able to dive right into figuring out what was going wrong. PowerPC CPUs have special registers called Condition Registers (CR). These registers are usually managed automatically within the CPU, containing information about the results of a previous operation: was it less than, equal, or greater than zero. Checking these is very costly, so Dolphin tries very hard to optimize operations around CRs. PowerPC also has specific opcodes to perform manipulations on CRs, but fortunately the compiler used by official games (Metrowerks CodeWarrior) as well as the most common homebrew toolchains (GCC) almost never use them. However, this means that Dolphin isn't well tested in these cases.
Enter LLVM, a compiler which is a big fan of these CR manipulation opcodes. It uses a wide range of opcodes that Dolphin has had almost no testing against. Unsurprisingly, one of these opcodes (crset) had a bug in its implementation: it would only work if a given bit was being set, and do nothing for all the other bits. Fixing that single issue cause all the bugs when using the LLVM optimizations on Dolphin to disappear!
The second issue takes us to a more established homebrew project for the Wii called Not64. This is a port of Mupen64 to the Wii which features a MIPS to PowerPC CPU recompiler and many other options to try and make N64 emulation playable on the Wii's limited processing power. With Dolphin, we can do a little bit of cheating and crank up the Emulated CPU Clock to ridiculous amounts to make most games run full speed - provided your computer can handle it. That being said, Not64 is a rather complicated homebrew to emulate and had some pretty big issues in Dolphin.
The biggest limitation facing users trying to run Not64 in Dolphin was the fact that any 32MB roms would fail to load when using the JIT. Because the Wii's memory is limited, Not64 would only partially load the ROM into MEM2. It would then use paging (much like MMU games) to load parts of the rom into and out of NAND. If you wanted to drop down to interpreter you could avoid this nasty bug, but by then any hopes of actually using the emulator in a playable manner would be gone.
Considering Not64 works in Dolphin's interpreter but not in its JIT, it may seem like an instruction in the JIT is broken. But that's not the case here, that bug is actually in the JIT's behavior when falling back to the interpreter in a very specific case! Homebrew can use instructions that games tend not to use much, and many of these rarely used instructions aren't implemented in the JIT. Some of these instructions are fairly difficult to implement while others just are so rare that it's not worth the trouble to write a JIT implementation. In Not64's case, it was using the instruction lswx (Load String Word Indexed) and triggering DSI (Data Storage Interrupt) exceptions with it in order to page data in and out of MEM1. That instruction was so seldom used for that case that Dolphin still had a panic alert in place to warn developers of this valid behavior until it was discovered something actually used it earlier this month!
This may make it sound like the bug must be in the interpreter, but as mentioned above, the interpreter could load the ROMs just fine. So what exactly was going on? Well, delroth dug deeper and found a rather egregious bug when falling back from the JIT to the interpreter: Dolphin was forgetting to update PC (Program Counter) to the correct value.
With an outdated PC, the exception handler would restore the point of execution to the beginning of the last block of execution in which the exception was triggered. That meant if the exception was triggered midway through the block of execution, Dolphin would end up erroneously running extra instructions a second time! This, more likely than not, would either crash Dolphin or Not64 in rather spectacular fashion.
Once this bug was corrected, the issues with Not64 vanished and it can now load ROMs of any size in without the performance penalty of enabling one of Dolphin's interpreters. So if you want to take out your frustrations on Nintendo's lackluster Wii Virtual Console N64 library by using Not64 emulated within Dolphin... you can. It's still a better idea to just use a native emulator on your device of choice, but, the option is there.
Note: Dolphin cannot detect whether or not Not64 is a Wii or GameCube executable because of the way it is packed and defaults to GameCube. As such, a Wii homebrew loader, such as the Open Homebrew Channel must be used in order to load Not64 in Dolphin. Yes we know this is silly.
5.0-8602, 5.0-8633, and 5.0-8669 - Discord Rich Presence Additions by YourWaifu, delroth, and Techjar¶
With the addition of Discord Rich Presence announced in the June Progress Report, one of the biggest questions asked across social media was if Discord could be used to help organize netplay games. The answer is now yes thanks to YourWaifu's latest addition to Dolphin's Rich Presence Support added last month. Joining netplay is easier than ever - just have a compatible Dolphin build on your computer and Discord's game detection enabled. Then, if you're hosting a netplay session, you can invite channels or individual people to play. In addition to that, other people can request to join your game as well.
delroth, and Techjar also teamed up to add game covers to show up for some of the most popular games when running them in discord. Note: Applications have a limit of 150 assets, so only a small subset of the most popular games will work with this feature.
With the removal of SOIL (Simple OpenGL Image Loader) from Dolphin's external dependencies in 5.0-7631, Dolphin now relies on libpng directly. While the move to something more modern has mostly been a smooth transition, some transparent PNG textures were having issues with the new loader. AdmiralCurtiss determined that LoadPNG() was failing with certain valid transparent PNG textures. In order to fix this and greatly simplify PNG loading, he migrated the PNG loader to use the new Simplified API present in libpng 1.6 and newer.
The only downside to this is that Dolphin now requires libpng 1.6 at the minimum and will not compile with older versions. There was also a crash bug present immediately after the merge of this build. This was quickly rectified in 5.0-8606.
Of course, these incredible texture packs wouldn't exist without content creators that put their heart into making quality packs. On the forums, a group of users with Custom Texture Subforum maintain tools, guides, and more. A lot of the issues that end up fixed in the Progress Reports come from these users that help maintain and improve Dolphin's Custom Texture feature. In order to know what content creators needs, sometimes it takes an expert within that community to help communicate what they need. Bighead has been that user for years and has helped request new features and report bugs. They even reported the bug we just talked about and the behavior that is about to follow!
Even when Dolphin is technically doing everything right, making a custom texture pack is an arduous process. Games can do a lot of annoying things to make replacing every last texture extremely frustrating. In this case, check out the following hashes:
tex1_48x51_53403146169829a2_45604eac43c6fd37_9 tex1_48x51_53403146169829a2_00bdbbec7bd28d9d_9 tex1_48x51_53403146169829a2_51202438fd7443e1_9 tex1_48x51_53403146169829a2_b85163ac8b4598d4_9
These hashes are all for the same texture - the Big Key in The Legend of Zelda: The Wind Waker. While the first part of the hash is stable, the second part seems effectively random. In fact, Bighead ended up with literally thousands of the same texture with each having a different hash after playing through the game. While the reason for this hasn't been completely isolated, a theory proposed that an unused part of the texture's palette keeps changing for other data. Nevertheless, this left custom texture creators with a very annoying problem.
Techjar decided to look into the situation and realized there was already a bruteforce solution to this. A wildcard symbol had been added years ago for this exact case! With the wildcard symbol, a single texture could represent the thousands of duplicates from the game! ...Except the wildcard symbol was "*", a character that is not valid for filenames on Windows. As such, none of the texture packs made use of it and even if they did, their pack wouldn't work on Windows. As such, Techjar changes the wildcard to $, because this change is straight cash. (TODO: remove this plz)
Now in the case of the duplicate boss keys, there only needs to be a single custom texture - tex1_48x51_53403146169829a2_$_9. This should make completing texture packs much easier, especially when dealing with pesky duplicate dumped textures.
While Dolphin's current peer to peer netplay is optimal for low latency two player games, things tend to fall apart when adding a third/fourth player. A session could only work well in the perfect situation: Over qualified computers with all players having strong internet connections, and games that didn't push things too hard. Most of the time users would end up disappointed or having to use incredibly high buffer that left most action/fighting games out of the question.
While looking at Factorio's networking articles, Techjar got an idea about using Host Input Authority Mode. By giving a host total authority over when inputs are given to the game, clients could run asynchronously without desyncing. This reduction in synchronization results in a much smoother netplay experience and greatly reduces latency in four player matches. If a particular client does stutter or struggle, they won't impact anyone else - instead, they will temporarily fall behind. Then, once the stutters are over, Dolphin will automatically get the player back up to their minimum latency. In most cases of shader generation, slight network hitches, and other forms of temporary slowdown, this process will be invisible. In order to show how it works, here's an extreme example of the process in action.
And that's really why Host Input Authority Mode works so much better for four player games. There was just simply too much synchronization to make it work in realistic situations before. There are some other benefits though for users familiar with Dolphin's netplay. In Host Input Authority Mode, you no longer need to manage your latency to the host. Dolphin will now automatically have your inputs fire as soon as they reach the host! We did keep the buffer option around, but it takes on a new purpose when using this mode. Instead of being directly tied to latency, it acts as a range in which Dolphin considers itself caught up to host. This is a fail-safe to keep unstable connections running smoothly, such as cellular internet. Unless you're on a particularly troublesome connection, you can simply set buffer to zero and let Dolphin give you the minimum possible latency.
There are some potential pitfalls when using Host Input Authority Mode. Because it's asynchronous, if one client is unable to play the game full speed, they won't be able to keep up with the rest of the room. Another thing to keep in mind is that base latency is now roundtrip for clients. This means in a typical two player game, the host gets zero latency and the client has double the latency of peer to peer. For three and four player rooms, Host Input Authority Mode tends to give lower latency as each client is only responsible for their own latency. For more information, check out the following video.
The Question of Dedicated Servers¶
Dedicated Servers could be an extremely useful tool for netplay using Host Input Authority Mode. After all, if you manage to join a server that's just right, you could avoid the double latency penalty of the new mode while getting all of the benefits! A potential use of this would be for competitive Super Smash Bros. Melee and Brawl websites (Okay okay, just kidding about Brawl. Serious fighting games like Shrek SuperSlam could benefit though.)
The idea would be to have dedicated servers for each region where players could join and host games. Because this server is more or less static and you're only responsible for your own latency, you'd be able to get the same amount of latency regardless of who you play while on this server! So if someone from Europe can stomach the lag and play on the East Coast server, they won't impact any of the server's regulars. On top of all of that, because the dedicated server acts as host, no player gets a competitive advantage by playing as host. The kicker? Doubles matches would be fair game as, like explained earlier, there's no latency penalty for having more players in a room! Servers could also automatically record inputs for match verification as the record inputs feature actually works with Host Input Authority Mode!
While this all sounds great, there's still some technical challenges ahead of us before we can even think about implementing dedicated servers. On top of Dolphin's netplay code not being designed for dedicated servers, there's the problem that Dolphin currently requires the host to be emulating the game so it can send emulate Serial Input and MMIO polls. In the long term, dedicated servers could happen, but there are going to need to be a lot of smaller steps and cleanups in order to make that a possibility.