diff --git a/Data/Sys/codehandler.bin b/Data/Sys/codehandler.bin new file mode 100644 index 0000000000..7a95e724b1 Binary files /dev/null and b/Data/Sys/codehandler.bin differ diff --git a/Source/Core/Common/Src/CommonPaths.h b/Source/Core/Common/Src/CommonPaths.h index 8d37482ce1..d319fb541e 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 "codehandler.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..c0b7af3779 100644 --- a/Source/Core/Core/Src/GeckoCode.cpp +++ b/Source/Core/Core/Src/GeckoCode.cpp @@ -1,3 +1,17 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + #include "GeckoCode.h" #include "Thread.h" @@ -5,6 +19,8 @@ #include "ConfigManager.h" #include "vector" +#include "PowerPC/PowerPC.h" +#include "CommonPaths.h" namespace Gecko { @@ -40,6 +56,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 +112,70 @@ void SetActiveCodes(const std::vector& gcodes) } inserted_asm_codes.clear(); + + code_handler_installed = false; +} + +bool InstallCodeHandler() +{ + u32 codelist_location = 0x800028B8; // Debugger on location (0x800022A8 = Debugger off, using codehandleronly.bin) + 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, 0x80002774); + + // 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, codelist_location); + Memory::Write_U32(0x00d0c0de, codelist_location + 4); + + 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; + + // Make sure we have enough memory to hold the code list + if ((codelist_location + 24 + i) < 0x80003000) + { + Memory::Write_U32(code.address, codelist_location + 8 + i); + Memory::Write_U32(code.data, codelist_location + 12 + i); + i += 8; + } + } + } + } + + Memory::Write_U32(0xff000000, codelist_location + 8 + i); + Memory::Write_U32(0x00000000, codelist_location + 12 + i); + + // 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) @@ -137,7 +220,7 @@ bool RunGeckoCode(GeckoCode& gecko_code) gecko_code.enabled = false; PanicAlertT("GeckoCode failed to run (CT%i CST%i) (%s)" - "\n(either a bad code or the code type is not yet supported.)" + "\n(either a bad code or the code type is not yet supported. Try using the native code handler by placing the codehandler.bin file into the Sys directory and restarting Dolphin.)" , code.type, code.subtype, gecko_code.name.c_str()); return false; } @@ -168,6 +251,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..d9a53dcfc3 100644 --- a/Source/Core/Core/Src/GeckoCode.h +++ b/Source/Core/Core/Src/GeckoCode.h @@ -1,3 +1,16 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ #ifndef __GECKOCODE_h__ #define __GECKOCODE_h__ @@ -67,6 +80,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/GeckoCodeConfig.cpp b/Source/Core/Core/Src/GeckoCodeConfig.cpp index f0e5a0585b..a23d531f7e 100644 --- a/Source/Core/Core/Src/GeckoCodeConfig.cpp +++ b/Source/Core/Core/Src/GeckoCodeConfig.cpp @@ -1,3 +1,16 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ #include "GeckoCodeConfig.h" diff --git a/Source/Core/Core/Src/GeckoCodeConfig.h b/Source/Core/Core/Src/GeckoCodeConfig.h index d7e28086c7..0ae630f784 100644 --- a/Source/Core/Core/Src/GeckoCodeConfig.h +++ b/Source/Core/Core/Src/GeckoCodeConfig.h @@ -1,3 +1,16 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ #ifndef __GECKOCODECONFIG_h__ #define __GECKOCODECONFIG_h__ 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(); diff --git a/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp b/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp index c491424376..e9089c6006 100644 --- a/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp +++ b/Source/Core/DolphinWX/Src/GeckoCodeDiag.cpp @@ -1,3 +1,16 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ #include "GeckoCodeDiag.h" diff --git a/Source/Core/DolphinWX/Src/GeckoCodeDiag.h b/Source/Core/DolphinWX/Src/GeckoCodeDiag.h index 92328d5f43..338c57c6e9 100644 --- a/Source/Core/DolphinWX/Src/GeckoCodeDiag.h +++ b/Source/Core/DolphinWX/Src/GeckoCodeDiag.h @@ -1,3 +1,16 @@ +// Copyright (C) 2003 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ #ifndef __GECKOCODEDIAG_h__ #define __GECKOCODEDIAG_h__