diff --git a/README.md b/README.md
index 38c366234..bd4ed7fae 100644
--- a/README.md
+++ b/README.md
@@ -147,14 +147,17 @@ All systems must be contained within the tag.-->
All subdirectories (and non-recursive links) will be included. -->
~/roms/snes
-
+
.smc .sfc .SMC .SFC
snesemulator %ROM%
-
+
snes
diff --git a/src/FileData.cpp b/src/FileData.cpp
index 38a2acaf3..bfb508084 100644
--- a/src/FileData.cpp
+++ b/src/FileData.cpp
@@ -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);
diff --git a/src/SystemData.cpp b/src/SystemData.cpp
index 72bcb5917..9cbafb2c6 100644
--- a/src/SystemData.cpp
+++ b/src/SystemData.cpp
@@ -18,7 +18,7 @@ std::vector SystemData::sSystemVector;
namespace fs = boost::filesystem;
SystemData::SystemData(const std::string& name, const std::string& fullName, const std::string& startPath, const std::vector& extensions,
- const std::string& command, PlatformIds::PlatformId platformId)
+ const std::string& command, const std::vector& 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 readList(const std::string& str, const char* delims = " \t\r\n,")
+{
+ std::vector 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 extensions;
- std::vector 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 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 platformStrs = readList(platformList);
+ std::vector 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 there appears to be an actual platform ID supplied but it didn't match the list, warn
+ 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)
" \n"
" ~/roms/nes\n"
"\n"
- " \n"
+ " \n"
" .nes .NES\n"
"\n"
" \n"
" retroarch -L ~/cores/libretro-fceumm.so %ROM%\n"
"\n"
- " \n"
+ " \n"
" nes\n"
"\n"
" \n"
diff --git a/src/SystemData.h b/src/SystemData.h
index 6b9887ac8..075f8f1ad 100644
--- a/src/SystemData.h
+++ b/src/SystemData.h
@@ -1,5 +1,4 @@
-#ifndef _SYSTEMDATA_H_
-#define _SYSTEMDATA_H_
+#pragma once
#include
#include
@@ -13,7 +12,7 @@ class SystemData
{
public:
SystemData(const std::string& name, const std::string& fullName, const std::string& startPath, const std::vector& extensions,
- const std::string& command, PlatformIds::PlatformId platformId = PlatformIds::PLATFORM_UNKNOWN);
+ const std::string& command, const std::vector& 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& getExtensions() const { return mSearchExtensions; }
- inline PlatformIds::PlatformId getPlatformId() const { return mPlatformId; }
+
+ inline const std::vector& 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& getTheme() const { return mTheme; }
std::string getGamelistPath(bool forWrite) const;
@@ -67,12 +69,10 @@ private:
std::string mStartPath;
std::vector mSearchExtensions;
std::string mLaunchCommand;
- PlatformIds::PlatformId mPlatformId;
+ std::vector mPlatformIds;
std::shared_ptr mTheme;
void populateFolder(FileData* folder);
FileData* mRootFolder;
};
-
-#endif
diff --git a/src/guis/GuiMetaDataEd.cpp b/src/guis/GuiMetaDataEd.cpp
index 6c6c2a58d..7ce471ea1 100644
--- a/src/guis/GuiMetaDataEd.cpp
+++ b/src/guis/GuiMetaDataEd.cpp
@@ -129,7 +129,7 @@ GuiMetaDataEd::GuiMetaDataEd(Window* window, MetaDataList* md, const std::vector
std::vector< std::shared_ptr > buttons;
- if(scraperParams.system->getPlatformId() != PlatformIds::PLATFORM_IGNORE)
+ if(!scraperParams.system->hasPlatformId(PlatformIds::PLATFORM_IGNORE))
buttons.push_back(std::make_shared(mWindow, "SCRAPE", "scrape", std::bind(&GuiMetaDataEd::fetch, this)));
buttons.push_back(std::make_shared(mWindow, "SAVE", "save", [&] { save(); delete this; }));
diff --git a/src/guis/GuiScraperStart.cpp b/src/guis/GuiScraperStart.cpp
index 188b56785..915a5c707 100644
--- a/src/guis/GuiScraperStart.cpp
+++ b/src/guis/GuiScraperStart.cpp
@@ -24,8 +24,8 @@ GuiScraperStart::GuiScraperStart(Window* window) : GuiComponent(window),
mSystems = std::make_shared< OptionListComponent >(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 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?"),
diff --git a/src/scrapers/GamesDBScraper.cpp b/src/scrapers/GamesDBScraper.cpp
index fa35b1eca..c569595d0 100644
--- a/src/scrapers/GamesDBScraper.cpp
+++ b/src/scrapers/GamesDBScraper.cpp
@@ -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(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 += "&platform=";
- path += HttpReq::urlEncode(platformIt->second);
- }
- else{
- LOG(LogWarning) << "TheGamesDB scraper warning - no support for platform " << getPlatformName(params.system->getPlatformId());
+ path = urlBase;
+ auto mapIt = gamesdb_platformid_map.find(*platformIt);
+ if(mapIt != gamesdb_platformid_map.end())
+ {
+ path += "&platform=";
+ path += HttpReq::urlEncode(mapIt->second);
+ }else{
+ LOG(LogWarning) << "TheGamesDB scraper warning - no support for platform " << getPlatformName(*platformIt);
+ }
+ requests.push(std::unique_ptr(new ScraperHttpRequest(results, path, &thegamesdb_process_httpreq)));
}
}
-
- requests.push(std::unique_ptr(new ScraperHttpRequest(results, path, &thegamesdb_process_httpreq)));
}
void thegamesdb_process_httpreq(const std::unique_ptr& req, std::vector& results)