From d773d5152e685a164a6eb9f419873ef1908364f7 Mon Sep 17 00:00:00 2001
From: Alex Barney <thealexbarney@gmail.com>
Date: Sun, 22 Oct 2023 16:30:46 -0700
Subject: [PATCH] Update to LibHac 0.19.0 (#5831)

* Update to LibHac v0.19.0

- PartitionFileSystem classes now fully match Nintendo's implementation. Current code creating a PartitionFileSystem now need to use the Initialize method.
- Implementing nn::gcsrv and nn::sdmmcsrv now means the FS server now uses that abstraction instead of the old one where we passed in an IDeviceOperator.

* Add GetFileSystemAttribute
---
 Directory.Packages.props                      |  2 +-
 src/Ryujinx.Ava/Common/ApplicationHelper.cs   |  6 ++++--
 .../DownloadableContentManagerViewModel.cs    |  6 ++++--
 .../UI/ViewModels/TitleUpdateViewModel.cs     |  4 +++-
 src/Ryujinx.HLE/FileSystem/ContentManager.cs  | 11 ++++++-----
 .../FileSystem/VirtualFileSystem.cs           |  9 +++++----
 src/Ryujinx.HLE/HOS/ModLoader.cs              |  4 +++-
 .../FileSystemProxy/FileSystemProxyHelper.cs  |  7 +++++--
 .../Fs/FileSystemProxy/IFileSystem.cs         | 11 +++++++++++
 .../HOS/Services/Fs/IFileSystemProxy.cs       |  5 ++++-
 .../PartitionFileSystemExtensions.cs          |  9 +++++++--
 .../Loaders/Processes/ProcessLoader.cs        |  3 ++-
 .../Loaders/Processes/ProcessLoaderHelper.cs  |  4 ++--
 src/Ryujinx.Ui.Common/App/ApplicationData.cs  |  6 ++++--
 .../App/ApplicationLibrary.cs                 | 19 ++++++++++++-------
 .../Ui/Widgets/GameTableContextMenu.cs        |  6 ++++--
 src/Ryujinx/Ui/Windows/DlcWindow.cs           |  6 ++++--
 src/Ryujinx/Ui/Windows/TitleUpdateWindow.cs   |  3 ++-
 18 files changed, 83 insertions(+), 38 deletions(-)

diff --git a/Directory.Packages.props b/Directory.Packages.props
index 6fdaafddca..4fd079af69 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -18,7 +18,7 @@
     <PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
     <PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
     <PackageVersion Include="jp2masa.Avalonia.Flexbox" Version="0.3.0-beta.4" />
-    <PackageVersion Include="LibHac" Version="0.18.0" />
+    <PackageVersion Include="LibHac" Version="0.19.0" />
     <PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
     <PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" />
     <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
diff --git a/src/Ryujinx.Ava/Common/ApplicationHelper.cs b/src/Ryujinx.Ava/Common/ApplicationHelper.cs
index b8cd06f3d5..91ca8f4d55 100644
--- a/src/Ryujinx.Ava/Common/ApplicationHelper.cs
+++ b/src/Ryujinx.Ava/Common/ApplicationHelper.cs
@@ -173,7 +173,7 @@ namespace Ryujinx.Ava.Common
                 string extension = Path.GetExtension(titleFilePath).ToLower();
                 if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci")
                 {
-                    PartitionFileSystem pfs;
+                    IFileSystem pfs;
 
                     if (extension == ".xci")
                     {
@@ -181,7 +181,9 @@ namespace Ryujinx.Ava.Common
                     }
                     else
                     {
-                        pfs = new PartitionFileSystem(file.AsStorage());
+                        var pfsTemp = new PartitionFileSystem();
+                        pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure();
+                        pfs = pfsTemp;
                     }
 
                     foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
diff --git a/src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs
index b88bd3d9c1..cdecae77dd 100644
--- a/src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs
+++ b/src/Ryujinx.Ava/UI/ViewModels/DownloadableContentManagerViewModel.cs
@@ -126,7 +126,8 @@ namespace Ryujinx.Ava.UI.ViewModels
                 {
                     using FileStream containerFile = File.OpenRead(downloadableContentContainer.ContainerPath);
 
-                    PartitionFileSystem partitionFileSystem = new(containerFile.AsStorage());
+                    PartitionFileSystem partitionFileSystem = new();
+                    partitionFileSystem.Initialize(containerFile.AsStorage()).ThrowIfFailure();
 
                     _virtualFileSystem.ImportTickets(partitionFileSystem);
 
@@ -232,7 +233,8 @@ namespace Ryujinx.Ava.UI.ViewModels
 
             using FileStream containerFile = File.OpenRead(path);
 
-            PartitionFileSystem partitionFileSystem = new(containerFile.AsStorage());
+            PartitionFileSystem partitionFileSystem = new();
+            partitionFileSystem.Initialize(containerFile.AsStorage()).ThrowIfFailure();
             bool containsDownloadableContent = false;
 
             _virtualFileSystem.ImportTickets(partitionFileSystem);
diff --git a/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs
index dd0b92a512..5090a8c70a 100644
--- a/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs
+++ b/src/Ryujinx.Ava/UI/ViewModels/TitleUpdateViewModel.cs
@@ -170,7 +170,9 @@ namespace Ryujinx.Ava.UI.ViewModels
 
                 try
                 {
-                    (Nca patchNca, Nca controlNca) = ApplicationLibrary.GetGameUpdateDataFromPartition(VirtualFileSystem, new PartitionFileSystem(file.AsStorage()), TitleId.ToString("x16"), 0);
+                    var pfs = new PartitionFileSystem();
+                    pfs.Initialize(file.AsStorage()).ThrowIfFailure();
+                    (Nca patchNca, Nca controlNca) = ApplicationLibrary.GetGameUpdateDataFromPartition(VirtualFileSystem, pfs, TitleId.ToString("x16"), 0);
 
                     if (controlNca != null && patchNca != null)
                     {
diff --git a/src/Ryujinx.HLE/FileSystem/ContentManager.cs b/src/Ryujinx.HLE/FileSystem/ContentManager.cs
index 646808e783..8ade34a8b4 100644
--- a/src/Ryujinx.HLE/FileSystem/ContentManager.cs
+++ b/src/Ryujinx.HLE/FileSystem/ContentManager.cs
@@ -238,7 +238,8 @@ namespace Ryujinx.HLE.FileSystem
                 if (!mergedToContainer)
                 {
                     using FileStream fileStream = File.OpenRead(containerPath);
-                    using PartitionFileSystem partitionFileSystem = new(fileStream.AsStorage());
+                    using PartitionFileSystem partitionFileSystem = new();
+                    partitionFileSystem.Initialize(fileStream.AsStorage()).ThrowIfFailure();
 
                     _virtualFileSystem.ImportTickets(partitionFileSystem);
                 }
@@ -259,16 +260,16 @@ namespace Ryujinx.HLE.FileSystem
             {
                 var file = new FileStream(aoc.ContainerPath, FileMode.Open, FileAccess.Read);
                 using var ncaFile = new UniqueRef<IFile>();
-                PartitionFileSystem pfs;
 
                 switch (Path.GetExtension(aoc.ContainerPath))
                 {
                     case ".xci":
-                        pfs = new Xci(_virtualFileSystem.KeySet, file.AsStorage()).OpenPartition(XciPartitionType.Secure);
-                        pfs.OpenFile(ref ncaFile.Ref, aoc.NcaPath.ToU8Span(), OpenMode.Read);
+                        var xci = new Xci(_virtualFileSystem.KeySet, file.AsStorage()).OpenPartition(XciPartitionType.Secure);
+                        xci.OpenFile(ref ncaFile.Ref, aoc.NcaPath.ToU8Span(), OpenMode.Read);
                         break;
                     case ".nsp":
-                        pfs = new PartitionFileSystem(file.AsStorage());
+                        var pfs = new PartitionFileSystem();
+                        pfs.Initialize(file.AsStorage());
                         pfs.OpenFile(ref ncaFile.Ref, aoc.NcaPath.ToU8Span(), OpenMode.Read);
                         break;
                     default:
diff --git a/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs b/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs
index 807020c607..eaf481dd78 100644
--- a/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs
+++ b/src/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs
@@ -7,6 +7,7 @@ using LibHac.Fs.Shim;
 using LibHac.FsSrv;
 using LibHac.FsSystem;
 using LibHac.Ncm;
+using LibHac.Sdmmc;
 using LibHac.Spl;
 using LibHac.Tools.Es;
 using LibHac.Tools.Fs;
@@ -32,7 +33,7 @@ namespace Ryujinx.HLE.FileSystem
 
         public KeySet KeySet { get; private set; }
         public EmulatedGameCard GameCard { get; private set; }
-        public EmulatedSdCard SdCard { get; private set; }
+        public SdmmcApi SdCard { get; private set; }
         public ModLoader ModLoader { get; private set; }
 
         private readonly ConcurrentDictionary<ulong, Stream> _romFsByPid;
@@ -198,15 +199,15 @@ namespace Ryujinx.HLE.FileSystem
             fsServerObjects.FsCreators.EncryptedFileSystemCreator = new EncryptedFileSystemCreator();
 
             GameCard = fsServerObjects.GameCard;
-            SdCard = fsServerObjects.SdCard;
+            SdCard = fsServerObjects.Sdmmc;
 
-            SdCard.SetSdCardInsertionStatus(true);
+            SdCard.SetSdCardInserted(true);
 
             var fsServerConfig = new FileSystemServerConfig
             {
-                DeviceOperator = fsServerObjects.DeviceOperator,
                 ExternalKeySet = KeySet.ExternalKeySet,
                 FsCreators = fsServerObjects.FsCreators,
+                StorageDeviceManagerFactory = fsServerObjects.StorageDeviceManagerFactory,
                 RandomGenerator = randomGenerator,
             };
 
diff --git a/src/Ryujinx.HLE/HOS/ModLoader.cs b/src/Ryujinx.HLE/HOS/ModLoader.cs
index 6706006c3e..834bc05951 100644
--- a/src/Ryujinx.HLE/HOS/ModLoader.cs
+++ b/src/Ryujinx.HLE/HOS/ModLoader.cs
@@ -533,7 +533,9 @@ namespace Ryujinx.HLE.HOS
 
             Logger.Info?.Print(LogClass.ModLoader, "Using replacement ExeFS partition");
 
-            exefs = new PartitionFileSystem(mods.ExefsContainers[0].Path.OpenRead().AsStorage());
+            var pfs = new PartitionFileSystem();
+            pfs.Initialize(mods.ExefsContainers[0].Path.OpenRead().AsStorage()).ThrowIfFailure();
+            exefs = pfs;
 
             return true;
         }
diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs
index 599025e3b5..1ef52a00d2 100644
--- a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs
@@ -26,7 +26,9 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
             try
             {
                 LocalStorage storage = new(pfsPath, FileAccess.Read, FileMode.Open);
-                using SharedRef<LibHac.Fs.Fsa.IFileSystem> nsp = new(new PartitionFileSystem(storage));
+                var pfs = new PartitionFileSystem();
+                using SharedRef<LibHac.Fs.Fsa.IFileSystem> nsp = new(pfs);
+                pfs.Initialize(storage).ThrowIfFailure();
 
                 ImportTitleKeysFromNsp(nsp.Get, context.Device.System.KeySet);
 
@@ -90,7 +92,8 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
 
                 try
                 {
-                    PartitionFileSystem nsp = new(pfsFile.AsStorage());
+                    PartitionFileSystem nsp = new();
+                    nsp.Initialize(pfsFile.AsStorage()).ThrowIfFailure();
 
                     ImportTitleKeysFromNsp(nsp, context.Device.System.KeySet);
 
diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs
index 4c5c562407..66020d57b6 100644
--- a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs
@@ -1,6 +1,7 @@
 using LibHac;
 using LibHac.Common;
 using LibHac.Fs;
+using LibHac.Fs.Fsa;
 using Path = LibHac.FsSrv.Sf.Path;
 
 namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
@@ -202,6 +203,16 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
             return (ResultCode)result.Value;
         }
 
+        [CommandCmif(16)]
+        public ResultCode GetFileSystemAttribute(ServiceCtx context)
+        {
+            Result result = _fileSystem.Get.GetFileSystemAttribute(out FileSystemAttribute attribute);
+
+            context.ResponseData.Write(SpanHelpers.AsReadOnlyByteSpan(in attribute));
+
+            return (ResultCode)result.Value;
+        }
+
         protected override void Dispose(bool isDisposing)
         {
             if (isDisposing)
diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs
index 644e1a17ad..24dd1e9be8 100644
--- a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs
@@ -1380,7 +1380,10 @@ namespace Ryujinx.HLE.HOS.Services.Fs
         [CommandCmif(1016)]
         public ResultCode FlushAccessLogOnSdCard(ServiceCtx context)
         {
-            return (ResultCode)_baseFileSystemProxy.Get.FlushAccessLogOnSdCard().Value;
+            // Logging the access log to the SD card isn't implemented, meaning this function will be a no-op since
+            // there's nothing to flush. Return success until it's implemented.
+            // return (ResultCode)_baseFileSystemProxy.Get.FlushAccessLogOnSdCard().Value;
+            return ResultCode.Success;
         }
 
         [CommandCmif(1017)]
diff --git a/src/Ryujinx.HLE/Loaders/Processes/Extensions/PartitionFileSystemExtensions.cs b/src/Ryujinx.HLE/Loaders/Processes/Extensions/PartitionFileSystemExtensions.cs
index 6de99131e5..50f7d58534 100644
--- a/src/Ryujinx.HLE/Loaders/Processes/Extensions/PartitionFileSystemExtensions.cs
+++ b/src/Ryujinx.HLE/Loaders/Processes/Extensions/PartitionFileSystemExtensions.cs
@@ -20,7 +20,11 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
         private static readonly DownloadableContentJsonSerializerContext _contentSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
         private static readonly TitleUpdateMetadataJsonSerializerContext _titleSerializerContext = new(JsonHelper.GetDefaultSerializerOptions());
 
-        internal static (bool, ProcessResult) TryLoad(this PartitionFileSystem partitionFileSystem, Switch device, string path, out string errorMessage)
+        internal static (bool, ProcessResult) TryLoad<TMetaData, TFormat, THeader, TEntry>(this PartitionFileSystemCore<TMetaData, TFormat, THeader, TEntry> partitionFileSystem, Switch device, string path, out string errorMessage)
+            where TMetaData : PartitionFileSystemMetaCore<TFormat, THeader, TEntry>, new()
+            where TFormat : IPartitionFileSystemFormat
+            where THeader : unmanaged, IPartitionFileSystemHeader
+            where TEntry : unmanaged, IPartitionFileSystemEntry
         {
             errorMessage = null;
 
@@ -91,7 +95,8 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
                         string updatePath = JsonHelper.DeserializeFromFile(titleUpdateMetadataPath, _titleSerializerContext.TitleUpdateMetadata).Selected;
                         if (File.Exists(updatePath))
                         {
-                            PartitionFileSystem updatePartitionFileSystem = new(new FileStream(updatePath, FileMode.Open, FileAccess.Read).AsStorage());
+                            PartitionFileSystem updatePartitionFileSystem = new();
+                            updatePartitionFileSystem.Initialize(new FileStream(updatePath, FileMode.Open, FileAccess.Read).AsStorage()).ThrowIfFailure();
 
                             device.Configuration.VirtualFileSystem.ImportTickets(updatePartitionFileSystem);
 
diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs
index 51cbb6f993..220b868dbc 100644
--- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs
+++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs
@@ -69,7 +69,8 @@ namespace Ryujinx.HLE.Loaders.Processes
         public bool LoadNsp(string path)
         {
             FileStream file = new(path, FileMode.Open, FileAccess.Read);
-            PartitionFileSystem partitionFileSystem = new(file.AsStorage());
+            PartitionFileSystem partitionFileSystem = new();
+            partitionFileSystem.Initialize(file.AsStorage()).ThrowIfFailure();
 
             (bool success, ProcessResult processResult) = partitionFileSystem.TryLoad(_device, path, out string errorMessage);
 
diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs
index 292a5c122e..c229b1742b 100644
--- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs
+++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs
@@ -1,8 +1,8 @@
 using LibHac.Account;
 using LibHac.Common;
 using LibHac.Fs;
+using LibHac.Fs.Fsa;
 using LibHac.Fs.Shim;
-using LibHac.FsSystem;
 using LibHac.Loader;
 using LibHac.Ncm;
 using LibHac.Ns;
@@ -33,7 +33,7 @@ namespace Ryujinx.HLE.Loaders.Processes
         // TODO: Remove this workaround when ASLR is implemented.
         private const ulong CodeStartOffset = 0x500000UL;
 
-        public static LibHac.Result RegisterProgramMapInfo(Switch device, PartitionFileSystem partitionFileSystem)
+        public static LibHac.Result RegisterProgramMapInfo(Switch device, IFileSystem partitionFileSystem)
         {
             ulong applicationId = 0;
             int programCount = 0;
diff --git a/src/Ryujinx.Ui.Common/App/ApplicationData.cs b/src/Ryujinx.Ui.Common/App/ApplicationData.cs
index e6130bdac8..1be883ee1a 100644
--- a/src/Ryujinx.Ui.Common/App/ApplicationData.cs
+++ b/src/Ryujinx.Ui.Common/App/ApplicationData.cs
@@ -65,7 +65,7 @@ namespace Ryujinx.Ui.App.Common
 
             if (extension is ".nsp" or ".xci")
             {
-                PartitionFileSystem pfs;
+                IFileSystem pfs;
 
                 if (extension == ".xci")
                 {
@@ -75,7 +75,9 @@ namespace Ryujinx.Ui.App.Common
                 }
                 else
                 {
-                    pfs = new PartitionFileSystem(file.AsStorage());
+                    var pfsTemp = new PartitionFileSystem();
+                    pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure();
+                    pfs = pfsTemp;
                 }
 
                 foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
diff --git a/src/Ryujinx.Ui.Common/App/ApplicationLibrary.cs b/src/Ryujinx.Ui.Common/App/ApplicationLibrary.cs
index 36b2b727d4..2f688126a4 100644
--- a/src/Ryujinx.Ui.Common/App/ApplicationLibrary.cs
+++ b/src/Ryujinx.Ui.Common/App/ApplicationLibrary.cs
@@ -174,7 +174,7 @@ namespace Ryujinx.Ui.App.Common
                         {
                             try
                             {
-                                PartitionFileSystem pfs;
+                                IFileSystem pfs;
 
                                 bool isExeFs = false;
 
@@ -186,7 +186,9 @@ namespace Ryujinx.Ui.App.Common
                                 }
                                 else
                                 {
-                                    pfs = new PartitionFileSystem(file.AsStorage());
+                                    var pfsTemp = new PartitionFileSystem();
+                                    pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure();
+                                    pfs = pfsTemp;
 
                                     // If the NSP doesn't have a main NCA, decrement the number of applications found and then continue to the next application.
                                     bool hasMainNca = false;
@@ -500,7 +502,7 @@ namespace Ryujinx.Ui.App.Common
             ApplicationCountUpdated?.Invoke(null, e);
         }
 
-        private void GetControlFsAndTitleId(PartitionFileSystem pfs, out IFileSystem controlFs, out string titleId)
+        private void GetControlFsAndTitleId(IFileSystem pfs, out IFileSystem controlFs, out string titleId)
         {
             (_, _, Nca controlNca) = GetGameData(_virtualFileSystem, pfs, 0);
 
@@ -563,7 +565,7 @@ namespace Ryujinx.Ui.App.Common
                     {
                         try
                         {
-                            PartitionFileSystem pfs;
+                            IFileSystem pfs;
 
                             bool isExeFs = false;
 
@@ -575,7 +577,9 @@ namespace Ryujinx.Ui.App.Common
                             }
                             else
                             {
-                                pfs = new PartitionFileSystem(file.AsStorage());
+                                var pfsTemp = new PartitionFileSystem();
+                                pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure();
+                                pfs = pfsTemp;
 
                                 foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*"))
                                 {
@@ -827,7 +831,7 @@ namespace Ryujinx.Ui.App.Common
             return false;
         }
 
-        public static (Nca main, Nca patch, Nca control) GetGameData(VirtualFileSystem fileSystem, PartitionFileSystem pfs, int programIndex)
+        public static (Nca main, Nca patch, Nca control) GetGameData(VirtualFileSystem fileSystem, IFileSystem pfs, int programIndex)
         {
             Nca mainNca = null;
             Nca patchNca = null;
@@ -931,7 +935,8 @@ namespace Ryujinx.Ui.App.Common
                     if (File.Exists(updatePath))
                     {
                         FileStream file = new(updatePath, FileMode.Open, FileAccess.Read);
-                        PartitionFileSystem nsp = new(file.AsStorage());
+                        PartitionFileSystem nsp = new();
+                        nsp.Initialize(file.AsStorage()).ThrowIfFailure();
 
                         return GetGameUpdateDataFromPartition(fileSystem, nsp, titleIdBase.ToString("x16"), programIndex);
                     }
diff --git a/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs b/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs
index ea60421f8f..5af181b083 100644
--- a/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs
+++ b/src/Ryujinx/Ui/Widgets/GameTableContextMenu.cs
@@ -211,7 +211,7 @@ namespace Ryujinx.Ui.Widgets
                         (System.IO.Path.GetExtension(_titleFilePath).ToLower() == ".pfs0") ||
                         (System.IO.Path.GetExtension(_titleFilePath).ToLower() == ".xci"))
                     {
-                        PartitionFileSystem pfs;
+                        IFileSystem pfs;
 
                         if (System.IO.Path.GetExtension(_titleFilePath) == ".xci")
                         {
@@ -221,7 +221,9 @@ namespace Ryujinx.Ui.Widgets
                         }
                         else
                         {
-                            pfs = new PartitionFileSystem(file.AsStorage());
+                            var pfsTemp = new PartitionFileSystem();
+                            pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure();
+                            pfs = pfsTemp;
                         }
 
                         foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca"))
diff --git a/src/Ryujinx/Ui/Windows/DlcWindow.cs b/src/Ryujinx/Ui/Windows/DlcWindow.cs
index 74aef00f46..9f7179467b 100644
--- a/src/Ryujinx/Ui/Windows/DlcWindow.cs
+++ b/src/Ryujinx/Ui/Windows/DlcWindow.cs
@@ -88,7 +88,8 @@ namespace Ryujinx.Ui.Windows
 
                     using FileStream containerFile = File.OpenRead(dlcContainer.ContainerPath);
 
-                    PartitionFileSystem pfs = new(containerFile.AsStorage());
+                    PartitionFileSystem pfs = new();
+                    pfs.Initialize(containerFile.AsStorage()).ThrowIfFailure();
 
                     _virtualFileSystem.ImportTickets(pfs);
 
@@ -153,7 +154,8 @@ namespace Ryujinx.Ui.Windows
 
                     using FileStream containerFile = File.OpenRead(containerPath);
 
-                    PartitionFileSystem pfs = new(containerFile.AsStorage());
+                    PartitionFileSystem pfs = new();
+                    pfs.Initialize(containerFile.AsStorage()).ThrowIfFailure();
                     bool containsDlc = false;
 
                     _virtualFileSystem.ImportTickets(pfs);
diff --git a/src/Ryujinx/Ui/Windows/TitleUpdateWindow.cs b/src/Ryujinx/Ui/Windows/TitleUpdateWindow.cs
index 044f7e95a7..51918eeab0 100644
--- a/src/Ryujinx/Ui/Windows/TitleUpdateWindow.cs
+++ b/src/Ryujinx/Ui/Windows/TitleUpdateWindow.cs
@@ -90,7 +90,8 @@ namespace Ryujinx.Ui.Windows
             {
                 using FileStream file = new(path, FileMode.Open, FileAccess.Read);
 
-                PartitionFileSystem nsp = new(file.AsStorage());
+                PartitionFileSystem nsp = new();
+                nsp.Initialize(file.AsStorage()).ThrowIfFailure();
 
                 try
                 {