Keep track of GameTDB ID separately from game ID

The difference between Dolphin's game IDs and GameTDB's game IDs
is that GameTDB uses four characters for non-disc titles, whereas
Dolphin uses six characters for all titles.

This fixes:

- TitleDatabase considering Datel discs to be NHL Hitz 2002
- Gecko code downloading not working for discs with IDs starting with P
- Cover downloading mixing up discs with channels (e.g. Mario Kart Wii
  and Mario Kart Channel) and making extra HTTP requests. (Android was
  actually doing a better job at this than DolphinQt!)
This commit is contained in:
JosJuice 2019-02-23 17:49:06 +01:00
parent d27036eb77
commit 8842a0f402
23 changed files with 106 additions and 84 deletions

View File

@ -30,6 +30,8 @@ public class GameFile
public native String getGameId(); public native String getGameId();
public native String getGameTdbId();
public native int getDiscNumber(); public native int getDiscNumber();
public native int getRevision(); public native int getRevision();
@ -43,7 +45,7 @@ public class GameFile
public String getCoverPath() public String getCoverPath()
{ {
return Environment.getExternalStorageDirectory().getPath() + return Environment.getExternalStorageDirectory().getPath() +
"/dolphin-emu/Cache/GameCovers/" + getGameId() + ".png"; "/dolphin-emu/Cache/GameCovers/" + getGameTdbId() + ".png";
} }
public String getCustomCoverPath() public String getCustomCoverPath()

View File

@ -12,10 +12,7 @@ public final class CoverHelper
public static String buildGameTDBUrl(GameFile game, String region) public static String buildGameTDBUrl(GameFile game, String region)
{ {
String gameId = game.getGameId(); return String.format(baseUrl, region, game.getGameTdbId());
if (game.getPlatform() == 2) // WiiWare
gameId = gameId.substring(0, 4);
return String.format(baseUrl, region, gameId);
} }
public static String getRegion(GameFile game) public static String getRegion(GameFile game)
@ -77,4 +74,4 @@ public final class CoverHelper
// Do nothing // Do nothing
} }
} }
} }

View File

