From 36f00985d3191ebd6ea909ddc4ed447ebdbf51b5 Mon Sep 17 00:00:00 2001
From: Alex Barney <thealexbarney@gmail.com>
Date: Wed, 23 Nov 2022 10:32:35 -0700
Subject: [PATCH] Update to LibHac 0.17.0 (#3878)

* Update to LibHac 0.17.0

* Don't clear SD card saves when starting the emulator

This was an old workaround for errors that happened when a user's SD card encryption seed changed. SD card saves have been unencrypted for over a year, so we should be fine to remove the workaround.
---
 Ryujinx.HLE/FileSystem/VirtualFileSystem.cs   |  9 +++++---
 Ryujinx.HLE/HOS/ApplicationLoader.cs          |  2 +-
 Ryujinx.HLE/HOS/LibHacHorizonManager.cs       | 23 -------------------
 .../HOS/Services/Fs/IDeviceOperator.cs        |  5 ++--
 .../HOS/Services/Fs/IFileSystemProxy.cs       | 16 +++++++++++--
 Ryujinx.HLE/Ryujinx.HLE.csproj                |  2 +-
 6 files changed, 25 insertions(+), 32 deletions(-)

diff --git a/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs b/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs
index 001a1f5f..c958c6e8 100644
--- a/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs
+++ b/Ryujinx.HLE/FileSystem/VirtualFileSystem.cs
@@ -172,9 +172,11 @@ namespace Ryujinx.HLE.FileSystem
             fsServerClient = horizon.CreatePrivilegedHorizonClient();
             var fsServer = new FileSystemServer(fsServerClient);
 
-            DefaultFsServerObjects fsServerObjects = DefaultFsServerObjects.GetDefaultEmulatedCreators(serverBaseFs, KeySet, fsServer);
+            RandomDataGenerator randomGenerator = buffer => Random.Shared.NextBytes(buffer);
 
-            // Use our own encrypted fs creator that always uses all-zero keys
+            DefaultFsServerObjects fsServerObjects = DefaultFsServerObjects.GetDefaultEmulatedCreators(serverBaseFs, KeySet, fsServer, randomGenerator);
+
+            // Use our own encrypted fs creator that doesn't actually do any encryption
             fsServerObjects.FsCreators.EncryptedFileSystemCreator = new EncryptedFileSystemCreator();
 
             GameCard = fsServerObjects.GameCard;
@@ -186,7 +188,8 @@ namespace Ryujinx.HLE.FileSystem
             {
                 DeviceOperator = fsServerObjects.DeviceOperator,
                 ExternalKeySet = KeySet.ExternalKeySet,
-                FsCreators = fsServerObjects.FsCreators
+                FsCreators = fsServerObjects.FsCreators,
+                RandomGenerator = randomGenerator
             };
 
             FileSystemServerInitializer.InitializeWithConfig(fsServerClient, fsServer, fsServerConfig);
diff --git a/Ryujinx.HLE/HOS/ApplicationLoader.cs b/Ryujinx.HLE/HOS/ApplicationLoader.cs
index 41d487eb..199da37a 100644
--- a/Ryujinx.HLE/HOS/ApplicationLoader.cs
+++ b/Ryujinx.HLE/HOS/ApplicationLoader.cs
@@ -850,7 +850,7 @@ namespace Ryujinx.HLE.HOS
             for (int i = 0; i < programCount; i++)
             {
                 mapInfo[i].ProgramId = new ProgramId(applicationId + (uint)i);
-                mapInfo[i].MainProgramId = new ProgramId(applicationId);
+                mapInfo[i].MainProgramId = new ApplicationId(applicationId);
                 mapInfo[i].ProgramIndex = (byte)i;
             }
 
diff --git a/Ryujinx.HLE/HOS/LibHacHorizonManager.cs b/Ryujinx.HLE/HOS/LibHacHorizonManager.cs
index 35e5c6e9..8fde5dd6 100644
--- a/Ryujinx.HLE/HOS/LibHacHorizonManager.cs
+++ b/Ryujinx.HLE/HOS/LibHacHorizonManager.cs
@@ -60,8 +60,6 @@ namespace Ryujinx.HLE.HOS
             virtualFileSystem.InitializeFsServer(Server, out var fsClient);
 
             FsClient = fsClient;
-
-            CleanSdCardDirectory();
         }
 
         public void InitializeSystemClients()
@@ -78,27 +76,6 @@ namespace Ryujinx.HLE.HOS
             ApplicationClient = Server.CreateHorizonClient(new ProgramLocation(programId, StorageId.BuiltInUser), npdm.FsAccessControlData, npdm.FsAccessControlDescriptor);
         }
 
-        // This function was added to avoid errors that come from a user's keys or SD encryption seed changing.
-        // Catching these errors and recreating the file ended up not working because of the different ways
-        // applications respond to a file suddenly containing all zeros or having a length of zero.
-        // Clearing the SD card save directory was determined to be the best option for the moment since
-        // the saves on the SD card are meant as caches that can be deleted at any time.
-        private void CleanSdCardDirectory()
-        {
-            Result rc = RyujinxClient.Fs.MountSdCard("sdcard".ToU8Span());
-            if (rc.IsFailure()) return;
-
-            try
-            {
-                RyujinxClient.Fs.CleanDirectoryRecursively("sdcard:/Nintendo/save".ToU8Span()).IgnoreResult();
-                RyujinxClient.Fs.DeleteDirectoryRecursively("sdcard:/save".ToU8Span()).IgnoreResult();
-            }
-            finally
-            {
-                RyujinxClient.Fs.Unmount("sdcard".ToU8Span());
-            }
-        }
-
         private static AccessControlBits.Bits AccountFsPermissions => AccessControlBits.Bits.SystemSaveData |
                                                                       AccessControlBits.Bits.GameCard |
                                                                       AccessControlBits.Bits.SaveDataMeta |
