diff --git a/Ryujinx.HLE/HOS/Services/Pctl/IParentalControlServiceFactory.cs b/Ryujinx.HLE/HOS/Services/Pctl/IParentalControlServiceFactory.cs index 678279f934..0729b56eec 100644 --- a/Ryujinx.HLE/HOS/Services/Pctl/IParentalControlServiceFactory.cs +++ b/Ryujinx.HLE/HOS/Services/Pctl/IParentalControlServiceFactory.cs @@ -2,19 +2,25 @@ using Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory; namespace Ryujinx.HLE.HOS.Services.Pctl { - [Service("pctl")] - [Service("pctl:a")] - [Service("pctl:r")] - [Service("pctl:s")] + [Service("pctl", 0x303)] + [Service("pctl:a", 0x83BE)] + [Service("pctl:r", 0x8040)] + [Service("pctl:s", 0x838E)] class IParentalControlServiceFactory : IpcService { - public IParentalControlServiceFactory(ServiceCtx context) { } + private int _permissionFlag; + + public IParentalControlServiceFactory(ServiceCtx context, int permissionFlag) + { + _permissionFlag = permissionFlag; + } [Command(0)] // CreateService(u64, pid) -> object public ResultCode CreateService(ServiceCtx context) { - MakeObject(context, new IParentalControlService()); + // TODO: Should pass the pid. + MakeObject(context, new IParentalControlService(context, true, _permissionFlag)); return ResultCode.Success; } @@ -23,7 +29,8 @@ namespace Ryujinx.HLE.HOS.Services.Pctl // CreateServiceWithoutInitialize(u64, pid) -> object public ResultCode CreateServiceWithoutInitialize(ServiceCtx context) { - MakeObject(context, new IParentalControlService(false)); + // TODO: Should pass the pid. + MakeObject(context, new IParentalControlService(context, 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 0e7c8432bc..6768f8886b 100644 --- a/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs +++ b/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs @@ -1,32 +1,69 @@ using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Services.Arp; +using System; namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory { class IParentalControlService : IpcService { - private bool _initialized = false; + private int _permissionFlag; + private ulong _titleId; + private bool _freeCommunicationEnabled; + private int[] _ratingAge; - private bool _needInitialize; - - public IParentalControlService(bool needInitialize = true) + public IParentalControlService(ServiceCtx context, bool withInitialize, int permissionFlag) { - _needInitialize = needInitialize; + _permissionFlag = permissionFlag; + + if (withInitialize) + { + Initialize(context); + } } [Command(1)] // 4.0.0+ // Initialize() public ResultCode Initialize(ServiceCtx context) { - if (_needInitialize && !_initialized) + if ((_permissionFlag & 0x8001) == 0) { - _initialized = true; - } - else - { - Logger.PrintWarning(LogClass.ServicePctl, "Service is already initialized!"); + return ResultCode.PermissionDenied; } - return ResultCode.Success; + ResultCode resultCode = ResultCode.InvalidPid; + + if (context.Process.Pid != 0) + { + if ((_permissionFlag & 0x40) == 0) + { + ulong titleId = ApplicationLaunchProperty.GetByPid(context).TitleId; + + if (titleId != 0) + { + _titleId = titleId; + + // TODO: Call nn::arp::GetApplicationControlProperty here when implemented, if it return ResultCode.Success we assign fields. + _ratingAge = Array.ConvertAll(context.Device.System.ControlData.Value.RatingAge.ToArray(), Convert.ToInt32); + _freeCommunicationEnabled = context.Device.System.ControlData.Value.ParentalControl == LibHac.Ns.ParentalControlFlagValue.FreeCommunication; + } + } + + if (_titleId != 0) + { + // TODO: Service store some private fields in another static object. + + if ((_permissionFlag & 0x8040) == 0) + { + // TODO: Service store TitleId and FreeCommunicationEnabled in another static object. + // When it's done it signal an event in this static object. + Logger.PrintStub(LogClass.ServicePctl); + } + } + + resultCode = ResultCode.Success; + } + + return resultCode; } [Command(1001)] @@ -35,6 +72,11 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory { Logger.PrintStub(LogClass.ServicePctl); + if (!_freeCommunicationEnabled) + { + return ResultCode.FreeCommunicationDisabled; + } + return ResultCode.Success; } } diff --git a/Ryujinx.HLE/HOS/Services/Pctl/ResultCode.cs b/Ryujinx.HLE/HOS/Services/Pctl/ResultCode.cs new file mode 100644 index 0000000000..bf58628c3a --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Pctl/ResultCode.cs @@ -0,0 +1,14 @@ +namespace Ryujinx.HLE.HOS.Services.Pctl +{ + enum ResultCode + { + ModuleId = 142, + ErrorCodeShift = 9, + + Success = 0, + + FreeCommunicationDisabled = (101 << ErrorCodeShift) | ModuleId, + InvalidPid = (131 << ErrorCodeShift) | ModuleId, + PermissionDenied = (133 << ErrorCodeShift) | ModuleId + } +}