Enable full trimming

Enables full trimming for Ryujinx, and in doing so removes many usages of reflection, namely:

IUserService no longer uses reflection to find possible service types, and now has a generated switch based on name

Ryujinx.HLE.HOS.Tamper no longer uses dynamic to do operations, now using INumber<T> and friends

Cmif and Tipc commands in Ryujinx.HLE.HOS.Services no longer get resolved via reflection and are now done via generated virtual methods

Fix things broken by trimming (profile panel, DiscordRPC)
This commit is contained in:
Aaron Robinson 2026-04-13 01:54:32 -05:00 committed by KeatonTheBot
parent 81468c1d25
commit 18dd1be961
178 changed files with 793 additions and 551 deletions

3
.gitignore vendored
View file

@ -185,3 +185,6 @@ PublishProfiles/
# Ignore distribution build files
distribution/macos/temp/
distribution/macos/output/
# MSBuild logs
*.binlog

6
Directory.Build.targets Normal file
View file

@ -0,0 +1,6 @@
<Project>
<PropertyGroup>
<IsTrimmable Condition="'$(IsTrimmable)' == '' AND $([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0'))">true</IsTrimmable>
<EnableTrimAnalyzer Condition="'$(EnableTrimAnalyzer)' == '' AND $([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0'))">true</EnableTrimAnalyzer>
</PropertyGroup>
</Project>

View file

@ -24,7 +24,7 @@
<PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" />
<PackageVersion Include="DynamicData" Version="9.4.31" />
<PackageVersion Include="FluentAvaloniaUI" Version="2.5.1" />
<PackageVersion Include="Humanizer" Version="2.14.1" />
<PackageVersion Include="Humanizer" Version="3.0.1" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.9.2" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.18.0" />
@ -41,6 +41,7 @@
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.9.4" />
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.9.4" />
<PackageVersion Include="Open.NAT.Core" Version="2.1.0.5" />
<PackageVersion Include="PolySharp" Version="1.15.0" />
<!-- Ryujinx.Audio.OpenAL.Dependencies is from the original project, last updated 12/30/20 -->
<!--<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />-->
<PackageVersion Include="Ryujinx.Audio.OpenAL" Version="1.25.1" />

View file

@ -2,12 +2,14 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<IsTrimmable>false</IsTrimmable>
<EnableTrimAnalyzer>false</EnableTrimAnalyzer>
</PropertyGroup>
<Target Name="PostBuildTarget" AfterTargets="AfterBuild">
<Message Text="Running Validation Project" Importance="high" />
<Exec WorkingDirectory="$(ProjectDir)bin\Debug\$(TargetFramework)\"
<Exec WorkingDirectory="$(OutDir)"
Command="dotnet Ryujinx.BuildValidationTasks.dll &quot;$(ProjectDir)..\..\\&quot;"
ConsoleToMsBuild="true"
Condition="'$(RuntimeIdentifier)' == ''"

View file

@ -37,7 +37,9 @@ namespace Ryujinx.Common.Logging.Formatters
return;
}
#pragma warning disable IL2075 // GetProperties is *probably* fine here, it only really matters what exists anyway
PropertyInfo[] props = dynamicObject.GetType().GetProperties();
#pragma warning restore IL2075
sb.Append('{');

View file

