diff --git a/Common/Data/Format/IniFile.cpp b/Common/Data/Format/IniFile.cpp index 9b6ea6ed553e..2f7c3347b517 100644 --- a/Common/Data/Format/IniFile.cpp +++ b/Common/Data/Format/IniFile.cpp @@ -162,7 +162,7 @@ static std::string EscapeHash(std::string_view value) { return result; } -void ParsedIniLine::ParseFrom(std::string_view line) { +ParsedIniLine::ParsedIniLine(std::string_view line) { line = StripSpaces(line); if (line.empty()) { key.clear(); @@ -534,7 +534,7 @@ bool IniFile::Load(std::istream &in) { while (!(in.eof() || in.fail())) { in.getline(templine, MAX_BYTES); - std::string line = templine; + std::string_view line = templine; // Remove UTF-8 byte order marks. if (line.substr(0, 3) == "\xEF\xBB\xBF") { @@ -543,8 +543,8 @@ bool IniFile::Load(std::istream &in) { #ifndef _WIN32 // Check for CRLF eol and convert it to LF - if (!line.empty() && line.at(line.size()-1) == '\r') { - line.erase(line.size()-1); + if (!line.empty() && line.at(line.size() - 1) == '\r') { + line = line.substr(line.size() - 1); } #endif @@ -556,7 +556,7 @@ bool IniFile::Load(std::istream &in) { if (sectionNameEnd != std::string::npos) { // New section! - std::string sub = line.substr(1, sectionNameEnd - 1); + std::string_view sub = line.substr(1, sectionNameEnd - 1); sections.push_back(std::make_unique
(sub)); if (sectionNameEnd + 1 < line.size()) { @@ -566,9 +566,7 @@ bool IniFile::Load(std::istream &in) { if (sections.empty()) { sections.push_back(std::make_unique
("")); } - ParsedIniLine parsedLine; - parsedLine.ParseFrom(line); - sections.back()->lines_.push_back(parsedLine); + sections.back()->lines_.emplace_back(line); } } } diff --git a/Common/Data/Format/IniFile.h b/Common/Data/Format/IniFile.h index 8e944f8d1e17..4ca92983a5a8 100644 --- a/Common/Data/Format/IniFile.h +++ b/Common/Data/Format/IniFile.h @@ -18,7 +18,8 @@ class VFSInterface; class ParsedIniLine { public: - ParsedIniLine() {} + explicit ParsedIniLine(std::string_view line); + ParsedIniLine(std::string_view key, std::string_view value) { this->key = key; this->value = value; @@ -32,8 +33,6 @@ class ParsedIniLine { return ParsedIniLine(std::string_view(), std::string_view(), comment); } - // Comments only come from "ParseFrom". - void ParseFrom(std::string_view line); void Reconstruct(std::string *output) const; // Having these as views allows a more efficient internal representation, like one joint string. diff --git a/Common/Data/Text/I18n.cpp b/Common/Data/Text/I18n.cpp index 43f18e62e864..5d08224fdf4f 100644 --- a/Common/Data/Text/I18n.cpp +++ b/Common/Data/Text/I18n.cpp @@ -131,9 +131,7 @@ Path I18NRepo::GetIniPath(const std::string &languageID) const { bool I18NRepo::IniExists(const std::string &languageID) const { File::FileInfo info; - if (!g_VFS.GetFileInfo(GetIniPath(languageID).ToString().c_str(), &info)) - return false; - if (!info.exists) + if (!g_VFS.Exists(GetIniPath(languageID).ToString().c_str())) return false; return true; } diff --git a/Common/File/AndroidStorage.cpp b/Common/File/AndroidStorage.cpp index e192d8286ffe..477ae13ac3cc 100644 --- a/Common/File/AndroidStorage.cpp +++ b/Common/File/AndroidStorage.cpp @@ -34,7 +34,7 @@ void Android_StorageSetNativeActivity(jobject nativeActivity) { void Android_RegisterStorageCallbacks(JNIEnv * env, jobject obj) { openContentUri = env->GetMethodID(env->GetObjectClass(obj), "openContentUri", "(Ljava/lang/String;Ljava/lang/String;)I"); _dbg_assert_(openContentUri); - listContentUriDir = env->GetMethodID(env->GetObjectClass(obj), "listContentUriDir", "(Ljava/lang/String;Ljava/lang/String;)[Ljava/lang/String;"); + listContentUriDir = env->GetMethodID(env->GetObjectClass(obj), "listContentUriDir", "(Ljava/lang/String;)[Ljava/lang/String;"); _dbg_assert_(listContentUriDir); contentUriCreateDirectory = env->GetMethodID(env->GetObjectClass(obj), "contentUriCreateDirectory", "(Ljava/lang/String;Ljava/lang/String;)I"); _dbg_assert_(contentUriCreateDirectory); @@ -233,8 +233,7 @@ std::vector Android_ListContentUri(const std::string &uri, const double start = time_now_d(); jstring param = env->NewStringUTF(uri.c_str()); - jstring filter = prefix.empty() ? nullptr : env->NewStringUTF(prefix.c_str()); - jobject retval = env->CallObjectMethod(g_nativeActivity, listContentUriDir, param, filter); + jobject retval = env->CallObjectMethod(g_nativeActivity, listContentUriDir, param); jobjectArray fileList = (jobjectArray)retval; std::vector items; @@ -251,6 +250,7 @@ std::vector Android_ListContentUri(const std::string &uri, const } else if (ParseFileInfo(line, &info)) { // We can just reconstruct the URI. info.fullName = Path(uri) / info.name; + INFO_LOG(Log::FileSystem, "%s", info.name.c_str()); items.push_back(info); } } diff --git a/Common/File/DirListing.cpp b/Common/File/DirListing.cpp index 0f9d10aa859b..0eb26ae32097 100644 --- a/Common/File/DirListing.cpp +++ b/Common/File/DirListing.cpp @@ -63,7 +63,7 @@ static uint64_t FiletimeToStatTime(FILETIME ft) { bool GetFileInfo(const Path &path, FileInfo * fileInfo) { if (LOG_IO) { - INFO_LOG(Log::System, "GetFileInfo %s", path.c_str()); + INFO_LOG(Log::System, "GetFileInfo %s", path.ToVisualString().c_str()); } if (SIMULATE_SLOW_IO) { sleep_ms(300, "slow-io-sim"); @@ -178,12 +178,14 @@ std::vector ApplyFilter(std::vector files, const } auto pred = [&](const File::FileInfo &info) { + // WARNING: Keep in mind that if we return true here, the files is REMOVED from the list. + // It's not retain_if. + if (!startsWith(info.name, prefix)) { + return true; + } if (info.isDirectory || !extensionFilter) return false; std::string ext = info.fullName.GetFileExtension(); - if (!startsWith(info.name, prefix)) { - return false; - } return filters.find(ext) == filters.end(); }; files.erase(std::remove_if(files.begin(), files.end(), pred), files.end()); @@ -192,7 +194,7 @@ std::vector ApplyFilter(std::vector files, const bool GetFilesInDir(const Path &directory, std::vector *files, const char *filter, int flags, std::string_view prefix) { if (LOG_IO) { - INFO_LOG(Log::System, "GetFilesInDir %s (ext %s, prefix %.*s)", directory.c_str(), filter, (int)prefix.size(), prefix.data()); + INFO_LOG(Log::System, "GetFilesInDir '%s' (ext %s, prefix %.*s)", directory.ToVisualString().c_str(), filter, (int)prefix.size(), prefix.data()); } if (SIMULATE_SLOW_IO) { sleep_ms(300, "slow-io-sim"); @@ -202,8 +204,10 @@ bool GetFilesInDir(const Path &directory, std::vector *files, const ch bool exists = false; // TODO: Move prefix filtering over to the Java side for more speed. std::vector fileList = Android_ListContentUri(directory.ToString(), std::string(prefix), &exists); - *files = ApplyFilter(fileList, filter, ""); + int beforeFilter = (int)fileList.size(); + *files = ApplyFilter(fileList, filter, prefix); std::sort(files->begin(), files->end()); + DEBUG_LOG(Log::System, "GetFilesInDir: Found %d entries (%d before filter)", (int)files->size(), beforeFilter); return exists; } @@ -276,12 +280,9 @@ bool GetFilesInDir(const Path &directory, std::vector *files, const ch continue; } - /* - if (SIMULATE_SLOW_IO) { - INFO_LOG(Log::System, "GetFilesInDir item %s", virtualName.c_str()); - sleep_ms(50, "slow-io-sim"); + if (LOG_IO) { + // INFO_LOG(Log::System, "GetFilesInDir item %s", virtualName.c_str()); } - */ FileInfo info; info.name = virtualName; diff --git a/Common/File/FileUtil.cpp b/Common/File/FileUtil.cpp index 74e490dc1a82..81ce5dcde519 100644 --- a/Common/File/FileUtil.cpp +++ b/Common/File/FileUtil.cpp @@ -420,7 +420,7 @@ bool ExistsInDir(const Path &path, const std::string &filename) { bool Exists(const Path &path) { if (LOG_IO) { - INFO_LOG(Log::System, "Exists %s", path.c_str()); + INFO_LOG(Log::System, "Exists %s", path.ToVisualString().c_str()); } if (SIMULATE_SLOW_IO) { sleep_ms(200, "slow-io-sim"); @@ -631,7 +631,7 @@ bool CreateDir(const Path &path) { // Creates the full path of fullPath returns true on success bool CreateFullPath(const Path &path) { if (File::Exists(path)) { - DEBUG_LOG(Log::Common, "CreateFullPath: path exists %s", path.c_str()); + DEBUG_LOG(Log::Common, "CreateFullPath: path exists %s", path.ToVisualString().c_str()); return true; } @@ -640,7 +640,7 @@ bool CreateFullPath(const Path &path) { case PathType::CONTENT_URI: break; // OK default: - ERROR_LOG(Log::Common, "CreateFullPath(%s): Not yet supported", path.c_str()); + ERROR_LOG(Log::Common, "CreateFullPath(%s): Not yet supported", path.ToVisualString().c_str()); return false; } @@ -665,9 +665,7 @@ bool CreateFullPath(const Path &path) { Path curPath = root; for (auto part : parts) { curPath /= part; - if (!File::Exists(curPath)) { - File::CreateDir(curPath); - } + File::CreateDir(curPath); } return true; diff --git a/Common/File/VFS/DirectoryReader.cpp b/Common/File/VFS/DirectoryReader.cpp index 981dff905bc9..2dd9a550aaff 100644 --- a/Common/File/VFS/DirectoryReader.cpp +++ b/Common/File/VFS/DirectoryReader.cpp @@ -32,6 +32,11 @@ bool DirectoryReader::GetFileInfo(const char *path, File::FileInfo *info) { return File::GetFileInfo(new_path, info); } +bool DirectoryReader::Exists(const char *path) { + Path new_path = Path(path).StartsWith(path_) ? Path(path) : path_ / path; + return File::Exists(new_path); +} + class DirectoryReaderFileReference : public VFSFileReference { public: Path path; diff --git a/Common/File/VFS/DirectoryReader.h b/Common/File/VFS/DirectoryReader.h index f742c6b3da59..1f438d028bfa 100644 --- a/Common/File/VFS/DirectoryReader.h +++ b/Common/File/VFS/DirectoryReader.h @@ -21,6 +21,7 @@ class DirectoryReader : public VFSBackend { bool GetFileListing(const char *path, std::vector *listing, const char *filter) override; bool GetFileInfo(const char *path, File::FileInfo *info) override; + bool Exists(const char *path) override; std::string toString() const override { return path_.ToString(); } diff --git a/Common/File/VFS/VFS.cpp b/Common/File/VFS/VFS.cpp index 3334b7cae484..60d4e08c4717 100644 --- a/Common/File/VFS/VFS.cpp +++ b/Common/File/VFS/VFS.cpp @@ -118,3 +118,29 @@ bool VFS::GetFileInfo(const char *path, File::FileInfo *info) { } // Otherwise, the file was just missing. No need to log. return false; } + +bool VFS::Exists(const char *path) { + if (IsLocalAbsolutePath(path)) { + // Local path, not VFS. + // INFO_LOG(Log::IO, "Not a VFS path: %s . Getting local file info.", path); + return File::Exists(Path(std::string(path))); + } + + bool fileSystemFound = false; + int fn_len = (int)strlen(path); + for (const auto &entry : entries_) { + int prefix_len = (int)strlen(entry.prefix); + if (prefix_len >= fn_len) continue; + if (0 == memcmp(path, entry.prefix, prefix_len)) { + fileSystemFound = true; + if (entry.reader->Exists(path + prefix_len)) + return true; + else + continue; + } + } + if (!fileSystemFound) { + ERROR_LOG(Log::IO, "Missing filesystem for '%s'", path); + } // Otherwise, the file was just missing. No need to log. + return false; +} diff --git a/Common/File/VFS/VFS.h b/Common/File/VFS/VFS.h index 87ef02dffb1f..24a738d3e682 100644 --- a/Common/File/VFS/VFS.h +++ b/Common/File/VFS/VFS.h @@ -56,6 +56,10 @@ class VFSBackend : public VFSInterface { // Filter support is optional but nice to have virtual bool GetFileInfo(const char *path, File::FileInfo *info) = 0; + virtual bool Exists(const char *path) { + File::FileInfo info{}; + return GetFileInfo(path, &info) && info.exists; + } virtual std::string toString() const = 0; }; @@ -70,14 +74,10 @@ class VFS : public VFSInterface { // Always allocates an extra zero byte at the end, so that it // can be used for text like shader sources. uint8_t *ReadFile(const char *filename, size_t *size) override; - bool GetFileInfo(const char *filename, File::FileInfo *fileInfo); bool GetFileListing(const char *path, std::vector *listing, const char *filter = nullptr) override; - // Shortcut for cleaner code - bool Exists(const char *path) { - File::FileInfo info{}; - return GetFileInfo(path, &info); - } + bool GetFileInfo(const char *filename, File::FileInfo *fileInfo); + bool Exists(const char *path); private: struct VFSEntry { diff --git a/Common/File/VFS/ZipFileReader.cpp b/Common/File/VFS/ZipFileReader.cpp index b51b7f479386..4bf3c7f87696 100644 --- a/Common/File/VFS/ZipFileReader.cpp +++ b/Common/File/VFS/ZipFileReader.cpp @@ -44,7 +44,7 @@ ZipFileReader *ZipFileReader::Create(const Path &zipFile, const char *inZipPath, if (!path.empty() && path.back() != '/') { path.push_back('/'); } - return new ZipFileReader(zip_file, path); + return new ZipFileReader(zip_file, zipFile, path); } ZipFileReader::~ZipFileReader() { diff --git a/Common/File/VFS/ZipFileReader.h b/Common/File/VFS/ZipFileReader.h index 30c61ccc76bf..4bd510b46396 100644 --- a/Common/File/VFS/ZipFileReader.h +++ b/Common/File/VFS/ZipFileReader.h @@ -36,15 +36,21 @@ class ZipFileReader : public VFSBackend { bool GetFileListing(const char *path, std::vector *listing, const char *filter) override; bool GetFileInfo(const char *path, File::FileInfo *info) override; std::string toString() const override { - return inZipPath_; + std::string retval = zipPath_.ToVisualString(); + if (!inZipPath_.empty()) { + retval += ": "; + retval += inZipPath_; + } + return retval; } private: - ZipFileReader(zip *zip_file, const std::string &inZipPath) : zip_file_(zip_file), inZipPath_(inZipPath) {} + ZipFileReader(zip *zip_file, const Path &zipPath, const std::string &inZipPath) : zip_file_(zip_file), zipPath_(zipPath), inZipPath_(inZipPath) {} // Path has to be either an empty string, or a string ending with a /. bool GetZipListings(const std::string &path, std::set &files, std::set &directories); zip *zip_file_ = nullptr; std::mutex lock_; std::string inZipPath_; + Path zipPath_; }; diff --git a/Common/Log/LogManager.cpp b/Common/Log/LogManager.cpp index 2ff671df420a..ddd8cee68f81 100644 --- a/Common/Log/LogManager.cpp +++ b/Common/Log/LogManager.cpp @@ -258,7 +258,7 @@ void LogManager::LogLine(LogLevel level, Log type, const char *file, int line, c const char *threadName; #if PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(MAC) const char *hostThreadName = GetCurrentThreadName(); - if (strcmp(hostThreadName, "EmuThread") != 0 || !hleCurrentThreadName) { + if (hostThreadName && strcmp(hostThreadName, "EmuThread") != 0 || !hleCurrentThreadName) { // Use the host thread name. threadName = hostThreadName; } else { diff --git a/Core/Config.cpp b/Core/Config.cpp index a0d7e7107ba7..7f9c117eff90 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -1090,10 +1090,11 @@ void Config::Reload() { void Config::UpdateIniLocation(const char *iniFileName, const char *controllerIniFilename) { const bool useIniFilename = iniFileName != nullptr && strlen(iniFileName) > 0; const char *ppssppIniFilename = IsVREnabled() ? "ppssppvr.ini" : "ppsspp.ini"; - iniFilename_ = FindConfigFile(useIniFilename ? iniFileName : ppssppIniFilename); + bool exists; + iniFilename_ = FindConfigFile(useIniFilename ? iniFileName : ppssppIniFilename, &exists); const bool useControllerIniFilename = controllerIniFilename != nullptr && strlen(controllerIniFilename) > 0; const char *controlsIniFilename = IsVREnabled() ? "controlsvr.ini" : "controls.ini"; - controllerIniFilename_ = FindConfigFile(useControllerIniFilename ? controllerIniFilename : controlsIniFilename); + controllerIniFilename_ = FindConfigFile(useControllerIniFilename ? controllerIniFilename : controlsIniFilename, &exists); } bool Config::LoadAppendedConfig() { @@ -1660,22 +1661,27 @@ void Config::SetSearchPath(const Path &searchPath) { searchPath_ = searchPath; } -const Path Config::FindConfigFile(const std::string &baseFilename) { +const Path Config::FindConfigFile(const std::string &baseFilename, bool *exists) { // Don't search for an absolute path. if (baseFilename.size() > 1 && baseFilename[0] == '/') { - return Path(baseFilename); + Path path(baseFilename); + *exists = File::Exists(path); + return path; } #ifdef _WIN32 if (baseFilename.size() > 3 && baseFilename[1] == ':' && (baseFilename[2] == '/' || baseFilename[2] == '\\')) { - return Path(baseFilename); + Path path(baseFilename); + *exists = File::Exists(path); + return path; } #endif Path filename = searchPath_ / baseFilename; if (File::Exists(filename)) { + *exists = true; return filename; } - + *exists = false; // Make sure at least the directory it's supposed to be in exists. Path parent = filename.NavigateUp(); @@ -1711,8 +1717,9 @@ void Config::RestoreDefaults(RestoreSettingsBits whatToRestore) { } bool Config::hasGameConfig(const std::string &pGameId) { - Path fullIniFilePath = getGameConfigFile(pGameId); - return File::Exists(fullIniFilePath); + bool exists = false; + Path fullIniFilePath = getGameConfigFile(pGameId, &exists); + return exists; } void Config::changeGameSpecific(const std::string &pGameId, const std::string &title) { @@ -1724,9 +1731,11 @@ void Config::changeGameSpecific(const std::string &pGameId, const std::string &t } bool Config::createGameConfig(const std::string &pGameId) { - Path fullIniFilePath = getGameConfigFile(pGameId); + bool exists; + Path fullIniFilePath = getGameConfigFile(pGameId, &exists); - if (hasGameConfig(pGameId)) { + if (exists) { + INFO_LOG(Log::System, "Game config already exists"); return false; } @@ -1735,16 +1744,19 @@ bool Config::createGameConfig(const std::string &pGameId) { } bool Config::deleteGameConfig(const std::string& pGameId) { - Path fullIniFilePath = Path(getGameConfigFile(pGameId)); + bool exists; + Path fullIniFilePath = Path(getGameConfigFile(pGameId, &exists)); - File::Delete(fullIniFilePath); + if (exists) { + File::Delete(fullIniFilePath); + } return true; } -Path Config::getGameConfigFile(const std::string &pGameId) { +Path Config::getGameConfigFile(const std::string &pGameId, bool *exists) { const char *ppssppIniFilename = IsVREnabled() ? "_ppssppvr.ini" : "_ppsspp.ini"; std::string iniFileName = pGameId + ppssppIniFilename; - Path iniFileNameFull = FindConfigFile(iniFileName); + Path iniFileNameFull = FindConfigFile(iniFileName, exists); return iniFileNameFull; } @@ -1754,7 +1766,8 @@ bool Config::saveGameConfig(const std::string &pGameId, const std::string &title return false; } - Path fullIniFilePath = getGameConfigFile(pGameId); + bool exists; + Path fullIniFilePath = getGameConfigFile(pGameId, &exists); IniFile iniFile; @@ -1791,9 +1804,9 @@ bool Config::saveGameConfig(const std::string &pGameId, const std::string &title } bool Config::loadGameConfig(const std::string &pGameId, const std::string &title) { - Path iniFileNameFull = getGameConfigFile(pGameId); - - if (!hasGameConfig(pGameId)) { + bool exists; + Path iniFileNameFull = getGameConfigFile(pGameId, &exists); + if (!exists) { DEBUG_LOG(Log::Loader, "No game-specific settings found in %s. Using global defaults.", iniFileNameFull.c_str()); return false; } diff --git a/Core/Config.h b/Core/Config.h index 49612b2d8363..8eff66237e4f 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -585,11 +585,11 @@ struct Config { bool loadGameConfig(const std::string &game_id, const std::string &title); bool saveGameConfig(const std::string &pGameId, const std::string &title); void unloadGameConfig(); - Path getGameConfigFile(const std::string &gameId); + Path getGameConfigFile(const std::string &gameId, bool *exists); bool hasGameConfig(const std::string &game_id); void SetSearchPath(const Path &path); - const Path FindConfigFile(const std::string &baseFilename); + const Path FindConfigFile(const std::string &baseFilename, bool *exists); void UpdateIniLocation(const char *iniFileName = nullptr, const char *controllerIniFilename = nullptr); diff --git a/Core/Dialog/SavedataParam.cpp b/Core/Dialog/SavedataParam.cpp index 9d1ef08bd4a1..f5bd4c093fa3 100644 --- a/Core/Dialog/SavedataParam.cpp +++ b/Core/Dialog/SavedataParam.cpp @@ -1558,12 +1558,20 @@ int SavedataParam::SetPspParam(SceUtilitySavedataParam *param) // get and stock file info for each file int realCount = 0; + + // TODO: Filter away non-directories directly? + std::vector allSaves = pspFileSystem.GetDirListing(savePath); + + bool fetchedAllSaves = false; + std::string gameName = GetGameName(param); + for (int i = 0; i < saveDataListCount; i++) { // "<>" means saveName can be anything... if (strncmp(saveNameListData[i], "<>", ARRAY_SIZE(saveNameListData[i])) == 0) { // TODO:Maybe we need a way to reorder the files? - auto allSaves = pspFileSystem.GetDirListing(savePath); - std::string gameName = GetGameName(param); + if (!fetchedAllSaves) { + fetchedAllSaves = true; + } for (auto it = allSaves.begin(); it != allSaves.end(); ++it) { if (it->name.compare(0, gameName.length(), gameName) == 0) { std::string saveName = it->name.substr(gameName.length()); @@ -1590,13 +1598,30 @@ int SavedataParam::SetPspParam(SceUtilitySavedataParam *param) const std::string thisSaveName = FixedToString(saveNameListData[i], ARRAY_SIZE(saveNameListData[i])); - std::string fileDataDir = savePath + GetGameName(param) + thisSaveName; - PSPFileInfo info = GetSaveInfo(fileDataDir); - if (info.exists) { - SetFileInfo(realCount, info, thisSaveName); - INFO_LOG(Log::sceUtility, "Save data exists: %s = %s", thisSaveName.c_str(), fileDataDir.c_str()); - realCount++; - } else { + const std::string folderName = gameName + thisSaveName; + + // Check if thisSaveName is in the list before processing. + // This is hopefully faster than doing file I/O. + bool found = false; + for (int i = 0; i < allSaves.size(); i++) { + if (allSaves[i].name == folderName) { + found = true; + } + } + + const std::string fileDataDir = savePath + gameName + thisSaveName; + if (found) { + PSPFileInfo info = GetSaveInfo(fileDataDir); + if (info.exists) { + SetFileInfo(realCount, info, thisSaveName); + INFO_LOG(Log::sceUtility, "Save data exists: %s = %s", thisSaveName.c_str(), fileDataDir.c_str()); + realCount++; + } else { + found = false; + } + } + + if (!found) { // NOTE: May be changed above, can't merge with the expression if (listEmptyFile) { ClearFileInfo(saveDataList[realCount], thisSaveName); INFO_LOG(Log::sceUtility, "Listing missing save data: %s = %s", thisSaveName.c_str(), fileDataDir.c_str()); @@ -2002,7 +2027,7 @@ int SavedataParam::GetSaveCryptMode(const SceUtilitySavedataParam *param, const bool SavedataParam::IsInSaveDataList(const std::string &saveName, int count) { for(int i = 0; i < count; ++i) { - if(strcmp(saveDataList[i].saveName.c_str(),saveName.c_str()) == 0) + if (saveDataList[i].saveName == saveName) return true; } return false; diff --git a/Core/FileLoaders/LocalFileLoader.cpp b/Core/FileLoaders/LocalFileLoader.cpp index 05f55f73e33f..f15b9399b629 100644 --- a/Core/FileLoaders/LocalFileLoader.cpp +++ b/Core/FileLoaders/LocalFileLoader.cpp @@ -155,12 +155,7 @@ bool LocalFileLoader::Exists() { return true; #endif - File::FileInfo info; - if (File::GetFileInfo(filename_, &info)) { - return info.exists; - } else { - return false; - } + return File::Exists(filename_); } bool LocalFileLoader::IsDirectory() { diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 292a3eba4a30..90117ebdd345 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -2466,6 +2466,7 @@ static u32 sceIoDopen(const char *path) { "TEXTURES", "DUMP", "SHADERS", + "DRIVERS", }; std::vector filtered; for (const auto &entry : dir->listing) { diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index ea83b2a24354..680d691e1e07 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -801,26 +801,24 @@ namespace SaveState std::string GetSlotDateAsString(const Path &gameFilename, int slot) { Path fn = GenerateSaveSlotFilename(gameFilename, slot, STATE_EXTENSION); - if (File::Exists(fn)) { - tm time; - if (File::GetModifTime(fn, time)) { - char buf[256]; - // TODO: Use local time format? Americans and some others might not like ISO standard :) - switch (g_Config.iDateFormat) { - case PSP_SYSTEMPARAM_DATE_FORMAT_YYYYMMDD: - strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &time); - break; - case PSP_SYSTEMPARAM_DATE_FORMAT_MMDDYYYY: - strftime(buf, sizeof(buf), "%m-%d-%Y %H:%M:%S", &time); - break; - case PSP_SYSTEMPARAM_DATE_FORMAT_DDMMYYYY: - strftime(buf, sizeof(buf), "%d-%m-%Y %H:%M:%S", &time); - break; - default: // Should never happen - return ""; - } - return std::string(buf); + tm time; + if (File::GetModifTime(fn, time)) { + char buf[256]; + // TODO: Use local time format? Americans and some others might not like ISO standard :) + switch (g_Config.iDateFormat) { + case PSP_SYSTEMPARAM_DATE_FORMAT_YYYYMMDD: + strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &time); + break; + case PSP_SYSTEMPARAM_DATE_FORMAT_MMDDYYYY: + strftime(buf, sizeof(buf), "%m-%d-%Y %H:%M:%S", &time); + break; + case PSP_SYSTEMPARAM_DATE_FORMAT_DDMMYYYY: + strftime(buf, sizeof(buf), "%d-%m-%Y %H:%M:%S", &time); + break; + default: // Should never happen + return ""; } + return std::string(buf); } return ""; } diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index f785c6105ab1..376064a482ab 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -101,7 +101,6 @@ ReplacedTexture::~ReplacedTexture() { if (threadWaitable_) { SetState(ReplacementState::CANCEL_INIT); - std::unique_lock lock(lock_); threadWaitable_->WaitAndRelease(); threadWaitable_ = nullptr; } @@ -225,7 +224,7 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { VFSFileReference *fileRef = vfs_->GetFile(desc_.filenames[i].c_str()); if (!fileRef) { if (i == 0) { - INFO_LOG(Log::G3D, "Texture replacement file '%s' not found", desc_.filenames[i].c_str()); + INFO_LOG(Log::G3D, "Texture replacement file '%s' not found in %s", desc_.filenames[i].c_str(), vfs_->toString().c_str()); // No file at all. Mark as NOT_FOUND. SetState(ReplacementState::NOT_FOUND); return; diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 8b3e1d91910b..572486c26a60 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -3103,7 +3103,7 @@ void TextureCacheCommon::DrawImGuiDebug(uint64_t &selectedTextureId) const { int w = dimWidth(dim); int h = dimHeight(dim); ImGui::Image(texId, ImVec2(w, h)); - ImGui::Text("%08x: %dx%d, %d mips, %s", selectedTextureId & 0xFFFFFFFF, w, h, entry->maxLevel + 1, GeTextureFormatToString((GETextureFormat)entry->format)); + ImGui::Text("%08x: %dx%d, %d mips, %s", (uint32_t)(selectedTextureId & 0xFFFFFFFF), w, h, entry->maxLevel + 1, GeTextureFormatToString((GETextureFormat)entry->format)); ImGui::Text("Stride: %d", entry->bufw); ImGui::Text("Status: %08x", entry->status); // TODO: Show the flags ImGui::Text("Hash: %08x", entry->fullhash); diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 1db43f0730de..b9365a68386c 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -269,6 +269,8 @@ void TextureReplacer::ComputeAliasMap(const std::mapGet("hash", &hash, ""); diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index 93d2684b74df..2c8a02e88b2a 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -303,14 +303,8 @@ void GameInfo::DisposeFileLoader() { bool GameInfo::DeleteAllSaveData() { std::vector saveDataDir = GetSaveDataDirectories(); for (size_t j = 0; j < saveDataDir.size(); j++) { - std::vector fileInfo; - File::GetFilesInDir(saveDataDir[j], &fileInfo); - - for (size_t i = 0; i < fileInfo.size(); i++) { - File::Delete(fileInfo[i].fullName); - } - - File::DeleteDir(saveDataDir[j]); + INFO_LOG(Log::System, "Deleting savedata from %s", saveDataDir[j].c_str()); + File::DeleteDirRecursively(saveDataDir[j]); } return true; } diff --git a/UI/GameScreen.cpp b/UI/GameScreen.cpp index cf1661538760..ef7d5ddca8ed 100644 --- a/UI/GameScreen.cpp +++ b/UI/GameScreen.cpp @@ -97,10 +97,6 @@ void GameScreen::update() { void GameScreen::CreateViews() { std::shared_ptr info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO | GameInfoFlags::ICON | GameInfoFlags::BG); - if (info->Ready(GameInfoFlags::PARAM_SFO)) { - saveDirs = info->GetSaveDataDirectories(); // Get's very heavy, let's not do it in update() - } - auto di = GetI18NCategory(I18NCat::DIALOG); auto ga = GetI18NCategory(I18NCat::GAME); @@ -478,7 +474,7 @@ ScreenRenderFlags GameScreen::render(ScreenRenderMode mode) { btnDeleteGameConfig_->SetVisibility(info->hasConfig ? UI::V_VISIBLE : UI::V_GONE); btnCreateGameConfig_->SetVisibility(info->hasConfig ? UI::V_GONE : UI::V_VISIBLE); - if (saveDirs.size()) { + if (info->saveDataSize) { btnDeleteSaveData_->SetVisibility(UI::V_VISIBLE); } if (info->pic0.texture || info->pic1.texture) { @@ -537,10 +533,10 @@ UI::EventReturn GameScreen::OnGameSettings(UI::EventParams &e) { } UI::EventReturn GameScreen::OnDeleteSaveData(UI::EventParams &e) { - std::shared_ptr info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO); + std::shared_ptr info = g_gameInfoCache->GetInfo(NULL, gamePath_, GameInfoFlags::PARAM_SFO | GameInfoFlags::SIZE); if (info) { // Check that there's any savedata to delete - if (saveDirs.size()) { + if (info->saveDataSize) { auto di = GetI18NCategory(I18NCat::DIALOG); auto ga = GetI18NCategory(I18NCat::GAME); screenManager()->push( diff --git a/UI/GameScreen.h b/UI/GameScreen.h index e06592788166..b1ec5554d8c1 100644 --- a/UI/GameScreen.h +++ b/UI/GameScreen.h @@ -87,7 +87,6 @@ class GameScreen : public UIDialogScreenWithGameBackground { UI::Choice *btnCalcCRC_ = nullptr; std::vector otherChoices_; - std::vector saveDirs; std::string CRC32string; bool isHomebrew_ = false; diff --git a/android/src/org/ppsspp/ppsspp/PpssppActivity.java b/android/src/org/ppsspp/ppsspp/PpssppActivity.java index a2d1072f4ded..0eb30d7c8f83 100644 --- a/android/src/org/ppsspp/ppsspp/PpssppActivity.java +++ b/android/src/org/ppsspp/ppsspp/PpssppActivity.java @@ -251,7 +251,7 @@ public long computeRecursiveDirectorySize(String uriString) { // * https://stackoverflow.com/q // uestions/42186820/documentfile-is-very-slow @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public String[] listContentUriDir(String uriString, String prefix) { + public String[] listContentUriDir(String uriString) { Cursor c = null; try { Uri uri = Uri.parse(uriString); @@ -262,13 +262,7 @@ public String[] listContentUriDir(String uriString, String prefix) { String selection = null; String[] selectionArgs = null; - if (prefix != null) { - selection = MediaStore.Files.FileColumns.DISPLAY_NAME + " LIKE ?"; - // Prefix followed by wildcard - selectionArgs = new String[]{ prefix + "%" }; - } - - c = resolver.query(childrenUri, columns, selection, selectionArgs, null); + c = resolver.query(childrenUri, columns, null, null, null); if (c == null) { return new String[]{ "X" }; } diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 3aed4a699144..34eb7efd26a5 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -989,14 +989,13 @@ bool TestIniFile() { const std::string testLine2 = "# Just a comment"; std::string temp; - ParsedIniLine line; - line.ParseFrom(testLine); + ParsedIniLine line(testLine); line.Reconstruct(&temp); EXPECT_EQ_STR(testLine, temp); temp.clear(); - line.ParseFrom(testLine2); - line.Reconstruct(&temp); + ParsedIniLine line2(testLine2); + line2.Reconstruct(&temp); EXPECT_EQ_STR(testLine2, temp); return true;