diff --git a/Source/Core/Common/CommonPaths.h b/Source/Core/Common/CommonPaths.h index 9e97dac6f1..d44bcb2a89 100644 --- a/Source/Core/Common/CommonPaths.h +++ b/Source/Core/Common/CommonPaths.h @@ -162,6 +162,8 @@ #define GECKO_CODE_HANDLER_MPN "codehandler-mpn.bin" +#define GECKO_CODE_HANDLER_MPN_SUPER "codehandler-mpn.bin" + // Subdirs in Sys #define GC_SYS_DIR "GC" #define WII_SYS_DIR "Wii" diff --git a/Source/Core/Core/Config/MainSettings.h b/Source/Core/Core/Config/MainSettings.h index 9e29dc9d49..d7e78bf6e9 100644 --- a/Source/Core/Core/Config/MainSettings.h +++ b/Source/Core/Core/Config/MainSettings.h @@ -67,7 +67,6 @@ extern const Info MAIN_CPU_THREAD; extern const Info MAIN_SYNC_ON_SKIP_IDLE; extern const Info MAIN_DEFAULT_ISO; extern const Info MAIN_ENABLE_CHEATS; -extern const Info MAIN_CODE_HANDLER; extern const Info MAIN_GC_LANGUAGE; extern const Info MAIN_OVERRIDE_REGION_SETTINGS; extern const Info MAIN_DPL2_DECODER; diff --git a/Source/Core/Core/ConfigManager.cpp b/Source/Core/Core/ConfigManager.cpp index e9a382d235..b51521bd7d 100644 --- a/Source/Core/Core/ConfigManager.cpp +++ b/Source/Core/Core/ConfigManager.cpp @@ -89,8 +89,7 @@ SConfig::~SConfig() namespace Config { - // Initialize the configuration option - const Info MAIN_CODE_HANDLER{{System::Main, "CodeHandler", "UseMPN"}, false}; + const Info MAIN_CODE_HANDLER{{System::Main, "CodeHandler", "CodeHandlerValue"}, 0}; } void SConfig::SaveSettings() diff --git a/Source/Core/Core/ConfigManager.h b/Source/Core/Core/ConfigManager.h index f333ee8635..6a3151d476 100644 --- a/Source/Core/Core/ConfigManager.h +++ b/Source/Core/Core/ConfigManager.h @@ -34,13 +34,11 @@ enum class Region; struct Partition; class Volume; } // namespace DiscIO - namespace Config { - // Define the configuration option - extern const Info MAIN_CODE_HANDLER; -} - +// Define the configuration option +extern const Info MAIN_CODE_HANDLER; +} // namespace Config namespace IOS::ES { class TMDReader; @@ -52,7 +50,7 @@ struct SConfig { // Settings bool bBootToPause = false; - + bool bJITNoBlockCache = false; bool bJITNoBlockLinking = false; diff --git a/Source/Core/Core/GeckoCode.cpp b/Source/Core/Core/GeckoCode.cpp index 456c4f8387..8d304d1cb0 100644 --- a/Source/Core/Core/GeckoCode.cpp +++ b/Source/Core/Core/GeckoCode.cpp @@ -122,19 +122,27 @@ std::vector SetAndReturnActiveCodes(std::span gcodes const char* GetGeckoCodeHandlerPath() { - return Config::Get(Config::MAIN_CODE_HANDLER) ? - GECKO_CODE_HANDLER_MPN : GECKO_CODE_HANDLER; + int code_handler_value = Config::Get(Config::MAIN_CODE_HANDLER); // Get the integer value + switch (code_handler_value) + { + case 0: return GECKO_CODE_HANDLER; // Dolphin (Stock) + case 1: return GECKO_CODE_HANDLER_MPN; // MPN (Extended) + case 2: return GECKO_CODE_HANDLER_MPN_SUPER; // MPN (Super Extended) + default: return GECKO_CODE_HANDLER; // Fallback + } } bool IsGeckoCodeHandlerEnabled() { - return Config::Get(Config::MAIN_CODE_HANDLER); + int code_handler_value = Config::Get(Config::MAIN_CODE_HANDLER); // Get the integer value + return code_handler_value == 1 || code_handler_value == 2; // Return true for 1 and 2 } - -const char* code_handler_file = GetGeckoCodeHandlerPath(); - -const bool is_mpn_handler = (code_handler_file = GECKO_CODE_HANDLER_MPN); +bool IsGeckoCodeHandlerSUPER() +{ + int code_handler_value = Config::Get(Config::MAIN_CODE_HANDLER); // Get the integer value + return code_handler_value == 2; // Return true for 1 and 2 +} // Requires s_active_codes_lock // NOTE: Refer to "codehandleronly.s" from Gecko OS. @@ -159,187 +167,117 @@ static Installation InstallCodeHandlerLocked(const Core::CPUThreadGuard& guard) mmio_addr = 0xCD; } - auto free_memory_base_address = Core::getGameFreeMemory(); - bool use_free_memory = free_memory_base_address.has_value(); - if (use_free_memory && is_mpn_handler == true) + // Install code handler + for (u32 i = 0; i < data.size(); ++i) + PowerPC::MMU::HostWrite_U8(guard, data[i], INSTALLER_BASE_ADDRESS + i); + + // Patch the code handler to the current system type (Gamecube/Wii) + for (u32 h = 0; h < data.length(); h += 4) { - // Move Gecko code handler to the free mem region - u32 codelist_base_address = free_memory_base_address.value().first; - u32 codelist_end_address = free_memory_base_address.value().second; - u32 codelist_start_address = free_memory_base_address.value().first; - - // Install code handler - for (u32 i = 0; i < data.size(); ++i) - PowerPC::MMU::HostWrite_U8(guard, data[i], codelist_base_address + i); - - // Patch the code handler to the current system type (Gamecube/Wii) - for (u32 h = 0; h < data.length(); h += 4) + // Patch MMIO address + if (PowerPC::MMU::HostRead_U32(guard, INSTALLER_BASE_ADDRESS + h) == + (0x3f000000u | ((mmio_addr ^ 1) << 8))) { - // Patch MMIO address - if (PowerPC::MMU::HostRead_U32(guard, codelist_base_address + h) == - (0x3f000000u | ((mmio_addr ^ 1) << 8))) - { - NOTICE_LOG_FMT(ACTIONREPLAY, "Patching MMIO access at {:08x}", codelist_base_address + h); - PowerPC::MMU::HostWrite_U32(guard, 0x3f000000u | mmio_addr << 8, codelist_base_address + h); - } + NOTICE_LOG_FMT(ACTIONREPLAY, "Patching MMIO access at {:08x}", INSTALLER_BASE_ADDRESS + h); + PowerPC::MMU::HostWrite_U32(guard, 0x3f000000u | mmio_addr << 8, INSTALLER_BASE_ADDRESS + h); } + } + const bool is_mpn_handler_and_game_id_gp7e01 = + IsGeckoCodeHandlerSUPER() && (SConfig::GetInstance().GetGameID() == "GP7E01"); + const bool is_mpn_handler_and_game_id_gp6e01 = + IsGeckoCodeHandlerSUPER() && (SConfig::GetInstance().GetGameID() == "GP6E01"); + const bool is_mpn_handler_and_game_id_gp5e01 = + IsGeckoCodeHandlerSUPER() && (SConfig::GetInstance().GetGameID() == "GP5E01"); + + u32 codelist_base_address = + is_mpn_handler_and_game_id_gp7e01 ? INSTALLER_BASE_ADDRESS_MP7 : + is_mpn_handler_and_game_id_gp6e01 ? INSTALLER_BASE_ADDRESS_MP6 : + is_mpn_handler_and_game_id_gp5e01 ? INSTALLER_BASE_ADDRESS_MP5 : + INSTALLER_BASE_ADDRESS + static_cast(data.size()) - + CODE_SIZE; + + u32 codelist_end_address = is_mpn_handler_and_game_id_gp7e01 ? INSTALLER_END_ADDRESS_MP7 : + is_mpn_handler_and_game_id_gp6e01 ? INSTALLER_END_ADDRESS_MP6 : + is_mpn_handler_and_game_id_gp5e01 ? INSTALLER_END_ADDRESS_MP5 : + INSTALLER_END_ADDRESS; + + if (is_mpn_handler_and_game_id_gp7e01 || is_mpn_handler_and_game_id_gp6e01 || + is_mpn_handler_and_game_id_gp5e01) + { + + // Move Gecko code handler to the free mem region + for (u32 addr = codelist_base_address; addr < codelist_end_address; addr += 4) + { + PowerPC::MMU::HostWrite_U32(guard, 0x00000000, addr); + } PowerPC::MMU::HostWrite_U32(guard, ((codelist_base_address & 0xFFFF0000) >> 16) + 0x3DE00000, 0x80001904); PowerPC::MMU::HostWrite_U32(guard, (codelist_base_address & 0x0000FFFF) + 0x61EF0000, 0x80001908); + } - // 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::GeckoCodeHandlerICacheFlush. - PowerPC::MMU::HostWrite_U32(guard, MAGIC_GAMEID, codelist_start_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::GeckoCodeHandlerICacheFlush. + PowerPC::MMU::HostWrite_U32(guard, MAGIC_GAMEID, codelist_base_address); - // Create GCT in memory - PowerPC::MMU::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address); - PowerPC::MMU::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address + 4); + // Create GCT in memory + PowerPC::MMU::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address); + PowerPC::MMU::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address + 4); - // Each code is 8 bytes (2 words) wide. There is a starter code and an end code. - const u32 start_address = codelist_base_address + CODE_SIZE; - const u32 end_address = codelist_end_address - CODE_SIZE; - u32 next_address = start_address; + // Each code is 8 bytes (2 words) wide. There is a starter code and an end code. + const u32 start_address = codelist_base_address + CODE_SIZE; + const u32 end_address = codelist_end_address - CODE_SIZE; + u32 next_address = start_address; - // NOTE: Only active codes are in the list - for (const GeckoCode& active_code : s_active_codes) + // NOTE: Only active codes are in the list + for (const GeckoCode& active_code : s_active_codes) + { + // If the code is not going to fit in the space we have left then we have to skip it + if (next_address + active_code.codes.size() * CODE_SIZE > end_address) { - // If the code is not going to fit in the space we have left then we have to skip it - if (next_address + active_code.codes.size() * CODE_SIZE > end_address) - { - NOTICE_LOG_FMT(ACTIONREPLAY, - "Too many GeckoCodes! Ran out of storage space in Game RAM. Could " - "not write: \"{}\". Need {} bytes, only {} remain.", - active_code.name, active_code.codes.size() * CODE_SIZE, - end_address - next_address); - OSD::AddMessage( - fmt::format("Too many GeckoCodes! Ran out of storage space in Game RAM. Could " - "not write: \"{}\". Need {} bytes, only {} remain.", - active_code.name, active_code.codes.size() * CODE_SIZE, - end_address - next_address), - OSD::Duration::VERY_LONG); - continue; - } - - for (const GeckoCode::Code& code : active_code.codes) - { - PowerPC::MMU::HostWrite_U32(guard, code.address, next_address); - PowerPC::MMU::HostWrite_U32(guard, code.data, next_address + 4); - next_address += CODE_SIZE; - } + NOTICE_LOG_FMT(ACTIONREPLAY, + "Too many GeckoCodes! Ran out of storage space in Game RAM. Could " + "not write: \"{}\". Need {} bytes, only {} remain.", + active_code.name, active_code.codes.size() * CODE_SIZE, + end_address - next_address); + OSD::AddMessage(fmt::format("Too many GeckoCodes! Ran out of storage space in Game RAM. Could " + "not write: \"{}\". Need {} bytes, only {} remain.", + active_code.name, active_code.codes.size() * CODE_SIZE, + end_address - next_address), + OSD::Duration::VERY_LONG); + continue; } - WARN_LOG_FMT(ACTIONREPLAY, "GeckoCodes: Using {} of {} bytes", next_address - start_address, - end_address - start_address); - - OSD::AddMessage(fmt::format("Gecko Codes: Using {} of {} bytes", next_address - start_address, - end_address - start_address)); - - // Stop code. Tells the handler that this is the end of the list. - PowerPC::MMU::HostWrite_U32(guard, 0xF0000000, next_address); - PowerPC::MMU::HostWrite_U32(guard, 0x00000000, next_address + 4); - PowerPC::MMU::HostWrite_U32(guard, 0, HLE_TRAMPOLINE_ADDRESS); - - // Turn on codes - PowerPC::MMU::HostWrite_U8(guard, 1, codelist_start_address + 7); - - // Invalidate the icache and any asm codes - auto& ppc_state = guard.GetSystem().GetPPCState(); - auto& memory = guard.GetSystem().GetMemory(); - auto& jit_interface = guard.GetSystem().GetJitInterface(); - for (u32 j = 0; j < (INSTALLER_END_ADDRESS - codelist_start_address); j += 32) + for (const GeckoCode::Code& code : active_code.codes) { - ppc_state.iCache.Invalidate(memory, jit_interface, codelist_start_address + j); + PowerPC::MMU::HostWrite_U32(guard, code.address, next_address); + PowerPC::MMU::HostWrite_U32(guard, code.data, next_address + 4); + next_address += CODE_SIZE; } } - else + + WARN_LOG_FMT(ACTIONREPLAY, "GeckoCodes: Using {} of {} bytes", next_address - start_address, + end_address - start_address); + + OSD::AddMessage(fmt::format("Gecko Codes: Using {} of {} bytes", next_address - start_address, + end_address - start_address)); + + // Stop code. Tells the handler that this is the end of the list. + PowerPC::MMU::HostWrite_U32(guard, 0xF0000000, next_address); + PowerPC::MMU::HostWrite_U32(guard, 0x00000000, next_address + 4); + PowerPC::MMU::HostWrite_U32(guard, 0, HLE_TRAMPOLINE_ADDRESS); + + // Turn on codes + PowerPC::MMU::HostWrite_U8(guard, 1, INSTALLER_BASE_ADDRESS + 7); + + // Invalidate the icache and any asm codes + auto& ppc_state = guard.GetSystem().GetPPCState(); + auto& memory = guard.GetSystem().GetMemory(); + auto& jit_interface = guard.GetSystem().GetJitInterface(); + for (u32 j = 0; j < (codelist_end_address - codelist_base_address); j += 32) { - u32 codelist_base_address = INSTALLER_BASE_ADDRESS + static_cast(data.size()) - CODE_SIZE; - u32 codelist_end_address = INSTALLER_END_ADDRESS; - u32 codelist_start_address = INSTALLER_BASE_ADDRESS; - - - // Install code handler - for (u32 i = 0; i < data.size(); ++i) - PowerPC::MMU::HostWrite_U8(guard, data[i], INSTALLER_BASE_ADDRESS + i); - - // Patch the code handler to the current system type (Gamecube/Wii) - for (u32 h = 0; h < data.length(); h += 4) - { - // Patch MMIO address - if (PowerPC::MMU::HostRead_U32(guard, INSTALLER_BASE_ADDRESS + h) == - (0x3f000000u | ((mmio_addr ^ 1) << 8))) - { - NOTICE_LOG_FMT(ACTIONREPLAY, "Patching MMIO access at {:08x}", INSTALLER_BASE_ADDRESS + h); - PowerPC::MMU::HostWrite_U32(guard, 0x3f000000u | mmio_addr << 8, - INSTALLER_BASE_ADDRESS + h); - } - } - - // 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::GeckoCodeHandlerICacheFlush. - PowerPC::MMU::HostWrite_U32(guard, MAGIC_GAMEID, codelist_start_address); - - // Create GCT in memory - PowerPC::MMU::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address); - PowerPC::MMU::HostWrite_U32(guard, 0x00d0c0de, codelist_base_address + 4); - - // Each code is 8 bytes (2 words) wide. There is a starter code and an end code. - const u32 start_address = codelist_base_address + CODE_SIZE; - const u32 end_address = codelist_end_address - CODE_SIZE; - u32 next_address = start_address; - - // NOTE: Only active codes are in the list - for (const GeckoCode& active_code : s_active_codes) - { - // If the code is not going to fit in the space we have left then we have to skip it - if (next_address + active_code.codes.size() * CODE_SIZE > end_address) - { - NOTICE_LOG_FMT(ACTIONREPLAY, - "Too many GeckoCodes! Ran out of storage space in Game RAM. Could " - "not write: \"{}\". Need {} bytes, only {} remain.", - active_code.name, active_code.codes.size() * CODE_SIZE, - end_address - next_address); - OSD::AddMessage( - fmt::format("Too many GeckoCodes! Ran out of storage space in Game RAM. Could " - "not write: \"{}\". Need {} bytes, only {} remain.", - active_code.name, active_code.codes.size() * CODE_SIZE, - end_address - next_address), - OSD::Duration::VERY_LONG); - continue; - } - - for (const GeckoCode::Code& code : active_code.codes) - { - PowerPC::MMU::HostWrite_U32(guard, code.address, next_address); - PowerPC::MMU::HostWrite_U32(guard, code.data, next_address + 4); - next_address += CODE_SIZE; - } - } - - WARN_LOG_FMT(ACTIONREPLAY, "GeckoCodes: Using {} of {} bytes", next_address - start_address, - end_address - start_address); - - OSD::AddMessage(fmt::format("Gecko Codes: Using {} of {} bytes", next_address - start_address, - end_address - start_address)); - - // Stop code. Tells the handler that this is the end of the list. - PowerPC::MMU::HostWrite_U32(guard, 0xF0000000, next_address); - PowerPC::MMU::HostWrite_U32(guard, 0x00000000, next_address + 4); - PowerPC::MMU::HostWrite_U32(guard, 0, HLE_TRAMPOLINE_ADDRESS); - - // Turn on codes - PowerPC::MMU::HostWrite_U8(guard, 1, codelist_start_address + 7); - - // Invalidate the icache and any asm codes - auto& ppc_state = guard.GetSystem().GetPPCState(); - auto& memory = guard.GetSystem().GetMemory(); - auto& jit_interface = guard.GetSystem().GetJitInterface(); - for (u32 j = 0; j < (INSTALLER_END_ADDRESS - codelist_start_address); j += 32) - { - ppc_state.iCache.Invalidate(memory, jit_interface, codelist_start_address + j); - } + ppc_state.iCache.Invalidate(memory, jit_interface, codelist_base_address + j); } return Installation::Installed; } diff --git a/Source/Core/Core/GeckoCode.h b/Source/Core/Core/GeckoCode.h index 5546f6873f..fec21eef41 100644 --- a/Source/Core/Core/GeckoCode.h +++ b/Source/Core/Core/GeckoCode.h @@ -49,7 +49,28 @@ bool operator!=(const GeckoCode::Code& lhs, const GeckoCode::Code& rhs); // Installation address for codehandler.bin in the Game's RAM constexpr u32 INSTALLER_BASE_ADDRESS = 0x80001800; constexpr u32 INSTALLER_END_ADDRESS = 0x80003000; + +// Override kerjump to 0x8023CF6C location for CodeHandler +constexpr u32 INSTALLER_BASE_ADDRESS_MP7 = 0x8023CF6C; +constexpr u32 INSTALLER_END_ADDRESS_MP7 = 0x8023F9D0; + +// Override kerjump to 0x80213974 location for CodeHandler +constexpr u32 INSTALLER_BASE_ADDRESS_MP6 = 0x817611C0; +constexpr u32 INSTALLER_END_ADDRESS_MP6 = 0x817611C0; + +// Override kerjump to 0x801A811C location for CodeHandler +constexpr u32 INSTALLER_BASE_ADDRESS_MP5 = 0x81788000; +constexpr u32 INSTALLER_END_ADDRESS_MP5 = 0x817F0000; + +// Override kerjump to 0x8011CCC4 location for CodeHandler +constexpr u32 INSTALLER_BASE_ADDRESS_MP4 = 0x81792D00; +constexpr u32 INSTALLER_END_ADDRESS_MP4 = 0x817F0000; + constexpr u32 ENTRY_POINT = INSTALLER_BASE_ADDRESS + 0xA8; +constexpr u32 ENTRY_POINT_MP7 = INSTALLER_BASE_ADDRESS_MP7 + 0xA8; +constexpr u32 ENTRY_POINT_MP6 = INSTALLER_BASE_ADDRESS_MP6 + 0xA8; +constexpr u32 ENTRY_POINT_MP5 = INSTALLER_BASE_ADDRESS_MP5 + 0xA8; + // If the GCT is max-length then this is the second word of the End code (0xF0000000 0x00000000) // If the table is shorter than the max-length then this address is unused / contains trash. constexpr u32 HLE_TRAMPOLINE_ADDRESS = INSTALLER_END_ADDRESS - 4; @@ -72,5 +93,4 @@ void RunCodeHandler(const Core::CPUThreadGuard& guard); void Shutdown(); void DoState(PointerWrap&); - } // namespace Gecko diff --git a/Source/Core/Core/HLE/HLE.cpp b/Source/Core/Core/HLE/HLE.cpp index ff9db8fc75..36d7a9d6b8 100644 --- a/Source/Core/Core/HLE/HLE.cpp +++ b/Source/Core/Core/HLE/HLE.cpp @@ -8,8 +8,10 @@ #include #include "Common/CommonTypes.h" +#include "Common/CommonPaths.h" #include "Common/Config/Config.h" +#include "Core/ConfigManager.h" #include "Core/Config/MainSettings.h" #include "Core/Core.h" #include "Core/GeckoCode.h" @@ -79,6 +81,30 @@ void Patch(Core::System& system, u32 addr, std::string_view func_name) } } +const char* GetGeckoCodeHandlerPath() +{ + int code_handler_value = Config::Get(Config::MAIN_CODE_HANDLER); // Get the integer value + switch (code_handler_value) + { + case 0: return GECKO_CODE_HANDLER; // Dolphin (Stock) + case 1: return GECKO_CODE_HANDLER_MPN; // MPN (Extended) + case 2: return GECKO_CODE_HANDLER_MPN_SUPER; // MPN (Super Extended) + default: return GECKO_CODE_HANDLER; // Fallback + } +} + +bool IsGeckoCodeHandlerEnabled() +{ + int code_handler_value = Config::Get(Config::MAIN_CODE_HANDLER); // Get the integer value + return code_handler_value == 1 || code_handler_value == 2; // Return true for 1 and 2 +} + +bool IsGeckoCodeHandlerSUPER() +{ + int code_handler_value = Config::Get(Config::MAIN_CODE_HANDLER); // Get the integer value + return code_handler_value == 2; // Return true for 1 and 2 +} + void PatchFixedFunctions(Core::System& system) { // MIOS puts patch data in low MEM1 (0x1800-0x3000) for its own use. @@ -100,7 +126,28 @@ void PatchFixedFunctions(Core::System& system) // Not part of the binary itself, but either we or Gecko OS might insert // this, and it doesn't clear the icache properly. - Patch(system, Gecko::ENTRY_POINT, "GeckoCodehandler"); + + const bool is_mpn_handler_and_game_id_gp7e01 = + IsGeckoCodeHandlerSUPER() && (SConfig::GetInstance().GetGameID() == "GP7E01"); + const bool is_mpn_handler_and_game_id_gp6e01 = + IsGeckoCodeHandlerSUPER() && (SConfig::GetInstance().GetGameID() == "GP6E01"); + const bool is_mpn_handler_and_game_id_gp5e01 = + IsGeckoCodeHandlerSUPER() && (SConfig::GetInstance().GetGameID() == "GP5E01"); + + u32 codelist_hook = is_mpn_handler_and_game_id_gp7e01 ? + Gecko::ENTRY_POINT_MP7 : + is_mpn_handler_and_game_id_gp6e01 ? + Gecko::ENTRY_POINT_MP6 : + is_mpn_handler_and_game_id_gp5e01 ? + Gecko::ENTRY_POINT_MP5 : + Gecko::ENTRY_POINT; + + + Patch(system, codelist_hook, "GeckoCodehandler"); + + + + // This has to always be installed even if cheats are not enabled because of the possiblity of // loading a savestate where PC is inside the code handler while cheats are disabled. Patch(system, Gecko::HLE_TRAMPOLINE_ADDRESS, "GeckoHandlerReturnTrampoline"); diff --git a/Source/Core/Core/HLE/HLE_Misc.cpp b/Source/Core/Core/HLE/HLE_Misc.cpp index 423ba465dd..4c4b343eb0 100644 --- a/Source/Core/Core/HLE/HLE_Misc.cpp +++ b/Source/Core/Core/HLE/HLE_Misc.cpp @@ -12,6 +12,8 @@ #include "Core/PowerPC/MMU.h" #include "Core/PowerPC/PowerPC.h" #include "Core/System.h" +#include +#include namespace HLE_Misc { @@ -24,6 +26,31 @@ void UnimplementedFunction(const Core::CPUThreadGuard& guard) ppc_state.npc = LR(ppc_state); } +const char* GetGeckoCodeHandlerPath() +{ + int code_handler_value = Config::Get(Config::MAIN_CODE_HANDLER); // Get the integer value + switch (code_handler_value) + { + case 0: return GECKO_CODE_HANDLER; // Dolphin (Stock) + case 1: return GECKO_CODE_HANDLER_MPN; // MPN (Extended) + case 2: return GECKO_CODE_HANDLER_MPN_SUPER; // MPN (Super Extended) + default: return GECKO_CODE_HANDLER; // Fallback + } +} + +bool IsGeckoCodeHandlerEnabled() +{ + int code_handler_value = Config::Get(Config::MAIN_CODE_HANDLER); // Get the integer value + return code_handler_value == 1 || code_handler_value == 2; // Return true for 1 and 2 +} + +bool IsGeckoCodeHandlerSUPER() +{ + int code_handler_value = Config::Get(Config::MAIN_CODE_HANDLER); // Get the integer value + return code_handler_value == 2; // Return true for 1 and 2 +} + + void HBReload(const Core::CPUThreadGuard& guard) { // There isn't much we can do. Just stop cleanly. @@ -44,7 +71,20 @@ void GeckoCodeHandlerICacheFlush(const Core::CPUThreadGuard& guard) // 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 gch_gameid = PowerPC::MMU::HostRead_U32(guard, Gecko::INSTALLER_BASE_ADDRESS); + + const bool is_mpn_handler_and_game_id_gp7e01 = + IsGeckoCodeHandlerSUPER() && (SConfig::GetInstance().GetGameID() == "GP7E01"); + const bool is_mpn_handler_and_game_id_gp6e01 = + IsGeckoCodeHandlerSUPER() && (SConfig::GetInstance().GetGameID() == "GP6E01"); + const bool is_mpn_handler_and_game_id_gp5e01 = + IsGeckoCodeHandlerSUPER() && (SConfig::GetInstance().GetGameID() == "GP5E01"); + + u32 codelist_hook = is_mpn_handler_and_game_id_gp7e01 ? Gecko::INSTALLER_BASE_ADDRESS_MP7 : + is_mpn_handler_and_game_id_gp6e01 ? Gecko::INSTALLER_BASE_ADDRESS_MP6 : + is_mpn_handler_and_game_id_gp5e01 ? Gecko::INSTALLER_BASE_ADDRESS_MP5 : + Gecko::INSTALLER_BASE_ADDRESS; + + u32 gch_gameid = PowerPC::MMU::HostRead_U32(guard, codelist_hook); if (gch_gameid - Gecko::MAGIC_GAMEID == 5) { return; @@ -53,7 +93,7 @@ void GeckoCodeHandlerICacheFlush(const Core::CPUThreadGuard& guard) { gch_gameid = Gecko::MAGIC_GAMEID; } - PowerPC::MMU::HostWrite_U32(guard, gch_gameid + 1, Gecko::INSTALLER_BASE_ADDRESS); + PowerPC::MMU::HostWrite_U32(guard, gch_gameid + 1, codelist_hook); ppc_state.iCache.Reset(jit_interface); } diff --git a/Source/Core/DolphinQt/Settings/GeneralPane.cpp b/Source/Core/DolphinQt/Settings/GeneralPane.cpp index dc03a095a3..a9b1f2cc42 100644 --- a/Source/Core/DolphinQt/Settings/GeneralPane.cpp +++ b/Source/Core/DolphinQt/Settings/GeneralPane.cpp @@ -225,8 +225,9 @@ void GeneralPane::CreateCheats() auto* code_handler_layout = new QFormLayout(); auto* code_handler_label = new QLabel(tr("Code Handler:")); m_combobox_codehandler = new QComboBox(); - m_combobox_codehandler->addItem(tr("Dolphin (Stock)"), QVariant(false)); - m_combobox_codehandler->addItem(tr("MPN (Extended)"), QVariant(true)); + m_combobox_codehandler->addItem(tr("Dolphin (Stock)"), QVariant(0)); + m_combobox_codehandler->addItem(tr("MPN (Extended)"), QVariant(1)); + m_combobox_codehandler->addItem(tr("MPN (Super Extended)"), QVariant(2)); code_handler_layout->addRow(code_handler_label, m_combobox_codehandler); @@ -248,7 +249,7 @@ void GeneralPane::LoadConfig() #endif SignalBlocking(m_checkbox_dualcore)->setChecked(Config::Get(Config::MAIN_CPU_THREAD)); SignalBlocking(m_checkbox_cheats)->setChecked(Settings::Instance().GetCheatsEnabled()); - SignalBlocking(m_combobox_codehandler)->setCurrentIndex(Config::Get(Config::MAIN_CODE_HANDLER) ? 1 : 0); + SignalBlocking(m_combobox_codehandler)->setCurrentIndex(Config::Get(Config::MAIN_CODE_HANDLER)); SignalBlocking(m_checkbox_override_region_settings) ->setChecked(Config::Get(Config::MAIN_OVERRIDE_REGION_SETTINGS)); SignalBlocking(m_checkbox_auto_disc_change) @@ -367,7 +368,7 @@ void GeneralPane::GenerateNewIdentity() void GeneralPane::OnCodeHandlerChanged(int index) { - bool use_mpn = m_combobox_codehandler->itemData(index).toBool(); - Config::SetBaseOrCurrent(Config::MAIN_CODE_HANDLER, use_mpn); // Ensure correct usage + int code_handler_value = m_combobox_codehandler->itemData(index).toInt(); + Config::SetBaseOrCurrent(Config::MAIN_CODE_HANDLER, code_handler_value); Config::Save(); }