GeckoCodes require address hooks which don't correspond to any
symbol in the symbol table. The hooks get deleted when repatching
the game because they did not persist across calls to
HLE::PatchFunctions.
Dolphin emulates GeckoCodes by fiddling with the CPU state when a
VI Interrupt occurs. The problem with this is that we don't know
where the PC is so it's non-deterministic and not necessarily
suitable for use with the codehandler.
There are two options: Patch the game like Gecko OS either directly
or using HLE::Patch, or use a trampoline so we can branch from any
PC even if it would otherwise not be valid. The problem with Gecko OS
patches is there are 10 of them and they have to be configured
manually (i.e. Game INIs to would need to have a [Core]GeckoHookType
property).
HLE_Misc::GeckoReturnTrampoline enables the Code Handler to be
entered from anywhere, the trampoline restores all the registers that
had to be secretly saved to the stack.
If the installation fails because codehandler.bin is missing or
unusable then Dolphin will try again every single frame even though
it's highly unlikely a disk file will have changed. Better to just
fail once then only try again when the active code set is changed.
Suppresses generating 60 log messages per second.
Turns out one of the magic numbers was very magic. The gameid is
an ad-hoc comm protocol with HLE_Misc to control the number of times
the ICache is reset.
The code table builder cuts off the end of codes that won't fit
after already writing part of it. That seems quite unlikely to
work the way anyone would find useful since the codes can contain
actual PPC instructions.
The active codes vector cannot safely be used outside the mutex,
move the lock out into RunCodeHandler. s_code_handler_installed was
also racing against SetActiveCodes since it's being written both
inside and outside the lock.
General cleanup. Add s_ prefixes, use constexpr, remove C casts.
Executing PPC code inside an external events callback is a bad idea.
CoreTiming::Advance does not support recursion properly which will
cause timing glitches. The interpreter has a slice length hack that
counters this but without it this would cause a 20000 cycles time
skip. It isn't clear what this was supposed to accomplish that just
changing the current PC would not. Changing the PC works fine.
Deleting instead of overwriting makes the INI cleaner.
Also, in case we change defaults in the future, users will
get the new default when using a new version even if
they have pressed the Reset button in an older version.
Makes the buffering code a bit more explicit (circular buffer, but
blocks until individual buffers get unqueued by OpenAL), and fixes a
bug in the startup of Super Mario Sunshine:
https://bugs.dolphin-emu.org/issues/9811