@ -0,0 +1,173 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Linq;
using System.Collections.Immutable;
using System.Threading;
namespace Ryujinx.HLE.Generators
{
[Generator]
public class IpcCommandGenerator : IIncrementalGenerator
{
private sealed class CommandData : IEquatable<CommandData>
{
public required string Namespace { get; init; }
public required string TypeName { get; init; }
public required string MethodName { get; init; }
public required ImmutableArray<int> CommandIds { get; init; }
public bool Equals(CommandData other)
{
return Namespace == other.Namespace && TypeName == other.TypeName && MethodName == other.MethodName && CommandIds.SequenceEqual(other.CommandIds);
}
public override bool Equals(object obj)
=> obj is CommandData other && Equals(other);
public override int GetHashCode()
{
unchecked
{
var hashCode = (Namespace != null ? Namespace.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (TypeName != null ? TypeName.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (MethodName != null ? MethodName.GetHashCode() : 0);
return hashCode;
}
}
}
private sealed class ServiceData : IEquatable<ServiceData>
{
public required string Namespace { get; init; }
public required string TypeName { get; init; }
public required ImmutableArray<CommandData> CmifCommands { get; init; }
public required ImmutableArray<CommandData> TipcCommands { get; init; }
public bool Equals(ServiceData other)
{
return Namespace == other.Namespace && TypeName == other.TypeName && CmifCommands.SequenceEqual(other.CmifCommands) && TipcCommands.SequenceEqual(other.TipcCommands);
}
public override bool Equals(object obj)
{
return obj is ServiceData other && Equals(other);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = (Namespace != null ? Namespace.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (TypeName != null ? TypeName.GetHashCode() : 0);
return hashCode;
}
}
}
public void Initialize(IncrementalGeneratorInitializationContext context)
{
Func<SyntaxNode, CancellationToken, bool> predicate = (node, _) => node is MethodDeclarationSyntax;
Func<GeneratorAttributeSyntaxContext, CancellationToken, CommandData> transform = (ctx, _) =>
{
var target = (IMethodSymbol)ctx.TargetSymbol;
return new CommandData
{
Namespace = target.ContainingType.ContainingNamespace?.ToDisplayString(),
TypeName = target.ContainingType.Name,
MethodName = target.Name,
CommandIds = ctx.Attributes.Select(attr => (int)attr.ConstructorArguments[0].Value!).ToImmutableArray(),
};
};
IncrementalValuesProvider<CommandData> cmifCommands =
context.SyntaxProvider.ForAttributeWithMetadataName("Ryujinx.HLE.HOS.Services.CommandCmifAttribute",
predicate,
transform
);
IncrementalValuesProvider<CommandData> tipcCommands =
context.SyntaxProvider.ForAttributeWithMetadataName("Ryujinx.HLE.HOS.Services.CommandTipcAttribute",
predicate,
transform
);
IncrementalValueProvider<(ImmutableArray<CommandData> Left, ImmutableArray<CommandData> Right)> allCommands =
cmifCommands.Collect().Combine(tipcCommands.Collect());
IncrementalValuesProvider<ServiceData> types = allCommands.SelectMany((commands, _) =>
{
ILookup<(string Namespace, string TypeName), CommandData> cmif = commands.Left.ToLookup(c => (c.Namespace, c.TypeName));
ILookup<(string Namespace, string TypeName), CommandData> tipc = commands.Right.ToLookup(c => (c.Namespace, c.TypeName));
ImmutableArray<ServiceData>.Builder builder = ImmutableArray.CreateBuilder<ServiceData>();
foreach ((string Namespace, string TypeName) type in cmif.Select(c => c.Key).Union(tipc.Select(t => t.Key)))
{
builder.Add(new ServiceData
{
Namespace = type.Namespace,
TypeName = type.TypeName,
CmifCommands = cmif.Contains(type) ? cmif[type].ToImmutableArray() : [],
TipcCommands = tipc.Contains(type) ? tipc[type].ToImmutableArray() : [],
});
}
return builder.DrainToImmutable();
});
context.RegisterSourceOutput(types, (ctx, data) =>
{
var generator = new CodeGenerator();
generator.AppendLine("using Ryujinx.HLE.HOS;");
generator.AppendLine("using RC = global::Ryujinx.HLE.HOS.ResultCode;");
generator.EnterScope($"namespace {data.Namespace}");
generator.EnterScope($"partial class {data.TypeName}");
if (!data.CmifCommands.IsEmpty)
{
GenerateCommandMethod("Cmif", data.CmifCommands);
}
if (!data.TipcCommands.IsEmpty)
{
GenerateCommandMethod("Tipc", data.TipcCommands);
}
generator.LeaveScope();
generator.LeaveScope();
ctx.AddSource($"{data.Namespace}.{data.TypeName}.g.cs", generator.ToString());
void GenerateCommandMethod(string commandType, ImmutableArray<CommandData> commands)
{
generator.EnterScope($"protected override RC Invoke{commandType}Method(int id, ServiceCtx context)");
generator.EnterScope("switch (id)");
foreach (CommandData command in commands)
{
generator.AppendLine($"case {string.Join(" or ", command.CommandIds)}:");
generator.IncreaseIndentation();
generator.AppendLine($"LogInvoke(\"{command.MethodName}\");");
generator.AppendLine($"return (RC){command.MethodName}(context);");
generator.DecreaseIndentation();
}
generator.AppendLine($"default: return base.Invoke{commandType}Method(id, context);");
generator.LeaveScope();
generator.LeaveScope();
generator.EnterScope($"public override int {commandType}CommandIdByMethodName(string name)");
generator.EnterScope("return name switch");
foreach (CommandData command in commands)
{
// just return the first command with this name
generator.AppendLine($"\"{command.MethodName}\" => {command.CommandIds[0]},");
}
generator.AppendLine($"_ => base.{commandType}CommandIdByMethodName(name),");
generator.LeaveScope(";");
generator.LeaveScope();
}
});
}
}
}

View file

@ -1,78 +0,0 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Linq;
namespace Ryujinx.HLE.Generators
{
[Generator]
public class IpcServiceGenerator : ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
ServiceSyntaxReceiver syntaxReceiver = (ServiceSyntaxReceiver)context.SyntaxReceiver;
CodeGenerator generator = new();
generator.AppendLine("#nullable enable");
generator.AppendLine("using System;");
generator.EnterScope($"namespace Ryujinx.HLE.HOS.Services.Sm");
generator.EnterScope($"partial class IUserInterface");
generator.EnterScope($"public IpcService? GetServiceInstance(Type type, ServiceCtx context, object? parameter = null)");
foreach (ClassDeclarationSyntax className in syntaxReceiver.Types)
{
if (className.Modifiers.Any(SyntaxKind.AbstractKeyword) || className.Modifiers.Any(SyntaxKind.PrivateKeyword) || !className.AttributeLists.Any(x => x.Attributes.Any(y => y.ToString().StartsWith("Service"))))
continue;
string name = GetFullName(className, context).Replace("global::", string.Empty);
if (!name.StartsWith("Ryujinx.HLE.HOS.Services"))
continue;
ConstructorDeclarationSyntax[] constructors = className.ChildNodes().Where(x => x.IsKind(SyntaxKind.ConstructorDeclaration)).Select(y => y as ConstructorDeclarationSyntax).ToArray();
if (!constructors.Any(x => x.ParameterList.Parameters.Count >= 1))
continue;
if (constructors.Where(x => x.ParameterList.Parameters.Count >= 1).FirstOrDefault().ParameterList.Parameters[0].Type.ToString() == "ServiceCtx")
{
generator.EnterScope($"if (type == typeof({GetFullName(className, context)}))");
if (constructors.Any(x => x.ParameterList.Parameters.Count == 2))
{
TypeSyntax type = constructors.Where(x => x.ParameterList.Parameters.Count == 2).FirstOrDefault().ParameterList.Parameters[1].Type;
SemanticModel model = context.Compilation.GetSemanticModel(type.SyntaxTree);
INamedTypeSymbol typeSymbol = model.GetSymbolInfo(type).Symbol as INamedTypeSymbol;
string fullName = typeSymbol.ToString();
generator.EnterScope("if (parameter != null)");
generator.AppendLine($"return new {GetFullName(className, context)}(context, ({fullName})parameter);");
generator.LeaveScope();
}
if (constructors.Any(x => x.ParameterList.Parameters.Count == 1))
{
generator.AppendLine($"return new {GetFullName(className, context)}(context);");
}
generator.LeaveScope();
}
}
generator.AppendLine("return null;");
generator.LeaveScope();
generator.LeaveScope();
generator.LeaveScope();
generator.AppendLine("#nullable disable");
context.AddSource($"IUserInterface.g.cs", generator.ToString());
}
private string GetFullName(ClassDeclarationSyntax syntaxNode, GeneratorExecutionContext context)
{
INamedTypeSymbol typeSymbol = context.Compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetDeclaredSymbol(syntaxNode);
return typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
}
public void Initialize(GeneratorInitializationContext context)
{
context.RegisterForSyntaxNotifications(() => new ServiceSyntaxReceiver());
}
}
}

View file

@ -3,8 +3,6 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
<IsRoslynComponent>true</IsRoslynComponent>
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
</PropertyGroup>
@ -14,10 +12,14 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" >
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="PolySharp">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>

View file

@ -1,24 +0,0 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Generic;
namespace Ryujinx.HLE.Generators
{
internal class ServiceSyntaxReceiver : ISyntaxReceiver
{
public HashSet<ClassDeclarationSyntax> Types = [];
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
{
if (syntaxNode is ClassDeclarationSyntax classDeclaration)
{
if (classDeclaration.BaseList == null)
{
return;
}
Types.Add(classDeclaration);
}
}
}
}