@ -123,6 +123,12 @@ JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getGameI
return ToJString(env, GetRef(env, obj)->GetGameID()); return ToJString(env, GetRef(env, obj)->GetGameID());
} }
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getGameTdbId(JNIEnv* env,
jobject obj)
{
return ToJString(env, GetRef(env, obj)->GetGameTDBID());
}
JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getDiscNumber(JNIEnv* env, JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_model_GameFile_getDiscNumber(JNIEnv* env,
jobject obj) jobject obj)
{ {

View File

@ -680,7 +680,7 @@ void SConfig::LoadJitDebugSettings(IniFile& ini)
void SConfig::ResetRunningGameMetadata() void SConfig::ResetRunningGameMetadata()
{ {
SetRunningGameMetadata("00000000", 0, 0, Core::TitleDatabase::TitleType::Other); SetRunningGameMetadata("00000000", "", 0, 0);
} }
void SConfig::SetRunningGameMetadata(const DiscIO::Volume& volume, void SConfig::SetRunningGameMetadata(const DiscIO::Volume& volume,
@ -688,14 +688,14 @@ void SConfig::SetRunningGameMetadata(const DiscIO::Volume& volume,
{ {
if (partition == volume.GetGamePartition()) if (partition == volume.GetGamePartition())
{ {
SetRunningGameMetadata(volume.GetGameID(), volume.GetTitleID().value_or(0), SetRunningGameMetadata(volume.GetGameID(), volume.GetGameTDBID(),
volume.GetRevision().value_or(0), Core::TitleDatabase::TitleType::Other); volume.GetTitleID().value_or(0), volume.GetRevision().value_or(0));
} }
else else
{ {
SetRunningGameMetadata(volume.GetGameID(partition), volume.GetTitleID(partition).value_or(0), SetRunningGameMetadata(volume.GetGameID(partition), volume.GetGameTDBID(),
volume.GetRevision(partition).value_or(0), volume.GetTitleID(partition).value_or(0),
Core::TitleDatabase::TitleType::Other); volume.GetRevision(partition).value_or(0));
} }
} }
@ -710,16 +710,18 @@ void SConfig::SetRunningGameMetadata(const IOS::ES::TMDReader& tmd)
if (!DVDInterface::UpdateRunningGameMetadata(tmd_title_id)) if (!DVDInterface::UpdateRunningGameMetadata(tmd_title_id))
{ {
// If not launching a disc game, just read everything from the TMD. // If not launching a disc game, just read everything from the TMD.
SetRunningGameMetadata(tmd.GetGameID(), tmd_title_id, tmd.GetTitleVersion(), const std::string game_id = tmd.GetGameID();
Core::TitleDatabase::TitleType::Channel); SetRunningGameMetadata(game_id, game_id, tmd_title_id, tmd.GetTitleVersion());
} }
} }
void SConfig::SetRunningGameMetadata(const std::string& game_id, u64 title_id, u16 revision, void SConfig::SetRunningGameMetadata(const std::string& game_id, const std::string& gametdb_id,
Core::TitleDatabase::TitleType type) u64 title_id, u16 revision)
{ {
const bool was_changed = m_game_id != game_id || m_title_id != title_id || m_revision != revision; const bool was_changed = m_game_id != game_id || m_gametdb_id != gametdb_id ||
m_title_id != title_id || m_revision != revision;
m_game_id = game_id; m_game_id = game_id;
m_gametdb_id = gametdb_id;
m_title_id = title_id; m_title_id = title_id;
m_revision = revision; m_revision = revision;
@ -747,7 +749,7 @@ void SConfig::SetRunningGameMetadata(const std::string& game_id, u64 title_id, u
} }
const Core::TitleDatabase title_database; const Core::TitleDatabase title_database;
m_title_description = title_database.Describe(m_game_id, type); m_title_description = title_database.Describe(m_gametdb_id);
NOTICE_LOG(CORE, "Active title: %s", m_title_description.c_str()); NOTICE_LOG(CORE, "Active title: %s", m_title_description.c_str());
Config::AddLayer(ConfigLoaders::GenerateGlobalGameConfigLoader(game_id, revision)); Config::AddLayer(ConfigLoaders::GenerateGlobalGameConfigLoader(game_id, revision));

View File

@ -367,12 +367,13 @@ private:
void LoadAutoUpdateSettings(IniFile& ini); void LoadAutoUpdateSettings(IniFile& ini);
void LoadJitDebugSettings(IniFile& ini); void LoadJitDebugSettings(IniFile& ini);
void SetRunningGameMetadata(const std::string& game_id, u64 title_id, u16 revision, void SetRunningGameMetadata(const std::string& game_id, const std::string& gametdb_id,
Core::TitleDatabase::TitleType type); u64 title_id, u16 revision);
static SConfig* m_Instance; static SConfig* m_Instance;
std::string m_game_id; std::string m_game_id;
std::string m_gametdb_id;
std::string m_title_description; std::string m_title_description;
u64 m_title_id; u64 m_title_id;
u16 m_revision; u16 m_revision;

View File

@ -16,21 +16,9 @@
namespace Gecko namespace Gecko
{ {
std::vector<GeckoCode> DownloadCodes(std::string gameid, bool* succeeded) std::vector<GeckoCode> DownloadCodes(std::string gametdb_id, bool* succeeded)
{ {
switch (gameid[0]) std::string endpoint{"https://www.geckocodes.org/txt.php?txt=" + gametdb_id};
{
case 'R':
case 'S':
case 'G':
break;
default:
// All channels (WiiWare, VirtualConsole, etc) are identified by their first four characters
gameid = gameid.substr(0, 4);
break;
}
std::string endpoint{"https://www.geckocodes.org/txt.php?txt=" + gameid};
Common::HttpRequest http; Common::HttpRequest http;
// Circumvent high-tech DDOS protection // Circumvent high-tech DDOS protection

View File

@ -13,6 +13,6 @@ class IniFile;
namespace Gecko namespace Gecko
{ {
std::vector<GeckoCode> LoadCodes(const IniFile& globalIni, const IniFile& localIni); std::vector<GeckoCode> LoadCodes(const IniFile& globalIni, const IniFile& localIni);
std::vector<GeckoCode> DownloadCodes(std::string gameid, bool* succeeded); std::vector<GeckoCode> DownloadCodes(std::string gametdb_id, bool* succeeded);
void SaveCodes(IniFile& inifile, const std::vector<GeckoCode>& gcodes); void SaveCodes(IniFile& inifile, const std::vector<GeckoCode>& gcodes);
} }

View File

@ -323,6 +323,20 @@ std::string TMDReader::GetGameID() const
return StringFromFormat("%016" PRIx64, GetTitleId()); return StringFromFormat("%016" PRIx64, GetTitleId());
} }
std::string TMDReader::GetGameTDBID() const
{
const u8* begin = m_bytes.data() + offsetof(TMDHeader, title_id) + 4;
const u8* end = begin + 4;
const bool all_printable =
std::all_of(begin, end, [](char c) { return std::isprint(c, std::locale::classic()); });
if (all_printable)
return std::string(begin, end);
return StringFromFormat("%016" PRIx64, GetTitleId());
}
u16 TMDReader::GetNumContents() const u16 TMDReader::GetNumContents() const
{ {
return Common::swap16(m_bytes.data() + offsetof(TMDHeader, num_contents)); return Common::swap16(m_bytes.data() + offsetof(TMDHeader, num_contents));

View File

@ -205,9 +205,15 @@ public:
// Constructs a 6-character game ID in the format typically used by Dolphin. // Constructs a 6-character game ID in the format typically used by Dolphin.
// If the 6-character game ID would contain unprintable characters, // If the 6-character game ID would contain unprintable characters,
// the title ID converted to hexadecimal is returned instead. // the title ID converted to 16 hexadecimal digits is returned instead.
std::string GetGameID() const; std::string GetGameID() const;
// Constructs a 4-character game ID in the format typically used by GameTDB.
// If the 4-character game ID would contain unprintable characters,
// the title ID converted to 16 hexadecimal digits is returned instead
// (a format which GameTDB does not actually use).
std::string GetGameTDBID() const;
u16 GetNumContents() const; u16 GetNumContents() const;
bool GetContent(u16 index, Content* content) const; bool GetContent(u16 index, Content* content) const;
std::vector<Content> GetContents() const; std::vector<Content> GetContents() const;

View File

@ -167,12 +167,10 @@ TitleDatabase::TitleDatabase()
TitleDatabase::~TitleDatabase() = default; TitleDatabase::~TitleDatabase() = default;
const std::string& TitleDatabase::GetTitleName(const std::string& game_id, TitleType type) const const std::string& TitleDatabase::GetTitleName(const std::string& gametdb_id) const
{ {
const auto& map = IsWiiTitle(game_id) ? m_wii_title_map : m_gc_title_map; const auto& map = IsWiiTitle(gametdb_id) ? m_wii_title_map : m_gc_title_map;
const std::string key = const auto iterator = map.find(gametdb_id);
type == TitleType::Channel && game_id.length() == 6 ? game_id.substr(0, 4) : game_id;
const auto iterator = map.find(key);
return iterator != map.end() ? iterator->second : EMPTY_STRING; return iterator != map.end() ? iterator->second : EMPTY_STRING;
} }
@ -181,14 +179,14 @@ const std::string& TitleDatabase::GetChannelName(u64 title_id) const
const std::string id{ const std::string id{
{static_cast<char>((title_id >> 24) & 0xff), static_cast<char>((title_id >> 16) & 0xff), {static_cast<char>((title_id >> 24) & 0xff), static_cast<char>((title_id >> 16) & 0xff),
static_cast<char>((title_id >> 8) & 0xff), static_cast<char>(title_id & 0xff)}}; static_cast<char>((title_id >> 8) & 0xff), static_cast<char>(title_id & 0xff)}};
return GetTitleName(id, TitleType::Channel); return GetTitleName(id);
} }
std::string TitleDatabase::Describe(const std::string& game_id, TitleType type) const std::string TitleDatabase::Describe(const std::string& gametdb_id) const
{ {
const std::string& title_name = GetTitleName(game_id, type); const std::string& title_name = GetTitleName(gametdb_id);
if (title_name.empty()) if (title_name.empty())
return game_id; return gametdb_id;
return StringFromFormat("%s (%s)", title_name.c_str(), game_id.c_str()); return StringFromFormat("%s (%s)", title_name.c_str(), gametdb_id.c_str());
} }
} // namespace Core } // namespace Core

View File

@ -18,21 +18,15 @@ public:
TitleDatabase(); TitleDatabase();
~TitleDatabase(); ~TitleDatabase();
enum class TitleType // Get a user friendly title name for a GameTDB ID.
{
Channel,
Other,
};
// Get a user friendly title name for a game ID.
// This falls back to returning an empty string if none could be found. // This falls back to returning an empty string if none could be found.
const std::string& GetTitleName(const std::string& game_id, TitleType = TitleType::Other) const; const std::string& GetTitleName(const std::string& gametdb_id) const;
// Same as above, but takes a title ID instead of a game ID, and can only find names of channels. // Same as above, but takes a title ID instead of a GameTDB ID, and only works for channels.
const std::string& GetChannelName(u64 title_id) const; const std::string& GetChannelName(u64 title_id) const;
// Get a description for a game ID (title name if available + game ID). // Get a description for a GameTDB ID (title name if available + GameTDB ID).
std::string Describe(const std::string& game_id, TitleType = TitleType::Other) const; std::string Describe(const std::string& gametdb_id) const;
private: private:
std::unordered_map<std::string, std::string> m_wii_title_map; std::unordered_map<std::string, std::string> m_wii_title_map;

View File

@ -76,6 +76,7 @@ public:
return offset; return offset;
} }
virtual std::string GetGameID(const Partition& partition = PARTITION_NONE) const = 0; virtual std::string GetGameID(const Partition& partition = PARTITION_NONE) const = 0;
virtual std::string GetGameTDBID(const Partition& partition = PARTITION_NONE) const = 0;
virtual std::string GetMakerID(const Partition& partition = PARTITION_NONE) const = 0; virtual std::string GetMakerID(const Partition& partition = PARTITION_NONE) const = 0;
virtual std::optional<u16> GetRevision(const Partition& partition = PARTITION_NONE) const = 0; virtual std::optional<u16> GetRevision(const Partition& partition = PARTITION_NONE) const = 0;
virtual std::string GetInternalName(const Partition& partition = PARTITION_NONE) const = 0; virtual std::string GetInternalName(const Partition& partition = PARTITION_NONE) const = 0;

View File

@ -72,6 +72,17 @@ std::string VolumeGC::GetGameID(const Partition& partition) const
return DecodeString(id); return DecodeString(id);
} }
std::string VolumeGC::GetGameTDBID(const Partition& partition) const
{
const std::string game_id = GetGameID(partition);
// Don't return an ID for Datel discs that are using the game ID of NHL Hitz 2002
if (game_id == "GNHE5d" && !GetBootDOLOffset(*this, partition).has_value())
return "";
return game_id;
}
Region VolumeGC::GetRegion() const Region VolumeGC::GetRegion() const
{ {
const std::optional<u32> region_code = ReadSwapped<u32>(0x458, PARTITION_NONE); const std::optional<u32> region_code = ReadSwapped<u32>(0x458, PARTITION_NONE);

View File

@ -34,6 +34,7 @@ public:
const Partition& partition = PARTITION_NONE) const override; const Partition& partition = PARTITION_NONE) const override;
const FileSystem* GetFileSystem(const Partition& partition = PARTITION_NONE) const override; const FileSystem* GetFileSystem(const Partition& partition = PARTITION_NONE) const override;
std::string GetGameID(const Partition& partition = PARTITION_NONE) const override; std::string GetGameID(const Partition& partition = PARTITION_NONE) const override;
std::string GetGameTDBID(const Partition& partition = PARTITION_NONE) const override;
std::string GetMakerID(const Partition& partition = PARTITION_NONE) const override; std::string GetMakerID(const Partition& partition = PARTITION_NONE) const override;
std::optional<u16> GetRevision(const Partition& partition = PARTITION_NONE) const override; std::optional<u16> GetRevision(const Partition& partition = PARTITION_NONE) const override;
std::string GetInternalName(const Partition& partition = PARTITION_NONE) const override; std::string GetInternalName(const Partition& partition = PARTITION_NONE) const override;

View File

@ -105,6 +105,11 @@ std::string VolumeWAD::GetGameID(const Partition& partition) const
return m_tmd.GetGameID(); return m_tmd.GetGameID();
} }
std::string VolumeWAD::GetGameTDBID(const Partition& partition) const
{
return m_tmd.GetGameTDBID();
}
std::string VolumeWAD::GetMakerID(const Partition& partition) const std::string VolumeWAD::GetMakerID(const Partition& partition) const
{ {
char temp[2]; char temp[2];

View File

@ -35,6 +35,7 @@ public:
std::optional<u64> GetTitleID(const Partition& partition = PARTITION_NONE) const override; std::optional<u64> GetTitleID(const Partition& partition = PARTITION_NONE) const override;
const IOS::ES::TMDReader& GetTMD(const Partition& partition = PARTITION_NONE) const override; const IOS::ES::TMDReader& GetTMD(const Partition& partition = PARTITION_NONE) const override;
std::string GetGameID(const Partition& partition = PARTITION_NONE) const override; std::string GetGameID(const Partition& partition = PARTITION_NONE) const override;
std::string GetGameTDBID(const Partition& partition = PARTITION_NONE) const override;
std::string GetMakerID(const Partition& partition = PARTITION_NONE) const override; std::string GetMakerID(const Partition& partition = PARTITION_NONE) const override;
std::optional<u16> GetRevision(const Partition& partition = PARTITION_NONE) const override; std::optional<u16> GetRevision(const Partition& partition = PARTITION_NONE) const override;
std::string GetInternalName(const Partition& partition = PARTITION_NONE) const override std::string GetInternalName(const Partition& partition = PARTITION_NONE) const override

View File

@ -278,6 +278,11 @@ std::string VolumeWii::GetGameID(const Partition& partition) const
return DecodeString(id); return DecodeString(id);
} }
std::string VolumeWii::GetGameTDBID(const Partition& partition) const
{
return GetGameID(partition);
}
Region VolumeWii::GetRegion() const Region VolumeWii::GetRegion() const
{ {
const std::optional<u32> region_code = m_reader->ReadSwapped<u32>(0x4E000); const std::optional<u32> region_code = m_reader->ReadSwapped<u32>(0x4E000);

View File

@ -45,6 +45,7 @@ public:
u64 partition_data_offset); u64 partition_data_offset);
u64 PartitionOffsetToRawOffset(u64 offset, const Partition& partition) const override; u64 PartitionOffsetToRawOffset(u64 offset, const Partition& partition) const override;
std::string GetGameID(const Partition& partition) const override; std::string GetGameID(const Partition& partition) const override;
std::string GetGameTDBID(const Partition& partition) const override;
std::string GetMakerID(const Partition& partition) const override; std::string GetMakerID(const Partition& partition) const override;
std::optional<u16> GetRevision(const Partition& partition) const override; std::optional<u16> GetRevision(const Partition& partition) const override;
std::string GetInternalName(const Partition& partition) const override; std::string GetInternalName(const Partition& partition) const override;

