mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-04-24 13:34:57 +00:00
code handler super extended
This commit is contained in:
parent
69e75c6cfd
commit
11413bf234
9 changed files with 231 additions and 187 deletions
|
@ -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"
|
||||
|
|
|
@ -67,7 +67,6 @@ extern const Info<bool> MAIN_CPU_THREAD;
|
|||
extern const Info<bool> MAIN_SYNC_ON_SKIP_IDLE;
|
||||
extern const Info<std::string> MAIN_DEFAULT_ISO;
|
||||
extern const Info<bool> MAIN_ENABLE_CHEATS;
|
||||
extern const Info<bool> MAIN_CODE_HANDLER;
|
||||
extern const Info<int> MAIN_GC_LANGUAGE;
|
||||
extern const Info<bool> MAIN_OVERRIDE_REGION_SETTINGS;
|
||||
extern const Info<bool> MAIN_DPL2_DECODER;
|
||||
|
|
|
@ -89,8 +89,7 @@ SConfig::~SConfig()
|
|||
|
||||
namespace Config
|
||||
{
|
||||
// Initialize the configuration option
|
||||
const Info<bool> MAIN_CODE_HANDLER{{System::Main, "CodeHandler", "UseMPN"}, false};
|
||||
const Info<int> MAIN_CODE_HANDLER{{System::Main, "CodeHandler", "CodeHandlerValue"}, 0};
|
||||
}
|
||||
|
||||
void SConfig::SaveSettings()
|
||||
|
|
|
@ -34,13 +34,11 @@ enum class Region;
|
|||
struct Partition;
|
||||
class Volume;
|
||||
} // namespace DiscIO
|
||||
|
||||
namespace Config
|
||||
{
|
||||
// Define the configuration option
|
||||
extern const Info<bool> MAIN_CODE_HANDLER;
|
||||
}
|
||||
|
||||
// Define the configuration option
|
||||
extern const Info<int> 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;
|
||||
|
||||
|
|
|
@ -122,19 +122,27 @@ std::vector<GeckoCode> SetAndReturnActiveCodes(std::span<const GeckoCode> 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<u32>(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<u32>(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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -8,8 +8,10 @@
|
|||
#include <map>
|
||||
|
||||
#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");
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "Core/PowerPC/MMU.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "Core/System.h"
|
||||
#include <Common/CommonPaths.h>
|
||||
#include <Core/ConfigManager.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue