From 27e7ecce655bdf4e9984337aae3ef935c1542d1c Mon Sep 17 00:00:00 2001 From: "Avi Halachmi (:avih)" Date: Thu, 28 Jul 2016 21:21:31 +0300 Subject: [PATCH] patches: load before recompiling the elf entry block Commit 330704a added code which applies the patches before recompiling the elf entry block, but because at that stage the patches for the current CRC were not yet loaded, effectively it did nothing. Now it actually loads the patches before applying them. As a result, it should now be possible for patches (with place=0) to be effective before the elf is executed. This is a hack, because the emulation loads the patches while it's not paused. It works, but it's not great. A better way would be to pause the emulation once the entry point is detected, then make the setting get applied normally (which also loads the patches normally), and then resume the emulation. This _should_ properly fix #627 (the test case works as expected now). --- pcsx2/gui/AppCoreThread.cpp | 19 +++++++++++++++++++ pcsx2/x86/ix86-32/iR5900-32.cpp | 6 ++++++ 2 files changed, 25 insertions(+) diff --git a/pcsx2/gui/AppCoreThread.cpp b/pcsx2/gui/AppCoreThread.cpp index 6e8e22aca2..368c6b578c 100644 --- a/pcsx2/gui/AppCoreThread.cpp +++ b/pcsx2/gui/AppCoreThread.cpp @@ -321,8 +321,10 @@ static void SetupPatchesCon(bool verbose) // Oh, and updates curGameKey. I think that's it. // It doesn't require that the emulation is paused, and console writes/title should // be thread safe, but it's best if things don't move around much while it runs. +static Threading::Mutex mtx__ApplySettings; static void _ApplySettings( const Pcsx2Config& src, Pcsx2Config& fixup ) { + Threading::ScopedLock lock(mtx__ApplySettings); // 'fixup' is the EmuConfig we're going to upload to the emulator, which very well may // differ from the user-configured EmuConfig settings. So we make a copy here and then // we apply the commandline overrides and database gamefixes, and then upload 'fixup' @@ -442,6 +444,23 @@ static void _ApplySettings( const Pcsx2Config& src, Pcsx2Config& fixup ) Console.SetTitle(consoleTitle); } +// FIXME: This function is not for general consumption. Its only consumer (and +// the only place it's declared at) is i5900-32.cpp . +// It's here specifically to allow loading the patches synchronously (to the caller) +// when the recompiler detects the game's elf entry point, such that the patches +// are applied to the elf in memory before it's getting recompiled. +// TODO: Find a way to pause the recompiler once it detects the elf entry, then +// make AppCoreThread::ApplySettings run more normally, and then resume +// the recompiler. +// The key point is that the patches should be loaded exactly before the elf +// is recompiled. Loading them earlier might incorrectly patch the bios memory, +// and later might be too late since the code was already recompiled +void LoadAllPatchesAndStuff(const Pcsx2Config& cfg) +{ + Pcsx2Config dummy; + _ApplySettings(cfg, dummy); +} + void AppCoreThread::ApplySettings( const Pcsx2Config& src ) { // Re-entry guard protects against cases where code wants to manually set core settings diff --git a/pcsx2/x86/ix86-32/iR5900-32.cpp b/pcsx2/x86/ix86-32/iR5900-32.cpp index 0ab577a73a..f064c40d51 100644 --- a/pcsx2/x86/ix86-32/iR5900-32.cpp +++ b/pcsx2/x86/ix86-32/iR5900-32.cpp @@ -1562,6 +1562,10 @@ bool skipMPEG_By_Pattern(u32 sPC) { return 0; } +// 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&); + static void __fastcall recRecompile( const u32 startpc ) { u32 i = 0; @@ -1611,6 +1615,7 @@ static void __fastcall recRecompile( const u32 startpc ) // this is the only way patches get applied, doesn't depend on a hack if (HWADDR(startpc) == ElfEntry) { + Console.WriteLn(L"Elf entry point @ 0x%08x about to get recompiled. Load patches first.", startpc); xFastCall(eeGameStarting); // Apply patch as soon as possible. Normally it is done in // eeGameStarting but first block is already compiled. @@ -1618,6 +1623,7 @@ static void __fastcall recRecompile( const u32 startpc ) // First tentative was to call eeGameStarting directly (not through the // recompiler) but it crashes some games (GT4, DMC3). It is either a // thread issue or linked to the various components reset. + LoadAllPatchesAndStuff(EmuConfig); ApplyLoadedPatches(PPT_ONCE_ON_LOAD); }