mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-24 23:25:38 +00:00
Added the ability to make complementary game systems customizations.
This commit is contained in:
parent
1ad55cdcec
commit
8a51919f31
|
@ -1320,8 +1320,13 @@ void CollectionSystemsManager::addEnabledCollectionsToDisplayedSystems(
|
|||
std::vector<std::string> CollectionSystemsManager::getSystemsFromConfig()
|
||||
{
|
||||
std::vector<std::string> systems;
|
||||
std::string path = SystemData::getConfigPath(false);
|
||||
std::vector<std::string> configPaths = SystemData::getConfigPath(false);
|
||||
|
||||
// Here we don't honor the <loadExclusive> tag which may be present in the custom es_systems.xml
|
||||
// file under ~/.emulationstation/custom_systems as we really want to include all the themes
|
||||
// supported by ES-DE. Otherwise a user may accidentally create a custom collection that
|
||||
// corresponds to a supported theme.
|
||||
for (auto path : configPaths) {
|
||||
if (!Utils::FileSystem::exists(path))
|
||||
return systems;
|
||||
|
||||
|
@ -1345,8 +1350,11 @@ std::vector<std::string> CollectionSystemsManager::getSystemsFromConfig()
|
|||
system = system.next_sibling("system")) {
|
||||
// Theme folder.
|
||||
std::string themeFolder = system.child("theme").text().get();
|
||||
if (std::find(systems.cbegin(), systems.cend(), themeFolder) == systems.cend())
|
||||
systems.push_back(themeFolder);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(systems.begin(), systems.end());
|
||||
return systems;
|
||||
}
|
||||
|
|
|
@ -387,9 +387,17 @@ bool SystemData::loadConfig()
|
|||
|
||||
LOG(LogInfo) << "Populating game systems...";
|
||||
|
||||
std::string path = getConfigPath(true);
|
||||
std::vector<std::string> configPaths = getConfigPath(true);
|
||||
const std::string rompath = FileData::getROMDirectory();
|
||||
|
||||
bool onlyProcessCustomFile = false;
|
||||
|
||||
for (auto path : configPaths) {
|
||||
// If the loadExclusive tag is present in the custom es_systems.xml file, then skip
|
||||
// processing of the bundled configuration file.
|
||||
if (onlyProcessCustomFile)
|
||||
break;
|
||||
|
||||
LOG(LogInfo) << "Parsing systems configuration file \"" << path << "\"...";
|
||||
|
||||
pugi::xml_document doc;
|
||||
|
@ -404,6 +412,19 @@ bool SystemData::loadConfig()
|
|||
return true;
|
||||
}
|
||||
|
||||
pugi::xml_node loadExclusive = doc.child("loadExclusive");
|
||||
if (loadExclusive) {
|
||||
if (path == configPaths.front() && configPaths.size() > 1) {
|
||||
LOG(LogInfo) << "Only loading custom file as the <loadExclusive> tag is present";
|
||||
onlyProcessCustomFile = true;
|
||||
}
|
||||
else {
|
||||
LOG(LogWarning) << "A <loadExclusive> tag is present in the bundled es_systems.xml "
|
||||
"file, ignoring it as this is only supposed to be used for the "
|
||||
"custom es_systems.xml file";
|
||||
}
|
||||
}
|
||||
|
||||
// Actually read the file.
|
||||
pugi::xml_node systemList = doc.child("systemList");
|
||||
|
||||
|
@ -448,10 +469,12 @@ bool SystemData::loadConfig()
|
|||
#endif
|
||||
path = Utils::String::replace(path, "//", "/");
|
||||
|
||||
// Check that the ROM directory for the system is valid or otherwise abort the processing.
|
||||
// Check that the ROM directory for the system is valid or otherwise abort the
|
||||
// processing.
|
||||
if (!Utils::FileSystem::exists(path)) {
|
||||
LOG(LogDebug) << "SystemData::loadConfig(): Skipping system \"" << name
|
||||
<< "\" as the defined ROM directory \"" << path << "\" does not exist";
|
||||
<< "\" as the defined ROM directory \"" << path
|
||||
<< "\" does not exist";
|
||||
continue;
|
||||
}
|
||||
if (!Utils::FileSystem::isDirectory(path)) {
|
||||
|
@ -465,9 +488,9 @@ bool SystemData::loadConfig()
|
|||
// as that would lead to an infite loop, meaning the application would never start.
|
||||
std::string resolvedRompath = Utils::FileSystem::getCanonicalPath(rompath);
|
||||
if (resolvedRompath.find(Utils::FileSystem::getCanonicalPath(path)) == 0) {
|
||||
LOG(LogWarning) << "Skipping system \"" << name
|
||||
<< "\" as the defined ROM directory \"" << path
|
||||
<< "\" is an infinitely recursive symlink";
|
||||
LOG(LogWarning)
|
||||
<< "Skipping system \"" << name << "\" as the defined ROM directory \""
|
||||
<< path << "\" is an infinitely recursive symlink";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -501,7 +524,8 @@ bool SystemData::loadConfig()
|
|||
}
|
||||
else if (!commands.empty() && commands.back().second == "") {
|
||||
// There are more than one command tags and the first tag did not have a label.
|
||||
LOG(LogError) << "Missing mandatory label attribute for alternative emulator "
|
||||
LOG(LogError)
|
||||
<< "Missing mandatory label attribute for alternative emulator "
|
||||
"entry, only the first command tag will be processed for system \""
|
||||
<< name << "\"";
|
||||
break;
|
||||
|
@ -582,7 +606,8 @@ bool SystemData::loadConfig()
|
|||
// If the option to show hidden games has been disabled, then check whether all
|
||||
// games for the system are hidden. That will flag the system as empty.
|
||||
if (!Settings::getInstance()->getBool("ShowHiddenGames")) {
|
||||
std::vector<FileData*> recursiveGames = newSys->getRootFolder()->getChildrenRecursive();
|
||||
std::vector<FileData*> recursiveGames =
|
||||
newSys->getRootFolder()->getChildrenRecursive();
|
||||
onlyHidden = true;
|
||||
for (auto it = recursiveGames.cbegin(); it != recursiveGames.cend(); it++) {
|
||||
if ((*it)->getType() != FOLDER) {
|
||||
|
@ -602,6 +627,7 @@ bool SystemData::loadConfig()
|
|||
sSystemVector.push_back(newSys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort systems by their full names.
|
||||
std::sort(std::begin(sSystemVector), std::end(sSystemVector),
|
||||
|
@ -634,8 +660,10 @@ void SystemData::deleteSystems()
|
|||
sSystemVector.clear();
|
||||
}
|
||||
|
||||
std::string SystemData::getConfigPath(bool legacyWarning)
|
||||
std::vector<std::string> SystemData::getConfigPath(bool legacyWarning)
|
||||
{
|
||||
std::vector<std::string> paths;
|
||||
|
||||
if (legacyWarning) {
|
||||
std::string legacyConfigFile =
|
||||
Utils::FileSystem::getHomePath() + "/.emulationstation/es_systems.cfg";
|
||||
|
@ -662,7 +690,7 @@ std::string SystemData::getConfigPath(bool legacyWarning)
|
|||
|
||||
if (Utils::FileSystem::exists(path)) {
|
||||
LOG(LogInfo) << "Found custom systems configuration file";
|
||||
return path;
|
||||
paths.push_back(path);
|
||||
}
|
||||
|
||||
#if defined(_WIN64)
|
||||
|
@ -674,18 +702,16 @@ std::string SystemData::getConfigPath(bool legacyWarning)
|
|||
path = ResourceManager::getInstance()->getResourcePath(":/systems/unix/es_systems.xml", true);
|
||||
#endif
|
||||
|
||||
return path;
|
||||
paths.push_back(path);
|
||||
return paths;
|
||||
}
|
||||
|
||||
bool SystemData::createSystemDirectories()
|
||||
{
|
||||
std::string path = getConfigPath(false);
|
||||
std::vector<std::string> configPaths = getConfigPath(true);
|
||||
const std::string rompath = FileData::getROMDirectory();
|
||||
|
||||
if (!Utils::FileSystem::exists(path)) {
|
||||
LOG(LogInfo) << "Systems configuration file does not exist, aborting";
|
||||
return true;
|
||||
}
|
||||
bool onlyProcessCustomFile = false;
|
||||
|
||||
LOG(LogInfo) << "Generating ROM directory structure...";
|
||||
|
||||
|
@ -706,13 +732,42 @@ bool SystemData::createSystemDirectories()
|
|||
LOG(LogInfo) << "Base ROM directory \"" << rompath << "\" already exists";
|
||||
}
|
||||
|
||||
LOG(LogInfo) << "Parsing systems configuration file \"" << path << "\"...";
|
||||
if (configPaths.size() > 1) {
|
||||
// If the loadExclusive tag is present in the custom es_systems.xml file, then skip
|
||||
// processing of the bundled configuration file.
|
||||
pugi::xml_document doc;
|
||||
#if defined(_WIN64)
|
||||
pugi::xml_parse_result res =
|
||||
doc.load_file(Utils::String::stringToWideString(configPath).c_str());
|
||||
#else
|
||||
pugi::xml_parse_result res = doc.load_file(configPaths.front().c_str());
|
||||
#endif
|
||||
if (res) {
|
||||
pugi::xml_node loadExclusive = doc.child("loadExclusive");
|
||||
if (loadExclusive)
|
||||
onlyProcessCustomFile = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Process the custom es_systems.xml file after the bundled file, as any systems with identical
|
||||
// <path> tags will be overwritten by the last occurrence.
|
||||
std::reverse(configPaths.begin(), configPaths.end());
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> systemsVector;
|
||||
|
||||
for (auto configPath : configPaths) {
|
||||
// If the loadExclusive tag is present.
|
||||
if (onlyProcessCustomFile && configPath == configPaths.front())
|
||||
continue;
|
||||
|
||||
LOG(LogInfo) << "Parsing systems configuration file \"" << configPath << "\"...";
|
||||
|
||||
pugi::xml_document doc;
|
||||
#if defined(_WIN64)
|
||||
pugi::xml_parse_result res = doc.load_file(Utils::String::stringToWideString(path).c_str());
|
||||
pugi::xml_parse_result res =
|
||||
doc.load_file(Utils::String::stringToWideString(configPath).c_str());
|
||||
#else
|
||||
pugi::xml_parse_result res = doc.load_file(path.c_str());
|
||||
pugi::xml_parse_result res = doc.load_file(configPath.c_str());
|
||||
#endif
|
||||
|
||||
if (!res) {
|
||||
|
@ -729,8 +784,6 @@ bool SystemData::createSystemDirectories()
|
|||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::string> systemsVector;
|
||||
|
||||
for (pugi::xml_node system = systemList.child("system"); system;
|
||||
system = system.next_sibling("system")) {
|
||||
std::string systemDir;
|
||||
|
@ -799,7 +852,8 @@ bool SystemData::createSystemDirectories()
|
|||
|
||||
#if defined(_WIN64)
|
||||
systemInfoFile.open(
|
||||
Utils::String::stringToWideString(rompath + systemDir + systemInfoFileName).c_str());
|
||||
Utils::String::stringToWideString(rompath + systemDir + systemInfoFileName)
|
||||
.c_str());
|
||||
#else
|
||||
systemInfoFile.open(rompath + systemDir + systemInfoFileName);
|
||||
#endif
|
||||
|
@ -813,6 +867,9 @@ bool SystemData::createSystemDirectories()
|
|||
}
|
||||
|
||||
systemInfoFile << "System name:" << std::endl;
|
||||
if (configPaths.size() != 1 && configPath == configPaths.back())
|
||||
systemInfoFile << name << " (custom system)" << std::endl << std::endl;
|
||||
else
|
||||
systemInfoFile << name << std::endl << std::endl;
|
||||
systemInfoFile << "Full system name:" << std::endl;
|
||||
systemInfoFile << fullname << std::endl << std::endl;
|
||||
|
@ -835,7 +892,18 @@ bool SystemData::createSystemDirectories()
|
|||
systemInfoFile << themeFolder << std::endl;
|
||||
systemInfoFile.close();
|
||||
|
||||
systemsVector.push_back(systemDir + ": " + fullname);
|
||||
auto systemIter = std::find_if(systemsVector.cbegin(), systemsVector.cend(),
|
||||
[systemDir](std::pair<std::string, std::string> system) {
|
||||
return system.first == systemDir;
|
||||
});
|
||||
|
||||
if (systemIter != systemsVector.cend())
|
||||
systemsVector.erase(systemIter);
|
||||
|
||||
if (configPaths.size() != 1 && configPath == configPaths.back())
|
||||
systemsVector.push_back(std::make_pair(systemDir + " (custom system)", fullname));
|
||||
else
|
||||
systemsVector.push_back(std::make_pair(systemDir, fullname));
|
||||
|
||||
if (replaceInfoFile) {
|
||||
LOG(LogInfo) << "Replaced existing system information file \""
|
||||
|
@ -846,6 +914,7 @@ bool SystemData::createSystemDirectories()
|
|||
<< rompath + systemDir + systemInfoFileName << "\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Also generate a systems.txt file directly in the ROM directory root that contains the
|
||||
// mappings between the system directory names and the full system names. This makes it
|
||||
|
@ -870,8 +939,10 @@ bool SystemData::createSystemDirectories()
|
|||
systemsFileSuccess = false;
|
||||
}
|
||||
else {
|
||||
for (std::string systemEntry : systemsVector) {
|
||||
systemsFile << systemEntry << std::endl;
|
||||
std::sort(systemsVector.begin(), systemsVector.end());
|
||||
for (auto systemEntry : systemsVector) {
|
||||
systemsFile << systemEntry.first.append(": ").append(systemEntry.second)
|
||||
<< std::endl;
|
||||
}
|
||||
systemsFile.close();
|
||||
}
|
||||
|
|
|
@ -102,9 +102,9 @@ public:
|
|||
std::string getLaunchCommandFromLabel(const std::string& label);
|
||||
|
||||
static void deleteSystems();
|
||||
// Loads the systems configuration file at getConfigPath() and creates the systems.
|
||||
// Loads the systems configuration file(s) at getConfigPath() and creates the systems.
|
||||
static bool loadConfig();
|
||||
static std::string getConfigPath(bool legacyWarning);
|
||||
static std::vector<std::string> getConfigPath(bool legacyWarning);
|
||||
|
||||
// Generates the game system directories and information files based on es_systems.xml.
|
||||
static bool createSystemDirectories();
|
||||
|
|
Loading…
Reference in a new issue