diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2023-05-04 13:16:51 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-05-04 18:16:51 +0200 |
| commit | 264438ff19898bcb8f8fc16dc9243bf9f4eba072 (patch) | |
| tree | fd069fe4f0dcd2a78fc9c8ccc6d4e93bec2330b5 /src/Ryujinx.HLE | |
| parent | 3b8ac1641a8a40849915396813e26384b5894911 (diff) | |
Revert "bcat ipc (#4446)" (#4801)
This reverts commit 42507323535443ad79be071367f3d4815afca688.
Diffstat (limited to 'src/Ryujinx.HLE')
9 files changed, 431 insertions, 1 deletions
diff --git a/src/Ryujinx.HLE/HOS/Horizon.cs b/src/Ryujinx.HLE/HOS/Horizon.cs index 34ab0d39..1639532e 100644 --- a/src/Ryujinx.HLE/HOS/Horizon.cs +++ b/src/Ryujinx.HLE/HOS/Horizon.cs @@ -327,7 +327,7 @@ namespace Ryujinx.HLE.HOS private void StartNewServices() { ServiceTable = new ServiceTable(); - var services = ServiceTable.GetServices(new HorizonOptions(Device.Configuration.IgnoreMissingServices, LibHacHorizonManager.BcatClient)); + var services = ServiceTable.GetServices(new HorizonOptions(Device.Configuration.IgnoreMissingServices)); foreach (var service in services) { diff --git a/src/Ryujinx.HLE/HOS/Services/Bcat/IServiceCreator.cs b/src/Ryujinx.HLE/HOS/Services/Bcat/IServiceCreator.cs new file mode 100644 index 00000000..1437a8e1 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Bcat/IServiceCreator.cs @@ -0,0 +1,85 @@ +using LibHac; +using LibHac.Common; +using Ryujinx.Common; +using Ryujinx.HLE.HOS.Services.Arp; +using Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator; + +namespace Ryujinx.HLE.HOS.Services.Bcat +{ + [Service("bcat:a", "bcat:a")] + [Service("bcat:m", "bcat:m")] + [Service("bcat:u", "bcat:u")] + [Service("bcat:s", "bcat:s")] + class IServiceCreator : DisposableIpcService + { + private SharedRef<LibHac.Bcat.Impl.Ipc.IServiceCreator> _base; + + public IServiceCreator(ServiceCtx context, string serviceName) + { + var applicationClient = context.Device.System.LibHacHorizonManager.ApplicationClient; + applicationClient.Sm.GetService(ref _base, serviceName).ThrowIfFailure(); + } + + protected override void Dispose(bool isDisposing) + { + if (isDisposing) + { + _base.Destroy(); + } + } + + [CommandCmif(0)] + // CreateBcatService(pid) -> object<nn::bcat::detail::ipc::IBcatService> + public ResultCode CreateBcatService(ServiceCtx context) + { + // TODO: Call arp:r GetApplicationLaunchProperty with the pid to get the TitleId. + // Add an instance of nn::bcat::detail::service::core::PassphraseManager. + // Add an instance of nn::bcat::detail::service::ServiceMemoryManager. + // Add an instance of nn::bcat::detail::service::core::TaskManager who load "bcat-sys:/" system save data and open "dc/task.bin". + // If the file don't exist, create a new one (size of 0x800) and write 2 empty struct with a size of 0x400. + + MakeObject(context, new IBcatService(ApplicationLaunchProperty.GetByPid(context))); + + // NOTE: If the IBcatService is null this error is returned, Doesn't occur in our case. + // return ResultCode.NullObject; + + return ResultCode.Success; + } + + [CommandCmif(1)] + // CreateDeliveryCacheStorageService(pid) -> object<nn::bcat::detail::ipc::IDeliveryCacheStorageService> + public ResultCode CreateDeliveryCacheStorageService(ServiceCtx context) + { + ulong pid = context.RequestData.ReadUInt64(); + + using var serv = new SharedRef<LibHac.Bcat.Impl.Ipc.IDeliveryCacheStorageService>(); + + Result rc = _base.Get.CreateDeliveryCacheStorageService(ref serv.Ref, pid); + + if (rc.IsSuccess()) + { + MakeObject(context, new IDeliveryCacheStorageService(context, ref serv.Ref)); + } + + return (ResultCode)rc.Value; + } + + [CommandCmif(2)] + // CreateDeliveryCacheStorageServiceWithApplicationId(nn::ApplicationId) -> object<nn::bcat::detail::ipc::IDeliveryCacheStorageService> + public ResultCode CreateDeliveryCacheStorageServiceWithApplicationId(ServiceCtx context) + { + ApplicationId applicationId = context.RequestData.ReadStruct<ApplicationId>(); + + using var service = new SharedRef<LibHac.Bcat.Impl.Ipc.IDeliveryCacheStorageService>(); + + Result rc = _base.Get.CreateDeliveryCacheStorageServiceWithApplicationId(ref service.Ref, applicationId); + + if (rc.IsSuccess()) + { + MakeObject(context, new IDeliveryCacheStorageService(context, ref service.Ref)); + } + + return (ResultCode)rc.Value; + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Bcat/ResultCode.cs b/src/Ryujinx.HLE/HOS/Services/Bcat/ResultCode.cs new file mode 100644 index 00000000..7f1b313e --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Bcat/ResultCode.cs @@ -0,0 +1,29 @@ +namespace Ryujinx.HLE.HOS.Services.Bcat +{ + enum ResultCode + { + ModuleId = 122, + ErrorCodeShift = 9, + + Success = 0, + + InvalidArgument = (1 << ErrorCodeShift) | ModuleId, + NotFound = (2 << ErrorCodeShift) | ModuleId, + TargetLocked = (3 << ErrorCodeShift) | ModuleId, + TargetAlreadyMounted = (4 << ErrorCodeShift) | ModuleId, + TargetNotMounted = (5 << ErrorCodeShift) | ModuleId, + AlreadyOpen = (6 << ErrorCodeShift) | ModuleId, + NotOpen = (7 << ErrorCodeShift) | ModuleId, + InternetRequestDenied = (8 << ErrorCodeShift) | ModuleId, + ServiceOpenLimitReached = (9 << ErrorCodeShift) | ModuleId, + SaveDataNotFound = (10 << ErrorCodeShift) | ModuleId, + NetworkServiceAccountNotAvailable = (31 << ErrorCodeShift) | ModuleId, + PassphrasePathNotFound = (80 << ErrorCodeShift) | ModuleId, + DataVerificationFailed = (81 << ErrorCodeShift) | ModuleId, + PermissionDenied = (90 << ErrorCodeShift) | ModuleId, + AllocationFailed = (91 << ErrorCodeShift) | ModuleId, + InvalidOperation = (98 << ErrorCodeShift) | ModuleId, + InvalidDeliveryCacheStorageFile = (204 << ErrorCodeShift) | ModuleId, + StorageOpenLimitReached = (205 << ErrorCodeShift) | ModuleId + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IBcatService.cs b/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IBcatService.cs new file mode 100644 index 00000000..fb11ceda --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IBcatService.cs @@ -0,0 +1,18 @@ +using Ryujinx.HLE.HOS.Services.Arp; + +namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator +{ + class IBcatService : IpcService + { + public IBcatService(ApplicationLaunchProperty applicationLaunchProperty) { } + + [CommandCmif(10100)] + // RequestSyncDeliveryCache() -> object<nn::bcat::detail::ipc::IDeliveryCacheProgressService> + public ResultCode RequestSyncDeliveryCache(ServiceCtx context) + { + MakeObject(context, new IDeliveryCacheProgressService(context)); + + return ResultCode.Success; + } + } +}
\ No newline at end of file diff --git a/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheDirectoryService.cs b/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheDirectoryService.cs new file mode 100644 index 00000000..57544977 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheDirectoryService.cs @@ -0,0 +1,65 @@ +using LibHac; +using LibHac.Bcat; +using LibHac.Common; +using Ryujinx.Common; +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator +{ + class IDeliveryCacheDirectoryService : DisposableIpcService + { + private SharedRef<LibHac.Bcat.Impl.Ipc.IDeliveryCacheDirectoryService> _base; + + public IDeliveryCacheDirectoryService(ref SharedRef<LibHac.Bcat.Impl.Ipc.IDeliveryCacheDirectoryService> baseService) + { + _base = SharedRef<LibHac.Bcat.Impl.Ipc.IDeliveryCacheDirectoryService>.CreateMove(ref baseService); + } + + protected override void Dispose(bool isDisposing) + { + if (isDisposing) + { + _base.Destroy(); + } + } + + [CommandCmif(0)] + // Open(nn::bcat::DirectoryName) + public ResultCode Open(ServiceCtx context) + { + DirectoryName directoryName = context.RequestData.ReadStruct<DirectoryName>(); + + Result result = _base.Get.Open(ref directoryName); + + return (ResultCode)result.Value; + } + + [CommandCmif(1)] + // Read() -> (u32, buffer<nn::bcat::DeliveryCacheDirectoryEntry, 6>) + public ResultCode Read(ServiceCtx context) + { + ulong bufferAddress = context.Request.ReceiveBuff[0].Position; + ulong bufferLen = context.Request.ReceiveBuff[0].Size; + + using (var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true)) + { + Result result = _base.Get.Read(out int entriesRead, MemoryMarshal.Cast<byte, DeliveryCacheDirectoryEntry>(region.Memory.Span)); + + context.ResponseData.Write(entriesRead); + + return (ResultCode)result.Value; + } + } + + [CommandCmif(2)] + // GetCount() -> u32 + public ResultCode GetCount(ServiceCtx context) + { + Result result = _base.Get.GetCount(out int count); + + context.ResponseData.Write(count); + + return (ResultCode)result.Value; + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheFileService.cs b/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheFileService.cs new file mode 100644 index 00000000..5a9110e6 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheFileService.cs @@ -0,0 +1,78 @@ +using LibHac; +using LibHac.Bcat; +using LibHac.Common; +using Ryujinx.Common; + +namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator +{ + class IDeliveryCacheFileService : DisposableIpcService + { + private SharedRef<LibHac.Bcat.Impl.Ipc.IDeliveryCacheFileService> _base; + + public IDeliveryCacheFileService(ref SharedRef<LibHac.Bcat.Impl.Ipc.IDeliveryCacheFileService> baseService) + { + _base = SharedRef<LibHac.Bcat.Impl.Ipc.IDeliveryCacheFileService>.CreateMove(ref baseService); + } + + protected override void Dispose(bool isDisposing) + { + if (isDisposing) + { + _base.Destroy(); + } + } + + [CommandCmif(0)] + // Open(nn::bcat::DirectoryName, nn::bcat::FileName) + public ResultCode Open(ServiceCtx context) + { + DirectoryName directoryName = context.RequestData.ReadStruct<DirectoryName>(); + FileName fileName = context.RequestData.ReadStruct<FileName>(); + + Result result = _base.Get.Open(ref directoryName, ref fileName); + + return (ResultCode)result.Value; + } + + [CommandCmif(1)] + // Read(u64) -> (u64, buffer<bytes, 6>) + public ResultCode Read(ServiceCtx context) + { + ulong bufferAddress = context.Request.ReceiveBuff[0].Position; + ulong bufferLen = context.Request.ReceiveBuff[0].Size; + + long offset = context.RequestData.ReadInt64(); + + using (var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true)) + { + Result result = _base.Get.Read(out long bytesRead, offset, region.Memory.Span); + + context.ResponseData.Write(bytesRead); + + return (ResultCode)result.Value; + } + } + + [CommandCmif(2)] + // GetSize() -> u64 + public ResultCode GetSize(ServiceCtx context) + { + Result result = _base.Get.GetSize(out long size); + + context.ResponseData.Write(size); + + return (ResultCode)result.Value; + } + + [CommandCmif(3)] + // GetDigest() -> nn::bcat::Digest + public ResultCode GetDigest(ServiceCtx context) + { + Result result = _base.Get.GetDigest(out Digest digest); + + context.ResponseData.WriteStruct(digest); + + return (ResultCode)result.Value; + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs b/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs new file mode 100644 index 00000000..1555f170 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheProgressService.cs @@ -0,0 +1,63 @@ +using Ryujinx.Common.Logging; +using Ryujinx.Cpu; +using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.HLE.HOS.Kernel.Threading; +using Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator.Types; +using Ryujinx.Horizon.Common; +using System; + +namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator +{ + class IDeliveryCacheProgressService : IpcService + { + private KEvent _event; + private int _eventHandle; + + public IDeliveryCacheProgressService(ServiceCtx context) + { + _event = new KEvent(context.Device.System.KernelContext); + } + + [CommandCmif(0)] + // GetEvent() -> handle<copy> + public ResultCode GetEvent(ServiceCtx context) + { + if (_eventHandle == 0) + { + if (context.Process.HandleTable.GenerateHandle(_event.ReadableEvent, out _eventHandle) != Result.Success) + { + throw new InvalidOperationException("Out of handles!"); + } + } + + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_eventHandle); + + Logger.Stub?.PrintStub(LogClass.ServiceBcat); + + return ResultCode.Success; + } + + [CommandCmif(1)] + // GetImpl() -> buffer<nn::bcat::detail::DeliveryCacheProgressImpl, 0x1a> + public ResultCode GetImpl(ServiceCtx context) + { + DeliveryCacheProgressImpl deliveryCacheProgress = new DeliveryCacheProgressImpl + { + State = DeliveryCacheProgressImpl.Status.Done, + Result = 0 + }; + + ulong dcpSize = WriteDeliveryCacheProgressImpl(context, context.Request.RecvListBuff[0], deliveryCacheProgress); + context.Response.PtrBuff[0] = context.Response.PtrBuff[0].WithSize(dcpSize); + + Logger.Stub?.PrintStub(LogClass.ServiceBcat); + + return ResultCode.Success; + } + + private ulong WriteDeliveryCacheProgressImpl(ServiceCtx context, IpcRecvListBuffDesc ipcDesc, DeliveryCacheProgressImpl deliveryCacheProgress) + { + return MemoryHelper.Write(context.Memory, ipcDesc.Position, deliveryCacheProgress); + } + } +}
\ No newline at end of file diff --git a/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheStorageService.cs b/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheStorageService.cs new file mode 100644 index 00000000..be77226c --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/IDeliveryCacheStorageService.cs @@ -0,0 +1,74 @@ +using LibHac; +using LibHac.Bcat; +using LibHac.Common; +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator +{ + class IDeliveryCacheStorageService : DisposableIpcService + { + private SharedRef<LibHac.Bcat.Impl.Ipc.IDeliveryCacheStorageService> _base; + + public IDeliveryCacheStorageService(ServiceCtx context, ref SharedRef<LibHac.Bcat.Impl.Ipc.IDeliveryCacheStorageService> baseService) + { + _base = SharedRef<LibHac.Bcat.Impl.Ipc.IDeliveryCacheStorageService>.CreateMove(ref baseService); + } + + [CommandCmif(0)] + // CreateFileService() -> object<nn::bcat::detail::ipc::IDeliveryCacheFileService> + public ResultCode CreateFileService(ServiceCtx context) + { + using var service = new SharedRef<LibHac.Bcat.Impl.Ipc.IDeliveryCacheFileService>(); + + Result result = _base.Get.CreateFileService(ref service.Ref); + + if (result.IsSuccess()) + { + MakeObject(context, new IDeliveryCacheFileService(ref service.Ref)); + } + + return (ResultCode)result.Value; + } + + [CommandCmif(1)] + // CreateDirectoryService() -> object<nn::bcat::detail::ipc::IDeliveryCacheDirectoryService> + public ResultCode CreateDirectoryService(ServiceCtx context) + { + using var service = new SharedRef<LibHac.Bcat.Impl.Ipc.IDeliveryCacheDirectoryService>(); + + Result result = _base.Get.CreateDirectoryService(ref service.Ref); + + if (result.IsSuccess()) + { + MakeObject(context, new IDeliveryCacheDirectoryService(ref service.Ref)); + } + + return (ResultCode)result.Value; + } + + [CommandCmif(10)] + // EnumerateDeliveryCacheDirectory() -> (u32, buffer<nn::bcat::DirectoryName, 6>) + public ResultCode EnumerateDeliveryCacheDirectory(ServiceCtx context) + { + ulong bufferAddress = context.Request.ReceiveBuff[0].Position; + ulong bufferLen = context.Request.ReceiveBuff[0].Size; + + using (var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true)) + { + Result result = _base.Get.EnumerateDeliveryCacheDirectory(out int count, MemoryMarshal.Cast<byte, DirectoryName>(region.Memory.Span)); + + context.ResponseData.Write(count); + + return (ResultCode)result.Value; + } + } + + protected override void Dispose(bool isDisposing) + { + if (isDisposing) + { + _base.Destroy(); + } + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/Types/DeliveryCacheProgressImpl.cs b/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/Types/DeliveryCacheProgressImpl.cs new file mode 100644 index 00000000..fb9a67be --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Bcat/ServiceCreator/Types/DeliveryCacheProgressImpl.cs @@ -0,0 +1,18 @@ +using System.Runtime.InteropServices; + +namespace Ryujinx.HLE.HOS.Services.Bcat.ServiceCreator.Types +{ + [StructLayout(LayoutKind.Sequential, Size = 0x200)] + public struct DeliveryCacheProgressImpl + { + public enum Status + { + // TODO: determine other values + Done = 9 + } + + public Status State; + public uint Result; + // TODO: reverse the rest of the structure + } +} |
