diff options
Diffstat (limited to 'src/Ryujinx.HLE/FileSystem')
-rw-r--r-- | src/Ryujinx.HLE/FileSystem/ContentManager.cs | 391 | ||||
-rw-r--r-- | src/Ryujinx.HLE/FileSystem/ContentPath.cs | 57 | ||||
-rw-r--r-- | src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs | 2 | ||||
-rw-r--r-- | src/Ryujinx.HLE/FileSystem/LocationEntry.cs | 10 | ||||
-rw-r--r-- | src/Ryujinx.HLE/FileSystem/SystemVersion.cs | 44 | ||||
-rw-r--r-- | src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs | 125 |
6 files changed, 316 insertions, 313 deletions
diff --git a/src/Ryujinx.HLE/FileSystem/ContentManager.cs b/src/Ryujinx.HLE/FileSystem/ContentManager.cs index e00310a0..13f98763 100644 --- a/src/Ryujinx.HLE/FileSystem/ContentManager.cs +++ b/src/Ryujinx.HLE/FileSystem/ContentManager.cs @@ -26,17 +26,17 @@ namespace Ryujinx.HLE.FileSystem public class ContentManager { private const ulong SystemVersionTitleId = 0x0100000000000809; - private const ulong SystemUpdateTitleId = 0x0100000000000816; + private const ulong SystemUpdateTitleId = 0x0100000000000816; private Dictionary<StorageId, LinkedList<LocationEntry>> _locationEntries; - private Dictionary<string, ulong> _sharedFontTitleDictionary; - private Dictionary<ulong, string> _systemTitlesNameDictionary; - private Dictionary<string, string> _sharedFontFilenameDictionary; + private readonly Dictionary<string, ulong> _sharedFontTitleDictionary; + private readonly Dictionary<ulong, string> _systemTitlesNameDictionary; + private readonly Dictionary<string, string> _sharedFontFilenameDictionary; private SortedDictionary<(ulong titleId, NcaContentType type), string> _contentDictionary; - private struct AocItem + private readonly struct AocItem { public readonly string ContainerPath; public readonly string NcaPath; @@ -48,16 +48,16 @@ namespace Ryujinx.HLE.FileSystem } } - private SortedList<ulong, AocItem> _aocData { get; } + private SortedList<ulong, AocItem> AocData { get; } - private VirtualFileSystem _virtualFileSystem; + private readonly VirtualFileSystem _virtualFileSystem; private readonly object _lock = new(); public ContentManager(VirtualFileSystem virtualFileSystem) { _contentDictionary = new SortedDictionary<(ulong, NcaContentType), string>(); - _locationEntries = new Dictionary<StorageId, LinkedList<LocationEntry>>(); + _locationEntries = new Dictionary<StorageId, LinkedList<LocationEntry>>(); _sharedFontTitleDictionary = new Dictionary<string, ulong> { @@ -66,7 +66,7 @@ namespace Ryujinx.HLE.FileSystem { "FontExtendedChineseSimplified", 0x0100000000000814 }, { "FontKorean", 0x0100000000000812 }, { "FontChineseTraditional", 0x0100000000000813 }, - { "FontNintendoExtended", 0x0100000000000810 } + { "FontNintendoExtended", 0x0100000000000810 }, }; _systemTitlesNameDictionary = new Dictionary<ulong, string>() @@ -86,12 +86,12 @@ namespace Ryujinx.HLE.FileSystem { "FontExtendedChineseSimplified", "nintendo_udsg-r_ext_zh-cn_003.bfttf" }, { "FontKorean", "nintendo_udsg-r_ko_003.bfttf" }, { "FontChineseTraditional", "nintendo_udjxh-db_zh-tw_003.bfttf" }, - { "FontNintendoExtended", "nintendo_ext_003.bfttf" } + { "FontNintendoExtended", "nintendo_ext_003.bfttf" }, }; _virtualFileSystem = virtualFileSystem; - _aocData = new SortedList<ulong, AocItem>(); + AocData = new SortedList<ulong, AocItem>(); } public void LoadEntries(Switch device = null) @@ -99,18 +99,18 @@ namespace Ryujinx.HLE.FileSystem lock (_lock) { _contentDictionary = new SortedDictionary<(ulong, NcaContentType), string>(); - _locationEntries = new Dictionary<StorageId, LinkedList<LocationEntry>>(); + _locationEntries = new Dictionary<StorageId, LinkedList<LocationEntry>>(); foreach (StorageId storageId in Enum.GetValues<StorageId>()) { - string contentDirectory = null; - string contentPathString = null; + string contentDirectory = null; + string contentPathString = null; string registeredDirectory = null; try { - contentPathString = ContentPath.GetContentPath(storageId); - contentDirectory = ContentPath.GetRealPath(_virtualFileSystem, contentPathString); + contentPathString = ContentPath.GetContentPath(storageId); + contentDirectory = ContentPath.GetRealPath(contentPathString); registeredDirectory = Path.Combine(contentDirectory, "registered"); } catch (NotSupportedException) @@ -120,7 +120,7 @@ namespace Ryujinx.HLE.FileSystem Directory.CreateDirectory(registeredDirectory); - LinkedList<LocationEntry> locationList = new LinkedList<LocationEntry>(); + LinkedList<LocationEntry> locationList = new(); void AddEntry(LocationEntry entry) { @@ -133,24 +133,19 @@ namespace Ryujinx.HLE.FileSystem { string ncaName = new DirectoryInfo(directoryPath).Name.Replace(".nca", string.Empty); - using (FileStream ncaFile = File.OpenRead(Directory.GetFiles(directoryPath)[0])) - { - Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage()); + using FileStream ncaFile = File.OpenRead(Directory.GetFiles(directoryPath)[0]); + Nca nca = new(_virtualFileSystem.KeySet, ncaFile.AsStorage()); - string switchPath = contentPathString + ":/" + ncaFile.Name.Replace(contentDirectory, string.Empty).TrimStart(Path.DirectorySeparatorChar); + string switchPath = contentPathString + ":/" + ncaFile.Name.Replace(contentDirectory, string.Empty).TrimStart(Path.DirectorySeparatorChar); - // Change path format to switch's - switchPath = switchPath.Replace('\\', '/'); + // Change path format to switch's + switchPath = switchPath.Replace('\\', '/'); - LocationEntry entry = new LocationEntry(switchPath, - 0, - nca.Header.TitleId, - nca.Header.ContentType); + LocationEntry entry = new(switchPath, 0, nca.Header.TitleId, nca.Header.ContentType); - AddEntry(entry); + AddEntry(entry); - _contentDictionary.Add((nca.Header.TitleId, nca.Header.ContentType), ncaName); - } + _contentDictionary.Add((nca.Header.TitleId, nca.Header.ContentType), ncaName); } } @@ -160,24 +155,19 @@ namespace Ryujinx.HLE.FileSystem { string ncaName = Path.GetFileNameWithoutExtension(filePath); - using (FileStream ncaFile = new FileStream(filePath, FileMode.Open, FileAccess.Read)) - { - Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile.AsStorage()); + using FileStream ncaFile = new(filePath, FileMode.Open, FileAccess.Read); + Nca nca = new(_virtualFileSystem.KeySet, ncaFile.AsStorage()); - string switchPath = contentPathString + ":/" + filePath.Replace(contentDirectory, string.Empty).TrimStart(Path.DirectorySeparatorChar); + string switchPath = contentPathString + ":/" + filePath.Replace(contentDirectory, string.Empty).TrimStart(Path.DirectorySeparatorChar); - // Change path format to switch's - switchPath = switchPath.Replace('\\', '/'); + // Change path format to switch's + switchPath = switchPath.Replace('\\', '/'); - LocationEntry entry = new LocationEntry(switchPath, - 0, - nca.Header.TitleId, - nca.Header.ContentType); + LocationEntry entry = new(switchPath, 0, nca.Header.TitleId, nca.Header.ContentType); - AddEntry(entry); + AddEntry(entry); - _contentDictionary.Add((nca.Header.TitleId, nca.Header.ContentType), ncaName); - } + _contentDictionary.Add((nca.Header.TitleId, nca.Header.ContentType), ncaName); } } @@ -186,10 +176,7 @@ namespace Ryujinx.HLE.FileSystem _locationEntries.Remove(storageId); } - if (!_locationEntries.ContainsKey(storageId)) - { - _locationEntries.Add(storageId, locationList); - } + _locationEntries.TryAdd(storageId, locationList); } if (device != null) @@ -239,7 +226,7 @@ namespace Ryujinx.HLE.FileSystem public void AddAocItem(ulong titleId, string containerPath, string ncaPath, bool mergedToContainer = false) { // TODO: Check Aoc version. - if (!_aocData.TryAdd(titleId, new AocItem(containerPath, ncaPath))) + if (!AocData.TryAdd(titleId, new AocItem(containerPath, ncaPath))) { Logger.Warning?.Print(LogClass.Application, $"Duplicate AddOnContent detected. TitleId {titleId:X16}"); } @@ -249,7 +236,7 @@ namespace Ryujinx.HLE.FileSystem if (!mergedToContainer) { - using FileStream fileStream = File.OpenRead(containerPath); + using FileStream fileStream = File.OpenRead(containerPath); using PartitionFileSystem partitionFileSystem = new(fileStream.AsStorage()); _virtualFileSystem.ImportTickets(partitionFileSystem); @@ -257,17 +244,17 @@ namespace Ryujinx.HLE.FileSystem } } - public void ClearAocData() => _aocData.Clear(); + public void ClearAocData() => AocData.Clear(); - public int GetAocCount() => _aocData.Count; + public int GetAocCount() => AocData.Count; - public IList<ulong> GetAocTitleIds() => _aocData.Select(e => e.Key).ToList(); + public IList<ulong> GetAocTitleIds() => AocData.Select(e => e.Key).ToList(); public bool GetAocDataStorage(ulong aocTitleId, out IStorage aocStorage, IntegrityCheckLevel integrityCheckLevel) { aocStorage = null; - if (_aocData.TryGetValue(aocTitleId, out AocItem aoc)) + if (AocData.TryGetValue(aocTitleId, out AocItem aoc)) { var file = new FileStream(aoc.ContainerPath, FileMode.Open, FileAccess.Read); using var ncaFile = new UniqueRef<IFile>(); @@ -307,7 +294,7 @@ namespace Ryujinx.HLE.FileSystem { lock (_lock) { - LinkedList<LocationEntry> locationList = _locationEntries[storageId]; + LinkedList<LocationEntry> locationList = _locationEntries[storageId]; LinkedListNode<LocationEntry> locationEntry = locationList.First; while (locationEntry != null) @@ -331,7 +318,7 @@ namespace Ryujinx.HLE.FileSystem if (_contentDictionary.ContainsValue(ncaId)) { var content = _contentDictionary.FirstOrDefault(x => x.Value == ncaId); - ulong titleId = content.Key.Item1; + ulong titleId = content.Key.titleId; NcaContentType contentType = content.Key.type; StorageId storage = GetInstalledStorage(titleId, contentType, storageId); @@ -403,19 +390,17 @@ namespace Ryujinx.HLE.FileSystem return false; } - string installedPath = _virtualFileSystem.SwitchPathToSystemPath(locationEntry.ContentPath); + string installedPath = VirtualFileSystem.SwitchPathToSystemPath(locationEntry.ContentPath); if (!string.IsNullOrWhiteSpace(installedPath)) { if (File.Exists(installedPath)) { - using (FileStream file = new FileStream(installedPath, FileMode.Open, FileAccess.Read)) - { - Nca nca = new Nca(_virtualFileSystem.KeySet, file.AsStorage()); - bool contentCheck = nca.Header.ContentType == contentType; + using FileStream file = new(installedPath, FileMode.Open, FileAccess.Read); + Nca nca = new(_virtualFileSystem.KeySet, file.AsStorage()); + bool contentCheck = nca.Header.ContentType == contentType; - return contentCheck; - } + return contentCheck; } } @@ -426,9 +411,9 @@ namespace Ryujinx.HLE.FileSystem { LinkedList<LocationEntry> locationList = null; - if (_locationEntries.ContainsKey(storageId)) + if (_locationEntries.TryGetValue(storageId, out LinkedList<LocationEntry> locationEntry)) { - locationList = _locationEntries[storageId]; + locationList = locationEntry; } if (locationList != null) @@ -446,9 +431,9 @@ namespace Ryujinx.HLE.FileSystem { LinkedList<LocationEntry> locationList = null; - if (_locationEntries.ContainsKey(storageId)) + if (_locationEntries.TryGetValue(storageId, out LinkedList<LocationEntry> locationEntry)) { - locationList = _locationEntries[storageId]; + locationList = locationEntry; } if (locationList != null) @@ -487,10 +472,10 @@ namespace Ryujinx.HLE.FileSystem public void InstallFirmware(string firmwareSource) { - string contentPathString = ContentPath.GetContentPath(StorageId.BuiltInSystem); - string contentDirectory = ContentPath.GetRealPath(_virtualFileSystem, contentPathString); + string contentPathString = ContentPath.GetContentPath(StorageId.BuiltInSystem); + string contentDirectory = ContentPath.GetRealPath(contentPathString); string registeredDirectory = Path.Combine(contentDirectory, "registered"); - string temporaryDirectory = Path.Combine(contentDirectory, "temp"); + string temporaryDirectory = Path.Combine(contentDirectory, "temp"); if (Directory.Exists(temporaryDirectory)) { @@ -510,28 +495,27 @@ namespace Ryujinx.HLE.FileSystem throw new FileNotFoundException("Firmware file does not exist."); } - FileInfo info = new FileInfo(firmwareSource); + FileInfo info = new(firmwareSource); - using (FileStream file = File.OpenRead(firmwareSource)) - { - switch (info.Extension) - { - case ".zip": - using (ZipArchive archive = ZipFile.OpenRead(firmwareSource)) - { - InstallFromZip(archive, temporaryDirectory); - } - break; - case ".xci": - Xci xci = new Xci(_virtualFileSystem.KeySet, file.AsStorage()); - InstallFromCart(xci, temporaryDirectory); - break; - default: - throw new InvalidFirmwarePackageException("Input file is not a valid firmware package"); - } + using FileStream file = File.OpenRead(firmwareSource); - FinishInstallation(temporaryDirectory, registeredDirectory); + switch (info.Extension) + { + case ".zip": + using (ZipArchive archive = ZipFile.OpenRead(firmwareSource)) + { + InstallFromZip(archive, temporaryDirectory); + } + break; + case ".xci": + Xci xci = new(_virtualFileSystem.KeySet, file.AsStorage()); + InstallFromCart(xci, temporaryDirectory); + break; + default: + throw new InvalidFirmwarePackageException("Input file is not a valid firmware package"); } + + FinishInstallation(temporaryDirectory, registeredDirectory); } private void FinishInstallation(string temporaryDirectory, string registeredDirectory) @@ -555,7 +539,7 @@ namespace Ryujinx.HLE.FileSystem { foreach (var entry in filesystem.EnumerateEntries("/", "*.nca")) { - Nca nca = new Nca(_virtualFileSystem.KeySet, OpenPossibleFragmentedFile(filesystem, entry.FullPath, OpenMode.Read).AsStorage()); + Nca nca = new(_virtualFileSystem.KeySet, OpenPossibleFragmentedFile(filesystem, entry.FullPath, OpenMode.Read).AsStorage()); SaveNca(nca, entry.Name.Remove(entry.Name.IndexOf('.')), temporaryDirectory); } @@ -575,52 +559,47 @@ namespace Ryujinx.HLE.FileSystem } } - private void InstallFromZip(ZipArchive archive, string temporaryDirectory) + private static void InstallFromZip(ZipArchive archive, string temporaryDirectory) { - using (archive) + foreach (var entry in archive.Entries) { - foreach (var entry in archive.Entries) + if (entry.FullName.EndsWith(".nca") || entry.FullName.EndsWith(".nca/00")) { - if (entry.FullName.EndsWith(".nca") || entry.FullName.EndsWith(".nca/00")) - { - // Clean up the name and get the NcaId + // Clean up the name and get the NcaId - string[] pathComponents = entry.FullName.Replace(".cnmt", "").Split('/'); + string[] pathComponents = entry.FullName.Replace(".cnmt", "").Split('/'); - string ncaId = pathComponents[pathComponents.Length - 1]; + string ncaId = pathComponents[^1]; - // If this is a fragmented nca, we need to get the previous element.GetZip - if (ncaId.Equals("00")) - { - ncaId = pathComponents[pathComponents.Length - 2]; - } + // If this is a fragmented nca, we need to get the previous element.GetZip + if (ncaId.Equals("00")) + { + ncaId = pathComponents[^2]; + } - if (ncaId.Contains(".nca")) - { - string newPath = Path.Combine(temporaryDirectory, ncaId); + if (ncaId.Contains(".nca")) + { + string newPath = Path.Combine(temporaryDirectory, ncaId); - Directory.CreateDirectory(newPath); + Directory.CreateDirectory(newPath); - entry.ExtractToFile(Path.Combine(newPath, "00")); - } + entry.ExtractToFile(Path.Combine(newPath, "00")); } } } } - public void SaveNca(Nca nca, string ncaId, string temporaryDirectory) + public static void SaveNca(Nca nca, string ncaId, string temporaryDirectory) { string newPath = Path.Combine(temporaryDirectory, ncaId + ".nca"); Directory.CreateDirectory(newPath); - using (FileStream file = File.Create(Path.Combine(newPath, "00"))) - { - nca.BaseStorage.AsStream().CopyTo(file); - } + using FileStream file = File.Create(Path.Combine(newPath, "00")); + nca.BaseStorage.AsStream().CopyTo(file); } - private IFile OpenPossibleFragmentedFile(IFileSystem filesystem, string path, OpenMode mode) + private static IFile OpenPossibleFragmentedFile(IFileSystem filesystem, string path, OpenMode mode) { using var file = new UniqueRef<IFile>(); @@ -636,14 +615,12 @@ namespace Ryujinx.HLE.FileSystem return file.Release(); } - private Stream GetZipStream(ZipArchiveEntry entry) + private static Stream GetZipStream(ZipArchiveEntry entry) { MemoryStream dest = MemoryStreamManager.Shared.GetStream(); - using (Stream src = entry.Open()) - { - src.CopyTo(dest); - } + using Stream src = entry.Open(); + src.CopyTo(dest); return dest; } @@ -659,7 +636,7 @@ namespace Ryujinx.HLE.FileSystem throw new MissingKeyException("HeaderKey is empty. Cannot decrypt NCA headers."); } - Dictionary<ulong, List<(NcaContentType type, string path)>> updateNcas = new Dictionary<ulong, List<(NcaContentType, string)>>(); + Dictionary<ulong, List<(NcaContentType type, string path)>> updateNcas = new(); if (Directory.Exists(firmwarePackage)) { @@ -671,33 +648,32 @@ namespace Ryujinx.HLE.FileSystem throw new FileNotFoundException("Firmware file does not exist."); } - FileInfo info = new FileInfo(firmwarePackage); + FileInfo info = new(firmwarePackage); + + using FileStream file = File.OpenRead(firmwarePackage); - using (FileStream file = File.OpenRead(firmwarePackage)) + switch (info.Extension) { - switch (info.Extension) - { - case ".zip": - using (ZipArchive archive = ZipFile.OpenRead(firmwarePackage)) - { - return VerifyAndGetVersionZip(archive); - } - case ".xci": - Xci xci = new Xci(_virtualFileSystem.KeySet, file.AsStorage()); + case ".zip": + using (ZipArchive archive = ZipFile.OpenRead(firmwarePackage)) + { + return VerifyAndGetVersionZip(archive); + } + case ".xci": + Xci xci = new(_virtualFileSystem.KeySet, file.AsStorage()); - if (xci.HasPartition(XciPartitionType.Update)) - { - XciPartition partition = xci.OpenPartition(XciPartitionType.Update); + if (xci.HasPartition(XciPartitionType.Update)) + { + XciPartition partition = xci.OpenPartition(XciPartitionType.Update); - return VerifyAndGetVersion(partition); - } - else - { - throw new InvalidFirmwarePackageException("Update not found in xci file."); - } - default: - break; - } + return VerifyAndGetVersion(partition); + } + else + { + throw new InvalidFirmwarePackageException("Update not found in xci file."); + } + default: + break; } SystemVersion VerifyAndGetVersionDirectory(string firmwareDirectory) @@ -713,21 +689,19 @@ namespace Ryujinx.HLE.FileSystem { if (entry.FullName.EndsWith(".nca") || entry.FullName.EndsWith(".nca/00")) { - using (Stream ncaStream = GetZipStream(entry)) - { - IStorage storage = ncaStream.AsStorage(); + using Stream ncaStream = GetZipStream(entry); + IStorage storage = ncaStream.AsStorage(); - Nca nca = new Nca(_virtualFileSystem.KeySet, storage); + Nca nca = new(_virtualFileSystem.KeySet, storage); - if (updateNcas.TryGetValue(nca.Header.TitleId, out var updateNcasItem)) - { - updateNcasItem.Add((nca.Header.ContentType, entry.FullName)); - } - else - { - updateNcas.Add(nca.Header.TitleId, new List<(NcaContentType, string)>()); - updateNcas[nca.Header.TitleId].Add((nca.Header.ContentType, entry.FullName)); - } + if (updateNcas.TryGetValue(nca.Header.TitleId, out var updateNcasItem)) + { + updateNcasItem.Add((nca.Header.ContentType, entry.FullName)); + } + else + { + updateNcas.Add(nca.Header.TitleId, new List<(NcaContentType, string)>()); + updateNcas[nca.Header.TitleId].Add((nca.Header.ContentType, entry.FullName)); } } } @@ -742,7 +716,7 @@ namespace Ryujinx.HLE.FileSystem using (Stream ncaStream = GetZipStream(fileEntry)) { - Nca metaNca = new Nca(_virtualFileSystem.KeySet, ncaStream.AsStorage()); + Nca metaNca = new(_virtualFileSystem.KeySet, ncaStream.AsStorage()); IFileSystem fs = metaNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); @@ -772,18 +746,16 @@ namespace Ryujinx.HLE.FileSystem { string versionEntry = updateNcasItem.Find(x => x.type != NcaContentType.Meta).path; - using (Stream ncaStream = GetZipStream(archive.GetEntry(versionEntry))) - { - Nca nca = new Nca(_virtualFileSystem.KeySet, ncaStream.AsStorage()); + using Stream ncaStream = GetZipStream(archive.GetEntry(versionEntry)); + Nca nca = new(_virtualFileSystem.KeySet, ncaStream.AsStorage()); - var romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); + var romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); - using var systemVersionFile = new UniqueRef<IFile>(); + using var systemVersionFile = new UniqueRef<IFile>(); - if (romfs.OpenFile(ref systemVersionFile.Ref, "/file".ToU8Span(), OpenMode.Read).IsSuccess()) - { - systemVersion = new SystemVersion(systemVersionFile.Get.AsStream()); - } + if (romfs.OpenFile(ref systemVersionFile.Ref, "/file".ToU8Span(), OpenMode.Read).IsSuccess()) + { + systemVersion = new SystemVersion(systemVersionFile.Get.AsStream()); } } @@ -804,43 +776,39 @@ namespace Ryujinx.HLE.FileSystem continue; } - ZipArchiveEntry metaZipEntry = archive.GetEntry(metaPath); + ZipArchiveEntry metaZipEntry = archive.GetEntry(metaPath); ZipArchiveEntry contentZipEntry = archive.GetEntry(contentPath); - using (Stream metaNcaStream = GetZipStream(metaZipEntry)) - { - using (Stream contentNcaStream = GetZipStream(contentZipEntry)) - { - Nca metaNca = new Nca(_virtualFileSystem.KeySet, metaNcaStream.AsStorage()); + using Stream metaNcaStream = GetZipStream(metaZipEntry); + using Stream contentNcaStream = GetZipStream(contentZipEntry); + Nca metaNca = new(_virtualFileSystem.KeySet, metaNcaStream.AsStorage()); - IFileSystem fs = metaNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); + IFileSystem fs = metaNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); - string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath; + string cnmtPath = fs.EnumerateEntries("/", "*.cnmt").Single().FullPath; - using var metaFile = new UniqueRef<IFile>(); + using var metaFile = new UniqueRef<IFile>(); - if (fs.OpenFile(ref metaFile.Ref, cnmtPath.ToU8Span(), OpenMode.Read).IsSuccess()) - { - var meta = new Cnmt(metaFile.Get.AsStream()); + if (fs.OpenFile(ref metaFile.Ref, cnmtPath.ToU8Span(), OpenMode.Read).IsSuccess()) + { + var meta = new Cnmt(metaFile.Get.AsStream()); - IStorage contentStorage = contentNcaStream.AsStorage(); - if (contentStorage.GetSize(out long size).IsSuccess()) - { - byte[] contentData = new byte[size]; + IStorage contentStorage = contentNcaStream.AsStorage(); + if (contentStorage.GetSize(out long size).IsSuccess()) + { + byte[] contentData = new byte[size]; - Span<byte> content = new Span<byte>(contentData); + Span<byte> content = new(contentData); - contentStorage.Read(0, content); + contentStorage.Read(0, content); - Span<byte> hash = new Span<byte>(new byte[32]); + Span<byte> hash = new(new byte[32]); - LibHac.Crypto.Sha256.GenerateSha256Hash(content, hash); + LibHac.Crypto.Sha256.GenerateSha256Hash(content, hash); - if (LibHac.Common.Utilities.ArraysEqual(hash.ToArray(), meta.ContentEntries[0].Hash)) - { - updateNcas.Remove(metaEntry.TitleId); - } - } + if (LibHac.Common.Utilities.ArraysEqual(hash.ToArray(), meta.ContentEntries[0].Hash)) + { + updateNcas.Remove(metaEntry.TitleId); } } } @@ -853,9 +821,9 @@ namespace Ryujinx.HLE.FileSystem foreach (var entry in updateNcas) { - foreach (var nca in entry.Value) + foreach (var (type, path) in entry.Value) { - extraNcas += nca.path + Environment.NewLine; + extraNcas += path + Environment.NewLine; } } @@ -880,7 +848,7 @@ namespace Ryujinx.HLE.FileSystem { IStorage ncaStorage = OpenPossibleFragmentedFile(filesystem, entry.FullPath, OpenMode.Read).AsStorage(); - Nca nca = new Nca(_virtualFileSystem.KeySet, ncaStorage); + Nca nca = new(_virtualFileSystem.KeySet, ncaStorage); if (nca.Header.TitleId == SystemUpdateTitleId && nca.Header.ContentType == NcaContentType.Meta) { @@ -936,8 +904,8 @@ namespace Ryujinx.HLE.FileSystem { if (updateNcas.TryGetValue(metaEntry.TitleId, out var ncaEntry)) { - var metaNcaEntry = ncaEntry.Find(x => x.type == NcaContentType.Meta); - string contentPath = ncaEntry.Find(x => x.type != NcaContentType.Meta).path; + string metaNcaPath = ncaEntry.Find(x => x.type == NcaContentType.Meta).path; + string contentPath = ncaEntry.Find(x => x.type != NcaContentType.Meta).path; // Nintendo in 9.0.0, removed PPC and only kept the meta nca of it. // This is a perfect valid case, so we should just ignore the missing content nca and continue. @@ -948,10 +916,10 @@ namespace Ryujinx.HLE.FileSystem continue; } - IStorage metaStorage = OpenPossibleFragmentedFile(filesystem, metaNcaEntry.path, OpenMode.Read).AsStorage(); + IStorage metaStorage = OpenPossibleFragmentedFile(filesystem, metaNcaPath, OpenMode.Read).AsStorage(); IStorage contentStorage = OpenPossibleFragmentedFile(filesystem, contentPath, OpenMode.Read).AsStorage(); - Nca metaNca = new Nca(_virtualFileSystem.KeySet, metaStorage); + Nca metaNca = new(_virtualFileSystem.KeySet, metaStorage); IFileSystem fs = metaNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); @@ -967,11 +935,11 @@ namespace Ryujinx.HLE.FileSystem { byte[] contentData = new byte[size]; - Span<byte> content = new Span<byte>(contentData); + Span<byte> content = new(contentData); contentStorage.Read(0, content); - Span<byte> hash = new Span<byte>(new byte[32]); + Span<byte> hash = new(new byte[32]); LibHac.Crypto.Sha256.GenerateSha256Hash(content, hash); @@ -1017,24 +985,21 @@ namespace Ryujinx.HLE.FileSystem { if (entry.ContentType == NcaContentType.Data) { - var path = _virtualFileSystem.SwitchPathToSystemPath(entry.ContentPath); + var path = VirtualFileSystem.SwitchPathToSystemPath(entry.ContentPath); - using (FileStream fileStream = File.OpenRead(path)) - { - Nca nca = new Nca(_virtualFileSystem.KeySet, fileStream.AsStorage()); + using FileStream fileStream = File.OpenRead(path); + Nca nca = new(_virtualFileSystem.KeySet, fileStream.AsStorage()); - if (nca.Header.TitleId == SystemVersionTitleId && nca.Header.ContentType == NcaContentType.Data) - { - var romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); + if (nca.Header.TitleId == SystemVersionTitleId && nca.Header.ContentType == NcaContentType.Data) + { + var romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid); - using var systemVersionFile = new UniqueRef<IFile>(); + using var systemVersionFile = new UniqueRef<IFile>(); - if (romfs.OpenFile(ref systemVersionFile.Ref, "/file".ToU8Span(), OpenMode.Read).IsSuccess()) - { - return new SystemVersion(systemVersionFile.Get.AsStream()); - } + if (romfs.OpenFile(ref systemVersionFile.Ref, "/file".ToU8Span(), OpenMode.Read).IsSuccess()) + { + return new SystemVersion(systemVersionFile.Get.AsStream()); } - } } } diff --git a/src/Ryujinx.HLE/FileSystem/ContentPath.cs b/src/Ryujinx.HLE/FileSystem/ContentPath.cs index c8663081..6d2f3f6a 100644 --- a/src/Ryujinx.HLE/FileSystem/ContentPath.cs +++ b/src/Ryujinx.HLE/FileSystem/ContentPath.cs @@ -2,7 +2,6 @@ using LibHac.Ncm; using Ryujinx.Common.Configuration; using System; - using static Ryujinx.HLE.FileSystem.VirtualFileSystem; using Path = System.IO.Path; @@ -10,33 +9,33 @@ namespace Ryujinx.HLE.FileSystem { internal static class ContentPath { - public const string SystemContent = "@SystemContent"; - public const string UserContent = "@UserContent"; - public const string SdCardContent = "@SdCardContent"; - public const string SdCard = "@Sdcard"; - public const string CalibFile = "@CalibFile"; - public const string Safe = "@Safe"; - public const string User = "@User"; - public const string System = "@System"; - public const string Host = "@Host"; - public const string GamecardApp = "@GcApp"; + public const string SystemContent = "@SystemContent"; + public const string UserContent = "@UserContent"; + public const string SdCardContent = "@SdCardContent"; + public const string SdCard = "@Sdcard"; + public const string CalibFile = "@CalibFile"; + public const string Safe = "@Safe"; + public const string User = "@User"; + public const string System = "@System"; + public const string Host = "@Host"; + public const string GamecardApp = "@GcApp"; public const string GamecardContents = "@GcS00000001"; - public const string GamecardUpdate = "@upp"; + public const string GamecardUpdate = "@upp"; public const string RegisteredUpdate = "@RegUpdate"; public const string Nintendo = "Nintendo"; public const string Contents = "Contents"; - public static string GetRealPath(VirtualFileSystem fileSystem, string switchContentPath) + public static string GetRealPath(string switchContentPath) { return switchContentPath switch { SystemContent => Path.Combine(AppDataManager.BaseDirPath, SystemNandPath, Contents), - UserContent => Path.Combine(AppDataManager.BaseDirPath, UserNandPath, Contents), - SdCardContent => Path.Combine(fileSystem.GetSdCardPath(), Nintendo, Contents), - System => Path.Combine(AppDataManager.BaseDirPath, SystemNandPath), - User => Path.Combine(AppDataManager.BaseDirPath, UserNandPath), - _ => throw new NotSupportedException($"Content Path \"`{switchContentPath}`\" is not supported.") + UserContent => Path.Combine(AppDataManager.BaseDirPath, UserNandPath, Contents), + SdCardContent => Path.Combine(GetSdCardPath(), Nintendo, Contents), + System => Path.Combine(AppDataManager.BaseDirPath, SystemNandPath), + User => Path.Combine(AppDataManager.BaseDirPath, UserNandPath), + _ => throw new NotSupportedException($"Content Path \"`{switchContentPath}`\" is not supported."), }; } @@ -45,9 +44,9 @@ namespace Ryujinx.HLE.FileSystem return contentStorageId switch { ContentStorageId.System => SystemContent, - ContentStorageId.User => UserContent, + ContentStorageId.User => UserContent, ContentStorageId.SdCard => SdCardContent, - _ => throw new NotSupportedException($"Content Storage Id \"`{contentStorageId}`\" is not supported.") + _ => throw new NotSupportedException($"Content Storage Id \"`{contentStorageId}`\" is not supported."), }; } @@ -56,9 +55,9 @@ namespace Ryujinx.HLE.FileSystem return storageId switch { StorageId.BuiltInSystem => SystemContent, - StorageId.BuiltInUser => UserContent, - StorageId.SdCard => SdCardContent, - _ => throw new NotSupportedException($"Storage Id \"`{storageId}`\" is not supported.") + StorageId.BuiltInUser => UserContent, + StorageId.SdCard => SdCardContent, + _ => throw new NotSupportedException($"Storage Id \"`{storageId}`\" is not supported."), }; } @@ -67,16 +66,16 @@ namespace Ryujinx.HLE.FileSystem return contentPathString.Split(':')[0] switch { SystemContent or - System => StorageId.BuiltInSystem, + System => StorageId.BuiltInSystem, UserContent or - User => StorageId.BuiltInUser, - SdCardContent => StorageId.SdCard, - Host => StorageId.Host, + User => StorageId.BuiltInUser, + SdCardContent => StorageId.SdCard, + Host => StorageId.Host, GamecardApp or GamecardContents or GamecardUpdate => StorageId.GameCard, - _ => StorageId.None + _ => StorageId.None, }; } } -}
\ No newline at end of file +} diff --git a/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs b/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs index f32dc2d7..d50b80ff 100644 --- a/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs +++ b/src/Ryujinx.HLE/FileSystem/EncryptedFileSystemCreator.cs @@ -23,4 +23,4 @@ namespace Ryujinx.HLE.FileSystem return Result.Success; } } -}
\ No newline at end of file +} diff --git a/src/Ryujinx.HLE/FileSystem/LocationEntry.cs b/src/Ryujinx.HLE/FileSystem/LocationEntry.cs index a60c2896..dd4068aa 100644 --- a/src/Ryujinx.HLE/FileSystem/LocationEntry.cs +++ b/src/Ryujinx.HLE/FileSystem/LocationEntry.cs @@ -4,16 +4,16 @@ namespace Ryujinx.HLE.FileSystem { public struct LocationEntry { - public string ContentPath { get; private set; } - public int Flag { get; private set; } - public ulong TitleId { get; private set; } + public string ContentPath { get; private set; } + public int Flag { get; private set; } + public ulong TitleId { get; private set; } public NcaContentType ContentType { get; private set; } public LocationEntry(string contentPath, int flag, ulong titleId, NcaContentType contentType) { ContentPath = contentPath; - Flag = flag; - TitleId = titleId; + Flag = flag; + TitleId = titleId; ContentType = contentType; } diff --git a/src/Ryujinx.HLE/FileSystem/SystemVersion.cs b/src/Ryujinx.HLE/FileSystem/SystemVersion.cs index a7926d5d..bd64d7f2 100644 --- a/src/Ryujinx.HLE/FileSystem/SystemVersion.cs +++ b/src/Ryujinx.HLE/FileSystem/SystemVersion.cs @@ -5,36 +5,34 @@ namespace Ryujinx.HLE.FileSystem { public class SystemVersion { - public byte Major { get; } - public byte Minor { get; } - public byte Micro { get; } - public byte RevisionMajor { get; } - public byte RevisionMinor { get; } + public byte Major { get; } + public byte Minor { get; } + public byte Micro { get; } + public byte RevisionMajor { get; } + public byte RevisionMinor { get; } public string PlatformString { get; } - public string Hex { get; } - public string VersionString { get; } - public string VersionTitle { get; } + public string Hex { get; } + public string VersionString { get; } + public string VersionTitle { get; } public SystemVersion(Stream systemVersionFile) { - using (BinaryReader reader = new BinaryReader(systemVersionFile)) - { - Major = reader.ReadByte(); - Minor = reader.ReadByte(); - Micro = reader.ReadByte(); + using BinaryReader reader = new(systemVersionFile); + Major = reader.ReadByte(); + Minor = reader.ReadByte(); + Micro = reader.ReadByte(); - reader.ReadByte(); // Padding + reader.ReadByte(); // Padding - RevisionMajor = reader.ReadByte(); - RevisionMinor = reader.ReadByte(); + RevisionMajor = reader.ReadByte(); + RevisionMinor = reader.ReadByte(); - reader.ReadBytes(2); // Padding + reader.ReadBytes(2); // Padding - PlatformString = StringUtils.ReadInlinedAsciiString(reader, 0x20); - Hex = StringUtils.ReadInlinedAsciiString(reader, 0x40); - VersionString = StringUtils.ReadInlinedAsciiString(reader, 0x18); - VersionTitle = StringUtils.ReadInlinedAsciiString(reader, 0x80); - } + PlatformString = StringUtils.ReadInlinedAsciiString(reader, 0x20); + Hex = StringUtils.ReadInlinedAsciiString(reader, 0x40); + VersionString = StringUtils.ReadInlinedAsciiString(reader, 0x18); + VersionTitle = StringUtils.ReadInlinedAsciiString(reader, 0x80); } } -}
\ No newline at end of file +} diff --git a/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs b/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs index 83604b42..807020c6 100644 --- a/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs +++ b/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs @@ -26,14 +26,14 @@ namespace Ryujinx.HLE.FileSystem { public class VirtualFileSystem : IDisposable { - public static string SafeNandPath = Path.Combine(AppDataManager.DefaultNandDir, "safe"); - public static string SystemNandPath = Path.Combine(AppDataManager.DefaultNandDir, "system"); - public static string UserNandPath = Path.Combine(AppDataManager.DefaultNandDir, "user"); + public static readonly string SafeNandPath = Path.Combine(AppDataManager.DefaultNandDir, "safe"); + public static readonly string SystemNandPath = Path.Combine(AppDataManager.DefaultNandDir, "system"); + public static readonly string UserNandPath = Path.Combine(AppDataManager.DefaultNandDir, "user"); - public KeySet KeySet { get; private set; } - public EmulatedGameCard GameCard { get; private set; } - public EmulatedSdCard SdCard { get; private set; } - public ModLoader ModLoader { get; private set; } + public KeySet KeySet { get; private set; } + public EmulatedGameCard GameCard { get; private set; } + public EmulatedSdCard SdCard { get; private set; } + public ModLoader ModLoader { get; private set; } private readonly ConcurrentDictionary<ulong, Stream> _romFsByPid; @@ -85,15 +85,15 @@ namespace Ryujinx.HLE.FileSystem return _romFsByPid[pid]; } - public string GetFullPath(string basePath, string fileName) + public static string GetFullPath(string basePath, string fileName) { if (fileName.StartsWith("//")) { - fileName = fileName.Substring(2); + fileName = fileName[2..]; } else if (fileName.StartsWith('/')) { - fileName = fileName.Substring(1); + fileName = fileName[1..]; } else { @@ -110,10 +110,10 @@ namespace Ryujinx.HLE.FileSystem return fullPath; } - internal string GetSdCardPath() => MakeFullPath(AppDataManager.DefaultSdcardDir); - public string GetNandPath() => MakeFullPath(AppDataManager.DefaultNandDir); + internal static string GetSdCardPath() => MakeFullPath(AppDataManager.DefaultSdcardDir); + public static string GetNandPath() => MakeFullPath(AppDataManager.DefaultNandDir); - public string SwitchPathToSystemPath(string switchPath) + public static string SwitchPathToSystemPath(string switchPath) { string[] parts = switchPath.Split(":"); @@ -125,7 +125,7 @@ namespace Ryujinx.HLE.FileSystem return GetFullPath(MakeFullPath(parts[0]), parts[1]); } - public string SystemPathToSwitchPath(string systemPath) + public static string SystemPathToSwitchPath(string systemPath) { string baseSystemPath = AppDataManager.BaseDirPath + Path.DirectorySeparatorChar; @@ -148,7 +148,7 @@ namespace Ryujinx.HLE.FileSystem return null; } - private string MakeFullPath(string path, bool isDirectory = true) + private static string MakeFullPath(string path, bool isDirectory = true) { // Handles Common Switch Content Paths switch (path) @@ -185,7 +185,7 @@ namespace Ryujinx.HLE.FileSystem public void InitializeFsServer(LibHac.Horizon horizon, out HorizonClient fsServerClient) { - LocalFileSystem serverBaseFs = new LocalFileSystem(AppDataManager.BaseDirPath); + LocalFileSystem serverBaseFs = new(AppDataManager.BaseDirPath); fsServerClient = horizon.CreatePrivilegedHorizonClient(); var fsServer = new FileSystemServer(fsServerClient); @@ -207,7 +207,7 @@ namespace Ryujinx.HLE.FileSystem DeviceOperator = fsServerObjects.DeviceOperator, ExternalKeySet = KeySet.ExternalKeySet, FsCreators = fsServerObjects.FsCreators, - RandomGenerator = randomGenerator + RandomGenerator = randomGenerator, }; FileSystemServerInitializer.InitializeWithConfig(fsServerClient, fsServer, fsServerConfig); @@ -282,16 +282,28 @@ namespace Ryujinx.HLE.FileSystem public static Result FixExtraData(HorizonClient hos) { Result rc = GetSystemSaveList(hos, out List<ulong> systemSaveIds); - if (rc.IsFailure()) return rc; + if (rc.IsFailure()) + { + return rc; + } rc = FixUnindexedSystemSaves(hos, systemSaveIds); - if (rc.IsFailure()) return rc; + if (rc.IsFailure()) + { + return rc; + } rc = FixExtraDataInSpaceId(hos, SaveDataSpaceId.System); - if (rc.IsFailure()) return rc; + if (rc.IsFailure()) + { + return rc; + } rc = FixExtraDataInSpaceId(hos, SaveDataSpaceId.User); - if (rc.IsFailure()) return rc; + if (rc.IsFailure()) + { + return rc; + } return Result.Success; } @@ -303,15 +315,23 @@ namespace Ryujinx.HLE.FileSystem using var iterator = new UniqueRef<SaveDataIterator>(); Result rc = hos.Fs.OpenSaveDataIterator(ref iterator.Ref, spaceId); - if (rc.IsFailure()) return rc; + if (rc.IsFailure()) + { + return rc; + } while (true) { rc = iterator.Get.ReadSaveDataInfo(out long count, info); - if (rc.IsFailure()) return rc; + if (rc.IsFailure()) + { + return rc; + } if (count == 0) + { return Result.Success; + } for (int i = 0; i < count; i++) { @@ -351,7 +371,9 @@ namespace Ryujinx.HLE.FileSystem private static Result CreateSaveDataDirectory(HorizonClient hos, in SaveDataInfo info) { if (info.SpaceId != SaveDataSpaceId.User && info.SpaceId != SaveDataSpaceId.System) + { return Result.Success; + } const string MountName = "SaveDir"; var mountNameU8 = MountName.ToU8Span(); @@ -360,11 +382,15 @@ namespace Ryujinx.HLE.FileSystem { SaveDataSpaceId.System => BisPartitionId.System, SaveDataSpaceId.User => BisPartitionId.User, - _ => throw new ArgumentOutOfRangeException() + _ => throw new ArgumentOutOfRangeException(nameof(info), info.SpaceId, null), }; Result rc = hos.Fs.MountBis(mountNameU8, partitionId); - if (rc.IsFailure()) return rc; + if (rc.IsFailure()) + { + return rc; + } + try { var path = $"{MountName}:/save/{info.SaveDataId:x16}".ToU8Span(); @@ -391,28 +417,38 @@ namespace Ryujinx.HLE.FileSystem var mountName = "system".ToU8Span(); DirectoryHandle handle = default; - List<ulong> localList = new List<ulong>(); + List<ulong> localList = new(); try { Result rc = hos.Fs.MountBis(mountName, BisPartitionId.System); - if (rc.IsFailure()) return rc; + if (rc.IsFailure()) + { + return rc; + } rc = hos.Fs.OpenDirectory(out handle, "system:/save".ToU8Span(), OpenDirectoryMode.All); - if (rc.IsFailure()) return rc; + if (rc.IsFailure()) + { + return rc; + } - DirectoryEntry entry = new DirectoryEntry(); + DirectoryEntry entry = new(); while (true) { rc = hos.Fs.ReadDirectory(out long readCount, SpanHelpers.AsSpan(ref entry), handle); - if (rc.IsFailure()) return rc; + if (rc.IsFailure()) + { + return rc; + } if (readCount == 0) + { break; + } - if (Utf8Parser.TryParse(entry.Name, out ulong saveDataId, out int bytesRead, 'x') && - bytesRead == 16 && (long)saveDataId < 0) + if (Utf8Parser.TryParse(entry.Name, out ulong saveDataId, out int bytesRead, 'x') && bytesRead == 16 && (long)saveDataId < 0) { localList.Add(saveDataId); } @@ -440,7 +476,7 @@ namespace Ryujinx.HLE.FileSystem // Only save data IDs added to SystemExtraDataFixInfo will be fixed. private static Result FixUnindexedSystemSaves(HorizonClient hos, List<ulong> existingSaveIds) { - foreach (var fixInfo in SystemExtraDataFixInfo) + foreach (var fixInfo in _systemExtraDataFixInfo) { if (!existingSaveIds.Contains(fixInfo.StaticSaveDataId)) { @@ -472,7 +508,9 @@ namespace Ryujinx.HLE.FileSystem if (!rc.IsSuccess()) { if (!ResultFs.TargetNotFound.Includes(rc)) + { return rc; + } // We'll reach this point only if the save data directory exists but it's not in the save data indexer. // Creating the save will add it to the indexer while leaving its existing contents intact. @@ -492,7 +530,7 @@ namespace Ryujinx.HLE.FileSystem OwnerId = info.OwnerId, Flags = info.Flags, DataSize = info.DataSize, - JournalSize = info.JournalSize + JournalSize = info.JournalSize, }; // Make a mask for writing the entire extra data @@ -507,9 +545,11 @@ namespace Ryujinx.HLE.FileSystem { wasFixNeeded = true; - Result rc = hos.Fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, info.SpaceId, - info.SaveDataId); - if (rc.IsFailure()) return rc; + Result rc = hos.Fs.Impl.ReadSaveDataFileSystemExtraData(out SaveDataExtraData extraData, info.SpaceId, info.SaveDataId); + if (rc.IsFailure()) + { + return rc; + } // The extra data should have program ID or static save data ID set if it's valid. // We only try to fix the extra data if the info from the save data indexer has a program ID or static save data ID. @@ -543,7 +583,7 @@ namespace Ryujinx.HLE.FileSystem else { // Try to match the system save with one of the known saves - foreach (ExtraDataFixInfo fixInfo in SystemExtraDataFixInfo) + foreach (ExtraDataFixInfo fixInfo in _systemExtraDataFixInfo) { if (extraData.Attribute.StaticSaveDataId == fixInfo.StaticSaveDataId) { @@ -573,7 +613,7 @@ namespace Ryujinx.HLE.FileSystem public long JournalSize; } - private static readonly ExtraDataFixInfo[] SystemExtraDataFixInfo = + private static readonly ExtraDataFixInfo[] _systemExtraDataFixInfo = { new ExtraDataFixInfo() { @@ -581,7 +621,7 @@ namespace Ryujinx.HLE.FileSystem OwnerId = 0x010000000000001F, Flags = SaveDataFlags.KeepAfterResettingSystemSaveDataWithoutUserSaveData, DataSize = 0x10000, - JournalSize = 0x10000 + JournalSize = 0x10000, }, new ExtraDataFixInfo() { @@ -589,12 +629,13 @@ namespace Ryujinx.HLE.FileSystem OwnerId = 0x0100000000001009, Flags = SaveDataFlags.None, DataSize = 0xC000, - JournalSize = 0xC000 - } + JournalSize = 0xC000, + }, }; public void Dispose() { + GC.SuppressFinalize(this); Dispose(true); } |