patches: simplify by unifying patches/cheats (effectively no-op)

patches and cheats are exactly the same (pnach style patch line) but we
stored two sets of them depending on their source: "patches" for
GameIndex.dbf patches, and "cheats" for all the rest (cheats, widescreen,
etc).

Unify patches and cheats and keep only "patches", cleanup and rename the
public API at Patch.h, and add documentation.

Also: add some console messages on invalid "place" value, and when we skip
searching cheats_ws.zip because a pnach file was found at cheats_ws dir.

Also: removed checks before applying different kinds of patches/cheats
because we don't need them (we didn't have disabled patches loaded anyway).

The checks removal _shouldn't_ have any effect, except that the checks were
wrong and accidentally prevented loading widescreen hacks which have a place
value of 0. No one probably noticed it since all the widescreen patches
which I looked at have a place value of 1. So now ws patches with place=0
would load correctly too. If we'll ever have such.
This commit is contained in:
Avi Halachmi (:avih) 2016-07-27 17:59:00 +03:00
parent eb1e890278
commit cff8cb137c
6 changed files with 134 additions and 128 deletions

View File

@ -27,11 +27,15 @@
#include <wx/txtstrm.h> #include <wx/txtstrm.h>
#include <wx/zipstrm.h> #include <wx/zipstrm.h>
// This is a declaration for PatchMemory.cpp::_ApplyPatch where we're (patch.cpp)
// the only consumer, so it's not made public via Patch.h
// Applies a single patch line to emulation memory regardless of its "place" value.
extern void _ApplyPatch(IniPatch *p);
IniPatch Patch[ MAX_PATCH ]; IniPatch Patch[ MAX_PATCH ];
IniPatch Cheat[ MAX_CHEAT ];
int patchnumber = 0; int patchnumber = 0;
int cheatnumber = 0;
wxString strgametitle; wxString strgametitle;
@ -49,13 +53,6 @@ static const PatchTextTable commands_patch[] =
{ 0, wxEmptyString, NULL } // Array Terminator { 0, wxEmptyString, NULL } // Array Terminator
}; };
static const PatchTextTable commands_cheat[] =
{
{ 1, L"comment", PatchFunc::comment },
{ 2, L"patch", PatchFunc::cheat },
{ 0, wxEmptyString, NULL } // Array Terminator
};
static const PatchTextTable dataType[] = static const PatchTextTable dataType[] =
{ {
{ 1, L"byte", NULL }, { 1, L"byte", NULL },
@ -75,7 +72,7 @@ static const PatchTextTable cpuCore[] =
// IniFile Functions. // IniFile Functions.
void inifile_trim( wxString& buffer ) static void inifile_trim( wxString& buffer )
{ {
buffer.Trim(false); // trims left side. buffer.Trim(false); // trims left side.
@ -112,7 +109,7 @@ static int PatchTableExecute( const ParsedAssignmentString& set, const PatchText
} }
// This routine is for executing the commands of the ini file. // This routine is for executing the commands of the ini file.
void inifile_command(bool isCheat, const wxString& cmd) static void inifile_command(const wxString& cmd)
{ {
ParsedAssignmentString set( cmd ); ParsedAssignmentString set( cmd );
@ -120,7 +117,7 @@ void inifile_command(bool isCheat, const wxString& cmd)
// would make more sense... --air // would make more sense... --air
if (set.rvalue.IsEmpty()) set.rvalue = set.lvalue; if (set.rvalue.IsEmpty()) set.rvalue = set.lvalue;
/*int code = */PatchTableExecute(set, isCheat ? commands_cheat : commands_patch); /*int code = */PatchTableExecute(set, commands_patch);
} }
// This routine receives a string containing patches, trims it, // This routine receives a string containing patches, trims it,
@ -130,17 +127,16 @@ void TrimPatches(wxString& s)
wxStringTokenizer tkn( s, L"\n" ); wxStringTokenizer tkn( s, L"\n" );
while(tkn.HasMoreTokens()) { while(tkn.HasMoreTokens()) {
inifile_command(0, tkn.GetNextToken()); inifile_command(tkn.GetNextToken());
} }
} }
// This routine loads patches from the game database // This routine loads patches from the game database (but not the config/game fixes/hacks)
// Returns number of patches loaded // Returns number of patches loaded
int InitPatches(const wxString& crc, const Game_Data& game) int LoadPatchesFromGamesDB(const wxString& crc, const Game_Data& game)
{ {
bool patchFound = false; bool patchFound = false;
wxString patch; wxString patch;
patchnumber = 0;
if (game.IsOk()) if (game.IsOk())
{ {
@ -163,7 +159,7 @@ void inifile_processString(const wxString& inStr)
{ {
wxString str(inStr); wxString str(inStr);
inifile_trim(str); inifile_trim(str);
if (!str.IsEmpty()) inifile_command(1, str); if (!str.IsEmpty()) inifile_command(str);
} }
// This routine receives a file from inifile_read, trims it, // This routine receives a file from inifile_read, trims it,
@ -176,20 +172,14 @@ void inifile_process(wxTextFile &f1 )
} }
} }
void ResetPatchesCount() void ForgetLoadedPatches()
{ {
patchnumber = 0; patchnumber = 0;
} }
static int _LoadPatchFiles(const wxDirName& folderName, wxString& fileSpec, const wxString& friendlyName, int& numberFoundPatchFiles)
void ResetCheatsCount()
{ {
cheatnumber = 0; numberFoundPatchFiles = 0;
}
static int LoadCheatsFiles(const wxDirName& folderName, wxString& fileSpec, const wxString& friendlyName, int& numberFoundCheatsFiles)
{
numberFoundCheatsFiles = 0;
if (!folderName.Exists()) { if (!folderName.Exists()) {
Console.WriteLn(Color_Red, L"The %s folder ('%s') is inaccessible. Skipping...", WX_STR(friendlyName), WX_STR(folderName.ToString())); Console.WriteLn(Color_Red, L"The %s folder ('%s') is inaccessible. Skipping...", WX_STR(friendlyName), WX_STR(folderName.ToString()));
@ -197,72 +187,72 @@ static int LoadCheatsFiles(const wxDirName& folderName, wxString& fileSpec, cons
} }
wxDir dir(folderName.ToString()); wxDir dir(folderName.ToString());
int before = cheatnumber; int before = patchnumber;
wxString buffer; wxString buffer;
wxTextFile f; wxTextFile f;
bool found = dir.GetFirst(&buffer, L"*", wxDIR_FILES); bool found = dir.GetFirst(&buffer, L"*", wxDIR_FILES);
while (found) { while (found) {
if (buffer.Upper().Matches(fileSpec.Upper())) { if (buffer.Upper().Matches(fileSpec.Upper())) {
PatchesCon->WriteLn(Color_Green, L"Found %s file: '%s'", WX_STR(friendlyName), WX_STR(buffer)); PatchesCon->WriteLn(Color_Green, L"Found %s file: '%s'", WX_STR(friendlyName), WX_STR(buffer));
int before = cheatnumber; int before = patchnumber;
f.Open(Path::Combine(dir.GetName(), buffer)); f.Open(Path::Combine(dir.GetName(), buffer));
inifile_process(f); inifile_process(f);
f.Close(); f.Close();
int loaded = cheatnumber - before; int loaded = patchnumber - before;
PatchesCon->WriteLn((loaded ? Color_Green : Color_Gray), L"Loaded %d %s from '%s' at '%s'", PatchesCon->WriteLn((loaded ? Color_Green : Color_Gray), L"Loaded %d %s from '%s' at '%s'",
loaded, WX_STR(friendlyName), WX_STR(buffer), WX_STR(folderName.ToString())); loaded, WX_STR(friendlyName), WX_STR(buffer), WX_STR(folderName.ToString()));
numberFoundCheatsFiles ++; numberFoundPatchFiles++;
} }
found = dir.GetNext(&buffer); found = dir.GetNext(&buffer);
} }
return cheatnumber - before; return patchnumber - before;
} }
// This routine loads cheats from a zip file // This routine loads patches from a zip file
// Returns number of cheats loaded // Returns number of patches loaded
// Note: Should be called after InitPatches() // Note: does not reset previously loaded patches (use ForgetLoadedPatches() for that)
// Note: only load cheats from the root folder of the zip // Note: only load patches from the root folder of the zip
int LoadCheatsFromZip(wxString gameCRC, const wxString& cheatsArchiveFilename) { int LoadPatchesFromZip(wxString gameCRC, const wxString& patchesArchiveFilename) {
gameCRC.MakeUpper(); gameCRC.MakeUpper();
int before = cheatnumber; int before = patchnumber;
std::unique_ptr<wxZipEntry> entry; std::unique_ptr<wxZipEntry> entry;
wxFFileInputStream in(cheatsArchiveFilename); wxFFileInputStream in(patchesArchiveFilename);
wxZipInputStream zip(in); wxZipInputStream zip(in);
while (entry.reset(zip.GetNextEntry()), entry.get() != NULL) while (entry.reset(zip.GetNextEntry()), entry.get() != NULL)
{ {
wxString name = entry->GetName(); wxString name = entry->GetName();
name.MakeUpper(); name.MakeUpper();
if (name.Find(gameCRC) == 0 && name.Find(L".PNACH")+6u == name.Length()) { if (name.Find(gameCRC) == 0 && name.Find(L".PNACH")+6u == name.Length()) {
PatchesCon->WriteLn(Color_Green, L"Loading patch '%s' from archive '%s'", PatchesCon->WriteLn(Color_Green, L"Loading patch '%s' from archive '%s'",
WX_STR(entry->GetName()), WX_STR(cheatsArchiveFilename)); WX_STR(entry->GetName()), WX_STR(patchesArchiveFilename));
wxTextInputStream pnach(zip); wxTextInputStream pnach(zip);
while (!zip.Eof()) { while (!zip.Eof()) {
inifile_processString(pnach.ReadLine()); inifile_processString(pnach.ReadLine());
} }
} }
} }
return cheatnumber - before; return patchnumber - before;
} }
// This routine loads cheats from *.pnach files // This routine loads patches from *.pnach files
// Returns number of cheats loaded // Returns number of patches loaded
// Note: Should be called after InitPatches() // Note: does not reset previously loaded patches (use ForgetLoadedPatches() for that)
int LoadCheats(wxString name, const wxDirName& folderName, const wxString& friendlyName) int LoadPatchesFromDir(wxString name, const wxDirName& folderName, const wxString& friendlyName)
{ {
int loaded = 0; int loaded = 0;
int numberFoundCheatsFiles; int numberFoundPatchFiles;
wxString filespec = name + L"*.pnach"; wxString filespec = name + L"*.pnach";
loaded += LoadCheatsFiles(folderName, filespec, friendlyName, numberFoundCheatsFiles); loaded += _LoadPatchFiles(folderName, filespec, friendlyName, numberFoundPatchFiles);
// This message _might_ be buggy. This function (LoadCheats) loads from an explicit folder. // This comment _might_ be buggy. This function (LoadPatchesFromDir) loads from an explicit folder.
// This folder can be cheats or cheats_ws at either the default location or a custom one. // This folder can be cheats or cheats_ws at either the default location or a custom one.
// This check only tests the default cheats folder, so the message it produces is possibly misleading. // This check only tests the default cheats folder, so the message it produces is possibly misleading.
if (folderName.ToString().IsSameAs(PathDefs::GetCheats().ToString()) && numberFoundCheatsFiles == 0) { if (folderName.ToString().IsSameAs(PathDefs::GetCheats().ToString()) && numberFoundPatchFiles == 0) {
wxString pathName = Path::Combine(folderName, name.MakeUpper() + L".pnach"); wxString pathName = Path::Combine(folderName, name.MakeUpper() + L".pnach");
PatchesCon->WriteLn(Color_Gray, L"Not found %s file: %s", WX_STR(friendlyName), WX_STR(pathName)); PatchesCon->WriteLn(Color_Gray, L"Not found %s file: %s", WX_STR(friendlyName), WX_STR(pathName));
} }
@ -311,7 +301,6 @@ namespace PatchFunc
const wxString& WriteValue() const { return m_pieces[4]; } const wxString& WriteValue() const { return m_pieces[4]; }
}; };
template<bool isCheat>
void patchHelper(const wxString& cmd, const wxString& param) { void patchHelper(const wxString& cmd, const wxString& param) {
// Error Handling Note: I just throw simple wxStrings here, and then catch them below and // Error Handling Note: I just throw simple wxStrings here, and then catch them below and
// format them into more detailed cmd+data+error printouts. If we want to add user-friendly // format them into more detailed cmd+data+error printouts. If we want to add user-friendly
@ -324,17 +313,17 @@ namespace PatchFunc
try try
{ {
if (isCheat && cheatnumber >= MAX_CHEAT) if(patchnumber >= MAX_PATCH)
throw wxString( L"Maximum number of cheats reached" );
if(!isCheat && patchnumber >= MAX_PATCH)
throw wxString( L"Maximum number of patches reached" ); throw wxString( L"Maximum number of patches reached" );
IniPatch& iPatch = isCheat ? Cheat[cheatnumber] : Patch[patchnumber]; IniPatch& iPatch = Patch[patchnumber];
PatchPieces pieces(param); PatchPieces pieces(param);
iPatch.enabled = 0; iPatch.enabled = 0;
iPatch.placetopatch = StrToU32(pieces.PlaceToPatch(), 10); iPatch.placetopatch = StrToU32(pieces.PlaceToPatch(), 10);
if (iPatch.placetopatch >= _PPT_END_MARKER)
throw wxsFormat(L"Invalid 'place' value '%s' (0 - once on startup, 1: continuously)", WX_STR(pieces.PlaceToPatch()));
iPatch.cpu = (patch_cpu_type)PatchTableExecute(pieces.CpuType(), cpuCore); iPatch.cpu = (patch_cpu_type)PatchTableExecute(pieces.CpuType(), cpuCore);
iPatch.addr = StrToU32(pieces.MemAddr(), 16); iPatch.addr = StrToU32(pieces.MemAddr(), 16);
iPatch.type = (patch_data_type)PatchTableExecute(pieces.OperandSize(), dataType); iPatch.type = (patch_data_type)PatchTableExecute(pieces.OperandSize(), dataType);
@ -348,8 +337,7 @@ namespace PatchFunc
iPatch.enabled = 1; // omg success!! iPatch.enabled = 1; // omg success!!
if (isCheat) cheatnumber++; patchnumber++;
else patchnumber++;
} }
catch( wxString& exmsg ) catch( wxString& exmsg )
{ {
@ -357,12 +345,11 @@ namespace PatchFunc
Console.Indent().Error( exmsg ); Console.Indent().Error( exmsg );
} }
} }
void patch(const wxString& cmd, const wxString& param) { patchHelper<0>(cmd, param); } void patch(const wxString& cmd, const wxString& param) { patchHelper(cmd, param); }
void cheat(const wxString& cmd, const wxString& param) { patchHelper<1>(cmd, param); }
} }
// This is for applying patches directly to memory // This is for applying patches directly to memory
void ApplyPatch(patch_place_type place) void ApplyLoadedPatches(patch_place_type place)
{ {
for (int i = 0; i < patchnumber; i++) for (int i = 0; i < patchnumber; i++)
{ {
@ -370,13 +357,3 @@ void ApplyPatch(patch_place_type place)
_ApplyPatch(&Patch[i]); _ApplyPatch(&Patch[i]);
} }
} }
// This is for applying cheats directly to memory
void ApplyCheat(patch_place_type place)
{
for (int i = 0; i < cheatnumber; i++)
{
if (Cheat[i].placetopatch == place)
_ApplyPatch(&Cheat[i]);
}
}

