From 3be1ff6ce486a079c9d61eeee7325e2a73004ad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 25 Jul 2021 00:16:30 +0200 Subject: [PATCH] Get the new setup flow going, with a confirmation dialog etc. Moving the folder while already installed still crashes. --- Common/File/DiskFree.cpp | 4 +- Common/File/DiskFree.h | 3 +- Common/File/Path.cpp | 1 - Common/File/PathBrowser.h | 4 + Common/System/NativeApp.h | 2 + Common/UI/Screen.cpp | 3 + Core/FileLoaders/DiskCachingFileLoader.cpp | 4 +- Core/FileSystems/DirectoryFileSystem.cpp | 4 +- Core/HLE/sceCtrl.cpp | 6 +- UI/MemStickScreen.cpp | 301 +++++++++++++++++---- UI/MemStickScreen.h | 30 +- UI/NativeApp.cpp | 21 +- 12 files changed, 299 insertions(+), 84 deletions(-) diff --git a/Common/File/DiskFree.cpp b/Common/File/DiskFree.cpp index 3a5fb9e722..f1412a35be 100644 --- a/Common/File/DiskFree.cpp +++ b/Common/File/DiskFree.cpp @@ -23,7 +23,7 @@ #include "Common/File/AndroidStorage.h" #include "Common/Data/Encoding/Utf8.h" -bool free_disk_space(const Path &path, uint64_t &space) { +bool free_disk_space(const Path &path, int64_t &space) { #ifdef _WIN32 ULARGE_INTEGER free; if (GetDiskFreeSpaceExW(path.ToWString().c_str(), &free, nullptr, nullptr)) { @@ -43,7 +43,7 @@ bool free_disk_space(const Path &path, uint64_t &space) { if (res == 0) { #ifndef __ANDROID__ if (diskstat.f_flag & ST_RDONLY) { - space = 0; + space = -1; return true; } #endif diff --git a/Common/File/DiskFree.h b/Common/File/DiskFree.h index 5405fc4dc4..a08f44bdd1 100644 --- a/Common/File/DiskFree.h +++ b/Common/File/DiskFree.h @@ -4,4 +4,5 @@ #include "Common/File/Path.h" -bool free_disk_space(const Path &path, uint64_t &space); +// If this fails, false is returned and space is negative. +bool free_disk_space(const Path &path, int64_t &space); diff --git a/Common/File/Path.cpp b/Common/File/Path.cpp index 5f0e905dda..86a43f20bd 100644 --- a/Common/File/Path.cpp +++ b/Common/File/Path.cpp @@ -236,7 +236,6 @@ bool Path::CanNavigateUp() const { if (type_ == PathType::CONTENT_URI) { return AndroidContentURI(path_).CanNavigateUp(); } - if (path_ == "/" || path_ == "") { return false; } diff --git a/Common/File/PathBrowser.h b/Common/File/PathBrowser.h index dd8cdeebb2..9f10cde560 100644 --- a/Common/File/PathBrowser.h +++ b/Common/File/PathBrowser.h @@ -35,6 +35,10 @@ public: } std::string GetFriendlyPath() const; + bool empty() const { + return path_.empty(); + } + private: void HandlePath(); void ResetPending(); diff --git a/Common/System/NativeApp.h b/Common/System/NativeApp.h index d501d03b43..d911fd9076 100644 --- a/Common/System/NativeApp.h +++ b/Common/System/NativeApp.h @@ -89,3 +89,5 @@ void NativeSetMixer(void* mixer); // Main thread. void NativeShutdownGraphics(); void NativeShutdown(); + +void PostLoadConfig(); diff --git a/Common/UI/Screen.cpp b/Common/UI/Screen.cpp index 1945b5be4f..ea5ed185f5 100644 --- a/Common/UI/Screen.cpp +++ b/Common/UI/Screen.cpp @@ -163,6 +163,8 @@ void ScreenManager::render() { iter--; Layer backback = *iter; + _assert_(backback.screen); + // TODO: Make really sure that this "mismatched" pre/post only happens // when screens are "compatible" (both are UIScreens, for example). backback.screen->preRender(); @@ -174,6 +176,7 @@ void ScreenManager::render() { break; } default: + _assert_(stack_.back().screen); stack_.back().screen->preRender(); stack_.back().screen->render(); if (postRenderCb_) diff --git a/Core/FileLoaders/DiskCachingFileLoader.cpp b/Core/FileLoaders/DiskCachingFileLoader.cpp index 06b140e0e5..73ba1ca868 100644 --- a/Core/FileLoaders/DiskCachingFileLoader.cpp +++ b/Core/FileLoaders/DiskCachingFileLoader.cpp @@ -754,9 +754,9 @@ u64 DiskCachingFileLoaderCache::FreeDiskSpace() { dir = GetSysDirectory(DIRECTORY_CACHE); } - uint64_t result = 0; + int64_t result = 0; if (free_disk_space(dir, result)) { - return result; + return (u64)result; } // We can't know for sure how much is free, so we have to assume none. diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 4e2ab9b2d8..528654a045 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -925,9 +925,9 @@ std::vector DirectoryFileSystem::GetDirListing(std::string path) { } u64 DirectoryFileSystem::FreeSpace(const std::string &path) { - uint64_t result = 0; + int64_t result = 0; if (free_disk_space(GetLocalPath(path), result)) { - return ReplayApplyDisk64(ReplayAction::FREESPACE, result, CoreTiming::GetGlobalTimeUs()); + return ReplayApplyDisk64(ReplayAction::FREESPACE, (uint64_t)result, CoreTiming::GetGlobalTimeUs()); } #if HOST_IS_CASE_SENSITIVE diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index fe78433792..78dee49bda 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -501,7 +501,8 @@ static int sceCtrlReadBufferNegative(u32 ctrlDataPtr, u32 nBufs) static int sceCtrlPeekBufferPositive(u32 ctrlDataPtr, u32 nBufs) { int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, false, true); - DEBUG_LOG(SCECTRL, "%d=sceCtrlPeekBufferPositive(%08x, %i)", done, ctrlDataPtr, nBufs); + // Some homebrew call this in a tight loop - so VERBOSE it is. + VERBOSE_LOG(SCECTRL, "%d=sceCtrlPeekBufferPositive(%08x, %i)", done, ctrlDataPtr, nBufs); hleEatCycles(330); return done; } @@ -509,7 +510,8 @@ static int sceCtrlPeekBufferPositive(u32 ctrlDataPtr, u32 nBufs) static int sceCtrlPeekBufferNegative(u32 ctrlDataPtr, u32 nBufs) { int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, true, true); - DEBUG_LOG(SCECTRL, "%d=sceCtrlPeekBufferNegative(%08x, %i)", done, ctrlDataPtr, nBufs); + // Some homebrew call this in a tight loop - so VERBOSE it is. + VERBOSE_LOG(SCECTRL, "%d=sceCtrlPeekBufferNegative(%08x, %i)", done, ctrlDataPtr, nBufs); hleEatCycles(330); return done; } diff --git a/UI/MemStickScreen.cpp b/UI/MemStickScreen.cpp index beee406b99..0e62fd644d 100644 --- a/UI/MemStickScreen.cpp +++ b/UI/MemStickScreen.cpp @@ -33,6 +33,7 @@ #include "Common/File/AndroidStorage.h" #include "Common/File/FileUtil.h" #include "Common/File/Path.h" +#include "Common/File/DiskFree.h" #include "Core/Util/GameManager.h" #include "Core/System.h" @@ -42,7 +43,63 @@ #include "UI/MainScreen.h" #include "UI/MiscScreens.h" -MemStickScreen::~MemStickScreen() { +static bool FolderSeemsToBeUsed(Path newMemstickFolder) { + // Inspect the potential new folder. + if (File::Exists(newMemstickFolder / "PSP") || File::Exists(newMemstickFolder / "SYSTEM")) { + // Does seem likely. We could add more critera like checking for actual savegames or something. + return true; + } else { + return false; + } +} + +static bool SwitchMemstickFolderTo(Path newMemstickFolder) { + Path testWriteFile = newMemstickFolder / ".write_verify_file"; + + // Doesn't already exist, create. + // Should this ever happen? + if (newMemstickFolder.Type() == PathType::NATIVE) { + if (!File::Exists(newMemstickFolder)) { + File::CreateFullPath(newMemstickFolder); + } + if (!File::WriteDataToFile(true, "1", 1, testWriteFile)) { + // settingInfo_->Show(sy->T("ChangingMemstickPathInvalid", "That path couldn't be used to save Memory Stick files."), nullptr); + // TODO: Display an error! + return UI::EVENT_DONE; + } + File::Delete(testWriteFile); + } else { + // TODO: Do the same but with scoped storage? Not really necessary, right? If it came from a browse + // for folder, we can assume it exists and is writable, barring wacky race conditions like the user + // being connected by USB and deleting it. + } + + Path memStickDirFile = g_Config.internalDataDirectory / "memstick_dir.txt"; + std::string str = newMemstickFolder.ToString(); + if (!File::WriteDataToFile(true, str.c_str(), (unsigned int)str.size(), memStickDirFile)) { + ERROR_LOG(SYSTEM, "Failed to write memstick path '%s' to '%s'", newMemstickFolder.c_str(), memStickDirFile.c_str()); + // Not sure what to do if this file. + } + + // Save so the settings, at least, are transferred. + g_Config.memStickDirectory = newMemstickFolder; + g_Config.SetSearchPath(GetSysDirectory(DIRECTORY_SYSTEM)); + g_Config.UpdateIniLocation(); + + return true; +} + +static std::string FormatSpaceString(int64_t space) { + if (space >= 0) { + // TODO: Smarter display (MB, GB as appropriate). Don't we have one of these somewhere? + return StringFromFormat("%lld MB", space / (1024 * 1024)); + } else { + return "N/A"; + } +} + +MemStickScreen::MemStickScreen(bool initialSetup) + : initialSetup_(initialSetup) { pendingMemStickFolder_ = g_Config.memStickDirectory; } @@ -54,7 +111,7 @@ void MemStickScreen::CreateViews() { Margins actionMenuMargins(15, 15, 15, 0); - root_ = new LinearLayout(ORIENT_HORIZONTAL, new AnchorLayoutParams(FILL_PARENT, FILL_PARENT)); + root_ = new LinearLayout(ORIENT_HORIZONTAL); Spacer *spacerColumn = new Spacer(new LinearLayoutParams(20.0, FILL_PARENT, 0.0f)); ViewGroup *leftColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0)); @@ -70,29 +127,6 @@ void MemStickScreen::CreateViews() { leftColumn->Add(new TextView(iz->T("MemoryStickDescription", "Choose PSP data storage (Memory Stick)"), ALIGN_LEFT, false)); -#if !PPSSPP_PLATFORM(WINDOWS) - if (!pendingMemStickFolder_.empty()) { - int64_t freeSpaceAtMemStick = -1; - if (Android_IsContentUri(pendingMemStickFolder_.ToString())) { - freeSpaceAtMemStick = Android_GetFreeSpaceByContentUri(pendingMemStickFolder_.ToString()); - } else { - freeSpaceAtMemStick = Android_GetFreeSpaceByFilePath(pendingMemStickFolder_.ToString()); - } - - leftColumn->Add(new TextView(pendingMemStickFolder_.ToVisualString(), ALIGN_LEFT, false)); - std::string freeSpaceText = "Free space: N/A"; - if (freeSpaceAtMemStick >= 0) { - freeSpaceText = StringFromFormat("free space: %lld MB", freeSpaceAtMemStick / (1024 * 1024)); - leftColumn->Add(new TextView(freeSpaceText, ALIGN_LEFT, false)); - } - } - - if (!g_Config.memStickDirectory.empty()) { - TextView *view = leftColumn->Add(new TextView(g_Config.memStickDirectory.ToVisualString(), ALIGN_LEFT, false)); - view->SetShadow(true); - } -#endif - leftColumn->Add(new Choice(iz->T("Create or Choose a PSP folder")))->OnClick.Handle(this, &MemStickScreen::OnBrowse); leftColumn->Add(new TextView(iz->T("ChooseFolderDesc", "* Data will stay even if you uninstall PPSSPP.\n* Data can be shared with PPSSPP Gold\n* Easy USB access"), ALIGN_LEFT, false)); @@ -101,13 +135,8 @@ void MemStickScreen::CreateViews() { leftColumn->Add(new Spacer(new LinearLayoutParams(FILL_PARENT, 12.0f, 0.0f))); - Choice *confirmButton = rightColumnItems->Add(new Choice(iz->T("Confirm"))); - confirmButton->OnClick.Handle(this, &MemStickScreen::OnConfirm); - confirmButton->SetEnabled(!pendingMemStickFolder_.empty()); - if (!initialSetup_) { - rightColumnItems->Add(new CheckBox(&moveData_, iz->T("Move Data"))); - rightColumnItems->Add(new Choice(di->T("Back")))->OnClick.Handle(this, &UIScreen::OnOK); + leftColumn->Add(new Choice(di->T("Back")))->OnClick.Handle(this, &UIScreen::OnBack); } INFO_LOG(SYSTEM, "MemStickScreen: initialSetup=%d", (int)initialSetup_); @@ -115,6 +144,16 @@ void MemStickScreen::CreateViews() { UI::EventReturn MemStickScreen::OnUseInternalStorage(UI::EventParams ¶ms) { pendingMemStickFolder_ = Path(g_extFilesDir); + + if (initialSetup_) { + // There's not gonna be any files here in this case since it's a fresh install. + // Let's just accept it and move on. No need to move files either. + SwitchMemstickFolderTo(pendingMemStickFolder_); + TriggerFinish(DialogResult::DR_OK); + } else { + // Always ask for confirmation when called from the UI. Likely there's already some data. + screenManager()->push(new ConfirmMemstickMoveScreen(pendingMemStickFolder_, false)); + } return UI::EVENT_DONE; } @@ -133,51 +172,195 @@ void MemStickScreen::sendMessage(const char *message, const char *value) { std::string filename; filename = value; INFO_LOG(SYSTEM, "Got folder: '%s'", filename.c_str()); + + // Browse finished. Let's pop up the confirmation dialog. pendingMemStickFolder_ = Path(filename); - RecreateViews(); + bool existingFiles = FolderSeemsToBeUsed(pendingMemStickFolder_); + screenManager()->push(new ConfirmMemstickMoveScreen(pendingMemStickFolder_, initialSetup_)); } } } -UI::EventReturn MemStickScreen::OnConfirm(UI::EventParams ¶ms) { - auto sy = GetI18NCategory("System"); +void MemStickScreen::dialogFinished(const Screen *dialog, DialogResult result) { + if (result == DialogResult::DR_OK) { + INFO_LOG(SYSTEM, "Confirmation screen done - moving on."); + // There's a screen manager bug if we call TriggerFinish directly. + // Can't be bothered right now, so we pick this up in update(). + done_ = true; + } + // otherwise, we just keep going. +} - Path memStickDirFile = g_Config.internalDataDirectory / "memstick_dir.txt"; - Path testWriteFile = pendingMemStickFolder_ / ".write_verify_file"; +void MemStickScreen::update() { + UIDialogScreenWithBackground::update(); + if (done_) { + TriggerFinish(DialogResult::DR_OK); + done_ = false; + } +} - // Doesn't already exist, create. - // Should this ever happen? - if (pendingMemStickFolder_.Type() == PathType::NATIVE) { - if (!File::Exists(pendingMemStickFolder_)) { - File::CreateFullPath(pendingMemStickFolder_); +static bool ListFileSuffixesRecursively(const Path &root, Path folder, std::vector &dirSuffixes, std::vector &fileSuffixes) { + std::vector files; + if (!File::GetFilesInDir(folder, &files)) { + return false; + } + + for (auto &file : files) { + if (file.isDirectory) { + dirSuffixes.push_back(root.PathTo(folder)); + ListFileSuffixesRecursively(root, folder / file.name, dirSuffixes, fileSuffixes); + } else { + fileSuffixes.push_back(root.PathTo(file.fullName)); } - if (!File::WriteDataToFile(true, "1", 1, testWriteFile)) { - // settingInfo_->Show(sy->T("ChangingMemstickPathInvalid", "That path couldn't be used to save Memory Stick files."), nullptr); + } + + return true; +} + +ConfirmMemstickMoveScreen::ConfirmMemstickMoveScreen(Path newMemstickFolder, bool initialSetup) + : newMemstickFolder_(newMemstickFolder), initialSetup_(initialSetup) { + existingFilesInNewFolder_ = FolderSeemsToBeUsed(newMemstickFolder); + if (initialSetup_) { + moveData_ = false; + } +} + +void ConfirmMemstickMoveScreen::CreateViews() { + using namespace UI; + auto di = GetI18NCategory("Dialog"); + auto sy = GetI18NCategory("System"); + auto iz = GetI18NCategory("MemStick"); + + root_ = new LinearLayout(ORIENT_HORIZONTAL); + + Path oldMemstickFolder = g_Config.memStickDirectory; + + Spacer *spacerColumn = new Spacer(new LinearLayoutParams(20.0, FILL_PARENT, 0.0f)); + ViewGroup *leftColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0)); + ViewGroup *rightColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(1.0)); + root_->Add(spacerColumn); + root_->Add(leftColumn); + root_->Add(rightColumn); + + int64_t freeSpaceNew; + int64_t freeSpaceOld; + free_disk_space(newMemstickFolder_, freeSpaceNew); + free_disk_space(oldMemstickFolder, freeSpaceOld); + + leftColumn->Add(new TextView(iz->T("New PSP Data Folder"), ALIGN_LEFT, false)); + leftColumn->Add(new TextView(newMemstickFolder_.ToVisualString(), ALIGN_LEFT, false)); + std::string newFreeSpaceText = std::string(iz->T("Free space")) + ": " + FormatSpaceString(freeSpaceNew); + leftColumn->Add(new TextView(newFreeSpaceText, ALIGN_LEFT, false)); + if (existingFilesInNewFolder_) { + leftColumn->Add(new TextView(iz->T("Warning: Already contains data"), ALIGN_LEFT, false)); + } + if (!error_.empty()) { + leftColumn->Add(new TextView(error_, ALIGN_LEFT, false)); + } + + if (!oldMemstickFolder.empty()) { + std::string oldFreeSpaceText = std::string(iz->T("Free space")) + ": " + FormatSpaceString(freeSpaceOld); + rightColumn->Add(new TextView(iz->T("Old PSP Data Folder"), ALIGN_LEFT, false)); + rightColumn->Add(new TextView(oldMemstickFolder.ToVisualString(), ALIGN_LEFT, false)); + rightColumn->Add(new TextView(oldFreeSpaceText, ALIGN_LEFT, false)); + } + + if (!initialSetup_) { + leftColumn->Add(new CheckBox(&moveData_, iz->T("Move Data"))); + } + + leftColumn->Add(new Choice(di->T("OK")))->OnClick.Handle(this, &ConfirmMemstickMoveScreen::OnConfirm); + leftColumn->Add(new Choice(di->T("Back")))->OnClick.Handle(this, &UIScreen::OnBack); +} + +UI::EventReturn ConfirmMemstickMoveScreen::OnConfirm(UI::EventParams ¶ms) { + auto sy = GetI18NCategory("System"); + auto iz = GetI18NCategory("MemStick"); + + // Transfer all the files in /PSP from the original directory. + // Should probably be done on a background thread so we can show some UI. + // So we probably need another screen for this with a progress bar.. + // If the directory itself is called PSP, don't go below. + + if (moveData_) { + Path moveSrc = g_Config.memStickDirectory; + Path moveDest = newMemstickFolder_; + if (moveSrc.GetFilename() != "PSP") { + moveSrc = moveSrc / "PSP"; + } + if (moveDest.GetFilename() != "PSP") { + moveDest = moveDest / "PSP"; + File::CreateDir(moveDest); + } + + INFO_LOG(SYSTEM, "About to move PSP data from '%s' to '%s'", moveSrc.c_str(), moveDest.c_str()); + + // Search through recursively, listing the files to move and also summing their sizes. + std::vector fileSuffixesToMove; + std::vector directorySuffixesToCreate; + + // NOTE: It's correct to pass moveSrc twice here, it's to keep the root in the recursion. + if (!ListFileSuffixesRecursively(moveSrc, moveSrc, directorySuffixesToCreate, fileSuffixesToMove)) { + // TODO: Handle failure listing files. + error_ = "Failed to read old directory"; + INFO_LOG(SYSTEM, "%s", error_.c_str()); + return UI::EVENT_DONE; + } + + bool dryRun = true; // Useful for debugging. + + size_t moveFailures = 0; + + if (!moveSrc.empty()) { + // Better not interrupt the app while this is happening! + + // Create all the necessary directories. + for (auto &dirSuffix : directorySuffixesToCreate) { + Path dir = moveDest / dirSuffix; + if (dryRun) { + INFO_LOG(SYSTEM, "dry run: Would have created dir '%s'", dir.c_str()); + } else { + if (!File::Exists(dir)) { + File::CreateDir(dir); + } + } + } + for (auto &fileSuffix : fileSuffixesToMove) { + Path from = moveSrc / fileSuffix; + Path to = moveDest / fileSuffix; + if (dryRun) { + INFO_LOG(SYSTEM, "dry run: Would have moved '%s' to '%s'", from.c_str(), to.c_str()); + } else { + // Remove the "from" prefix from the path. + // We have to drop down to string operations for this. + if (!File::Move(from, to)) { + ERROR_LOG(SYSTEM, "Failed to move file '%s' to '%s'", from.c_str(), to.c_str()); + moveFailures++; + // Should probably just bail? + } + } + } + } + + if (moveFailures > 0) { + error_ = "Failed to move some files!"; + RecreateViews(); return UI::EVENT_DONE; } - File::Delete(testWriteFile); - } else { - // TODO: Do the same but with scoped storage? Not really necessary, right? If it came from a browse - // for folder, we can assume it exists and is writable, barring wacky race conditions like the user - // being connected by USB and deleting it. } - // This doesn't need the storage API - this path is accessible the normal way. - std::string str = pendingMemStickFolder_.ToString(); - if (!File::WriteDataToFile(true, str.c_str(), (unsigned int)str.size(), memStickDirFile)) { - ERROR_LOG(SYSTEM, "Failed to write memstick path '%s' to '%s'", pendingMemStickFolder_.c_str(), memStickDirFile.c_str()); - // Not sure what to do if this file. - } + // Successful so far, switch the memstick folder. + SwitchMemstickFolderTo(newMemstickFolder_); + + // If the chosen folder already had a config, reload it! + g_Config.Load(); + - // Save so the settings, at least, are transferred. - g_Config.memStickDirectory = pendingMemStickFolder_; - g_Config.SetSearchPath(GetSysDirectory(DIRECTORY_SYSTEM)); - g_Config.UpdateIniLocation(); if (g_Config.Save("MemstickPathChanged")) { TriggerFinish(DialogResult::DR_OK); } else { - error_ = sy->T("Failed to save config"); + error_ = iz->T("Failed to save config"); RecreateViews(); } diff --git a/UI/MemStickScreen.h b/UI/MemStickScreen.h index 7f7ccaafa2..1a5d12b63d 100644 --- a/UI/MemStickScreen.h +++ b/UI/MemStickScreen.h @@ -30,27 +30,43 @@ // Currently only useful for Android. class MemStickScreen : public UIDialogScreenWithBackground { public: - MemStickScreen(bool initialSetup) - : initialSetup_(initialSetup) {} - virtual ~MemStickScreen(); + MemStickScreen(bool initialSetup); + ~MemStickScreen() {} std::string tag() const override { return "game"; } void CreateViews() override; protected: void sendMessage(const char *message, const char *value) override; + void dialogFinished(const Screen *dialog, DialogResult result) override; + void update() override; private: // Event handlers UI::EventReturn OnBrowse(UI::EventParams &e); - UI::EventReturn OnConfirm(UI::EventParams ¶ms); UI::EventReturn OnUseInternalStorage(UI::EventParams ¶ms); + // TODO: probably not necessary to store here, we just forward to the confirmation dialog. Path pendingMemStickFolder_; SettingInfoMessage *settingInfo_ = nullptr; - std::string error_; - bool initialSetup_; - bool moveData_ = true; + bool done_ = false; +}; + +class ConfirmMemstickMoveScreen : public UIDialogScreenWithBackground { +public: + ConfirmMemstickMoveScreen(Path newMemstickFolder, bool initialSetup); + + void CreateViews() override; + +private: + UI::EventReturn OnConfirm(UI::EventParams ¶ms); + + Path newMemstickFolder_; + bool existingFilesInNewFolder_; + bool moveData_ = true; + bool initialSetup_; + + std::string error_; }; diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 8925f0485c..6a0d731c0b 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -322,7 +322,9 @@ static bool CheckFontIsUsable(const wchar_t *fontFace) { } #endif -static void PostLoadConfig() { +bool CreateDirectoriesAndroid(); + +void PostLoadConfig() { // On Windows, we deal with currentDirectory in InitSysDirectories(). #if !PPSSPP_PLATFORM(WINDOWS) if (g_Config.currentDirectory.empty()) { @@ -339,11 +341,14 @@ static void PostLoadConfig() { i18nrepo.LoadIni(g_Config.sLanguageIni); else i18nrepo.LoadIni(g_Config.sLanguageIni, langOverridePath); + +#if PPSSPP_PLATFORM(ANDROID) + CreateDirectoriesAndroid(); +#endif } -static bool CreateDirectoriesAndroid() { - // On Android, create a PSP directory tree in the external_dir, - // to hopefully reduce confusion a bit. +bool CreateDirectoriesAndroid() { + // TODO: Really not sure why this code is Android-exclusive, except the ".nomedia" part. Path pspDir = g_Config.memStickDirectory; if (pspDir.GetFilename() != "PSP") { @@ -530,9 +535,9 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch } else { ERROR_LOG(SYSTEM, "Couldn't read directory '%s' specified by memstick_dir.txt.", memstickDir.c_str()); if (System_GetPropertyBool(SYSPROP_ANDROID_SCOPED_STORAGE)) { - // Ask the user to configure a memstick directory. - INFO_LOG(SYSTEM, "Asking the user."); - g_Config.memStickDirectory.clear(); + // Ask the user to configure a memstick directory. + INFO_LOG(SYSTEM, "Asking the user."); + g_Config.memStickDirectory.clear(); } } } @@ -785,7 +790,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch screenManager = new ScreenManager(); if (g_Config.memStickDirectory.empty()) { INFO_LOG(SYSTEM, "No memstick directory! Asking for one to be configured."); - screenManager->switchScreen(new MainScreen()); + screenManager->switchScreen(new LogoScreen(false)); screenManager->push(new MemStickScreen(true)); } else if (gotoGameSettings) { screenManager->switchScreen(new LogoScreen(true));