From b2268f1f8d51ee03fac4571c2e0d58641413e2fe Mon Sep 17 00:00:00 2001
From: Zach Hilman <zachhilman@gmail.com>
Date: Sat, 1 Sep 2018 14:49:07 -0400
Subject: [PATCH 1/3] settings: Save and load NAND/SD dirs from config

---
 src/core/settings.h               |  2 ++
 src/yuzu/configuration/config.cpp | 18 ++++++++++++++++++
 src/yuzu_cmd/config.cpp           |  6 ++++++
 3 files changed, 26 insertions(+)

diff --git a/src/core/settings.h b/src/core/settings.h
index ed6f42471..5bf1863e6 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -127,6 +127,8 @@ struct Values {
 
     // Data Storage
     bool use_virtual_sd;
+    std::string nand_dir;
+    std::string sdmc_dir;
 
     // Renderer
     float resolution_factor;
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 60b6d6d44..c43e79e78 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -102,6 +102,20 @@ void Config::ReadValues() {
 
     qt_config->beginGroup("Data Storage");
     Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool();
+    FileUtil::GetUserPath(
+        FileUtil::UserPath::NANDDir,
+        qt_config
+            ->value("nand_directory",
+                    QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)))
+            .toString()
+            .toStdString());
+    FileUtil::GetUserPath(
+        FileUtil::UserPath::SDMCDir,
+        qt_config
+            ->value("sdmc_directory",
+                    QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir)))
+            .toString()
+            .toStdString());
     qt_config->endGroup();
 
     qt_config->beginGroup("System");
@@ -222,6 +236,10 @@ void Config::SaveValues() {
 
     qt_config->beginGroup("Data Storage");
     qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd);
+    qt_config->setValue("nand_directory",
+                        QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)));
+    qt_config->setValue("sdmc_directory",
+                        QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir)));
     qt_config->endGroup();
 
     qt_config->beginGroup("System");
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index a95580152..f00b5a66b 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -114,6 +114,12 @@ void Config::ReadValues() {
     // Data Storage
     Settings::values.use_virtual_sd =
         sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true);
+    FileUtil::GetUserPath(FileUtil::UserPath::NANDDir,
+                          sdl2_config->Get("Data Storage", "nand_directory",
+                                           FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)));
+    FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir,
+                          sdl2_config->Get("Data Storage", "nand_directory",
+                                           FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir)));
 
     // System
     Settings::values.use_docked_mode = sdl2_config->GetBoolean("System", "use_docked_mode", false);

From 1ff3318458e15e68b5a5946c8d395d625692637a Mon Sep 17 00:00:00 2001
From: Zach Hilman <zachhilman@gmail.com>
Date: Sat, 1 Sep 2018 14:49:18 -0400
Subject: [PATCH 2/3] qt: Add UI options to change NAND/SD dirs

---
 src/yuzu/main.cpp | 14 ++++++++++++++
 src/yuzu/main.h   |  3 +++
 src/yuzu/main.ui  | 19 +++++++++++++++++++
 3 files changed, 36 insertions(+)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index cfc48a416..01a5d2552 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -372,6 +372,10 @@ void GMainWindow::ConnectMenuEvents() {
             &GMainWindow::OnMenuInstallToNAND);
     connect(ui.action_Select_Game_List_Root, &QAction::triggered, this,
             &GMainWindow::OnMenuSelectGameListRoot);
+    connect(ui.action_Select_NAND_Directory, &QAction::triggered, this,
+            [this] { OnMenuSelectEmulatedDirectory(false); });
+    connect(ui.action_Select_SDMC_Directory, &QAction::triggered, this,
+            [this] { OnMenuSelectEmulatedDirectory(true); });
     connect(ui.action_Exit, &QAction::triggered, this, &QMainWindow::close);
 
     // Emulation
@@ -887,6 +891,16 @@ void GMainWindow::OnMenuSelectGameListRoot() {
     }
 }
 
