forked from Mirror/Ryujinx
Implement/Stub mnpp:app service and some hid calls (#3131)
* Implement/Stub mnpp:app service and some hid calls This PR Implement/Stub the `mnpp:app` service (closes #3107) accordingly to RE, which seems to do some telemetry for China region only, so everything is stubbed. This PR fixes some inconsistencies in the hid service too and stub EnableSixAxisSensorUnalteredPassthrough, IsSixAxisSensorUnalteredPassthroughEnabled, LoadSixAxisSensorCalibrationParameter, GetSixAxisSensorIcInformation calls (closes #3123 and closes #3124). * Addresses Thog review
This commit is contained in:
parent
747876dc67
commit
a113ed0811
5 changed files with 186 additions and 38 deletions
|
@ -39,6 +39,7 @@ namespace Ryujinx.Common.Logging
|
|||
ServiceLm,
|
||||
ServiceMii,
|
||||
ServiceMm,
|
||||
ServiceMnpp,
|
||||
ServiceNfc,
|
||||
ServiceNfp,
|
||||
ServiceNgct,
|
||||
|
|
|
@ -15,12 +15,12 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
|
|||
// GetAppletResourceUserId() -> nn::applet::AppletResourceUserId
|
||||
public ResultCode GetAppletResourceUserId(ServiceCtx context)
|
||||
{
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceAm);
|
||||
|
||||
long appletResourceUserId = context.Device.System.AppletState.AppletResourceUserIds.Add(_pid);
|
||||
|
||||
context.ResponseData.Write(appletResourceUserId);
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceAm, new { appletResourceUserId });
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
private bool _vibrationPermitted;
|
||||
private bool _usbFullKeyControllerEnabled;
|
||||
private bool _isFirmwareUpdateAvailableForSixAxisSensor;
|
||||
private bool _isSixAxisSensorUnalteredPassthroughEnabled;
|
||||
|
||||
private HidNpadJoyAssignmentMode _npadJoyAssignmentMode;
|
||||
private HidNpadHandheldActivationMode _npadHandheldActivationMode;
|
||||
|
@ -336,6 +337,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
public ResultCode StartSixAxisSensor(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, sixAxisSensorHandle });
|
||||
|
@ -348,6 +350,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
public ResultCode StopSixAxisSensor(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, sixAxisSensorHandle });
|
||||
|
@ -360,6 +363,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
public ResultCode IsSixAxisSensorFusionEnabled(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
context.ResponseData.Write(_sixAxisSensorFusionEnabled);
|
||||
|
@ -373,7 +377,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
// EnableSixAxisSensorFusion(bool Enabled, nn::hid::SixAxisSensorHandle, nn::applet::AppletResourceUserId)
|
||||
public ResultCode EnableSixAxisSensorFusion(ServiceCtx context)
|
||||
{
|
||||
_sixAxisSensorFusionEnabled = context.RequestData.ReadBoolean();
|
||||
_sixAxisSensorFusionEnabled = context.RequestData.ReadUInt32() != 0;
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
|
@ -387,6 +391,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
public ResultCode SetSixAxisSensorFusionParameters(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
|
||||
_sensorFusionParams = new HidSensorFusionParameters
|
||||
{
|
||||
|
@ -406,6 +411,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
public ResultCode GetSixAxisSensorFusionParameters(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
context.ResponseData.Write(_sensorFusionParams.RevisePower);
|
||||
|
@ -421,6 +427,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
public ResultCode ResetSixAxisSensorFusionParameters(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
_sensorFusionParams.RevisePower = 0;
|
||||
|
@ -436,6 +443,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
public ResultCode SetAccelerometerParameters(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
|
||||
_accelerometerParams = new HidAccelerometerParameters
|
||||
{
|
||||
|
@ -455,6 +463,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
public ResultCode GetAccelerometerParameters(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
context.ResponseData.Write(_accelerometerParams.X);
|
||||
|
@ -470,6 +479,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
public ResultCode ResetAccelerometerParameters(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
_accelerometerParams.X = 0;
|
||||
|
@ -485,6 +495,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
public ResultCode SetAccelerometerPlayMode(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
_accelerometerPlayMode = context.RequestData.ReadUInt32();
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
|
@ -498,6 +509,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
public ResultCode GetAccelerometerPlayMode(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
context.ResponseData.Write(_accelerometerPlayMode);
|
||||
|
@ -512,6 +524,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
public ResultCode ResetAccelerometerPlayMode(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
_accelerometerPlayMode = 0;
|
||||
|
@ -539,6 +552,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
public ResultCode GetGyroscopeZeroDriftMode(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
context.ResponseData.Write((int)_gyroscopeZeroDriftMode);
|
||||
|
@ -553,6 +567,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
public ResultCode ResetGyroscopeZeroDriftMode(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
_gyroscopeZeroDriftMode = HidGyroscopeZeroDriftMode.Standard;
|
||||
|
@ -567,6 +582,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
public ResultCode IsSixAxisSensorAtRest(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
bool isAtRest = true;
|
||||
|
@ -583,7 +599,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
public ResultCode IsFirmwareUpdateAvailableForSixAxisSensor(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4;
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
context.ResponseData.Write(_isFirmwareUpdateAvailableForSixAxisSensor);
|
||||
|
@ -593,6 +609,64 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandHipc(84)] // 13.0.0+
|
||||
// EnableSixAxisSensorUnalteredPassthrough(nn::applet::AppletResourceUserId, nn::hid::SixAxisSensorHandle, u8 enabled)
|
||||
public ResultCode EnableSixAxisSensorUnalteredPassthrough(ServiceCtx context)
|
||||
{
|
||||
_isSixAxisSensorUnalteredPassthroughEnabled = context.RequestData.ReadUInt32() != 0;
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, sixAxisSensorHandle, _isSixAxisSensorUnalteredPassthroughEnabled });
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandHipc(85)] // 13.0.0+
|
||||
// IsSixAxisSensorUnalteredPassthroughEnabled(nn::applet::AppletResourceUserId, nn::hid::SixAxisSensorHandle) -> u8 enabled
|
||||
public ResultCode IsSixAxisSensorUnalteredPassthroughEnabled(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
context.ResponseData.Write(_isSixAxisSensorUnalteredPassthroughEnabled);
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, sixAxisSensorHandle });
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandHipc(87)] // 13.0.0+
|
||||
// LoadSixAxisSensorCalibrationParameter(nn::applet::AppletResourceUserId, nn::hid::SixAxisSensorHandle, u64 unknown)
|
||||
public ResultCode LoadSixAxisSensorCalibrationParameter(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
// TODO: CalibrationParameter have to be determined.
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, sixAxisSensorHandle });
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandHipc(88)] // 13.0.0+
|
||||
// GetSixAxisSensorIcInformation(nn::applet::AppletResourceUserId, nn::hid::SixAxisSensorHandle) -> u64 unknown
|
||||
public ResultCode GetSixAxisSensorIcInformation(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
// TODO: IcInformation have to be determined.
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, sixAxisSensorHandle });
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandHipc(91)]
|
||||
// ActivateGesture(nn::applet::AppletResourceUserId, int Unknown0)
|
||||
public ResultCode ActivateGesture(ServiceCtx context)
|
||||
|
@ -606,16 +680,15 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
}
|
||||
|
||||
[CommandHipc(100)]
|
||||
// SetSupportedNpadStyleSet(nn::applet::AppletResourceUserId, nn::hid::NpadStyleTag)
|
||||
// SetSupportedNpadStyleSet(pid, nn::applet::AppletResourceUserId, nn::hid::NpadStyleTag)
|
||||
public ResultCode SetSupportedNpadStyleSet(ServiceCtx context)
|
||||
{
|
||||
ulong pid = context.Request.HandleDesc.PId;
|
||||
ControllerType type = (ControllerType)context.RequestData.ReadInt32();
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, new {
|
||||
appletResourceUserId,
|
||||
type
|
||||
});
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { pid, appletResourceUserId, type });
|
||||
|
||||
context.Device.Hid.Npads.SupportedStyleSets = type;
|
||||
|
||||
|
@ -623,17 +696,15 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
}
|
||||
|
||||
[CommandHipc(101)]
|
||||
// GetSupportedNpadStyleSet(nn::applet::AppletResourceUserId) -> uint nn::hid::NpadStyleTag
|
||||
// GetSupportedNpadStyleSet(pid, nn::applet::AppletResourceUserId) -> uint nn::hid::NpadStyleTag
|
||||
public ResultCode GetSupportedNpadStyleSet(ServiceCtx context)
|
||||
{
|
||||
ulong pid = context.Request.HandleDesc.PId;
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
context.ResponseData.Write((int)context.Device.Hid.Npads.SupportedStyleSets);
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, new {
|
||||
appletResourceUserId,
|
||||
context.Device.Hid.Npads.SupportedStyleSets
|
||||
});
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, context.Device.Hid.Npads.SupportedStyleSets });
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
@ -658,7 +729,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
|||
}
|
||||
}
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, $"{supportedPlayerIds.Length} " + string.Join(",", supportedPlayerIds.ToArray()));
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, $"{supportedPlayerIds.Length} Players: " + string.Join(",", supportedPlayerIds.ToArray()));
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
|
63
Ryujinx.HLE/HOS/Services/Mnpp/IServiceForApplication.cs
Normal file
63
Ryujinx.HLE/HOS/Services/Mnpp/IServiceForApplication.cs
Normal file
|
@ -0,0 +1,63 @@
|
|||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Cpu;
|
||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Mnpp
|
||||
{
|
||||
[Service("mnpp:app")] // 13.0.0+
|
||||
class IServiceForApplication : IpcService
|
||||
{
|
||||
public IServiceForApplication(ServiceCtx context) { }
|
||||
|
||||
[CommandHipc(0)]
|
||||
// Initialize(pid)
|
||||
public ResultCode Initialize(ServiceCtx context)
|
||||
{
|
||||
// Pid placeholder
|
||||
context.RequestData.ReadInt64();
|
||||
ulong pid = context.Request.HandleDesc.PId;
|
||||
|
||||
// TODO: Service calls set:sys GetPlatformRegion.
|
||||
// If the result == 1 (China) it calls arp:r GetApplicationInstanceId and GetApplicationLaunchProperty to get the title id and store it internally.
|
||||
// If not, it does nothing.
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceMnpp, new { pid });
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
[CommandHipc(1)]
|
||||
// SendRawTelemetryData(nn::account::Uid user_id, buffer<bytes, 5> title_id)
|
||||
public ResultCode SendRawTelemetryData(ServiceCtx context)
|
||||
{
|
||||
ulong titleIdInputPosition = context.Request.SendBuff[0].Position;
|
||||
ulong titleIdInputSize = context.Request.SendBuff[0].Size;
|
||||
|
||||
UserId userId = context.RequestData.ReadStruct<UserId>();
|
||||
|
||||
// TODO: Service calls set:sys GetPlatformRegion.
|
||||
// If the result != 1 (China) it returns ResultCode.Success.
|
||||
|
||||
if (userId.IsNull)
|
||||
{
|
||||
return ResultCode.InvalidArgument;
|
||||
}
|
||||
|
||||
if (titleIdInputSize <= 64)
|
||||
{
|
||||
string titleId = MemoryHelper.ReadAsciiString(context.Memory, titleIdInputPosition, (long)titleIdInputSize);
|
||||
|
||||
// TODO: The service stores the titleId internally and seems proceed to some telemetry for China, which is not needed here.
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceMnpp, new { userId, titleId });
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceMnpp, new { userId });
|
||||
|
||||
return ResultCode.InvalidBufferSize;
|
||||
}
|
||||
}
|
||||
}
|
13
Ryujinx.HLE/HOS/Services/Mnpp/ResultCode.cs
Normal file
13
Ryujinx.HLE/HOS/Services/Mnpp/ResultCode.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
namespace Ryujinx.HLE.HOS.Services.Mnpp
|
||||
{
|
||||
enum ResultCode
|
||||
{
|
||||
ModuleId = 239,
|
||||
ErrorCodeShift = 9,
|
||||
|
||||
Success = 0,
|
||||
|
||||
InvalidArgument = (100 << ErrorCodeShift) | ModuleId,
|
||||
InvalidBufferSize = (101 << ErrorCodeShift) | ModuleId
|
||||
}
|
||||
}
|
Reference in a new issue