mirror of https://github.com/PCSX2/pcsx2.git
GameDatabase: Move out of gui
This commit is contained in:
parent
120ee6c673
commit
46912595ea
|
@ -900,7 +900,6 @@ set(pcsx2GuiSources
|
|||
gui/AppConfig.cpp
|
||||
gui/AppCoreThread.cpp
|
||||
gui/AppEventSources.cpp
|
||||
gui/AppGameDatabase.cpp
|
||||
gui/AppHost.cpp
|
||||
gui/AppUserMode.cpp
|
||||
gui/AppInit.cpp
|
||||
|
@ -977,7 +976,6 @@ set(pcsx2GuiHeaders
|
|||
gui/AppCoreThread.h
|
||||
gui/AppEventListeners.h
|
||||
gui/AppForwardDefs.h
|
||||
gui/AppGameDatabase.h
|
||||
gui/App.h
|
||||
gui/ApplyState.h
|
||||
gui/AppSaveStates.h
|
||||
|
@ -1498,9 +1496,7 @@ if (APPLE)
|
|||
)
|
||||
|
||||
target_sources(PCSX2 PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/gui/Resources/PCSX2.icns")
|
||||
target_sources(PCSX2 PRIVATE "${CMAKE_SOURCE_DIR}/bin/GameIndex.yaml")
|
||||
set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/gui/Resources/PCSX2.icns" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
set_source_files_properties("${CMAKE_SOURCE_DIR}/bin/GameIndex.yaml" PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
|
||||
# Add in shaders and other resources.
|
||||
file(GLOB resource_files "${CMAKE_SOURCE_DIR}/bin/resources/*")
|
||||
|
@ -1559,5 +1555,5 @@ source_group(System/Ps2/USB REGULAR_EXPRESSION USB/*)
|
|||
source_group(Resources/GUI FILES ${pcsx2GuiResources})
|
||||
source_group(Resources/PAD FILES ${pcsx2PADResources})
|
||||
source_group(Resources/Recording FILES ${pcsx2RecordingVirtualPadResources})
|
||||
source_group(Resources FILES ../bin/GameIndex.yaml gui/Resources/PCSX2.icns)
|
||||
source_group(Resources FILES gui/Resources/PCSX2.icns)
|
||||
source_group(Resources REGULAR_EXPRESSION ${CMAKE_CURRENT_BINARY_DIR}/*)
|
||||
|
|
|
@ -16,54 +16,83 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "GameDatabase.h"
|
||||
#include "Config.h"
|
||||
#include "Host.h"
|
||||
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/Path.h"
|
||||
#include "common/StringUtil.h"
|
||||
#include "common/Timer.h"
|
||||
|
||||
#include "fmt/core.h"
|
||||
#include "fmt/ranges.h"
|
||||
#include "yaml-cpp/yaml.h"
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
std::string strToLower(std::string str)
|
||||
static constexpr char GAMEDB_YAML_FILE_NAME[] = "GameIndex.yaml";
|
||||
|
||||
static std::unordered_map<std::string, GameDatabaseSchema::GameEntry> s_game_db;
|
||||
static std::once_flag s_load_once_flag;
|
||||
|
||||
static std::string strToLower(std::string str)
|
||||
{
|
||||
std::transform(str.begin(), str.end(), str.begin(),
|
||||
[](unsigned char c) { return std::tolower(c); });
|
||||
[](unsigned char c) { return std::tolower(c); });
|
||||
return str;
|
||||
}
|
||||
|
||||
bool compareStrNoCase(const std::string str1, const std::string str2)
|
||||
{
|
||||
return std::equal(str1.begin(), str1.end(), str2.begin(),
|
||||
[](char a, char b) {
|
||||
return tolower(a) == tolower(b);
|
||||
});
|
||||
}
|
||||
|
||||
std::string GameDatabaseSchema::GameEntry::memcardFiltersAsString() const
|
||||
std::string GameDatabaseSchema::GameEntry::MemcardFiltersAsString() const
|
||||
{
|
||||
return fmt::to_string(fmt::join(memcardFilters, "/"));
|
||||
}
|
||||
|
||||
bool GameDatabaseSchema::GameEntry::findPatch(const std::string crc, Patch& patch) const
|
||||
const GameDatabaseSchema::Patch* GameDatabaseSchema::GameEntry::FindPatch(const std::string& crc) const
|
||||
{
|
||||
std::string crcLower = strToLower(crc);
|
||||
const std::string crcLower(strToLower(crc));
|
||||
Console.WriteLn(fmt::format("[GameDB] Searching for patch with CRC '{}'", crc));
|
||||
if (patches.count(crcLower) == 1)
|
||||
|
||||
auto it = patches.find(crcLower);
|
||||
if (it != patches.end())
|
||||
{
|
||||
Console.WriteLn(fmt::format("[GameDB] Found patch with CRC '{}'", crc));
|
||||
patch = patches.at(crcLower);
|
||||
return true;
|
||||
return &it->second;
|
||||
}
|
||||
else if (patches.count("default") == 1)
|
||||
|
||||
it = patches.find("default");
|
||||
if (it != patches.end())
|
||||
{
|
||||
Console.WriteLn("[GameDB] Found and falling back to default patch");
|
||||
patch = patches.at("default");
|
||||
return true;
|
||||
return &it->second;
|
||||
}
|
||||
Console.WriteLn("[GameDB] No CRC-specific patch or default patch found");
|
||||
return false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<std::string> YamlGameDatabaseImpl::convertMultiLineStringToVector(const std::string multiLineString)
|
||||
const char* GameDatabaseSchema::compatToString(Compatibility compat)
|
||||
{
|
||||
switch (compat)
|
||||
{
|
||||
case GameDatabaseSchema::Compatibility::Perfect:
|
||||
return "Perfect";
|
||||
case GameDatabaseSchema::Compatibility::Playable:
|
||||
return "Playable";
|
||||
case GameDatabaseSchema::Compatibility::InGame:
|
||||
return "In-Game";
|
||||
case GameDatabaseSchema::Compatibility::Menu:
|
||||
return "Menu";
|
||||
case GameDatabaseSchema::Compatibility::Intro:
|
||||
return "Intro";
|
||||
case GameDatabaseSchema::Compatibility::Nothing:
|
||||
return "Nothing";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<std::string> convertMultiLineStringToVector(const std::string& multiLineString)
|
||||
{
|
||||
std::vector<std::string> lines;
|
||||
std::istringstream stream(multiLineString);
|
||||
|
@ -77,7 +106,7 @@ std::vector<std::string> YamlGameDatabaseImpl::convertMultiLineStringToVector(co
|
|||
return lines;
|
||||
}
|
||||
|
||||
GameDatabaseSchema::GameEntry YamlGameDatabaseImpl::entryFromYaml(const std::string serial, const YAML::Node& node)
|
||||
static bool parseAndInsert(std::string serial, const YAML::Node& node)
|
||||
{
|
||||
GameDatabaseSchema::GameEntry gameEntry;
|
||||
try
|
||||
|
@ -161,60 +190,38 @@ GameDatabaseSchema::GameEntry YamlGameDatabaseImpl::entryFromYaml(const std::str
|
|||
}
|
||||
YAML::Node patchNode = entry.second;
|
||||
|
||||
GameDatabaseSchema::Patch patchCol;
|
||||
|
||||
patchCol.author = patchNode["author"].as<std::string>("");
|
||||
patchCol.patchLines = convertMultiLineStringToVector(patchNode["content"].as<std::string>(""));
|
||||
gameEntry.patches[crc] = patchCol;
|
||||
gameEntry.patches[crc] = convertMultiLineStringToVector(patchNode["content"].as<std::string>(""));
|
||||
}
|
||||
}
|
||||
|
||||
s_game_db.emplace(std::move(serial), std::move(gameEntry));
|
||||
return true;
|
||||
}
|
||||
catch (const YAML::RepresentationException& e)
|
||||
{
|
||||
Console.Error(fmt::format("[GameDB] Invalid GameDB syntax detected on serial: '{}'. Error Details - {}", serial, e.msg));
|
||||
gameEntry.isValid = false;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
Console.Error(fmt::format("[GameDB] Unexpected error occurred when reading serial: '{}'. Error Details - {}", serial, e.what()));
|
||||
gameEntry.isValid = false;
|
||||
}
|
||||
return gameEntry;
|
||||
}
|
||||
|
||||
GameDatabaseSchema::GameEntry YamlGameDatabaseImpl::findGame(const std::string serial)
|
||||
{
|
||||
std::string serialLower = strToLower(serial);
|
||||
Console.WriteLn(fmt::format("[GameDB] Searching for '{}' in GameDB", serialLower));
|
||||
if (gameDb.count(serialLower) == 1)
|
||||
{
|
||||
Console.WriteLn(fmt::format("[GameDB] Found '{}' in GameDB", serialLower));
|
||||
return gameDb[serialLower];
|
||||
}
|
||||
|
||||
Console.Error(fmt::format("[GameDB] Could not find '{}' in GameDB", serialLower));
|
||||
GameDatabaseSchema::GameEntry entry;
|
||||
entry.isValid = false;
|
||||
return entry;
|
||||
return false;
|
||||
}
|
||||
|
||||
int YamlGameDatabaseImpl::numGames()
|
||||
{
|
||||
return gameDb.size();
|
||||
}
|
||||
|
||||
bool YamlGameDatabaseImpl::initDatabase(std::ifstream& stream)
|
||||
static bool LoadYamlFile()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!stream)
|
||||
std::optional<std::string> file_data(Host::ReadResourceFileToString(GAMEDB_YAML_FILE_NAME));
|
||||
if (!file_data.has_value())
|
||||
{
|
||||
Console.Error("[GameDB] Unable to open GameDB file.");
|
||||
return false;
|
||||
}
|
||||
// yaml-cpp has memory leak issues if you persist and modify a YAML::Node
|
||||
// convert to a map and throw it away instead!
|
||||
YAML::Node data = YAML::Load(stream);
|
||||
YAML::Node data = YAML::Load(file_data.value());
|
||||
for (const auto& entry : data)
|
||||
{
|
||||
// we don't want to throw away the entire GameDB file if a single entry is made incorrectly,
|
||||
|
@ -225,13 +232,13 @@ bool YamlGameDatabaseImpl::initDatabase(std::ifstream& stream)
|
|||
// this is because the application may pass a lowercase CRC or serial along
|
||||
//
|
||||
// However, YAML's keys are as expected case-sensitive, so we have to explicitly do our own duplicate checking
|
||||
std::string serial = strToLower(entry.first.as<std::string>());
|
||||
if (gameDb.count(serial) == 1)
|
||||
std::string serial(strToLower(entry.first.as<std::string>()));
|
||||
if (s_game_db.count(serial) == 1)
|
||||
{
|
||||
Console.Error(fmt::format("[GameDB] Duplicate serial '{}' found in GameDB. Skipping, Serials are case-insensitive!", serial));
|
||||
continue;
|
||||
}
|
||||
gameDb[serial] = entryFromYaml(serial, entry.second);
|
||||
parseAndInsert(std::move(serial), entry.second);
|
||||
}
|
||||
catch (const YAML::RepresentationException& e)
|
||||
{
|
||||
|
@ -247,3 +254,36 @@ bool YamlGameDatabaseImpl::initDatabase(std::ifstream& stream)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameDatabase::EnsureLoaded()
|
||||
{
|
||||
std::call_once(s_load_once_flag, []() {
|
||||
Common::Timer timer;
|
||||
|
||||
if (!LoadYamlFile())
|
||||
{
|
||||
Console.Error("GameDB: Failed to load YAML file");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLn("[GameDB] %zu games on record (loaded in %.2fms)", s_game_db.size(), timer.GetTimeMilliseconds());
|
||||
});
|
||||
}
|
||||
|
||||
const GameDatabaseSchema::GameEntry* GameDatabase::FindGame(const std::string& serial)
|
||||
{
|
||||
EnsureLoaded();
|
||||
|
||||
const std::string serialLower(strToLower(serial));
|
||||
Console.WriteLn("[GameDB] Searching for '%s' in GameDB", serialLower.c_str());
|
||||
|
||||
auto iter = s_game_db.find(serialLower);
|
||||
if (iter == s_game_db.end())
|
||||
{
|
||||
Console.Error("[GameDB] Could not find '%s' in GameDB", serialLower.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Console.WriteLn("[GameDB] Found '%s' in GameDB", serialLower.c_str());
|
||||
return &iter->second;
|
||||
}
|
||||
|
|
|
@ -15,8 +15,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "yaml-cpp/yaml.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
@ -56,15 +54,10 @@ public:
|
|||
Full
|
||||
};
|
||||
|
||||
struct Patch
|
||||
{
|
||||
std::string author;
|
||||
std::vector<std::string> patchLines;
|
||||
};
|
||||
using Patch = std::vector<std::string>;
|
||||
|
||||
struct GameEntry
|
||||
{
|
||||
bool isValid = true;
|
||||
std::string name;
|
||||
std::string region;
|
||||
Compatibility compat = Compatibility::Unknown;
|
||||
|
@ -78,33 +71,16 @@ public:
|
|||
std::unordered_map<std::string, Patch> patches;
|
||||
|
||||
// Returns the list of memory card serials as a `/` delimited string
|
||||
std::string memcardFiltersAsString() const;
|
||||
bool findPatch(const std::string crc, Patch& patch) const;
|
||||
std::string MemcardFiltersAsString() const;
|
||||
const Patch* FindPatch(const std::string& crc) const;
|
||||
};
|
||||
|
||||
static const char* compatToString(GameDatabaseSchema::Compatibility compat);
|
||||
};
|
||||
|
||||
class IGameDatabase
|
||||
namespace GameDatabase
|
||||
{
|
||||
public:
|
||||
virtual bool initDatabase(std::ifstream& stream) = 0;
|
||||
virtual GameDatabaseSchema::GameEntry findGame(const std::string serial) = 0;
|
||||
virtual int numGames() = 0;
|
||||
};
|
||||
void EnsureLoaded();
|
||||
|
||||
class YamlGameDatabaseImpl : public IGameDatabase
|
||||
{
|
||||
public:
|
||||
bool initDatabase(std::ifstream& stream) override;
|
||||
GameDatabaseSchema::GameEntry findGame(const std::string serial) override;
|
||||
int numGames() override;
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, GameDatabaseSchema::GameEntry> gameDb;
|
||||
GameDatabaseSchema::GameEntry entryFromYaml(const std::string serial, const YAML::Node& node);
|
||||
|
||||
std::vector<std::string> convertMultiLineStringToVector(const std::string multiLineString);
|
||||
};
|
||||
|
||||
extern IGameDatabase* AppHost_GetGameDatabase();
|
||||
extern std::string strToLower(std::string str);
|
||||
extern bool compareStrNoCase(const std::string str1, const std::string str2);
|
||||
const GameDatabaseSchema::GameEntry* FindGame(const std::string& serial);
|
||||
}; // namespace GameDatabase
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#define _PC_ // disables MIPS opcode macros.
|
||||
|
||||
#include "common/StringUtil.h"
|
||||
#include "IopCommon.h"
|
||||
#include "Patch.h"
|
||||
#include "Config.h"
|
||||
|
@ -129,19 +130,13 @@ static void inifile_command(const wxString& cmd)
|
|||
|
||||
// This routine loads patches from the game database (but not the config/game fixes/hacks)
|
||||
// Returns number of patches loaded
|
||||
int LoadPatchesFromGamesDB(const wxString& crc, const GameDatabaseSchema::GameEntry& game)
|
||||
int LoadPatchesFromGamesDB(const std::string& crc, const GameDatabaseSchema::GameEntry& game)
|
||||
{
|
||||
if (game.isValid)
|
||||
const GameDatabaseSchema::Patch* patch = game.FindPatch(crc);
|
||||
if (patch)
|
||||
{
|
||||
GameDatabaseSchema::Patch patch;
|
||||
bool patchFound = game.findPatch(std::string(crc.ToUTF8()), patch);
|
||||
if (patchFound && patch.patchLines.size() > 0)
|
||||
{
|
||||
for (auto line : patch.patchLines)
|
||||
{
|
||||
inifile_command(fromUTF8(line));
|
||||
}
|
||||
}
|
||||
for (const std::string& line : *patch)
|
||||
inifile_command(StringUtil::UTF8StringToWxString(line));
|
||||
}
|
||||
|
||||
return Patch.size();
|
||||
|
@ -209,20 +204,19 @@ static int _LoadPatchFiles(const wxDirName& folderName, wxString& fileSpec, cons
|
|||
// 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(wxString gameCRC, const wxString& patchesArchiveFilename)
|
||||
int LoadPatchesFromZip(const wxString& gameCRC, const wxString& patchesArchiveFilename, wxInputStream* stream)
|
||||
{
|
||||
gameCRC.MakeUpper();
|
||||
wxString upperGameCRC(gameCRC.Upper());
|
||||
|
||||
int before = Patch.size();
|
||||
|
||||
std::unique_ptr<wxZipEntry> entry;
|
||||
wxFFileInputStream in(patchesArchiveFilename);
|
||||
wxZipInputStream zip(in);
|
||||
wxZipInputStream zip(stream);
|
||||
while (entry.reset(zip.GetNextEntry()), entry.get() != NULL)
|
||||
{
|
||||
wxString name = entry->GetName();
|
||||
name.MakeUpper();
|
||||
if (name.Find(gameCRC) == 0 && name.Find(L".PNACH") + 6u == name.Length())
|
||||
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));
|
||||
|
@ -240,7 +234,7 @@ int LoadPatchesFromZip(wxString gameCRC, const wxString& patchesArchiveFilename)
|
|||
// 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(wxString name, const wxDirName& folderName, const wxString& friendlyName)
|
||||
int LoadPatchesFromDir(const wxString& name, const wxDirName& folderName, const wxString& friendlyName)
|
||||
{
|
||||
int loaded = 0;
|
||||
int numberFoundPatchFiles;
|
||||
|
@ -250,7 +244,7 @@ int LoadPatchesFromDir(wxString name, const wxDirName& folderName, const wxStrin
|
|||
|
||||
if (folderName.ToString().IsSameAs(EmuFolders::Cheats.ToString()) && numberFoundPatchFiles == 0)
|
||||
{
|
||||
wxString pathName = Path::Combine(folderName, name.MakeUpper() + L".pnach");
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,9 @@
|
|||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "SysForwardDefs.h"
|
||||
#include "gui/AppGameDatabase.h"
|
||||
#include "GameDatabase.h"
|
||||
|
||||
class wxInputStream;
|
||||
|
||||
enum patch_cpu_type {
|
||||
NO_CPU,
|
||||
|
@ -106,9 +108,9 @@ namespace PatchFunc
|
|||
// The following LoadPatchesFrom* functions:
|
||||
// - 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 wxString& crc, const GameDatabaseSchema::GameEntry& game);
|
||||
extern int LoadPatchesFromDir(wxString name, const wxDirName& folderName, const wxString& friendlyName);
|
||||
extern int LoadPatchesFromZip(wxString gameCRC, const wxString& cheatsArchiveFilename);
|
||||
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);
|
||||
|
||||
// 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
|
||||
|
|
|
@ -15,18 +15,21 @@
|
|||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "gui/AppSaveStates.h"
|
||||
#include "common/StringUtil.h"
|
||||
#include "Counters.h"
|
||||
#include "SaveState.h"
|
||||
|
||||
#ifndef DISABLE_RECORDING
|
||||
|
||||
#include "gui/AppGameDatabase.h"
|
||||
#include "GameDatabase.h"
|
||||
#include "DebugTools/Debug.h"
|
||||
|
||||
#include "InputRecording.h"
|
||||
#include "InputRecordingControls.h"
|
||||
#include "Utilities/InputRecordingLogger.h"
|
||||
|
||||
#include "gui/AppSaveStates.h"
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#endif
|
||||
|
@ -448,21 +451,18 @@ void InputRecording::GoToFirstFrame(wxWindow* parent)
|
|||
wxString InputRecording::resolveGameName()
|
||||
{
|
||||
// Code loosely taken from AppCoreThread::_ApplySettings to resolve the Game Name
|
||||
wxString gameName;
|
||||
const wxString gameKey(SysGetDiscID());
|
||||
if (!gameKey.IsEmpty())
|
||||
std::string gameName;
|
||||
const std::string gameKey(StringUtil::wxStringToUTF8String(SysGetDiscID()));
|
||||
if (!gameKey.empty())
|
||||
{
|
||||
if (IGameDatabase* gameDB = AppHost_GetGameDatabase())
|
||||
const GameDatabaseSchema::GameEntry* game = GameDatabase::FindGame(gameKey);
|
||||
if (game)
|
||||
{
|
||||
GameDatabaseSchema::GameEntry game = gameDB->findGame(std::string(gameKey.ToUTF8()));
|
||||
if (game.isValid)
|
||||
{
|
||||
gameName = fromUTF8(game.name);
|
||||
gameName += L" (" + fromUTF8(game.region) + L")";
|
||||
}
|
||||
gameName = game->name;
|
||||
gameName += " (" + game->region + ")";
|
||||
}
|
||||
}
|
||||
return !gameName.IsEmpty() ? gameName : (wxString)Path::GetFilename(g_Conf->CurrentIso);
|
||||
return !gameName.empty() ? StringUtil::UTF8StringToWxString(gameName) : Path::GetFilename(g_Conf->CurrentIso);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -279,7 +279,6 @@ public:
|
|||
std::unique_ptr<wxIconBundle> IconBundle;
|
||||
std::unique_ptr<wxBitmap> Bitmap_Logo;
|
||||
std::unique_ptr<wxBitmap> ScreenshotBitmap;
|
||||
std::unique_ptr<AppGameDatabase> GameDB;
|
||||
|
||||
pxAppResources();
|
||||
virtual ~pxAppResources();
|
||||
|
@ -592,7 +591,6 @@ public:
|
|||
wxImageList& GetImgList_Toolbars();
|
||||
|
||||
const AppImageIds& GetImgId() const;
|
||||
AppGameDatabase* GetGameDatabase();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Overrides of wxApp virtuals:
|
||||
|
|
|
@ -16,9 +16,10 @@
|
|||
#include "PrecompiledHeader.h"
|
||||
#include "App.h"
|
||||
#include "AppSaveStates.h"
|
||||
#include "AppGameDatabase.h"
|
||||
#include "GameDatabase.h"
|
||||
|
||||
#include <wx/stdpaths.h>
|
||||
#include <wx/wfstream.h>
|
||||
#include "fmt/core.h"
|
||||
|
||||
#include "common/StringUtil.h"
|
||||
|
@ -264,9 +265,6 @@ void AppCoreThread::OnPauseDebug()
|
|||
// Returns number of gamefixes set
|
||||
static int loadGameSettings(Pcsx2Config& dest, const GameDatabaseSchema::GameEntry& game)
|
||||
{
|
||||
if (!game.isValid)
|
||||
return 0;
|
||||
|
||||
int gf = 0;
|
||||
|
||||
if (game.eeRoundMode != GameDatabaseSchema::RoundMode::Undefined)
|
||||
|
@ -450,33 +448,29 @@ static void _ApplySettings(const Pcsx2Config& src, Pcsx2Config& fixup)
|
|||
|
||||
if (!curGameKey.IsEmpty())
|
||||
{
|
||||
if (IGameDatabase* GameDB = AppHost_GetGameDatabase())
|
||||
const GameDatabaseSchema::GameEntry* game = GameDatabase::FindGame(StringUtil::wxStringToUTF8String(curGameKey));
|
||||
if (game)
|
||||
{
|
||||
GameDatabaseSchema::GameEntry game = GameDB->findGame(std::string(curGameKey.ToUTF8()));
|
||||
if (game.isValid)
|
||||
{
|
||||
GameInfo::gameName = fromUTF8(game.name);
|
||||
GameInfo::gameName += L" (" + fromUTF8(game.region) + L")";
|
||||
gameCompat = L" [Status = " + compatToStringWX(game.compat) + L"]";
|
||||
gameMemCardFilter = fromUTF8(game.memcardFiltersAsString());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set correct title for loading standalone/homebrew ELFs
|
||||
GameInfo::gameName = LastELF.AfterLast('\\');
|
||||
}
|
||||
GameInfo::gameName = StringUtil::UTF8StringToWxString(StringUtil::StdStringFromFormat("%s (%s)", game->name.c_str(), game->region.c_str()));
|
||||
gameCompat.Printf(" [Status = %s]", GameDatabaseSchema::compatToString(game->compat));
|
||||
gameMemCardFilter = StringUtil::UTF8StringToWxString(game->MemcardFiltersAsString());
|
||||
|
||||
if (fixup.EnablePatches)
|
||||
{
|
||||
if (int patches = LoadPatchesFromGamesDB(GameInfo::gameCRC, game))
|
||||
if (int patches = LoadPatchesFromGamesDB(GameInfo::gameCRC.ToStdString(), *game))
|
||||
{
|
||||
gamePatch.Printf(L" [%d Patches]", patches);
|
||||
PatchesCon->WriteLn(Color_Green, "(GameDB) Patches Loaded: %d", patches);
|
||||
}
|
||||
if (int fixes = loadGameSettings(fixup, game))
|
||||
if (int fixes = loadGameSettings(fixup, *game))
|
||||
gameFixes.Printf(L" [%d Fixes]", fixes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set correct title for loading standalone/homebrew ELFs
|
||||
GameInfo::gameName = LastELF.AfterLast('\\');
|
||||
}
|
||||
}
|
||||
|
||||
if (!gameMemCardFilter.IsEmpty())
|
||||
|
@ -516,9 +510,12 @@ static void _ApplySettings(const Pcsx2Config& src, Pcsx2Config& fixup)
|
|||
{
|
||||
// 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"));
|
||||
int numberDbfCheatsLoaded = LoadPatchesFromZip(GameInfo::gameCRC, cheats_ws_archive);
|
||||
PatchesCon->WriteLn(Color_Green, "(Wide Screen Cheats DB) Patches Loaded: %d", numberDbfCheatsLoaded);
|
||||
gameWsHacks.Printf(L" [%d widescreen hacks]", numberDbfCheatsLoaded);
|
||||
if (wxFile::Exists(cheats_ws_archive))
|
||||
{
|
||||
int numberDbfCheatsLoaded = LoadPatchesFromZip(GameInfo::gameCRC, cheats_ws_archive, new wxFFileInputStream(cheats_ws_archive));
|
||||
PatchesCon->WriteLn(Color_Green, "(Wide Screen Cheats DB) Patches Loaded: %d", numberDbfCheatsLoaded);
|
||||
gameWsHacks.Printf(L" [%d widescreen hacks]", numberDbfCheatsLoaded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@ class PipeRedirectionBase;
|
|||
class AppCoreThread;
|
||||
class Pcsx2AppMethodEvent;
|
||||
class pxAppResources;
|
||||
class AppGameDatabase;
|
||||
class IScopedCoreThread;
|
||||
|
||||
struct KeyAcceleratorCode;
|
||||
|
|
|
@ -1,96 +0,0 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2020 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "PrecompiledHeader.h"
|
||||
|
||||
#include "App.h"
|
||||
#include "AppGameDatabase.h"
|
||||
|
||||
#include <wx/stdpaths.h>
|
||||
#include "fmt/core.h"
|
||||
#include <fstream>
|
||||
|
||||
std::ifstream AppGameDatabase::getFileAsStream(const wxString& file)
|
||||
{
|
||||
// TODO - config - refactor with std::filesystem/ghc::filesystem
|
||||
#ifdef _WIN32
|
||||
return std::ifstream(file.wc_str());
|
||||
#else
|
||||
return std::ifstream(file.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
AppGameDatabase& AppGameDatabase::LoadFromFile(const wxString& _file)
|
||||
{
|
||||
// TODO - config - refactor with std::filesystem/ghc::filesystem
|
||||
|
||||
wxString file(_file);
|
||||
if (wxFileName(file).IsRelative())
|
||||
{
|
||||
// InstallFolder is the preferred base directory for the DB file, but the registry can point to previous
|
||||
// installs if uninstall wasn't done properly.
|
||||
// Since the games DB file is considered part of pcsx2.exe itself, look for it at the exe folder
|
||||
// regardless of any other settings.
|
||||
|
||||
// Note 1: Portable setup didn't suffer from this as install folder pointed already to the exe folder in portable.
|
||||
// Note 2: Other folders are either configurable (memcards, etc) or create their content automatically (inis)
|
||||
// So the games DB was really the only one that suffers from residues of prior installs.
|
||||
|
||||
//wxDirName dir = InstallFolder;
|
||||
wxDirName dir = (wxDirName)wxFileName(wxStandardPaths::Get().GetExecutablePath()).GetPath();
|
||||
file = (dir + file).GetFullPath();
|
||||
}
|
||||
|
||||
|
||||
if (!wxFileExists(file))
|
||||
{
|
||||
Console.Error(L"[GameDB] Database Not Found! [%s]", WX_STR(file));
|
||||
return *this;
|
||||
}
|
||||
|
||||
const u64 qpc_Start = GetCPUTicks();
|
||||
|
||||
std::ifstream fileStream = getFileAsStream(file);
|
||||
if (!this->initDatabase(fileStream))
|
||||
{
|
||||
Console.Error(L"[GameDB] Database could not be loaded successfully");
|
||||
return *this;
|
||||
}
|
||||
|
||||
const u64 qpc_end = GetCPUTicks();
|
||||
|
||||
Console.WriteLn(fmt::format("[GameDB] {} games on record (loaded in {}ms)", this->numGames(),
|
||||
(u32)(((qpc_end - qpc_Start) * 1000) / GetTickFrequency())));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
AppGameDatabase* Pcsx2App::GetGameDatabase()
|
||||
{
|
||||
pxAppResources& res(GetResourceCache());
|
||||
|
||||
ScopedLock lock(m_mtx_LoadingGameDB);
|
||||
if (!res.GameDB)
|
||||
{
|
||||
res.GameDB = std::make_unique<AppGameDatabase>();
|
||||
res.GameDB->LoadFromFile();
|
||||
}
|
||||
return res.GameDB.get();
|
||||
}
|
||||
|
||||
IGameDatabase* AppHost_GetGameDatabase()
|
||||
{
|
||||
return wxGetApp().GetGameDatabase();
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2020 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GameDatabase.h"
|
||||
|
||||
#include "AppConfig.h"
|
||||
|
||||
class AppGameDatabase : public YamlGameDatabaseImpl
|
||||
{
|
||||
public:
|
||||
AppGameDatabase() {}
|
||||
virtual ~AppGameDatabase()
|
||||
{
|
||||
try
|
||||
{
|
||||
Console.WriteLn("(GameDB) Unloading...");
|
||||
}
|
||||
DESTRUCTOR_CATCHALL
|
||||
}
|
||||
|
||||
AppGameDatabase& LoadFromFile(const wxString& file = Path::Combine(PathDefs::GetProgramDataDir(), wxFileName(L"GameIndex.yaml")));
|
||||
|
||||
private:
|
||||
std::ifstream getFileAsStream(const wxString& file);
|
||||
};
|
||||
|
||||
static wxString compatToStringWX(GameDatabaseSchema::Compatibility compat)
|
||||
{
|
||||
switch (compat)
|
||||
{
|
||||
case GameDatabaseSchema::Compatibility::Perfect:
|
||||
return L"Perfect";
|
||||
case GameDatabaseSchema::Compatibility::Playable:
|
||||
return L"Playable";
|
||||
case GameDatabaseSchema::Compatibility::InGame:
|
||||
return L"In-Game";
|
||||
case GameDatabaseSchema::Compatibility::Menu:
|
||||
return L"Menu";
|
||||
case GameDatabaseSchema::Compatibility::Intro:
|
||||
return L"Intro";
|
||||
case GameDatabaseSchema::Compatibility::Nothing:
|
||||
return L"Nothing";
|
||||
default:
|
||||
return L"Unknown";
|
||||
}
|
||||
}
|
|
@ -352,47 +352,6 @@ bool Pcsx2App::OnCmdLineParsed(wxCmdLineParser& parser)
|
|||
typedef void (wxEvtHandler::*pxInvokeAppMethodEventFunction)(Pcsx2AppMethodEvent&);
|
||||
typedef void (wxEvtHandler::*pxStuckThreadEventHandler)(pxMessageBoxEvent&);
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// GameDatabaseLoaderThread
|
||||
// --------------------------------------------------------------------------------------
|
||||
class GameDatabaseLoaderThread : public pxThread, EventListener_AppStatus
|
||||
{
|
||||
typedef pxThread _parent;
|
||||
|
||||
public:
|
||||
GameDatabaseLoaderThread()
|
||||
: pxThread(L"GameDatabaseLoader")
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~GameDatabaseLoaderThread()
|
||||
{
|
||||
try
|
||||
{
|
||||
_parent::Cancel();
|
||||
}
|
||||
DESTRUCTOR_CATCHALL
|
||||
}
|
||||
|
||||
protected:
|
||||
void ExecuteTaskInThread()
|
||||
{
|
||||
Sleep(2);
|
||||
wxGetApp().GetGameDatabase();
|
||||
}
|
||||
|
||||
void OnCleanupInThread()
|
||||
{
|
||||
_parent::OnCleanupInThread();
|
||||
wxGetApp().DeleteThread(this);
|
||||
}
|
||||
|
||||
void AppStatusEvent_OnExit()
|
||||
{
|
||||
Block();
|
||||
}
|
||||
};
|
||||
|
||||
bool Pcsx2App::OnInit()
|
||||
{
|
||||
EnableAllLogging();
|
||||
|
@ -464,8 +423,6 @@ bool Pcsx2App::OnInit()
|
|||
OpenMainFrame();
|
||||
|
||||
|
||||
(new GameDatabaseLoaderThread())->Start();
|
||||
|
||||
// By default no IRX injection
|
||||
EmuConfig.CurrentIRX.clear();
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "GS.h"
|
||||
#include "Host.h"
|
||||
#include "AppSaveStates.h"
|
||||
#include "AppGameDatabase.h"
|
||||
#include "AppAccelerators.h"
|
||||
#include "PAD/Gamepad.h"
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
#include "PrecompiledHeader.h"
|
||||
#include "MainFrame.h"
|
||||
#include "AppGameDatabase.h"
|
||||
|
||||
#include <wx/zipstrm.h>
|
||||
#include <wx/wfstream.h>
|
||||
|
|
|
@ -307,7 +307,6 @@
|
|||
<ClCompile Include="Gif_Unit.cpp" />
|
||||
<ClCompile Include="GS\Renderers\DX11\D3D.cpp" />
|
||||
<ClCompile Include="GS\Window\GSwxDialog.cpp" />
|
||||
<ClCompile Include="gui\AppGameDatabase.cpp" />
|
||||
<ClCompile Include="gui\AppHost.cpp" />
|
||||
<ClCompile Include="gui\AppUserMode.cpp" />
|
||||
<ClCompile Include="gui\CheckedStaticBox.cpp" />
|
||||
|
@ -746,7 +745,6 @@
|
|||
<ClInclude Include="Gif_Unit.h" />
|
||||
<ClInclude Include="GS\Renderers\DX11\D3D.h" />
|
||||
<ClInclude Include="GS\Window\GSwxDialog.h" />
|
||||
<ClInclude Include="gui\AppGameDatabase.h" />
|
||||
<ClInclude Include="gui\CheckedStaticBox.h" />
|
||||
<ClInclude Include="gui\i18n.h" />
|
||||
<ClInclude Include="gui\DriveList.h" />
|
||||
|
|
|
@ -884,9 +884,6 @@
|
|||
<ClCompile Include="gui\AppUserMode.cpp">
|
||||
<Filter>AppHost</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gui\AppGameDatabase.cpp">
|
||||
<Filter>AppHost</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gui\Dialogs\McdConfigDialog.cpp">
|
||||
<Filter>AppHost\Dialogs</Filter>
|
||||
</ClCompile>
|
||||
|
@ -2008,9 +2005,6 @@
|
|||
<ClInclude Include="IPU\IPUdma.h">
|
||||
<Filter>System\Ps2\IPU</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gui\AppGameDatabase.h">
|
||||
<Filter>AppHost</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gui\i18n.h">
|
||||
<Filter>AppHost</Filter>
|
||||
</ClInclude>
|
||||
|
|
Loading…
Reference in New Issue