mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-29 09:35:39 +00:00
Added support for multiple platforms in the <platform> tag.
You can also use any of the whitespace characters as extension delimiters now (", \n\r\t").
This commit is contained in:
parent
ae129c5325
commit
28e7f357f7
|
@ -147,14 +147,17 @@ All systems must be contained within the <systemList> tag.-->
|
|||
All subdirectories (and non-recursive links) will be included. -->
|
||||
<path>~/roms/snes</path>
|
||||
|
||||
<!-- A list of extensions to search for, delimited by a space. You MUST include the period! It's also case sensitive. -->
|
||||
<!-- A list of extensions to search for, delimited by any of the whitespace characters (", \r\n\t").
|
||||
You MUST include the period at the start of the extension! It's also case sensitive. -->
|
||||
<extension>.smc .sfc .SMC .SFC</extension>
|
||||
|
||||
<!-- The shell command executed when a game is selected. A few special tags are replaced if found in a command, like %ROM%. -->
|
||||
<command>snesemulator %ROM%</command>
|
||||
<!-- This example would run the bash command "snesemulator /home/user/roms/snes/Super\ Mario\ World.sfc". -->
|
||||
|
||||
<!-- The platform to use when scraping. You can see the full list of accepted platforms in src/PlatformIds.cpp. -->
|
||||
<!-- The platform(s) to use when scraping. You can see the full list of accepted platforms in src/PlatformIds.cpp.
|
||||
It's case sensitive, but everything is lowercase. This tag is optional.
|
||||
You can use multiple platforms too, delimited with any of the whitespace characters (", \r\n\t"), eg: "<platform>genesis, megadrive</platform>" -->
|
||||
<platform>snes</platform>
|
||||
</system>
|
||||
</systemList>
|
||||
|
|
|
@ -56,7 +56,7 @@ FileData::~FileData()
|
|||
std::string FileData::getCleanName() const
|
||||
{
|
||||
std::string stem = mPath.stem().generic_string();
|
||||
if(mSystem && mSystem->getPlatformId() == PlatformIds::ARCADE || mSystem->getPlatformId() == PlatformIds::NEOGEO)
|
||||
if(mSystem && mSystem->hasPlatformId(PlatformIds::ARCADE) || mSystem->hasPlatformId(PlatformIds::NEOGEO))
|
||||
stem = PlatformIds::getCleanMameName(stem.c_str());
|
||||
|
||||
return removeParenthesis(stem);
|
||||
|
|
|
@ -18,7 +18,7 @@ std::vector<SystemData*> SystemData::sSystemVector;
|
|||
namespace fs = boost::filesystem;
|
||||
|
||||
SystemData::SystemData(const std::string& name, const std::string& fullName, const std::string& startPath, const std::vector<std::string>& extensions,
|
||||
const std::string& command, PlatformIds::PlatformId platformId)
|
||||
const std::string& command, const std::vector<PlatformIds::PlatformId>& platformIds)
|
||||
{
|
||||
mName = name;
|
||||
mFullName = fullName;
|
||||
|
@ -33,7 +33,7 @@ SystemData::SystemData(const std::string& name, const std::string& fullName, con
|
|||
|
||||
mSearchExtensions = extensions;
|
||||
mLaunchCommand = command;
|
||||
mPlatformId = platformId;
|
||||
mPlatformIds = platformIds;
|
||||
|
||||
mRootFolder = new FileData(FOLDER, mStartPath, this);
|
||||
mRootFolder->metadata.set("name", mFullName);
|
||||
|
@ -200,6 +200,23 @@ void SystemData::populateFolder(FileData* folder)
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> readList(const std::string& str, const char* delims = " \t\r\n,")
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
|
||||
size_t prevOff = str.find_first_not_of(delims, 0);
|
||||
size_t off = str.find_first_of(delims, prevOff);
|
||||
while(off != std::string::npos || prevOff != std::string::npos)
|
||||
{
|
||||
ret.push_back(str.substr(prevOff, off - prevOff));
|
||||
|
||||
prevOff = str.find_first_not_of(delims, off);
|
||||
off = str.find_first_of(delims, prevOff);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//creates systems from information located in a config file
|
||||
bool SystemData::loadConfig()
|
||||
{
|
||||
|
@ -244,26 +261,34 @@ bool SystemData::loadConfig()
|
|||
fullname = system.child("fullname").text().get();
|
||||
path = system.child("path").text().get();
|
||||
|
||||
//convert extensions list from a string into a vector of strings
|
||||
const pugi::char_t* extStr = system.child("extension").text().get();
|
||||
std::vector<std::string> extensions;
|
||||
std::vector<char> buff(strlen(extStr) + 1);
|
||||
strcpy(buff.data(), extStr);
|
||||
char* ext = strtok(buff.data(), " ");
|
||||
while(ext != NULL)
|
||||
{
|
||||
extensions.push_back(ext);
|
||||
ext = strtok(NULL, " ");
|
||||
}
|
||||
// convert extensions list from a string into a vector of strings
|
||||
std::vector<std::string> extensions = readList(system.child("extension").text().get());
|
||||
|
||||
cmd = system.child("command").text().get();
|
||||
|
||||
const char* platformIdString = system.child("platform").text().as_string();
|
||||
platformId = PlatformIds::getPlatformId(platformIdString);
|
||||
// platform id list
|
||||
const char* platformList = system.child("platform").text().get();
|
||||
std::vector<std::string> platformStrs = readList(platformList);
|
||||
std::vector<PlatformIds::PlatformId> platformIds;
|
||||
for(auto it = platformStrs.begin(); it != platformStrs.end(); it++)
|
||||
{
|
||||
const char* str = it->c_str();
|
||||
PlatformIds::PlatformId platformId = PlatformIds::getPlatformId(str);
|
||||
|
||||
if(platformId == PlatformIds::PLATFORM_IGNORE)
|
||||
{
|
||||
// when platform is ignore, do not allow other platforms
|
||||
platformIds.clear();
|
||||
platformIds.push_back(platformId);
|
||||
break;
|
||||
}
|
||||
|
||||
// if there appears to be an actual platform ID supplied but it didn't match the list, warn
|
||||
if(platformIdString != NULL && platformIdString[0] != '\0' && platformId == PlatformIds::PLATFORM_UNKNOWN)
|
||||
LOG(LogWarning) << " Unknown platform for system \"" << name << "\" (platform \"" << platformIdString << "\")";
|
||||
if(str != NULL && str[0] != '\0' && platformId == PlatformIds::PLATFORM_UNKNOWN)
|
||||
LOG(LogWarning) << " Unknown platform for system \"" << name << "\" (platform \"" << str << "\" from list \"" << platformList << "\")";
|
||||
else if(platformId != PlatformIds::PLATFORM_UNKNOWN)
|
||||
platformIds.push_back(platformId);
|
||||
}
|
||||
|
||||
//validate
|
||||
if(name.empty() || path.empty() || extensions.empty() || cmd.empty())
|
||||
|
@ -276,7 +301,7 @@ bool SystemData::loadConfig()
|
|||
boost::filesystem::path genericPath(path);
|
||||
path = genericPath.generic_string();
|
||||
|
||||
SystemData* newSys = new SystemData(name, fullname, path, extensions, cmd, platformId);
|
||||
SystemData* newSys = new SystemData(name, fullname, path, extensions, cmd, platformIds);
|
||||
if(newSys->getRootFolder()->getChildren().size() == 0)
|
||||
{
|
||||
LOG(LogWarning) << "System \"" << name << "\" has no games! Ignoring it.";
|
||||
|
@ -309,7 +334,8 @@ void SystemData::writeExampleConfig(const std::string& path)
|
|||
" <!-- The path to start searching for ROMs in. '~' will be expanded to $HOME on Linux or %HOMEPATH% on Windows. -->\n"
|
||||
" <path>~/roms/nes</path>\n"
|
||||
"\n"
|
||||
" <!-- A list of extensions to search for, delimited by a space. You MUST include the period! It's also case sensitive. -->\n"
|
||||
" <!-- A list of extensions to search for, delimited by any of the whitespace characters (\", \\r\\n\\t\").\n"
|
||||
" You MUST include the period at the start of the extension! It's also case sensitive. -->\n"
|
||||
" <extension>.nes .NES</extension>\n"
|
||||
"\n"
|
||||
" <!-- The shell command executed when a game is selected. A few special tags are replaced if found in a command:\n"
|
||||
|
@ -318,7 +344,9 @@ void SystemData::writeExampleConfig(const std::string& path)
|
|||
" %ROM_RAW% is the raw, unescaped path to the ROM. -->\n"
|
||||
" <command>retroarch -L ~/cores/libretro-fceumm.so %ROM%</command>\n"
|
||||
"\n"
|
||||
" <!-- The platform to use when scraping. You can see the full list of accepted platforms in src/PlatformIds.cpp. This tag is optional. -->\n"
|
||||
" <!-- The platform to use when scraping. You can see the full list of accepted platforms in src/PlatformIds.cpp.\n"
|
||||
" It's case sensitive, but everything is lowercase. This tag is optional.\n"
|
||||
" You can use multiple platforms too, delimited with any of the whitespace characters (\", \\r\\n\\t\"), eg: \"<platform>genesis, megadrive</platform>\" -->\n"
|
||||
" <platform>nes</platform>\n"
|
||||
"\n"
|
||||
" </system>\n"
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#ifndef _SYSTEMDATA_H_
|
||||
#define _SYSTEMDATA_H_
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
@ -13,7 +12,7 @@ class SystemData
|
|||
{
|
||||
public:
|
||||
SystemData(const std::string& name, const std::string& fullName, const std::string& startPath, const std::vector<std::string>& extensions,
|
||||
const std::string& command, PlatformIds::PlatformId platformId = PlatformIds::PLATFORM_UNKNOWN);
|
||||
const std::string& command, const std::vector<PlatformIds::PlatformId>& platformIds);
|
||||
~SystemData();
|
||||
|
||||
inline FileData* getRootFolder() const { return mRootFolder; };
|
||||
|
@ -21,7 +20,10 @@ public:
|
|||
inline const std::string& getFullName() const { return mFullName; }
|
||||
inline const std::string& getStartPath() const { return mStartPath; }
|
||||
inline const std::vector<std::string>& getExtensions() const { return mSearchExtensions; }
|
||||
inline PlatformIds::PlatformId getPlatformId() const { return mPlatformId; }
|
||||
|
||||
inline const std::vector<PlatformIds::PlatformId>& getPlatformIds() const { return mPlatformIds; }
|
||||
inline bool hasPlatformId(PlatformIds::PlatformId id) { return std::find(mPlatformIds.begin(), mPlatformIds.end(), id) != mPlatformIds.end(); }
|
||||
|
||||
inline const std::shared_ptr<ThemeData>& getTheme() const { return mTheme; }
|
||||
|
||||
std::string getGamelistPath(bool forWrite) const;
|
||||
|
@ -67,12 +69,10 @@ private:
|
|||
std::string mStartPath;
|
||||
std::vector<std::string> mSearchExtensions;
|
||||
std::string mLaunchCommand;
|
||||
PlatformIds::PlatformId mPlatformId;
|
||||
std::vector<PlatformIds::PlatformId> mPlatformIds;
|
||||
std::shared_ptr<ThemeData> mTheme;
|
||||
|
||||
void populateFolder(FileData* folder);
|
||||
|
||||
FileData* mRootFolder;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -129,7 +129,7 @@ GuiMetaDataEd::GuiMetaDataEd(Window* window, MetaDataList* md, const std::vector
|
|||
|
||||
std::vector< std::shared_ptr<ButtonComponent> > buttons;
|
||||
|
||||
if(scraperParams.system->getPlatformId() != PlatformIds::PLATFORM_IGNORE)
|
||||
if(!scraperParams.system->hasPlatformId(PlatformIds::PLATFORM_IGNORE))
|
||||
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "SCRAPE", "scrape", std::bind(&GuiMetaDataEd::fetch, this)));
|
||||
|
||||
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "SAVE", "save", [&] { save(); delete this; }));
|
||||
|
|
|
@ -24,8 +24,8 @@ GuiScraperStart::GuiScraperStart(Window* window) : GuiComponent(window),
|
|||
mSystems = std::make_shared< OptionListComponent<SystemData*> >(mWindow, "SCRAPE THESE SYSTEMS", true);
|
||||
for(auto it = SystemData::sSystemVector.begin(); it != SystemData::sSystemVector.end(); it++)
|
||||
{
|
||||
if((*it)->getPlatformId() != PlatformIds::PLATFORM_IGNORE)
|
||||
mSystems->add((*it)->getFullName(), *it, (*it)->getPlatformId() != PlatformIds::PLATFORM_UNKNOWN);
|
||||
if(!(*it)->hasPlatformId(PlatformIds::PLATFORM_IGNORE))
|
||||
mSystems->add((*it)->getFullName(), *it, !(*it)->getPlatformIds().empty());
|
||||
}
|
||||
mMenu.addWithLabel("Systems", mSystems);
|
||||
|
||||
|
@ -44,7 +44,7 @@ void GuiScraperStart::pressedStart()
|
|||
std::vector<SystemData*> sys = mSystems->getSelectedObjects();
|
||||
for(auto it = sys.begin(); it != sys.end(); it++)
|
||||
{
|
||||
if((*it)->getPlatformId() == PlatformIds::PLATFORM_UNKNOWN)
|
||||
if((*it)->getPlatformIds().empty())
|
||||
{
|
||||
mWindow->pushGui(new GuiMsgBox(mWindow,
|
||||
strToUpper("Warning: some of your selected systems do not have a platform set. Results may be even more inaccurate than usual!\nContinue anyway?"),
|
||||
|
|
|
@ -70,20 +70,29 @@ void thegamesdb_generate_scraper_requests(const ScraperSearchParams& params, std
|
|||
|
||||
path += "name=" + HttpReq::urlEncode(cleanName);
|
||||
|
||||
if(params.system->getPlatformId() != PLATFORM_UNKNOWN)
|
||||
if(params.system->getPlatformIds().empty())
|
||||
{
|
||||
auto platformIt = gamesdb_platformid_map.find(params.system->getPlatformId());
|
||||
if(platformIt != gamesdb_platformid_map.end())
|
||||
// no platform specified, we're done
|
||||
requests.push(std::unique_ptr<ScraperRequest>(new ScraperHttpRequest(results, path, &thegamesdb_process_httpreq)));
|
||||
}else{
|
||||
// go through the list, we need to split this into multiple requests
|
||||
// because TheGamesDB API either sucks or I don't know how to use it properly...
|
||||
std::string urlBase = path;
|
||||
auto& platforms = params.system->getPlatformIds();
|
||||
for(auto platformIt = platforms.begin(); platformIt != platforms.end(); platformIt++)
|
||||
{
|
||||
path = urlBase;
|
||||
auto mapIt = gamesdb_platformid_map.find(*platformIt);
|
||||
if(mapIt != gamesdb_platformid_map.end())
|
||||
{
|
||||
path += "&platform=";
|
||||
path += HttpReq::urlEncode(platformIt->second);
|
||||
path += HttpReq::urlEncode(mapIt->second);
|
||||
}else{
|
||||
LOG(LogWarning) << "TheGamesDB scraper warning - no support for platform " << getPlatformName(*platformIt);
|
||||
}
|
||||
else{
|
||||
LOG(LogWarning) << "TheGamesDB scraper warning - no support for platform " << getPlatformName(params.system->getPlatformId());
|
||||
}
|
||||
}
|
||||
|
||||
requests.push(std::unique_ptr<ScraperRequest>(new ScraperHttpRequest(results, path, &thegamesdb_process_httpreq)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void thegamesdb_process_httpreq(const std::unique_ptr<HttpReq>& req, std::vector<ScraperSearchResult>& results)
|
||||
|
|
Loading…
Reference in a new issue