[App] Fix game scanning
This commit is contained in:
parent
3459ee11d4
commit
fb3a52983a
|
@ -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, ¤t_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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue