diff --git a/Source/Core/Common/Src/CommonPaths.h b/Source/Core/Common/Src/CommonPaths.h index 8d37482ce1..150453928e 100644 --- a/Source/Core/Common/Src/CommonPaths.h +++ b/Source/Core/Common/Src/CommonPaths.h @@ -126,6 +126,8 @@ #define WII_USA_SETTING "setting-usa.txt" #define WII_JAP_SETTING "setting-jpn.txt" +#define GECKO_CODE_HANDLER "kenobiwii.bin" + // Subdirs in Sys #define GC_SYS_DIR "GC" #define WII_SYS_DIR "Wii" diff --git a/Source/Core/Core/Src/Boot/Boot.cpp b/Source/Core/Core/Src/Boot/Boot.cpp index 5a9880533e..3dcbf5730c 100644 --- a/Source/Core/Core/Src/Boot/Boot.cpp +++ b/Source/Core/Core/Src/Boot/Boot.cpp @@ -195,10 +195,13 @@ bool CBoot::BootUp() NOTICE_LOG(BOOT, "Booting %s", _StartupPara.m_strFilename.c_str()); - // HLE jump to loader (homebrew) - HLE::Patch(0x80001800, "HBReload"); - const u8 stubstr[] = { 'S', 'T', 'U', 'B', 'H', 'A', 'X', 'X' }; - Memory::WriteBigEData(stubstr, 0x80001804, 8); + // HLE jump to loader (homebrew). Disabled when Gecko is active as it interferes with the code handler + if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats) + { + HLE::Patch(0x80001800, "HBReload"); + const u8 stubstr[] = { 'S', 'T', 'U', 'B', 'H', 'A', 'X', 'X' }; + Memory::WriteBigEData(stubstr, 0x80001804, 8); + } g_symbolDB.Clear(); VideoInterface::Preset(_StartupPara.bNTSC); diff --git a/Source/Core/Core/Src/GeckoCode.cpp b/Source/Core/Core/Src/GeckoCode.cpp index 9ea30b9fb0..207aa8fb8b 100644 --- a/Source/Core/Core/Src/GeckoCode.cpp +++ b/Source/Core/Core/Src/GeckoCode.cpp @@ -5,6 +5,8 @@ #include "ConfigManager.h" #include "vector" +#include "PowerPC/PowerPC.h" +#include "CommonPaths.h" namespace Gecko { @@ -40,6 +42,9 @@ static struct // codes execute when counter is 0 static int code_execution_counter = 0; +// Track whether the code handler has been installed +static bool code_handler_installed = false; + // the currently active codes std::vector active_codes; @@ -93,6 +98,64 @@ void SetActiveCodes(const std::vector& gcodes) } inserted_asm_codes.clear(); + + code_handler_installed = false; +} + +bool InstallCodeHandler() +{ + std::string data; + std::string _rCodeHandlerFilename = File::GetSysDirectory() + GECKO_CODE_HANDLER; + if (!File::ReadFileToString(false, _rCodeHandlerFilename.c_str(), data)) + return false; + + // Install code handler + Memory::WriteBigEData((const u8*)data.data(), 0x80001800, data.length()); + + // Turn off Pause on start + Memory::Write_U32(0, 0x80001808); + + // Write the Game ID into the location expected by WiiRD + Memory::WriteBigEData(Memory::GetPointer(0x80000000), 0x80001800, 6); + + // Create GCT in memory + Memory::Write_U32(0x00d0c0de, 0x800027d0); + Memory::Write_U32(0x00d0c0de, 0x800027d4); + + std::lock_guard lk(active_codes_lock); + + int i = 0; + std::vector::iterator + gcodes_iter = active_codes.begin(), + gcodes_end = active_codes.end(); + for (; gcodes_iter!=gcodes_end; ++gcodes_iter) + { + if (gcodes_iter->enabled) + { + current_code = codes_start = &*gcodes_iter->codes.begin(); + codes_end = &*gcodes_iter->codes.end(); + for (; current_code < codes_end; ++current_code) + { + const GeckoCode::Code& code = *current_code; + Memory::Write_U32(code.address, 0x800027d8 + i); + Memory::Write_U32(code.data, 0x800027d8 + i + 4); + i += 8; + } + } + } + + Memory::Write_U32(0xff000000, 0x800027d8 + i); + Memory::Write_U32(0x00000000, 0x800027d8 + i + 4); + + // Turn on codes + Memory::Write_U8(1, 0x80001807); + + // Invalidate the icache + for (int i = 0; i < data.length(); i += 32) + { + PowerPC::ppcState.iCache.Invalidate(0x80001800 + i); + } + return true; } bool RunGeckoCode(GeckoCode& gecko_code) @@ -168,6 +231,41 @@ bool RunActiveCodes() return true; } +void RunCodeHandler() +{ + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats) + { + if (!code_handler_installed) + code_handler_installed = InstallCodeHandler(); + + if (code_handler_installed) + { + if (PC == LR) + { + u32 oldLR = LR; + PowerPC::CoreMode oldMode = PowerPC::GetMode(); + + PC = 0x800018A8; + LR = 0; + + // Execute the code handler in interpreter mode to track when it exits + PowerPC::SetMode(PowerPC::MODE_INTERPRETER); + + while (PC != 0) + PowerPC::SingleStep(); + + PowerPC::SetMode(oldMode); + PC = LR = oldLR; + } + } + else + { + // Use the emulated code handler + Gecko::RunActiveCodes(); + } + } +} + const std::map >& GetInsertedAsmCodes() { return inserted_asm_codes; } diff --git a/Source/Core/Core/Src/GeckoCode.h b/Source/Core/Core/Src/GeckoCode.h index 016e38f3d2..1cd83bdf65 100644 --- a/Source/Core/Core/Src/GeckoCode.h +++ b/Source/Core/Core/Src/GeckoCode.h @@ -67,6 +67,7 @@ namespace Gecko void SetActiveCodes(const std::vector& gcodes); bool RunActiveCodes(); + void RunCodeHandler(); const std::map >& GetInsertedAsmCodes(); } // namespace Gecko diff --git a/Source/Core/Core/Src/PatchEngine.cpp b/Source/Core/Core/Src/PatchEngine.cpp index 6528ad6752..74e778c916 100644 --- a/Source/Core/Core/Src/PatchEngine.cpp +++ b/Source/Core/Core/Src/PatchEngine.cpp @@ -210,13 +210,14 @@ void ApplyPatches(const std::vector &patches) void ApplyFramePatches() { ApplyPatches(onFrame); + + // Run the Gecko code handler + Gecko::RunCodeHandler(); } void ApplyARPatches() { ActionReplay::RunAllActive(); - // w/e this can be changed later - Gecko::RunActiveCodes(); } } // namespace diff --git a/Source/Core/Core/Src/PowerPC/PowerPC.cpp b/Source/Core/Core/Src/PowerPC/PowerPC.cpp index a247ec5035..7e5d9ba763 100644 --- a/Source/Core/Core/Src/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/Src/PowerPC/PowerPC.cpp @@ -213,6 +213,11 @@ void Shutdown() state = CPU_POWERDOWN; } +CoreMode GetMode() +{ + return mode; +} + void SetMode(CoreMode new_mode) { if (new_mode == mode) @@ -223,7 +228,6 @@ void SetMode(CoreMode new_mode) switch (mode) { case MODE_INTERPRETER: // Switching from JIT to interpreter - jit->ClearCache(); // Remove all those nasty JIT patches. cpu_core_base = interpreter; break; diff --git a/Source/Core/Core/Src/PowerPC/PowerPC.h b/Source/Core/Core/Src/PowerPC/PowerPC.h index 9ac979bcfb..54690ac6b5 100644 --- a/Source/Core/Core/Src/PowerPC/PowerPC.h +++ b/Source/Core/Core/Src/PowerPC/PowerPC.h @@ -97,6 +97,7 @@ void Init(int cpu_core); void Shutdown(); void DoState(PointerWrap &p); +CoreMode GetMode(); void SetMode(CoreMode _coreType); void SingleStep();