This hack was added in 8f0cbefbe5, and the part of it in SI_DeviceGCAdapter is present on Android already, so I don't see any reason why this part doesn't apply to Android.
This is mostly a brainless merge, #ifdef-ing anything that doesn't match between the two while preserving common logic. I didn't rename any variables (although similar ones do exist), but I did change one log that was ERROR on android and NOTICE elsewhere to just always be NOTICE. Further merging will follow.
The current code expects new mail almost immediately after the last map was sent for it to be saved properly. However, I have a test program that ends up looping for 32768 iterations before it sends more mail; this resulted in an incomplete result dump. I've changed it to wait a frame between checking for mail, which solves that issue. This does slow down dumping, but the end speed matches the speed at which the UI updates the registers so this isn't a big deal (the UI waits a frame between mail normally). (Theoretically, it could take even longer for dumping to finish, so this is not a perfect solution. However, for tests that take that long to run, it would be better to save the existing results instead of re-running the test and saving that; that'd be something to do with later improvements.)
There were 3 bugs here:
- The input register for the full register wasn't actually being used; it was read into RCX but RCX wasn't used by Update_SR_Register16_OverS32 (except as a scratch register). The way the DSP LLE recompiler uses registers is in general confusing, so this commit changes a few uses to have a variable for the register being used, to make code a bit more readable. (Default parameter values were also removed so that they needed to be explicitly specified).
- Update_SR_Register16 was doing a 64-bit test, when it should have been doing a 16-bit test. For the most part this doesn't matter due to sign-extension, but it does come up with e.g. `ORI` or `ANDI`.
- Update_SR_Register16_OverS32 did the over s32 check, and then called Update_SR_Register16. Update_SR_Register16 masks $sr with ~SR_CMP_MASK, clearing the over s32 bit. Now the over s32 check is performed after calling Update_SR_Register16 (without masking a second time). No official uCode cares about the over s32 bit.
We don't have anything called $amD, though we do have $acsD. However, these instructions affect flags based on the whole accumulator, so it's better to just use $acD.
For more information, ApplyWriteBackLog, WriteToBackLog, and ZeroWriteBackLog were added in b787f5f8f7 and the explanatory comment was added in fd40513fed, although it did not mention the specific instructions that could trigger this edge case. The statements about which registers can be written by main opcodes and extension opcodes are based on my own checking of all instructions in the manual.
It's been unused since DolphinWX was removed in 44b22c90df. Prior to that, it was used in Source/Core/DolphinWX/NetPlay/NetWindow.cpp. But the new equivalent in Source/Core/DolphinQt/NetPlay/NetPlayDialog.cpp uses NetPlayClient::GetPlayers instead. Stringifying (or creating a table, as is done now) should be done by the UI in any case.
Among other things, this trims trailing newline characters. Before (on windows) the \r would corrupt the output and make them very hard to understand (as the error message would be drawn over the code line, but part of the code line would peek out from behind it).
Without this, execution continues beyond the end of the function, into the great unknown (probably eventually falling into either code left from a previous test, or the start of the DSP ROM). end_of_test is just an infinite loop to stop executing until the DSP is reset.