Add a TitleDatabase

Add a TitleDatabase to allow easily querying a title database to get
a user-friendly string for a game ID.
This commit is contained in:
Léo Lam 2017-05-15 12:25:45 +02:00
parent ae9dabed1e
commit 4a55d757dd
5 changed files with 194 additions and 0 deletions

View File

@ -17,6 +17,7 @@ set(SRCS
NetPlayServer.cpp
PatchEngine.cpp
State.cpp
TitleDatabase.cpp
WiiRoot.cpp
Boot/Boot_BS2Emu.cpp
Boot/Boot.cpp

View File

@ -285,6 +285,7 @@
<ClCompile Include="PowerPC\PPCTables.cpp" />
<ClCompile Include="PowerPC\Profiler.cpp" />
<ClCompile Include="State.cpp" />
<ClCompile Include="TitleDatabase.cpp" />
<ClCompile Include="WiiRoot.cpp" />
</ItemGroup>
<ItemGroup>
@ -512,6 +513,7 @@
<ClInclude Include="PowerPC\PPCTables.h" />
<ClInclude Include="PowerPC\Profiler.h" />
<ClInclude Include="State.h" />
<ClInclude Include="TitleDatabase.h" />
<ClInclude Include="WiiRoot.h" />
</ItemGroup>
<ItemGroup>

View File

@ -168,6 +168,7 @@
<ClCompile Include="NetPlayServer.cpp" />
<ClCompile Include="PatchEngine.cpp" />
<ClCompile Include="State.cpp" />
<ClCompile Include="TitleDatabase.cpp" />
<ClCompile Include="WiiRoot.cpp" />
<ClCompile Include="ActionReplay.cpp">
<Filter>ActionReplay</Filter>
@ -871,6 +872,7 @@
<ClInclude Include="NetPlayServer.h" />
<ClInclude Include="PatchEngine.h" />
<ClInclude Include="State.h" />
<ClInclude Include="TitleDatabase.h" />
<ClInclude Include="WiiRoot.h" />
<ClInclude Include="ActionReplay.h">
<Filter>ActionReplay</Filter>

View File

@ -0,0 +1,151 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <fstream>
#include <functional>
#include <iostream>
#include "Core/TitleDatabase.h"
#include "Common/FileUtil.h"
#include "Common/MsgHandler.h"
#include "Common/StringUtil.h"
#include "Core/ConfigManager.h"
#include "DiscIO/Enums.h"
namespace Core
{
static std::string GetLanguageCode(DiscIO::Language language)
{
switch (language)
{
case DiscIO::Language::LANGUAGE_JAPANESE:
return "ja";
case DiscIO::Language::LANGUAGE_ENGLISH:
return "en";
case DiscIO::Language::LANGUAGE_GERMAN:
return "de";
case DiscIO::Language::LANGUAGE_FRENCH:
return "fr";
case DiscIO::Language::LANGUAGE_SPANISH:
return "es";
case DiscIO::Language::LANGUAGE_ITALIAN:
return "it";
case DiscIO::Language::LANGUAGE_DUTCH:
return "nl";
case DiscIO::Language::LANGUAGE_SIMPLIFIED_CHINESE:
return "zh_CN";
case DiscIO::Language::LANGUAGE_TRADITIONAL_CHINESE:
return "zh_TW";
case DiscIO::Language::LANGUAGE_KOREAN:
return "ko";
default:
return "en";
}
}
using Map = std::unordered_map<std::string, std::string>;
static bool LoadMap(const std::string& file_path, Map& map,
std::function<bool(const std::string& game_id)> predicate)
{
std::ifstream txt;
OpenFStream(txt, file_path, std::ios::in);
if (!txt.is_open())
return false;
std::string line;
while (std::getline(txt, line))
{
if (line.empty())
continue;
const size_t equals_index = line.find('=');
if (equals_index != std::string::npos)
{
const std::string game_id = StripSpaces(line.substr(0, equals_index));
if (predicate(game_id))
map[game_id] = StripSpaces(line.substr(equals_index + 1));
}
}
return true;
}
// This should only be used with the standard game ID format (used by WiiTDBs), not Dolphin's.
// The main difference is that Dolphin uses 6 characters for non-disc titles (instead of 4).
static bool IsGCTitle(const std::string& game_id)
{
const char system_id = game_id[0];
return game_id.length() == 6 &&
(system_id == 'G' || system_id == 'D' || system_id == 'U' || system_id == 'P');
}
static bool IsWiiTitle(const std::string& game_id)
{
// Assume that any non-GameCube title is a Wii title.
return !IsGCTitle(game_id);
}
static bool LoadMap(const std::string& file_path, Map& gc_map, Map& wii_map)
{
Map map;
if (!LoadMap(file_path, map, [](const auto& game_id) { return true; }))
return false;
for (auto& entry : map)
{
auto& destination_map = IsGCTitle(entry.first) ? gc_map : wii_map;
destination_map.emplace(std::move(entry));
}
return true;
}
TitleDatabase::TitleDatabase()
{
// Titles that cannot be part of the Wii TDB,
// but common enough to justify having entries for them.
// i18n: "Wii Menu" (or System Menu) refers to the Wii's main menu,
// which is (usually) the first thing users see when a Wii console starts.
m_wii_title_map.emplace("0000000100000002", GetStringT("Wii Menu"));
for (const auto& id : {"HAXX", "JODI", "00010001af1bf516", "LULZ", "OHBC"})
m_wii_title_map.emplace(id, "The Homebrew Channel");
// Load the English database as the base database.
LoadMap(File::GetSysDirectory() + "wiitdb-en.txt", m_gc_title_map, m_wii_title_map);
// Load the database in the console language.
const std::string gc_code = GetLanguageCode(SConfig::GetInstance().GetCurrentLanguage(false));
const std::string wii_code = GetLanguageCode(SConfig::GetInstance().GetCurrentLanguage(true));
if (gc_code != "en")
LoadMap(File::GetSysDirectory() + "wiitdb-" + gc_code + ".txt", m_gc_title_map, IsGCTitle);
if (wii_code != "en")
LoadMap(File::GetSysDirectory() + "wiitdb-" + wii_code + ".txt", m_wii_title_map, IsWiiTitle);
// Load the user databases.
const std::string& load_directory = File::GetUserPath(D_LOAD_IDX);
if (!LoadMap(load_directory + "wiitdb.txt", m_gc_title_map, m_wii_title_map))
LoadMap(load_directory + "titles.txt", m_gc_title_map, m_wii_title_map);
}
TitleDatabase::~TitleDatabase() = default;
std::string TitleDatabase::GetTitleName(const std::string& game_id, TitleType type) const
{
const auto& map = IsWiiTitle(game_id) ? m_wii_title_map : m_gc_title_map;
const std::string key =
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 : "";
}
std::string TitleDatabase::Describe(const std::string& game_id, TitleType type) const
{
const std::string title_name = GetTitleName(game_id, type);
if (title_name.empty())
return game_id;
return StringFromFormat("%s (%s)", title_name.c_str(), game_id.c_str());
}
} // namespace Core

View File

@ -0,0 +1,38 @@
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <string>
#include <unordered_map>
#include "Common/CommonTypes.h"
namespace Core
{
// Reader for title database files.
class TitleDatabase final
{
public:
TitleDatabase();
~TitleDatabase();
enum class TitleType
{
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.
std::string GetTitleName(const std::string& game_id, TitleType = TitleType::Other) const;
// Get a description for a game ID (title name if available + game ID).
std::string Describe(const std::string& game_id, TitleType = TitleType::Other) const;
private:
std::unordered_map<std::string, std::string> m_wii_title_map;
std::unordered_map<std::string, std::string> m_gc_title_map;
};
} // namespace Core