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.
This commit is contained in:
EmptyChaos 2016-09-23 12:58:40 +00:00
parent 4fef9d8d64
commit 541a42a7e3
4 changed files with 26 additions and 11 deletions

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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<GeckoCode>& gcodes);
void RunCodeHandler();

View File

@ -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();
}
}