View File

@ -15,11 +15,30 @@
#pragma once #pragma once
// Note about terminology:
// "patch" in pcsx2 terminology is a single pnach style patch line, e.g. patch=1,EE,001110e0,word,00000000
// Such patches can appear in several places:
// - At <CRC>.pnach files where each file could have several such patches:
// - At the "cheats" folder
// - UI name: "Cheats", controlled via system -> enable cheats
// - At the "cheats_ws" folder or inside "cheats_ws.zip" (the zip also called "widescreen cheats DB")
// - the latter is searched if the former is not found for a CRC
// - UI name: "Widescreen hacks/patches", controlled via system -> enable widescreen patches
// - At GameIndex.DBF inside a [patches] section
// - UI name: "Patches", controlled via system -> enable automatic game fixes
// - note that automatic game fixes also controls automatic config changes from GameIndex.dbf (UI name: "fixes")
//
// So, if the console title contains the following suffix: "... [2 Fixes] [1 Patches] [0 Cheats] [6 widescreen hacks]" then:
// - The 2 fixes are configuration (not patches) fixes applied from the Games DB (automatic game fixes).
// - The 1 Patch is one uncommented pnach-style patch line from the GamesDB (automatic game fixes).
// - The 0 cheats - cheats are enabled but nothing found/loaded from the "cheats" folder.
// - The 6 widescreen patches are 6 pnach-style patch lines loaded either from cheats_ws folder or from cheats_ws.zip
#include "Pcsx2Defs.h" #include "Pcsx2Defs.h"
#include "SysForwardDefs.h" #include "SysForwardDefs.h"
#define MAX_PATCH 512 #define MAX_PATCH 2048
#define MAX_CHEAT 1024
enum patch_cpu_type { enum patch_cpu_type {
NO_CPU, NO_CPU,
@ -53,9 +72,12 @@ enum patch_data_type {
// - There's no "place" value which indicates to apply both once on startup // - There's no "place" value which indicates to apply both once on startup
// and then also continuously, however such behavior can be achieved by // and then also continuously, however such behavior can be achieved by
// duplicating the line where one has a 0 place and the other has a 1 place. // duplicating the line where one has a 0 place and the other has a 1 place.
// FIXME: Do we want to apply the place=1 patches also on startup? (when the 0 patches are applied)
enum patch_place_type { enum patch_place_type {
PPT_ONCE_ON_LOAD = 0, PPT_ONCE_ON_LOAD = 0,
PPT_CONTINUOUSLY = 1 PPT_CONTINUOUSLY = 1,
_PPT_END_MARKER
}; };
typedef void PATCHTABLEFUNC( const wxString& text1, const wxString& text2 ); typedef void PATCHTABLEFUNC( const wxString& text1, const wxString& text2 );
@ -76,21 +98,30 @@ namespace PatchFunc
PATCHTABLEFUNC comment; PATCHTABLEFUNC comment;
PATCHTABLEFUNC gametitle; PATCHTABLEFUNC gametitle;
PATCHTABLEFUNC patch; PATCHTABLEFUNC patch;
PATCHTABLEFUNC cheat;
} }
extern void ResetPatchesCount(); // The following LoadPatchesFrom* functions:
extern void ResetCheatsCount(); // - do not reset/unload previously loaded patches (use ForgetLoadedPatches() for that)
extern int LoadCheats(wxString name, const wxDirName& folderName, const wxString& friendlyName); // - do not actually patch the emulation memory (that happens at ApplyLoadedPatches(...) )
extern int LoadCheatsFromZip(wxString gameCRC, const wxString& cheatsArchiveFilename); extern int LoadPatchesFromGamesDB(const wxString& name, const Game_Data& game);
extern void inifile_command(bool isCheat, const wxString& cmd); extern int LoadPatchesFromDir(wxString name, const wxDirName& folderName, const wxString& friendlyName);
extern void inifile_trim(wxString& buffer); extern int LoadPatchesFromZip(wxString gameCRC, const wxString& cheatsArchiveFilename);
extern int InitPatches(const wxString& name, const Game_Data& game); // Patches the emulation memory by applying all the loaded patches with a specific place value.
extern int AddPatch(int Mode, int Place, int Address, int Size, u64 data); // Note: unless you know better, there's no need to check whether or not different patch sources
extern void ResetPatch(void); // are enabled (e.g. ws patches, auto game fixes, etc) before calling ApplyLoadedPatches,
extern void ApplyPatch(patch_place_type place); // because on boot or on any configuration change --> all the loaded patches are invalidated,
extern void ApplyCheat(patch_place_type place); // and then it loads only the ones which are enabled according to the current config
extern void _ApplyPatch(IniPatch *p); // (this happens at AppCoreThread::ApplySettings(...) )
extern void ApplyLoadedPatches(patch_place_type place);
// Empties the patches store ("unload" the patches) but doesn't touch the emulation memory.
// Following ApplyLoadedPatches calls will do nothing until some LoadPatchesFrom* are invoked.
extern void ForgetLoadedPatches();
extern const IConsoleWriter *PatchesCon; extern const IConsoleWriter *PatchesCon;
// The following prototypes seem unused in PCSX2, but maybe part of the cheats browser?
// regardless, they don't seem to have an implementation anywhere.
// extern int AddPatch(int Mode, int Place, int Address, int Size, u64 data);
// extern void ResetPatch(void);

View File

@ -424,6 +424,8 @@ void handle_extended_t(IniPatch *p)
} }
} }
// Only used from Patch.cpp and we don't export this in any h file.
// Patch.cpp itself declares this prototype, so make sure to keep in sync.
void _ApplyPatch(IniPatch *p) void _ApplyPatch(IniPatch *p)
{ {
if (p->enabled == 0) return; if (p->enabled == 0) return;

View File

@ -198,8 +198,7 @@ void SysCoreThread::_reset_stuff_as_needed()
m_resetVirtualMachine = false; m_resetVirtualMachine = false;
m_resetVsyncTimers = false; m_resetVsyncTimers = false;
ResetPatchesCount(); ForgetLoadedPatches();
ResetCheatsCount();
} }
if( m_resetVsyncTimers ) if( m_resetVsyncTimers )
@ -228,9 +227,7 @@ void SysCoreThread::DoCpuReset()
// //
void SysCoreThread::VsyncInThread() void SysCoreThread::VsyncInThread()
{ {
if (EmuConfig.EnablePatches) ApplyPatch(PPT_CONTINUOUSLY); ApplyLoadedPatches(PPT_CONTINUOUSLY);
if (EmuConfig.EnableCheats) ApplyCheat(PPT_CONTINUOUSLY);
if (EmuConfig.EnableWideScreenPatches) ApplyCheat(PPT_CONTINUOUSLY);
} }
void SysCoreThread::GameStartingInThread() void SysCoreThread::GameStartingInThread()
@ -241,8 +238,7 @@ void SysCoreThread::GameStartingInThread()
symbolMap.UpdateActiveSymbols(); symbolMap.UpdateActiveSymbols();
sApp.PostAppMethod(&Pcsx2App::resetDebugger); sApp.PostAppMethod(&Pcsx2App::resetDebugger);
if (EmuConfig.EnablePatches) ApplyPatch(PPT_ONCE_ON_LOAD); ApplyLoadedPatches(PPT_ONCE_ON_LOAD);
if (EmuConfig.EnableCheats) ApplyCheat(PPT_ONCE_ON_LOAD);
} }
bool SysCoreThread::StateCheckInThread() bool SysCoreThread::StateCheckInThread()