View file

@ -0,0 +1,93 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Ryujinx.HLE.Generators
{
[Generator]
public sealed class UserServiceGenerator : IIncrementalGenerator
{
private sealed class ServiceData : IEquatable<ServiceData>
{
public required string FullName { get; init; }
public required IReadOnlyList<(string ServiceName, string ParameterValue)> Instances { get; init; }
public override bool Equals(object obj)
=> obj is ServiceData data && Equals(data);
public bool Equals(ServiceData other)
{
return this.FullName == other.FullName && this.Instances.SequenceEqual(other.Instances);
}
public override int GetHashCode() => FullName.GetHashCode();
}
public void Initialize(IncrementalGeneratorInitializationContext context)
{
IncrementalValuesProvider<ServiceData> pipeline = context.SyntaxProvider.ForAttributeWithMetadataName("Ryujinx.HLE.HOS.Services.ServiceAttribute",
predicate: (node, _) => node is ClassDeclarationSyntax decl && !decl.Modifiers.Any(SyntaxKind.AbstractKeyword) && !decl.Modifiers.Any(SyntaxKind.PrivateKeyword),
transform: (ctx, _) =>
{
var target = (INamedTypeSymbol)ctx.TargetSymbol;
IEnumerable<(string, string param)> instances = ctx.Attributes.Select(attr =>
{
string param = attr.ConstructorArguments is [_, { IsNull: false } arg] ? arg.ToCSharpString() : null;
return ((string)attr.ConstructorArguments[0].Value, param);
});
return new ServiceData
{
FullName = target.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
Instances = instances.ToList(),
};
}
);
context.RegisterSourceOutput(pipeline.Collect(),
(ctx, data) =>
{
var generator = new CodeGenerator();
generator.AppendLine("#nullable enable");
generator.AppendLine("using System;");
generator.EnterScope("namespace Ryujinx.HLE.HOS.Services.Sm");
generator.EnterScope("partial class IUserInterface");
generator.EnterScope("public IpcService? GetServiceInstance(string name, ServiceCtx context)");
generator.EnterScope("return name switch");
foreach (ServiceData serviceImpl in data)
{
foreach ((string ServiceName, string ParameterValue) instance in serviceImpl.Instances)
{
if (instance.ParameterValue == null)
{
generator.AppendLine($"\"{instance.ServiceName}\" => new {serviceImpl.FullName}(context),");
}
else
{
generator.AppendLine($"\"{instance.ServiceName}\" => new {serviceImpl.FullName}(context, {instance.ParameterValue}),");
}
}
}
generator.AppendLine("_ => null,");
generator.LeaveScope(";");
generator.LeaveScope();
generator.LeaveScope();
generator.LeaveScope();
generator.AppendLine("#nullable disable");
ctx.AddSource("IUserInterface.g.cs", generator.ToString());
});
}
}
}

View file

@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
namespace Ryujinx.HLE.Exceptions
@ -17,22 +18,22 @@ namespace Ryujinx.HLE.Exceptions
public IpcService Service { get; }
public ServiceCtx Context { get; }
public IpcMessage Request { get; }
private string MethodName { get; }
public ServiceNotImplementedException(IpcService service, ServiceCtx context)
: this(service, context, "The service call is not implemented.") { }
public ServiceNotImplementedException(IpcService service, ServiceCtx context, string message) : base(message)
public ServiceNotImplementedException(IpcService service, ServiceCtx context, string message = "The service call is not implemented.", [CallerMemberName] string methodName = null) : base(message)
{
Service = service;
Context = context;
Request = context.Request;
MethodName = methodName;
}
public ServiceNotImplementedException(IpcService service, ServiceCtx context, string message, Exception inner) : base(message, inner)
public ServiceNotImplementedException(IpcService service, ServiceCtx context, string message, Exception inner, [CallerMemberName] string methodName = null) : base(message, inner)
{
Service = service;
Context = context;
Request = context.Request;
MethodName = methodName;
}
public override string Message
@ -47,25 +48,12 @@ namespace Ryujinx.HLE.Exceptions
{
StringBuilder sb = new();
// Print the IPC command details (service name, command ID, and handler)
(Type callingType, MethodBase callingMethod) = WalkStackTrace(new StackTrace(this));
int commandId = Request.Type > IpcMessageType.TipcCloseSession
? Service.TipcCommandIdByMethodName(MethodName)
: Service.CmifCommandIdByMethodName(MethodName);
if (callingType != null && callingMethod != null)
{
// If the type is past 0xF, we are using TIPC
IReadOnlyDictionary<int, MethodInfo> ipcCommands = Request.Type > IpcMessageType.TipcCloseSession ? Service.TipcCommands : Service.CmifCommands;
// Find the handler for the method called
KeyValuePair<int, MethodInfo> ipcHandler = ipcCommands.FirstOrDefault(x => x.Value == callingMethod);
int ipcCommandId = ipcHandler.Key;
MethodInfo ipcMethod = ipcHandler.Value;
if (ipcMethod != null)
{
sb.AppendLine($"Service Command: {Service.GetType().FullName}: {ipcCommandId} ({ipcMethod.Name})");
sb.AppendLine();
}
}
sb.AppendLine($"Service Command: {Service.GetType().FullName}: {commandId} ({MethodName})");
sb.AppendLine();
sb.AppendLine("Guest Stack Trace:");
sb.AppendLine(Context.Thread.GetGuestStackTrace());
@ -137,26 +125,5 @@ namespace Ryujinx.HLE.Exceptions
return sb.ToString();
}
private static (Type, MethodBase) WalkStackTrace(StackTrace trace)
{
int i = 0;
StackFrame frame;
// Find the IIpcService method that threw this exception
while ((frame = trace.GetFrame(i++)) != null)
{
MethodBase method = frame.GetMethod();
Type declType = method.DeclaringType;
if (typeof(IpcService).IsAssignableFrom(declType))
{
return (declType, method);
}
}
return (null, null);
}
}
}

View file

