using Ryujinx.Common.Logging;
using Ryujinx.Horizon.Common;
using Ryujinx.Horizon.Sdk.MmNv;
using Ryujinx.Horizon.Sdk.Sf;
using System.Collections.Generic;
namespace Ryujinx.Horizon.MmNv.Ipc
{
partial class Request : IRequest
{
private readonly List<Session> _sessionList = new();
private uint _uniqueId = 1;
[CmifCommand(0)]
public Result InitializeOld(Module module, uint fgmPriority, uint autoClearEvent)
{
bool isAutoClearEvent = autoClearEvent != 0;
Logger.Stub?.PrintStub(LogClass.ServiceMm, new { module, fgmPriority, isAutoClearEvent });
Register(module, fgmPriority, isAutoClearEvent);
return Result.Success;
}
[CmifCommand(1)]
public Result FinalizeOld(Module module)
{
Logger.Stub?.PrintStub(LogClass.ServiceMm, new { module });
lock (_sessionList)
{
_sessionList.Remove(GetSessionByModule(module));
}
return Result.Success;
}
[CmifCommand(2)]
public Result SetAndWaitOld(Module module, uint clockRateMin, int clockRateMax)
{
Logger.Stub?.PrintStub(LogClass.ServiceMm, new { module, clockRateMin, clockRateMax });
lock (_sessionList)
{
GetSessionByModule(module)?.SetAndWait(clockRateMin, clockRateMax);
}
return Result.Success;
}
[CmifCommand(3)]
public Result GetOld(out uint clockRateActual, Module module)
{
Logger.Stub?.PrintStub(LogClass.ServiceMm, new { module });
lock (_sessionList)
{
Session session = GetSessionByModule(module);
clockRateActual = session == null ? 0 : session.ClockRateMin;
}
return Result.Success;
}
[CmifCommand(4)]
public Result Initialize(out uint requestId, Module module, uint fgmPriority, uint autoClearEvent)
{
bool isAutoClearEvent = autoClearEvent != 0;
Logger.Stub?.PrintStub(LogClass.ServiceMm, new { module, fgmPriority, isAutoClearEvent });
requestId = Register(module, fgmPriority, isAutoClearEvent);
return Result.Success;
}
[CmifCommand(5)]
public Result Finalize(uint requestId)
{
Logger.Stub?.PrintStub(LogClass.ServiceMm, new { requestId });
lock (_sessionList)
{
_sessionList.Remove(GetSessionById(requestId));
}
return Result.Success;
}
[CmifCommand(6)]
public Result SetAndWait(uint requestId, uint clockRateMin, int clockRateMax)
{
Logger.Stub?.PrintStub(LogClass.ServiceMm, new { requestId, clockRateMin, clockRateMax });
lock (_sessionList)
{
GetSessionById(requestId)?.SetAndWait(clockRateMin, clockRateMax);
}
return Result.Success;
}
[CmifCommand(7)]
public Result Get(out uint clockRateActual, uint requestId)
{
Logger.Stub?.PrintStub(LogClass.ServiceMm, new { requestId });
lock (_sessionList)
{
Session session = GetSessionById(requestId);
clockRateActual = session == null ? 0 : session.ClockRateMin;
}
return Result.Success;
}
private Session GetSessionById(uint id)
{
foreach (Session session in _sessionList)
{
if (session.Id == id)
{
return session;
}
}
return null;
}
private Session GetSessionByModule(Module module)
{
foreach (Session session in _sessionList)
{
if (session.Module == module)
{
return session;
}
}
return null;
}
private uint Register(Module module, uint fgmPriority, bool isAutoClearEvent)
{
lock (_sessionList)
{
// Nintendo ignores the fgm priority as the other services were deprecated.
Session session = new(_uniqueId++, module, isAutoClearEvent);
_sessionList.Add(session);
return session.Id;
}
}
}
}