View File

@ -359,6 +359,8 @@ void AppCoreThread::ApplySettings( const Pcsx2Config& src )
curGameKey = newGameKey; curGameKey = newGameKey;
ForgetLoadedPatches();
if (!curGameKey.IsEmpty()) if (!curGameKey.IsEmpty())
{ {
if (IGameDatabase* GameDB = AppHost_GetGameDatabase() ) if (IGameDatabase* GameDB = AppHost_GetGameDatabase() )
@ -375,7 +377,7 @@ void AppCoreThread::ApplySettings( const Pcsx2Config& src )
if (fixup.EnablePatches) if (fixup.EnablePatches)
{ {
if (int patches = InitPatches(gameCRC, game)) if (int patches = LoadPatchesFromGamesDB(gameCRC, game))
{ {
gamePatch.Printf(L" [%d Patches]", patches); gamePatch.Printf(L" [%d Patches]", patches);
PatchesCon->WriteLn(Color_Green, "(GameDB) Patches Loaded: %d", patches); PatchesCon->WriteLn(Color_Green, "(GameDB) Patches Loaded: %d", patches);
@ -400,8 +402,6 @@ void AppCoreThread::ApplySettings( const Pcsx2Config& src )
gameName = L"Booting PS2 BIOS... "; gameName = L"Booting PS2 BIOS... ";
} }
ResetCheatsCount();
//Till the end of this function, entry CRC will be 00000000 //Till the end of this function, entry CRC will be 00000000
if (!gameCRC.Length()) if (!gameCRC.Length())
{ {
@ -411,20 +411,21 @@ void AppCoreThread::ApplySettings( const Pcsx2Config& src )
// regular cheat patches // regular cheat patches
if (fixup.EnableCheats) if (fixup.EnableCheats)
gameCheats.Printf(L" [%d Cheats]", LoadCheats(gameCRC, GetCheatsFolder(), L"Cheats")); gameCheats.Printf(L" [%d Cheats]", LoadPatchesFromDir(gameCRC, GetCheatsFolder(), L"Cheats"));
// wide screen patches // wide screen patches
if (fixup.EnableWideScreenPatches) if (fixup.EnableWideScreenPatches)
{ {
if (int numberLoadedWideScreenPatches = LoadCheats(gameCRC, GetCheatsWsFolder(), L"Widescreen hacks")) if (int numberLoadedWideScreenPatches = LoadPatchesFromDir(gameCRC, GetCheatsWsFolder(), L"Widescreen hacks"))
{ {
gameWsHacks.Printf(L" [%d widescreen hacks]", numberLoadedWideScreenPatches); gameWsHacks.Printf(L" [%d widescreen hacks]", numberLoadedWideScreenPatches);
Console.WriteLn(Color_Gray, "Found ws patches at cheats_ws --> skipping cheats_ws.zip");
} }
else else
{ {
// No ws cheat files found at the cheats_ws folder, try the ws cheats zip file. // No ws cheat files found at the cheats_ws folder, try the ws cheats zip file.
wxString cheats_ws_archive = Path::Combine(PathDefs::GetProgramDataDir(), wxFileName(L"cheats_ws.zip")); wxString cheats_ws_archive = Path::Combine(PathDefs::GetProgramDataDir(), wxFileName(L"cheats_ws.zip"));
int numberDbfCheatsLoaded = LoadCheatsFromZip(gameCRC, cheats_ws_archive); int numberDbfCheatsLoaded = LoadPatchesFromZip(gameCRC, cheats_ws_archive);
PatchesCon->WriteLn(Color_Green, "(Wide Screen Cheats DB) Patches Loaded: %d", numberDbfCheatsLoaded); PatchesCon->WriteLn(Color_Green, "(Wide Screen Cheats DB) Patches Loaded: %d", numberDbfCheatsLoaded);
gameWsHacks.Printf(L" [%d widescreen hacks]", numberDbfCheatsLoaded); gameWsHacks.Printf(L" [%d widescreen hacks]", numberDbfCheatsLoaded);
} }

View File

@ -1618,8 +1618,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.
if (EmuConfig.EnablePatches) ApplyPatch(PPT_ONCE_ON_LOAD); ApplyLoadedPatches(PPT_ONCE_ON_LOAD);
if (EmuConfig.EnableCheats) ApplyCheat(PPT_ONCE_ON_LOAD);
} }
g_branch = 0; g_branch = 0;