From 8cc872fb60ec1b825655ba8dba06cc978fcd7e66 Mon Sep 17 00:00:00 2001 From: Ac_K Date: Tue, 29 Jun 2021 18:57:06 +0200 Subject: [PATCH] aoc/am: Cleanup aoc service and stub am calls (#2414) * aoc/am: Cleanup aoc service and stub am calls This PR implement aoc call `GetAddOnContentListChangedEventWithProcessId` (Closes #2408) and `CreateContentsServiceManager`. Additionnally, a big cleanup (checked by RE on latest firmware) is made on the whole service. I've added `CountAddOnContent`, `ListAddOnContent` and `GetAddonContentBaseId` for games which require version `1.0.0-6.2.0` too. Am service call `ReportUserIsActive` is stubbed (checked by RE, closes #2413). Since some logic in the service (aoc) which handle the DLCs has been changed, it could be nice to have some testing to be sure there is no regression. * Remove wrong check * Addresses gdkchan feedback * Fix GetAddOnContentLostErrorCode * fix null pid in services * Add missing comment * remove leftover comment --- .../SystemAppletProxy/ISelfController.cs | 11 + .../Friend/ServiceCreator/IFriendService.cs | 2 +- .../Services/Ns/Aoc/IAddOnContentManager.cs | 285 ++++++++++++++++++ .../Ns/Aoc/IContentsServiceManager.cs | 7 + .../Ns/{ => Aoc}/IPurchaseEventManager.cs | 11 +- Ryujinx.HLE/HOS/Services/Ns/Aoc/ResultCode.cs | 13 + .../HOS/Services/Ns/IAddOnContentManager.cs | 193 ------------ .../Pctl/IParentalControlServiceFactory.cs | 10 +- .../IParentalControlService.cs | 6 +- 9 files changed, 332 insertions(+), 206 deletions(-) create mode 100644 Ryujinx.HLE/HOS/Services/Ns/Aoc/IAddOnContentManager.cs create mode 100644 Ryujinx.HLE/HOS/Services/Ns/Aoc/IContentsServiceManager.cs rename Ryujinx.HLE/HOS/Services/Ns/{ => Aoc}/IPurchaseEventManager.cs (83%) create mode 100644 Ryujinx.HLE/HOS/Services/Ns/Aoc/ResultCode.cs delete mode 100644 Ryujinx.HLE/HOS/Services/Ns/IAddOnContentManager.cs diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs index 0ecbd4a07..51b204f0f 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs @@ -285,6 +285,17 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys return ResultCode.Success; } + [CommandHipc(65)] + // ReportUserIsActive() + public ResultCode ReportUserIsActive(ServiceCtx context) + { + // TODO: Call idle:sys ReportUserIsActive when implemented. + + Logger.Stub?.PrintStub(LogClass.ServiceAm); + + return ResultCode.Success; + } + [CommandHipc(68)] // SetAutoSleepDisabled(u8) public ResultCode SetAutoSleepDisabled(ServiceCtx context) diff --git a/Ryujinx.HLE/HOS/Services/Friend/ServiceCreator/IFriendService.cs b/Ryujinx.HLE/HOS/Services/Friend/ServiceCreator/IFriendService.cs index a2865e9c1..f8a7b3371 100644 --- a/Ryujinx.HLE/HOS/Services/Friend/ServiceCreator/IFriendService.cs +++ b/Ryujinx.HLE/HOS/Services/Friend/ServiceCreator/IFriendService.cs @@ -279,7 +279,7 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator // Pid placeholder context.RequestData.ReadInt64(); - long pid = context.Process.Pid; + long pid = context.Request.HandleDesc.PId; ulong playHistoryRegistrationKeyPosition = context.Request.PtrBuff[0].Position; ulong PlayHistoryRegistrationKeySize = context.Request.PtrBuff[0].Size; diff --git a/Ryujinx.HLE/HOS/Services/Ns/Aoc/IAddOnContentManager.cs b/Ryujinx.HLE/HOS/Services/Ns/Aoc/IAddOnContentManager.cs new file mode 100644 index 000000000..bdffbbc74 --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Ns/Aoc/IAddOnContentManager.cs @@ -0,0 +1,285 @@ +using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; +using System; +using System.Collections.Generic; + +namespace Ryujinx.HLE.HOS.Services.Ns.Aoc +{ + [Service("aoc:u")] + class IAddOnContentManager : IpcService + { + private readonly KEvent _addOnContentListChangedEvent; + + private ulong _addOnContentBaseId; + + public IAddOnContentManager(ServiceCtx context) + { + _addOnContentListChangedEvent = new KEvent(context.Device.System.KernelContext); + } + + [CommandHipc(0)] // 1.0.0-6.2.0 + // CountAddOnContentByApplicationId(u64 title_id) -> u32 + public ResultCode CountAddOnContentByApplicationId(ServiceCtx context) + { + ulong titleId = context.RequestData.ReadUInt64(); + + return CountAddOnContentImpl(context, titleId); + } + + [CommandHipc(1)] // 1.0.0-6.2.0 + // ListAddOnContentByApplicationId(u64 title_id, u32 start_index, u32 buffer_size) -> (u32 count, buffer) + public ResultCode ListAddOnContentByApplicationId(ServiceCtx context) + { + ulong titleId = context.RequestData.ReadUInt64(); + + return ListAddContentImpl(context, titleId); + } + + [CommandHipc(2)] + // CountAddOnContent(pid) -> u32 + public ResultCode CountAddOnContent(ServiceCtx context) + { + long pid = context.Request.HandleDesc.PId; + + // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. + + return CountAddOnContentImpl(context, context.Device.Application.TitleId); + } + + [CommandHipc(3)] + // ListAddOnContent(u32 start_index, u32 buffer_size, pid) -> (u32 count, buffer) + public ResultCode ListAddOnContent(ServiceCtx context) + { + long pid = context.Request.HandleDesc.PId; + + // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. + + return ListAddContentImpl(context, context.Device.Application.TitleId); + } + + [CommandHipc(4)] // 1.0.0-6.2.0 + // GetAddOnContentBaseIdByApplicationId(u64 title_id) -> u64 + public ResultCode GetAddOnContentBaseIdByApplicationId(ServiceCtx context) + { + ulong titleId = context.RequestData.ReadUInt64(); + + return GetAddOnContentBaseIdImpl(context, titleId); + } + + [CommandHipc(5)] + // GetAddOnContentBaseId(pid) -> u64 + public ResultCode GetAddOnContentBaseId(ServiceCtx context) + { + long pid = context.Request.HandleDesc.PId; + + // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. + + return GetAddOnContentBaseIdImpl(context, context.Device.Application.TitleId); + } + + [CommandHipc(6)] // 1.0.0-6.2.0 + // PrepareAddOnContentByApplicationId(u64 title_id, u32 index) + public ResultCode PrepareAddOnContentByApplicationId(ServiceCtx context) + { + ulong titleId = context.RequestData.ReadUInt64(); + + return PrepareAddOnContentImpl(context, titleId); + } + + [CommandHipc(7)] + // PrepareAddOnContent(u32 index, pid) + public ResultCode PrepareAddOnContent(ServiceCtx context) + { + long pid = context.Request.HandleDesc.PId; + + // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. + + return PrepareAddOnContentImpl(context, context.Device.Application.TitleId); + } + + [CommandHipc(8)] // 4.0.0+ + // GetAddOnContentListChangedEvent() -> handle + public ResultCode GetAddOnContentListChangedEvent(ServiceCtx context) + { + return GetAddOnContentListChangedEventImpl(context); + } + + [CommandHipc(9)] // 10.0.0+ + // GetAddOnContentLostErrorCode() -> u64 + public ResultCode GetAddOnContentLostErrorCode(ServiceCtx context) + { + // NOTE: 0x7D0A4 -> 2164-1000 + context.ResponseData.Write(GetAddOnContentLostErrorCodeImpl(0x7D0A4)); + + return ResultCode.Success; + } + + [CommandHipc(10)] // 11.0.0+ + // GetAddOnContentListChangedEventWithProcessId(pid) -> handle + public ResultCode GetAddOnContentListChangedEventWithProcessId(ServiceCtx context) + { + long pid = context.Request.HandleDesc.PId; + + // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. + + // TODO: Found where stored value is used. + ResultCode resultCode = GetAddOnContentBaseIdFromTitleId(context, context.Device.Application.TitleId); + + if (resultCode != ResultCode.Success) + { + return resultCode; + } + + return GetAddOnContentListChangedEventImpl(context); + } + + [CommandHipc(100)] // 7.0.0+ + // CreateEcPurchasedEventManager() -> object + public ResultCode CreateEcPurchasedEventManager(ServiceCtx context) + { + MakeObject(context, new IPurchaseEventManager(context.Device.System)); + + return ResultCode.Success; + } + + [CommandHipc(101)] // 9.0.0+ + // CreatePermanentEcPurchasedEventManager() -> object + public ResultCode CreatePermanentEcPurchasedEventManager(ServiceCtx context) + { + // NOTE: Service call arp:r to get the TitleId, do some extra checks and pass it to returned interface. + + MakeObject(context, new IPurchaseEventManager(context.Device.System)); + + return ResultCode.Success; + } + + [CommandHipc(110)] // 12.0.0+ + // CreateContentsServiceManager() -> object + public ResultCode CreateContentsServiceManager(ServiceCtx context) + { + MakeObject(context, new IContentsServiceManager()); + + return ResultCode.Success; + } + + private ResultCode CountAddOnContentImpl(ServiceCtx context, ulong titleId) + { + // NOTE: Service call sys:set GetQuestFlag and store it internally. + // If QuestFlag is true, counts some extra titles. + + ResultCode resultCode = GetAddOnContentBaseIdFromTitleId(context, titleId); + + if (resultCode != ResultCode.Success) + { + return resultCode; + } + + // TODO: This should use _addOnContentBaseId; + uint aocCount = (uint)context.Device.System.ContentManager.GetAocCount(); + + context.ResponseData.Write(aocCount); + + return ResultCode.Success; + } + + private ResultCode ListAddContentImpl(ServiceCtx context, ulong titleId) + { + // NOTE: Service call sys:set GetQuestFlag and store it internally. + // If QuestFlag is true, counts some extra titles. + + uint startIndex = context.RequestData.ReadUInt32(); + uint bufferSize = context.RequestData.ReadUInt32(); + ulong bufferPosition = context.Request.ReceiveBuff[0].Position; + + // TODO: This should use _addOnContentBaseId; + uint aocCount = (uint)context.Device.System.ContentManager.GetAocCount(); + + if (aocCount - startIndex > bufferSize) + { + return ResultCode.InvalidBufferSize; + } + + if (aocCount <= startIndex) + { + context.ResponseData.Write(0); + + return ResultCode.Success; + } + + IList aocTitleIds = context.Device.System.ContentManager.GetAocTitleIds(); + + GetAddOnContentBaseIdFromTitleId(context, titleId); + + for (int i = 0; i < aocCount; i++) + { + context.Memory.Write(bufferPosition + (ulong)i * 4, (uint)(aocTitleIds[i + (int)startIndex] - _addOnContentBaseId)); + } + + context.ResponseData.Write(aocCount); + + return ResultCode.Success; + } + + private ResultCode GetAddOnContentBaseIdImpl(ServiceCtx context, ulong titleId) + { + ResultCode resultCode = GetAddOnContentBaseIdFromTitleId(context, titleId); + + context.ResponseData.Write(_addOnContentBaseId); + + return resultCode; + } + + private ResultCode GetAddOnContentBaseIdFromTitleId(ServiceCtx context, ulong titleId) + { + // NOTE: Service calls arp:r GetApplicationControlProperty to get AddOnContentBaseId using TitleId, + // If the call fails, it returns ResultCode.InvalidPid. + + _addOnContentBaseId = context.Device.Application.ControlData.Value.AddOnContentBaseId; + + if (_addOnContentBaseId == 0) + { + _addOnContentBaseId = titleId + 0x1000; + } + + return ResultCode.Success; + } + + private ResultCode PrepareAddOnContentImpl(ServiceCtx context, ulong titleId) + { + uint index = context.RequestData.ReadUInt32(); + + ResultCode resultCode = GetAddOnContentBaseIdFromTitleId(context, context.Device.Application.TitleId); + + if (resultCode != ResultCode.Success) + { + return resultCode; + } + + // TODO: Service calls ns:am RegisterContentsExternalKey?, GetOwnedApplicationContentMetaStatus? etc... + // Ideally, this should probably initialize the AocData values for the specified index + + Logger.Stub?.PrintStub(LogClass.ServiceNs, new { index }); + + return ResultCode.Success; + } + + private ResultCode GetAddOnContentListChangedEventImpl(ServiceCtx context) + { + if (context.Process.HandleTable.GenerateHandle(_addOnContentListChangedEvent.ReadableEvent, out int addOnContentListChangedEventHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } + + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(addOnContentListChangedEventHandle); + + return ResultCode.Success; + } + + private static ulong GetAddOnContentLostErrorCodeImpl(int errorCode) + { + return ((ulong)errorCode & 0x1FF | ((((ulong)errorCode >> 9) & 0x1FFF) << 32)) + 2000; + } + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Ns/Aoc/IContentsServiceManager.cs b/Ryujinx.HLE/HOS/Services/Ns/Aoc/IContentsServiceManager.cs new file mode 100644 index 000000000..cb8903d42 --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Ns/Aoc/IContentsServiceManager.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.HLE.HOS.Services.Ns.Aoc +{ + class IContentsServiceManager : IpcService + { + public IContentsServiceManager() { } + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Ns/IPurchaseEventManager.cs b/Ryujinx.HLE/HOS/Services/Ns/Aoc/IPurchaseEventManager.cs similarity index 83% rename from Ryujinx.HLE/HOS/Services/Ns/IPurchaseEventManager.cs rename to Ryujinx.HLE/HOS/Services/Ns/Aoc/IPurchaseEventManager.cs index 7ee743701..eb2b03208 100644 --- a/Ryujinx.HLE/HOS/Services/Ns/IPurchaseEventManager.cs +++ b/Ryujinx.HLE/HOS/Services/Ns/Aoc/IPurchaseEventManager.cs @@ -1,11 +1,10 @@ -using Ryujinx.Common; using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Kernel.Common; using Ryujinx.HLE.HOS.Kernel.Threading; using System; -namespace Ryujinx.HLE.HOS.Services.Ns +namespace Ryujinx.HLE.HOS.Services.Ns.Aoc { class IPurchaseEventManager : IpcService { @@ -20,8 +19,8 @@ namespace Ryujinx.HLE.HOS.Services.Ns // SetDefaultDeliveryTarget(pid, buffer unknown) public ResultCode SetDefaultDeliveryTarget(ServiceCtx context) { - ulong inBufferPosition = context.Request.SendBuff[0].Position; - ulong inBufferSize = context.Request.SendBuff[0].Size; + ulong inBufferPosition = context.Request.SendBuff[0].Position; + ulong inBufferSize = context.Request.SendBuff[0].Size; byte[] buffer = new byte[inBufferSize]; context.Memory.Read(inBufferPosition, buffer); @@ -39,12 +38,12 @@ namespace Ryujinx.HLE.HOS.Services.Ns // GetPurchasedEventReadableHandle() -> handle public ResultCode GetPurchasedEventReadableHandle(ServiceCtx context) { - if (context.Process.HandleTable.GenerateHandle(_purchasedEvent.ReadableEvent, out int handle) != KernelResult.Success) + if (context.Process.HandleTable.GenerateHandle(_purchasedEvent.ReadableEvent, out int purchasedEventReadableHandle) != KernelResult.Success) { throw new InvalidOperationException("Out of handles!"); } - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle); + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(purchasedEventReadableHandle); return ResultCode.Success; } diff --git a/Ryujinx.HLE/HOS/Services/Ns/Aoc/ResultCode.cs b/Ryujinx.HLE/HOS/Services/Ns/Aoc/ResultCode.cs new file mode 100644 index 000000000..7602ecb36 --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Ns/Aoc/ResultCode.cs @@ -0,0 +1,13 @@ +namespace Ryujinx.HLE.HOS.Services.Ns.Aoc +{ + enum ResultCode + { + ModuleId = 166, + ErrorCodeShift = 9, + + Success = 0, + + InvalidBufferSize = (200 << ErrorCodeShift) | ModuleId, + InvalidPid = (300 << ErrorCodeShift) | ModuleId + } +} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Ns/IAddOnContentManager.cs b/Ryujinx.HLE/HOS/Services/Ns/IAddOnContentManager.cs deleted file mode 100644 index c5525a5d6..000000000 --- a/Ryujinx.HLE/HOS/Services/Ns/IAddOnContentManager.cs +++ /dev/null @@ -1,193 +0,0 @@ -using Ryujinx.Common.Logging; -using Ryujinx.HLE.HOS.Ipc; -using Ryujinx.HLE.HOS.Kernel.Common; -using Ryujinx.HLE.HOS.Kernel.Threading; -using System; - -namespace Ryujinx.HLE.HOS.Services.Ns -{ - [Service("aoc:u")] - class IAddOnContentManager : IpcService - { - private readonly KEvent _addOnContentListChangedEvent; - - private int _addOnContentListChangedEventHandle; - - public IAddOnContentManager(ServiceCtx context) - { - _addOnContentListChangedEvent = new KEvent(context.Device.System.KernelContext); - } - - [CommandHipc(2)] - // CountAddOnContent(pid) -> u32 - public ResultCode CountAddOnContent(ServiceCtx context) - { - long pid = context.Process.Pid; - - // Official code checks ApplicationControlProperty.RuntimeAddOnContentInstall - // if true calls ns:am ListAvailableAddOnContent again to get updated count - - byte runtimeAddOnContentInstall = context.Device.Application.ControlData.Value.RuntimeAddOnContentInstall; - if (runtimeAddOnContentInstall != 0) - { - Logger.Warning?.Print(LogClass.ServiceNs, $"RuntimeAddOnContentInstall is true. Some DLC may be missing"); - } - - uint aocCount = CountAddOnContentImpl(context); - - context.ResponseData.Write(aocCount); - - Logger.Stub?.PrintStub(LogClass.ServiceNs, new { aocCount, runtimeAddOnContentInstall }); - - return ResultCode.Success; - } - - private static uint CountAddOnContentImpl(ServiceCtx context) - { - return (uint)context.Device.System.ContentManager.GetAocCount(); - } - - [CommandHipc(3)] - // ListAddOnContent(u32, u32, pid) -> (u32, buffer) - public ResultCode ListAddOnContent(ServiceCtx context) - { - uint startIndex = context.RequestData.ReadUInt32(); - uint bufferSize = context.RequestData.ReadUInt32(); - long pid = context.Process.Pid; - - var aocTitleIds = context.Device.System.ContentManager.GetAocTitleIds(); - - uint aocCount = CountAddOnContentImpl(context); - - if (aocCount <= startIndex) - { - context.ResponseData.Write((uint)0); - - return ResultCode.Success; - } - - aocCount = Math.Min(aocCount - startIndex, bufferSize); - - context.ResponseData.Write(aocCount); - - ulong bufAddr = (ulong)context.Request.ReceiveBuff[0].Position; - - ulong aocBaseId = GetAddOnContentBaseIdImpl(context); - - for (int i = 0; i < aocCount; ++i) - { - context.Memory.Write(bufAddr + (ulong)i * 4, (int)(aocTitleIds[i + (int)startIndex] - aocBaseId)); - } - - Logger.Stub?.PrintStub(LogClass.ServiceNs, new { bufferSize, startIndex, aocCount }); - - return ResultCode.Success; - } - - [CommandHipc(5)] - // GetAddOnContentBaseId(pid) -> u64 - public ResultCode GetAddonContentBaseId(ServiceCtx context) - { - long pid = context.Process.Pid; - - // Official code calls arp:r GetApplicationControlProperty to get AddOnContentBaseId - // If the call fails, calls arp:r GetApplicationLaunchProperty to get App TitleId - ulong aocBaseId = GetAddOnContentBaseIdImpl(context); - - context.ResponseData.Write(aocBaseId); - - Logger.Stub?.PrintStub(LogClass.ServiceNs, $"aocBaseId={aocBaseId:X16}"); - - // ResultCode will be error code of GetApplicationLaunchProperty if it fails - return ResultCode.Success; - } - - private static ulong GetAddOnContentBaseIdImpl(ServiceCtx context) - { - ulong aocBaseId = context.Device.Application.ControlData.Value.AddOnContentBaseId; - - if (aocBaseId == 0) - { - aocBaseId = context.Device.Application.TitleId + 0x1000; - } - - return aocBaseId; - } - - [CommandHipc(7)] - // PrepareAddOnContent(u32, pid) - public ResultCode PrepareAddOnContent(ServiceCtx context) - { - uint aocIndex = context.RequestData.ReadUInt32(); - long pid = context.Process.Pid; - - // Official Code calls a bunch of functions from arp:r for aocBaseId - // and ns:am RegisterContentsExternalKey?, GetOwnedApplicationContentMetaStatus? etc... - - // Ideally, this should probably initialize the AocData values for the specified index - - Logger.Stub?.PrintStub(LogClass.ServiceNs, new { aocIndex }); - - return ResultCode.Success; - } - - [CommandHipc(8)] - // GetAddOnContentListChangedEvent() -> handle - public ResultCode GetAddOnContentListChangedEvent(ServiceCtx context) - { - // Official code seems to make an internal call to ns:am Cmd 84 GetDynamicCommitEvent() - - if (_addOnContentListChangedEventHandle == 0) - { - if (context.Process.HandleTable.GenerateHandle(_addOnContentListChangedEvent.ReadableEvent, out _addOnContentListChangedEventHandle) != KernelResult.Success) - { - throw new InvalidOperationException("Out of handles!"); - } - } - - context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_addOnContentListChangedEventHandle); - - Logger.Stub?.PrintStub(LogClass.ServiceNs); - - return ResultCode.Success; - } - - - [CommandHipc(9)] // [10.0.0+] - // GetAddOnContentLostErrorCode() -> u64 - public ResultCode GetAddOnContentLostErrorCode(ServiceCtx context) - { - // Seems to calculate ((value & 0x1ff)) + 2000 on 0x7d0a4 - // which gives 0x874 (2000+164). 164 being Module ID of `EC (Shop)` - context.ResponseData.Write(2164L); - - Logger.Stub?.PrintStub(LogClass.ServiceNs); - - return ResultCode.Success; - } - - [CommandHipc(100)] - // CreateEcPurchasedEventManager() -> object - public ResultCode CreateEcPurchasedEventManager(ServiceCtx context) - { - MakeObject(context, new IPurchaseEventManager(context.Device.System)); - - Logger.Stub?.PrintStub(LogClass.ServiceNs); - - return ResultCode.Success; - } - - [CommandHipc(101)] - // CreatePermanentEcPurchasedEventManager() -> object - public ResultCode CreatePermanentEcPurchasedEventManager(ServiceCtx context) - { - // Very similar to CreateEcPurchasedEventManager but with some extra code - - MakeObject(context, new IPurchaseEventManager(context.Device.System)); - - Logger.Stub?.PrintStub(LogClass.ServiceNs); - - return ResultCode.Success; - } - } -} \ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Pctl/IParentalControlServiceFactory.cs b/Ryujinx.HLE/HOS/Services/Pctl/IParentalControlServiceFactory.cs index 785d2280e..a84e13b54 100644 --- a/Ryujinx.HLE/HOS/Services/Pctl/IParentalControlServiceFactory.cs +++ b/Ryujinx.HLE/HOS/Services/Pctl/IParentalControlServiceFactory.cs @@ -19,8 +19,9 @@ namespace Ryujinx.HLE.HOS.Services.Pctl // CreateService(u64, pid) -> object public ResultCode CreateService(ServiceCtx context) { - // TODO: Should pass the pid. - MakeObject(context, new IParentalControlService(context, true, _permissionFlag)); + long pid = context.Request.HandleDesc.PId; + + MakeObject(context, new IParentalControlService(context, pid, true, _permissionFlag)); return ResultCode.Success; } @@ -29,8 +30,9 @@ namespace Ryujinx.HLE.HOS.Services.Pctl // CreateServiceWithoutInitialize(u64, pid) -> object public ResultCode CreateServiceWithoutInitialize(ServiceCtx context) { - // TODO: Should pass the pid. - MakeObject(context, new IParentalControlService(context, false, _permissionFlag)); + long pid = context.Request.HandleDesc.PId; + + MakeObject(context, new IParentalControlService(context, pid, false, _permissionFlag)); return ResultCode.Success; } diff --git a/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs b/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs index 183c570c6..173b3223d 100644 --- a/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs +++ b/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs @@ -7,6 +7,7 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory { class IParentalControlService : IpcService { + private long _pid; private int _permissionFlag; private ulong _titleId; private ParentalControlFlagValue _parentalControlFlag; @@ -18,8 +19,9 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory private bool _stereoVisionRestrictionConfigurable = true; private bool _stereoVisionRestriction = false; - public IParentalControlService(ServiceCtx context, bool withInitialize, int permissionFlag) + public IParentalControlService(ServiceCtx context, long pid, bool withInitialize, int permissionFlag) { + _pid = pid; _permissionFlag = permissionFlag; if (withInitialize) @@ -39,7 +41,7 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory ResultCode resultCode = ResultCode.InvalidPid; - if (context.Process.Pid != 0) + if (_pid != 0) { if ((_permissionFlag & 0x40) == 0) {