View File

@ -26,8 +26,8 @@
#include "UICommon/GameFile.h" #include "UICommon/GameFile.h"
GeckoCodeWidget::GeckoCodeWidget(const UICommon::GameFile& game, bool restart_required) GeckoCodeWidget::GeckoCodeWidget(const UICommon::GameFile& game, bool restart_required)
: m_game(game), m_game_id(game.GetGameID()), m_game_revision(game.GetRevision()), : m_game(game), m_game_id(game.GetGameID()), m_gametdb_id(game.GetGameTDBID()),
m_restart_required(restart_required) m_game_revision(game.GetRevision()), m_restart_required(restart_required)
{ {
CreateWidgets(); CreateWidgets();
ConnectWidgets(); ConnectWidgets();
@ -251,7 +251,7 @@ void GeckoCodeWidget::DownloadCodes()
{ {
bool success; bool success;
std::vector<Gecko::GeckoCode> codes = Gecko::DownloadCodes(m_game_id, &success); std::vector<Gecko::GeckoCode> codes = Gecko::DownloadCodes(m_gametdb_id, &success);
if (!success) if (!success)
{ {

View File

@ -48,6 +48,7 @@ private:
const UICommon::GameFile& m_game; const UICommon::GameFile& m_game;
std::string m_game_id; std::string m_game_id;
std::string m_gametdb_id;
u16 m_game_revision; u16 m_game_revision;
CheatWarningWidget* m_warning; CheatWarningWidget* m_warning;

View File

@ -132,6 +132,7 @@ GameFile::GameFile(const std::string& path)
m_internal_name = volume->GetInternalName(); m_internal_name = volume->GetInternalName();
m_game_id = volume->GetGameID(); m_game_id = volume->GetGameID();
m_gametdb_id = volume->GetGameTDBID();
m_title_id = volume->GetTitleID().value_or(0); m_title_id = volume->GetTitleID().value_or(0);
m_maker_id = volume->GetMakerID(); m_maker_id = volume->GetMakerID();
m_revision = volume->GetRevision().value_or(0); m_revision = volume->GetRevision().value_or(0);
@ -198,9 +199,8 @@ void GameFile::DownloadDefaultCover()
const auto cover_path = File::GetUserPath(D_COVERCACHE_IDX) + DIR_SEP; const auto cover_path = File::GetUserPath(D_COVERCACHE_IDX) + DIR_SEP;
// If covers have already been downloaded, abort // If the cover has already been downloaded, abort
if (File::Exists(cover_path + m_game_id + ".png") || if (File::Exists(cover_path + m_gametdb_id + ".png"))
File::Exists(cover_path + m_game_id.substr(0, 4) + ".png"))
return; return;
Common::HttpRequest request; Common::HttpRequest request;
@ -249,22 +249,13 @@ void GameFile::DownloadDefaultCover()
break; break;
} }
auto response = request.Get(StringFromFormat(COVER_URL, region_code.c_str(), m_game_id.c_str())); auto response =
request.Get(StringFromFormat(COVER_URL, region_code.c_str(), m_gametdb_id.c_str()));
if (response) if (response)
{ {
File::WriteStringToFile(std::string(response.value().begin(), response.value().end()), File::WriteStringToFile(std::string(response.value().begin(), response.value().end()),
cover_path + m_game_id + ".png"); cover_path + m_gametdb_id + ".png");
return;
}
response =
request.Get(StringFromFormat(COVER_URL, region_code.c_str(), m_game_id.substr(0, 4).c_str()));
if (response)
{
File::WriteStringToFile(std::string(response.value().begin(), response.value().end()),
cover_path + m_game_id.substr(0, 4) + ".png");
} }
} }
@ -277,10 +268,7 @@ bool GameFile::DefaultCoverChanged()
std::string contents; std::string contents;
File::ReadFileToString(cover_path + m_game_id + ".png", contents); File::ReadFileToString(cover_path + m_gametdb_id + ".png", contents);
if (contents.empty())
File::ReadFileToString(cover_path + m_game_id.substr(0, 4).c_str() + ".png", contents);
if (contents.empty()) if (contents.empty())
return false; return false;
@ -328,6 +316,7 @@ void GameFile::DoState(PointerWrap& p)
p.Do(m_descriptions); p.Do(m_descriptions);
p.Do(m_internal_name); p.Do(m_internal_name);
p.Do(m_game_id); p.Do(m_game_id);
p.Do(m_gametdb_id);
p.Do(m_title_id); p.Do(m_title_id);
p.Do(m_maker_id); p.Do(m_maker_id);
@ -433,10 +422,7 @@ void GameFile::CustomBannerCommit()
const std::string& GameFile::GetName(const Core::TitleDatabase& title_database) const const std::string& GameFile::GetName(const Core::TitleDatabase& title_database) const
{ {
const auto type = m_platform == DiscIO::Platform::WiiWAD ? const std::string& custom_name = title_database.GetTitleName(m_gametdb_id);
Core::TitleDatabase::TitleType::Channel :
Core::TitleDatabase::TitleType::Other;
const std::string& custom_name = title_database.GetTitleName(m_game_id, type);
return custom_name.empty() ? GetName() : custom_name; return custom_name.empty() ? GetName() : custom_name;
} }

View File

@ -67,6 +67,7 @@ public:
std::vector<DiscIO::Language> GetLanguages() const; std::vector<DiscIO::Language> GetLanguages() const;
const std::string& GetInternalName() const { return m_internal_name; } const std::string& GetInternalName() const { return m_internal_name; }
const std::string& GetGameID() const { return m_game_id; } const std::string& GetGameID() const { return m_game_id; }
const std::string& GetGameTDBID() const { return m_gametdb_id; }
u64 GetTitleID() const { return m_title_id; } u64 GetTitleID() const { return m_title_id; }
const std::string& GetMakerID() const { return m_maker_id; } const std::string& GetMakerID() const { return m_maker_id; }
u16 GetRevision() const { return m_revision; } u16 GetRevision() const { return m_revision; }
@ -120,6 +121,7 @@ private:
std::map<DiscIO::Language, std::string> m_descriptions{}; std::map<DiscIO::Language, std::string> m_descriptions{};
std::string m_internal_name{}; std::string m_internal_name{};
std::string m_game_id{}; std::string m_game_id{};
std::string m_gametdb_id{};
u64 m_title_id{}; u64 m_title_id{};
std::string m_maker_id{}; std::string m_maker_id{};

View File

@ -27,7 +27,7 @@
namespace UICommon namespace UICommon
{ {
static constexpr u32 CACHE_REVISION = 14; // Last changed in PR 7441 static constexpr u32 CACHE_REVISION = 15; // Last changed in PR 7816
std::vector<std::string> FindAllGamePaths(const std::vector<std::string>& directories_to_scan, std::vector<std::string> FindAllGamePaths(const std::vector<std::string>& directories_to_scan,
bool recursive_scan) bool recursive_scan)