From 80504efcdf6df7a459b47d52bd4ee64902f6e4f1 Mon Sep 17 00:00:00 2001 From: skidau Date: Sat, 31 Dec 2011 15:18:48 +1100 Subject: [PATCH] Changed the Gecko code handling to the native code handler. This provides full compatibility with all Gecko codes. To use the native code handler, place the kenobiwii.bin file into the Sys directory. Dolphin will silently fall-back to the emulated code handler if the file is not there. Fixes issue 4561. --- Source/Core/Common/Src/CommonPaths.h | 2 + Source/Core/Core/Src/Boot/Boot.cpp | 11 ++- Source/Core/Core/Src/GeckoCode.cpp | 98 ++++++++++++++++++++++++ Source/Core/Core/Src/GeckoCode.h | 1 + Source/Core/Core/Src/PatchEngine.cpp | 5 +- Source/Core/Core/Src/PowerPC/PowerPC.cpp | 6 +- Source/Core/Core/Src/PowerPC/PowerPC.h | 1 + 7 files changed, 117 insertions(+), 7 deletions(-) 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();