| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- using LibHac;
- using LibHac.Common;
- using LibHac.Fs;
- using LibHac.Fs.Shim;
- using LibHac.FsSystem;
- using LibHac.Ncm;
- using Ryujinx.HLE.Utilities;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Runtime.CompilerServices;
- namespace Ryujinx.Ui
- {
- internal class SaveImporter
- {
- private FileSystemClient FsClient { get; }
- private string ImportPath { get; }
- public SaveImporter(string importPath, FileSystemClient destFsClient)
- {
- ImportPath = importPath;
- FsClient = destFsClient;
- }
- // Returns the number of saves imported
- public int Import()
- {
- return ImportSaves(FsClient, ImportPath);
- }
- private static int ImportSaves(FileSystemClient fsClient, string rootSaveDir)
- {
- if (!Directory.Exists(rootSaveDir))
- {
- return 0;
- }
- SaveFinder finder = new SaveFinder();
- finder.FindSaves(rootSaveDir);
- foreach (SaveToImport save in finder.Saves)
- {
- Result importResult = ImportSave(fsClient, save);
- if (importResult.IsFailure())
- {
- throw new HorizonResultException(importResult, $"Error importing save {save.Path}");
- }
- }
- return finder.Saves.Count;
- }
- private static Result ImportSave(FileSystemClient fs, SaveToImport save)
- {
- SaveDataAttribute key = save.Attribute;
- Result result = fs.CreateSaveData(key.TitleId, key.UserId, key.TitleId, 0, 0, 0);
- if (result.IsFailure()) return result;
- bool isOldMounted = false;
- bool isNewMounted = false;
- try
- {
- result = fs.Register("OldSave".ToU8Span(), new LocalFileSystem(save.Path));
- if (result.IsFailure()) return result;
- isOldMounted = true;
- result = fs.MountSaveData("NewSave".ToU8Span(), key.TitleId, key.UserId);
- if (result.IsFailure()) return result;
- isNewMounted = true;
- result = fs.CopyDirectory("OldSave:/", "NewSave:/");
- if (result.IsFailure()) return result;
- result = fs.Commit("NewSave".ToU8Span());
- }
- finally
- {
- if (isOldMounted)
- {
- fs.Unmount("OldSave".ToU8Span());
- }
- if (isNewMounted)
- {
- fs.Unmount("NewSave".ToU8Span());
- }
- }
- return result;
- }
- private class SaveFinder
- {
- public List<SaveToImport> Saves { get; } = new List<SaveToImport>();
- public void FindSaves(string rootPath)
- {
- foreach (string subDir in Directory.EnumerateDirectories(rootPath))
- {
- if (TryGetUInt64(subDir, out ulong saveDataId))
- {
- SearchSaveId(subDir, saveDataId);
- }
- }
- }
- private void SearchSaveId(string path, ulong saveDataId)
- {
- foreach (string subDir in Directory.EnumerateDirectories(path))
- {
- if (TryGetUserId(subDir, out UserId userId))
- {
- SearchUser(subDir, saveDataId, userId);
- }
- }
- }
- private void SearchUser(string path, ulong saveDataId, UserId userId)
- {
- foreach (string subDir in Directory.EnumerateDirectories(path))
- {
- if (TryGetUInt64(subDir, out ulong titleId) && TryGetDataPath(subDir, out string dataPath))
- {
- SaveDataAttribute attribute = new SaveDataAttribute
- {
- Type = SaveDataType.Account,
- UserId = userId,
- TitleId = new TitleId(titleId)
- };
- SaveToImport save = new SaveToImport(dataPath, attribute);
- Saves.Add(save);
- }
- }
- }
- private static bool TryGetDataPath(string path, out string dataPath)
- {
- string committedPath = Path.Combine(path, "0");
- string workingPath = Path.Combine(path, "1");
- if (Directory.Exists(committedPath) && Directory.EnumerateFileSystemEntries(committedPath).Any())
- {
- dataPath = committedPath;
- return true;
- }
- if (Directory.Exists(workingPath) && Directory.EnumerateFileSystemEntries(workingPath).Any())
- {
- dataPath = workingPath;
- return true;
- }
- dataPath = default;
- return false;
- }
- private static bool TryGetUInt64(string path, out ulong converted)
- {
- string name = Path.GetFileName(path);
- if (name.Length == 16)
- {
- try
- {
- converted = Convert.ToUInt64(name, 16);
- return true;
- }
- catch { }
- }
- converted = default;
- return false;
- }
- private static bool TryGetUserId(string path, out UserId userId)
- {
- string name = Path.GetFileName(path);
- if (name.Length == 32)
- {
- try
- {
- UInt128 id = new UInt128(name);
- userId = Unsafe.As<UInt128, UserId>(ref id);
- return true;
- }
- catch { }
- }
- userId = default;
- return false;
- }
- }
- private class SaveToImport
- {
- public string Path { get; }
- public SaveDataAttribute Attribute { get; }
- public SaveToImport(string path, SaveDataAttribute attribute)
- {
- Path = path;
- Attribute = attribute;
- }
- }
- }
- }
|