mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 08:09:26 +01:00
Don't show "extra" files from DirectoryBlobs in game list
For instance, we don't want to show TGC files that might be inside the /files/ directory of a GameCube DirectoryBlob, and we don't want to show the /sys/main.dol files for extra partitions of Wii DirectoryBlobs.
This commit is contained in:
parent
1ea44f425d
commit
5fe3745750
@ -150,15 +150,20 @@ static std::optional<PartitionType> ParsePartitionDirectoryName(const std::strin
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool PathCharactersEqual(char a, char b)
|
static bool IsDirectorySeparator(char c)
|
||||||
{
|
{
|
||||||
return a == b
|
return c == '/'
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|| (a == '/' && b == '\\') || (a == '\\' && b == '/')
|
|| c == '\\'
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool PathCharactersEqual(char a, char b)
|
||||||
|
{
|
||||||
|
return a == b || (IsDirectorySeparator(a) && IsDirectorySeparator(b));
|
||||||
|
}
|
||||||
|
|
||||||
static bool PathEndsWith(const std::string& path, const std::string& suffix)
|
static bool PathEndsWith(const std::string& path, const std::string& suffix)
|
||||||
{
|
{
|
||||||
if (suffix.size() > path.size())
|
if (suffix.size() > path.size())
|
||||||
@ -178,7 +183,7 @@ static bool PathEndsWith(const std::string& path, const std::string& suffix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool IsValidDirectoryBlob(const std::string& dol_path, std::string* partition_root,
|
static bool IsValidDirectoryBlob(const std::string& dol_path, std::string* partition_root,
|
||||||
std::string* true_root)
|
std::string* true_root = nullptr)
|
||||||
{
|
{
|
||||||
if (!PathEndsWith(dol_path, "/sys/main.dol"))
|
if (!PathEndsWith(dol_path, "/sys/main.dol"))
|
||||||
return false;
|
return false;
|
||||||
@ -194,12 +199,75 @@ static bool IsValidDirectoryBlob(const std::string& dol_path, std::string* parti
|
|||||||
#else
|
#else
|
||||||
constexpr char dir_separator = '/';
|
constexpr char dir_separator = '/';
|
||||||
#endif
|
#endif
|
||||||
const size_t true_root_end = dol_path.find_last_of(dir_separator, partition_root->size() - 2) + 1;
|
if (true_root)
|
||||||
*true_root = dol_path.substr(0, true_root_end);
|
{
|
||||||
|
*true_root =
|
||||||
|
dol_path.substr(0, dol_path.find_last_of(dir_separator, partition_root->size() - 2) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ExistsAndIsValidDirectoryBlob(const std::string& dol_path)
|
||||||
|
{
|
||||||
|
std::string partition_root;
|
||||||
|
return File::Exists(dol_path) && IsValidDirectoryBlob(dol_path, &partition_root);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsInFilesDirectory(const std::string& path)
|
||||||
|
{
|
||||||
|
size_t files_pos = std::string::npos;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
files_pos = path.rfind("files", files_pos);
|
||||||
|
if (files_pos == std::string::npos)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const size_t slash_before_pos = files_pos - 1;
|
||||||
|
const size_t slash_after_pos = files_pos + 5;
|
||||||
|
if ((files_pos == 0 || IsDirectorySeparator(path[slash_before_pos])) &&
|
||||||
|
(slash_after_pos == path.size() || (IsDirectorySeparator(path[slash_after_pos]))) &&
|
||||||
|
ExistsAndIsValidDirectoryBlob(path.substr(0, files_pos) + "sys/main.dol"))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
--files_pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsMainDolForNonGamePartition(const std::string& path)
|
||||||
|
{
|
||||||
|
std::string partition_root, true_root;
|
||||||
|
if (!IsValidDirectoryBlob(path, &partition_root, &true_root))
|
||||||
|
return false; // This is not a /sys/main.dol
|
||||||
|
|
||||||
|
std::string partition_directory_name = partition_root.substr(true_root.size());
|
||||||
|
partition_directory_name.pop_back(); // Remove trailing slash
|
||||||
|
const std::optional<PartitionType> partition_type =
|
||||||
|
ParsePartitionDirectoryName(partition_directory_name);
|
||||||
|
if (!partition_type || *partition_type == PartitionType::Game)
|
||||||
|
return false; // volume_path is the game partition's /sys/main.dol
|
||||||
|
|
||||||
|
const File::FSTEntry true_root_entry = File::ScanDirectoryTree(true_root, false);
|
||||||
|
for (const File::FSTEntry& entry : true_root_entry.children)
|
||||||
|
{
|
||||||
|
if (entry.isDirectory &&
|
||||||
|
ParsePartitionDirectoryName(entry.virtualName) == PartitionType::Game &&
|
||||||
|
ExistsAndIsValidDirectoryBlob(entry.physicalName + "/sys/main.dol"))
|
||||||
|
{
|
||||||
|
return true; // volume_path is the /sys/main.dol for a non-game partition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // volume_path is the game partition's /sys/main.dol
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ShouldHideFromGameList(const std::string& volume_path)
|
||||||
|
{
|
||||||
|
return IsInFilesDirectory(volume_path) || IsMainDolForNonGamePartition(volume_path);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<DirectoryBlobReader> DirectoryBlobReader::Create(const std::string& dol_path)
|
std::unique_ptr<DirectoryBlobReader> DirectoryBlobReader::Create(const std::string& dol_path)
|
||||||
{
|
{
|
||||||
std::string partition_root, true_root;
|
std::string partition_root, true_root;
|
||||||
|
@ -27,6 +27,9 @@ namespace DiscIO
|
|||||||
{
|
{
|
||||||
enum class PartitionType : u32;
|
enum class PartitionType : u32;
|
||||||
|
|
||||||
|
// Returns true if the path is inside a DirectoryBlob and doesn't represent the DirectoryBlob itself
|
||||||
|
bool ShouldHideFromGameList(const std::string& volume_path);
|
||||||
|
|
||||||
class DiscContent
|
class DiscContent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
||||||
|
#include "DiscIO/DirectoryBlob.h"
|
||||||
#include "DolphinQt2/GameList/GameTracker.h"
|
#include "DolphinQt2/GameList/GameTracker.h"
|
||||||
#include "DolphinQt2/Settings.h"
|
#include "DolphinQt2/Settings.h"
|
||||||
|
|
||||||
@ -137,3 +138,13 @@ void GameTracker::UpdateFile(const QString& file)
|
|||||||
emit GameRemoved(file);
|
emit GameRemoved(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameLoader::LoadGame(const QString& path)
|
||||||
|
{
|
||||||
|
if (!DiscIO::ShouldHideFromGameList(path.toStdString()))
|
||||||
|
{
|
||||||
|
GameFile* game = new GameFile(path);
|
||||||
|
if (game->IsValid())
|
||||||
|
emit GameLoaded(QSharedPointer<GameFile>(game));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -54,12 +54,7 @@ class GameLoader final : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void LoadGame(const QString& path)
|
void LoadGame(const QString& path);
|
||||||
{
|
|
||||||
GameFile* game = new GameFile(path);
|
|
||||||
if (game->IsValid())
|
|
||||||
emit GameLoaded(QSharedPointer<GameFile>(game));
|
|
||||||
}
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void GameLoaded(QSharedPointer<GameFile> game);
|
void GameLoaded(QSharedPointer<GameFile> game);
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
#include "Core/Movie.h"
|
#include "Core/Movie.h"
|
||||||
#include "Core/TitleDatabase.h"
|
#include "Core/TitleDatabase.h"
|
||||||
#include "DiscIO/Blob.h"
|
#include "DiscIO/Blob.h"
|
||||||
|
#include "DiscIO/DirectoryBlob.h"
|
||||||
#include "DiscIO/Enums.h"
|
#include "DiscIO/Enums.h"
|
||||||
#include "DiscIO/Volume.h"
|
#include "DiscIO/Volume.h"
|
||||||
#include "DolphinWX/Frame.h"
|
#include "DolphinWX/Frame.h"
|
||||||
@ -761,6 +762,12 @@ void GameListCtrl::RescanList()
|
|||||||
auto search_results = Common::DoFileSearch(SConfig::GetInstance().m_ISOFolder, search_extensions,
|
auto search_results = Common::DoFileSearch(SConfig::GetInstance().m_ISOFolder, search_extensions,
|
||||||
SConfig::GetInstance().m_RecursiveISOFolder);
|
SConfig::GetInstance().m_RecursiveISOFolder);
|
||||||
|
|
||||||
|
// TODO Prevent DoFileSearch from looking inside /files/ directories of DirectoryBlobs at all?
|
||||||
|
// TODO Make DoFileSearch support filter predicates so we don't have remove things afterwards?
|
||||||
|
search_results.erase(
|
||||||
|
std::remove_if(search_results.begin(), search_results.end(), DiscIO::ShouldHideFromGameList),
|
||||||
|
search_results.end());
|
||||||
|
|
||||||
std::vector<std::string> cached_paths;
|
std::vector<std::string> cached_paths;
|
||||||
for (const auto& file : m_cached_files)
|
for (const auto& file : m_cached_files)
|
||||||
cached_paths.emplace_back(file->GetFileName());
|
cached_paths.emplace_back(file->GetFileName());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user