diff options
Diffstat (limited to 'src/Ryujinx.HLE/HOS/Services/Mm/IRequest.cs')
| -rw-r--r-- | src/Ryujinx.HLE/HOS/Services/Mm/IRequest.cs | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/src/Ryujinx.HLE/HOS/Services/Mm/IRequest.cs b/src/Ryujinx.HLE/HOS/Services/Mm/IRequest.cs new file mode 100644 index 00000000..fac42555 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Mm/IRequest.cs @@ -0,0 +1,196 @@ +using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Services.Mm.Types; +using System.Collections.Generic; + +namespace Ryujinx.HLE.HOS.Services.Mm +{ + [Service("mm:u")] + class IRequest : IpcService + { + private static object _sessionListLock = new object(); + private static List<MultiMediaSession> _sessionList = new List<MultiMediaSession>(); + + private static uint _uniqueId = 1; + + public IRequest(ServiceCtx context) { } + + [CommandCmif(0)] + // InitializeOld(u32, u32, u32) + public ResultCode InitializeOld(ServiceCtx context) + { + MultiMediaOperationType operationType = (MultiMediaOperationType)context.RequestData.ReadUInt32(); + int fgmId = context.RequestData.ReadInt32(); + bool isAutoClearEvent = context.RequestData.ReadInt32() != 0; + + Logger.Stub?.PrintStub(LogClass.ServiceMm, new { operationType, fgmId, isAutoClearEvent }); + + Register(operationType, fgmId, isAutoClearEvent); + + return ResultCode.Success; + } + + [CommandCmif(1)] + // FinalizeOld(u32) + public ResultCode FinalizeOld(ServiceCtx context) + { + MultiMediaOperationType operationType = (MultiMediaOperationType)context.RequestData.ReadUInt32(); + + Logger.Stub?.PrintStub(LogClass.ServiceMm, new { operationType }); + + lock (_sessionListLock) + { + _sessionList.Remove(GetSessionByType(operationType)); + } + + return ResultCode.Success; + } + + [CommandCmif(2)] + // SetAndWaitOld(u32, u32, u32) + public ResultCode SetAndWaitOld(ServiceCtx context) + { + MultiMediaOperationType operationType = (MultiMediaOperationType)context.RequestData.ReadUInt32(); + uint frequenceHz = context.RequestData.ReadUInt32(); + int timeout = context.RequestData.ReadInt32(); + + Logger.Stub?.PrintStub(LogClass.ServiceMm, new { operationType, frequenceHz, timeout }); + + lock (_sessionListLock) + { + GetSessionByType(operationType)?.SetAndWait(frequenceHz, timeout); + } + + return ResultCode.Success; + } + + [CommandCmif(3)] + // GetOld(u32) -> u32 + public ResultCode GetOld(ServiceCtx context) + { + MultiMediaOperationType operationType = (MultiMediaOperationType)context.RequestData.ReadUInt32(); + + Logger.Stub?.PrintStub(LogClass.ServiceMm, new { operationType }); + + lock (_sessionListLock) + { + MultiMediaSession session = GetSessionByType(operationType); + + uint currentValue = session == null ? 0 : session.CurrentValue; + + context.ResponseData.Write(currentValue); + } + + return ResultCode.Success; + } + + [CommandCmif(4)] + // Initialize(u32, u32, u32) -> u32 + public ResultCode Initialize(ServiceCtx context) + { + MultiMediaOperationType operationType = (MultiMediaOperationType)context.RequestData.ReadUInt32(); + int fgmId = context.RequestData.ReadInt32(); + bool isAutoClearEvent = context.RequestData.ReadInt32() != 0; + + Logger.Stub?.PrintStub(LogClass.ServiceMm, new { operationType, fgmId, isAutoClearEvent }); + + uint id = Register(operationType, fgmId, isAutoClearEvent); + + context.ResponseData.Write(id); + + return ResultCode.Success; + } + + [CommandCmif(5)] + // Finalize(u32) + public ResultCode Finalize(ServiceCtx context) + { + uint id = context.RequestData.ReadUInt32(); + + Logger.Stub?.PrintStub(LogClass.ServiceMm, new { id }); + + lock (_sessionListLock) + { + _sessionList.Remove(GetSessionById(id)); + } + + return ResultCode.Success; + } + + [CommandCmif(6)] + // SetAndWait(u32, u32, u32) + public ResultCode SetAndWait(ServiceCtx context) + { + uint id = context.RequestData.ReadUInt32(); + uint frequenceHz = context.RequestData.ReadUInt32(); + int timeout = context.RequestData.ReadInt32(); + + Logger.Stub?.PrintStub(LogClass.ServiceMm, new { id, frequenceHz, timeout }); + + lock (_sessionListLock) + { + GetSessionById(id)?.SetAndWait(frequenceHz, timeout); + } + + return ResultCode.Success; + } + + [CommandCmif(7)] + // Get(u32) -> u32 + public ResultCode Get(ServiceCtx context) + { + uint id = context.RequestData.ReadUInt32(); + + Logger.Stub?.PrintStub(LogClass.ServiceMm, new { id }); + + lock (_sessionListLock) + { + MultiMediaSession session = GetSessionById(id); + + uint currentValue = session == null ? 0 : session.CurrentValue; + + context.ResponseData.Write(currentValue); + } + + return ResultCode.Success; + } + + private MultiMediaSession GetSessionById(uint id) + { + foreach (MultiMediaSession session in _sessionList) + { + if (session.Id == id) + { + return session; + } + } + + return null; + } + + private MultiMediaSession GetSessionByType(MultiMediaOperationType type) + { + foreach (MultiMediaSession session in _sessionList) + { + if (session.Type == type) + { + return session; + } + } + + return null; + } + + private uint Register(MultiMediaOperationType type, int fgmId, bool isAutoClearEvent) + { + lock (_sessionListLock) + { + // Nintendo ignore the fgm id as the other interfaces were deprecated. + MultiMediaSession session = new MultiMediaSession(_uniqueId++, type, isAutoClearEvent); + + _sessionList.Add(session); + + return session.Id; + } + } + } +}
\ No newline at end of file |
