Patch: Store gamedb patches as single string

This commit is contained in:
Connor McLaughlin 2022-04-12 18:59:59 +10:00 committed by refractionpcsx2
parent 29cea58471
commit 5fa9427323
6 changed files with 41 additions and 56 deletions

View File

@ -57,23 +57,22 @@ std::string GameDatabaseSchema::GameEntry::memcardFiltersAsString() const
return fmt::to_string(fmt::join(memcardFilters, "/")); return fmt::to_string(fmt::join(memcardFilters, "/"));
} }
const GameDatabaseSchema::Patch* GameDatabaseSchema::GameEntry::findPatch(const std::string_view& crc) const const std::string* GameDatabaseSchema::GameEntry::findPatch(u32 crc) const
{ {
std::string crcLower = StringUtil::toLower(crc); Console.WriteLn(fmt::format("[GameDB] Searching for patch with CRC '{:08X}'", crc));
Console.WriteLn(fmt::format("[GameDB] Searching for patch with CRC '{}'", crc));
auto it = patches.find(crcLower); auto it = patches.find(crc);
if (it != patches.end()) if (it != patches.end())
{ {
Console.WriteLn(fmt::format("[GameDB] Found patch with CRC '{}'", crc)); Console.WriteLn(fmt::format("[GameDB] Found patch with CRC '{:08X}'", crc));
return &patches.at(crcLower); return &it->second;
} }
it = patches.find("default"); it = patches.find(0);
if (it != patches.end()) if (it != patches.end())
{ {
Console.WriteLn("[GameDB] Found and falling back to default patch"); Console.WriteLn("[GameDB] Found and falling back to default patch");
return &patches.at("default"); return &it->second;
} }
Console.WriteLn("[GameDB] No CRC-specific patch or default patch found"); Console.WriteLn("[GameDB] No CRC-specific patch or default patch found");
return nullptr; return nullptr;
@ -245,20 +244,24 @@ void GameDatabase::parseAndInsert(const std::string_view& serial, const c4::yml:
{ {
for (const ryml::NodeRef& n : node["patches"].children()) for (const ryml::NodeRef& n : node["patches"].children())
{ {
auto crc = StringUtil::toLower(std::string(n.key().str, n.key().len)); // use a crc of 0 for default patches
if (gameEntry.patches.count(crc) == 1) const std::string_view crc_str(n.key().str, n.key().len);
const std::optional<u32> crc = (StringUtil::compareNoCase(crc_str, "default")) ? std::optional<u32>(0) : StringUtil::FromChars<u32>(crc_str, 16);
if (!crc.has_value())
{ {
Console.Error(fmt::format("[GameDB] Duplicate CRC '{}' found for serial: '{}'. Skipping, CRCs are case-insensitive!", crc, serial)); Console.Error(fmt::format("[GameDB] Invalid CRC '{}' found for serial: '{}'. Skipping!", crc_str, serial));
continue; continue;
} }
GameDatabaseSchema::Patch patch; if (gameEntry.patches.find(crc.value()) != gameEntry.patches.end())
if (n.has_child("content"))
{ {
std::string patchLines; Console.Error(fmt::format("[GameDB] Duplicate CRC '{}' found for serial: '{}'. Skipping, CRCs are case-insensitive!", crc_str, serial));
n["content"] >> patchLines; continue;
patch = StringUtil::splitOnNewLine(patchLines);
} }
gameEntry.patches[crc] = patch;
std::string patch;
if (n.has_child("content"))
n["content"] >> patch;
gameEntry.patches.emplace(crc.value(), std::move(patch));
} }
} }

View File

@ -86,8 +86,6 @@ namespace GameDatabaseSchema
Count Count
}; };
using Patch = std::vector<std::string>;
struct GameEntry struct GameEntry
{ {
std::string name; std::string name;
@ -101,11 +99,11 @@ namespace GameDatabaseSchema
std::vector<std::pair<SpeedhackId, int>> speedHacks; std::vector<std::pair<SpeedhackId, int>> speedHacks;
std::vector<std::pair<GSHWFixId, s32>> gsHWFixes; std::vector<std::pair<GSHWFixId, s32>> gsHWFixes;
std::vector<std::string> memcardFilters; std::vector<std::string> memcardFilters;
std::unordered_map<std::string, Patch> patches; std::unordered_map<u32, std::string> patches;
// Returns the list of memory card serials as a `/` delimited string // Returns the list of memory card serials as a `/` delimited string
std::string memcardFiltersAsString() const; std::string memcardFiltersAsString() const;
const Patch* findPatch(const std::string_view& crc) const; const std::string* findPatch(u32 crc) const;
const char* compatAsString() const; const char* compatAsString() const;
/// Applies Core game fixes to an existing config. Returns the number of applied fixes. /// Applies Core game fixes to an existing config. Returns the number of applied fixes.

View File

@ -120,23 +120,11 @@ static void inifile_command(const std::string& cmd)
/*int code = */ PatchTableExecute(key, value, commands_patch); /*int code = */ PatchTableExecute(key, value, commands_patch);
} }
// This routine loads patches from the game database (but not the config/game fixes/hacks) int LoadPatchesFromString(const std::string& patches)
// Returns number of patches loaded
int LoadPatchesFromGamesDB(const std::string& crc, const GameDatabaseSchema::GameEntry& game)
{ {
const GameDatabaseSchema::Patch* patch = game.findPatch(crc); const size_t before = Patch.size();
if (patch)
{
for (const std::string& line : *patch)
inifile_command(line);
}
return Patch.size(); std::istringstream ss(patches);
}
static void inifile_processString(const std::string& inStr)
{
std::istringstream ss(inStr);
std::string line; std::string line;
while (std::getline(ss, line)) while (std::getline(ss, line))
{ {
@ -144,6 +132,8 @@ static void inifile_processString(const std::string& inStr)
if (!line.empty()) if (!line.empty())
inifile_command(line); inifile_command(line);
} }
return static_cast<int>(Patch.size() - before);
} }
void ForgetLoadedPatches() void ForgetLoadedPatches()
@ -162,18 +152,13 @@ int LoadPatchesFromZip(const std::string& crc, const u8* zip_data, size_t zip_da
if (!zf) if (!zf)
return 0; return 0;
const int before = Patch.size();
const std::string pnach_filename(crc + ".pnach"); const std::string pnach_filename(crc + ".pnach");
std::optional<std::string> pnach_data(ReadFileInZipToString(zf.get(), pnach_filename.c_str())); std::optional<std::string> pnach_data(ReadFileInZipToString(zf.get(), pnach_filename.c_str()));
if (!pnach_data.has_value()) if (!pnach_data.has_value())
return 0; return 0;
PatchesCon->WriteLn(Color_Green, "Loading patch '%s' from archive.", pnach_filename.c_str()); PatchesCon->WriteLn(Color_Green, "Loading patch '%s' from archive.", pnach_filename.c_str());
return LoadPatchesFromString(pnach_data.value());
inifile_processString(pnach_data.value());
return Patch.size() - before;
} }
@ -198,7 +183,7 @@ int LoadPatchesFromDir(const std::string& crc, const wxDirName& folder, const ch
friendly_name, folder.ToUTF8().data(), crc.c_str()); friendly_name, folder.ToUTF8().data(), crc.c_str());
} }
const size_t before_all = Patch.size(); int total_loaded = 0;
for (const FILESYSTEM_FIND_DATA& fd : files) for (const FILESYSTEM_FIND_DATA& fd : files)
{ {
@ -209,17 +194,13 @@ int LoadPatchesFromDir(const std::string& crc, const wxDirName& folder, const ch
if (!pnach_data.has_value()) if (!pnach_data.has_value())
continue; continue;
const size_t before = Patch.size(); const int loaded = LoadPatchesFromString(pnach_data.value());
inifile_processString(pnach_data.value()); PatchesCon->WriteLn((loaded ? Color_Green : Color_Gray), "Loaded %d %s from '%.*s'.",
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()); loaded, friendly_name, static_cast<int>(name.size()), name.data());
} }
const size_t loaded = Patch.size() - before_all; PatchesCon->WriteLn((total_loaded ? Color_Green : Color_Gray), "Overall %d %s loaded", total_loaded, friendly_name);
PatchesCon->WriteLn((loaded ? Color_Green : Color_Gray), "Overall %zu %s loaded", loaded, friendly_name); return total_loaded;
return loaded;
} }
// PatchFunc Functions. // PatchFunc Functions.