diff --git a/Ryujinx.HLE/HOS/Services/Fs/IDeviceOperator.cs b/Ryujinx.HLE/HOS/Services/Fs/IDeviceOperator.cs
index 07ade0c6..f069fa3e 100644
--- a/Ryujinx.HLE/HOS/Services/Fs/IDeviceOperator.cs
+++ b/Ryujinx.HLE/HOS/Services/Fs/IDeviceOperator.cs
@@ -1,6 +1,7 @@
 using LibHac;
 using LibHac.Common;
-using LibHac.Fs;
+
+using GameCardHandle = System.UInt32;
 
 namespace Ryujinx.HLE.HOS.Services.Fs
 {
@@ -41,7 +42,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
         {
             Result result = _baseOperator.Get.GetGameCardHandle(out GameCardHandle handle);
 
-            context.ResponseData.Write(handle.Value);
+            context.ResponseData.Write(handle);
 
             return (ResultCode)result.Value;
         }
diff --git a/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs b/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs
index 2ec45aa5..970aab95 100644
--- a/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs
+++ b/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs
@@ -19,6 +19,7 @@ using static Ryujinx.HLE.Utilities.StringUtils;
 using IFileSystem = LibHac.FsSrv.Sf.IFileSystem;
 using IStorage = LibHac.FsSrv.Sf.IStorage;
 using RightsId = LibHac.Fs.RightsId;
+using GameCardHandle = System.UInt32;
 
 namespace Ryujinx.HLE.HOS.Services.Fs
 {
@@ -239,7 +240,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
         // OpenGameCardStorage(u32 handle, u32 partitionId) -> object<nn::fssrv::sf::IStorage>
         public ResultCode OpenGameCardStorage(ServiceCtx context)
         {
-            GameCardHandle handle = new GameCardHandle(context.RequestData.ReadInt32());
+            GameCardHandle handle = context.RequestData.ReadUInt32();
             GameCardPartitionRaw partitionId = (GameCardPartitionRaw)context.RequestData.ReadInt32();
             using var storage = new SharedRef<IStorage>();
 
@@ -255,7 +256,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs
         // OpenGameCardFileSystem(u32 handle, u32 partitionId) -> object<nn::fssrv::sf::IFileSystem>
         public ResultCode OpenGameCardFileSystem(ServiceCtx context)
         {
-            GameCardHandle handle = new GameCardHandle(context.RequestData.ReadInt32());
+            GameCardHandle handle = context.RequestData.ReadUInt32();
             GameCardPartition partitionId = (GameCardPartition)context.RequestData.ReadInt32();
             using var fileSystem = new SharedRef<IFileSystem>();
 
@@ -315,6 +316,17 @@ namespace Ryujinx.HLE.HOS.Services.Fs
             return (ResultCode)_baseFileSystemProxy.Get.CreateSaveDataFileSystemWithHashSalt(in attribute, in creationInfo, in metaCreateInfo, in hashSalt).Value;
         }
 
+        [CommandHipc(37)] // 14.0.0+
+        // CreateSaveDataFileSystemWithCreationInfo2(buffer<nn::fs::SaveDataCreationInfo2, 25> creationInfo) -> ()
+        public ResultCode CreateSaveDataFileSystemWithCreationInfo2(ServiceCtx context)
+        {
+            byte[] creationInfoBuffer = new byte[context.Request.SendBuff[0].Size];
+            context.Memory.Read(context.Request.SendBuff[0].Position, creationInfoBuffer);
+            ref readonly SaveDataCreationInfo2 creationInfo = ref SpanHelpers.AsReadOnlyStruct<SaveDataCreationInfo2>(creationInfoBuffer);
+
+            return (ResultCode)_baseFileSystemProxy.Get.CreateSaveDataFileSystemWithCreationInfo2(in creationInfo).Value;
+        }
+
         [CommandHipc(51)]
         // OpenSaveDataFileSystem(u8 spaceId, nn::fs::SaveDataAttribute attribute) -> object<nn::fssrv::sf::IFileSystem> saveDataFs
         public ResultCode OpenSaveDataFileSystem(ServiceCtx context)
diff --git a/Ryujinx.HLE/Ryujinx.HLE.csproj b/Ryujinx.HLE/Ryujinx.HLE.csproj
index bdcbaca8..1ec92a44 100644
--- a/Ryujinx.HLE/Ryujinx.HLE.csproj
+++ b/Ryujinx.HLE/Ryujinx.HLE.csproj
@@ -22,7 +22,7 @@
 
   <ItemGroup>
     <PackageReference Include="Concentus" Version="1.1.7" />
-    <PackageReference Include="LibHac" Version="0.16.1" />
+    <PackageReference Include="LibHac" Version="0.17.0" />
     <PackageReference Include="MsgPack.Cli" Version="1.0.1" />
     <PackageReference Include="SixLabors.ImageSharp" Version="1.0.4" />
     <PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />