diff --git a/Source/Core/Core/Src/Boot/Boot.cpp b/Source/Core/Core/Src/Boot/Boot.cpp index 6f8f67bf11..9f48b87a32 100644 --- a/Source/Core/Core/Src/Boot/Boot.cpp +++ b/Source/Core/Core/Src/Boot/Boot.cpp @@ -192,6 +192,10 @@ bool CBoot::BootUp() Memory::WriteBigEData(stubstr, 0x80001804, 8); } + // Not part of the binary itself, but either we or Gecko OS might insert + // this, and it doesn't clear the icache properly. + HLE::Patch(0x800018a8, "GeckoCodehandler"); + g_symbolDB.Clear(); VideoInterface::Preset(_StartupPara.bNTSC); switch (_StartupPara.m_BootType) diff --git a/Source/Core/Core/Src/HLE/HLE.cpp b/Source/Core/Core/Src/HLE/HLE.cpp index 6469359a31..3d3d8d6052 100644 --- a/Source/Core/Core/Src/HLE/HLE.cpp +++ b/Source/Core/Core/Src/HLE/HLE.cpp @@ -63,6 +63,7 @@ static const SPatch OSPatches[] = { "___blank(char *,...)", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, // used for early init things (normally) { "___blank", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, { "__write_console", HLE_OS::HLE_write_console, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, // used by sysmenu (+more?) + { "GeckoCodehandler", HLE_Misc::HLEGeckoCodehandler, HLE_HOOK_START, HLE_TYPE_GENERIC }, }; static const SPatch OSBreakPoints[] = diff --git a/Source/Core/Core/Src/HLE/HLE_Misc.cpp b/Source/Core/Core/Src/HLE/HLE_Misc.cpp index 0b5db4f17f..fa5f8c7d61 100644 --- a/Source/Core/Core/Src/HLE/HLE_Misc.cpp +++ b/Source/Core/Core/Src/HLE/HLE_Misc.cpp @@ -17,6 +17,7 @@ #include "IPC_HLE/WII_IPC_HLE_Device_usb.h" #include "HLE.h" #include "PowerPC/PPCAnalyst.h" +#include "PowerPC/PPCCache.h" #include "PowerPC/SignatureDB.h" #include "PowerPC/PPCSymbolDB.h" #include "CommonPaths.h" @@ -242,4 +243,26 @@ void OSBootDol() NPC = PC; } +void HLEGeckoCodehandler() +{ + // Work around the codehandler not properly invalidating the icache, but + // only the first few frames. + // (Project M uses a conditional to only apply patches after something has + // been read into memory, or such, so we do the first 5 frames. More + // robust alternative would be to actually detect memory writes, but that + // would be even uglier.) + u32 magic = 0xd01f1bad; + u32 existing = Memory::Read_U32(0x80001800); + if (existing - magic == 5) + { + return; + } + else if(existing - magic > 5) + { + existing = magic; + } + Memory::Write_U32(existing + 1, 0x80001800); + PowerPC::ppcState.iCache.Reset(); +} + } diff --git a/Source/Core/Core/Src/HLE/HLE_Misc.h b/Source/Core/Core/Src/HLE/HLE_Misc.h index 43924a4dcf..bc3acd143f 100644 --- a/Source/Core/Core/Src/HLE/HLE_Misc.h +++ b/Source/Core/Core/Src/HLE/HLE_Misc.h @@ -12,6 +12,7 @@ namespace HLE_Misc void HBReload(); void OSBootDol(); void OSGetResetCode(); + void HLEGeckoCodehandler(); } #endif