aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Ryujinx.sln6
-rw-r--r--src/Ryujinx.Graphics.Device/DeviceState.cs5
-rw-r--r--src/Ryujinx.Graphics.Device/SizeCalculator.cs63
-rw-r--r--src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdateTracker.cs5
-rw-r--r--src/Ryujinx.HLE.Generators/CodeGenerator.cs63
-rw-r--r--src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs76
-rw-r--r--src/Ryujinx.HLE.Generators/Ryujinx.HLE.Generators.csproj19
-rw-r--r--src/Ryujinx.HLE.Generators/ServiceSyntaxReceiver.cs24
-rw-r--r--src/Ryujinx.HLE/HOS/Applets/AppletManager.cs33
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs7
-rw-r--r--src/Ryujinx.HLE/Ryujinx.HLE.csproj1
11 files changed, 215 insertions, 87 deletions
diff --git a/Ryujinx.sln b/Ryujinx.sln
index b8304164d..76ebd573f 100644
--- a/Ryujinx.sln
+++ b/Ryujinx.sln
@@ -87,6 +87,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon", "src\Ryuj
87EndProject 87EndProject
88Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}" 88Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}"
89EndProject 89EndProject
90Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
91EndProject
90Global 92Global
91 GlobalSection(SolutionConfigurationPlatforms) = preSolution 93 GlobalSection(SolutionConfigurationPlatforms) = preSolution
92 Debug|Any CPU = Debug|Any CPU 94 Debug|Any CPU = Debug|Any CPU
@@ -249,6 +251,10 @@ Global
249 {7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.Build.0 = Debug|Any CPU 251 {7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
250 {7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.ActiveCfg = Release|Any CPU 252 {7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
251 {7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.Build.0 = Release|Any CPU 253 {7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.Build.0 = Release|Any CPU
254 {B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
255 {B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
256 {B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
257 {B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
252 EndGlobalSection 258 EndGlobalSection
253 GlobalSection(SolutionProperties) = preSolution 259 GlobalSection(SolutionProperties) = preSolution
254 HideSolutionNode = FALSE 260 HideSolutionNode = FALSE
diff --git a/src/Ryujinx.Graphics.Device/DeviceState.cs b/src/Ryujinx.Graphics.Device/DeviceState.cs
index de8582a3b..54178a414 100644
--- a/src/Ryujinx.Graphics.Device/DeviceState.cs
+++ b/src/Ryujinx.Graphics.Device/DeviceState.cs
@@ -39,7 +39,10 @@ namespace Ryujinx.Graphics.Device
39 { 39 {
40 var field = fields[fieldIndex]; 40 var field = fields[fieldIndex];
41 41
42 int sizeOfField = SizeCalculator.SizeOf(field.FieldType); 42 var currentFieldOffset = (int)Marshal.OffsetOf<TState>(field.Name);
43 var nextFieldOffset = fieldIndex + 1 == fields.Length ? Unsafe.SizeOf<TState>() : (int)Marshal.OffsetOf<TState>(fields[fieldIndex + 1].Name);
44
45 int sizeOfField = nextFieldOffset - currentFieldOffset;
43 46
44 for (int i = 0; i < ((sizeOfField + 3) & ~3); i += 4) 47 for (int i = 0; i < ((sizeOfField + 3) & ~3); i += 4)
45 { 48 {
diff --git a/src/Ryujinx.Graphics.Device/SizeCalculator.cs b/src/Ryujinx.Graphics.Device/SizeCalculator.cs
deleted file mode 100644
index 54820ec36..000000000
--- a/src/Ryujinx.Graphics.Device/SizeCalculator.cs
+++ /dev/null
@@ -1,63 +0,0 @@
1using System;
2using System.Reflection;
3
4namespace Ryujinx.Graphics.Device
5{
6 public static class SizeCalculator
7 {
8 public static int SizeOf(Type type)
9 {
10 // Is type a enum type?
11 if (type.IsEnum)
12 {
13 type = type.GetEnumUnderlyingType();
14 }
15
16 // Is type a pointer type?
17 if (type.IsPointer || type == typeof(IntPtr) || type == typeof(UIntPtr))
18 {
19 return IntPtr.Size;
20 }
21
22 // Is type a struct type?
23 if (type.IsValueType && !type.IsPrimitive)
24 {
25 // Check if the struct has a explicit size, if so, return that.
26 if (type.StructLayoutAttribute.Size != 0)
27 {
28 return type.StructLayoutAttribute.Size;
29 }
30
31 // Otherwise we calculate the sum of the sizes of all fields.
32 int size = 0;
33 var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
34
35 for (int fieldIndex = 0; fieldIndex < fields.Length; fieldIndex++)
36 {
37 size += SizeOf(fields[fieldIndex].FieldType);
38 }
39
40 return size;
41 }
42
43 // Primitive types.
44 return (Type.GetTypeCode(type)) switch
45 {
46 TypeCode.SByte => sizeof(sbyte),
47 TypeCode.Byte => sizeof(byte),
48 TypeCode.Int16 => sizeof(short),
49 TypeCode.UInt16 => sizeof(ushort),
50 TypeCode.Int32 => sizeof(int),
51 TypeCode.UInt32 => sizeof(uint),
52 TypeCode.Int64 => sizeof(long),
53 TypeCode.UInt64 => sizeof(ulong),
54 TypeCode.Char => sizeof(char),
55 TypeCode.Single => sizeof(float),
56 TypeCode.Double => sizeof(double),
57 TypeCode.Decimal => sizeof(decimal),
58 TypeCode.Boolean => sizeof(bool),
59 _ => throw new ArgumentException($"Length for type \"{type.Name}\" is unknown."),
60 };
61 }
62 }
63}
diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdateTracker.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdateTracker.cs
index e54855a8f..effcb7bbb 100644
--- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdateTracker.cs
+++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/StateUpdateTracker.cs
@@ -79,7 +79,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
79 { 79 {
80 var field = fields[fieldIndex]; 80 var field = fields[fieldIndex];
81 81
82 int sizeOfField = SizeCalculator.SizeOf(field.FieldType); 82 var currentFieldOffset = (int)Marshal.OffsetOf<TState>(field.Name);
83 var nextFieldOffset = fieldIndex + 1 == fields.Length ? Unsafe.SizeOf<TState>() : (int)Marshal.OffsetOf<TState>(fields[fieldIndex + 1].Name);
84
85 int sizeOfField = nextFieldOffset - currentFieldOffset;
83 86
84 if (fieldToDelegate.TryGetValue(field.Name, out int entryIndex)) 87 if (fieldToDelegate.TryGetValue(field.Name, out int entryIndex))
85 { 88 {
diff --git a/src/Ryujinx.HLE.Generators/CodeGenerator.cs b/src/Ryujinx.HLE.Generators/CodeGenerator.cs
new file mode 100644
index 000000000..7e4848ad3
--- /dev/null
+++ b/src/Ryujinx.HLE.Generators/CodeGenerator.cs
@@ -0,0 +1,63 @@
1using System.Text;
2
3namespace Ryujinx.HLE.Generators
4{
5 class CodeGenerator
6 {
7 private const int IndentLength = 4;
8
9 private readonly StringBuilder _sb;
10 private int _currentIndentCount;
11
12 public CodeGenerator()
13 {
14 _sb = new StringBuilder();
15 }
16
17 public void EnterScope(string header = null)
18 {
19 if (header != null)
20 {
21 AppendLine(header);
22 }
23
24 AppendLine("{");
25 IncreaseIndentation();
26 }
27
28 public void LeaveScope(string suffix = "")
29 {
30 DecreaseIndentation();
31 AppendLine($"}}{suffix}");
32 }
33
34 public void IncreaseIndentation()
35 {
36 _currentIndentCount++;
37 }
38
39 public void DecreaseIndentation()
40 {
41 if (_currentIndentCount - 1 >= 0)
42 {
43 _currentIndentCount--;
44 }
45 }
46
47 public void AppendLine()
48 {
49 _sb.AppendLine();
50 }
51
52 public void AppendLine(string text)
53 {
54 _sb.Append(' ', IndentLength * _currentIndentCount);
55 _sb.AppendLine(text);
56 }
57
58 public override string ToString()
59 {
60 return _sb.ToString();
61 }
62 }
63}
diff --git a/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs b/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs
new file mode 100644
index 000000000..19fdbe197
--- /dev/null
+++ b/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs
@@ -0,0 +1,76 @@
1using Microsoft.CodeAnalysis;
2using Microsoft.CodeAnalysis.CSharp;
3using Microsoft.CodeAnalysis.CSharp.Syntax;
4using System.Linq;
5
6namespace Ryujinx.HLE.Generators
7{
8 [Generator]
9 public class IpcServiceGenerator : ISourceGenerator
10 {
11 public void Execute(GeneratorExecutionContext context)
12 {
13 var syntaxReceiver = (ServiceSyntaxReceiver)context.SyntaxReceiver;
14 CodeGenerator generator = new CodeGenerator();
15
16 generator.AppendLine("using System;");
17 generator.EnterScope($"namespace Ryujinx.HLE.HOS.Services.Sm");
18 generator.EnterScope($"partial class IUserInterface");
19
20 generator.EnterScope($"public IpcService? GetServiceInstance(Type type, ServiceCtx context, object? parameter = null)");
21 foreach (var className in syntaxReceiver.Types)
22 {
23 if (className.Modifiers.Any(SyntaxKind.AbstractKeyword) || className.Modifiers.Any(SyntaxKind.PrivateKeyword) || !className.AttributeLists.Any(x => x.Attributes.Any(y => y.ToString().StartsWith("Service"))))
24 continue;
25 var name = GetFullName(className, context).Replace("global::", "");
26 if (!name.StartsWith("Ryujinx.HLE.HOS.Services"))
27 continue;
28 var constructors = className.ChildNodes().Where(x => x.IsKind(SyntaxKind.ConstructorDeclaration)).Select(y => y as ConstructorDeclarationSyntax);
29
30 if (!constructors.Any(x => x.ParameterList.Parameters.Count >= 1))
31 continue;
32
33 if (constructors.Where(x => x.ParameterList.Parameters.Count >= 1).FirstOrDefault().ParameterList.Parameters[0].Type.ToString() == "ServiceCtx")
34 {
35 generator.EnterScope($"if (type == typeof({GetFullName(className, context)}))");
36 if (constructors.Any(x => x.ParameterList.Parameters.Count == 2))
37 {
38 var type = constructors.Where(x => x.ParameterList.Parameters.Count == 2).FirstOrDefault().ParameterList.Parameters[1].Type;
39 var model = context.Compilation.GetSemanticModel(type.SyntaxTree);
40 var typeSymbol = model.GetSymbolInfo(type).Symbol as INamedTypeSymbol;
41 var fullName = typeSymbol.ToString();
42 generator.EnterScope("if (parameter != null)");
43 generator.AppendLine($"return new {GetFullName(className, context)}(context, ({fullName})parameter);");
44 generator.LeaveScope();
45 }
46
47 if (constructors.Any(x => x.ParameterList.Parameters.Count == 1))
48 {
49 generator.AppendLine($"return new {GetFullName(className, context)}(context);");
50 }
51
52 generator.LeaveScope();
53 }
54 }
55
56 generator.AppendLine("return null;");
57 generator.LeaveScope();
58
59 generator.LeaveScope();
60 generator.LeaveScope();
61 context.AddSource($"IUserInterface.g.cs", generator.ToString());
62 }
63
64 private string GetFullName(ClassDeclarationSyntax syntaxNode, GeneratorExecutionContext context)
65 {
66 var typeSymbol = context.Compilation.GetSemanticModel(syntaxNode.SyntaxTree).GetDeclaredSymbol(syntaxNode);
67
68 return typeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);
69 }
70
71 public void Initialize(GeneratorInitializationContext context)
72 {
73 context.RegisterForSyntaxNotifications(() => new ServiceSyntaxReceiver());
74 }
75 }
76}
diff --git a/src/Ryujinx.HLE.Generators/Ryujinx.HLE.Generators.csproj b/src/Ryujinx.HLE.Generators/Ryujinx.HLE.Generators.csproj
new file mode 100644
index 000000000..eeab9c0e9
--- /dev/null
+++ b/src/Ryujinx.HLE.Generators/Ryujinx.HLE.Generators.csproj
@@ -0,0 +1,19 @@
1<Project Sdk="Microsoft.NET.Sdk">
2
3 <PropertyGroup>
4 <TargetFramework>netstandard2.0</TargetFramework>
5 <EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
6 <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
7 <CompilerGeneratedFilesOutputPath>Generated</CompilerGeneratedFilesOutputPath>
8 <IsRoslynComponent>true</IsRoslynComponent>
9 </PropertyGroup>
10
11 <ItemGroup>
12 <PackageReference Include="Microsoft.CodeAnalysis.Analyzers">
13 <PrivateAssets>all</PrivateAssets>
14 <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
15 </PackageReference>
16 <PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
17 </ItemGroup>
18
19</Project>
diff --git a/src/Ryujinx.HLE.Generators/ServiceSyntaxReceiver.cs b/src/Ryujinx.HLE.Generators/ServiceSyntaxReceiver.cs
new file mode 100644
index 000000000..e4269cb9a
--- /dev/null
+++ b/src/Ryujinx.HLE.Generators/ServiceSyntaxReceiver.cs
@@ -0,0 +1,24 @@
1using Microsoft.CodeAnalysis;
2using Microsoft.CodeAnalysis.CSharp.Syntax;
3using System.Collections.Generic;
4
5namespace Ryujinx.HLE.Generators
6{
7 internal class ServiceSyntaxReceiver : ISyntaxReceiver
8 {
9 public HashSet<ClassDeclarationSyntax> Types = new HashSet<ClassDeclarationSyntax>();
10
11 public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
12 {
13 if (syntaxNode is ClassDeclarationSyntax classDeclaration)
14 {
15 if (classDeclaration.BaseList == null)
16 {
17 return;
18 }
19
20 Types.Add(classDeclaration);
21 }
22 }
23 }
24}
diff --git a/src/Ryujinx.HLE/HOS/Applets/AppletManager.cs b/src/Ryujinx.HLE/HOS/Applets/AppletManager.cs
index 30300f1b6..3c34d5c78 100644
--- a/src/Ryujinx.HLE/HOS/Applets/AppletManager.cs
+++ b/src/Ryujinx.HLE/HOS/Applets/AppletManager.cs
@@ -8,27 +8,24 @@ namespace Ryujinx.HLE.HOS.Applets
8{ 8{
9 static class AppletManager 9 static class AppletManager
10 { 10 {
11 private static readonly Dictionary<AppletId, Type> _appletMapping;
12
13 static AppletManager()
14 {
15 _appletMapping = new Dictionary<AppletId, Type>
16 {
17 { AppletId.Error, typeof(ErrorApplet) },
18 { AppletId.PlayerSelect, typeof(PlayerSelectApplet) },
19 { AppletId.Controller, typeof(ControllerApplet) },
20 { AppletId.SoftwareKeyboard, typeof(SoftwareKeyboardApplet) },
21 { AppletId.LibAppletWeb, typeof(BrowserApplet) },
22 { AppletId.LibAppletShop, typeof(BrowserApplet) },
23 { AppletId.LibAppletOff, typeof(BrowserApplet) },
24 };
25 }
26
27 public static IApplet Create(AppletId applet, Horizon system) 11 public static IApplet Create(AppletId applet, Horizon system)
28 { 12 {
29 if (_appletMapping.TryGetValue(applet, out Type appletClass)) 13 switch (applet)
30 { 14 {
31 return (IApplet)Activator.CreateInstance(appletClass, system); 15 case AppletId.Controller:
16 return new ControllerApplet(system);
17 case AppletId.Error:
18 return new ErrorApplet(system);
19 case AppletId.PlayerSelect:
20 return new PlayerSelectApplet(system);
21 case AppletId.SoftwareKeyboard:
22 return new SoftwareKeyboardApplet(system);
23 case AppletId.LibAppletWeb:
24 return new BrowserApplet(system);
25 case AppletId.LibAppletShop:
26 return new BrowserApplet(system);
27 case AppletId.LibAppletOff:
28 return new BrowserApplet(system);
32 } 29 }
33 30
34 throw new NotImplementedException($"{applet} applet is not implemented."); 31 throw new NotImplementedException($"{applet} applet is not implemented.");
diff --git a/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs b/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs
index 3dc82035f..7a90c664e 100644
--- a/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs
+++ b/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs
@@ -2,6 +2,7 @@ using Ryujinx.Common.Logging;
2using Ryujinx.HLE.HOS.Ipc; 2using Ryujinx.HLE.HOS.Ipc;
3using Ryujinx.HLE.HOS.Kernel; 3using Ryujinx.HLE.HOS.Kernel;
4using Ryujinx.HLE.HOS.Kernel.Ipc; 4using Ryujinx.HLE.HOS.Kernel.Ipc;
5using Ryujinx.HLE.HOS.Services.Apm;
5using Ryujinx.Horizon.Common; 6using Ryujinx.Horizon.Common;
6using System; 7using System;
7using System.Collections.Generic; 8using System.Collections.Generic;
@@ -12,7 +13,7 @@ using System.Text;
12 13
13namespace Ryujinx.HLE.HOS.Services.Sm 14namespace Ryujinx.HLE.HOS.Services.Sm
14{ 15{
15 class IUserInterface : IpcService 16 partial class IUserInterface : IpcService
16 { 17 {
17 private static readonly Dictionary<string, Type> _services; 18 private static readonly Dictionary<string, Type> _services;
18 19
@@ -95,9 +96,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm
95 { 96 {
96 ServiceAttribute serviceAttribute = (ServiceAttribute)type.GetCustomAttributes(typeof(ServiceAttribute)).First(service => ((ServiceAttribute)service).Name == name); 97 ServiceAttribute serviceAttribute = (ServiceAttribute)type.GetCustomAttributes(typeof(ServiceAttribute)).First(service => ((ServiceAttribute)service).Name == name);
97 98
98 IpcService service = serviceAttribute.Parameter != null 99 IpcService service = GetServiceInstance(type, context, serviceAttribute.Parameter);
99 ? (IpcService)Activator.CreateInstance(type, context, serviceAttribute.Parameter)
100 : (IpcService)Activator.CreateInstance(type, context);
101 100
102 service.TrySetServer(_commonServer); 101 service.TrySetServer(_commonServer);
103 service.Server.AddSessionObj(session.ServerSession, service); 102 service.Server.AddSessionObj(session.ServerSession, service);
diff --git a/src/Ryujinx.HLE/Ryujinx.HLE.csproj b/src/Ryujinx.HLE/Ryujinx.HLE.csproj
index 83a11d4e0..a7bb3cd7f 100644
--- a/src/Ryujinx.HLE/Ryujinx.HLE.csproj
+++ b/src/Ryujinx.HLE/Ryujinx.HLE.csproj
@@ -12,6 +12,7 @@
12 <ProjectReference Include="..\Ryujinx.Graphics.Host1x\Ryujinx.Graphics.Host1x.csproj" /> 12 <ProjectReference Include="..\Ryujinx.Graphics.Host1x\Ryujinx.Graphics.Host1x.csproj" />
13 <ProjectReference Include="..\Ryujinx.Graphics.Nvdec\Ryujinx.Graphics.Nvdec.csproj" /> 13 <ProjectReference Include="..\Ryujinx.Graphics.Nvdec\Ryujinx.Graphics.Nvdec.csproj" />
14 <ProjectReference Include="..\Ryujinx.Graphics.Vic\Ryujinx.Graphics.Vic.csproj" /> 14 <ProjectReference Include="..\Ryujinx.Graphics.Vic\Ryujinx.Graphics.Vic.csproj" />
15 <ProjectReference Include="..\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
15 <ProjectReference Include="..\Ryujinx.Horizon.Common\Ryujinx.Horizon.Common.csproj" /> 16 <ProjectReference Include="..\Ryujinx.Horizon.Common\Ryujinx.Horizon.Common.csproj" />
16 <ProjectReference Include="..\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> 17 <ProjectReference Include="..\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
17 <ProjectReference Include="..\Ryujinx.Horizon\Ryujinx.Horizon.csproj" /> 18 <ProjectReference Include="..\Ryujinx.Horizon\Ryujinx.Horizon.csproj" />