[App] Fix game scanning

This commit is contained in:
Jonathan Goyvaerts 2020-08-23 16:00:40 +02:00 committed by Satori
parent 3459ee11d4
commit fb3a52983a
4 changed files with 32 additions and 25 deletions

View File

@ -11,18 +11,19 @@ namespace app {
using filesystem::FileInfo;
using AsyncCallback = XGameScanner::AsyncCallback;
std::vector<wstring> XGameScanner::FindGamesInPath(const wstring& path) {
std::vector<std::filesystem::path> XGameScanner::FindGamesInPath(
const std::filesystem::path& path) {
// Path is a directory, scan recursively
// TODO: Warn about recursively scanning paths with large hierarchies
std::deque<wstring> queue;
std::deque<std::filesystem::path> queue;
queue.push_front(path);
std::vector<wstring> paths;
std::vector<std::filesystem::path> paths;
int game_count = 0;
while (!queue.empty()) {
wstring current_path = queue.front();
std::filesystem::path current_path = queue.front();
FileInfo current_file;
filesystem::GetInfo(current_path, &current_file);
@ -34,10 +35,10 @@ std::vector<wstring> XGameScanner::FindGamesInPath(const wstring& path) {
for (FileInfo file : directory_files) {
if (CompareCaseInsensitive(file.name, L"$SystemUpdate")) continue;
auto next_path = (current_path, file.name);
auto next_path = current_path / file.name;
// Skip searching directories with an extracted default.xex file
if (std::filesystem::exists(next_path / L"default.xex")) {
queue.push_front(next_path / L"default.xex");
if (std::filesystem::exists(next_path / "default.xex")) {
queue.push_front(next_path / "default.xex");
continue;
}
queue.push_front(next_path);
@ -45,7 +46,7 @@ std::vector<wstring> XGameScanner::FindGamesInPath(const wstring& path) {
} else {
// Exclusively scan iso, xex, or files without an extension.
auto extension = GetFileExtension(current_path);
if (!extension.empty() && extension != L"xex" && extension != L"iso") {
if (!extension.empty() && extension != ".xex" && extension != ".iso") {
continue;
}
@ -63,7 +64,8 @@ std::vector<wstring> XGameScanner::FindGamesInPath(const wstring& path) {
return paths;
}
std::vector<XGameEntry> XGameScanner::ScanPath(const wstring& path) {
std::vector<XGameEntry> XGameScanner::ScanPath(
const std::filesystem::path& path) {
std::vector<XGameEntry> games;
// Check if the given path exists
@ -80,8 +82,9 @@ std::vector<XGameEntry> XGameScanner::ScanPath(const wstring& path) {
games.emplace_back(std::move(game_entry));
}
} else {
const std::vector<wstring>& game_paths = FindGamesInPath(path);
for (const wstring& game_path : game_paths) {
const std::vector<std::filesystem::path>& game_paths =
FindGamesInPath(path);
for (const std::filesystem::path& game_path : game_paths) {
XGameEntry game_entry;
if (XFAILED(ScanGame(game_path, &game_entry))) {
continue;
@ -94,20 +97,23 @@ std::vector<XGameEntry> XGameScanner::ScanPath(const wstring& path) {
return games;
}
int XGameScanner::ScanPathAsync(const wstring& path, const AsyncCallback& cb) {
std::vector<wstring> paths = {path};
int XGameScanner::ScanPathAsync(const std::filesystem::path& path,
const AsyncCallback& cb) {
std::vector<std::filesystem::path> paths = {path};
return ScanPathsAsync(paths, cb);
}
int XGameScanner::ScanPathsAsync(const std::vector<wstring>& paths,
int XGameScanner::ScanPathsAsync(
const std::vector<std::filesystem::path>& paths,
const AsyncCallback& cb) {
// start scanning in a new thread
// TODO: switch to xe::threading::Thread instead of std::thread?
std::thread scan_thread = std::thread(
[](std::vector<wstring> paths, AsyncCallback cb) {
[](std::vector<std::filesystem::path> paths, AsyncCallback cb) {
std::atomic<int> scanned = 0;
auto scan_func = [&](const std::vector<wstring>& paths, size_t start,
auto scan_func = [&](const std::vector<std::filesystem::path>& paths,
size_t start,
size_t size) {
for (auto it = paths.begin() + start;
it != paths.begin() + start + size; ++it) {

View File

@ -18,22 +18,23 @@ class XGameScanner {
using AsyncCallback = std::function<void(const XGameEntry&, int)>;
// Returns a vector of all supported games in provided path.
static std::vector<wstring> FindGamesInPath(const wstring& path);
static std::vector<std::filesystem::path> FindGamesInPath(
const std::filesystem::path& path);
// Scans a provided path and recursively parses the games.
// Returns a vector of parsed game entries.
static std::vector<XGameEntry> ScanPath(const wstring& path);
static std::vector<XGameEntry> ScanPath(const std::filesystem::path& path);
// Scans a provided path and recursively parses the games asynchronously.
// The callback provided is called on each successfully parsed game.
// Returns the number of games found in the path.
static int ScanPathAsync(const wstring& path,
static int ScanPathAsync(const std::filesystem::path& path,
const AsyncCallback& cb = nullptr);
// Scans a list of provided paths and recursively parses the games
// asynchronously. The callback provided is called on each successfully parsed
// game. Returns the number of games found in all paths provided.
static int ScanPathsAsync(const std::vector<wstring>& paths,
static int ScanPathsAsync(const std::vector<std::filesystem::path>& paths,
const AsyncCallback& cb = nullptr);
// Scans a path for a single game, populating the provided output game entry

View File

@ -113,7 +113,7 @@ inline const bool CompareCaseInsensitive(const wstring& left,
inline const std::filesystem::path GetFileExtension(
const std::filesystem::path& path) {
return path.extension();
return xe::utf8::lower_ascii(xe::path_to_utf8(path.extension()));
}
inline const std::filesystem::path GetFileName(const std::filesystem::path& path) {
@ -157,8 +157,8 @@ inline void ReadStfsMagic(const std::filesystem::path& path, char out[4]) {
inline const XGameFormat ResolveFormat(const std::filesystem::path& path) {
const std::wstring& extension = GetFileExtension(path);
if (CompareCaseInsensitive(extension, L"iso")) return XGameFormat::kIso;
if (CompareCaseInsensitive(extension, L"xex")) return XGameFormat::kXex;
if (CompareCaseInsensitive(extension, L".iso")) return XGameFormat::kIso;
if (CompareCaseInsensitive(extension, L".xex")) return XGameFormat::kXex;
// STFS Container
char magic[4];

View File

@ -491,8 +491,8 @@ X_STATUS ReadXexResources(File* file, XexInfo* info) {
auto resource = &resources[i];
uint32_t title_id = info->execution_info.title_id;
uint32_t name =
xe::string_util::from_string<uint32_t>(resource->name, true);
uint32_t name = xe::string_util::from_string<uint32_t>(
std::string(reinterpret_cast<char*>(resource->name), 8), true);
XELOGI("Found resource: %X", name);
// Game resources are listed as the TitleID