diff --git a/Common/File/FileUtil.cpp b/Common/File/FileUtil.cpp index 3a964b0df9..138600b12b 100644 --- a/Common/File/FileUtil.cpp +++ b/Common/File/FileUtil.cpp @@ -327,13 +327,13 @@ bool Delete(const Path &filename) { // Return true because we care about the file no // being there, not the actual delete. if (!Exists(filename)) { - WARN_LOG(COMMON, "Delete: %s does not exists", filename.c_str()); + WARN_LOG(COMMON, "Delete: '%s' already does not exist", filename.c_str()); return true; } // We can't delete a directory if (IsDirectory(filename)) { - WARN_LOG(COMMON, "Delete failed: %s is a directory", filename.c_str()); + WARN_LOG(COMMON, "Delete failed: '%s' is a directory", filename.c_str()); return false; } diff --git a/Common/File/Path.h b/Common/File/Path.h index ded1064b3a..387d7742c6 100644 --- a/Common/File/Path.h +++ b/Common/File/Path.h @@ -44,7 +44,7 @@ public: return path_.size(); } - // WARNING: Unsafe usage. + // WARNING: Potentially unsafe usage, if it's not NATIVE. const char *c_str() const { return path_.c_str(); } diff --git a/Core/Config.cpp b/Core/Config.cpp index 92ed2982c6..634ed94abd 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -1212,17 +1212,22 @@ void Config::Reload() { reload_ = false; } -void Config::Load(const char *iniFileName, const char *controllerIniFilename) { +// Call this if you change the search path (such as when changing memstick directory. can't +// really think of any other legit uses). +void Config::UpdateIniLocation(const char *iniFileName, const char *controllerIniFilename) { const bool useIniFilename = iniFileName != nullptr && strlen(iniFileName) > 0; iniFilename_ = FindConfigFile(useIniFilename ? iniFileName : "ppsspp.ini"); + const bool useControllerIniFilename = controllerIniFilename != nullptr && strlen(controllerIniFilename) > 0; + controllerIniFilename_ = FindConfigFile(useControllerIniFilename ? controllerIniFilename : "controls.ini"); +} +void Config::Load(const char *iniFileName, const char *controllerIniFilename) { if (!bUpdatedInstanceCounter) { InitInstanceCounter(); bUpdatedInstanceCounter = true; } - const bool useControllerIniFilename = controllerIniFilename != nullptr && strlen(controllerIniFilename) > 0; - controllerIniFilename_ = FindConfigFile(useControllerIniFilename ? controllerIniFilename : "controls.ini"); + UpdateIniLocation(iniFileName, controllerIniFilename); INFO_LOG(LOADER, "Loading config: %s", iniFilename_.c_str()); bSaveSettings = true; diff --git a/Core/Config.h b/Core/Config.h index 79323eefca..6dbe092183 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -508,6 +508,8 @@ public: void SetSearchPath(const Path &path); const Path FindConfigFile(const std::string &baseFilename); + void UpdateIniLocation(const char *iniFileName = nullptr, const char *controllerIniFilename = nullptr); + // Utility functions for "recent" management void AddRecent(const std::string &file); void RemoveRecent(const std::string &file); diff --git a/Core/System.cpp b/Core/System.cpp index d47407f6d0..808e39ff76 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -581,38 +581,47 @@ CoreParameter &PSP_CoreParameter() { } Path GetSysDirectory(PSPDirectories directoryType) { + Path memStickDirectory = g_Config.memStickDirectory; + Path pspDirectory; + if (memStickDirectory.GetFilename() == "PSP") { + // Let's strip this off, to easily allow choosing a root directory named "PSP" on Android. + pspDirectory = memStickDirectory; + } else { + pspDirectory = memStickDirectory / "PSP"; + } + switch (directoryType) { case DIRECTORY_CHEATS: - return g_Config.memStickDirectory / "PSP/Cheats"; + return pspDirectory / "Cheats"; case DIRECTORY_GAME: - return g_Config.memStickDirectory / "PSP/GAME"; + return pspDirectory / "GAME"; case DIRECTORY_SAVEDATA: - return g_Config.memStickDirectory / "PSP/SAVEDATA"; + return pspDirectory / "SAVEDATA"; case DIRECTORY_SCREENSHOT: - return g_Config.memStickDirectory / "PSP/SCREENSHOT"; + return pspDirectory / "SCREENSHOT"; case DIRECTORY_SYSTEM: - return g_Config.memStickDirectory / "PSP/SYSTEM"; + return pspDirectory / "SYSTEM"; case DIRECTORY_PAUTH: - return g_Config.memStickDirectory / "PAUTH"; + return memStickDirectory / "PAUTH"; // This one's at the root... case DIRECTORY_DUMP: - return g_Config.memStickDirectory / "PSP/SYSTEM/DUMP"; + return pspDirectory / "SYSTEM/DUMP"; case DIRECTORY_SAVESTATE: - return g_Config.memStickDirectory / "PSP/PPSSPP_STATE"; + return pspDirectory / "PPSSPP_STATE"; case DIRECTORY_CACHE: - return g_Config.memStickDirectory / "PSP/SYSTEM/CACHE"; + return pspDirectory / "SYSTEM/CACHE"; case DIRECTORY_TEXTURES: - return g_Config.memStickDirectory / "PSP/TEXTURES"; + return pspDirectory / "TEXTURES"; case DIRECTORY_PLUGINS: - return g_Config.memStickDirectory / "PSP/PLUGINS"; + return pspDirectory / "PLUGINS"; case DIRECTORY_APP_CACHE: if (!g_Config.appCacheDirectory.empty()) { return g_Config.appCacheDirectory; } - return g_Config.memStickDirectory / "PSP/SYSTEM/CACHE"; + return pspDirectory / "SYSTEM/CACHE"; case DIRECTORY_VIDEO: - return g_Config.memStickDirectory / "PSP/VIDEO"; + return pspDirectory / "VIDEO"; case DIRECTORY_AUDIO: - return g_Config.memStickDirectory / "PSP/AUDIO"; + return pspDirectory / "AUDIO"; case DIRECTORY_MEMSTICK_ROOT: return g_Config.memStickDirectory; // Just return the memory stick root if we run into some sort of problem. diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 90e1c0ac89..e4064d8ba3 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1278,10 +1278,13 @@ void GameSettingsScreen::CallbackMemstickFolder(bool yes) { } File::Delete(Path(testWriteFile)); - File::WriteDataToFile(true, pendingMemstickFolder_.c_str(), (unsigned int)pendingMemstickFolder_.size(), memstickDirFile); - // Save so the settings, at least, are transferred. - g_Config.memStickDirectory = Path(pendingMemstickFolder_); - g_Config.Save("MemstickPathChanged"); + if (!File::WriteDataToFile(true, pendingMemstickFolder_.c_str(), (unsigned int)pendingMemstickFolder_.size(), memstickDirFile)) { + WARN_LOG(SYSTEM, "Failed to write memstick folder to '%s'", memstickDirFile.c_str()); + } else { + // Save so the settings, at least, are transferred. + g_Config.memStickDirectory = Path(pendingMemstickFolder_); + g_Config.Save("MemstickPathChanged"); + } screenManager()->RecreateAllViews(); } } diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 9649882cbf..749b83cb27 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -338,11 +338,19 @@ static void PostLoadConfig() { i18nrepo.LoadIni(g_Config.sLanguageIni, langOverridePath); } -void CreateDirectoriesAndroid() { +static bool CreateDirectoriesAndroid() { // On Android, create a PSP directory tree in the external_dir, // to hopefully reduce confusion a bit. - INFO_LOG(IO, "Creating %s and subdirs:", (g_Config.memStickDirectory / "PSP").c_str()); - File::CreateFullPath(g_Config.memStickDirectory / "PSP"); + + Path pspDir = g_Config.memStickDirectory / "PSP"; + + INFO_LOG(IO, "Creating '%s' and subdirs:", pspDir.c_str()); + File::CreateFullPath(pspDir); + if (!File::Exists(pspDir)) { + INFO_LOG(IO, "Not a workable memstick directory. Giving up"); + return false; + } + File::CreateFullPath(GetSysDirectory(DIRECTORY_SAVEDATA)); File::CreateFullPath(GetSysDirectory(DIRECTORY_SAVESTATE)); File::CreateFullPath(GetSysDirectory(DIRECTORY_GAME)); @@ -357,6 +365,7 @@ void CreateDirectoriesAndroid() { File::CreateEmptyFile(GetSysDirectory(DIRECTORY_SYSTEM) / ".nomedia"); File::CreateEmptyFile(GetSysDirectory(DIRECTORY_TEXTURES) / ".nomedia"); File::CreateEmptyFile(GetSysDirectory(DIRECTORY_PLUGINS) / ".nomedia"); + return true; } static void CheckFailedGPUBackends() { @@ -487,18 +496,21 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch g_Config.internalDataDirectory = Path(savegame_dir); #if PPSSPP_PLATFORM(ANDROID) + // In Android 12 with scoped storage, due to the above, the external directory + // is no longer the plain root of external storage, but it's an app specific directory + // on external storage (g_extFilesDir). if (System_GetPropertyBool(SYSPROP_ANDROID_SCOPED_STORAGE)) { - g_Config.externalDirectory = Path(g_extFilesDir); + g_Config.defaultCurrentDirectory = Path(g_extFilesDir); } else { - g_Config.externalDirectory = Path(external_dir); + // Maybe there should be an option to use internal memory instead, but I think + // that for most people, using external memory (SDCard/USB Storage) makes the + // most sense. + g_Config.defaultCurrentDirectory = Path(external_dir); } - // TODO: This needs to change in Android 12. - // - // Maybe there should be an option to use internal memory instead, but I think - // that for most people, using external memory (SDCard/USB Storage) makes the - // most sense. - g_Config.defaultCurrentDirectory = Path(external_dir); + // Might also add an option to move it to internal / non-visible storage, but there's + // little point, really. + g_Config.memStickDirectory = Path(external_dir); g_Config.flash0Directory = Path(external_dir) / "flash0"; @@ -506,13 +518,15 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch if (File::Exists(memstickDirFile)) { std::string memstickDir; if (File::ReadFileToString(true, memstickDirFile, memstickDir)) { - Path memstickPath(memstickDir); if (!memstickPath.empty() && File::Exists(memstickPath)) { g_Config.memStickDirectory = memstickPath; - INFO_LOG(SYSTEM, "Memstick Directory from memstick_dir.txt: %s", g_Config.memStickDirectory.c_str()); + INFO_LOG(SYSTEM, "Memstick Directory from memstick_dir.txt: '%s'", g_Config.memStickDirectory.c_str()); } else { ERROR_LOG(SYSTEM, "Couldn't read directory '%s' specified by memstick_dir.txt.", memstickDir.c_str()); + if (System_GetPropertyBool(SYSPROP_ANDROID_SCOPED_STORAGE)) { + // + } } } } else { diff --git a/android/jni/AndroidContentURI.h b/android/jni/AndroidContentURI.h index 3f0d1ee2fb..59a8b9b710 100644 --- a/android/jni/AndroidContentURI.h +++ b/android/jni/AndroidContentURI.h @@ -132,8 +132,11 @@ public: } if (!CanNavigateUp()) { - // Kinda useless to get the "primary:" volume. - return std::string(); + size_t colon = file.rfind(':'); + if (colon == std::string::npos) { + return std::string(); + } + return file.substr(colon + 1); } size_t slash = file.rfind('/'); diff --git a/android/src/org/ppsspp/ppsspp/PpssppActivity.java b/android/src/org/ppsspp/ppsspp/PpssppActivity.java index 4a953be2bc..ed047f07bd 100644 --- a/android/src/org/ppsspp/ppsspp/PpssppActivity.java +++ b/android/src/org/ppsspp/ppsspp/PpssppActivity.java @@ -129,7 +129,7 @@ public class PpssppActivity extends NativeActivity { } return filePfd.detachFd(); // Take ownership of the fd. } catch (Exception e) { - Log.e(TAG, "Exception opening content uri: " + e.toString()); + Log.e(TAG, "openContentUri exception: " + e.toString()); return -1; } } @@ -159,7 +159,7 @@ public class PpssppActivity extends NativeActivity { String[] strings = new String[listing.size()]; return listing.toArray(strings); } catch (Exception e) { - Log.e(TAG, "Exception opening content uri: " + e.toString()); + Log.e(TAG, "listContentUriDir exception: " + e.toString()); return new String[]{}; } } @@ -175,7 +175,7 @@ public class PpssppActivity extends NativeActivity { return false; } } catch (Exception e) { - Log.e(TAG, "Exception opening content uri: " + e.toString()); + Log.e(TAG, "contentUriCreateDirectory exception: " + e.toString()); return false; } } @@ -191,7 +191,7 @@ public class PpssppActivity extends NativeActivity { return false; } } catch (Exception e) { - Log.e(TAG, "Exception opening content uri: " + e.toString()); + Log.e(TAG, "contentUriCreateFile exception: " + e.toString()); return false; } } @@ -206,7 +206,7 @@ public class PpssppActivity extends NativeActivity { return false; } } catch (Exception e) { - Log.e(TAG, "Exception opening content uri: " + e.toString()); + Log.e(TAG, "contentUriRemoveFile exception: " + e.toString()); return false; } } @@ -222,7 +222,7 @@ public class PpssppActivity extends NativeActivity { return null; } } catch (Exception e) { - Log.e(TAG, "Exception opening content uri: " + e.toString()); + Log.e(TAG, "contentUriGetFileInfo exception: " + e.toString()); return null; } } @@ -246,7 +246,7 @@ public class PpssppActivity extends NativeActivity { long availableBytes = storageManager.getAllocatableBytes(volumeUUID); return availableBytes; } catch (Exception e) { - Log.e(TAG, "Exception checking free space: " + e.toString()); + Log.e(TAG, "contentUriGetFreeStorageSpace exception: " + e.toString()); return -1; } } @@ -259,7 +259,7 @@ public class PpssppActivity extends NativeActivity { long availableBytes = storageManager.getAllocatableBytes(volumeUUID); return availableBytes; } catch (Exception e) { - Log.e(TAG, "Exception checking free space: " + e.toString()); + Log.e(TAG, "filePathGetFreeStorageSpace exception: " + e.toString()); return -1; } }