| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346 |
- 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 int _addOnContentListChangedEventHandle;
- private ulong _addOnContentBaseId;
- private List<ulong> _mountedAocTitleIds = new List<ulong>();
- 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<u32>)
- public ResultCode ListAddOnContentByApplicationId(ServiceCtx context)
- {
- ulong titleId = context.RequestData.ReadUInt64();
- return ListAddContentImpl(context, titleId);
- }
- [CommandHipc(2)]
- // CountAddOnContent(pid) -> u32
- public ResultCode CountAddOnContent(ServiceCtx context)
- {
- ulong 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<u32>)
- public ResultCode ListAddOnContent(ServiceCtx context)
- {
- ulong 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)
- {
- ulong 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)
- {
- ulong 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<copy>
- 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<copy>
- public ResultCode GetAddOnContentListChangedEventWithProcessId(ServiceCtx context)
- {
- ulong 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(11)] // 13.0.0+
- // NotifyMountAddOnContent(pid, u64 title_id)
- public ResultCode NotifyMountAddOnContent(ServiceCtx context)
- {
- ulong pid = context.Request.HandleDesc.PId;
- // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
- ulong aocTitleId = context.RequestData.ReadUInt64();
- if (_mountedAocTitleIds.Count <= 0x7F)
- {
- _mountedAocTitleIds.Add(aocTitleId);
- }
- return ResultCode.Success;
- }
- [CommandHipc(12)] // 13.0.0+
- // NotifyUnmountAddOnContent(pid, u64 title_id)
- public ResultCode NotifyUnmountAddOnContent(ServiceCtx context)
- {
- ulong pid = context.Request.HandleDesc.PId;
- // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
- ulong aocTitleId = context.RequestData.ReadUInt64();
- _mountedAocTitleIds.Remove(aocTitleId);
- return ResultCode.Success;
- }
- [CommandHipc(50)] // 13.0.0+
- // CheckAddOnContentMountStatus(pid)
- public ResultCode CheckAddOnContentMountStatus(ServiceCtx context)
- {
- ulong pid = context.Request.HandleDesc.PId;
- // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId.
- // Then it does some internal checks and returns InvalidBufferSize if they fail.
- Logger.Stub?.PrintStub(LogClass.ServiceNs);
- return ResultCode.Success;
- }
- [CommandHipc(100)] // 7.0.0+
- // CreateEcPurchasedEventManager() -> object<nn::ec::IPurchaseEventManager>
- public ResultCode CreateEcPurchasedEventManager(ServiceCtx context)
- {
- MakeObject(context, new IPurchaseEventManager(context.Device.System));
- return ResultCode.Success;
- }
- [CommandHipc(101)] // 9.0.0+
- // CreatePermanentEcPurchasedEventManager() -> object<nn::ec::IPurchaseEventManager>
- 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<nn::ec::IContentsServiceManager>
- 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 indexNumber = context.RequestData.ReadUInt32();
- ulong bufferPosition = context.Request.ReceiveBuff[0].Position;
- ulong bufferSize = context.Request.ReceiveBuff[0].Size;
- // TODO: This should use _addOnContentBaseId;
- uint aocTotalCount = (uint)context.Device.System.ContentManager.GetAocCount();
- if (indexNumber > bufferSize / sizeof(uint))
- {
- return ResultCode.InvalidBufferSize;
- }
- if (aocTotalCount <= startIndex)
- {
- context.ResponseData.Write(0);
- return ResultCode.Success;
- }
- IList<ulong> aocTitleIds = context.Device.System.ContentManager.GetAocTitleIds();
- GetAddOnContentBaseIdFromTitleId(context, titleId);
- uint indexCounter = 0;
- for (int i = 0; i < indexNumber; i++)
- {
- if (i + (int)startIndex < aocTitleIds.Count)
- {
- context.Memory.Write(bufferPosition + (ulong)i * sizeof(uint), (uint)(aocTitleIds[i + (int)startIndex] - _addOnContentBaseId));
- indexCounter++;
- }
- }
- context.ResponseData.Write(indexCounter);
- 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 (_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);
- return ResultCode.Success;
- }
- private static ulong GetAddOnContentLostErrorCodeImpl(int errorCode)
- {
- return ((ulong)errorCode & 0x1FF | ((((ulong)errorCode >> 9) & 0x1FFF) << 32)) + 2000;
- }
- }
- }
|