mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2026-01-12 02:31:08 +00:00
Move Tipc commands and fix remaining warnings
This commit is contained in:
parent
8e1e2d69df
commit
73406d1f3a
11 changed files with 86 additions and 118 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -185,3 +185,6 @@ PublishProfiles/
|
|||
# Ignore distribution build files
|
||||
distribution/macos/temp/
|
||||
distribution/macos/output/
|
||||
|
||||
# MSBuild logs
|
||||
*.binlog
|
||||
|
|
|
|||
|
|
@ -2,8 +2,5 @@
|
|||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<IsTrimmable Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0'))">true</IsTrimmable>
|
||||
<EnableTrimAnalyzer>true</EnableTrimAnalyzer>
|
||||
<UseArtifactsOutput>true</UseArtifactsOutput>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
|
|
|
|||
6
Directory.Build.targets
Normal file
6
Directory.Build.targets
Normal 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>
|
||||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<IsTrimmable>false</IsTrimmable>
|
||||
<EnableTrimAnalyzer>false</EnableTrimAnalyzer>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="PostBuildTarget" AfterTargets="AfterBuild">
|
||||
|
|
|
|||
|
|
@ -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('{');
|
||||
|
||||
|
|
|
|||
|
|
@ -83,35 +83,41 @@ namespace Ryujinx.HLE.Generators
|
|||
generator.EnterScope($"namespace {data.Namespace}");
|
||||
generator.EnterScope($"partial class {data.TypeName}");
|
||||
|
||||
generator.EnterScope("protected override RC InvokeCmifMethod(int id, ServiceCtx context)");
|
||||
generator.EnterScope("switch (id)");
|
||||
foreach (var command in data.CmifCommands)
|
||||
{
|
||||
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.InvokeCmifMethod(id, context);");
|
||||
generator.LeaveScope();
|
||||
generator.LeaveScope();
|
||||
|
||||
generator.EnterScope("public override int CmifCommandIdByMethodName(string name)");
|
||||
generator.EnterScope("return name switch");
|
||||
foreach (var command in data.CmifCommands)
|
||||
{
|
||||
// just return the first command with this name
|
||||
generator.AppendLine($"\"{command.MethodName}\" => {command.CommandIds[0]},");
|
||||
}
|
||||
generator.AppendLine("_ => base.CmifCommandIdByMethodName(name),");
|
||||
generator.LeaveScope(";");
|
||||
generator.LeaveScope();
|
||||
GenerateCommandMethod("Cmif", data.CmifCommands);
|
||||
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 (var 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 (var 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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ namespace Ryujinx.HLE.Exceptions
|
|||
StringBuilder sb = new();
|
||||
|
||||
var commandId = Request.Type > IpcMessageType.TipcCloseSession
|
||||
? -1 // TODO: tipc name
|
||||
? Service.TipcCommandIdByMethodName(MethodName)
|
||||
: Service.CmifCommandIdByMethodName(MethodName);
|
||||
|
||||
sb.AppendLine($"Service Command: {Service.GetType().FullName}: {commandId} ({MethodName})");
|
||||
|
|
|
|||
|
|
@ -11,10 +11,8 @@ using System.Reflection;
|
|||
|
||||
namespace Ryujinx.HLE.HOS.Services
|
||||
{
|
||||
abstract partial class IpcService
|
||||
abstract class IpcService
|
||||
{
|
||||
public IReadOnlyDictionary<int, MethodInfo> TipcCommands { get; }
|
||||
|
||||
public ServerBase Server { get; private set; }
|
||||
|
||||
private IpcService _parent;
|
||||
|
|
@ -24,25 +22,6 @@ namespace Ryujinx.HLE.HOS.Services
|
|||
|
||||
public IpcService(ServerBase server = null)
|
||||
{
|
||||
if (true)
|
||||
{
|
||||
var sw = Stopwatch.StartNew();
|
||||
|
||||
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;
|
||||
|
|
@ -85,11 +64,31 @@ namespace Ryujinx.HLE.HOS.Services
|
|||
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 virtual int CmifCommandIdByMethodName(string name) => -1;
|
||||
|
||||
public void CallCmifMethod(ServiceCtx context)
|
||||
{
|
||||
IpcService service = this;
|
||||
|
|
@ -166,39 +165,13 @@ namespace Ryujinx.HLE.HOS.Services
|
|||
{
|
||||
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}");
|
||||
|
||||
result = (ResultCode)processRequest.Invoke(this, [context]);
|
||||
}
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -32,20 +32,20 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
|||
"/dev/nvhost-prof-gpu"
|
||||
];
|
||||
|
||||
private static readonly Dictionary<string, Type> _deviceFileRegistry = new()
|
||||
private static readonly Dictionary<string, Func<ServiceCtx, IVirtualMemoryManager, ulong, NvDeviceFile>> _deviceFileRegistry = new()
|
||||
{
|
||||
{ "/dev/nvmap", typeof(NvMapDeviceFile) },
|
||||
{ "/dev/nvhost-ctrl", typeof(NvHostCtrlDeviceFile) },
|
||||
{ "/dev/nvhost-ctrl-gpu", typeof(NvHostCtrlGpuDeviceFile) },
|
||||
{ "/dev/nvhost-as-gpu", typeof(NvHostAsGpuDeviceFile) },
|
||||
{ "/dev/nvhost-gpu", typeof(NvHostGpuDeviceFile) },
|
||||
//{ "/dev/nvhost-msenc", typeof(NvHostChannelDeviceFile) },
|
||||
{ "/dev/nvhost-nvdec", typeof(NvHostChannelDeviceFile) },
|
||||
//{ "/dev/nvhost-nvjpg", typeof(NvHostChannelDeviceFile) },
|
||||
{ "/dev/nvhost-vic", typeof(NvHostChannelDeviceFile) },
|
||||
//{ "/dev/nvhost-display", typeof(NvHostChannelDeviceFile) },
|
||||
{ "/dev/nvhost-dbg-gpu", typeof(NvHostDbgGpuDeviceFile) },
|
||||
{ "/dev/nvhost-prof-gpu", typeof(NvHostProfGpuDeviceFile) },
|
||||
{ "/dev/nvmap", (ctx, mem, owner) => new NvMapDeviceFile(ctx, mem, owner) },
|
||||
{ "/dev/nvhost-ctrl", (ctx, mem, owner) => new NvHostCtrlDeviceFile(ctx, mem, owner) },
|
||||
{ "/dev/nvhost-ctrl-gpu", (ctx, mem, owner) => new NvHostCtrlGpuDeviceFile(ctx, mem, owner) },
|
||||
{ "/dev/nvhost-as-gpu", (ctx, mem, owner) => new NvHostAsGpuDeviceFile(ctx, mem, owner) },
|
||||
{ "/dev/nvhost-gpu", (ctx, mem, owner) => new NvHostGpuDeviceFile(ctx, mem, owner) },
|
||||
//{ "/dev/nvhost-msenc", (ctx, mem, owner) => new NvHostChannelDeviceFile(ctx, mem, owner) },
|
||||
{ "/dev/nvhost-nvdec", (ctx, mem, owner) => new NvHostChannelDeviceFile(ctx, mem, owner) },
|
||||
//{ "/dev/nvhost-nvjpg", (ctx, mem, owner) => new NvHostChannelDeviceFile(ctx, mem, owner) },
|
||||
{ "/dev/nvhost-vic", (ctx, mem, owner) => new NvHostChannelDeviceFile(ctx, mem, owner) },
|
||||
//{ "/dev/nvhost-display", (ctx, mem, owner) => new NvHostChannelDeviceFile(ctx, mem, owner) },
|
||||
{ "/dev/nvhost-dbg-gpu", (ctx, mem, owner) => new NvHostDbgGpuDeviceFile(ctx, mem, owner) },
|
||||
{ "/dev/nvhost-prof-gpu", (ctx, mem, owner) => new NvHostProfGpuDeviceFile(ctx, mem, owner) },
|
||||
};
|
||||
|
||||
private static readonly ArrayPool<byte> _byteArrayPool = ArrayPool<byte>.Create();
|
||||
|
|
@ -78,12 +78,9 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
|||
return NvResult.NotSupported;
|
||||
}
|
||||
|
||||
if (_deviceFileRegistry.TryGetValue(path, out Type deviceFileClass))
|
||||
if (_deviceFileRegistry.TryGetValue(path, out Func<ServiceCtx, IVirtualMemoryManager, ulong, NvDeviceFile> deviceFileFactory))
|
||||
{
|
||||
ConstructorInfo constructor = deviceFileClass.GetConstructor([typeof(ServiceCtx), typeof(IVirtualMemoryManager), typeof(ulong)
|
||||
]);
|
||||
|
||||
NvDeviceFile deviceFile = (NvDeviceFile)constructor.Invoke([context, _clientMemory, _owner]);
|
||||
NvDeviceFile deviceFile = deviceFileFactory(context, _clientMemory, _owner);
|
||||
|
||||
deviceFile.Path = path;
|
||||
|
||||
|
|
|
|||
|
|
@ -28,21 +28,12 @@
|
|||
<PublishTrimmed>true</PublishTrimmed>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'win-arm64'">
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<PublishTrimmed>false</PublishTrimmed>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
FluentAvalonia, used in the Avalonia UI, requires a workaround for the json serializer used internally when using .NET 8+ System.Text.Json.
|
||||
See:
|
||||
https://github.com/amwx/FluentAvalonia/issues/481
|
||||
https://devblogs.microsoft.com/dotnet/system-text-json-in-dotnet-8/
|
||||
-->
|
||||
|
||||
<PropertyGroup>
|
||||
<JsonSerializerIsReflectionEnabledByDefault>true</JsonSerializerIsReflectionEnabledByDefault>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" />
|
||||
|
|
@ -179,8 +170,4 @@
|
|||
<ItemGroup>
|
||||
<AdditionalFiles Include="..\..\assets\Locales\*.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<TrimmerRootDescriptor Include="TrimmerRoots.xml" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
<linker>
|
||||
<assembly fullname="Ryujinx.HLE">
|
||||
<type fullname="Ryujinx.HLE.HOS.Services*" preserve="all"/>
|
||||
</assembly>
|
||||
</linker>
|
||||
Loading…
Reference in a new issue