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).
This commit is contained in:
Avi Halachmi (:avih) 2016-07-28 21:21:31 +03:00
parent defbdcc2b8
commit 27e7ecce65
2 changed files with 25 additions and 0 deletions

View File

@ -321,8 +321,10 @@ static void SetupPatchesCon(bool verbose)
// Oh, and updates curGameKey. I think that's it. // Oh, and updates curGameKey. I think that's it.
// It doesn't require that the emulation is paused, and console writes/title should // 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. // 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 ) 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 // '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 // 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' // 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); 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 ) void AppCoreThread::ApplySettings( const Pcsx2Config& src )
{ {
// Re-entry guard protects against cases where code wants to manually set core settings // Re-entry guard protects against cases where code wants to manually set core settings

View File

@ -1562,6 +1562,10 @@ bool skipMPEG_By_Pattern(u32 sPC) {
return 0; 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 ) static void __fastcall recRecompile( const u32 startpc )
{ {
u32 i = 0; 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 // this is the only way patches get applied, doesn't depend on a hack
if (HWADDR(startpc) == ElfEntry) { if (HWADDR(startpc) == ElfEntry) {
Console.WriteLn(L"Elf entry point @ 0x%08x about to get recompiled. Load patches first.", startpc);
xFastCall(eeGameStarting); xFastCall(eeGameStarting);
// Apply patch as soon as possible. Normally it is done in // Apply patch as soon as possible. Normally it is done in
// eeGameStarting but first block is already compiled. // 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 // First tentative was to call eeGameStarting directly (not through the
// recompiler) but it crashes some games (GT4, DMC3). It is either a // recompiler) but it crashes some games (GT4, DMC3). It is either a
// thread issue or linked to the various components reset. // thread issue or linked to the various components reset.
LoadAllPatchesAndStuff(EmuConfig);
ApplyLoadedPatches(PPT_ONCE_ON_LOAD); ApplyLoadedPatches(PPT_ONCE_ON_LOAD);
} }