From 541a42a7e39a0ae9962dc05b4816f296774e47f1 Mon Sep 17 00:00:00 2001 From: EmptyChaos Date: Fri, 23 Sep 2016 12:58:40 +0000 Subject: [PATCH] GeckoCode: Use named constants in ICache flush hack 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. --- Source/Core/Core/Boot/Boot.cpp | 3 ++- Source/Core/Core/GeckoCode.cpp | 7 +++---- Source/Core/Core/GeckoCode.h | 14 ++++++++++++++ Source/Core/Core/HLE/HLE_Misc.cpp | 13 +++++++------ 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp index 44d01a87f2..50cc596bb8 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -17,6 +17,7 @@ #include "Core/ConfigManager.h" #include "Core/Core.h" #include "Core/Debugger/Debugger_SymbolMap.h" +#include "Core/GeckoCode.h" #include "Core/HLE/HLE.h" #include "Core/HW/DVDInterface.h" #include "Core/HW/EXI_DeviceIPL.h" @@ -481,6 +482,6 @@ bool CBoot::BootUp() // 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"); + HLE::Patch(Gecko::ENTRY_POINT, "GeckoCodehandler"); return true; } diff --git a/Source/Core/Core/GeckoCode.cpp b/Source/Core/Core/GeckoCode.cpp index 9ad15b94f6..7e033a8d9e 100644 --- a/Source/Core/Core/GeckoCode.cpp +++ b/Source/Core/Core/GeckoCode.cpp @@ -18,10 +18,8 @@ namespace Gecko { -static constexpr u32 INSTALLER_BASE_ADDRESS = 0x80001800; static constexpr u32 INSTALLER_END_ADDRESS = 0x80003000; static constexpr u32 CODE_SIZE = 8; -static constexpr u32 MAGIC_GAMEID = 0xD01F1BAD; // return true if a code exists bool GeckoCode::Exist(u32 address, u32 data) const @@ -102,6 +100,7 @@ static bool InstallCodeHandlerLocked() const u32 codelist_end_address = INSTALLER_END_ADDRESS; // Write a magic value to 'gameid' (codehandleronly does not actually read this). + // This value will be read back and modified over time by HLE_Misc::HLEGeckoCodehandler. PowerPC::HostWrite_U32(MAGIC_GAMEID, INSTALLER_BASE_ADDRESS); // Create GCT in memory @@ -161,7 +160,7 @@ void RunCodeHandler() if (s_active_codes.empty()) return; - if (!s_code_handler_installed || PowerPC::HostRead_U32(INSTALLER_BASE_ADDRESS) - MAGIC_GAMEID > 5) + if (!s_code_handler_installed) { s_code_handler_installed = InstallCodeHandlerLocked(); @@ -175,7 +174,7 @@ void RunCodeHandler() // the original return address (which will still be in the link register) at the end. if (PC == LR) { - PC = NPC = INSTALLER_BASE_ADDRESS + 0xA8; + PC = NPC = ENTRY_POINT; } } diff --git a/Source/Core/Core/GeckoCode.h b/Source/Core/Core/GeckoCode.h index a54fa22149..47f408f164 100644 --- a/Source/Core/Core/GeckoCode.h +++ b/Source/Core/Core/GeckoCode.h @@ -33,6 +33,20 @@ public: bool Exist(u32 address, u32 data) const; }; +// Installation address for codehandler.bin in the Game's RAM +constexpr u32 INSTALLER_BASE_ADDRESS = 0x80001800; +constexpr u32 ENTRY_POINT = 0x800018A8; + +// This forms part of a communication protocol with HLE_Misc::HLEGeckoCodehandler. +// Basically, codehandleronly.s doesn't use ICBI like it's supposed to when patching the +// game's code. This results in the JIT happily ignoring all code patches for blocks that +// are already compiled. The hack for getting around that is that the first 5 frames after +// the handler is installed (0xD01F1BAD -> +5 -> 0xD01F1BB2) cause full ICache resets. +// +// HLEGeckoCodehandler will increment this value 5 times then cease flushing the ICache to +// preserve the emulation performance. +constexpr u32 MAGIC_GAMEID = 0xD01F1BAD; + void SetActiveCodes(const std::vector& gcodes); void RunCodeHandler(); diff --git a/Source/Core/Core/HLE/HLE_Misc.cpp b/Source/Core/Core/HLE/HLE_Misc.cpp index a59b474916..d2a32262d4 100644 --- a/Source/Core/Core/HLE/HLE_Misc.cpp +++ b/Source/Core/Core/HLE/HLE_Misc.cpp @@ -7,6 +7,7 @@ #include "Common/CommonTypes.h" #include "Core/ConfigManager.h" +#include "Core/GeckoCode.h" #include "Core/HLE/HLE_Misc.h" #include "Core/HW/CPU.h" #include "Core/Host.h" @@ -47,17 +48,17 @@ void HLEGeckoCodehandler() // 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 = PowerPC::HostRead_U32(0x80001800); - if (existing - magic == 5) + u32 gch_gameid = PowerPC::HostRead_U32(Gecko::INSTALLER_BASE_ADDRESS); + if (gch_gameid - Gecko::MAGIC_GAMEID == 5) { return; } - else if (existing - magic > 5) + else if (gch_gameid - Gecko::MAGIC_GAMEID > 5) { - existing = magic; + gch_gameid = Gecko::MAGIC_GAMEID; } - PowerPC::HostWrite_U32(existing + 1, 0x80001800); + PowerPC::HostWrite_U32(gch_gameid + 1, Gecko::INSTALLER_BASE_ADDRESS); + PowerPC::ppcState.iCache.Reset(); } }