diff --git a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs index 2b0f06dda7..01126e72e2 100644 --- a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs +++ b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs @@ -154,5 +154,15 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy } } } + + public static Result ReadFsPath(out FsPath path, ServiceCtx context, int index = 0) + { + long position = context.Request.SendBuff[index].Position; + long size = context.Request.SendBuff[index].Size; + + byte[] pathBytes = context.Memory.ReadBytes(position, size); + + return FsPath.FromSpan(out path, pathBytes); + } } } diff --git a/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs b/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs index 3811101998..9b3da35f35 100644 --- a/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs +++ b/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs @@ -3,13 +3,14 @@ using LibHac.Fs; using LibHac.FsService; using LibHac.FsSystem; using LibHac.FsSystem.NcaUtils; +using LibHac.Ncm; +using Ryujinx.Common; using Ryujinx.Common.Logging; -using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy; using System.IO; -using static Ryujinx.HLE.FileSystem.VirtualFileSystem; using static Ryujinx.HLE.Utilities.StringUtils; +using StorageId = Ryujinx.HLE.FileSystem.StorageId; namespace Ryujinx.HLE.HOS.Services.Fs { @@ -90,29 +91,13 @@ namespace Ryujinx.HLE.HOS.Services.Fs // OpenBisFileSystem(nn::fssrv::sf::Partition partitionID, buffer, 0x19, 0x301>) -> object Bis public ResultCode OpenBisFileSystem(ServiceCtx context) { - int bisPartitionId = context.RequestData.ReadInt32(); - string partitionString = ReadUtf8String(context); - string bisPartitionPath = string.Empty; + BisPartitionId bisPartitionId = (BisPartitionId)context.RequestData.ReadInt32(); - switch (bisPartitionId) - { - case 29: - bisPartitionPath = SafeNandPath; - break; - case 30: - case 31: - bisPartitionPath = SystemNandPath; - break; - case 32: - bisPartitionPath = UserNandPath; - break; - default: - return ResultCode.InvalidInput; - } + Result rc = FileSystemProxyHelper.ReadFsPath(out FsPath path, context); + if (rc.IsFailure()) return (ResultCode)rc.Value; - string fullPath = context.Device.FileSystem.GetFullPartitionPath(bisPartitionPath); - - LocalFileSystem fileSystem = new LocalFileSystem(fullPath); + rc = _baseFileSystemProxy.OpenBisFileSystem(out LibHac.Fs.IFileSystem fileSystem, ref path, bisPartitionId); + if (rc.IsFailure()) return (ResultCode)rc.Value; MakeObject(context, new FileSystemProxy.IFileSystem(fileSystem)); @@ -123,15 +108,69 @@ namespace Ryujinx.HLE.HOS.Services.Fs // OpenSdCardFileSystem() -> object public ResultCode OpenSdCardFileSystem(ServiceCtx context) { - string sdCardPath = context.Device.FileSystem.GetSdCardPath(); - - LocalFileSystem fileSystem = new LocalFileSystem(sdCardPath); + Result rc = _baseFileSystemProxy.OpenSdCardFileSystem(out LibHac.Fs.IFileSystem fileSystem); + if (rc.IsFailure()) return (ResultCode)rc.Value; MakeObject(context, new FileSystemProxy.IFileSystem(fileSystem)); return ResultCode.Success; } + [Command(21)] + public ResultCode DeleteSaveDataFileSystem(ServiceCtx context) + { + ulong saveDataId = context.RequestData.ReadUInt64(); + + Result result = _baseFileSystemProxy.DeleteSaveDataFileSystem(saveDataId); + + return (ResultCode)result.Value; + } + + [Command(22)] + public ResultCode CreateSaveDataFileSystem(ServiceCtx context) + { + SaveDataAttribute attribute = context.RequestData.ReadStruct(); + SaveDataCreateInfo createInfo = context.RequestData.ReadStruct(); + SaveMetaCreateInfo metaCreateInfo = context.RequestData.ReadStruct(); + + Result result = _baseFileSystemProxy.CreateSaveDataFileSystem(ref attribute, ref createInfo, ref metaCreateInfo); + + return (ResultCode)result.Value; + } + + [Command(23)] + public ResultCode CreateSaveDataFileSystemBySystemSaveDataId(ServiceCtx context) + { + SaveDataAttribute attribute = context.RequestData.ReadStruct(); + SaveDataCreateInfo createInfo = context.RequestData.ReadStruct(); + + Result result = _baseFileSystemProxy.CreateSaveDataFileSystemBySystemSaveDataId(ref attribute, ref createInfo); + + return (ResultCode)result.Value; + } + + [Command(25)] + public ResultCode DeleteSaveDataFileSystemBySaveDataSpaceId(ServiceCtx context) + { + SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadInt64(); + ulong saveDataId = context.RequestData.ReadUInt64(); + + Result result = _baseFileSystemProxy.DeleteSaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId); + + return (ResultCode)result.Value; + } + + [Command(28)] + public ResultCode DeleteSaveDataFileSystemBySaveDataAttribute(ServiceCtx context) + { + SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadInt64(); + SaveDataAttribute attribute = context.RequestData.ReadStruct(); + + Result result = _baseFileSystemProxy.DeleteSaveDataFileSystemBySaveDataAttribute(spaceId, ref attribute); + + return (ResultCode)result.Value; + } + [Command(30)] // OpenGameCardStorage(u32, u32) -> object public ResultCode OpenGameCardStorage(ServiceCtx context) @@ -149,46 +188,141 @@ namespace Ryujinx.HLE.HOS.Services.Fs return (ResultCode)result.Value; } + [Command(35)] + public ResultCode CreateSaveDataFileSystemWithHashSalt(ServiceCtx context) + { + SaveDataAttribute attribute = context.RequestData.ReadStruct(); + SaveDataCreateInfo createInfo = context.RequestData.ReadStruct(); + SaveMetaCreateInfo metaCreateInfo = context.RequestData.ReadStruct(); + HashSalt hashSalt = context.RequestData.ReadStruct(); + + Result result = _baseFileSystemProxy.CreateSaveDataFileSystemWithHashSalt(ref attribute, ref createInfo, ref metaCreateInfo, ref hashSalt); + + return (ResultCode)result.Value; + } + [Command(51)] // OpenSaveDataFileSystem(u8 save_data_space_id, nn::fssrv::sf::SaveStruct saveStruct) -> object saveDataFs public ResultCode OpenSaveDataFileSystem(ServiceCtx context) { - ResultCode result = FileSystemProxyHelper.LoadSaveDataFileSystem(context, false, out FileSystemProxy.IFileSystem fileSystem); + SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadInt64(); + SaveDataAttribute attribute = context.RequestData.ReadStruct(); - if (result == ResultCode.Success) + if (attribute.TitleId == TitleId.Zero) { - MakeObject(context, fileSystem); + attribute.TitleId = new TitleId(context.Process.TitleId); } - return result; + Result result = _baseFileSystemProxy.OpenSaveDataFileSystem(out LibHac.Fs.IFileSystem fileSystem, spaceId, ref attribute); + + if (result.IsSuccess()) + { + MakeObject(context, new FileSystemProxy.IFileSystem(fileSystem)); + } + + return (ResultCode)result.Value; } [Command(52)] // OpenSaveDataFileSystemBySystemSaveDataId(u8 save_data_space_id, nn::fssrv::sf::SaveStruct saveStruct) -> object systemSaveDataFs public ResultCode OpenSaveDataFileSystemBySystemSaveDataId(ServiceCtx context) { - ResultCode result = FileSystemProxyHelper.LoadSaveDataFileSystem(context, false, out FileSystemProxy.IFileSystem fileSystem); + SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadInt64(); + SaveDataAttribute attribute = context.RequestData.ReadStruct(); - if (result == ResultCode.Success) + Result result = _baseFileSystemProxy.OpenSaveDataFileSystemBySystemSaveDataId(out LibHac.Fs.IFileSystem fileSystem, spaceId, ref attribute); + + if (result.IsSuccess()) { - MakeObject(context, fileSystem); + MakeObject(context, new FileSystemProxy.IFileSystem(fileSystem)); } - return result; + return (ResultCode)result.Value; } [Command(53)] // OpenReadOnlySaveDataFileSystem(u8 save_data_space_id, nn::fssrv::sf::SaveStruct save_struct) -> object public ResultCode OpenReadOnlySaveDataFileSystem(ServiceCtx context) { - ResultCode result = FileSystemProxyHelper.LoadSaveDataFileSystem(context, true, out FileSystemProxy.IFileSystem fileSystem); + SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadInt64(); + SaveDataAttribute attribute = context.RequestData.ReadStruct(); - if (result == ResultCode.Success) + if (attribute.TitleId == TitleId.Zero) { - MakeObject(context, fileSystem); + attribute.TitleId = new TitleId(context.Process.TitleId); } - return result; + Result result = _baseFileSystemProxy.OpenReadOnlySaveDataFileSystem(out LibHac.Fs.IFileSystem fileSystem, spaceId, ref attribute); + + if (result.IsSuccess()) + { + MakeObject(context, new FileSystemProxy.IFileSystem(fileSystem)); + } + + return (ResultCode)result.Value; + } + + [Command(60)] + public ResultCode OpenSaveDataInfoReader(ServiceCtx context) + { + Result result = _baseFileSystemProxy.OpenSaveDataInfoReader(out LibHac.FsService.ISaveDataInfoReader infoReader); + + if (result.IsSuccess()) + { + MakeObject(context, new ISaveDataInfoReader(infoReader)); + } + + return (ResultCode)result.Value; + } + + [Command(61)] + public ResultCode OpenSaveDataInfoReaderBySaveDataSpaceId(ServiceCtx context) + { + SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadByte(); + + Result result = _baseFileSystemProxy.OpenSaveDataInfoReaderBySaveDataSpaceId(out LibHac.FsService.ISaveDataInfoReader infoReader, spaceId); + + if (result.IsSuccess()) + { + MakeObject(context, new ISaveDataInfoReader(infoReader)); + } + + return (ResultCode)result.Value; + } + + [Command(67)] + public ResultCode FindSaveDataWithFilter(ServiceCtx context) + { + SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadInt64(); + SaveDataFilter filter = context.RequestData.ReadStruct(); + + long bufferPosition = context.Request.ReceiveBuff[0].Position; + long bufferLen = context.Request.ReceiveBuff[0].Size; + + byte[] infoBuffer = new byte[bufferLen]; + + Result result = _baseFileSystemProxy.FindSaveDataWithFilter(out long count, infoBuffer, spaceId, ref filter); + + context.Memory.WriteBytes(bufferPosition, infoBuffer); + context.ResponseData.Write(count); + + return (ResultCode)result.Value; + } + + [Command(68)] + public ResultCode OpenSaveDataInfoReaderWithFilter(ServiceCtx context) + { + SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadInt64(); + SaveDataFilter filter = context.RequestData.ReadStruct(); + + Result result = _baseFileSystemProxy.OpenSaveDataInfoReaderWithFilter(out LibHac.FsService.ISaveDataInfoReader infoReader, spaceId, ref filter); + + if (result.IsSuccess()) + { + MakeObject(context, new ISaveDataInfoReader(infoReader)); + } + + return (ResultCode)result.Value; } [Command(200)] diff --git a/Ryujinx.HLE/HOS/Services/Fs/ISaveDataInfoReader.cs b/Ryujinx.HLE/HOS/Services/Fs/ISaveDataInfoReader.cs new file mode 100644 index 0000000000..3d5ae8e2cd --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Fs/ISaveDataInfoReader.cs @@ -0,0 +1,31 @@ +using LibHac; + +namespace Ryujinx.HLE.HOS.Services.Fs +{ + class ISaveDataInfoReader : IpcService + { + private LibHac.FsService.ISaveDataInfoReader _baseReader; + + public ISaveDataInfoReader(LibHac.FsService.ISaveDataInfoReader baseReader) + { + _baseReader = baseReader; + } + + [Command(0)] + // ReadSaveDataInfo() -> (u64, buffer) + public ResultCode ReadSaveDataInfo(ServiceCtx context) + { + long bufferPosition = context.Request.ReceiveBuff[0].Position; + long bufferLen = context.Request.ReceiveBuff[0].Size; + + byte[] infoBuffer = new byte[bufferLen]; + + Result result = _baseReader.ReadSaveDataInfo(out long readCount, infoBuffer); + + context.Memory.WriteBytes(bufferPosition, infoBuffer); + context.ResponseData.Write(readCount); + + return (ResultCode)result.Value; + } + } +} diff --git a/Ryujinx.HLE/Ryujinx.HLE.csproj b/Ryujinx.HLE/Ryujinx.HLE.csproj index 42bc4ddc0f..2b6837ccdf 100644 --- a/Ryujinx.HLE/Ryujinx.HLE.csproj +++ b/Ryujinx.HLE/Ryujinx.HLE.csproj @@ -51,7 +51,7 @@ - +