+void GMainWindow::OnMenuSelectEmulatedDirectory(bool is_sdmc) {
+    QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory"));
+    if (!dir_path.isEmpty()) {
+        FileUtil::GetUserPath(is_sdmc ? FileUtil::UserPath::SDMCDir : FileUtil::UserPath::NANDDir,
+                              dir_path.toStdString());
+        Service::FileSystem::CreateFactories(vfs);
+        game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan);
+    }
+}
+
 void GMainWindow::OnMenuRecentFile() {
     QAction* action = qobject_cast<QAction*>(sender());
     assert(action);
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 3d6ebe329..b85149f8e 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -137,6 +137,9 @@ private slots:
     void OnMenuInstallToNAND();
     /// Called whenever a user selects the "File->Select Game List Root" menu item
     void OnMenuSelectGameListRoot();
+    /// Called whenever a user select the "File->Select -- Directory" where -- is NAND or SD Card
+    /// (false for nand, true for sdmc)
+    void OnMenuSelectEmulatedDirectory(bool is_sdmc);
     void OnMenuRecentFile();
     void OnConfigure();
     void OnAbout();
diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui
index faa0c626a..3879d4813 100644
--- a/src/yuzu/main.ui
+++ b/src/yuzu/main.ui
@@ -65,6 +65,9 @@
     <addaction name="action_Select_Game_List_Root"/>
     <addaction name="menu_recent_files"/>
     <addaction name="separator"/>
+    <addaction name="action_Select_NAND_Directory"/>
+    <addaction name="action_Select_SDMC_Directory"/>
+    <addaction name="separator"/>
     <addaction name="action_Exit"/>
    </widget>
    <widget class="QMenu" name="menu_Emulation">
@@ -204,6 +207,22 @@
     <string>Selects a folder to display in the game list</string>
    </property>
   </action>
+  <action name="action_Select_NAND_Directory">
+   <property name="text">
+    <string>Select NAND Directory...</string>
+   </property>
+   <property name="toolTip">
+    <string>Selects a folder to use as the root of the emulated NAND</string>
+   </property>
+  </action>
+  <action name="action_Select_SDMC_Directory">
+   <property name="text">
+    <string>Select SD Card Directory...</string>
+   </property>
+   <property name="toolTip">
+    <string>Selects a folder to use as the root of the emulated SD card</string>
+   </property>
+  </action>
   <action name="action_Fullscreen">
    <property name="checkable">
     <bool>true</bool>

From 04397cd185bf6f6f8c979df4fe48379f669f0ed5 Mon Sep 17 00:00:00 2001
From: Zach Hilman <zachhilman@gmail.com>
Date: Mon, 3 Sep 2018 19:23:10 -0400
Subject: [PATCH 3/3] qt: Add message about not moving contents on dir change

---
 src/yuzu/main.cpp | 21 +++++++++++++++++----
 src/yuzu/main.h   |  8 ++++++--
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 01a5d2552..a21f7bdbc 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -12,6 +12,7 @@
 
 #define QT_NO_OPENGL
 #include <QDesktopWidget>
+#include <QDialogButtonBox>
 #include <QFileDialog>
 #include <QMessageBox>
 #include <QtGui>
@@ -373,9 +374,9 @@ void GMainWindow::ConnectMenuEvents() {
     connect(ui.action_Select_Game_List_Root, &QAction::triggered, this,
             &GMainWindow::OnMenuSelectGameListRoot);
     connect(ui.action_Select_NAND_Directory, &QAction::triggered, this,
-            [this] { OnMenuSelectEmulatedDirectory(false); });
+            [this] { OnMenuSelectEmulatedDirectory(EmulatedDirectoryTarget::NAND); });
     connect(ui.action_Select_SDMC_Directory, &QAction::triggered, this,
-            [this] { OnMenuSelectEmulatedDirectory(true); });
+            [this] { OnMenuSelectEmulatedDirectory(EmulatedDirectoryTarget::SDMC); });
     connect(ui.action_Exit, &QAction::triggered, this, &QMainWindow::close);
 
     // Emulation
@@ -891,10 +892,22 @@ void GMainWindow::OnMenuSelectGameListRoot() {
     }
 }
 
-void GMainWindow::OnMenuSelectEmulatedDirectory(bool is_sdmc) {
+void GMainWindow::OnMenuSelectEmulatedDirectory(EmulatedDirectoryTarget target) {
+    const auto res = QMessageBox::information(
+        this, tr("Changing Emulated Directory"),
+        tr("You are about to change the emulated %1 directory of the system. Please note "
+           "that this does not also move the contents of the previous directory to the "
+           "new one and you will have to do that yourself.")
+            .arg(target == EmulatedDirectoryTarget::SDMC ? tr("SD card") : tr("NAND")),
+        QMessageBox::StandardButtons{QMessageBox::Ok, QMessageBox::Cancel});
+
+    if (res == QMessageBox::Cancel)
+        return;
+
     QString dir_path = QFileDialog::getExistingDirectory(this, tr("Select Directory"));
     if (!dir_path.isEmpty()) {
-        FileUtil::GetUserPath(is_sdmc ? FileUtil::UserPath::SDMCDir : FileUtil::UserPath::NANDDir,
+        FileUtil::GetUserPath(target == EmulatedDirectoryTarget::SDMC ? FileUtil::UserPath::SDMCDir
+                                                                      : FileUtil::UserPath::NANDDir,
                               dir_path.toStdString());
         Service::FileSystem::CreateFactories(vfs);
         game_list->PopulateAsync(UISettings::values.gamedir, UISettings::values.gamedir_deepscan);
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index b85149f8e..56b592a9e 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -32,6 +32,11 @@ namespace Tegra {
 class DebugContext;
 }
 
+enum class EmulatedDirectoryTarget {
+    NAND,
+    SDMC,
+};
+
 class GMainWindow : public QMainWindow {
     Q_OBJECT
 
@@ -138,8 +143,7 @@ private slots:
     /// Called whenever a user selects the "File->Select Game List Root" menu item
     void OnMenuSelectGameListRoot();
     /// Called whenever a user select the "File->Select -- Directory" where -- is NAND or SD Card
-    /// (false for nand, true for sdmc)
-    void OnMenuSelectEmulatedDirectory(bool is_sdmc);
+    void OnMenuSelectEmulatedDirectory(EmulatedDirectoryTarget target);
     void OnMenuRecentFile();
     void OnConfigure();
     void OnAbout();