diff --git a/Core/FileLoaders/DiskCachingFileLoader.cpp b/Core/FileLoaders/DiskCachingFileLoader.cpp index 27379a9bc9..7935e0f021 100644 --- a/Core/FileLoaders/DiskCachingFileLoader.cpp +++ b/Core/FileLoaders/DiskCachingFileLoader.cpp @@ -54,6 +54,11 @@ DiskCachingFileLoader::~DiskCachingFileLoader() { } bool DiskCachingFileLoader::Exists() { + if (cache_->HasData()) { + // It may require a slow operation to check - if we have data, let's say yes. + // This helps initial load, since we check each recent file for existence. + return true; + } return backend_->Exists(); } @@ -718,6 +723,19 @@ void DiskCachingFileLoaderCache::CloseFileHandle() { fd_ = 0; } +bool DiskCachingFileLoaderCache::HasData() const { + if (!f_) { + return false; + } + + for (size_t i = 0; i < blockIndexLookup_.size(); ++i) { + if (blockIndexLookup_[i] != INVALID_INDEX) { + return true; + } + } + return false; +} + u64 DiskCachingFileLoaderCache::FreeDiskSpace() { std::string dir = cacheDir_; if (dir.empty()) { diff --git a/Core/FileLoaders/DiskCachingFileLoader.h b/Core/FileLoaders/DiskCachingFileLoader.h index ac944ce08d..511507d240 100644 --- a/Core/FileLoaders/DiskCachingFileLoader.h +++ b/Core/FileLoaders/DiskCachingFileLoader.h @@ -89,6 +89,8 @@ public: // Guaranteed to read at least one block into the cache. size_t SaveIntoCache(FileLoader *backend, s64 pos, size_t bytes, void *data); + bool HasData() const; + private: void InitCache(const std::string &path); void ShutdownCache(); diff --git a/Core/Loaders.cpp b/Core/Loaders.cpp index db28d4d315..4632c58714 100644 --- a/Core/Loaders.cpp +++ b/Core/Loaders.cpp @@ -194,16 +194,41 @@ IdentifiedFileType Identify_File(FileLoader *fileLoader) { FileLoader *ResolveFileLoaderTarget(FileLoader *fileLoader) { IdentifiedFileType type = Identify_File(fileLoader); - if (type == FILETYPE_PSP_PBP_DIRECTORY && !endsWith(fileLoader->Path(), "/EBOOT.PBP")) { - std::string ebootFilename = fileLoader->Path() + "/EBOOT.PBP"; - - // Switch fileLoader to the actual EBOOT. - delete fileLoader; - fileLoader = ConstructFileLoader(ebootFilename); + if (type == FILETYPE_PSP_PBP_DIRECTORY) { + const std::string ebootFilename = ResolvePBPFile(fileLoader->Path()); + if (ebootFilename != fileLoader->Path()) { + // Switch fileLoader to the actual EBOOT. + delete fileLoader; + fileLoader = ConstructFileLoader(ebootFilename); + } } return fileLoader; } +std::string ResolvePBPDirectory(const std::string &filename) { + bool hasPBP = endsWith(filename, "/EBOOT.PBP"); +#ifdef _WIN32 + hasPBP = hasPBP || endsWith(filename, "\\EBOOT.PBP"); +#endif + + if (hasPBP) { + return filename.substr(0, filename.length() - strlen("/EBOOT.PBP")); + } + return filename; +} + +std::string ResolvePBPFile(const std::string &filename) { + bool hasPBP = endsWith(filename, "/EBOOT.PBP"); +#ifdef _WIN32 + hasPBP = hasPBP || endsWith(filename, "\\EBOOT.PBP"); +#endif + + if (!hasPBP) { + return filename + "/EBOOT.PBP"; + } + return filename; +} + bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) { FileLoader *&fileLoader = *fileLoaderPtr; // Note that this can modify filename! @@ -227,9 +252,7 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) { std::string path = fileLoader->Path(); size_t pos = path.find("/PSP/GAME/"); if (pos != std::string::npos) { - if (path.rfind("/EBOOT.PBP") != std::string::npos) { - path = path.substr(0, path.length() - strlen("/EBOOT.PBP")); - } + path = ResolvePBPDirectory(path); pspFileSystem.SetStartingDirectory("ms0:" + path.substr(pos)); } return Load_PSP_ELF_PBP(fileLoader, error_string); diff --git a/Core/Loaders.h b/Core/Loaders.h index f7d297923f..4fbe126a5a 100644 --- a/Core/Loaders.h +++ b/Core/Loaders.h @@ -82,8 +82,9 @@ FileLoader *ConstructFileLoader(const std::string &filename); // Resolve to the target binary, ISO, or other file (e.g. from a directory.) FileLoader *ResolveFileLoaderTarget(FileLoader *fileLoader); -// This can modify the string, for example for stripping off the "/EBOOT.PBP" -// for a FILETYPE_PSP_PBP_DIRECTORY. +std::string ResolvePBPDirectory(const std::string &filename); +std::string ResolvePBPFile(const std::string &filename); + IdentifiedFileType Identify_File(FileLoader *fileLoader); // Can modify the string filename, as it calls IdentifyFile above. diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index c82fe9fdcd..f47d9e372e 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -72,8 +72,8 @@ bool GameInfo::Delete() { case FILETYPE_PSP_SAVEDATA_DIRECTORY: { // TODO: This could be handled by Core/Util/GameManager too somehow. - const char *directoryToRemove = filePath_.c_str(); - INFO_LOG(HLE, "Deleting %s", directoryToRemove); + std::string directoryToRemove = ResolvePBPDirectory(filePath_); + INFO_LOG(HLE, "Deleting %s", directoryToRemove.c_str()); if (!File::DeleteDirRecursively(directoryToRemove)) { ERROR_LOG(HLE, "Failed to delete file"); return false; @@ -109,7 +109,7 @@ bool GameInfo::Delete() { } } -static int64_t GetDirectoryRecursiveSize(std::string path) { +static int64_t GetDirectoryRecursiveSize(const std::string &path) { std::vector fileInfo; getFilesInDir(path.c_str(), &fileInfo); int64_t sizeSum = 0; @@ -129,9 +129,8 @@ u64 GameInfo::GetGameSizeInBytes() { switch (fileType) { case FILETYPE_PSP_PBP_DIRECTORY: case FILETYPE_PSP_SAVEDATA_DIRECTORY: - { - return GetDirectoryRecursiveSize(filePath_); - } + return GetDirectoryRecursiveSize(ResolvePBPDirectory(filePath_)); + default: return GetFileLoader()->FileSize(); } @@ -358,11 +357,14 @@ public: : gamePath_(gamePath), info_(info) { } + ~GameInfoWorkItem() override { + info_->DisposeFileLoader(); + } + virtual void run() { if (!info_->LoadFromPath(gamePath_)) return; - std::string filename = gamePath_; { lock_guard lock(info_->lock); info_->working = true; @@ -376,8 +378,11 @@ public: FileLoader *pbpLoader = info_->GetFileLoader(); std::unique_ptr altLoader; if (info_->fileType == FILETYPE_PSP_PBP_DIRECTORY) { - pbpLoader = ConstructFileLoader(pbpLoader->Path() + "/EBOOT.PBP"); - altLoader.reset(pbpLoader); + std::string ebootPath = ResolvePBPFile(gamePath_); + if (ebootPath != gamePath_) { + pbpLoader = ConstructFileLoader(ebootPath); + altLoader.reset(pbpLoader); + } } PBPReader pbp(pbpLoader); @@ -593,8 +598,6 @@ handleELF: info_->installDataSize = info_->GetInstallDataSizeInBytes(); } - info_->DisposeFileLoader(); - lock_guard lock(info_->lock); info_->pending = false; info_->working = false; diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index 317bf72fbc..b8e17d378a 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -829,11 +829,11 @@ namespace MainWindow else { TCHAR filename[512]; - DragQueryFile(hdrop,0,filename,512); - TCHAR *type = filename+_tcslen(filename)-3; - - NativeMessageReceived("boot", ConvertWStringToUTF8(filename).c_str()); - Core_EnableStepping(false); + if (DragQueryFile(hdrop, 0, filename, 512) != 0) { + const std::string utf8_filename = ReplaceAll(ConvertWStringToUTF8(filename), "\\", "/"); + NativeMessageReceived("boot", utf8_filename.c_str()); + Core_EnableStepping(false); + } } } break;