diff --git a/Ryujinx.HLE/HOS/Services/Friend/ServiceCreator/IFriendService.cs b/Ryujinx.HLE/HOS/Services/Friend/ServiceCreator/IFriendService.cs index fc9b5d59..64ef5b2b 100644 --- a/Ryujinx.HLE/HOS/Services/Friend/ServiceCreator/IFriendService.cs +++ b/Ryujinx.HLE/HOS/Services/Friend/ServiceCreator/IFriendService.cs @@ -1,26 +1,48 @@ +using LibHac.Ns; using Ryujinx.Common; using Ryujinx.Common.Logging; using Ryujinx.Common.Memory; using Ryujinx.Common.Utilities; +using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.HLE.HOS.Kernel.Common; +using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.HOS.Services.Friend.ServiceCreator.FriendService; using System; using System.IO; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Security.Cryptography; namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator { class IFriendService : IpcService { private FriendServicePermissionLevel _permissionLevel; + private KEvent _completionEvent; public IFriendService(FriendServicePermissionLevel permissionLevel) { _permissionLevel = permissionLevel; } + [Command(0)] + // GetCompletionEvent() -> handle + public ResultCode GetCompletionEvent(ServiceCtx context) + { + if (_completionEvent == null) + { + _completionEvent = new KEvent(context.Device.System.KernelContext); + } + + if (context.Process.HandleTable.GenerateHandle(_completionEvent.ReadableEvent, out int completionEventHandle) != KernelResult.Success) + { + throw new InvalidOperationException("Out of handles!"); + } + + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(completionEventHandle); + + return ResultCode.Success; + } + [Command(10100)] // nn::friends::GetFriendListIds(int offset, nn::account::Uid userId, nn::friends::detail::ipc::SizedFriendFilter friendFilter, ulong pidPlaceHolder, pid) // -> int outCount, array @@ -252,5 +274,45 @@ namespace Ryujinx.HLE.HOS.Services.Friend.ServiceCreator return ResultCode.Success; } + + [Command(10702)] + // nn::friends::AddPlayHistory(nn::account::Uid, u64, pid, buffer, buffer, buffer) + public ResultCode AddPlayHistory(ServiceCtx context) + { + UserId userId = context.RequestData.ReadStruct(); + + // Pid placeholder + context.RequestData.ReadInt64(); + long pid = context.Process.Pid; + + long playHistoryRegistrationKeyPosition = context.Request.PtrBuff[0].Position; + long PlayHistoryRegistrationKeySize = context.Request.PtrBuff[0].Size; + + long inAppScreenName1Position = context.Request.PtrBuff[1].Position; + long inAppScreenName1Size = context.Request.PtrBuff[1].Size; + + long inAppScreenName2Position = context.Request.PtrBuff[2].Position; + long inAppScreenName2Size = context.Request.PtrBuff[2].Size; + + if (userId.IsNull || inAppScreenName1Size > 0x48 || inAppScreenName2Size > 0x48) + { + return ResultCode.InvalidArgument; + } + + // TODO: Call nn::arp::GetApplicationControlProperty here when implemented. + ApplicationControlProperty controlProperty = context.Device.Application.ControlData.Value; + + /* + + NOTE: The service calls nn::friends::detail::service::core::PlayHistoryManager to store informations using the registration key computed in GetPlayHistoryRegistrationKey. + Then calls nn::friends::detail::service::core::FriendListManager to update informations on the friend list. + We currently don't support play history and online services so it's fine to do nothing. + + */ + + Logger.Stub?.PrintStub(LogClass.ServiceFriend); + + return ResultCode.Success; + } } } \ No newline at end of file