mirror of https://github.com/PCSX2/pcsx2.git
Patch: Remove all wx usage
This commit is contained in:
parent
4779bc830a
commit
29cea58471
334
pcsx2/Patch.cpp
334
pcsx2/Patch.cpp
|
@ -17,94 +17,87 @@
|
|||
|
||||
#define _PC_ // disables MIPS opcode macros.
|
||||
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/StringUtil.h"
|
||||
#include "Patch.h"
|
||||
#include "common/ZipHelpers.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "Patch.h"
|
||||
#include "PathDefs.h"
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <wx/textfile.h>
|
||||
#include <wx/dir.h>
|
||||
#include <wx/txtstrm.h>
|
||||
#include <wx/zipstrm.h>
|
||||
#include <wx/wfstream.h>
|
||||
#include "PathDefs.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);
|
||||
|
||||
|
||||
static std::vector<IniPatch> Patch;
|
||||
|
||||
|
||||
struct PatchTextTable
|
||||
{
|
||||
int code;
|
||||
const wxChar* text;
|
||||
const char* text;
|
||||
PATCHTABLEFUNC* func;
|
||||
};
|
||||
|
||||
static const PatchTextTable commands_patch[] =
|
||||
{
|
||||
{ 1, L"author", PatchFunc::author},
|
||||
{ 2, L"comment", PatchFunc::comment },
|
||||
{ 3, L"patch", PatchFunc::patch },
|
||||
{ 0, wxEmptyString, NULL } // Array Terminator
|
||||
{
|
||||
{1, "author", PatchFunc::author},
|
||||
{2, "comment", PatchFunc::comment},
|
||||
{3, "patch", PatchFunc::patch},
|
||||
{0, nullptr, nullptr} // Array Terminator
|
||||
};
|
||||
|
||||
static const PatchTextTable dataType[] =
|
||||
{
|
||||
{ 1, L"byte", NULL },
|
||||
{ 2, L"short", NULL },
|
||||
{ 3, L"word", NULL },
|
||||
{ 4, L"double", NULL },
|
||||
{ 5, L"extended", NULL },
|
||||
{ 6, L"leshort", NULL},
|
||||
{ 7, L"leword", NULL},
|
||||
{ 8, L"ledouble", NULL},
|
||||
{ 0, wxEmptyString, NULL }
|
||||
{
|
||||
{1, "byte", nullptr},
|
||||
{2, "short", nullptr},
|
||||
{3, "word", nullptr},
|
||||
{4, "double", nullptr},
|
||||
{5, "extended", nullptr},
|
||||
{6, "leshort", nullptr},
|
||||
{7, "leword", nullptr},
|
||||
{8, "ledouble", nullptr},
|
||||
{0, nullptr, nullptr} // Array Terminator
|
||||
};
|
||||
|
||||
static const PatchTextTable cpuCore[] =
|
||||
{
|
||||
{ 1, L"EE", NULL },
|
||||
{ 2, L"IOP", NULL },
|
||||
{ 0, wxEmptyString, NULL }
|
||||
{
|
||||
{1, "EE", nullptr},
|
||||
{2, "IOP", nullptr},
|
||||
{0, nullptr, nullptr} // Array Terminator
|
||||
};
|
||||
|
||||
// IniFile Functions.
|
||||
|
||||
static void inifile_trim(wxString& buffer)
|
||||
static void inifile_trim(std::string& buffer)
|
||||
{
|
||||
buffer.Trim(false); // trims left side.
|
||||
|
||||
if (buffer.Length() <= 1) // this I'm not sure about... - air
|
||||
StringUtil::StripWhitespace(&buffer);
|
||||
if (std::strncmp(buffer.c_str(), "//", 2) == 0)
|
||||
{
|
||||
buffer.Empty();
|
||||
return;
|
||||
// comment
|
||||
buffer.clear();
|
||||
}
|
||||
|
||||
if (buffer.Left(2) == L"//")
|
||||
{
|
||||
buffer.Empty();
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.Trim(true); // trims right side.
|
||||
// check for comments at the end of a line
|
||||
const std::string::size_type pos = buffer.find("//");
|
||||
if (pos != std::string::npos)
|
||||
buffer.erase(pos);
|
||||
}
|
||||
|
||||
static int PatchTableExecute(const ParsedAssignmentString& set, const PatchTextTable* Table)
|
||||
static int PatchTableExecute(const std::string_view& lhs, const std::string_view& rhs, const PatchTextTable* Table)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (Table[i].text[0])
|
||||
while (Table[i].text)
|
||||
{
|
||||
if (!set.lvalue.Cmp(Table[i].text))
|
||||
if (lhs.compare(Table[i].text) == 0)
|
||||
{
|
||||
if (Table[i].func)
|
||||
Table[i].func(set.lvalue, set.rvalue);
|
||||
Table[i].func(lhs, rhs);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
|
@ -114,16 +107,17 @@ static int PatchTableExecute(const ParsedAssignmentString& set, const PatchTextT
|
|||
}
|
||||
|
||||
// This routine is for executing the commands of the ini file.
|
||||
static void inifile_command(const wxString& cmd)
|
||||
static void inifile_command(const std::string& cmd)
|
||||
{
|
||||
ParsedAssignmentString set(cmd);
|
||||
std::string_view key, value;
|
||||
StringUtil::ParseAssignmentString(cmd, &key, &value);
|
||||
|
||||
// Is this really what we want to be doing here? Seems like just leaving it empty/blank
|
||||
// would make more sense... --air
|
||||
if (set.rvalue.IsEmpty())
|
||||
set.rvalue = set.lvalue;
|
||||
if (value.empty())
|
||||
value = key;
|
||||
|
||||
/*int code = */ PatchTableExecute(set, commands_patch);
|
||||
/*int code = */ PatchTableExecute(key, value, commands_patch);
|
||||
}
|
||||
|
||||
// This routine loads patches from the game database (but not the config/game fixes/hacks)
|
||||
|
@ -134,27 +128,21 @@ int LoadPatchesFromGamesDB(const std::string& crc, const GameDatabaseSchema::Gam
|
|||
if (patch)
|
||||
{
|
||||
for (const std::string& line : *patch)
|
||||
inifile_command(StringUtil::UTF8StringToWxString(line));
|
||||
inifile_command(line);
|
||||
}
|
||||
|
||||
return Patch.size();
|
||||
}
|
||||
|
||||
void inifile_processString(const wxString& inStr)
|
||||
static void inifile_processString(const std::string& inStr)
|
||||
{
|
||||
wxString str(inStr);
|
||||
inifile_trim(str);
|
||||
if (!str.IsEmpty())
|
||||
inifile_command(str);
|
||||
}
|
||||
|
||||
// This routine receives a file from inifile_read, trims it,
|
||||
// Then sends the command to be parsed.
|
||||
void inifile_process(wxTextFile& f1)
|
||||
{
|
||||
for (uint i = 0; i < f1.GetLineCount(); i++)
|
||||
std::istringstream ss(inStr);
|
||||
std::string line;
|
||||
while (std::getline(ss, line))
|
||||
{
|
||||
inifile_processString(f1[i]);
|
||||
inifile_trim(line);
|
||||
if (!line.empty())
|
||||
inifile_command(line);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,68 +151,28 @@ void ForgetLoadedPatches()
|
|||
Patch.clear();
|
||||
}
|
||||
|
||||
static int _LoadPatchFiles(const wxDirName& folderName, wxString& fileSpec, const wxString& friendlyName, int& numberFoundPatchFiles)
|
||||
{
|
||||
numberFoundPatchFiles = 0;
|
||||
|
||||
if (!folderName.Exists())
|
||||
{
|
||||
Console.WriteLn(Color_Red, L"The %s folder ('%s') is inaccessible. Skipping...", WX_STR(friendlyName), WX_STR(folderName.ToString()));
|
||||
return 0;
|
||||
}
|
||||
wxDir dir(folderName.ToString());
|
||||
|
||||
int before = Patch.size();
|
||||
wxString buffer;
|
||||
wxTextFile f;
|
||||
bool found = dir.GetFirst(&buffer, L"*", wxDIR_FILES);
|
||||
while (found)
|
||||
{
|
||||
if (buffer.Upper().Matches(fileSpec.Upper()))
|
||||
{
|
||||
PatchesCon->WriteLn(Color_Green, L"Found %s file: '%s'", WX_STR(friendlyName), WX_STR(buffer));
|
||||
int before = Patch.size();
|
||||
f.Open(Path::Combine(dir.GetName(), buffer));
|
||||
inifile_process(f);
|
||||
f.Close();
|
||||
int loaded = Patch.size() - before;
|
||||
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()));
|
||||
numberFoundPatchFiles++;
|
||||
}
|
||||
found = dir.GetNext(&buffer);
|
||||
}
|
||||
|
||||
return Patch.size() - before;
|
||||
}
|
||||
|
||||
// This routine loads patches from a zip file
|
||||
// Returns number of patches loaded
|
||||
// Note: does not reset previously loaded patches (use ForgetLoadedPatches() for that)
|
||||
// Note: only load patches from the root folder of the zip
|
||||
int LoadPatchesFromZip(const wxString& gameCRC, const wxString& patchesArchiveFilename, wxInputStream* stream)
|
||||
int LoadPatchesFromZip(const std::string& crc, const u8* zip_data, size_t zip_data_size)
|
||||
{
|
||||
wxString upperGameCRC(gameCRC.Upper());
|
||||
zip_error ze = {};
|
||||
auto zf = zip_open_buffer_managed(zip_data, zip_data_size, ZIP_RDONLY, 0, &ze);
|
||||
if (!zf)
|
||||
return 0;
|
||||
|
||||
int before = Patch.size();
|
||||
const int before = Patch.size();
|
||||
|
||||
const std::string pnach_filename(crc + ".pnach");
|
||||
std::optional<std::string> pnach_data(ReadFileInZipToString(zf.get(), pnach_filename.c_str()));
|
||||
if (!pnach_data.has_value())
|
||||
return 0;
|
||||
|
||||
PatchesCon->WriteLn(Color_Green, "Loading patch '%s' from archive.", pnach_filename.c_str());
|
||||
|
||||
inifile_processString(pnach_data.value());
|
||||
|
||||
std::unique_ptr<wxZipEntry> entry;
|
||||
wxZipInputStream zip(stream);
|
||||
while (entry.reset(zip.GetNextEntry()), entry.get() != NULL)
|
||||
{
|
||||
wxString name = entry->GetName();
|
||||
name.MakeUpper();
|
||||
if (name.Find(upperGameCRC) == 0 && name.Find(L".PNACH") + 6u == name.Length())
|
||||
{
|
||||
PatchesCon->WriteLn(Color_Green, L"Loading patch '%s' from archive '%s'",
|
||||
WX_STR(entry->GetName()), WX_STR(patchesArchiveFilename));
|
||||
wxTextInputStream pnach(zip);
|
||||
while (!zip.Eof())
|
||||
{
|
||||
inifile_processString(pnach.ReadLine());
|
||||
}
|
||||
}
|
||||
}
|
||||
return Patch.size() - before;
|
||||
}
|
||||
|
||||
|
@ -232,70 +180,62 @@ int LoadPatchesFromZip(const wxString& gameCRC, const wxString& patchesArchiveFi
|
|||
// This routine loads patches from *.pnach files
|
||||
// Returns number of patches loaded
|
||||
// Note: does not reset previously loaded patches (use ForgetLoadedPatches() for that)
|
||||
int LoadPatchesFromDir(const wxString& name, const wxDirName& folderName, const wxString& friendlyName)
|
||||
int LoadPatchesFromDir(const std::string& crc, const wxDirName& folder, const char* friendly_name, bool show_error_when_missing)
|
||||
{
|
||||
int loaded = 0;
|
||||
int numberFoundPatchFiles;
|
||||
|
||||
wxString filespec = name + L"*.pnach";
|
||||
loaded += _LoadPatchFiles(folderName, filespec, friendlyName, numberFoundPatchFiles);
|
||||
|
||||
if (folderName.ToString().IsSameAs(EmuFolders::Cheats.ToString()) && numberFoundPatchFiles == 0)
|
||||
if (!folder.Exists())
|
||||
{
|
||||
wxString pathName = Path::Combine(folderName, name.Upper() + L".pnach");
|
||||
PatchesCon->WriteLn(Color_Gray, L"Not found %s file: %s", WX_STR(friendlyName), WX_STR(pathName));
|
||||
Console.WriteLn(Color_Red, "The %s folder ('%s') is inaccessible. Skipping...", friendly_name, folder.ToUTF8().data());
|
||||
return 0;
|
||||
}
|
||||
|
||||
PatchesCon->WriteLn((loaded ? Color_Green : Color_Gray), L"Overall %d %s loaded", loaded, WX_STR(friendlyName));
|
||||
FileSystem::FindResultsArray files;
|
||||
FileSystem::FindFiles(folder.ToUTF8(), StringUtil::StdStringFromFormat("%s*.pnach", crc.c_str()).c_str(),
|
||||
FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_HIDDEN_FILES, &files);
|
||||
|
||||
if (show_error_when_missing && files.empty())
|
||||
{
|
||||
PatchesCon->WriteLn(Color_Gray, "Not found %s file: %s" FS_OSPATH_SEPARATOR_STR "%s.pnach",
|
||||
friendly_name, folder.ToUTF8().data(), crc.c_str());
|
||||
}
|
||||
|
||||
const size_t before_all = Patch.size();
|
||||
|
||||
for (const FILESYSTEM_FIND_DATA& fd : files)
|
||||
{
|
||||
const std::string_view name(FileSystem::GetFileNameFromPath(fd.FileName));
|
||||
PatchesCon->WriteLn(Color_Green, "Found %s file: '%.*s'", friendly_name, static_cast<int>(name.size()), name.data());
|
||||
|
||||
const std::optional<std::string> pnach_data(FileSystem::ReadFileToString(fd.FileName.c_str()));
|
||||
if (!pnach_data.has_value())
|
||||
continue;
|
||||
|
||||
const size_t before = Patch.size();
|
||||
inifile_processString(pnach_data.value());
|
||||
const size_t loaded = Patch.size() - before;
|
||||
|
||||
PatchesCon->WriteLn((loaded ? Color_Green : Color_Gray), "Loaded %zu %s from '%.*s'.",
|
||||
loaded, friendly_name, static_cast<int>(name.size()), name.data());
|
||||
}
|
||||
|
||||
const size_t loaded = Patch.size() - before_all;
|
||||
PatchesCon->WriteLn((loaded ? Color_Green : Color_Gray), "Overall %zu %s loaded", loaded, friendly_name);
|
||||
return loaded;
|
||||
}
|
||||
|
||||
static u32 StrToU32(const wxString& str, int base = 10)
|
||||
{
|
||||
unsigned long l;
|
||||
str.ToULong(&l, base);
|
||||
return l;
|
||||
}
|
||||
|
||||
static u64 StrToU64(const wxString& str, int base = 10)
|
||||
{
|
||||
wxULongLong_t l;
|
||||
str.ToULongLong(&l, base);
|
||||
return l;
|
||||
}
|
||||
|
||||
// PatchFunc Functions.
|
||||
namespace PatchFunc
|
||||
{
|
||||
void comment(const wxString& text1, const wxString& text2)
|
||||
void comment(const std::string_view& text1, const std::string_view& text2)
|
||||
{
|
||||
PatchesCon->WriteLn(L"comment: " + text2);
|
||||
PatchesCon->WriteLn("comment: %.*s", static_cast<int>(text2.length()), text2.data());
|
||||
}
|
||||
|
||||
void author(const wxString& text1, const wxString& text2)
|
||||
void author(const std::string_view& text1, const std::string_view& text2)
|
||||
{
|
||||
PatchesCon->WriteLn(L"Author: " + text2);
|
||||
PatchesCon->WriteLn("Author: %.*s", static_cast<int>(text2.length()), text2.data());
|
||||
}
|
||||
|
||||
struct PatchPieces
|
||||
{
|
||||
wxArrayString m_pieces;
|
||||
|
||||
PatchPieces(const wxString& param)
|
||||
{
|
||||
SplitString(m_pieces, param, L",");
|
||||
if (m_pieces.Count() < 5)
|
||||
throw wxsFormat(L"Expected 5 data parameters; only found %d", m_pieces.Count());
|
||||
}
|
||||
|
||||
const wxString& PlaceToPatch() const { return m_pieces[0]; }
|
||||
const wxString& CpuType() const { return m_pieces[1]; }
|
||||
const wxString& MemAddr() const { return m_pieces[2]; }
|
||||
const wxString& OperandSize() const { return m_pieces[3]; }
|
||||
const wxString& WriteValue() const { return m_pieces[4]; }
|
||||
};
|
||||
|
||||
void patchHelper(const wxString& cmd, const wxString& param)
|
||||
void patchHelper(const std::string_view& cmd, const std::string_view& param)
|
||||
{
|
||||
// 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
|
||||
|
@ -304,40 +244,58 @@ namespace PatchFunc
|
|||
|
||||
// print the actual patch lines only in verbose mode (even in devel)
|
||||
if (DevConWriterEnabled)
|
||||
DevCon.WriteLn(cmd + L" " + param);
|
||||
|
||||
try
|
||||
{
|
||||
PatchPieces pieces(param);
|
||||
DevCon.WriteLn("%.*s %.*s", static_cast<int>(cmd.size()), cmd.data(),
|
||||
static_cast<int>(param.size()), param.data());
|
||||
}
|
||||
|
||||
#define PATCH_ERROR(fmt, ...) Console.Error("(Patch) Error Parsing: %.*s=%.*s: " fmt, \
|
||||
static_cast<int>(cmd.size()), cmd.data(), static_cast<int>(param.size()), param.data(), \
|
||||
__VA_ARGS__)
|
||||
|
||||
// [0]=PlaceToPatch,[1]=CpuType,[2]=MemAddr,[3]=OperandSize,[4]=WriteValue
|
||||
const std::vector<std::string_view> pieces(StringUtil::SplitString(param, ',', false));
|
||||
if (pieces.size() != 5)
|
||||
{
|
||||
PATCH_ERROR("Expected 5 data parameters; only found %zu", pieces.size());
|
||||
return;
|
||||
}
|
||||
|
||||
IniPatch iPatch = {0};
|
||||
iPatch.enabled = 0;
|
||||
iPatch.placetopatch = StrToU32(pieces.PlaceToPatch(), 10);
|
||||
iPatch.placetopatch = StringUtil::FromChars<u32>(pieces[0]).value_or(_PPT_END_MARKER);
|
||||
|
||||
if (iPatch.placetopatch >= _PPT_END_MARKER)
|
||||
throw wxsFormat(L"Invalid 'place' value '%s' (0 - once on startup, 1: continuously)", WX_STR(pieces.PlaceToPatch()));
|
||||
{
|
||||
PATCH_ERROR("Invalid 'place' value '%.*s' (0 - once on startup, 1: continuously)",
|
||||
static_cast<int>(pieces[0].size()), pieces[0].data());
|
||||
return;
|
||||
}
|
||||
|
||||
iPatch.cpu = (patch_cpu_type)PatchTableExecute(pieces.CpuType(), cpuCore);
|
||||
iPatch.addr = StrToU32(pieces.MemAddr(), 16);
|
||||
iPatch.type = (patch_data_type)PatchTableExecute(pieces.OperandSize(), dataType);
|
||||
iPatch.data = StrToU64(pieces.WriteValue(), 16);
|
||||
iPatch.cpu = (patch_cpu_type)PatchTableExecute(pieces[1], std::string_view(), cpuCore);
|
||||
iPatch.addr = StringUtil::FromChars<u32>(pieces[2], 16).value_or(0);
|
||||
iPatch.type = (patch_data_type)PatchTableExecute(pieces[3], std::string_view(), dataType);
|
||||
iPatch.data = StringUtil::FromChars<u64>(pieces[4], 16).value_or(0);
|
||||
|
||||
if (iPatch.cpu == 0)
|
||||
throw wxsFormat(L"Unrecognized CPU Target: '%s'", WX_STR(pieces.CpuType()));
|
||||
{
|
||||
PATCH_ERROR("Unrecognized CPU Target: '%s'", static_cast<int>(pieces[1].size()), pieces[1].data());
|
||||
return;
|
||||
}
|
||||
|
||||
if (iPatch.type == 0)
|
||||
throw wxsFormat(L"Unrecognized Operand Size: '%s'", WX_STR(pieces.OperandSize()));
|
||||
|
||||
iPatch.enabled = 1; // omg success!!
|
||||
Patch.push_back(iPatch);
|
||||
}
|
||||
catch (wxString& exmsg)
|
||||
{
|
||||
Console.Error(L"(Patch) Error Parsing: %s=%s", WX_STR(cmd), WX_STR(param));
|
||||
Console.Indent().Error(exmsg);
|
||||
PATCH_ERROR("Unrecognized Operand Size: '%s'", static_cast<int>(pieces[3].size()), pieces[3].data());
|
||||
return;
|
||||
}
|
||||
|
||||
iPatch.enabled = 1;
|
||||
Patch.push_back(iPatch);
|
||||
|
||||
#undef PATCH_ERROR
|
||||
}
|
||||
void patch(const wxString& cmd, const wxString& param) { patchHelper(cmd, param); }
|
||||
|
||||
void patch(const std::string_view& cmd, const std::string_view& param) { patchHelper(cmd, param); }
|
||||
} // namespace PatchFunc
|
||||
|
||||
// This is for applying patches directly to memory
|
||||
|
|
|
@ -38,8 +38,7 @@
|
|||
#include "common/Pcsx2Defs.h"
|
||||
#include "SysForwardDefs.h"
|
||||
#include "GameDatabase.h"
|
||||
|
||||
class wxInputStream;
|
||||
#include <string_view>
|
||||
|
||||
enum patch_cpu_type {
|
||||
NO_CPU,
|
||||
|
@ -85,7 +84,7 @@ enum patch_place_type {
|
|||
_PPT_END_MARKER
|
||||
};
|
||||
|
||||
typedef void PATCHTABLEFUNC( const wxString& text1, const wxString& text2 );
|
||||
typedef void PATCHTABLEFUNC(const std::string_view& text1, const std::string_view& text2);
|
||||
|
||||
struct IniPatch
|
||||
{
|
||||
|
@ -109,8 +108,8 @@ namespace PatchFunc
|
|||
// - do not reset/unload previously loaded patches (use ForgetLoadedPatches() for that)
|
||||
// - do not actually patch the emulation memory (that happens at ApplyLoadedPatches(...) )
|
||||
extern int LoadPatchesFromGamesDB(const std::string& crc, const GameDatabaseSchema::GameEntry& game);
|
||||
extern int LoadPatchesFromDir(const wxString& name, const wxDirName& folderName, const wxString& friendlyName);
|
||||
extern int LoadPatchesFromZip(const wxString& gameCRC, const wxString& patchesArchiveFilename, wxInputStream* stream);
|
||||
extern int LoadPatchesFromDir(const std::string& crc, const wxDirName& folder, const char* friendly_name, bool show_error_when_missing);
|
||||
extern int LoadPatchesFromZip(const std::string& crc, const u8* zip_data, size_t zip_data_size);
|
||||
|
||||
// Patches the emulation memory by applying all the loaded patches with a specific place value.
|
||||
// Note: unless you know better, there's no need to check whether or not different patch sources
|
||||
|
|
|
@ -348,7 +348,7 @@ static void LoadPatches(const std::string& crc_string, bool show_messages, bool
|
|||
int cheat_count = 0;
|
||||
if (EmuConfig.EnableCheats)
|
||||
{
|
||||
cheat_count = LoadPatchesFromDir(StringUtil::UTF8StringToWxString(crc_string), EmuFolders::Cheats, L"Cheats");
|
||||
cheat_count = LoadPatchesFromDir(crc_string, EmuFolders::Cheats, "Cheats", true);
|
||||
if (cheat_count > 0)
|
||||
{
|
||||
PatchesCon->WriteLn(Color_Green, "Cheats Loaded: %d", cheat_count);
|
||||
|
@ -360,7 +360,7 @@ static void LoadPatches(const std::string& crc_string, bool show_messages, bool
|
|||
int ws_patch_count = 0;
|
||||
if (EmuConfig.EnableWideScreenPatches && s_game_crc != 0)
|
||||
{
|
||||
if (ws_patch_count = LoadPatchesFromDir(StringUtil::UTF8StringToWxString(crc_string), EmuFolders::CheatsWS, L"Widescreen hacks"))
|
||||
if (ws_patch_count = LoadPatchesFromDir(crc_string, EmuFolders::CheatsWS, "Widescreen hacks", false))
|
||||
{
|
||||
Console.WriteLn(Color_Gray, "Found widescreen patches in the cheats_ws folder --> skipping cheats_ws.zip");
|
||||
}
|
||||
|
@ -376,7 +376,7 @@ static void LoadPatches(const std::string& crc_string, bool show_messages, bool
|
|||
|
||||
if (!s_widescreen_cheats_data.empty())
|
||||
{
|
||||
ws_patch_count = LoadPatchesFromZip(StringUtil::UTF8StringToWxString(crc_string), wxT("cheats_ws.zip"), new wxMemoryInputStream(s_widescreen_cheats_data.data(), s_widescreen_cheats_data.size()));
|
||||
ws_patch_count = LoadPatchesFromZip(crc_string, s_widescreen_cheats_data.data(), s_widescreen_cheats_data.size());
|
||||
PatchesCon->WriteLn(Color_Green, "(Wide Screen Cheats DB) Patches Loaded: %d", ws_patch_count);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "common/StringUtil.h"
|
||||
#include "common/Threading.h"
|
||||
|
||||
#include "Host.h"
|
||||
#include "ps2/BiosTools.h"
|
||||
#include "GS.h"
|
||||
|
||||
|
@ -43,6 +44,9 @@
|
|||
alignas(16) SysMtgsThread mtgsThread;
|
||||
alignas(16) AppCoreThread CoreThread;
|
||||
|
||||
static std::vector<u8> s_widescreen_cheats_data;
|
||||
static bool s_widescreen_cheats_loaded = false;
|
||||
|
||||
typedef void (AppCoreThread::*FnPtr_CoreThreadMethod)();
|
||||
|
||||
SysCoreThread& GetCoreThread()
|
||||
|
@ -426,12 +430,12 @@ static void _ApplySettings(const Pcsx2Config& src, Pcsx2Config& fixup)
|
|||
|
||||
// regular cheat patches
|
||||
if (fixup.EnableCheats)
|
||||
gameCheats.Printf(L" [%d Cheats]", LoadPatchesFromDir(GameInfo::gameCRC, EmuFolders::Cheats, L"Cheats"));
|
||||
gameCheats.Printf(L" [%d Cheats]", LoadPatchesFromDir(StringUtil::wxStringToUTF8String(GameInfo::gameCRC), EmuFolders::Cheats, "Cheats", true));
|
||||
|
||||
// wide screen patches
|
||||
if (fixup.EnableWideScreenPatches)
|
||||
{
|
||||
if (int numberLoadedWideScreenPatches = LoadPatchesFromDir(GameInfo::gameCRC, EmuFolders::CheatsWS, L"Widescreen hacks"))
|
||||
if (int numberLoadedWideScreenPatches = LoadPatchesFromDir(StringUtil::wxStringToUTF8String(GameInfo::gameCRC), EmuFolders::CheatsWS, "Widescreen hacks", false))
|
||||
{
|
||||
gameWsHacks.Printf(L" [%d widescreen hacks]", numberLoadedWideScreenPatches);
|
||||
Console.WriteLn(Color_Gray, "Found widescreen patches in the cheats_ws folder --> skipping cheats_ws.zip");
|
||||
|
@ -439,11 +443,16 @@ static void _ApplySettings(const Pcsx2Config& src, Pcsx2Config& fixup)
|
|||
else
|
||||
{
|
||||
// No ws cheat files found at the cheats_ws folder, try the ws cheats zip file.
|
||||
const wxString cheats_ws_archive(Path::Combine(EmuFolders::Resources, wxFileName(L"cheats_ws.zip")));
|
||||
if (wxFile::Exists(cheats_ws_archive))
|
||||
if (!s_widescreen_cheats_loaded)
|
||||
{
|
||||
wxFFileInputStream* strm = new wxFFileInputStream(cheats_ws_archive);
|
||||
int numberDbfCheatsLoaded = LoadPatchesFromZip(GameInfo::gameCRC, cheats_ws_archive, strm);
|
||||
std::optional<std::vector<u8>> data = Host::ReadResourceFile("cheats_ws.zip");
|
||||
if (data.has_value())
|
||||
s_widescreen_cheats_data = std::move(data.value());
|
||||
}
|
||||
|
||||
if (!s_widescreen_cheats_data.empty())
|
||||
{
|
||||
int numberDbfCheatsLoaded = LoadPatchesFromZip(StringUtil::wxStringToUTF8String(GameInfo::gameCRC), s_widescreen_cheats_data.data(), s_widescreen_cheats_data.size());
|
||||
PatchesCon->WriteLn(Color_Green, "(Wide Screen Cheats DB) Patches Loaded: %d", numberDbfCheatsLoaded);
|
||||
gameWsHacks.Printf(L" [%d widescreen hacks]", numberDbfCheatsLoaded);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue