mirror of https://github.com/PCSX2/pcsx2.git
Qt: Apply patches on entry point compile
Fixes WRC4's entrypoint patch not being used.
This commit is contained in:
parent
d5cd2446e4
commit
aa47018197
|
@ -67,6 +67,7 @@ static void SaveSettings();
|
|||
//////////////////////////////////////////////////////////////////////////
|
||||
// Local variable declarations
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
const IConsoleWriter* PatchesCon = &Console;
|
||||
static std::unique_ptr<QTimer> s_settings_save_timer;
|
||||
static std::unique_ptr<INISettingsInterface> s_base_settings_interface;
|
||||
static bool s_batch_mode = false;
|
||||
|
@ -488,18 +489,6 @@ void Host::OnInputDeviceDisconnected(const std::string_view& identifier)
|
|||
// Interface Stuff
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const IConsoleWriter* PatchesCon = &Console;
|
||||
|
||||
void LoadAllPatchesAndStuff(const Pcsx2Config& cfg)
|
||||
{
|
||||
// FIXME
|
||||
}
|
||||
|
||||
void PatchesVerboseReset()
|
||||
{
|
||||
// FIXME
|
||||
}
|
||||
|
||||
static void SignalHandler(int signal)
|
||||
{
|
||||
// First try the normal (graceful) shutdown/exit.
|
||||
|
|
|
@ -83,7 +83,9 @@ namespace VMManager
|
|||
static bool AutoDetectSource(const std::string& filename);
|
||||
static bool ApplyBootParameters(const VMBootParameters& params, std::string* state_to_load);
|
||||
static bool CheckBIOSAvailability();
|
||||
static void UpdateRunningGame(bool force);
|
||||
static void LoadPatches(const std::string& serial, u32 crc,
|
||||
bool show_messages, bool show_messages_when_disabled);
|
||||
static void UpdateRunningGame(bool force, bool game_starting);
|
||||
|
||||
static std::string GetCurrentSaveStateFileName(s32 slot);
|
||||
static bool DoLoadState(const char* filename);
|
||||
|
@ -113,6 +115,7 @@ static std::mutex s_save_state_threads_mutex;
|
|||
static std::mutex s_info_mutex;
|
||||
static std::string s_disc_path;
|
||||
static u32 s_game_crc;
|
||||
static u32 s_patches_crc;
|
||||
static std::string s_game_serial;
|
||||
static std::string s_game_name;
|
||||
static std::string s_elf_override;
|
||||
|
@ -386,15 +389,19 @@ bool VMManager::UpdateGameSettingsLayer()
|
|||
return true;
|
||||
}
|
||||
|
||||
static void LoadPatches(const std::string& crc_string, bool show_messages, bool show_messages_when_disabled)
|
||||
void VMManager::LoadPatches(const std::string& serial, u32 crc, bool show_messages, bool show_messages_when_disabled)
|
||||
{
|
||||
const std::string crc_string(fmt::format("{:08X}", crc));
|
||||
s_patches_crc = crc;
|
||||
ForgetLoadedPatches();
|
||||
|
||||
std::string message;
|
||||
|
||||
int patch_count = 0;
|
||||
if (EmuConfig.EnablePatches)
|
||||
{
|
||||
const GameDatabaseSchema::GameEntry* game = GameDatabase::findGame(s_game_serial);
|
||||
const std::string* patches = game ? game->findPatch(s_game_crc) : nullptr;
|
||||
const GameDatabaseSchema::GameEntry* game = GameDatabase::findGame(serial);
|
||||
const std::string* patches = game ? game->findPatch(crc) : nullptr;
|
||||
if (patches && (patch_count = LoadPatchesFromString(*patches)) > 0)
|
||||
{
|
||||
PatchesCon->WriteLn(Color_Green, "(GameDB) Patches Loaded: %d", patch_count);
|
||||
|
@ -416,7 +423,7 @@ static void LoadPatches(const std::string& crc_string, bool show_messages, bool
|
|||
|
||||
// wide screen patches
|
||||
int ws_patch_count = 0;
|
||||
if (EmuConfig.EnableWideScreenPatches && s_game_crc != 0)
|
||||
if (EmuConfig.EnableWideScreenPatches && crc != 0)
|
||||
{
|
||||
if (ws_patch_count = LoadPatchesFromDir(crc_string, EmuFolders::CheatsWS, "Widescreen hacks", false))
|
||||
{
|
||||
|
@ -446,7 +453,7 @@ static void LoadPatches(const std::string& crc_string, bool show_messages, bool
|
|||
}
|
||||
|
||||
// no-interlacing patches
|
||||
if (EmuConfig.EnableNoInterlacingPatches && s_game_crc != 0)
|
||||
if (EmuConfig.EnableNoInterlacingPatches && crc != 0)
|
||||
{
|
||||
if (s_active_no_interlacing_patches = LoadPatchesFromDir(crc_string, EmuFolders::CheatsNI, "No-interlacing patches", false))
|
||||
{
|
||||
|
@ -502,7 +509,7 @@ static void LoadPatches(const std::string& crc_string, bool show_messages, bool
|
|||
}
|
||||
}
|
||||
|
||||
void VMManager::UpdateRunningGame(bool force)
|
||||
void VMManager::UpdateRunningGame(bool force, bool game_starting)
|
||||
{
|
||||
// The CRC can be known before the game actually starts (at the bios), so when
|
||||
// we have the CRC but we're still at the bios and the settings are changed
|
||||
|
@ -545,22 +552,32 @@ void VMManager::UpdateRunningGame(bool force)
|
|||
}
|
||||
|
||||
sioSetGameSerial(memcardFilters.empty() ? s_game_serial : memcardFilters);
|
||||
|
||||
// If we don't reset the timer here, when using folder memcards the reindex will cause an eject,
|
||||
// which a bunch of games don't like since they access the memory card on boot.
|
||||
if (game_starting)
|
||||
ClearMcdEjectTimeoutNow();
|
||||
}
|
||||
|
||||
UpdateGameSettingsLayer();
|
||||
ApplySettings();
|
||||
|
||||
ForgetLoadedPatches();
|
||||
LoadPatches(StringUtil::StdStringFromFormat("%08X", new_crc), true, false);
|
||||
// check this here, for two cases: dynarec on, and when enable cheats is set per-game.
|
||||
if (s_patches_crc != s_game_crc)
|
||||
ReloadPatches(false);
|
||||
|
||||
GetMTGS().SendGameCRC(new_crc);
|
||||
|
||||
Host::OnGameChanged(s_disc_path, s_game_serial, s_game_name, s_game_crc);
|
||||
|
||||
MIPSAnalyst::ScanForFunctions(R5900SymbolMap, ElfTextRange.first, ElfTextRange.first + ElfTextRange.second, true);
|
||||
R5900SymbolMap.UpdateActiveSymbols();
|
||||
R3000SymbolMap.UpdateActiveSymbols();
|
||||
}
|
||||
|
||||
void VMManager::ReloadPatches(bool verbose)
|
||||
{
|
||||
ForgetLoadedPatches();
|
||||
LoadPatches(StringUtil::StdStringFromFormat("%08X", s_game_crc), verbose, verbose);
|
||||
LoadPatches(s_game_serial, s_game_crc, verbose, verbose);
|
||||
}
|
||||
|
||||
static LimiterModeType GetInitialLimiterMode()
|
||||
|
@ -828,7 +845,7 @@ bool VMManager::Initialize(const VMBootParameters& boot_params)
|
|||
s_state.store(VMState::Paused);
|
||||
Host::OnVMStarted();
|
||||
|
||||
UpdateRunningGame(true);
|
||||
UpdateRunningGame(true, true);
|
||||
|
||||
SetEmuThreadAffinities(true);
|
||||
|
||||
|
@ -871,6 +888,7 @@ void VMManager::Shutdown(bool save_resume_state)
|
|||
std::unique_lock lock(s_info_mutex);
|
||||
s_disc_path.clear();
|
||||
s_game_crc = 0;
|
||||
s_patches_crc = 0;
|
||||
s_game_serial.clear();
|
||||
s_game_name.clear();
|
||||
Host::OnGameChanged(s_disc_path, s_game_serial, s_game_name, 0);
|
||||
|
@ -924,7 +942,7 @@ void VMManager::Reset()
|
|||
|
||||
// gameid change, so apply settings
|
||||
if (game_was_started)
|
||||
UpdateRunningGame(true);
|
||||
UpdateRunningGame(true, true);
|
||||
}
|
||||
|
||||
std::string VMManager::GetSaveStateFileName(const char* game_serial, u32 game_crc, s32 slot)
|
||||
|
@ -989,7 +1007,7 @@ bool VMManager::DoLoadState(const char* filename)
|
|||
{
|
||||
Host::OnSaveStateLoading(filename);
|
||||
SaveState_UnzipFromDisk(filename);
|
||||
UpdateRunningGame(false);
|
||||
UpdateRunningGame(false, false);
|
||||
Host::OnSaveStateLoaded(filename, true);
|
||||
return true;
|
||||
}
|
||||
|
@ -1232,21 +1250,21 @@ bool VMManager::Internal::IsExecutionInterrupted()
|
|||
return s_state.load() != VMState::Running || s_cpu_implementation_changed.load();
|
||||
}
|
||||
|
||||
void VMManager::Internal::EntryPointCompilingOnCPUThread()
|
||||
{
|
||||
// Classic chicken and egg problem here. We don't want to update the running game
|
||||
// until the game entry point actually runs, because that can update settings, which
|
||||
// can flush the JIT, etc. But we need to apply patches for games where the entry
|
||||
// point is in the patch (e.g. WRC 4). So. Gross, but the only way to handle it really.
|
||||
LoadPatches(SysGetDiscID(), ElfCRC, false, false);
|
||||
ApplyLoadedPatches(PPT_ONCE_ON_LOAD);
|
||||
}
|
||||
|
||||
void VMManager::Internal::GameStartingOnCPUThread()
|
||||
{
|
||||
GetMTGS().SendGameCRC(ElfCRC);
|
||||
|
||||
MIPSAnalyst::ScanForFunctions(R5900SymbolMap, ElfTextRange.first, ElfTextRange.first + ElfTextRange.second, true);
|
||||
R5900SymbolMap.UpdateActiveSymbols();
|
||||
R3000SymbolMap.UpdateActiveSymbols();
|
||||
|
||||
UpdateRunningGame(false);
|
||||
UpdateRunningGame(false, true);
|
||||
ApplyLoadedPatches(PPT_ONCE_ON_LOAD);
|
||||
ApplyLoadedPatches(PPT_COMBINED_0_1);
|
||||
|
||||
// If we don't reset the timer here, when using folder memcards the reindex will cause an eject,
|
||||
// which a bunch of games don't like since they access the memory card on boot.
|
||||
ClearMcdEjectTimeoutNow();
|
||||
}
|
||||
|
||||
void VMManager::Internal::VSyncOnCPUThread()
|
||||
|
|
|
@ -164,6 +164,7 @@ namespace VMManager
|
|||
|
||||
const std::string& GetElfOverride();
|
||||
bool IsExecutionInterrupted();
|
||||
void EntryPointCompilingOnCPUThread();
|
||||
void GameStartingOnCPUThread();
|
||||
void VSyncOnCPUThread();
|
||||
}
|
||||
|
|
|
@ -56,7 +56,9 @@ static std::atomic<bool> eeRecNeedsReset(false);
|
|||
static bool eeCpuExecuting = false;
|
||||
static bool eeRecExitRequested = false;
|
||||
static bool g_resetEeScalingStats = false;
|
||||
#ifndef PCSX2_CORE
|
||||
static int g_patchesNeedRedo = 0;
|
||||
#endif
|
||||
|
||||
#define PC_GETBLOCK(x) PC_GETBLOCK_(x, recLUT)
|
||||
|
||||
|
@ -665,7 +667,9 @@ static void recResetRaw()
|
|||
|
||||
g_branch = 0;
|
||||
g_resetEeScalingStats = true;
|
||||
#ifndef PCSX2_CORE
|
||||
g_patchesNeedRedo = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void recShutdown()
|
||||
|
@ -1797,14 +1801,16 @@ bool skipMPEG_By_Pattern(u32 sPC)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
// defined at AppCoreThread.cpp but unclean and should not be public. We're the only
|
||||
// consumers of it, so it's declared only here.
|
||||
void LoadAllPatchesAndStuff(const Pcsx2Config&);
|
||||
void doPlace0Patches()
|
||||
static void doPlace0Patches()
|
||||
{
|
||||
LoadAllPatchesAndStuff(EmuConfig);
|
||||
ApplyLoadedPatches(PPT_ONCE_ON_LOAD);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void recRecompile(const u32 startpc)
|
||||
{
|
||||
|
@ -1878,6 +1884,7 @@ static void recRecompile(const u32 startpc)
|
|||
Console.WriteLn("recRecompile: Could not enable launch arguments for fast boot mode; unidentified BIOS version! Please report this to the PCSX2 developers.");
|
||||
}
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
// On fast/full boot this will have a crc of 0x0. But when the game/elf itself is
|
||||
// recompiled (below - ElfEntry && g_GameLoading), then the crc would be from the elf.
|
||||
// g_patchesNeedRedo is set on rec reset, and this is the only consumer.
|
||||
|
@ -1885,6 +1892,7 @@ static void recRecompile(const u32 startpc)
|
|||
if (g_patchesNeedRedo)
|
||||
doPlace0Patches();
|
||||
g_patchesNeedRedo = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (g_eeloadExec && HWADDR(startpc) == HWADDR(g_eeloadExec))
|
||||
|
@ -1896,9 +1904,13 @@ static void recRecompile(const u32 startpc)
|
|||
Console.WriteLn("Elf entry point @ 0x%08x about to get recompiled. Load patches first.", startpc);
|
||||
xFastCall((void*)eeGameStarting);
|
||||
|
||||
#ifndef PCSX2_CORE
|
||||
// Apply patch as soon as possible. Normally it is done in
|
||||
// eeGameStarting but first block is already compiled.
|
||||
doPlace0Patches();
|
||||
#else
|
||||
VMManager::Internal::EntryPointCompilingOnCPUThread();
|
||||
#endif
|
||||
}
|
||||
|
||||
g_branch = 0;
|
||||
|
|
Loading…
Reference in New Issue