Smarter game selection when a zip file contains multiple games (prefer child when parent is also present in zip)

This commit is contained in:
Bart Trzynadlowski 2017-03-31 05:23:04 +00:00
parent e40d268214
commit b0957e6459
2 changed files with 48 additions and 14 deletions

View file

@ -276,6 +276,15 @@ bool GameLoader::ParseXML(const Util::Config::Node &xml)
return false; return false;
} }
bool GameLoader::LoadDefinitionXML(const std::string &filename)
{
m_xml_filename = filename;
Util::Config::Node xml("xml");
if (Util::Config::FromXMLFile(&xml, filename))
return true;
return ParseXML(xml);
}
std::set<std::string> GameLoader::IdentifyCompleteGamesInZipArchive(const ZipArchive &zip) const std::set<std::string> GameLoader::IdentifyCompleteGamesInZipArchive(const ZipArchive &zip) const
{ {
std::set<std::string> complete_games; std::set<std::string> complete_games;
@ -490,15 +499,6 @@ bool GameLoader::LoadROMs(ROMSet *rom_set, const std::string &game_name, const Z
return error; return error;
} }
bool GameLoader::LoadDefinitionXML(const std::string &filename)
{
m_xml_filename = filename;
Util::Config::Node xml("xml");
if (Util::Config::FromXMLFile(&xml, filename))
return true;
return ParseXML(xml);
}
std::string StripFilename(const std::string &filepath) std::string StripFilename(const std::string &filepath)
{ {
// Search for last '/' or '\', if any // Search for last '/' or '\', if any
@ -520,6 +520,36 @@ std::string StripFilename(const std::string &filepath)
return std::string(filepath, 0, last_slash + 1); return std::string(filepath, 0, last_slash + 1);
} }
// A heuristic is used that favors child sets with present parent
std::string GameLoader::ChooseGame(const std::set<std::string> &games_found) const
{
// Identify children sets and parent sets
std::set<std::string> parents;
std::set<std::string> children;
for (auto &game_name: games_found)
{
auto it = m_game_info_by_game.find(game_name);
const Game &game = it->second;
if (game.parent.empty())
parents.insert(game_name);
else
children.insert(game_name);
}
// Find the first child set whose parent is also present
for (auto &child: children)
{
auto it = m_game_info_by_game.find(child);
const Game &game = it->second;
const std::string &parent = game.parent;
if (parents.count(parent) > 0)
return child;
}
// Otherwise, just grab whatever is first
return *games_found.begin();
}
bool GameLoader::Load(Game *game, ROMSet *rom_set, const std::string &zipfilename) bool GameLoader::Load(Game *game, ROMSet *rom_set, const std::string &zipfilename)
{ {
*game = Game(); *game = Game();
@ -534,11 +564,14 @@ bool GameLoader::Load(Game *game, ROMSet *rom_set, const std::string &zipfilenam
ErrorLog("No complete Model 3 games found in '%s'.", zipfilename.c_str()); ErrorLog("No complete Model 3 games found in '%s'.", zipfilename.c_str());
return true; return true;
} }
else if (games_found.size() > 1)
ErrorLog("Multiple games found in '%s' (%s). Loading '%s'.", zipfilename.c_str(), std::string(Util::Format(", ").Join(games_found)).c_str(), games_found.begin()->c_str());
// Pick the first game in the first zip file // Pick the game to load (if there are multiple games present)
*game = m_game_info_by_game[*games_found.begin()]; std::string chosen_game = ChooseGame(games_found);
if (games_found.size() > 1)
ErrorLog("Multiple games found in '%s' (%s). Loading '%s'.", zipfilename.c_str(), std::string(Util::Format(", ").Join(games_found)).c_str(), chosen_game.c_str());
// Return game information to caller
*game = m_game_info_by_game[chosen_game];
// If there is a parent ROM set, determine where it is 1) contained in the // If there is a parent ROM set, determine where it is 1) contained in the
// same zip file or 2) try loading it from the same directory // same zip file or 2) try loading it from the same directory

View file

@ -68,11 +68,12 @@ private:
const ZippedFile *LookupFile(const File::ptr_t &file, const ZipArchive &zip) const; const ZippedFile *LookupFile(const File::ptr_t &file, const ZipArchive &zip) const;
static bool MissingAttrib(const GameLoader &loader, const Util::Config::Node &node, const std::string &attribute); static bool MissingAttrib(const GameLoader &loader, const Util::Config::Node &node, const std::string &attribute);
bool ParseXML(const Util::Config::Node &xml); bool ParseXML(const Util::Config::Node &xml);
bool LoadDefinitionXML(const std::string &filename);
std::set<std::string> IdentifyCompleteGamesInZipArchive(const ZipArchive &zip) const; std::set<std::string> IdentifyCompleteGamesInZipArchive(const ZipArchive &zip) const;
bool ComputeRegionSize(uint32_t *region_size, const Region::ptr_t &region, const ZipArchive &zip) const; bool ComputeRegionSize(uint32_t *region_size, const Region::ptr_t &region, const ZipArchive &zip) const;
bool LoadRegion(ROM *buffer, const GameLoader::Region::ptr_t &region, const ZipArchive &zip); bool LoadRegion(ROM *buffer, const GameLoader::Region::ptr_t &region, const ZipArchive &zip);
bool LoadROMs(ROMSet *rom_set, const std::string &game_name, const ZipArchive *zip, const std::string &parent_name, const ZipArchive *parent_zip); bool LoadROMs(ROMSet *rom_set, const std::string &game_name, const ZipArchive *zip, const std::string &parent_name, const ZipArchive *parent_zip);
bool LoadDefinitionXML(const std::string &filename); std::string ChooseGame(const std::set<std::string> &games_found) const;
public: public:
GameLoader(const std::string &xml_file); GameLoader(const std::string &xml_file);