| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- using Gtk;
- using LibHac;
- using System;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using Switch = Ryujinx.HLE.Switch;
- namespace Ryujinx.Ui
- {
- internal class Migration
- {
- private Switch Device { get; }
- public Migration(Switch device)
- {
- Device = device;
- }
- public static bool PromptIfMigrationNeededForStartup(Window parentWindow, out bool isMigrationNeeded)
- {
- if (!IsMigrationNeeded())
- {
- isMigrationNeeded = false;
- return true;
- }
- isMigrationNeeded = true;
- int dialogResponse;
- using (MessageDialog dialog = new MessageDialog(parentWindow, DialogFlags.Modal, MessageType.Question,
- ButtonsType.YesNo, "What's this?"))
- {
- dialog.Title = "Data Migration Needed";
- dialog.Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png");
- dialog.Text =
- "The folder structure of Ryujinx's RyuFs folder has been updated and renamed to \"Ryujinx\". " +
- "Your RyuFs folder must be copied and migrated to the new \"Ryujinx\" structure. Would you like to do the migration now?\n\n" +
- "Select \"Yes\" to automatically perform the migration. Your old RyuFs folder will remain as it is.\n\n" +
- "Selecting \"No\" will exit Ryujinx without changing anything.";
- dialogResponse = dialog.Run();
- }
- return dialogResponse == (int)ResponseType.Yes;
- }
- public static bool DoMigrationForStartup(Window parentWindow, Switch device)
- {
- try
- {
- Migration migration = new Migration(device);
- int saveCount = migration.Migrate();
- using MessageDialog dialogSuccess = new MessageDialog(parentWindow, DialogFlags.Modal, MessageType.Info, ButtonsType.Ok, null)
- {
- Title = "Migration Success",
- Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Icon.png"),
- Text = $"Data migration was successful. {saveCount} saves were migrated.",
- };
- dialogSuccess.Run();
- // Reload key set after migration to be sure to catch the keys in the system directory.
- device.System.LoadKeySet();
- return true;
- }
- catch (HorizonResultException ex)
- {
- GtkDialog.CreateErrorDialog(ex.Message);
- return false;
- }
- }
- // Returns the number of saves migrated
- public int Migrate()
- {
- string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
- string oldBasePath = Path.Combine(appDataPath, "RyuFs");
- string newBasePath = Path.Combine(appDataPath, "Ryujinx");
- string oldSaveDir = Path.Combine(oldBasePath, "nand/user/save");
- CopyRyuFs(oldBasePath, newBasePath);
- SaveImporter importer = new SaveImporter(oldSaveDir, Device.System.FsClient);
- return importer.Import();
- }
- private static void CopyRyuFs(string oldPath, string newPath)
- {
- Directory.CreateDirectory(newPath);
- CopyExcept(oldPath, newPath, "nand", "bis", "sdmc", "sdcard");
- string oldNandPath = Path.Combine(oldPath, "nand");
- string newNandPath = Path.Combine(newPath, "bis");
- CopyExcept(oldNandPath, newNandPath, "system", "user");
- string oldSdPath = Path.Combine(oldPath, "sdmc");
- string newSdPath = Path.Combine(newPath, "sdcard");
- CopyDirectory(oldSdPath, newSdPath);
- string oldSystemPath = Path.Combine(oldNandPath, "system");
- string newSystemPath = Path.Combine(newNandPath, "system");
- CopyExcept(oldSystemPath, newSystemPath, "save");
- string oldUserPath = Path.Combine(oldNandPath, "user");
- string newUserPath = Path.Combine(newNandPath, "user");
- CopyExcept(oldUserPath, newUserPath, "save");
- }
- private static void CopyExcept(string srcPath, string dstPath, params string[] exclude)
- {
- exclude = exclude.Select(x => x.ToLowerInvariant()).ToArray();
- DirectoryInfo srcDir = new DirectoryInfo(srcPath);
- if (!srcDir.Exists)
- {
- return;
- }
- Directory.CreateDirectory(dstPath);
- foreach (DirectoryInfo subDir in srcDir.EnumerateDirectories())
- {
- if (exclude.Contains(subDir.Name.ToLowerInvariant()))
- {
- continue;
- }
- CopyDirectory(subDir.FullName, Path.Combine(dstPath, subDir.Name));
- }
- foreach (FileInfo file in srcDir.EnumerateFiles())
- {
- file.CopyTo(Path.Combine(dstPath, file.Name));
- }
- }
- private static void CopyDirectory(string srcPath, string dstPath)
- {
- Directory.CreateDirectory(dstPath);
- DirectoryInfo srcDir = new DirectoryInfo(srcPath);
- if (!srcDir.Exists)
- {
- return;
- }
- Directory.CreateDirectory(dstPath);
- foreach (DirectoryInfo subDir in srcDir.EnumerateDirectories())
- {
- CopyDirectory(subDir.FullName, Path.Combine(dstPath, subDir.Name));
- }
- foreach (FileInfo file in srcDir.EnumerateFiles())
- {
- file.CopyTo(Path.Combine(dstPath, file.Name));
- }
- }
- public static bool IsMigrationNeeded()
- {
- string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
- string oldBasePath = Path.Combine(appDataPath, "RyuFs");
- string newBasePath = Path.Combine(appDataPath, "Ryujinx");
- return Directory.Exists(oldBasePath) && !Directory.Exists(newBasePath);
- }
- }
- }
|