@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
{
class IManagerForApplication : IpcService
partial class IManagerForApplication : IpcService
{
private readonly ManagerServer _managerServer;

View file

@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
{
class IManagerForSystemService : IpcService
partial class IManagerForSystemService : IpcService
{
private readonly ManagerServer _managerServer;

View file

@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
{
class IProfile : IpcService
partial class IProfile : IpcService
{
private readonly ProfileServer _profileServer;

View file

@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService
{
class IProfileEditor : IpcService
partial class IProfileEditor : IpcService
{
private readonly ProfileServer _profileServer;

View file

@ -5,7 +5,7 @@ using Ryujinx.HLE.HOS.Services.Account.Acc.AccountService;
namespace Ryujinx.HLE.HOS.Services.Account.Acc
{
[Service("acc:su", AccountServiceFlag.Administrator)] // Max Sessions: 8
class IAccountServiceForAdministrator : IpcService
partial class IAccountServiceForAdministrator : IpcService
{
private readonly ApplicationServiceServer _applicationServiceServer;

View file

@ -5,7 +5,7 @@ using Ryujinx.HLE.HOS.Services.Arp;
namespace Ryujinx.HLE.HOS.Services.Account.Acc
{
[Service("acc:u0", AccountServiceFlag.Application)] // Max Sessions: 4
class IAccountServiceForApplication : IpcService
partial class IAccountServiceForApplication : IpcService
{
private readonly ApplicationServiceServer _applicationServiceServer;

View file

@ -4,7 +4,7 @@ using Ryujinx.HLE.HOS.Services.Account.Acc.AccountService;
namespace Ryujinx.HLE.HOS.Services.Account.Acc
{
[Service("acc:u1", AccountServiceFlag.SystemService)] // Max Sessions: 16
class IAccountServiceForSystemService : IpcService
partial class IAccountServiceForSystemService : IpcService
{
private readonly ApplicationServiceServer _applicationServiceServer;

View file

@ -5,7 +5,7 @@ using System;
namespace Ryujinx.HLE.HOS.Services.Account.Acc
{
class IAsyncContext : IpcService
partial class IAsyncContext : IpcService
{
protected AsyncExecution AsyncExecution;

View file

@ -2,7 +2,7 @@ using Ryujinx.HLE.HOS.Services.Account.Acc.AsyncContext;
namespace Ryujinx.HLE.HOS.Services.Account.Acc
{
class IAsyncNetworkServiceLicenseKindContext : IAsyncContext
partial class IAsyncNetworkServiceLicenseKindContext : IAsyncContext
{
private readonly NetworkServiceLicenseKind? _serviceLicenseKind;

View file

@ -3,6 +3,6 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc
[Service("acc:aa", AccountServiceFlag.BaasAccessTokenAccessor)] // Max Sessions: 4
class IBaasAccessTokenAccessor : IpcService
{
public IBaasAccessTokenAccessor(ServiceCtx context) { }
public IBaasAccessTokenAccessor(ServiceCtx context, AccountServiceFlag serviceFlag) { }
}
}

View file

@ -3,7 +3,7 @@ using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemA
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
{
class ILibraryAppletProxy : IpcService
partial class ILibraryAppletProxy : IpcService
{
private readonly ulong _pid;

View file

@ -2,7 +2,7 @@ using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemA
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
{
class ISystemAppletProxy : IpcService
partial class ISystemAppletProxy : IpcService
{
private readonly ulong _pid;

View file

@ -9,7 +9,7 @@ using System;
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletCreator
{
class ILibraryAppletAccessor : DisposableIpcService
partial class ILibraryAppletAccessor : DisposableIpcService
{
private readonly KernelContext _kernelContext;

View file

@ -4,7 +4,7 @@ using System;
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletProxy
{
class ILibraryAppletSelfAccessor : IpcService
partial class ILibraryAppletSelfAccessor : IpcService
{
private readonly AppletStandalone _appletStandalone = new();

View file

@ -2,7 +2,7 @@ using Ryujinx.Common;
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletProxy
{
class IProcessWindingController : IpcService
partial class IProcessWindingController : IpcService
{
public IProcessWindingController() { }

View file

@ -2,7 +2,7 @@ using Ryujinx.Common.Logging;
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
{
class IAudioController : IpcService
partial class IAudioController : IpcService
{
public IAudioController() { }

View file

@ -10,7 +10,7 @@ using System;
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
{
class ICommonStateGetter : DisposableIpcService
partial class ICommonStateGetter : DisposableIpcService
{
private readonly ServiceCtx _context;

View file

@ -6,7 +6,7 @@ using System;
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
{
class IDisplayController : IpcService
partial class IDisplayController : IpcService
{
private readonly KTransferMemory _transferMem;
private bool _lastApplicationCaptureBufferAcquired;

View file

@ -6,7 +6,7 @@ using System;
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
{
class IHomeMenuFunctions : IpcService
partial class IHomeMenuFunctions : IpcService
{
private readonly KEvent _channelEvent;
private int _channelEventHandle;

View file

@ -3,7 +3,7 @@ using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Library
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
{
class ILibraryAppletCreator : IpcService
partial class ILibraryAppletCreator : IpcService
{
public ILibraryAppletCreator() { }

View file

@ -8,7 +8,7 @@ using System.Threading;
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
{
class ISelfController : IpcService
partial class ISelfController : IpcService
{
private readonly ulong _pid;

View file

@ -2,7 +2,7 @@ using Ryujinx.Common.Logging;
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
{
class IWindowController : IpcService
partial class IWindowController : IpcService
{
private readonly ulong _pid;

View file

@ -4,7 +4,7 @@ using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService;
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
{
[Service("appletAE")]
class IAllSystemAppletProxiesService : IpcService
partial class IAllSystemAppletProxiesService : IpcService
{
public IAllSystemAppletProxiesService(ServiceCtx context) { }

View file

@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
{
class IStorage : IpcService
partial class IStorage : IpcService
{
public bool IsReadOnly { get; private set; }
public byte[] Data { get; private set; }

View file

@ -2,7 +2,7 @@ using System;
namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
{
class IStorageAccessor : IpcService
partial class IStorageAccessor : IpcService
{
private readonly IStorage _storage;

View file

@ -22,7 +22,7 @@ using ApplicationId = LibHac.Ncm.ApplicationId;
namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy
{
class IApplicationFunctions : IpcService
partial class IApplicationFunctions : IpcService
{
private long _defaultSaveDataSize = 200000000;
private long _defaultJournalSaveDataSize = 200000000;

View file

@ -3,7 +3,7 @@ using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationPr
namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService
{
class IApplicationProxy : IpcService
partial class IApplicationProxy : IpcService
{
private readonly ulong _pid;

View file

@ -3,7 +3,7 @@ using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService;
namespace Ryujinx.HLE.HOS.Services.Am
{
[Service("appletOE")]
class IApplicationProxyService : IpcService
partial class IApplicationProxyService : IpcService
{
public IApplicationProxyService(ServiceCtx context) { }

View file

@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.Apm
{
abstract class IManager : IpcService
abstract partial class IManager : IpcService
{
public IManager(ServiceCtx context) { }

View file

@ -3,7 +3,7 @@ namespace Ryujinx.HLE.HOS.Services.Apm
// NOTE: This service doesnt exist anymore after firmware 7.0.1. But some outdated homebrew still uses it.
[Service("apm:p")] // 1.0.0-7.0.1
class IManagerPrivileged : IpcService
partial class IManagerPrivileged : IpcService
{
public IManagerPrivileged(ServiceCtx context) { }

View file

@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.Apm
{
abstract class ISession : IpcService
abstract partial class ISession : IpcService
{
public ISession(ServiceCtx context) { }

View file

@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.Apm
{
abstract class ISystemManager : IpcService
abstract partial class ISystemManager : IpcService
{
public ISystemManager(ServiceCtx context) { }

View file

@ -8,7 +8,7 @@ using System;
namespace Ryujinx.HLE.HOS.Services.Bluetooth
{
[Service("btdrv")]
class IBluetoothDriver : IpcService
partial class IBluetoothDriver : IpcService
{
#pragma warning disable CS0414, IDE0052 // Remove unread private member
private string _unknownLowEnergy;

View file

@ -5,7 +5,7 @@ using Ryujinx.HLE.HOS.Services.Settings;
namespace Ryujinx.HLE.HOS.Services.Bluetooth
{
[Service("bt")]
class IBluetoothUser : IpcService
partial class IBluetoothUser : IpcService
{
public IBluetoothUser(ServiceCtx context) { }

View file

@ -5,7 +5,7 @@ using Ryujinx.Horizon.Common;
namespace Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser
{
class IBtmUserCore : IpcService
partial class IBtmUserCore : IpcService
{
public KEvent _bleScanEvent;
public int _bleScanEventHandle;

View file

@ -3,7 +3,7 @@ using Ryujinx.HLE.HOS.Services.BluetoothManager.BtmUser;
namespace Ryujinx.HLE.HOS.Services.BluetoothManager
{
[Service("btm:u")] // 5.0.0+
class IBtmUser : IpcService
partial class IBtmUser : IpcService
{
public IBtmUser(ServiceCtx context) { }

View file

@ -5,7 +5,7 @@ using Ryujinx.HLE.HOS.Services.Caps.Types;
namespace Ryujinx.HLE.HOS.Services.Caps
{
[Service("caps:u")]
class IAlbumApplicationService : IpcService
partial class IAlbumApplicationService : IpcService
{
public IAlbumApplicationService(ServiceCtx context) { }

View file

@ -1,7 +1,7 @@
namespace Ryujinx.HLE.HOS.Services.Caps
{
[Service("caps:c")]
class IAlbumControlService : IpcService
partial class IAlbumControlService : IpcService
{
public IAlbumControlService(ServiceCtx context) { }

View file

@ -4,7 +4,7 @@ using Ryujinx.Horizon.Common;
namespace Ryujinx.HLE.HOS.Services.Ectx
{
class IContextRegistrar : DisposableIpcService
partial class IContextRegistrar : DisposableIpcService
{
public IContextRegistrar(ServiceCtx context) { }

View file

@ -1,7 +1,7 @@
namespace Ryujinx.HLE.HOS.Services.Ectx
{
[Service("ectx:aw")] // 11.0.0+
class IWriterForApplication : IpcService
partial class IWriterForApplication : IpcService
{
public IWriterForApplication(ServiceCtx context) { }

View file

@ -7,7 +7,7 @@ using System.Text;
namespace Ryujinx.HLE.HOS.Services.Fatal
{
[Service("fatal:u")]
class IService : IpcService
partial class IService : IpcService
{
public IService(ServiceCtx context) { }

View file

@ -5,7 +5,7 @@ using Ryujinx.Memory;
namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
{
class IDirectory : DisposableIpcService
partial class IDirectory : DisposableIpcService
{
private SharedRef<LibHac.FsSrv.Sf.IDirectory> _baseDirectory;

View file

@ -7,7 +7,7 @@ using Ryujinx.Memory;
namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
{
class IFile : DisposableIpcService
partial class IFile : DisposableIpcService
{
private SharedRef<LibHac.FsSrv.Sf.IFile> _baseFile;

View file

@ -7,7 +7,7 @@ using Path = LibHac.FsSrv.Sf.Path;
namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
{
class IFileSystem : DisposableIpcService
partial class IFileSystem : DisposableIpcService
{
private SharedRef<LibHac.FsSrv.Sf.IFileSystem> _fileSystem;

View file

@ -10,7 +10,7 @@ using System.Threading;
namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
{
class IStorage : DisposableIpcService
partial class IStorage : DisposableIpcService
{
private SharedRef<LibHac.FsSrv.Sf.IStorage> _baseStorage;

View file

@ -5,7 +5,7 @@ using GameCardHandle = System.UInt32;
namespace Ryujinx.HLE.HOS.Services.Fs
{
class IDeviceOperator : DisposableIpcService
partial class IDeviceOperator : DisposableIpcService
{
private SharedRef<LibHac.FsSrv.Sf.IDeviceOperator> _baseOperator;

View file

@ -25,7 +25,7 @@ using IStorage = LibHac.FsSrv.Sf.IStorage;
namespace Ryujinx.HLE.HOS.Services.Fs
{
[Service("fsp-srv")]
class IFileSystemProxy : DisposableIpcService
partial class IFileSystemProxy : DisposableIpcService
{
private SharedRef<LibHac.FsSrv.Sf.IFileSystemProxy> _baseFileSystemProxy;
private ulong _pid;

View file

@ -4,7 +4,7 @@ using Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy;
namespace Ryujinx.HLE.HOS.Services.Fs
{
class IMultiCommitManager : DisposableIpcService // 6.0.0+
partial class IMultiCommitManager : DisposableIpcService // 6.0.0+
{
private SharedRef<LibHac.FsSrv.Sf.IMultiCommitManager> _baseCommitManager;

View file

@ -5,7 +5,7 @@ using Ryujinx.Memory;
namespace Ryujinx.HLE.HOS.Services.Fs
{
class ISaveDataInfoReader : DisposableIpcService
partial class ISaveDataInfoReader : DisposableIpcService
{
private SharedRef<LibHac.FsSrv.Sf.ISaveDataInfoReader> _baseReader;

View file

@ -1,6 +1,6 @@
namespace Ryujinx.HLE.HOS.Services.Hid.HidServer
{
class IActiveApplicationDeviceList : IpcService
partial class IActiveApplicationDeviceList : IpcService
{
public IActiveApplicationDeviceList() { }

View file

@ -5,7 +5,7 @@ using System;
namespace Ryujinx.HLE.HOS.Services.Hid.HidServer
{
class IAppletResource : IpcService
partial class IAppletResource : IpcService
{
private readonly KSharedMemory _hidSharedMem;
private int _hidSharedMemHandle;

View file

@ -13,7 +13,7 @@ using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Hid
{
[Service("hid")]
class IHidServer : IpcService
partial class IHidServer : IpcService
{
private readonly KEvent _xpadIdEvent;
private readonly KEvent _palmaOperationCompleteEvent;

View file

@ -5,7 +5,7 @@ using Ryujinx.HLE.HOS.Services.Hid.Types;
namespace Ryujinx.HLE.HOS.Services.Hid
{
[Service("hid:sys")]
class IHidSystemServer : IpcService
partial class IHidSystemServer : IpcService
{
public IHidSystemServer(ServiceCtx context) { }

View file

@ -4,7 +4,7 @@ using Ryujinx.Common.Logging;
namespace Ryujinx.HLE.HOS.Services.Hid
{
[Service("hidbus")]
class IHidbusServer : IpcService
partial class IHidbusServer : IpcService
{
public IHidbusServer(ServiceCtx context) { }

View file

@ -9,7 +9,7 @@ using System;
namespace Ryujinx.HLE.HOS.Services.Hid.Irs
{
[Service("irs")]
class IIrSensorServer : IpcService
partial class IIrSensorServer : IpcService
{
private int _irsensorSharedMemoryHandle = 0;

View file

@ -13,9 +13,6 @@ namespace Ryujinx.HLE.HOS.Services
{
abstract class IpcService
{
public IReadOnlyDictionary<int, MethodInfo> CmifCommands { get; }
public IReadOnlyDictionary<int, MethodInfo> TipcCommands { get; }
public ServerBase Server { get; private set; }
private IpcService _parent;
@ -23,46 +20,8 @@ namespace Ryujinx.HLE.HOS.Services
private int _selfId;
private bool _isDomain;
// cache array so we don't recreate it all the time
private object[] _parameters = [null];
public IpcService(ServerBase server = null, bool registerTipc = false)
public IpcService(ServerBase server = null)
{
Stopwatch sw = Stopwatch.StartNew();
CmifCommands = GetType()
.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public)
.SelectMany(methodInfo => methodInfo.GetCustomAttributes<CommandCmifAttribute>()
.Select(command => (command.Id, methodInfo)))
.ToDictionary(command => command.Id, command => command.methodInfo);
sw.Stop();
Logger.Debug?.Print(
LogClass.Emulation,
$"{CmifCommands.Count} Cmif commands loaded in {sw.ElapsedTicks} ticks ({Stopwatch.Frequency} tps).",
GetType().AsPrettyString()
);
if (registerTipc)
{
sw.Start();
TipcCommands = GetType()
.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public)
.SelectMany(methodInfo => methodInfo.GetCustomAttributes<CommandTipcAttribute>()
.Select(command => (command.Id, methodInfo)))
.ToDictionary(command => command.Id, command => command.methodInfo);
sw.Stop();
Logger.Debug?.Print(
LogClass.Emulation,
$"{TipcCommands.Count} Tipc commands loaded in {sw.ElapsedTicks} ticks ({Stopwatch.Frequency} tps).",
GetType().AsPrettyString()
);
}
Server = server;
_parent = this;
@ -87,6 +46,49 @@ namespace Ryujinx.HLE.HOS.Services
_isDomain = false;
}
protected virtual ResultCode InvokeCmifMethod(int id, ServiceCtx context)
{
if (!context.Device.Configuration.IgnoreMissingServices)
{
string dbgMessage = $"{this.GetType().FullName}: {id}";
throw new ServiceNotImplementedException(this, context, dbgMessage);
}
string serviceName = (this is not DummyService dummyService)
? this.GetType().FullName
: dummyService.ServiceName;
Logger.Warning?.Print(LogClass.KernelIpc, $"Missing service {serviceName}: {id} ignored");
return ResultCode.Success;
}
public virtual int CmifCommandIdByMethodName(string name) => -1;
protected virtual ResultCode InvokeTipcMethod(int id, ServiceCtx context)
{
if (!context.Device.Configuration.IgnoreMissingServices)
{
string dbgMessage = $"{this.GetType().FullName}: {id}";
throw new ServiceNotImplementedException(this, context, dbgMessage);
}
string serviceName = (this is not DummyService dummyService)
? this.GetType().FullName
: dummyService.ServiceName;
Logger.Warning?.Print(LogClass.KernelIpc, $"Missing service {serviceName}: {id} ignored");
return ResultCode.Success;
}
public virtual int TipcCommandIdByMethodName(string name) => -1;
protected void LogInvoke(string name)
=> Logger.Trace?.Print(LogClass.KernelIpc, $"{this.GetType().Name}: {name}");
public void CallCmifMethod(ServiceCtx context)
{
IpcService service = this;
@ -137,93 +139,39 @@ namespace Ryujinx.HLE.HOS.Services
#pragma warning restore IDE0059
int commandId = (int)context.RequestData.ReadInt64();
bool serviceExists = service.CmifCommands.TryGetValue(commandId, out MethodInfo processRequest);
context.ResponseData.BaseStream.Seek(_isDomain ? 0x20 : 0x10, SeekOrigin.Begin);
if (context.Device.Configuration.IgnoreMissingServices || serviceExists)
ResultCode result = service.InvokeCmifMethod(commandId, context);
if (_isDomain)
{
ResultCode result = ResultCode.Success;
context.ResponseData.BaseStream.Seek(_isDomain ? 0x20 : 0x10, SeekOrigin.Begin);
if (serviceExists)
foreach (int id in context.Response.ObjectIds)
{
Logger.Trace?.Print(LogClass.KernelIpc, $"{service.GetType().Name}: {processRequest.Name}");
_parameters[0] = context;
result = (ResultCode)processRequest.Invoke(service, _parameters);
}
else
{
string serviceName = (service is not DummyService dummyService) ? service.GetType().FullName : dummyService.ServiceName;
Logger.Warning?.Print(LogClass.KernelIpc, $"Missing service {serviceName}: {commandId} ignored");
context.ResponseData.Write(id);
}
if (_isDomain)
{
foreach (int id in context.Response.ObjectIds)
{
context.ResponseData.Write(id);
}
context.ResponseData.BaseStream.Seek(0, SeekOrigin.Begin);
context.ResponseData.BaseStream.Seek(0, SeekOrigin.Begin);
context.ResponseData.Write(context.Response.ObjectIds.Count);
}
context.ResponseData.BaseStream.Seek(_isDomain ? 0x10 : 0, SeekOrigin.Begin);
context.ResponseData.Write(IpcMagic.Sfco);
context.ResponseData.Write((long)result);
context.ResponseData.Write(context.Response.ObjectIds.Count);
}
else
{
string dbgMessage = $"{service.GetType().FullName}: {commandId}";
throw new ServiceNotImplementedException(service, context, dbgMessage);
}
context.ResponseData.BaseStream.Seek(_isDomain ? 0x10 : 0, SeekOrigin.Begin);
context.ResponseData.Write(IpcMagic.Sfco);
context.ResponseData.Write((long)result);
}
public void CallTipcMethod(ServiceCtx context)
{
int commandId = (int)context.Request.Type - 0x10;
bool serviceExists = TipcCommands.TryGetValue(commandId, out MethodInfo processRequest);
context.ResponseData.BaseStream.Seek(0x4, SeekOrigin.Begin);
if (context.Device.Configuration.IgnoreMissingServices || serviceExists)
{
ResultCode result = ResultCode.Success;
ResultCode result = InvokeTipcMethod(commandId, context);
context.ResponseData.BaseStream.Seek(0x4, SeekOrigin.Begin);
context.ResponseData.BaseStream.Seek(0, SeekOrigin.Begin);
if (serviceExists)
{
Logger.Debug?.Print(LogClass.KernelIpc, $"{GetType().Name}: {processRequest.Name}");
_parameters[0] = context;
result = (ResultCode)processRequest.Invoke(this, _parameters);
}
else
{
string serviceName;
serviceName = (this is not DummyService dummyService) ? GetType().FullName : dummyService.ServiceName;
Logger.Warning?.Print(LogClass.KernelIpc, $"Missing service {serviceName}: {commandId} ignored");
}
context.ResponseData.BaseStream.Seek(0, SeekOrigin.Begin);
context.ResponseData.Write((uint)result);
}
else
{
string dbgMessage = $"{GetType().FullName}: {commandId}";
throw new ServiceNotImplementedException(this, context, dbgMessage);
}
context.ResponseData.Write((uint)result);
}
protected void MakeObject(ServiceCtx context, IpcService obj)

View file

@ -3,7 +3,7 @@ using Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator;
namespace Ryujinx.HLE.HOS.Services.Ldn
{
[Service("ldn:u")]
class IUserServiceCreator : IpcService
partial class IUserServiceCreator : IpcService
{
public IUserServiceCreator(ServiceCtx context) : base(context.Device.System.LdnServer) { }

View file

@ -2,7 +2,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.Lp2p
{
[Service("lp2p:app")] // 9.0.0+
[Service("lp2p:sys")] // 9.0.0+
class IServiceCreator : IpcService
partial class IServiceCreator : IpcService
{
public IServiceCreator(ServiceCtx context) { }

View file

@ -2,7 +2,7 @@ using Ryujinx.Common.Logging;
namespace Ryujinx.HLE.HOS.Services.Ldn.Lp2p
{
class ISfService : IpcService
partial class ISfService : IpcService
{
public ISfService(ServiceCtx context) { }

View file

@ -6,7 +6,7 @@ using System;
namespace Ryujinx.HLE.HOS.Services.Ldn.Lp2p
{
class ISfServiceMonitor : IpcService
partial class ISfServiceMonitor : IpcService
{
private readonly KEvent _stateChangeEvent;
private readonly KEvent _jointEvent;

View file

@ -2,7 +2,7 @@ using Ryujinx.Common.Logging;
namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
{
class IClientProcessMonitor : DisposableIpcService
partial class IClientProcessMonitor : DisposableIpcService
{
public IClientProcessMonitor(ServiceCtx context) { }

View file

@ -21,7 +21,7 @@ using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
{
class IUserLocalCommunicationService : IpcService, IDisposable
partial class IUserLocalCommunicationService : IpcService, IDisposable
{
public INetworkClient NetworkClient { get; private set; }

View file

@ -3,7 +3,7 @@ using Ryujinx.Common.Logging;
namespace Ryujinx.HLE.HOS.Services.Mii
{
[Service("miiimg")] // 5.0.0+
class IImageDatabaseService : IpcService
partial class IImageDatabaseService : IpcService
{
private uint _imageCount;
private bool _isDirty;

View file

@ -6,7 +6,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii
{
[Service("mii:e", true)]
[Service("mii:u", false)]
class IStaticService : IpcService
partial class IStaticService : IpcService
{
private readonly DatabaseImpl _databaseImpl;

View file

@ -6,7 +6,7 @@ using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Services.Mii.StaticService
{
abstract class IDatabaseService : IpcService
abstract partial class IDatabaseService : IpcService
{
[CommandCmif(0)]
// IsUpdated(SourceFlag flag) -> bool

View file

@ -6,7 +6,7 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
namespace Ryujinx.HLE.HOS.Services.Mnpp
{
[Service("mnpp:app")] // 13.0.0+
class IServiceForApplication : IpcService
partial class IServiceForApplication : IpcService
{
public IServiceForApplication(ServiceCtx context) { }

View file

@ -4,7 +4,7 @@ using Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager;
namespace Ryujinx.HLE.HOS.Services.Ncm.Lr
{
[Service("lr")]
class ILocationResolverManager : IpcService
partial class ILocationResolverManager : IpcService
{
public ILocationResolverManager(ServiceCtx context) { }

View file

@ -6,7 +6,7 @@ using static Ryujinx.HLE.Utilities.StringUtils;
namespace Ryujinx.HLE.HOS.Services.Ncm.Lr.LocationResolverManager
{
class ILocationResolver : IpcService
partial class ILocationResolver : IpcService
{
private readonly StorageId _storageId;

View file

@ -3,7 +3,7 @@ using Ryujinx.HLE.HOS.Services.Nfc.NfcManager;
namespace Ryujinx.HLE.HOS.Services.Nfc
{
[Service("nfc:sys")]
class ISystemManager : IpcService
partial class ISystemManager : IpcService
{
public ISystemManager(ServiceCtx context) { }

View file

@ -3,7 +3,7 @@ using Ryujinx.HLE.HOS.Services.Nfc.NfcManager;
namespace Ryujinx.HLE.HOS.Services.Nfc
{
[Service("nfc:user")]
class IUserManager : IpcService
partial class IUserManager : IpcService
{
public IUserManager(ServiceCtx context) { }

View file

@ -2,7 +2,7 @@ using Ryujinx.Common.Logging;
namespace Ryujinx.HLE.HOS.Services.Nfc.NfcManager
{
class INfc : IpcService
partial class INfc : IpcService
{
private readonly NfcPermissionLevel _permissionLevel;
private State _state;

View file

@ -3,7 +3,7 @@ using Ryujinx.HLE.HOS.Services.Nfc.Nfp.NfpManager;
namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
{
[Service("nfp:dbg")]
class IAmManager : IpcService
partial class IAmManager : IpcService
{
public IAmManager(ServiceCtx context) { }

View file

@ -3,7 +3,7 @@ using Ryujinx.HLE.HOS.Services.Nfc.Nfp.NfpManager;
namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
{
[Service("nfp:sys")]
class ISystemManager : IpcService
partial class ISystemManager : IpcService
{
public ISystemManager(ServiceCtx context) { }

View file

@ -3,7 +3,7 @@ using Ryujinx.HLE.HOS.Services.Nfc.Nfp.NfpManager;
namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
{
[Service("nfp:user")]
class IUserManager : IpcService
partial class IUserManager : IpcService
{
public IUserManager(ServiceCtx context) { }

View file

@ -16,7 +16,7 @@ using System.Threading.Tasks;
namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
{
class INfp : IpcService
partial class INfp : IpcService
{
#pragma warning disable IDE0052 // Remove unread private member
private ulong _appletResourceUserId;

View file

@ -1,7 +1,7 @@
namespace Ryujinx.HLE.HOS.Services.Ngct
{
[Service("ngct:u")] // 9.0.0+
class IService : IpcService
partial class IService : IpcService
{
public IService(ServiceCtx context) { }

View file

@ -1,7 +1,7 @@
namespace Ryujinx.HLE.HOS.Services.Ngct
{
[Service("ngct:s")] // 9.0.0+
class IServiceWithManagementApi : IpcService
partial class IServiceWithManagementApi : IpcService
{
public IServiceWithManagementApi(ServiceCtx context) { }

View file

@ -5,7 +5,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm
[Service("nifm:a")] // Max sessions: 2
[Service("nifm:s")] // Max sessions: 16
[Service("nifm:u")] // Max sessions: 5
class IStaticService : IpcService
partial class IStaticService : IpcService
{
public IStaticService(ServiceCtx context) { }

View file

@ -10,7 +10,7 @@ using System.Runtime.CompilerServices;
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
{
class IGeneralService : DisposableIpcService
partial class IGeneralService : DisposableIpcService
{
private readonly GeneralServiceDetail _generalServiceDetail;

View file

@ -6,7 +6,7 @@ using System;
namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
{
class IRequest : IpcService
partial class IRequest : IpcService
{
private enum RequestState
{

View file

@ -3,7 +3,7 @@ using Ryujinx.HLE.HOS.Services.Nim.ShopServiceAccessServerInterface.ShopServiceA
namespace Ryujinx.HLE.HOS.Services.Nim.ShopServiceAccessServerInterface
{
class IShopServiceAccessServer : IpcService
partial class IShopServiceAccessServer : IpcService
{
public IShopServiceAccessServer() { }

View file

@ -6,7 +6,7 @@ using Ryujinx.HLE.HOS.Services.Nim.ShopServiceAccessServerInterface;
namespace Ryujinx.HLE.HOS.Services.Nim
{
[Service("nim:eca")] // 5.0.0+
class IShopServiceAccessServerInterface : IpcService
partial class IShopServiceAccessServerInterface : IpcService
{
public IShopServiceAccessServerInterface(ServiceCtx context) { }

View file

@ -7,7 +7,7 @@ using System;
namespace Ryujinx.HLE.HOS.Services.Nim.ShopServiceAccessServerInterface.ShopServiceAccessServer
{
class IShopServiceAccessor : IpcService
partial class IShopServiceAccessor : IpcService
{
private readonly KEvent _event;

View file

@ -4,7 +4,7 @@ using Ryujinx.HLE.HOS.Services.Nim.Ntc.StaticService;
namespace Ryujinx.HLE.HOS.Services.Nim.Ntc
{
[Service("ntc")]
class IStaticService : IpcService
partial class IStaticService : IpcService
{
public IStaticService(ServiceCtx context) { }

View file

@ -6,7 +6,7 @@ using System;
namespace Ryujinx.HLE.HOS.Services.Nim.Ntc.StaticService
{
class IEnsureNetworkClockAvailabilityService : IpcService
partial class IEnsureNetworkClockAvailabilityService : IpcService
{
private readonly KEvent _finishNotificationEvent;
private ResultCode _taskResultCode;

View file

@ -8,7 +8,7 @@ using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
{
[Service("aoc:u")]
class IAddOnContentManager : IpcService
partial class IAddOnContentManager : IpcService
{
private readonly KEvent _addOnContentListChangedEvent;
private int _addOnContentListChangedEventHandle;

View file

@ -6,7 +6,7 @@ using System;
namespace Ryujinx.HLE.HOS.Services.Ns.Aoc
{
class IPurchaseEventManager : IpcService
partial class IPurchaseEventManager : IpcService
{
private readonly KEvent _purchasedEvent;

View file

@ -4,7 +4,7 @@ using Ryujinx.Common.Utilities;
namespace Ryujinx.HLE.HOS.Services.Ns
{
[Service("ns:am")]
class IApplicationManagerInterface : IpcService
partial class IApplicationManagerInterface : IpcService
{
public IApplicationManagerInterface(ServiceCtx context) { }

View file

@ -3,7 +3,7 @@ using LibHac.Ns;
namespace Ryujinx.HLE.HOS.Services.Ns
{
class IReadOnlyApplicationControlDataInterface : IpcService
partial class IReadOnlyApplicationControlDataInterface : IpcService
{
public IReadOnlyApplicationControlDataInterface(ServiceCtx context) { }

Some files were not shown because too many files have changed in this diff Show more