aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAc_K <Acoustik666@gmail.com>2023-08-17 14:59:05 +0200
committerGitHub <noreply@github.com>2023-08-17 09:59:05 -0300
commitb0b7843d5c7372db60211255be0edfcb97dcb56d (patch)
tree08ddc16f41e3455f66c47d86bba83d7295e1a83c
parent6ed613a6e6a66d57d2fdb045d926e42dfcdd3206 (diff)
mm: Migrate service in Horizon project (#5580)1.1.996
* mm: Migrate service in Horizon project This PR migrate the `mm:u` service to the Horizon project, things were checked by some RE aswell, that's why some vars are renamed, the logic should be the same as before. Tests are welcome. * Lock _sessionList instead * Fix comment * Fix Session fields order
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Mm/IRequest.cs196
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Mm/Types/MultiMediaOperationType.cs10
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Mm/Types/MultiMediaSession.cs24
-rw-r--r--src/Ryujinx.Horizon/MmNv/Ipc/Request.cs160
-rw-r--r--src/Ryujinx.Horizon/MmNv/MmNvIpcServer.cs43
-rw-r--r--src/Ryujinx.Horizon/MmNv/MmNvMain.cs17
-rw-r--r--src/Ryujinx.Horizon/Sdk/MmNv/IRequest.cs17
-rw-r--r--src/Ryujinx.Horizon/Sdk/MmNv/Module.cs15
-rw-r--r--src/Ryujinx.Horizon/Sdk/MmNv/Session.cs26
-rw-r--r--src/Ryujinx.Horizon/ServiceTable.cs2
10 files changed, 280 insertions, 230 deletions
diff --git a/src/Ryujinx.HLE/HOS/Services/Mm/IRequest.cs b/src/Ryujinx.HLE/HOS/Services/Mm/IRequest.cs
deleted file mode 100644
index 31d325a9..00000000
--- a/src/Ryujinx.HLE/HOS/Services/Mm/IRequest.cs
+++ /dev/null
@@ -1,196 +0,0 @@
-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 readonly object _sessionListLock = new();
- private readonly List<MultiMediaSession> _sessionList = new();
-
- private 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(_uniqueId++, type, isAutoClearEvent);
-
- _sessionList.Add(session);
-
- return session.Id;
- }
- }
- }
-}
diff --git a/src/Ryujinx.HLE/HOS/Services/Mm/Types/MultiMediaOperationType.cs b/src/Ryujinx.HLE/HOS/Services/Mm/Types/MultiMediaOperationType.cs
deleted file mode 100644
index 095dbfc3..00000000
--- a/src/Ryujinx.HLE/HOS/Services/Mm/Types/MultiMediaOperationType.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Mm.Types
-{
- enum MultiMediaOperationType : uint
- {
- Ram = 2,
- NvEnc = 5,
- NvDec = 6,
- NvJpg = 7,
- }
-}
diff --git a/src/Ryujinx.HLE/HOS/Services/Mm/Types/MultiMediaSession.cs b/src/Ryujinx.HLE/HOS/Services/Mm/Types/MultiMediaSession.cs
deleted file mode 100644
index 32b52ca5..00000000
--- a/src/Ryujinx.HLE/HOS/Services/Mm/Types/MultiMediaSession.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-namespace Ryujinx.HLE.HOS.Services.Mm.Types
-{
- class MultiMediaSession
- {
- public MultiMediaOperationType Type { get; }
-
- public bool IsAutoClearEvent { get; }
- public uint Id { get; }
- public uint CurrentValue { get; private set; }
-
- public MultiMediaSession(uint id, MultiMediaOperationType type, bool isAutoClearEvent)
- {
- Type = type;
- Id = id;
- IsAutoClearEvent = isAutoClearEvent;
- CurrentValue = 0;
- }
-
- public void SetAndWait(uint value, int timeout)
- {
- CurrentValue = value;
- }
- }
-}
diff --git a/src/Ryujinx.Horizon/MmNv/Ipc/Request.cs b/src/Ryujinx.Horizon/MmNv/Ipc/Request.cs
new file mode 100644
index 00000000..9a24c75e
--- /dev/null
+++ b/src/Ryujinx.Horizon/MmNv/Ipc/Request.cs
@@ -0,0 +1,160 @@
+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;
+ }
+ }
+ }
+}
diff --git a/src/Ryujinx.Horizon/MmNv/MmNvIpcServer.cs b/src/Ryujinx.Horizon/MmNv/MmNvIpcServer.cs
new file mode 100644
index 00000000..e60b2558
--- /dev/null
+++ b/src/Ryujinx.Horizon/MmNv/MmNvIpcServer.cs
@@ -0,0 +1,43 @@
+using Ryujinx.Horizon.MmNv.Ipc;
+using Ryujinx.Horizon.Sdk.Sf.Hipc;
+using Ryujinx.Horizon.Sdk.Sm;
+
+namespace Ryujinx.Horizon.MmNv
+{
+ class MmNvIpcServer
+ {
+ private const int MmNvMaxSessionsCount = 9;
+
+ private const int PointerBufferSize = 0;
+ private const int MaxDomains = 0;
+ private const int MaxDomainObjects = 0;
+ private const int MaxPortsCount = 1;
+
+ private static readonly ManagerOptions _mmNvOptions = new(PointerBufferSize, MaxDomains, MaxDomainObjects, false);
+
+ private SmApi _sm;
+ private ServerManager _serverManager;
+
+ public void Initialize()
+ {
+ HeapAllocator allocator = new();
+
+ _sm = new SmApi();
+ _sm.Initialize().AbortOnFailure();
+
+ _serverManager = new ServerManager(allocator, _sm, MaxPortsCount, _mmNvOptions, MmNvMaxSessionsCount);
+
+ _serverManager.RegisterObjectForServer(new Request(), ServiceName.Encode("mm:u"), MmNvMaxSessionsCount);
+ }
+
+ public void ServiceRequests()
+ {
+ _serverManager.ServiceRequests();
+ }
+
+ public void Shutdown()
+ {
+ _serverManager.Dispose();
+ }
+ }
+}
diff --git a/src/Ryujinx.Horizon/MmNv/MmNvMain.cs b/src/Ryujinx.Horizon/MmNv/MmNvMain.cs
new file mode 100644
index 00000000..ac5eff1a
--- /dev/null
+++ b/src/Ryujinx.Horizon/MmNv/MmNvMain.cs
@@ -0,0 +1,17 @@
+namespace Ryujinx.Horizon.MmNv
+{
+ class MmNvMain : IService
+ {
+ public static void Main(ServiceTable serviceTable)
+ {
+ MmNvIpcServer ipcServer = new();
+
+ ipcServer.Initialize();
+
+ serviceTable.SignalServiceReady();
+
+ ipcServer.ServiceRequests();
+ ipcServer.Shutdown();
+ }
+ }
+}
diff --git a/src/Ryujinx.Horizon/Sdk/MmNv/IRequest.cs b/src/Ryujinx.Horizon/Sdk/MmNv/IRequest.cs
new file mode 100644
index 00000000..300b957f
--- /dev/null
+++ b/src/Ryujinx.Horizon/Sdk/MmNv/IRequest.cs
@@ -0,0 +1,17 @@
+using Ryujinx.Horizon.Common;
+using Ryujinx.Horizon.Sdk.Sf;
+
+namespace Ryujinx.Horizon.Sdk.MmNv
+{
+ interface IRequest : IServiceObject
+ {
+ Result InitializeOld(Module module, uint fgmPriority, uint autoClearEvent);
+ Result FinalizeOld(Module module);
+ Result SetAndWaitOld(Module module, uint clockRateMin, int clockRateMax);
+ Result GetOld(out uint clockRateActual, Module module);
+ Result Initialize(out uint requestId, Module module, uint fgmPriority, uint autoClearEvent);
+ Result Finalize(uint requestId);
+ Result SetAndWait(uint requestId, uint clockRateMin, int clockRateMax);
+ Result Get(out uint clockRateActual, uint requestId);
+ }
+}
diff --git a/src/Ryujinx.Horizon/Sdk/MmNv/Module.cs b/src/Ryujinx.Horizon/Sdk/MmNv/Module.cs
new file mode 100644
index 00000000..e029d037
--- /dev/null
+++ b/src/Ryujinx.Horizon/Sdk/MmNv/Module.cs
@@ -0,0 +1,15 @@
+namespace Ryujinx.Horizon.Sdk.MmNv
+{
+ enum Module : uint
+ {
+ Cpu,
+ Gpu,
+ Emc,
+ SysBus,
+ MSelect,
+ NvDec,
+ NvEnc,
+ NvJpg,
+ Test,
+ }
+}
diff --git a/src/Ryujinx.Horizon/Sdk/MmNv/Session.cs b/src/Ryujinx.Horizon/Sdk/MmNv/Session.cs
new file mode 100644
index 00000000..b9158569
--- /dev/null
+++ b/src/Ryujinx.Horizon/Sdk/MmNv/Session.cs
@@ -0,0 +1,26 @@
+namespace Ryujinx.Horizon.Sdk.MmNv
+{
+ class Session
+ {
+ public Module Module { get; }
+ public uint Id { get; }
+ public bool IsAutoClearEvent { get; }
+ public uint ClockRateMin { get; private set; }
+ public int ClockRateMax { get; private set; }
+
+ public Session(uint id, Module module, bool isAutoClearEvent)
+ {
+ Module = module;
+ Id = id;
+ IsAutoClearEvent = isAutoClearEvent;
+ ClockRateMin = 0;
+ ClockRateMax = -1;
+ }
+
+ public void SetAndWait(uint clockRateMin, int clockRateMax)
+ {
+ ClockRateMin = clockRateMin;
+ ClockRateMax = clockRateMax;
+ }
+ }
+}
diff --git a/src/Ryujinx.Horizon/ServiceTable.cs b/src/Ryujinx.Horizon/ServiceTable.cs
index d47f91bf..8dfacbeb 100644
--- a/src/Ryujinx.Horizon/ServiceTable.cs
+++ b/src/Ryujinx.Horizon/ServiceTable.cs
@@ -1,5 +1,6 @@
using Ryujinx.Horizon.Bcat;
using Ryujinx.Horizon.LogManager;
+using Ryujinx.Horizon.MmNv;
using Ryujinx.Horizon.Prepo;
using System.Collections.Generic;
using System.Threading;
@@ -25,6 +26,7 @@ namespace Ryujinx.Horizon
RegisterService<LmMain>();
RegisterService<PrepoMain>();
RegisterService<BcatMain>();
+ RegisterService<MmNvMain>();
_totalServices = entries.Count;