View File

@ -107,7 +107,7 @@ namespace PatchFunc
// The following LoadPatchesFrom* functions: // The following LoadPatchesFrom* functions:
// - do not reset/unload previously loaded patches (use ForgetLoadedPatches() for that) // - do not reset/unload previously loaded patches (use ForgetLoadedPatches() for that)
// - do not actually patch the emulation memory (that happens at ApplyLoadedPatches(...) ) // - do not actually patch the emulation memory (that happens at ApplyLoadedPatches(...) )
extern int LoadPatchesFromGamesDB(const std::string& crc, const GameDatabaseSchema::GameEntry& game); extern int LoadPatchesFromString(const std::string& patches);
extern int LoadPatchesFromDir(const std::string& crc, const wxDirName& folder, const char* friendly_name, bool show_error_when_missing); 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); extern int LoadPatchesFromZip(const std::string& crc, const u8* zip_data, size_t zip_data_size);

View File

@ -337,7 +337,8 @@ static void LoadPatches(const std::string& crc_string, bool show_messages, bool
if (EmuConfig.EnablePatches) if (EmuConfig.EnablePatches)
{ {
const GameDatabaseSchema::GameEntry* game = GameDatabase::findGame(s_game_serial); const GameDatabaseSchema::GameEntry* game = GameDatabase::findGame(s_game_serial);
if (game && (patch_count = LoadPatchesFromGamesDB(crc_string, *game)) > 0) const std::string* patches = game ? game->findPatch(s_game_crc) : nullptr;
if (patches && (patch_count = LoadPatchesFromString(*patches)) > 0)
{ {
PatchesCon->WriteLn(Color_Green, "(GameDB) Patches Loaded: %d", patch_count); PatchesCon->WriteLn(Color_Green, "(GameDB) Patches Loaded: %d", patch_count);
message.Write("%u game patches", patch_count); message.Write("%u game patches", patch_count);

View File

@ -391,10 +391,12 @@ static void _ApplySettings(const Pcsx2Config& src, Pcsx2Config& fixup)
if (fixup.EnablePatches) if (fixup.EnablePatches)
{ {
if (int patches = LoadPatchesFromGamesDB(GameInfo::gameCRC.ToStdString(), *game)) const std::string* patches = ingame ? game->findPatch(ElfCRC) : 0;
int numPatches;
if (patches && (numPatches = LoadPatchesFromString(*patches)) > 0)
{ {
gamePatch.Printf(L" [%d Patches]", patches); gamePatch.Printf(L" [%d Patches]", numPatches);
PatchesCon->WriteLn(Color_Green, "(GameDB) Patches Loaded: %d", patches); PatchesCon->WriteLn(Color_Green, "(GameDB) Patches Loaded: %d", numPatches);
} }
} }
if (int fixes = loadGameSettings(fixup, *game)) if (int fixes = loadGameSettings(fixup, *game))