apm/am: Refactoring/Unstub services (#1662)
* apm: Refactoring/Unstub service This PR implement some IPC calls of apm service: - nn::apm::IManager is fully implemented. - nn::apm::ISession is fully implemented (close #1633). - nn::apm::ISystemManager is partially implemented. nn::appletAE::ICommonStateGetter have some calls which are just a layer of apm IPC calls. What we did in some calls was wrong, it's fixed now! Everything is checked with RE. * abstract Apm *Server as Thog requested * abstract ISession and fix other classes * Address gdkchan feedback * Fix class * Fix Logging
This commit is contained in:
parent
8d168574eb
commit
eda6b78894
15 changed files with 282 additions and 37 deletions
|
@ -15,6 +15,7 @@ using Ryujinx.HLE.HOS.Kernel.Memory;
|
|||
using Ryujinx.HLE.HOS.Kernel.Process;
|
||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||
using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy;
|
||||
using Ryujinx.HLE.HOS.Services.Apm;
|
||||
using Ryujinx.HLE.HOS.Services.Arp;
|
||||
using Ryujinx.HLE.HOS.Services.Audio.AudioRenderer;
|
||||
using Ryujinx.HLE.HOS.Services.Mii;
|
||||
|
@ -53,6 +54,8 @@ namespace Ryujinx.HLE.HOS
|
|||
|
||||
public SystemStateMgr State { get; private set; }
|
||||
|
||||
internal PerformanceState PerformanceState { get; private set; }
|
||||
|
||||
internal AppletStateMgr AppletState { get; private set; }
|
||||
|
||||
internal KSharedMemory HidSharedMem { get; private set; }
|
||||
|
@ -94,6 +97,8 @@ namespace Ryujinx.HLE.HOS
|
|||
|
||||
State = new SystemStateMgr();
|
||||
|
||||
PerformanceState = new PerformanceState();
|
||||
|
||||
// Note: This is not really correct, but with HLE of services, the only memory
|
||||
// region used that is used is Application, so we can use the other ones for anything.
|
||||
KMemoryRegionManager region = KernelContext.MemoryRegions[(int)MemoryRegion.NvServices];
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
|
|||
// GetCommonStateGetter() -> object<nn::am::service::ICommonStateGetter>
|
||||
public ResultCode GetCommonStateGetter(ServiceCtx context)
|
||||
{
|
||||
MakeObject(context, new ICommonStateGetter());
|
||||
MakeObject(context, new ICommonStateGetter(context));
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
|
|
@ -2,17 +2,22 @@ using Ryujinx.Common.Logging;
|
|||
using Ryujinx.HLE.HOS.Ipc;
|
||||
using Ryujinx.HLE.HOS.Kernel.Common;
|
||||
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||
using Ryujinx.HLE.HOS.Services.Apm;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
|
||||
{
|
||||
class ICommonStateGetter : IpcService
|
||||
{
|
||||
private CpuBoostMode _cpuBoostMode = CpuBoostMode.Disabled;
|
||||
private Apm.ManagerServer apmManagerServer;
|
||||
private Apm.SystemManagerServer apmSystemManagerServer;
|
||||
|
||||
private bool _vrModeEnabled = false;
|
||||
|
||||
public ICommonStateGetter() { }
|
||||
public ICommonStateGetter(ServiceCtx context)
|
||||
{
|
||||
apmManagerServer = new Apm.ManagerServer(context);
|
||||
apmSystemManagerServer = new Apm.SystemManagerServer(context);
|
||||
}
|
||||
|
||||
[Command(0)]
|
||||
// GetEventHandle() -> handle<copy>
|
||||
|
@ -58,16 +63,10 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
|||
}
|
||||
|
||||
[Command(6)]
|
||||
// GetPerformanceMode() -> u32
|
||||
// GetPerformanceMode() -> nn::apm::PerformanceMode
|
||||
public ResultCode GetPerformanceMode(ServiceCtx context)
|
||||
{
|
||||
PerformanceMode mode = context.Device.System.State.DockedMode
|
||||
? PerformanceMode.Docked
|
||||
: PerformanceMode.Handheld;
|
||||
|
||||
context.ResponseData.Write((int)mode);
|
||||
|
||||
return ResultCode.Success;
|
||||
return (ResultCode)apmManagerServer.GetPerformanceMode(context);
|
||||
}
|
||||
|
||||
[Command(8)]
|
||||
|
@ -136,12 +135,18 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
|||
return ResultCode.InvalidParameters;
|
||||
}
|
||||
|
||||
_cpuBoostMode = (CpuBoostMode)cpuBoostMode;
|
||||
apmSystemManagerServer.SetCpuBoostMode((Apm.CpuBoostMode)cpuBoostMode);
|
||||
|
||||
// NOTE: There is a condition variable after the assignment, probably waiting something with apm:sys service (SetCpuBoostMode call?).
|
||||
// Since we will probably never support CPU boost things, it's not needed to implement more.
|
||||
// TODO: It signals an internal event of ICommonStateGetter. We have to determine where this event is used.
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[Command(91)] // 7.0.0+
|
||||
// GetCurrentPerformanceConfiguration() -> nn::apm::PerformanceConfiguration
|
||||
public ResultCode GetCurrentPerformanceConfiguration(ServiceCtx context)
|
||||
{
|
||||
return (ResultCode)apmSystemManagerServer.GetCurrentPerformanceConfiguration(context);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService
|
|||
// GetCommonStateGetter() -> object<nn::am::service::ICommonStateGetter>
|
||||
public ResultCode GetCommonStateGetter(ServiceCtx context)
|
||||
{
|
||||
MakeObject(context, new ICommonStateGetter());
|
||||
MakeObject(context, new ICommonStateGetter(context));
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,41 @@
|
|||
namespace Ryujinx.HLE.HOS.Services.Apm
|
||||
{
|
||||
[Service("apm")] // 8.0.0+
|
||||
class IManager : IpcService
|
||||
abstract class IManager : IpcService
|
||||
{
|
||||
public IManager(ServiceCtx context) { }
|
||||
|
||||
protected abstract ResultCode OpenSession(out SessionServer sessionServer);
|
||||
protected abstract PerformanceMode GetPerformanceMode();
|
||||
protected abstract bool IsCpuOverclockEnabled();
|
||||
|
||||
[Command(0)]
|
||||
// OpenSession() -> object<nn::apm::ISession>
|
||||
public ResultCode OpenSession(ServiceCtx context)
|
||||
{
|
||||
MakeObject(context, new ISession());
|
||||
ResultCode resultCode = OpenSession(out SessionServer sessionServer);
|
||||
|
||||
if (resultCode == ResultCode.Success)
|
||||
{
|
||||
MakeObject(context, sessionServer);
|
||||
}
|
||||
|
||||
return resultCode;
|
||||
}
|
||||
|
||||
[Command(1)]
|
||||
// GetPerformanceMode() -> nn::apm::PerformanceMode
|
||||
public ResultCode GetPerformanceMode(ServiceCtx context)
|
||||
{
|
||||
context.ResponseData.Write((uint)GetPerformanceMode());
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[Command(6)] // 7.0.0+
|
||||
// IsCpuOverclockEnabled() -> bool
|
||||
public ResultCode IsCpuOverclockEnabled(ServiceCtx context)
|
||||
{
|
||||
context.ResponseData.Write(IsCpuOverclockEnabled());
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
|
|
@ -1,30 +1,43 @@
|
|||
using Ryujinx.Common.Logging;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Apm
|
||||
{
|
||||
class ISession : IpcService
|
||||
abstract class ISession : IpcService
|
||||
{
|
||||
public ISession() { }
|
||||
public ISession(ServiceCtx context) { }
|
||||
|
||||
protected abstract ResultCode SetPerformanceConfiguration(PerformanceMode performanceMode, PerformanceConfiguration performanceConfiguration);
|
||||
protected abstract ResultCode GetPerformanceConfiguration(PerformanceMode performanceMode, out PerformanceConfiguration performanceConfiguration);
|
||||
protected abstract void SetCpuOverclockEnabled(bool enabled);
|
||||
|
||||
[Command(0)]
|
||||
// SetPerformanceConfiguration(nn::apm::PerformanceMode, nn::apm::PerformanceConfiguration)
|
||||
public ResultCode SetPerformanceConfiguration(ServiceCtx context)
|
||||
{
|
||||
PerformanceMode perfMode = (PerformanceMode)context.RequestData.ReadInt32();
|
||||
PerformanceConfiguration perfConfig = (PerformanceConfiguration)context.RequestData.ReadInt32();
|
||||
PerformanceMode performanceMode = (PerformanceMode)context.RequestData.ReadInt32();
|
||||
PerformanceConfiguration performanceConfiguration = (PerformanceConfiguration)context.RequestData.ReadInt32();
|
||||
|
||||
return ResultCode.Success;
|
||||
return SetPerformanceConfiguration(performanceMode, performanceConfiguration);
|
||||
}
|
||||
|
||||
[Command(1)]
|
||||
// GetPerformanceConfiguration(nn::apm::PerformanceMode) -> nn::apm::PerformanceConfiguration
|
||||
public ResultCode GetPerformanceConfiguration(ServiceCtx context)
|
||||
{
|
||||
PerformanceMode perfMode = (PerformanceMode)context.RequestData.ReadInt32();
|
||||
PerformanceMode performanceMode = (PerformanceMode)context.RequestData.ReadInt32();
|
||||
|
||||
context.ResponseData.Write((uint)PerformanceConfiguration.PerformanceConfiguration1);
|
||||
ResultCode resultCode = GetPerformanceConfiguration(performanceMode, out PerformanceConfiguration performanceConfiguration);
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceApm);
|
||||
context.ResponseData.Write((uint)performanceConfiguration);
|
||||
|
||||
return resultCode;
|
||||
}
|
||||
|
||||
[Command(2)] // 8.0.0+
|
||||
// SetCpuOverclockEnabled(bool)
|
||||
public ResultCode SetCpuOverclockEnabled(ServiceCtx context)
|
||||
{
|
||||
bool enabled = context.RequestData.ReadBoolean();
|
||||
|
||||
SetCpuOverclockEnabled(enabled);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
|
42
Ryujinx.HLE/HOS/Services/Apm/ISystemManager.cs
Normal file
42
Ryujinx.HLE/HOS/Services/Apm/ISystemManager.cs
Normal file
|
@ -0,0 +1,42 @@
|
|||
namespace Ryujinx.HLE.HOS.Services.Apm
|
||||
{
|
||||
abstract class ISystemManager : IpcService
|
||||
{
|
||||
public ISystemManager(ServiceCtx context) { }
|
||||
|
||||
protected abstract void RequestPerformanceMode(PerformanceMode performanceMode);
|
||||
internal abstract void SetCpuBoostMode(CpuBoostMode cpuBoostMode);
|
||||
protected abstract PerformanceConfiguration GetCurrentPerformanceConfiguration();
|
||||
|
||||
[Command(0)]
|
||||
// RequestPerformanceMode(nn::apm::PerformanceMode)
|
||||
public ResultCode RequestPerformanceMode(ServiceCtx context)
|
||||
{
|
||||
RequestPerformanceMode((PerformanceMode)context.RequestData.ReadInt32());
|
||||
|
||||
// NOTE: This call seems to overclock the system related to the PerformanceMode, since we emulate it, it's fine to do nothing instead.
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[Command(6)] // 7.0.0+
|
||||
// SetCpuBoostMode(nn::apm::CpuBootMode)
|
||||
public ResultCode SetCpuBoostMode(ServiceCtx context)
|
||||
{
|
||||
SetCpuBoostMode((CpuBoostMode)context.RequestData.ReadUInt32());
|
||||
|
||||
// NOTE: This call seems to overclock the system related to the CpuBoostMode, since we emulate it, it's fine to do nothing instead.
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[Command(7)] // 7.0.0+
|
||||
// GetCurrentPerformanceConfiguration() -> nn::apm::PerformanceConfiguration
|
||||
public ResultCode GetCurrentPerformanceConfiguration(ServiceCtx context)
|
||||
{
|
||||
context.ResponseData.Write((uint)GetCurrentPerformanceConfiguration());
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
}
|
||||
}
|
31
Ryujinx.HLE/HOS/Services/Apm/ManagerServer.cs
Normal file
31
Ryujinx.HLE/HOS/Services/Apm/ManagerServer.cs
Normal file
|
@ -0,0 +1,31 @@
|
|||
namespace Ryujinx.HLE.HOS.Services.Apm
|
||||
{
|
||||
[Service("apm")]
|
||||
[Service("apm:am")] // 8.0.0+
|
||||
class ManagerServer : IManager
|
||||
{
|
||||
private readonly ServiceCtx _context;
|
||||
|
||||
public ManagerServer(ServiceCtx context) : base(context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
protected override ResultCode OpenSession(out SessionServer sessionServer)
|
||||
{
|
||||
sessionServer = new SessionServer(_context);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
protected override PerformanceMode GetPerformanceMode()
|
||||
{
|
||||
return _context.Device.System.PerformanceState.PerformanceMode;
|
||||
}
|
||||
|
||||
protected override bool IsCpuOverclockEnabled()
|
||||
{
|
||||
return _context.Device.System.PerformanceState.CpuOverclockEnabled;
|
||||
}
|
||||
}
|
||||
}
|
25
Ryujinx.HLE/HOS/Services/Apm/PerformanceState.cs
Normal file
25
Ryujinx.HLE/HOS/Services/Apm/PerformanceState.cs
Normal file
|
@ -0,0 +1,25 @@
|
|||
namespace Ryujinx.HLE.HOS.Services.Apm
|
||||
{
|
||||
class PerformanceState
|
||||
{
|
||||
public PerformanceState() { }
|
||||
|
||||
public bool CpuOverclockEnabled = false;
|
||||
|
||||
public PerformanceMode PerformanceMode = PerformanceMode.Default;
|
||||
public CpuBoostMode CpuBoostMode = CpuBoostMode.Disabled;
|
||||
|
||||
public PerformanceConfiguration DefaultPerformanceConfiguration = PerformanceConfiguration.PerformanceConfiguration7;
|
||||
public PerformanceConfiguration BoostPerformanceConfiguration = PerformanceConfiguration.PerformanceConfiguration8;
|
||||
|
||||
public PerformanceConfiguration GetCurrentPerformanceConfiguration(PerformanceMode performanceMode)
|
||||
{
|
||||
return performanceMode switch
|
||||
{
|
||||
PerformanceMode.Default => DefaultPerformanceConfiguration,
|
||||
PerformanceMode.Boost => BoostPerformanceConfiguration,
|
||||
_ => PerformanceConfiguration.PerformanceConfiguration7
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
12
Ryujinx.HLE/HOS/Services/Apm/ResultCode.cs
Normal file
12
Ryujinx.HLE/HOS/Services/Apm/ResultCode.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
namespace Ryujinx.HLE.HOS.Services.Apm
|
||||
{
|
||||
enum ResultCode
|
||||
{
|
||||
ModuleId = 148,
|
||||
ErrorCodeShift = 9,
|
||||
|
||||
Success = 0,
|
||||
|
||||
InvalidParameters = (1 << ErrorCodeShift) | ModuleId
|
||||
}
|
||||
}
|
58
Ryujinx.HLE/HOS/Services/Apm/SessionServer.cs
Normal file
58
Ryujinx.HLE/HOS/Services/Apm/SessionServer.cs
Normal file
|
@ -0,0 +1,58 @@
|
|||
using Ryujinx.Common.Logging;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Apm
|
||||
{
|
||||
class SessionServer : ISession
|
||||
{
|
||||
private readonly ServiceCtx _context;
|
||||
|
||||
public SessionServer(ServiceCtx context) : base(context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
protected override ResultCode SetPerformanceConfiguration(PerformanceMode performanceMode, PerformanceConfiguration performanceConfiguration)
|
||||
{
|
||||
if (performanceMode > PerformanceMode.Boost)
|
||||
{
|
||||
return ResultCode.InvalidParameters;
|
||||
}
|
||||
|
||||
switch (performanceMode)
|
||||
{
|
||||
case PerformanceMode.Default:
|
||||
_context.Device.System.PerformanceState.DefaultPerformanceConfiguration = performanceConfiguration;
|
||||
break;
|
||||
case PerformanceMode.Boost:
|
||||
_context.Device.System.PerformanceState.BoostPerformanceConfiguration = performanceConfiguration;
|
||||
break;
|
||||
default:
|
||||
Logger.Error?.Print(LogClass.ServiceApm, $"PerformanceMode isn't supported: {performanceMode}");
|
||||
break;
|
||||
}
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
protected override ResultCode GetPerformanceConfiguration(PerformanceMode performanceMode, out PerformanceConfiguration performanceConfiguration)
|
||||
{
|
||||
if (performanceMode > PerformanceMode.Boost)
|
||||
{
|
||||
performanceConfiguration = 0;
|
||||
|
||||
return ResultCode.InvalidParameters;
|
||||
}
|
||||
|
||||
performanceConfiguration = _context.Device.System.PerformanceState.GetCurrentPerformanceConfiguration(performanceMode);
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
protected override void SetCpuOverclockEnabled(bool enabled)
|
||||
{
|
||||
_context.Device.System.PerformanceState.CpuOverclockEnabled = enabled;
|
||||
|
||||
// NOTE: This call seems to overclock the system, since we emulate it, it's fine to do nothing instead.
|
||||
}
|
||||
}
|
||||
}
|
28
Ryujinx.HLE/HOS/Services/Apm/SystemManagerServer.cs
Normal file
28
Ryujinx.HLE/HOS/Services/Apm/SystemManagerServer.cs
Normal file
|
@ -0,0 +1,28 @@
|
|||
namespace Ryujinx.HLE.HOS.Services.Apm
|
||||
{
|
||||
[Service("apm:sys")]
|
||||
class SystemManagerServer : ISystemManager
|
||||
{
|
||||
private readonly ServiceCtx _context;
|
||||
|
||||
public SystemManagerServer(ServiceCtx context) : base(context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
protected override void RequestPerformanceMode(PerformanceMode performanceMode)
|
||||
{
|
||||
_context.Device.System.PerformanceState.PerformanceMode = performanceMode;
|
||||
}
|
||||
|
||||
internal override void SetCpuBoostMode(CpuBoostMode cpuBoostMode)
|
||||
{
|
||||
_context.Device.System.PerformanceState.CpuBoostMode = cpuBoostMode;
|
||||
}
|
||||
|
||||
protected override PerformanceConfiguration GetCurrentPerformanceConfiguration()
|
||||
{
|
||||
return _context.Device.System.PerformanceState.GetCurrentPerformanceConfiguration(_context.Device.System.PerformanceState.PerformanceMode);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
enum CpuBoostMode
|
||||
{
|
||||
Disabled = 0,
|
||||
Mode1 = 1, // Use PerformanceConfiguration13 and PerformanceConfiguration14, or PerformanceConfiguration15 and PerformanceConfiguration16
|
||||
Mode2 = 2 // Use PerformanceConfiguration15 and PerformanceConfiguration16.
|
||||
BoostCPU = 1, // Uses PerformanceConfiguration13 and PerformanceConfiguration14, or PerformanceConfiguration15 and PerformanceConfiguration16
|
||||
ConservePower = 2 // Uses PerformanceConfiguration15 and PerformanceConfiguration16.
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
namespace Ryujinx.HLE.HOS.Services.Apm
|
||||
{
|
||||
enum PerformanceMode
|
||||
enum PerformanceMode : uint
|
||||
{
|
||||
Handheld = 0,
|
||||
Docked = 1
|
||||
Default = 0,
|
||||
Boost = 1
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue