From 4f5eea341718dd187b01f37fb133629530360395 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 19 Nov 2025 00:32:38 -0600 Subject: [PATCH 01/10] Enable full trimming --- Directory.Build.props | 3 +++ src/Ryujinx/Ryujinx.csproj | 5 ++++- src/Ryujinx/TrimmerRoots.xml | 5 +++++ 3 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 src/Ryujinx/TrimmerRoots.xml diff --git a/Directory.Build.props b/Directory.Build.props index a4df830a3..d20dcd0eb 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,5 +2,8 @@ net10.0 preview + true + true + true diff --git a/src/Ryujinx/Ryujinx.csproj b/src/Ryujinx/Ryujinx.csproj index ddb013412..fd17db406 100644 --- a/src/Ryujinx/Ryujinx.csproj +++ b/src/Ryujinx/Ryujinx.csproj @@ -26,7 +26,6 @@ true false true - partial @@ -180,4 +179,8 @@ + + + + diff --git a/src/Ryujinx/TrimmerRoots.xml b/src/Ryujinx/TrimmerRoots.xml new file mode 100644 index 000000000..1db3915e7 --- /dev/null +++ b/src/Ryujinx/TrimmerRoots.xml @@ -0,0 +1,5 @@ + + + + + From 00021121eaedc2f791f5c3fd487c18fded949fc1 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 19 Nov 2025 00:33:17 -0600 Subject: [PATCH 02/10] Remove dynamic usage from Ryujinx.HLE (will come back to make this not generic explode) --- .../HOS/Tamper/CodeEmitters/Arithmetic.cs | 37 +++++---------- .../HOS/Tamper/CodeEmitters/DebugLog.cs | 11 ++++- .../Tamper/CodeEmitters/LegacyArithmetic.cs | 14 +++--- .../CodeEmitters/LoadRegisterWithMemory.cs | 3 +- .../CodeEmitters/StoreConstantToAddress.cs | 4 +- .../CodeEmitters/StoreConstantToMemory.cs | 2 +- .../CodeEmitters/StoreRegisterToMemory.cs | 2 +- .../HOS/Tamper/Conditions/CondEQ.cs | 8 +++- .../HOS/Tamper/Conditions/CondGE.cs | 8 +++- .../HOS/Tamper/Conditions/CondGT.cs | 8 +++- .../HOS/Tamper/Conditions/CondLE.cs | 8 +++- .../HOS/Tamper/Conditions/CondLT.cs | 8 +++- .../HOS/Tamper/Conditions/CondNE.cs | 8 +++- .../HOS/Tamper/Conditions/ICondition.cs | 6 +++ .../HOS/Tamper/InstructionHelper.cs | 47 ++++++++++--------- .../HOS/Tamper/Operations/IOperand.cs | 6 ++- .../HOS/Tamper/Operations/IOperation.cs | 6 +++ .../HOS/Tamper/Operations/OpAdd.cs | 9 +++- .../HOS/Tamper/Operations/OpAnd.cs | 9 +++- .../HOS/Tamper/Operations/OpLog.cs | 5 +- .../HOS/Tamper/Operations/OpLsh.cs | 9 +++- .../HOS/Tamper/Operations/OpMov.cs | 7 ++- .../HOS/Tamper/Operations/OpMul.cs | 9 +++- .../HOS/Tamper/Operations/OpNot.cs | 9 +++- src/Ryujinx.HLE/HOS/Tamper/Operations/OpOr.cs | 9 +++- .../HOS/Tamper/Operations/OpRsh.cs | 9 +++- .../HOS/Tamper/Operations/OpSub.cs | 9 +++- .../HOS/Tamper/Operations/OpXor.cs | 9 +++- src/Ryujinx.HLE/HOS/Tamper/Pointer.cs | 5 +- src/Ryujinx.HLE/HOS/Tamper/Register.cs | 9 ++-- src/Ryujinx.HLE/HOS/Tamper/Value.cs | 11 +++-- 31 files changed, 198 insertions(+), 106 deletions(-) diff --git a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/Arithmetic.cs b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/Arithmetic.cs index ce1b91cec..d0a2e2aa1 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/Arithmetic.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/Arithmetic.cs @@ -1,7 +1,5 @@ using Ryujinx.HLE.Exceptions; using Ryujinx.HLE.HOS.Tamper.Operations; -using System; -using System.Collections.Generic; namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters { @@ -71,53 +69,42 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters throw new TamperCompilationException($"Invalid right-hand side switch {rightHandSideIsImmediate} in Atmosphere cheat"); } - void Emit(Type operationType, IOperand rhs = null) + void EmitCore(IOperand rhs = null) where TOp : IOperation { - List operandList = - [ - destinationRegister, - leftHandSideRegister - ]; - - if (rhs != null) - { - operandList.Add(rhs); - } - - InstructionHelper.Emit(operationType, operationWidth, context, operandList.ToArray()); + InstructionHelper.Emit(operationWidth, context, destinationRegister, leftHandSideRegister, rhs); } switch (operation) { case Add: - Emit(typeof(OpAdd<>), rightHandSideOperand); + EmitCore>(rightHandSideOperand); break; case Sub: - Emit(typeof(OpSub<>), rightHandSideOperand); + EmitCore>(rightHandSideOperand); break; case Mul: - Emit(typeof(OpMul<>), rightHandSideOperand); + EmitCore>(rightHandSideOperand); break; case Lsh: - Emit(typeof(OpLsh<>), rightHandSideOperand); + EmitCore>(rightHandSideOperand); break; case Rsh: - Emit(typeof(OpRsh<>), rightHandSideOperand); + EmitCore>(rightHandSideOperand); break; case And: - Emit(typeof(OpAnd<>), rightHandSideOperand); + EmitCore>(rightHandSideOperand); break; case Or: - Emit(typeof(OpOr<>), rightHandSideOperand); + EmitCore>(rightHandSideOperand); break; case Not: - Emit(typeof(OpNot<>)); + EmitCore>(); break; case Xor: - Emit(typeof(OpXor<>), rightHandSideOperand); + EmitCore>(rightHandSideOperand); break; case Mov: - Emit(typeof(OpMov<>)); + EmitCore>(); break; default: throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat"); diff --git a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/DebugLog.cs b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/DebugLog.cs index d74a998f4..771b87d1a 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/DebugLog.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/DebugLog.cs @@ -1,5 +1,6 @@ using Ryujinx.HLE.Exceptions; using Ryujinx.HLE.HOS.Tamper.Operations; +using System; namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters { @@ -81,7 +82,15 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters throw new TamperCompilationException($"Invalid operand type {operandType} in Atmosphere cheat"); } - InstructionHelper.Emit(typeof(OpLog<>), operationWidth, context, logId, sourceOperand); + IOperation op = operationWidth switch + { + 1 => new OpLog(logId, sourceOperand), + 2 => new OpLog(logId, sourceOperand), + 4 => new OpLog(logId, sourceOperand), + 8 => new OpLog(logId, sourceOperand), + _ => throw new NotSupportedException(), + }; + InstructionHelper.Emit(op, context); } } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/LegacyArithmetic.cs b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/LegacyArithmetic.cs index 3f222864f..df60b058d 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/LegacyArithmetic.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/LegacyArithmetic.cs @@ -37,27 +37,27 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters ulong immediate = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, ValueImmediateSize); Value rightHandSideValue = new(immediate); - void Emit(Type operationType) + void EmitCore() where TOp : IOperation { - InstructionHelper.Emit(operationType, operationWidth, context, register, register, rightHandSideValue); + InstructionHelper.Emit(operationWidth, context, register, register, rightHandSideValue); } switch (operation) { case Add: - Emit(typeof(OpAdd<>)); + EmitCore>(); break; case Sub: - Emit(typeof(OpSub<>)); + EmitCore>(); break; case Mul: - Emit(typeof(OpMul<>)); + EmitCore>(); break; case Lsh: - Emit(typeof(OpLsh<>)); + EmitCore>(); break; case Rsh: - Emit(typeof(OpRsh<>)); + EmitCore>(); break; default: throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat"); diff --git a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/LoadRegisterWithMemory.cs b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/LoadRegisterWithMemory.cs index 3440efcec..183f4dd2f 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/LoadRegisterWithMemory.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/LoadRegisterWithMemory.cs @@ -1,4 +1,5 @@ using Ryujinx.HLE.Exceptions; +using Ryujinx.HLE.HOS.Tamper.Operations; namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters { @@ -52,7 +53,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters throw new TamperCompilationException($"Invalid source mode {useDestinationAsSourceIndex} in Atmosphere cheat"); } - InstructionHelper.EmitMov(operationWidth, context, destinationRegister, sourceMemory); + InstructionHelper.Emit>(operationWidth, context, destinationRegister, sourceMemory, null); } } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreConstantToAddress.cs b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreConstantToAddress.cs index 537166798..beb61b459 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreConstantToAddress.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreConstantToAddress.cs @@ -1,3 +1,5 @@ +using Ryujinx.HLE.HOS.Tamper.Operations; + namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters { /// @@ -35,7 +37,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters ulong valueImmediate = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, valueImmediateSize); Value storeValue = new(valueImmediate); - InstructionHelper.EmitMov(operationWidth, context, dstMem, storeValue); + InstructionHelper.Emit>(operationWidth, context, dstMem, storeValue, null); } } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreConstantToMemory.cs b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreConstantToMemory.cs index 27a99bb63..8426592ba 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreConstantToMemory.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreConstantToMemory.cs @@ -51,7 +51,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters throw new TamperCompilationException($"Invalid offset mode {useOffsetRegister} in Atmosphere cheat"); } - InstructionHelper.EmitMov(operationWidth, context, destinationMemory, storeValue); + InstructionHelper.Emit>(operationWidth, context, destinationMemory, storeValue, null); switch (incrementAddressRegister) { diff --git a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreRegisterToMemory.cs b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreRegisterToMemory.cs index d7f3045bc..3b7df67b2 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreRegisterToMemory.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreRegisterToMemory.cs @@ -79,7 +79,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters throw new TamperCompilationException($"Invalid offset type {offsetType} in Atmosphere cheat"); } - InstructionHelper.EmitMov(operationWidth, context, destinationMemory, sourceRegister); + InstructionHelper.Emit>(operationWidth, context, destinationMemory, sourceRegister, null); switch (incrementAddressRegister) { diff --git a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondEQ.cs b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondEQ.cs index 529ed25b6..e0b98e3d8 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondEQ.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondEQ.cs @@ -1,8 +1,9 @@ using Ryujinx.HLE.HOS.Tamper.Operations; +using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Conditions { - class CondEQ : ICondition where T : unmanaged + class CondEQ : ICondition where T : unmanaged, INumber { private readonly IOperand _lhs; private readonly IOperand _rhs; @@ -15,7 +16,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions public bool Evaluate() { - return (dynamic)_lhs.Get() == (dynamic)_rhs.Get(); + return _lhs.Get() == _rhs.Get(); } + + public static ICondition CreateFor(IOperand lhs, IOperand rhs) where T1 : INumber + => new CondEQ(lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondGE.cs b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondGE.cs index 94877c2a6..5c3ef83e6 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondGE.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondGE.cs @@ -1,8 +1,9 @@ using Ryujinx.HLE.HOS.Tamper.Operations; +using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Conditions { - class CondGE : ICondition where T : unmanaged + class CondGE : ICondition where T : unmanaged, INumber { private readonly IOperand _lhs; private readonly IOperand _rhs; @@ -15,7 +16,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions public bool Evaluate() { - return (dynamic)_lhs.Get() >= (dynamic)_rhs.Get(); + return _lhs.Get() >= _rhs.Get(); } + + public static ICondition CreateFor(IOperand lhs, IOperand rhs) where T1 : INumber + => new CondGE(lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondGT.cs b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondGT.cs index 350688164..131da14bb 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondGT.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondGT.cs @@ -1,8 +1,9 @@ using Ryujinx.HLE.HOS.Tamper.Operations; +using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Conditions { - class CondGT : ICondition where T : unmanaged + class CondGT : ICondition where T : unmanaged, INumber { private readonly IOperand _lhs; private readonly IOperand _rhs; @@ -15,7 +16,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions public bool Evaluate() { - return (dynamic)_lhs.Get() > (dynamic)_rhs.Get(); + return _lhs.Get() > _rhs.Get(); } + + public static ICondition CreateFor(IOperand lhs, IOperand rhs) where T1 : INumber + => new CondGT(lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondLE.cs b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondLE.cs index dd9cf70cc..2e709e243 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondLE.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondLE.cs @@ -1,8 +1,9 @@ using Ryujinx.HLE.HOS.Tamper.Operations; +using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Conditions { - class CondLE : ICondition where T : unmanaged + class CondLE : ICondition where T : unmanaged, INumber { private readonly IOperand _lhs; private readonly IOperand _rhs; @@ -15,7 +16,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions public bool Evaluate() { - return (dynamic)_lhs.Get() <= (dynamic)_rhs.Get(); + return _lhs.Get() <= _rhs.Get(); } + + public static ICondition CreateFor(IOperand lhs, IOperand rhs) where T1 : INumber + => new CondLE(lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondLT.cs b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondLT.cs index 0c85f5e47..7393d9ec5 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondLT.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondLT.cs @@ -1,8 +1,9 @@ using Ryujinx.HLE.HOS.Tamper.Operations; +using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Conditions { - class CondLT : ICondition where T : unmanaged + class CondLT : ICondition where T : unmanaged, INumber { private readonly IOperand _lhs; private readonly IOperand _rhs; @@ -15,7 +16,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions public bool Evaluate() { - return (dynamic)_lhs.Get() < (dynamic)_rhs.Get(); + return _lhs.Get() < _rhs.Get(); } + + public static ICondition CreateFor(IOperand lhs, IOperand rhs) where T1 : INumber + => new CondLT(lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondNE.cs b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondNE.cs index b649eccee..fdd0a4845 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondNE.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondNE.cs @@ -1,8 +1,9 @@ using Ryujinx.HLE.HOS.Tamper.Operations; +using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Conditions { - class CondNE : ICondition where T : unmanaged + class CondNE : ICondition where T : unmanaged, INumber { private readonly IOperand _lhs; private readonly IOperand _rhs; @@ -15,7 +16,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions public bool Evaluate() { - return (dynamic)_lhs.Get() != (dynamic)_rhs.Get(); + return _lhs.Get() != _rhs.Get(); } + + public static ICondition CreateFor(IOperand lhs, IOperand rhs) where T1 : INumber + => new CondNE(lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Conditions/ICondition.cs b/src/Ryujinx.HLE/HOS/Tamper/Conditions/ICondition.cs index f15ceffe1..130fb5623 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Conditions/ICondition.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Conditions/ICondition.cs @@ -1,7 +1,13 @@ +using Ryujinx.HLE.HOS.Tamper.Operations; +using System; +using System.Numerics; + namespace Ryujinx.HLE.HOS.Tamper.Conditions { interface ICondition { bool Evaluate(); + + static virtual ICondition CreateFor(IOperand lhs, IOperand rhs) where T : INumber => throw new NotImplementedException(); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/InstructionHelper.cs b/src/Ryujinx.HLE/HOS/Tamper/InstructionHelper.cs index 46e4fd9f7..e50a5bd7f 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/InstructionHelper.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/InstructionHelper.cs @@ -15,46 +15,47 @@ namespace Ryujinx.HLE.HOS.Tamper context.CurrentOperations.Add(operation); } - public static void Emit(Type instruction, byte width, CompilationContext context, params Object[] operands) + public static void Emit(byte width, CompilationContext context, IOperand destination, IOperand lhs, IOperand rhs) where TOp : IOperation { - Emit((IOperation)Create(instruction, width, operands), context); - } - - public static void EmitMov(byte width, CompilationContext context, IOperand destination, IOperand source) - { - Emit(typeof(OpMov<>), width, context, destination, source); + Emit(Create(width, destination, lhs, rhs), context); } public static ICondition CreateCondition(Comparison comparison, byte width, IOperand lhs, IOperand rhs) { - ICondition Create(Type conditionType) + ICondition CreateCore() where TOp : ICondition { - return (ICondition)InstructionHelper.Create(conditionType, width, lhs, rhs); + return width switch + { + 1 => TOp.CreateFor(lhs, rhs), + 2 => TOp.CreateFor(lhs, rhs), + 4 => TOp.CreateFor(lhs, rhs), + 8 => TOp.CreateFor(lhs, rhs), + _ => throw new NotSupportedException(), + }; } return comparison switch { - Comparison.Greater => Create(typeof(CondGT<>)), - Comparison.GreaterOrEqual => Create(typeof(CondGE<>)), - Comparison.Less => Create(typeof(CondLT<>)), - Comparison.LessOrEqual => Create(typeof(CondLE<>)), - Comparison.Equal => Create(typeof(CondEQ<>)), - Comparison.NotEqual => Create(typeof(CondNE<>)), + Comparison.Greater => CreateCore>(), + Comparison.GreaterOrEqual => CreateCore>(), + Comparison.Less => CreateCore>(), + Comparison.LessOrEqual => CreateCore>(), + Comparison.Equal => CreateCore>(), + Comparison.NotEqual => CreateCore>(), _ => throw new TamperCompilationException($"Invalid comparison {comparison} in Atmosphere cheat"), }; } - public static Object Create(Type instruction, byte width, params Object[] operands) + public static IOperation Create(byte width, IOperand destination, IOperand lhs, IOperand rhs) where TOp : IOperation { - Type realType = width switch + return width switch { - 1 => instruction.MakeGenericType(typeof(byte)), - 2 => instruction.MakeGenericType(typeof(ushort)), - 4 => instruction.MakeGenericType(typeof(uint)), - 8 => instruction.MakeGenericType(typeof(ulong)), - _ => throw new TamperCompilationException($"Invalid instruction width {width} in Atmosphere cheat"), + 1 => TOp.CreateFor(destination, lhs, rhs), + 2 => TOp.CreateFor(destination, lhs, rhs), + 4 => TOp.CreateFor(destination, lhs, rhs), + 8 => TOp.CreateFor(destination, lhs, rhs), + _ => throw new NotSupportedException(), }; - return Activator.CreateInstance(realType, operands); } public static ulong GetImmediate(byte[] instruction, int index, int nybbleCount) diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/IOperand.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/IOperand.cs index 1aadda0bf..d7345d727 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/IOperand.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/IOperand.cs @@ -1,8 +1,10 @@ +using System.Numerics; + namespace Ryujinx.HLE.HOS.Tamper.Operations { interface IOperand { - public T Get() where T : unmanaged; - public void Set(T value) where T : unmanaged; + public T Get() where T : unmanaged, INumber; + public void Set(T value) where T : unmanaged, INumber; } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/IOperation.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/IOperation.cs index a4474979c..a0af81409 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/IOperation.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/IOperation.cs @@ -1,7 +1,13 @@ +using System; +using System.Numerics; + namespace Ryujinx.HLE.HOS.Tamper.Operations { interface IOperation { void Execute(); + + static virtual IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger + => throw new NotImplementedException(); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpAdd.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpAdd.cs index 855245e34..9154b20ea 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpAdd.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpAdd.cs @@ -1,6 +1,8 @@ +using System.Numerics; + namespace Ryujinx.HLE.HOS.Tamper.Operations { - class OpAdd : IOperation where T : unmanaged + class OpAdd : IOperation where T : unmanaged, INumber { readonly IOperand _destination; readonly IOperand _lhs; @@ -15,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations public void Execute() { - _destination.Set((T)((dynamic)_lhs.Get() + (dynamic)_rhs.Get())); + _destination.Set(_lhs.Get() + _rhs.Get()); } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger + => new OpAdd(destination, lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpAnd.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpAnd.cs index 7d1fa10b9..b0a1031a5 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpAnd.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpAnd.cs @@ -1,6 +1,8 @@ +using System.Numerics; + namespace Ryujinx.HLE.HOS.Tamper.Operations { - class OpAnd : IOperation where T : unmanaged + class OpAnd : IOperation where T : unmanaged, IBinaryNumber { readonly IOperand _destination; readonly IOperand _lhs; @@ -15,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations public void Execute() { - _destination.Set((T)((dynamic)_lhs.Get() & (dynamic)_rhs.Get())); + _destination.Set(_lhs.Get() & _rhs.Get()); } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger + => new OpAnd(destination, lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpLog.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpLog.cs index 4017e5f75..b33431330 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpLog.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpLog.cs @@ -1,8 +1,9 @@ using Ryujinx.Common.Logging; +using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Operations { - class OpLog : IOperation where T : unmanaged + class OpLog : IOperation where T : unmanaged, INumber { readonly int _logId; readonly IOperand _source; @@ -15,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations public void Execute() { - Logger.Debug?.Print(LogClass.TamperMachine, $"Tamper debug log id={_logId} value={(dynamic)_source.Get():X}"); + Logger.Debug?.Print(LogClass.TamperMachine, $"Tamper debug log id={_logId} value={_source.Get():X}"); } } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpLsh.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpLsh.cs index 6c846425f..cb7ae2237 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpLsh.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpLsh.cs @@ -1,6 +1,8 @@ +using System.Numerics; + namespace Ryujinx.HLE.HOS.Tamper.Operations { - class OpLsh : IOperation where T : unmanaged + class OpLsh : IOperation where T : unmanaged, IBinaryInteger { readonly IOperand _destination; readonly IOperand _lhs; @@ -15,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations public void Execute() { - _destination.Set((T)((dynamic)_lhs.Get() << (dynamic)_rhs.Get())); + _destination.Set(_lhs.Get() << int.CreateTruncating(_rhs.Get())); } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger + => new OpLsh(destination, lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpMov.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpMov.cs index af82f18e0..54266b422 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpMov.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpMov.cs @@ -1,6 +1,8 @@ +using System.Numerics; + namespace Ryujinx.HLE.HOS.Tamper.Operations { - class OpMov : IOperation where T : unmanaged + class OpMov : IOperation where T : unmanaged, INumber { readonly IOperand _destination; readonly IOperand _source; @@ -15,5 +17,8 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations { _destination.Set(_source.Get()); } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger + => new OpMov(destination, lhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpMul.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpMul.cs index a1b080f00..14c43dd03 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpMul.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpMul.cs @@ -1,6 +1,8 @@ +using System.Numerics; + namespace Ryujinx.HLE.HOS.Tamper.Operations { - class OpMul : IOperation where T : unmanaged + class OpMul : IOperation where T : unmanaged, INumber { readonly IOperand _destination; readonly IOperand _lhs; @@ -15,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations public void Execute() { - _destination.Set((T)((dynamic)_lhs.Get() * (dynamic)_rhs.Get())); + _destination.Set(_lhs.Get() * _rhs.Get()); } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger + => new OpMul(destination, lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpNot.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpNot.cs index 034e22008..91e0f6321 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpNot.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpNot.cs @@ -1,6 +1,8 @@ +using System.Numerics; + namespace Ryujinx.HLE.HOS.Tamper.Operations { - class OpNot : IOperation where T : unmanaged + class OpNot : IOperation where T : unmanaged, IBinaryNumber { readonly IOperand _destination; readonly IOperand _source; @@ -13,7 +15,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations public void Execute() { - _destination.Set((T)(~(dynamic)_source.Get())); + _destination.Set(~_source.Get()); } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger + => new OpNot(destination, lhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpOr.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpOr.cs index 0afdc3f4b..704597423 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpOr.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpOr.cs @@ -1,6 +1,8 @@ +using System.Numerics; + namespace Ryujinx.HLE.HOS.Tamper.Operations { - class OpOr : IOperation where T : unmanaged + class OpOr : IOperation where T : unmanaged, IBinaryNumber { readonly IOperand _destination; readonly IOperand _lhs; @@ -15,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations public void Execute() { - _destination.Set((T)((dynamic)_lhs.Get() | (dynamic)_rhs.Get())); + _destination.Set(_lhs.Get() | _rhs.Get()); } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger + => new OpOr(destination, lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpRsh.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpRsh.cs index e7e0f870e..b48c76a5c 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpRsh.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpRsh.cs @@ -1,6 +1,8 @@ +using System.Numerics; + namespace Ryujinx.HLE.HOS.Tamper.Operations { - class OpRsh : IOperation where T : unmanaged + class OpRsh : IOperation where T : unmanaged, IBinaryInteger { readonly IOperand _destination; readonly IOperand _lhs; @@ -15,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations public void Execute() { - _destination.Set((T)((dynamic)_lhs.Get() >> (dynamic)_rhs.Get())); + _destination.Set(_lhs.Get() >> int.CreateTruncating(_rhs.Get())); } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger + => new OpRsh(destination, lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpSub.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpSub.cs index d860d66fd..1092643cf 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpSub.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpSub.cs @@ -1,6 +1,8 @@ +using System.Numerics; + namespace Ryujinx.HLE.HOS.Tamper.Operations { - class OpSub : IOperation where T : unmanaged + class OpSub : IOperation where T : unmanaged, INumber { readonly IOperand _destination; readonly IOperand _lhs; @@ -15,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations public void Execute() { - _destination.Set((T)((dynamic)_lhs.Get() - (dynamic)_rhs.Get())); + _destination.Set(_lhs.Get() - _rhs.Get()); } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger + => new OpSub(destination, lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpXor.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpXor.cs index 07ba6b335..8fc241ced 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpXor.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpXor.cs @@ -1,6 +1,8 @@ +using System.Numerics; + namespace Ryujinx.HLE.HOS.Tamper.Operations { - class OpXor : IOperation where T : unmanaged + class OpXor : IOperation where T : unmanaged, IBinaryNumber { readonly IOperand _destination; readonly IOperand _lhs; @@ -15,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations public void Execute() { - _destination.Set((T)((dynamic)_lhs.Get() ^ (dynamic)_rhs.Get())); + _destination.Set(_lhs.Get() ^ _rhs.Get()); } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger + => new OpXor(destination, lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Pointer.cs b/src/Ryujinx.HLE/HOS/Tamper/Pointer.cs index c961e1a7d..aeb7fcf62 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Pointer.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Pointer.cs @@ -1,5 +1,6 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Tamper.Operations; +using System.Numerics; using System.Runtime.CompilerServices; namespace Ryujinx.HLE.HOS.Tamper @@ -15,12 +16,12 @@ namespace Ryujinx.HLE.HOS.Tamper _process = process; } - public T Get() where T : unmanaged + public T Get() where T : unmanaged, INumber { return _process.ReadMemory(_position.Get()); } - public void Set(T value) where T : unmanaged + public void Set(T value) where T : unmanaged, INumber { ulong position = _position.Get(); diff --git a/src/Ryujinx.HLE/HOS/Tamper/Register.cs b/src/Ryujinx.HLE/HOS/Tamper/Register.cs index cce13ee69..69b1d14b6 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Register.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Register.cs @@ -1,5 +1,6 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Tamper.Operations; +using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper { @@ -13,16 +14,16 @@ namespace Ryujinx.HLE.HOS.Tamper _alias = alias; } - public T Get() where T : unmanaged + public T Get() where T : unmanaged, INumber { - return (T)(dynamic)_register; + return T.CreateTruncating(_register); } - public void Set(T value) where T : unmanaged + public void Set(T value) where T : unmanaged, INumber { Logger.Debug?.Print(LogClass.TamperMachine, $"{_alias}: {value}"); - _register = (ulong)(dynamic)value; + _register = ulong.CreateTruncating(value); } } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Value.cs b/src/Ryujinx.HLE/HOS/Tamper/Value.cs index 436fc13d3..8e72d7c0b 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Value.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Value.cs @@ -1,8 +1,9 @@ using Ryujinx.HLE.HOS.Tamper.Operations; +using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper { - class Value : IOperand where TP : unmanaged + class Value : IOperand where TP : unmanaged, INumber { private TP _value; @@ -11,14 +12,14 @@ namespace Ryujinx.HLE.HOS.Tamper _value = value; } - public T Get() where T : unmanaged + public T Get() where T : unmanaged, INumber { - return (T)(dynamic)_value; + return T.CreateTruncating(_value); } - public void Set(T value) where T : unmanaged + public void Set(T value) where T : unmanaged, INumber { - _value = (TP)(dynamic)value; + _value = TP.CreateTruncating(value); } } } From 1a55a553eabb29a26fc81f43ef2689305bc6966d Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 19 Nov 2025 00:33:39 -0600 Subject: [PATCH 03/10] Convert HLE.Generators to IIncrementalSourceGenerator --- Directory.Packages.props | 3 +- .../IpcServiceGenerator.cs | 118 +++++++++--------- .../Ryujinx.HLE.Generators.csproj | 6 +- .../ServiceSyntaxReceiver.cs | 24 ---- 4 files changed, 65 insertions(+), 86 deletions(-) delete mode 100644 src/Ryujinx.HLE.Generators/ServiceSyntaxReceiver.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index fd61602a8..4a74eba02 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -38,6 +38,7 @@ + @@ -59,4 +60,4 @@ - \ No newline at end of file + diff --git a/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs b/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs index cdd062826..a5c8e9c5f 100644 --- a/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs +++ b/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs @@ -6,73 +6,73 @@ using System.Linq; namespace Ryujinx.HLE.Generators { [Generator] - public class IpcServiceGenerator : ISourceGenerator + public sealed class IpcServiceGenerator : IIncrementalGenerator { - public void Execute(GeneratorExecutionContext context) + private sealed record ServiceData { - 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") + public required string FullName { get; init; } + public required bool HasOneParamCtor { get; init; } + public required bool HasTwoParamCtor { get; init; } + public required string SecondParamTypeFullName { get; init; } + } + + public void Initialize(IncrementalGeneratorInitializationContext context) + { + var 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, _) => { - generator.EnterScope($"if (type == typeof({GetFullName(className, context)}))"); - if (constructors.Any(x => x.ParameterList.Parameters.Count == 2)) + var target = (INamedTypeSymbol)ctx.TargetSymbol; + var twoParamCtor = target.Constructors.FirstOrDefault(ctor => ctor.Parameters.Length == 2); + return new ServiceData { - 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);"); + FullName = target.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat), + HasOneParamCtor = target.Constructors.Any(ctor => ctor.Parameters.Length == 1), + HasTwoParamCtor = twoParamCtor != null, + SecondParamTypeFullName = twoParamCtor?.Parameters[1].Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat), + }; + } + ) + .Where(data => data.HasOneParamCtor || data.HasTwoParamCtor); + + 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(Type type, ServiceCtx context, object? parameter = null)"); + + foreach (var service in data) + { + generator.EnterScope($"if (type == typeof({service.FullName}))"); + if (service.HasTwoParamCtor) + { + generator.EnterScope("if (parameter != null)"); + generator.AppendLine($"return new {service.FullName}(context, ({service.SecondParamTypeFullName})parameter);"); + generator.LeaveScope(); + } + if (service.HasOneParamCtor) + { + generator.AppendLine($"return new {service.FullName}(context);"); + } generator.LeaveScope(); } - - if (constructors.Any(x => x.ParameterList.Parameters.Count == 1)) - { - generator.AppendLine($"return new {GetFullName(className, context)}(context);"); - } + + generator.AppendLine("return null;"); + generator.LeaveScope(); 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()); + generator.LeaveScope(); + + generator.AppendLine("#nullable disable"); + + ctx.AddSource("IUserInterface.g.cs", generator.ToString()); + }); } } } diff --git a/src/Ryujinx.HLE.Generators/Ryujinx.HLE.Generators.csproj b/src/Ryujinx.HLE.Generators/Ryujinx.HLE.Generators.csproj index 4791a3b27..5de37c865 100644 --- a/src/Ryujinx.HLE.Generators/Ryujinx.HLE.Generators.csproj +++ b/src/Ryujinx.HLE.Generators/Ryujinx.HLE.Generators.csproj @@ -3,8 +3,6 @@ netstandard2.0 true - true - Generated true $(DefaultItemExcludes);._* @@ -15,6 +13,10 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/src/Ryujinx.HLE.Generators/ServiceSyntaxReceiver.cs b/src/Ryujinx.HLE.Generators/ServiceSyntaxReceiver.cs deleted file mode 100644 index 7513f5f45..000000000 --- a/src/Ryujinx.HLE.Generators/ServiceSyntaxReceiver.cs +++ /dev/null @@ -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 Types = []; - - public void OnVisitSyntaxNode(SyntaxNode syntaxNode) - { - if (syntaxNode is ClassDeclarationSyntax classDeclaration) - { - if (classDeclaration.BaseList == null) - { - return; - } - - Types.Add(classDeclaration); - } - } - } -} From 19de0d0db62113ccb0f39d381a053eb10165ce2f Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 19 Nov 2025 03:51:07 -0600 Subject: [PATCH 04/10] Replace GetServiceInstance with fully source-generated version --- ...ceGenerator.cs => UserServiceGenerator.cs} | 63 ++++++++++++------- .../Account/Acc/IBaasAccessTokenAccessor.cs | 2 +- src/Ryujinx.HLE/HOS/Services/IpcService.cs | 3 +- .../HOS/Services/Sm/IUserInterface.cs | 19 +----- 4 files changed, 43 insertions(+), 44 deletions(-) rename src/Ryujinx.HLE.Generators/{IpcServiceGenerator.cs => UserServiceGenerator.cs} (50%) diff --git a/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs b/src/Ryujinx.HLE.Generators/UserServiceGenerator.cs similarity index 50% rename from src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs rename to src/Ryujinx.HLE.Generators/UserServiceGenerator.cs index a5c8e9c5f..ace720667 100644 --- a/src/Ryujinx.HLE.Generators/IpcServiceGenerator.cs +++ b/src/Ryujinx.HLE.Generators/UserServiceGenerator.cs @@ -1,19 +1,29 @@ 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 IpcServiceGenerator : IIncrementalGenerator + public sealed class UserServiceGenerator : IIncrementalGenerator { - private sealed record ServiceData + private sealed class ServiceData : IEquatable { public required string FullName { get; init; } - public required bool HasOneParamCtor { get; init; } - public required bool HasTwoParamCtor { get; init; } - public required string SecondParamTypeFullName { 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) @@ -23,17 +33,18 @@ namespace Ryujinx.HLE.Generators transform: (ctx, _) => { var target = (INamedTypeSymbol)ctx.TargetSymbol; - var twoParamCtor = target.Constructors.FirstOrDefault(ctor => ctor.Parameters.Length == 2); + var 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), - HasOneParamCtor = target.Constructors.Any(ctor => ctor.Parameters.Length == 1), - HasTwoParamCtor = twoParamCtor != null, - SecondParamTypeFullName = twoParamCtor?.Parameters[1].Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat), + Instances = instances.ToList(), }; } - ) - .Where(data => data.HasOneParamCtor || data.HasTwoParamCtor); + ); context.RegisterSourceOutput(pipeline.Collect(), (ctx, data) => @@ -45,25 +56,29 @@ namespace Ryujinx.HLE.Generators 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)"); + generator.EnterScope("public IpcService? GetServiceInstance(string name, ServiceCtx context)"); + + generator.EnterScope("return name switch"); - foreach (var service in data) + foreach (var serviceImpl in data) { - generator.EnterScope($"if (type == typeof({service.FullName}))"); - if (service.HasTwoParamCtor) + foreach (var instance in serviceImpl.Instances) { - generator.EnterScope("if (parameter != null)"); - generator.AppendLine($"return new {service.FullName}(context, ({service.SecondParamTypeFullName})parameter);"); - generator.LeaveScope(); + if (instance.ParameterValue == null) + { + generator.AppendLine($"\"{instance.ServiceName}\" => new {serviceImpl.FullName}(context),"); + } + else + { + generator.AppendLine($"\"{instance.ServiceName}\" => new {serviceImpl.FullName}(context, {instance.ParameterValue}),"); + } } - if (service.HasOneParamCtor) - { - generator.AppendLine($"return new {service.FullName}(context);"); - } - generator.LeaveScope(); } - generator.AppendLine("return null;"); + generator.AppendLine("_ => null,"); + + generator.LeaveScope(";"); + generator.LeaveScope(); generator.LeaveScope(); diff --git a/src/Ryujinx.HLE/HOS/Services/Account/Acc/IBaasAccessTokenAccessor.cs b/src/Ryujinx.HLE/HOS/Services/Account/Acc/IBaasAccessTokenAccessor.cs index b88815778..3f2832ef2 100644 --- a/src/Ryujinx.HLE/HOS/Services/Account/Acc/IBaasAccessTokenAccessor.cs +++ b/src/Ryujinx.HLE/HOS/Services/Account/Acc/IBaasAccessTokenAccessor.cs @@ -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) { } } } diff --git a/src/Ryujinx.HLE/HOS/Services/IpcService.cs b/src/Ryujinx.HLE/HOS/Services/IpcService.cs index c7dee64fb..87e9d7b59 100644 --- a/src/Ryujinx.HLE/HOS/Services/IpcService.cs +++ b/src/Ryujinx.HLE/HOS/Services/IpcService.cs @@ -11,8 +11,9 @@ using System.Reflection; namespace Ryujinx.HLE.HOS.Services { - abstract class IpcService + abstract partial class IpcService { + public IReadOnlyDictionary CmifCommands { get; } public IReadOnlyDictionary TipcCommands { get; } diff --git a/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs b/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs index f19eeebfc..743c208e4 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs @@ -4,18 +4,13 @@ using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel.Ipc; using Ryujinx.Horizon.Common; using System; -using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Reflection; using System.Text; namespace Ryujinx.HLE.HOS.Services.Sm { partial class IUserInterface : IpcService { - private static readonly Dictionary _services; - private readonly SmRegistry _registry; private readonly ServerBase _commonServer; @@ -27,14 +22,6 @@ namespace Ryujinx.HLE.HOS.Services.Sm _registry = registry; } - static IUserInterface() - { - _services = typeof(IUserInterface).Assembly.GetTypes() - .SelectMany(type => type.GetCustomAttributes(typeof(ServiceAttribute), true) - .Select(service => (((ServiceAttribute)service).Name, type))) - .ToDictionary(service => service.Name, service => service.type); - } - [CommandCmif(0)] [CommandTipc(0)] // 12.0.0+ // Initialize(pid, u64 reserved) @@ -91,12 +78,8 @@ namespace Ryujinx.HLE.HOS.Services.Sm } else { - if (_services.TryGetValue(name, out Type type)) + if (GetServiceInstance(name, context) is { } service) { - ServiceAttribute serviceAttribute = type.GetCustomAttributes().First(service => service.Name == name); - - IpcService service = GetServiceInstance(type, context, serviceAttribute.Parameter); - service.TrySetServer(_commonServer); service.Server.AddSessionObj(session.ServerSession, service); } From 8e1e2d69df22ab3df91c108d67ff3aa6d6a899cc Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 19 Nov 2025 18:31:35 -0600 Subject: [PATCH 05/10] Make Cmif commands in HLE use virtual method invocation instead of reflection # Conflicts: # src/Ryujinx.HLE/HOS/Services/IpcService.cs --- .../Ryujinx.BuildValidationTasks.csproj | 2 +- .../IpcCommandGenerator.cs | 118 ++++++++++++++++++ .../ServiceNotImplementedException.cs | 55 ++------ .../AccountService/IManagerForApplication.cs | 2 +- .../IManagerForSystemService.cs | 2 +- .../Account/Acc/AccountService/IProfile.cs | 2 +- .../Acc/AccountService/IProfileEditor.cs | 2 +- .../Acc/IAccountServiceForAdministrator.cs | 2 +- .../Acc/IAccountServiceForApplication.cs | 2 +- .../Acc/IAccountServiceForSystemService.cs | 2 +- .../HOS/Services/Account/Acc/IAsyncContext.cs | 2 +- .../IAsyncNetworkServiceLicenseKindContext.cs | 2 +- .../ILibraryAppletProxy.cs | 2 +- .../ISystemAppletProxy.cs | 2 +- .../ILibraryAppletAccessor.cs | 2 +- .../ILibraryAppletSelfAccessor.cs | 2 +- .../IProcessWindingController.cs | 2 +- .../SystemAppletProxy/IAudioController.cs | 2 +- .../SystemAppletProxy/ICommonStateGetter.cs | 2 +- .../SystemAppletProxy/IDisplayController.cs | 2 +- .../SystemAppletProxy/IHomeMenuFunctions.cs | 2 +- .../ILibraryAppletCreator.cs | 2 +- .../SystemAppletProxy/ISelfController.cs | 2 +- .../SystemAppletProxy/IWindowController.cs | 2 +- .../IAllSystemAppletProxiesService.cs | 2 +- .../HOS/Services/Am/AppletAE/IStorage.cs | 2 +- .../Services/Am/AppletAE/IStorageAccessor.cs | 2 +- .../ApplicationProxy/IApplicationFunctions.cs | 2 +- .../IApplicationProxy.cs | 2 +- .../Am/AppletOE/IApplicationProxyService.cs | 2 +- src/Ryujinx.HLE/HOS/Services/Apm/IManager.cs | 2 +- .../HOS/Services/Apm/IManagerPrivileged.cs | 2 +- src/Ryujinx.HLE/HOS/Services/Apm/ISession.cs | 2 +- .../HOS/Services/Apm/ISystemManager.cs | 2 +- .../Services/Bluetooth/IBluetoothDriver.cs | 2 +- .../HOS/Services/Bluetooth/IBluetoothUser.cs | 2 +- .../BluetoothManager/BtmUser/IBtmUserCore.cs | 2 +- .../HOS/Services/BluetoothManager/IBtmUser.cs | 2 +- .../Services/Caps/IAlbumApplicationService.cs | 2 +- .../HOS/Services/Caps/IAlbumControlService.cs | 2 +- .../Caps/IScreenShotApplicationService.cs | 2 +- .../HOS/Services/Ectx/IContextRegistrar.cs | 2 +- .../Services/Ectx/IWriterForApplication.cs | 2 +- .../HOS/Services/Fatal/IService.cs | 2 +- .../Services/Fs/FileSystemProxy/IDirectory.cs | 2 +- .../HOS/Services/Fs/FileSystemProxy/IFile.cs | 2 +- .../Fs/FileSystemProxy/IFileSystem.cs | 2 +- .../Services/Fs/FileSystemProxy/IStorage.cs | 2 +- .../HOS/Services/Fs/IDeviceOperator.cs | 2 +- .../HOS/Services/Fs/IFileSystemProxy.cs | 2 +- .../HOS/Services/Fs/IMultiCommitManager.cs | 2 +- .../HOS/Services/Fs/ISaveDataInfoReader.cs | 2 +- .../HidServer/IActiveVibrationDeviceList.cs | 2 +- .../Services/Hid/HidServer/IAppletResource.cs | 2 +- .../HOS/Services/Hid/IHidServer.cs | 2 +- .../HOS/Services/Hid/IHidSystemServer.cs | 2 +- .../HOS/Services/Hid/IHidbusServer.cs | 2 +- .../HOS/Services/Hid/Irs/IIrSensorServer.cs | 2 +- src/Ryujinx.HLE/HOS/Services/IpcService.cs | 104 ++++++--------- .../HOS/Services/Ldn/IUserServiceCreator.cs | 2 +- .../HOS/Services/Ldn/Lp2p/IServiceCreator.cs | 2 +- .../HOS/Services/Ldn/Lp2p/ISfService.cs | 2 +- .../Services/Ldn/Lp2p/ISfServiceMonitor.cs | 2 +- .../IClientProcessMonitor.cs | 2 +- .../IUserLocalCommunicationService.cs | 2 +- .../HOS/Services/Mii/IImageDatabaseService.cs | 2 +- .../HOS/Services/Mii/IStaticService.cs | 2 +- .../Mii/StaticService/IDatabaseService.cs | 2 +- .../Services/Mnpp/IServiceForApplication.cs | 2 +- .../Ncm/Lr/ILocationResolverManager.cs | 2 +- .../ILocationResolver.cs | 2 +- .../HOS/Services/Nfc/ISystemManager.cs | 2 +- .../HOS/Services/Nfc/IUserManager.cs | 2 +- .../HOS/Services/Nfc/NfcManager/INfc.cs | 2 +- .../HOS/Services/Nfc/Nfp/IDebugManager.cs | 2 +- .../HOS/Services/Nfc/Nfp/ISystemManager.cs | 2 +- .../HOS/Services/Nfc/Nfp/IUserManager.cs | 2 +- .../HOS/Services/Nfc/Nfp/NfpManager/INfp.cs | 2 +- src/Ryujinx.HLE/HOS/Services/Ngct/IService.cs | 2 +- .../Ngct/IServiceWithManagementApi.cs | 2 +- .../HOS/Services/Nifm/IStaticService.cs | 2 +- .../Nifm/StaticService/IGeneralService.cs | 2 +- .../Services/Nifm/StaticService/IRequest.cs | 2 +- .../Services/Nim/IShopServiceAccessServer.cs | 2 +- .../Nim/IShopServiceAccessServerInterface.cs | 2 +- .../HOS/Services/Nim/IShopServiceAccessor.cs | 2 +- .../HOS/Services/Nim/Ntc/IStaticService.cs | 2 +- .../IEnsureNetworkClockAvailabilityService.cs | 2 +- .../Services/Ns/Aoc/IAddOnContentManager.cs | 2 +- .../Services/Ns/Aoc/IPurchaseEventManager.cs | 2 +- .../Ns/IApplicationManagerInterface.cs | 2 +- ...ReadOnlyApplicationControlDataInterface.cs | 2 +- .../Services/Ns/IServiceGetterInterface.cs | 2 +- .../HOS/Services/Nv/INvDrvServices.cs | 2 +- .../Olsc/IOlscServiceForApplication.cs | 2 +- .../Pctl/IParentalControlServiceFactory.cs | 2 +- .../IParentalControlService.cs | 2 +- .../HOS/Services/Pcv/Bpc/IRtcManager.cs | 2 +- .../Clkrst/ClkrstManager/IClkrstSession.cs | 2 +- .../HOS/Services/Pcv/Clkrst/IClkrstManager.cs | 2 +- .../HOS/Services/Pm/IDebugMonitorInterface.cs | 2 +- .../HOS/Services/Pm/IInformationInterface.cs | 2 +- .../HOS/Services/Pm/IShellInterface.cs | 2 +- .../HOS/Services/Ptm/Psm/IPsmServer.cs | 2 +- .../HOS/Services/Ptm/Psm/IPsmSession.cs | 2 +- .../HOS/Services/Ro/IRoInterface.cs | 2 +- .../HOS/Services/Sdb/Pdm/IQueryService.cs | 2 +- .../HOS/Services/Sdb/Pl/ISharedFontManager.cs | 2 +- .../HOS/Services/Settings/ISettingsServer.cs | 2 +- .../Settings/ISystemSettingsServer.cs | 2 +- .../HOS/Services/Sm/IUserInterface.cs | 2 +- .../HOS/Services/Sockets/Bsd/IClient.cs | 2 +- .../HOS/Services/Sockets/Nsd/IManager.cs | 2 +- .../Services/Sockets/Sfdnsres/IResolver.cs | 2 +- .../HOS/Services/Spl/IGeneralInterface.cs | 2 +- .../HOS/Services/Spl/IRandomInterface.cs | 2 +- .../HOS/Services/Ssl/ISslService.cs | 2 +- .../Services/Ssl/SslService/ISslConnection.cs | 2 +- .../Services/Ssl/SslService/ISslContext.cs | 2 +- .../SurfaceFlinger/IHOSBinderDriver.cs | 2 +- .../Services/Time/IStaticServiceForGlue.cs | 2 +- .../HOS/Services/Time/IStaticServiceForPsc.cs | 2 +- .../HOS/Services/Time/ITimeServiceManager.cs | 2 +- .../Time/StaticService/ISteadyClock.cs | 2 +- .../Time/StaticService/ISystemClock.cs | 2 +- .../StaticService/ITimeZoneServiceForGlue.cs | 2 +- .../StaticService/ITimeZoneServiceForPsc.cs | 2 +- .../Services/Vi/IApplicationRootService.cs | 2 +- .../HOS/Services/Vi/IManagerRootService.cs | 2 +- .../HOS/Services/Vi/ISystemRootService.cs | 2 +- .../IManagerDisplayService.cs | 2 +- .../ISystemDisplayService.cs | 2 +- .../RootService/IApplicationDisplayService.cs | 2 +- 133 files changed, 298 insertions(+), 239 deletions(-) create mode 100644 src/Ryujinx.HLE.Generators/IpcCommandGenerator.cs diff --git a/src/Ryujinx.BuildValidationTasks/Ryujinx.BuildValidationTasks.csproj b/src/Ryujinx.BuildValidationTasks/Ryujinx.BuildValidationTasks.csproj index c89a044b2..31181bc55 100644 --- a/src/Ryujinx.BuildValidationTasks/Ryujinx.BuildValidationTasks.csproj +++ b/src/Ryujinx.BuildValidationTasks/Ryujinx.BuildValidationTasks.csproj @@ -7,7 +7,7 @@ - CommandIds { get; init; } + } + + private sealed class ServiceData + { + public required string Namespace { get; init; } + public required string TypeName { get; init; } + public required ImmutableArray CmifCommands { get; init; } + public required ImmutableArray TipcCommands { get; init; } + } + + public void Initialize(IncrementalGeneratorInitializationContext context) + { + var predicate = (SyntaxNode node, CancellationToken _) => node is MethodDeclarationSyntax; + var transform = (GeneratorAttributeSyntaxContext ctx, CancellationToken _) => + { + 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(), + }; + }; + var cmifCommands = + context.SyntaxProvider.ForAttributeWithMetadataName("Ryujinx.HLE.HOS.Services.CommandCmifAttribute", + predicate, + transform + ); + var tipcCommands = + context.SyntaxProvider.ForAttributeWithMetadataName("Ryujinx.HLE.HOS.Services.CommandTipcAttribute", + predicate, + transform + ); + + var allCommands = cmifCommands.Collect().Combine(tipcCommands.Collect()); + + var types = allCommands.SelectMany((commands, _) => + { + var cmif = commands.Left.ToLookup(c => (c.Namespace, c.TypeName)); + var tipc = commands.Right.ToLookup(c => (c.Namespace, c.TypeName)); + + var builder = ImmutableArray.CreateBuilder(); + + foreach (var 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}"); + + 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(); + + generator.LeaveScope(); + generator.LeaveScope(); + + ctx.AddSource($"{data.Namespace}.{data.TypeName}.g.cs", generator.ToString()); + }); + } + } +} diff --git a/src/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs b/src/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs index 23068bf72..f1d453172 100644 --- a/src/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs +++ b/src/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs @@ -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)); + var commandId = Request.Type > IpcMessageType.TipcCloseSession + ? -1 // TODO: tipc name + : Service.CmifCommandIdByMethodName(MethodName); - if (callingType != null && callingMethod != null) - { - // If the type is past 0xF, we are using TIPC - IReadOnlyDictionary ipcCommands = Request.Type > IpcMessageType.TipcCloseSession ? Service.TipcCommands : Service.CmifCommands; - - // Find the handler for the method called - KeyValuePair 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); - } } } diff --git a/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IManagerForApplication.cs b/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IManagerForApplication.cs index a00514cb6..486e50aed 100644 --- a/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IManagerForApplication.cs +++ b/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IManagerForApplication.cs @@ -1,6 +1,6 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService { - class IManagerForApplication : IpcService + partial class IManagerForApplication : IpcService { private readonly ManagerServer _managerServer; diff --git a/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IManagerForSystemService.cs b/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IManagerForSystemService.cs index 40c73c439..b9e29d516 100644 --- a/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IManagerForSystemService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IManagerForSystemService.cs @@ -1,6 +1,6 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService { - class IManagerForSystemService : IpcService + partial class IManagerForSystemService : IpcService { private readonly ManagerServer _managerServer; diff --git a/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IProfile.cs b/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IProfile.cs index a0021917f..391cb0b72 100644 --- a/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IProfile.cs +++ b/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IProfile.cs @@ -1,6 +1,6 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService { - class IProfile : IpcService + partial class IProfile : IpcService { private readonly ProfileServer _profileServer; diff --git a/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IProfileEditor.cs b/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IProfileEditor.cs index 5d5d0dd69..e605ddc63 100644 --- a/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IProfileEditor.cs +++ b/src/Ryujinx.HLE/HOS/Services/Account/Acc/AccountService/IProfileEditor.cs @@ -1,6 +1,6 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc.AccountService { - class IProfileEditor : IpcService + partial class IProfileEditor : IpcService { private readonly ProfileServer _profileServer; diff --git a/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForAdministrator.cs b/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForAdministrator.cs index 74c135aed..b0b1718af 100644 --- a/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForAdministrator.cs +++ b/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForAdministrator.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs b/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs index 98af10694..a8558e5f4 100644 --- a/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs +++ b/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForSystemService.cs b/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForSystemService.cs index 682b5327f..4b4c823ff 100644 --- a/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForSystemService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForSystemService.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAsyncContext.cs b/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAsyncContext.cs index 91daba5f0..24886cd91 100644 --- a/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAsyncContext.cs +++ b/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAsyncContext.cs @@ -5,7 +5,7 @@ using System; namespace Ryujinx.HLE.HOS.Services.Account.Acc { - class IAsyncContext : IpcService + partial class IAsyncContext : IpcService { protected AsyncExecution AsyncExecution; diff --git a/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAsyncNetworkServiceLicenseKindContext.cs b/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAsyncNetworkServiceLicenseKindContext.cs index 175838506..27a97cd8c 100644 --- a/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAsyncNetworkServiceLicenseKindContext.cs +++ b/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAsyncNetworkServiceLicenseKindContext.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ILibraryAppletProxy.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ILibraryAppletProxy.cs index 7700cac09..2644641a8 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ILibraryAppletProxy.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ILibraryAppletProxy.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs index dd015fd80..30f8f8b57 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs index cd71103ca..6d4c2e3a7 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/ILibraryAppletSelfAccessor.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/ILibraryAppletSelfAccessor.cs index fc02ea172..7c5b51dce 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/ILibraryAppletSelfAccessor.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/ILibraryAppletSelfAccessor.cs @@ -3,7 +3,7 @@ using System; namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletProxy { - class ILibraryAppletSelfAccessor : IpcService + partial class ILibraryAppletSelfAccessor : IpcService { private readonly AppletStandalone _appletStandalone = new(); diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/IProcessWindingController.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/IProcessWindingController.cs index d86a896d6..33a333786 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/IProcessWindingController.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/IProcessWindingController.cs @@ -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() { } diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IAudioController.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IAudioController.cs index 05a4b0a63..a9141ffb9 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IAudioController.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IAudioController.cs @@ -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() { } diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs index ad776fe6e..f07372fe4 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDisplayController.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDisplayController.cs index 6bd35a779..fe88c3570 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDisplayController.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDisplayController.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs index 78f47e0e9..7ba2a5c51 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs index f1ae81f8d..70e85585e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs @@ -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() { } diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs index 7aac6f3ea..479bfe09b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IWindowController.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IWindowController.cs index 46dc4916d..9c5815670 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IWindowController.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IWindowController.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/IAllSystemAppletProxiesService.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/IAllSystemAppletProxiesService.cs index b8741b22b..8d7ed5e3f 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/IAllSystemAppletProxiesService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/IAllSystemAppletProxiesService.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorage.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorage.cs index 311084aa1..e8169fea8 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorage.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorage.cs @@ -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; } diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorageAccessor.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorageAccessor.cs index 54c7b69e5..fead139f7 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorageAccessor.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/IStorageAccessor.cs @@ -2,7 +2,7 @@ using System; namespace Ryujinx.HLE.HOS.Services.Am.AppletAE { - class IStorageAccessor : IpcService + partial class IStorageAccessor : IpcService { private readonly IStorage _storage; diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs index 9986bf824..1ba8ffc63 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs index b24e1bf4f..c763ffe53 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/IApplicationProxyService.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/IApplicationProxyService.cs index 9814976f7..e64c2037b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/IApplicationProxyService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/IApplicationProxyService.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Apm/IManager.cs b/src/Ryujinx.HLE/HOS/Services/Apm/IManager.cs index 83215befa..5398a20e5 100644 --- a/src/Ryujinx.HLE/HOS/Services/Apm/IManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Apm/IManager.cs @@ -1,6 +1,6 @@ namespace Ryujinx.HLE.HOS.Services.Apm { - abstract class IManager : IpcService + abstract partial class IManager : IpcService { public IManager(ServiceCtx context) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Apm/IManagerPrivileged.cs b/src/Ryujinx.HLE/HOS/Services/Apm/IManagerPrivileged.cs index bb0049d1b..08b681d57 100644 --- a/src/Ryujinx.HLE/HOS/Services/Apm/IManagerPrivileged.cs +++ b/src/Ryujinx.HLE/HOS/Services/Apm/IManagerPrivileged.cs @@ -3,7 +3,7 @@ namespace Ryujinx.HLE.HOS.Services.Apm // NOTE: This service doesn’t 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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Apm/ISession.cs b/src/Ryujinx.HLE/HOS/Services/Apm/ISession.cs index 6ee696056..f4103e00b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Apm/ISession.cs +++ b/src/Ryujinx.HLE/HOS/Services/Apm/ISession.cs @@ -1,6 +1,6 @@ namespace Ryujinx.HLE.HOS.Services.Apm { - abstract class ISession : IpcService + abstract partial class ISession : IpcService { public ISession(ServiceCtx context) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Apm/ISystemManager.cs b/src/Ryujinx.HLE/HOS/Services/Apm/ISystemManager.cs index 375423cf2..d01e33872 100644 --- a/src/Ryujinx.HLE/HOS/Services/Apm/ISystemManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Apm/ISystemManager.cs @@ -1,6 +1,6 @@ namespace Ryujinx.HLE.HOS.Services.Apm { - abstract class ISystemManager : IpcService + abstract partial class ISystemManager : IpcService { public ISystemManager(ServiceCtx context) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Bluetooth/IBluetoothDriver.cs b/src/Ryujinx.HLE/HOS/Services/Bluetooth/IBluetoothDriver.cs index 8f2642695..a8d2c66a7 100644 --- a/src/Ryujinx.HLE/HOS/Services/Bluetooth/IBluetoothDriver.cs +++ b/src/Ryujinx.HLE/HOS/Services/Bluetooth/IBluetoothDriver.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Bluetooth/IBluetoothUser.cs b/src/Ryujinx.HLE/HOS/Services/Bluetooth/IBluetoothUser.cs index ea4a46f92..2756ede7c 100644 --- a/src/Ryujinx.HLE/HOS/Services/Bluetooth/IBluetoothUser.cs +++ b/src/Ryujinx.HLE/HOS/Services/Bluetooth/IBluetoothUser.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/BluetoothManager/BtmUser/IBtmUserCore.cs b/src/Ryujinx.HLE/HOS/Services/BluetoothManager/BtmUser/IBtmUserCore.cs index d4e23b93d..9d06e44e7 100644 --- a/src/Ryujinx.HLE/HOS/Services/BluetoothManager/BtmUser/IBtmUserCore.cs +++ b/src/Ryujinx.HLE/HOS/Services/BluetoothManager/BtmUser/IBtmUserCore.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/BluetoothManager/IBtmUser.cs b/src/Ryujinx.HLE/HOS/Services/BluetoothManager/IBtmUser.cs index 78f8fd8f5..29190eb44 100644 --- a/src/Ryujinx.HLE/HOS/Services/BluetoothManager/IBtmUser.cs +++ b/src/Ryujinx.HLE/HOS/Services/BluetoothManager/IBtmUser.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumApplicationService.cs b/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumApplicationService.cs index 754a44025..e794be54e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumApplicationService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumApplicationService.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumControlService.cs b/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumControlService.cs index 4376c4d14..81295f910 100644 --- a/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumControlService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumControlService.cs @@ -1,7 +1,7 @@ namespace Ryujinx.HLE.HOS.Services.Caps { [Service("caps:c")] - class IAlbumControlService : IpcService + partial class IAlbumControlService : IpcService { public IAlbumControlService(ServiceCtx context) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Caps/IScreenShotApplicationService.cs b/src/Ryujinx.HLE/HOS/Services/Caps/IScreenShotApplicationService.cs index 0723b57cc..153f7df7c 100644 --- a/src/Ryujinx.HLE/HOS/Services/Caps/IScreenShotApplicationService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Caps/IScreenShotApplicationService.cs @@ -4,7 +4,7 @@ using Ryujinx.HLE.HOS.Services.Caps.Types; namespace Ryujinx.HLE.HOS.Services.Caps { [Service("caps:su")] // 6.0.0+ - class IScreenShotApplicationService : IpcService + partial class IScreenShotApplicationService : IpcService { public IScreenShotApplicationService(ServiceCtx context) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Ectx/IContextRegistrar.cs b/src/Ryujinx.HLE/HOS/Services/Ectx/IContextRegistrar.cs index 34adfe9be..8cc33637f 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ectx/IContextRegistrar.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ectx/IContextRegistrar.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Ectx/IWriterForApplication.cs b/src/Ryujinx.HLE/HOS/Services/Ectx/IWriterForApplication.cs index c8ef155e3..177349c33 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ectx/IWriterForApplication.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ectx/IWriterForApplication.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Fatal/IService.cs b/src/Ryujinx.HLE/HOS/Services/Fatal/IService.cs index c3ed92ed0..55efbdf6e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fatal/IService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fatal/IService.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IDirectory.cs b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IDirectory.cs index 0fe7bcdd6..91e3ea08f 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IDirectory.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IDirectory.cs @@ -5,7 +5,7 @@ using Ryujinx.Memory; namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { - class IDirectory : DisposableIpcService + partial class IDirectory : DisposableIpcService { private SharedRef _baseDirectory; diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFile.cs b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFile.cs index 0ea57f5a4..1fd69520d 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFile.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFile.cs @@ -7,7 +7,7 @@ using Ryujinx.Memory; namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { - class IFile : DisposableIpcService + partial class IFile : DisposableIpcService { private SharedRef _baseFile; diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs index 168dfc37a..4f74bb272 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs @@ -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 _fileSystem; diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs index 480899ae1..4d8d84e36 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs @@ -10,7 +10,7 @@ using System.Threading; namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { - class IStorage : DisposableIpcService + partial class IStorage : DisposableIpcService { private SharedRef _baseStorage; diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/IDeviceOperator.cs b/src/Ryujinx.HLE/HOS/Services/Fs/IDeviceOperator.cs index 49453e83a..75f6fbd2a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/IDeviceOperator.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/IDeviceOperator.cs @@ -5,7 +5,7 @@ using GameCardHandle = System.UInt32; namespace Ryujinx.HLE.HOS.Services.Fs { - class IDeviceOperator : DisposableIpcService + partial class IDeviceOperator : DisposableIpcService { private SharedRef _baseOperator; diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs index 08ede2b5b..c95f7192e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs @@ -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 _baseFileSystemProxy; private ulong _pid; diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/IMultiCommitManager.cs b/src/Ryujinx.HLE/HOS/Services/Fs/IMultiCommitManager.cs index 134e2ed8c..033fa9da1 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/IMultiCommitManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/IMultiCommitManager.cs @@ -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 _baseCommitManager; diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/ISaveDataInfoReader.cs b/src/Ryujinx.HLE/HOS/Services/Fs/ISaveDataInfoReader.cs index b86eb1fa1..49a8608a8 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/ISaveDataInfoReader.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/ISaveDataInfoReader.cs @@ -5,7 +5,7 @@ using Ryujinx.Memory; namespace Ryujinx.HLE.HOS.Services.Fs { - class ISaveDataInfoReader : DisposableIpcService + partial class ISaveDataInfoReader : DisposableIpcService { private SharedRef _baseReader; diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/HidServer/IActiveVibrationDeviceList.cs b/src/Ryujinx.HLE/HOS/Services/Hid/HidServer/IActiveVibrationDeviceList.cs index 93f19c915..eef5bda83 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/HidServer/IActiveVibrationDeviceList.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/HidServer/IActiveVibrationDeviceList.cs @@ -1,6 +1,6 @@ namespace Ryujinx.HLE.HOS.Services.Hid.HidServer { - class IActiveApplicationDeviceList : IpcService + partial class IActiveApplicationDeviceList : IpcService { public IActiveApplicationDeviceList() { } diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/HidServer/IAppletResource.cs b/src/Ryujinx.HLE/HOS/Services/Hid/HidServer/IAppletResource.cs index 56eb345af..a9df89a0e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/HidServer/IAppletResource.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/HidServer/IAppletResource.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs b/src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs index 28db75663..04b66b1f3 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/IHidServer.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/IHidSystemServer.cs b/src/Ryujinx.HLE/HOS/Services/Hid/IHidSystemServer.cs index 0b4eba948..3255a644c 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/IHidSystemServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/IHidSystemServer.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/IHidbusServer.cs b/src/Ryujinx.HLE/HOS/Services/Hid/IHidbusServer.cs index 5082bddc2..614e865d4 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/IHidbusServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/IHidbusServer.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs b/src/Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs index 8a30ce066..50b8c14cf 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/Irs/IIrSensorServer.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/IpcService.cs b/src/Ryujinx.HLE/HOS/Services/IpcService.cs index 87e9d7b59..31420f485 100644 --- a/src/Ryujinx.HLE/HOS/Services/IpcService.cs +++ b/src/Ryujinx.HLE/HOS/Services/IpcService.cs @@ -13,8 +13,6 @@ namespace Ryujinx.HLE.HOS.Services { abstract partial class IpcService { - - public IReadOnlyDictionary CmifCommands { get; } public IReadOnlyDictionary TipcCommands { get; } public ServerBase Server { get; private set; } @@ -24,30 +22,11 @@ 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() - .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) + if (true) { - sw.Start(); + var sw = Stopwatch.StartNew(); TipcCommands = GetType() .GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public) @@ -88,6 +67,29 @@ 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; + } + + 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; @@ -138,52 +140,26 @@ 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) @@ -202,9 +178,7 @@ namespace Ryujinx.HLE.HOS.Services { Logger.Debug?.Print(LogClass.KernelIpc, $"{GetType().Name}: {processRequest.Name}"); - _parameters[0] = context; - - result = (ResultCode)processRequest.Invoke(this, _parameters); + result = (ResultCode)processRequest.Invoke(this, [context]); } else { diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/IUserServiceCreator.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/IUserServiceCreator.cs index 3e3a226ae..bbb0c3190 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/IUserServiceCreator.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/IUserServiceCreator.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/IServiceCreator.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/IServiceCreator.cs index 705e5f258..16b7da424 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/IServiceCreator.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/IServiceCreator.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/ISfService.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/ISfService.cs index 8f9f0e3e4..7533e3cd0 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/ISfService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/ISfService.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/ISfServiceMonitor.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/ISfServiceMonitor.cs index d3a8bead2..92181127c 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/ISfServiceMonitor.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/ISfServiceMonitor.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IClientProcessMonitor.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IClientProcessMonitor.cs index 349d51a3f..07b3eb757 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IClientProcessMonitor.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IClientProcessMonitor.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs index 62a86ad91..20d7a270b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs @@ -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; } diff --git a/src/Ryujinx.HLE/HOS/Services/Mii/IImageDatabaseService.cs b/src/Ryujinx.HLE/HOS/Services/Mii/IImageDatabaseService.cs index 88d7d7b3c..a36aad19a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Mii/IImageDatabaseService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Mii/IImageDatabaseService.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Mii/IStaticService.cs b/src/Ryujinx.HLE/HOS/Services/Mii/IStaticService.cs index 8a6800024..a2713d3c1 100644 --- a/src/Ryujinx.HLE/HOS/Services/Mii/IStaticService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Mii/IStaticService.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Mii/StaticService/IDatabaseService.cs b/src/Ryujinx.HLE/HOS/Services/Mii/StaticService/IDatabaseService.cs index 1a1c20d6e..715d49e8b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Mii/StaticService/IDatabaseService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Mii/StaticService/IDatabaseService.cs @@ -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 diff --git a/src/Ryujinx.HLE/HOS/Services/Mnpp/IServiceForApplication.cs b/src/Ryujinx.HLE/HOS/Services/Mnpp/IServiceForApplication.cs index 8cdab6419..10010193a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Mnpp/IServiceForApplication.cs +++ b/src/Ryujinx.HLE/HOS/Services/Mnpp/IServiceForApplication.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Ncm/Lr/ILocationResolverManager.cs b/src/Ryujinx.HLE/HOS/Services/Ncm/Lr/ILocationResolverManager.cs index 35e311c4d..7a11166a1 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ncm/Lr/ILocationResolverManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ncm/Lr/ILocationResolverManager.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Ncm/Lr/LocationResolverManager/ILocationResolver.cs b/src/Ryujinx.HLE/HOS/Services/Ncm/Lr/LocationResolverManager/ILocationResolver.cs index 71ed56385..c81d50869 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ncm/Lr/LocationResolverManager/ILocationResolver.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ncm/Lr/LocationResolverManager/ILocationResolver.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/ISystemManager.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/ISystemManager.cs index be23d2cdc..2c1dc3af7 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nfc/ISystemManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nfc/ISystemManager.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/IUserManager.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/IUserManager.cs index 5b8afce79..24e9a1475 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nfc/IUserManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nfc/IUserManager.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/NfcManager/INfc.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/NfcManager/INfc.cs index 72027cf48..635fe2a2a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nfc/NfcManager/INfc.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nfc/NfcManager/INfc.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/IDebugManager.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/IDebugManager.cs index b3eff0c2d..677f81127 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/IDebugManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/IDebugManager.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/ISystemManager.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/ISystemManager.cs index 4cb541a6c..5d429d0ba 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/ISystemManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/ISystemManager.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/IUserManager.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/IUserManager.cs index 229386c01..4cfc0c247 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/IUserManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/IUserManager.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/NfpManager/INfp.cs b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/NfpManager/INfp.cs index ca833e33d..5e12510a1 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/NfpManager/INfp.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nfc/Nfp/NfpManager/INfp.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Ngct/IService.cs b/src/Ryujinx.HLE/HOS/Services/Ngct/IService.cs index d9ca70047..6925695c9 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ngct/IService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ngct/IService.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Ngct/IServiceWithManagementApi.cs b/src/Ryujinx.HLE/HOS/Services/Ngct/IServiceWithManagementApi.cs index 88995335c..a5026e227 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ngct/IServiceWithManagementApi.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ngct/IServiceWithManagementApi.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Nifm/IStaticService.cs b/src/Ryujinx.HLE/HOS/Services/Nifm/IStaticService.cs index d669caba1..dc69f19d3 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nifm/IStaticService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nifm/IStaticService.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IGeneralService.cs b/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IGeneralService.cs index dd4efce6e..3abb52b9b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IGeneralService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IGeneralService.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs b/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs index 577d03822..68ba510a2 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nifm/StaticService/IRequest.cs @@ -6,7 +6,7 @@ using System; namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService { - class IRequest : IpcService + partial class IRequest : IpcService { private enum RequestState { diff --git a/src/Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessServer.cs b/src/Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessServer.cs index 4deecc531..9bdc8ea04 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessServer.cs @@ -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() { } diff --git a/src/Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessServerInterface.cs b/src/Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessServerInterface.cs index d7e276ea0..213338299 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessServerInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessServerInterface.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessor.cs b/src/Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessor.cs index c1f58a076..6ec5d8b13 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessor.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nim/IShopServiceAccessor.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Nim/Ntc/IStaticService.cs b/src/Ryujinx.HLE/HOS/Services/Nim/Ntc/IStaticService.cs index ed6e4472e..ead72efe0 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nim/Ntc/IStaticService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nim/Ntc/IStaticService.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Nim/Ntc/StaticService/IEnsureNetworkClockAvailabilityService.cs b/src/Ryujinx.HLE/HOS/Services/Nim/Ntc/StaticService/IEnsureNetworkClockAvailabilityService.cs index 2bd6f4f0d..11247af1a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nim/Ntc/StaticService/IEnsureNetworkClockAvailabilityService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nim/Ntc/StaticService/IEnsureNetworkClockAvailabilityService.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/IAddOnContentManager.cs b/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/IAddOnContentManager.cs index c77358803..cd4ab6d4e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/IAddOnContentManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/IAddOnContentManager.cs @@ -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; diff --git a/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/IPurchaseEventManager.cs b/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/IPurchaseEventManager.cs index 8521adc6e..b01db8a35 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/IPurchaseEventManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/IPurchaseEventManager.cs @@ -6,7 +6,7 @@ using System; namespace Ryujinx.HLE.HOS.Services.Ns.Aoc { - class IPurchaseEventManager : IpcService + partial class IPurchaseEventManager : IpcService { private readonly KEvent _purchasedEvent; diff --git a/src/Ryujinx.HLE/HOS/Services/Ns/IApplicationManagerInterface.cs b/src/Ryujinx.HLE/HOS/Services/Ns/IApplicationManagerInterface.cs index f510da594..e9cca2935 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ns/IApplicationManagerInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ns/IApplicationManagerInterface.cs @@ -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) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Ns/IReadOnlyApplicationControlDataInterface.cs b/src/Ryujinx.HLE/HOS/Services/Ns/IReadOnlyApplicationControlDataInterface.cs index ca7d42b48..a052c6d0e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ns/IReadOnlyApplicationControlDataInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ns/IReadOnlyApplicationControlDataInterface.cs @@ -3,7 +3,7 @@ using LibHac.Ns; namespace Ryujinx.HLE.HOS.Services.Ns { - class IReadOnlyApplicationControlDataInterface : IpcService + partial class IReadOnlyApplicationControlDataInterface : IpcService { public IReadOnlyApplicationControlDataInterface(ServiceCtx context) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Ns/IServiceGetterInterface.cs b/src/Ryujinx.HLE/HOS/Services/Ns/IServiceGetterInterface.cs index e45c6750c..bcca7278f 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ns/IServiceGetterInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ns/IServiceGetterInterface.cs @@ -5,7 +5,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns [Service("ns:rid")] [Service("ns:rt")] [Service("ns:web")] - class IServiceGetterInterface : IpcService + partial class IServiceGetterInterface : IpcService { public IServiceGetterInterface(ServiceCtx context) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs b/src/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs index ed14b3e15..d7e420383 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs @@ -24,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Services.Nv [Service("nvdrv:a")] [Service("nvdrv:s")] [Service("nvdrv:t")] - class INvDrvServices : IpcService + partial class INvDrvServices : IpcService { private static readonly List _deviceFileDebugRegistry = [ diff --git a/src/Ryujinx.HLE/HOS/Services/Olsc/IOlscServiceForApplication.cs b/src/Ryujinx.HLE/HOS/Services/Olsc/IOlscServiceForApplication.cs index 1513d6fed..aac888272 100644 --- a/src/Ryujinx.HLE/HOS/Services/Olsc/IOlscServiceForApplication.cs +++ b/src/Ryujinx.HLE/HOS/Services/Olsc/IOlscServiceForApplication.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; namespace Ryujinx.HLE.HOS.Services.Olsc { [Service("olsc:u")] // 10.0.0+ - class IOlscServiceForApplication : IpcService + partial class IOlscServiceForApplication : IpcService { private bool _initialized; private Dictionary _saveDataBackupSettingDatabase; diff --git a/src/Ryujinx.HLE/HOS/Services/Pctl/IParentalControlServiceFactory.cs b/src/Ryujinx.HLE/HOS/Services/Pctl/IParentalControlServiceFactory.cs index 707f6423c..12938bf2b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Pctl/IParentalControlServiceFactory.cs +++ b/src/Ryujinx.HLE/HOS/Services/Pctl/IParentalControlServiceFactory.cs @@ -6,7 +6,7 @@ namespace Ryujinx.HLE.HOS.Services.Pctl [Service("pctl:a", 0x83BE)] [Service("pctl:r", 0x8040)] [Service("pctl:s", 0x838E)] - class IParentalControlServiceFactory : IpcService + partial class IParentalControlServiceFactory : IpcService { private readonly int _permissionFlag; diff --git a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs index c36482e41..ddf7b21bd 100644 --- a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs @@ -5,7 +5,7 @@ using static LibHac.Ns.ApplicationControlProperty; namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory { - class IParentalControlService : IpcService + partial class IParentalControlService : IpcService { private readonly ulong _pid; private readonly int _permissionFlag; diff --git a/src/Ryujinx.HLE/HOS/Services/Pcv/Bpc/IRtcManager.cs b/src/Ryujinx.HLE/HOS/Services/Pcv/Bpc/IRtcManager.cs index c37176845..7cab9a2a0 100644 --- a/src/Ryujinx.HLE/HOS/Services/Pcv/Bpc/IRtcManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Pcv/Bpc/IRtcManager.cs @@ -3,7 +3,7 @@ using System; namespace Ryujinx.HLE.HOS.Services.Pcv.Bpc { [Service("bpc:r")] // 1.0.0 - 8.1.0 - class IRtcManager : IpcService + partial class IRtcManager : IpcService { public IRtcManager(ServiceCtx context) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Pcv/Clkrst/ClkrstManager/IClkrstSession.cs b/src/Ryujinx.HLE/HOS/Services/Pcv/Clkrst/ClkrstManager/IClkrstSession.cs index 5d90fcbe2..3bdfe9119 100644 --- a/src/Ryujinx.HLE/HOS/Services/Pcv/Clkrst/ClkrstManager/IClkrstSession.cs +++ b/src/Ryujinx.HLE/HOS/Services/Pcv/Clkrst/ClkrstManager/IClkrstSession.cs @@ -4,7 +4,7 @@ using System.Linq; namespace Ryujinx.HLE.HOS.Services.Pcv.Clkrst.ClkrstManager { - class IClkrstSession : IpcService + partial class IClkrstSession : IpcService { private readonly DeviceCode _deviceCode; #pragma warning disable IDE0052 // Remove unread private member diff --git a/src/Ryujinx.HLE/HOS/Services/Pcv/Clkrst/IClkrstManager.cs b/src/Ryujinx.HLE/HOS/Services/Pcv/Clkrst/IClkrstManager.cs index c7c459196..228a3d632 100644 --- a/src/Ryujinx.HLE/HOS/Services/Pcv/Clkrst/IClkrstManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Pcv/Clkrst/IClkrstManager.cs @@ -8,7 +8,7 @@ namespace Ryujinx.HLE.HOS.Services.Pcv.Clkrst { [Service("clkrst")] // 8.0.0+ [Service("clkrst:i")] // 8.0.0+ - class IClkrstManager : IpcService + partial class IClkrstManager : IpcService { private int _moduleStateTableEventHandle = 0; diff --git a/src/Ryujinx.HLE/HOS/Services/Pm/IDebugMonitorInterface.cs b/src/Ryujinx.HLE/HOS/Services/Pm/IDebugMonitorInterface.cs index 9becc6e46..12fdad24f 100644 --- a/src/Ryujinx.HLE/HOS/Services/Pm/IDebugMonitorInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Pm/IDebugMonitorInterface.cs @@ -6,7 +6,7 @@ using Ryujinx.Horizon.Common; namespace Ryujinx.HLE.HOS.Services.Pm { [Service("pm:dmnt")] - class IDebugMonitorInterface : IpcService + partial class IDebugMonitorInterface : IpcService { public IDebugMonitorInterface(ServiceCtx context) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Pm/IInformationInterface.cs b/src/Ryujinx.HLE/HOS/Services/Pm/IInformationInterface.cs index d6440a4d1..e3277f3ff 100644 --- a/src/Ryujinx.HLE/HOS/Services/Pm/IInformationInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Pm/IInformationInterface.cs @@ -3,7 +3,7 @@ using Ryujinx.HLE.HOS.Kernel.Process; namespace Ryujinx.HLE.HOS.Services.Pm { [Service("pm:info")] - class IInformationInterface : IpcService + partial class IInformationInterface : IpcService { public IInformationInterface(ServiceCtx context) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Pm/IShellInterface.cs b/src/Ryujinx.HLE/HOS/Services/Pm/IShellInterface.cs index 1ee2c377f..9bac12bca 100644 --- a/src/Ryujinx.HLE/HOS/Services/Pm/IShellInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Pm/IShellInterface.cs @@ -1,7 +1,7 @@ namespace Ryujinx.HLE.HOS.Services.Pm { [Service("pm:shell")] - class IShellInterface : IpcService + partial class IShellInterface : IpcService { public IShellInterface(ServiceCtx context) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Ptm/Psm/IPsmServer.cs b/src/Ryujinx.HLE/HOS/Services/Ptm/Psm/IPsmServer.cs index 3ce502974..94536382f 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ptm/Psm/IPsmServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ptm/Psm/IPsmServer.cs @@ -3,7 +3,7 @@ using Ryujinx.Common.Logging; namespace Ryujinx.HLE.HOS.Services.Ptm.Psm { [Service("psm")] - class IPsmServer : IpcService + partial class IPsmServer : IpcService { public IPsmServer(ServiceCtx context) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Ptm/Psm/IPsmSession.cs b/src/Ryujinx.HLE/HOS/Services/Ptm/Psm/IPsmSession.cs index edfa60afd..3d737108d 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ptm/Psm/IPsmSession.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ptm/Psm/IPsmSession.cs @@ -5,7 +5,7 @@ using Ryujinx.Horizon.Common; namespace Ryujinx.HLE.HOS.Services.Ptm.Psm { - class IPsmSession : IpcService + partial class IPsmSession : IpcService { private readonly KEvent _stateChangeEvent; private int _stateChangeEventHandle; diff --git a/src/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs b/src/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs index 873782d87..e8e80853e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs @@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro { [Service("ldr:ro")] [Service("ro:1")] // 7.0.0+ - class IRoInterface : DisposableIpcService + partial class IRoInterface : DisposableIpcService { private const int MaxNrr = 0x40; private const int MaxNro = 0x40; diff --git a/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/IQueryService.cs b/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/IQueryService.cs index 6508794ab..ecc28e111 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/IQueryService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/IQueryService.cs @@ -3,7 +3,7 @@ using Ryujinx.HLE.HOS.Services.Sdb.Pdm.QueryService; namespace Ryujinx.HLE.HOS.Services.Sdb.Pdm { [Service("pdm:qry")] - class IQueryService : IpcService + partial class IQueryService : IpcService { public IQueryService(ServiceCtx context) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Sdb/Pl/ISharedFontManager.cs b/src/Ryujinx.HLE/HOS/Services/Sdb/Pl/ISharedFontManager.cs index 45c4ce7e1..e8df8d2da 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sdb/Pl/ISharedFontManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sdb/Pl/ISharedFontManager.cs @@ -7,7 +7,7 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pl { [Service("pl:u")] [Service("pl:s")] // 9.0.0+ - class ISharedFontManager : IpcService + partial class ISharedFontManager : IpcService { private int _fontSharedMemHandle; diff --git a/src/Ryujinx.HLE/HOS/Services/Settings/ISettingsServer.cs b/src/Ryujinx.HLE/HOS/Services/Settings/ISettingsServer.cs index fef994bf8..68ca85df3 100644 --- a/src/Ryujinx.HLE/HOS/Services/Settings/ISettingsServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Settings/ISettingsServer.cs @@ -6,7 +6,7 @@ using System.Text; namespace Ryujinx.HLE.HOS.Services.Settings { [Service("set")] - class ISettingsServer : IpcService + partial class ISettingsServer : IpcService { public ISettingsServer(ServiceCtx context) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Settings/ISystemSettingsServer.cs b/src/Ryujinx.HLE/HOS/Services/Settings/ISystemSettingsServer.cs index cfad2884a..7dc89b5f1 100644 --- a/src/Ryujinx.HLE/HOS/Services/Settings/ISystemSettingsServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Settings/ISystemSettingsServer.cs @@ -15,7 +15,7 @@ using System.Text; namespace Ryujinx.HLE.HOS.Services.Settings { [Service("set:sys")] - class ISystemSettingsServer : IpcService + partial class ISystemSettingsServer : IpcService { public ISystemSettingsServer(ServiceCtx context) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs b/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs index 743c208e4..bf1ba5b8e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sm/IUserInterface.cs @@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Sm private bool _isInitialized; - public IUserInterface(KernelContext context, SmRegistry registry) : base(registerTipc: true) + public IUserInterface(KernelContext context, SmRegistry registry) { _commonServer = new ServerBase(context, "CommonServer"); _registry = registry; diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs index ef3b68b27..cb56be35b 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Bsd/IClient.cs @@ -14,7 +14,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd { [Service("bsd:s", true)] [Service("bsd:u", false)] - class IClient : IpcService + partial class IClient : IpcService { private static readonly List _pollManagers = [ diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs index 9e13a005c..17ec989c2 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Nsd/IManager.cs @@ -11,7 +11,7 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Nsd { [Service("nsd:a")] // Max sessions: 5 [Service("nsd:u")] // Max sessions: 20 - class IManager : IpcService + partial class IManager : IpcService { public static readonly NsdSettings NsdSettings; private readonly FqdnResolver _fqdnResolver; diff --git a/src/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/IResolver.cs b/src/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/IResolver.cs index 80bdbec8a..2df19228d 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/IResolver.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sockets/Sfdnsres/IResolver.cs @@ -16,7 +16,7 @@ using System.Text; namespace Ryujinx.HLE.HOS.Services.Sockets.Sfdnsres { [Service("sfdnsres")] - class IResolver : IpcService + partial class IResolver : IpcService { public IResolver(ServiceCtx context) { diff --git a/src/Ryujinx.HLE/HOS/Services/Spl/IGeneralInterface.cs b/src/Ryujinx.HLE/HOS/Services/Spl/IGeneralInterface.cs index 6a9b4d442..725b27054 100644 --- a/src/Ryujinx.HLE/HOS/Services/Spl/IGeneralInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Spl/IGeneralInterface.cs @@ -10,7 +10,7 @@ namespace Ryujinx.HLE.HOS.Services.Spl [Service("spl:manu")] [Service("spl:mig")] [Service("spl:ssl")] - class IGeneralInterface : IpcService + partial class IGeneralInterface : IpcService { public IGeneralInterface(ServiceCtx context) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Spl/IRandomInterface.cs b/src/Ryujinx.HLE/HOS/Services/Spl/IRandomInterface.cs index fc58613f5..65b482bf2 100644 --- a/src/Ryujinx.HLE/HOS/Services/Spl/IRandomInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Spl/IRandomInterface.cs @@ -3,7 +3,7 @@ using System.Security.Cryptography; namespace Ryujinx.HLE.HOS.Services.Spl { [Service("csrng")] - class IRandomInterface : DisposableIpcService + partial class IRandomInterface : DisposableIpcService { private readonly RandomNumberGenerator _rng; diff --git a/src/Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs b/src/Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs index 8f38f293f..4d9d9777e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ssl/ISslService.cs @@ -10,7 +10,7 @@ namespace Ryujinx.HLE.HOS.Services.Ssl { [Service("ssl")] [Service("ssl:s")] - class ISslService : IpcService + partial class ISslService : IpcService { // NOTE: The SSL service is used by games to connect it to various official online services, which we do not intend to support. // In this case it is acceptable to stub all calls of the service. diff --git a/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/ISslConnection.cs b/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/ISslConnection.cs index 623990a58..830eb635a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/ISslConnection.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/ISslConnection.cs @@ -8,7 +8,7 @@ using System.Text; namespace Ryujinx.HLE.HOS.Services.Ssl.SslService { - class ISslConnection : IpcService, IDisposable + partial class ISslConnection : IpcService, IDisposable { private bool _doNotClockSocket; private bool _getServerCertChain; diff --git a/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/ISslContext.cs b/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/ISslContext.cs index 7b371d299..d86c87bd0 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/ISslContext.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ssl/SslService/ISslContext.cs @@ -4,7 +4,7 @@ using System.Text; namespace Ryujinx.HLE.HOS.Services.Ssl.SslService { - class ISslContext : IpcService + partial class ISslContext : IpcService { private uint _connectionCount; diff --git a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs index e23e6fa3f..9a3da9571 100644 --- a/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs +++ b/src/Ryujinx.HLE/HOS/Services/SurfaceFlinger/IHOSBinderDriver.cs @@ -6,7 +6,7 @@ using System; namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger { - abstract class IHOSBinderDriver : IpcService + abstract partial class IHOSBinderDriver : IpcService { public IHOSBinderDriver() { } diff --git a/src/Ryujinx.HLE/HOS/Services/Time/IStaticServiceForGlue.cs b/src/Ryujinx.HLE/HOS/Services/Time/IStaticServiceForGlue.cs index eaddf9cff..2c2c63f9f 100644 --- a/src/Ryujinx.HLE/HOS/Services/Time/IStaticServiceForGlue.cs +++ b/src/Ryujinx.HLE/HOS/Services/Time/IStaticServiceForGlue.cs @@ -10,7 +10,7 @@ namespace Ryujinx.HLE.HOS.Services.Time [Service("time:a", TimePermissions.Admin)] [Service("time:r", TimePermissions.Repair)] [Service("time:u", TimePermissions.User)] - class IStaticServiceForGlue : IpcService + partial class IStaticServiceForGlue : IpcService { private readonly IStaticServiceForPsc _inner; private readonly TimePermissions _permissions; diff --git a/src/Ryujinx.HLE/HOS/Services/Time/IStaticServiceForPsc.cs b/src/Ryujinx.HLE/HOS/Services/Time/IStaticServiceForPsc.cs index a6b33e4ae..53cd1b87e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Time/IStaticServiceForPsc.cs +++ b/src/Ryujinx.HLE/HOS/Services/Time/IStaticServiceForPsc.cs @@ -16,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Services.Time { [Service("time:s", TimePermissions.System)] [Service("time:su", TimePermissions.SystemUpdate)] - class IStaticServiceForPsc : IpcService + partial class IStaticServiceForPsc : IpcService { private readonly TimeManager _timeManager; private readonly TimePermissions _permissions; diff --git a/src/Ryujinx.HLE/HOS/Services/Time/ITimeServiceManager.cs b/src/Ryujinx.HLE/HOS/Services/Time/ITimeServiceManager.cs index 1648aa3e1..3abee97df 100644 --- a/src/Ryujinx.HLE/HOS/Services/Time/ITimeServiceManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Time/ITimeServiceManager.cs @@ -11,7 +11,7 @@ using System.IO; namespace Ryujinx.HLE.HOS.Services.Time { [Service("time:m")] // 9.0.0+ - class ITimeServiceManager : IpcService + partial class ITimeServiceManager : IpcService { private readonly TimeManager _timeManager; private int _automaticCorrectionEvent; diff --git a/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ISteadyClock.cs b/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ISteadyClock.cs index 8ddb646b9..6c99bf683 100644 --- a/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ISteadyClock.cs +++ b/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ISteadyClock.cs @@ -4,7 +4,7 @@ using Ryujinx.HLE.HOS.Services.Time.Clock; namespace Ryujinx.HLE.HOS.Services.Time.StaticService { - class ISteadyClock : IpcService + partial class ISteadyClock : IpcService { private readonly SteadyClockCore _steadyClock; private readonly bool _writePermission; diff --git a/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs b/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs index ada5f057a..47bcfc802 100644 --- a/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs +++ b/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs @@ -8,7 +8,7 @@ using System; namespace Ryujinx.HLE.HOS.Services.Time.StaticService { - class ISystemClock : IpcService + partial class ISystemClock : IpcService { private readonly SystemClockCore _clockCore; private readonly bool _writePermission; diff --git a/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ITimeZoneServiceForGlue.cs b/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ITimeZoneServiceForGlue.cs index 81944c835..028506a3e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ITimeZoneServiceForGlue.cs +++ b/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ITimeZoneServiceForGlue.cs @@ -10,7 +10,7 @@ using System.Text; namespace Ryujinx.HLE.HOS.Services.Time.StaticService { - class ITimeZoneServiceForGlue : IpcService + partial class ITimeZoneServiceForGlue : IpcService { private readonly TimeZoneContentManager _timeZoneContentManager; private readonly ITimeZoneServiceForPsc _inner; diff --git a/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ITimeZoneServiceForPsc.cs b/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ITimeZoneServiceForPsc.cs index b18a4f76c..245a5a050 100644 --- a/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ITimeZoneServiceForPsc.cs +++ b/src/Ryujinx.HLE/HOS/Services/Time/StaticService/ITimeZoneServiceForPsc.cs @@ -12,7 +12,7 @@ using System.Runtime.InteropServices; namespace Ryujinx.HLE.HOS.Services.Time.StaticService { - class ITimeZoneServiceForPsc : IpcService + partial class ITimeZoneServiceForPsc : IpcService { private readonly TimeZoneManager _timeZoneManager; private readonly bool _writePermission; diff --git a/src/Ryujinx.HLE/HOS/Services/Vi/IApplicationRootService.cs b/src/Ryujinx.HLE/HOS/Services/Vi/IApplicationRootService.cs index 9cc9d421f..385ef486e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Vi/IApplicationRootService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Vi/IApplicationRootService.cs @@ -4,7 +4,7 @@ using Ryujinx.HLE.HOS.Services.Vi.Types; namespace Ryujinx.HLE.HOS.Services.Vi { [Service("vi:u")] - class IApplicationRootService : IpcService + partial class IApplicationRootService : IpcService { public IApplicationRootService(ServiceCtx context) : base(context.Device.System.ViServer) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Vi/IManagerRootService.cs b/src/Ryujinx.HLE/HOS/Services/Vi/IManagerRootService.cs index dd4b25a08..0ef80b196 100644 --- a/src/Ryujinx.HLE/HOS/Services/Vi/IManagerRootService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Vi/IManagerRootService.cs @@ -4,7 +4,7 @@ using Ryujinx.HLE.HOS.Services.Vi.Types; namespace Ryujinx.HLE.HOS.Services.Vi { [Service("vi:m")] - class IManagerRootService : IpcService + partial class IManagerRootService : IpcService { // vi:u/m/s aren't on 3 separate threads but we can't put them together with the current ServerBase public IManagerRootService(ServiceCtx context) : base(context.Device.System.ViServerM) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Vi/ISystemRootService.cs b/src/Ryujinx.HLE/HOS/Services/Vi/ISystemRootService.cs index b2415f2e4..974684d36 100644 --- a/src/Ryujinx.HLE/HOS/Services/Vi/ISystemRootService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Vi/ISystemRootService.cs @@ -4,7 +4,7 @@ using Ryujinx.HLE.HOS.Services.Vi.Types; namespace Ryujinx.HLE.HOS.Services.Vi { [Service("vi:s")] - class ISystemRootService : IpcService + partial class ISystemRootService : IpcService { // vi:u/m/s aren't on 3 separate threads but we can't put them together with the current ServerBase public ISystemRootService(ServiceCtx context) : base(context.Device.System.ViServerS) { } diff --git a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs index 0e5d103d1..5a3780bb6 100644 --- a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/IManagerDisplayService.cs @@ -2,7 +2,7 @@ using Ryujinx.Common.Logging; namespace Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService { - class IManagerDisplayService : IpcService + partial class IManagerDisplayService : IpcService { private readonly IApplicationDisplayService _applicationDisplayService; diff --git a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/ISystemDisplayService.cs b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/ISystemDisplayService.cs index 507290692..0140c0ee1 100644 --- a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/ISystemDisplayService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/ApplicationDisplayService/ISystemDisplayService.cs @@ -2,7 +2,7 @@ using Ryujinx.Common.Logging; namespace Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService { - class ISystemDisplayService : IpcService + partial class ISystemDisplayService : IpcService { private readonly IApplicationDisplayService _applicationDisplayService; diff --git a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs index 99c640aa0..c5cc05610 100644 --- a/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Vi/RootService/IApplicationDisplayService.cs @@ -17,7 +17,7 @@ using System.Text; namespace Ryujinx.HLE.HOS.Services.Vi.RootService { - class IApplicationDisplayService : IpcService + partial class IApplicationDisplayService : IpcService { private readonly ViServiceType _serviceType; From 73406d1f3aae4bb220a1c53bd9975dd3cded0a4e Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 19 Nov 2025 21:46:10 -0600 Subject: [PATCH 06/10] Move Tipc commands and fix remaining warnings --- .gitignore | 3 + Directory.Build.props | 3 - Directory.Build.targets | 6 ++ .../Ryujinx.BuildValidationTasks.csproj | 2 + .../Formatters/DynamicObjectFormatter.cs | 2 + .../IpcCommandGenerator.cs | 54 +++++++------ .../ServiceNotImplementedException.cs | 2 +- src/Ryujinx.HLE/HOS/Services/IpcService.cs | 81 +++++++------------ .../HOS/Services/Nv/INvDrvServices.cs | 33 ++++---- src/Ryujinx/Ryujinx.csproj | 13 --- src/Ryujinx/TrimmerRoots.xml | 5 -- 11 files changed, 86 insertions(+), 118 deletions(-) create mode 100644 Directory.Build.targets delete mode 100644 src/Ryujinx/TrimmerRoots.xml diff --git a/.gitignore b/.gitignore index 6f887e638..17df1588e 100644 --- a/.gitignore +++ b/.gitignore @@ -185,3 +185,6 @@ PublishProfiles/ # Ignore distribution build files distribution/macos/temp/ distribution/macos/output/ + +# MSBuild logs +*.binlog diff --git a/Directory.Build.props b/Directory.Build.props index d20dcd0eb..a4df830a3 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,8 +2,5 @@ net10.0 preview - true - true - true diff --git a/Directory.Build.targets b/Directory.Build.targets new file mode 100644 index 000000000..9ef091149 --- /dev/null +++ b/Directory.Build.targets @@ -0,0 +1,6 @@ + + + true + true + + diff --git a/src/Ryujinx.BuildValidationTasks/Ryujinx.BuildValidationTasks.csproj b/src/Ryujinx.BuildValidationTasks/Ryujinx.BuildValidationTasks.csproj index 31181bc55..eff20a215 100644 --- a/src/Ryujinx.BuildValidationTasks/Ryujinx.BuildValidationTasks.csproj +++ b/src/Ryujinx.BuildValidationTasks/Ryujinx.BuildValidationTasks.csproj @@ -2,6 +2,8 @@ Exe + false + false diff --git a/src/Ryujinx.Common/Logging/Formatters/DynamicObjectFormatter.cs b/src/Ryujinx.Common/Logging/Formatters/DynamicObjectFormatter.cs index a7b4da40f..7533bf6fb 100644 --- a/src/Ryujinx.Common/Logging/Formatters/DynamicObjectFormatter.cs +++ b/src/Ryujinx.Common/Logging/Formatters/DynamicObjectFormatter.cs @@ -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('{'); diff --git a/src/Ryujinx.HLE.Generators/IpcCommandGenerator.cs b/src/Ryujinx.HLE.Generators/IpcCommandGenerator.cs index f96195f84..47918c5cf 100644 --- a/src/Ryujinx.HLE.Generators/IpcCommandGenerator.cs +++ b/src/Ryujinx.HLE.Generators/IpcCommandGenerator.cs @@ -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 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(); + } }); } } diff --git a/src/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs b/src/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs index f1d453172..038eed023 100644 --- a/src/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs +++ b/src/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs @@ -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})"); diff --git a/src/Ryujinx.HLE/HOS/Services/IpcService.cs b/src/Ryujinx.HLE/HOS/Services/IpcService.cs index 31420f485..780b68f79 100644 --- a/src/Ryujinx.HLE/HOS/Services/IpcService.cs +++ b/src/Ryujinx.HLE/HOS/Services/IpcService.cs @@ -11,10 +11,8 @@ using System.Reflection; namespace Ryujinx.HLE.HOS.Services { - abstract partial class IpcService + abstract class IpcService { - public IReadOnlyDictionary 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() - .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) diff --git a/src/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs b/src/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs index d7e420383..50e041766 100644 --- a/src/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs +++ b/src/Ryujinx.HLE/HOS/Services/Nv/INvDrvServices.cs @@ -32,20 +32,20 @@ namespace Ryujinx.HLE.HOS.Services.Nv "/dev/nvhost-prof-gpu" ]; - private static readonly Dictionary _deviceFileRegistry = new() + private static readonly Dictionary> _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 _byteArrayPool = ArrayPool.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 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; diff --git a/src/Ryujinx/Ryujinx.csproj b/src/Ryujinx/Ryujinx.csproj index fd17db406..b67bb054b 100644 --- a/src/Ryujinx/Ryujinx.csproj +++ b/src/Ryujinx/Ryujinx.csproj @@ -28,21 +28,12 @@ true - - true - false - - - - - true - @@ -179,8 +170,4 @@ - - - - diff --git a/src/Ryujinx/TrimmerRoots.xml b/src/Ryujinx/TrimmerRoots.xml deleted file mode 100644 index 1db3915e7..000000000 --- a/src/Ryujinx/TrimmerRoots.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - From b9da6a15d73187ef661be9ae5dc114da5107c757 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 19 Nov 2025 21:57:15 -0600 Subject: [PATCH 07/10] Optimize IpcCommand source gen --- .../IpcCommandGenerator.cs | 60 +++++++++++++++++-- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/src/Ryujinx.HLE.Generators/IpcCommandGenerator.cs b/src/Ryujinx.HLE.Generators/IpcCommandGenerator.cs index 47918c5cf..b201220fe 100644 --- a/src/Ryujinx.HLE.Generators/IpcCommandGenerator.cs +++ b/src/Ryujinx.HLE.Generators/IpcCommandGenerator.cs @@ -1,5 +1,6 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; +using System; using System.Linq; using System.Collections.Immutable; using System.Threading; @@ -9,20 +10,60 @@ namespace Ryujinx.HLE.Generators [Generator] public class IpcCommandGenerator : IIncrementalGenerator { - private sealed class CommandData + private sealed class CommandData : IEquatable { public required string Namespace { get; init; } public required string TypeName { get; init; } public required string MethodName { get; init; } public required ImmutableArray 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 + private sealed class ServiceData : IEquatable { public required string Namespace { get; init; } public required string TypeName { get; init; } public required ImmutableArray CmifCommands { get; init; } public required ImmutableArray 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) @@ -82,10 +123,17 @@ namespace Ryujinx.HLE.Generators generator.EnterScope($"namespace {data.Namespace}"); generator.EnterScope($"partial class {data.TypeName}"); - - GenerateCommandMethod("Cmif", data.CmifCommands); - GenerateCommandMethod("Tipc", data.TipcCommands); - + + if (!data.CmifCommands.IsEmpty) + { + GenerateCommandMethod("Cmif", data.CmifCommands); + } + + if (!data.TipcCommands.IsEmpty) + { + GenerateCommandMethod("Tipc", data.TipcCommands); + } + generator.LeaveScope(); generator.LeaveScope(); From 529d6f44bb70c90e5c9da69da56bf3abc2ee4016 Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 19 Nov 2025 22:28:50 -0600 Subject: [PATCH 08/10] Tamper generic explosion and code style --- .../IpcCommandGenerator.cs | 25 ++++++++++--------- .../UserServiceGenerator.cs | 8 +++--- .../ServiceNotImplementedException.cs | 2 +- .../HOS/Tamper/CodeEmitters/Arithmetic.cs | 22 ++++++++-------- .../Tamper/CodeEmitters/LegacyArithmetic.cs | 12 ++++----- .../CodeEmitters/LoadRegisterWithMemory.cs | 2 +- .../CodeEmitters/StoreConstantToAddress.cs | 2 +- .../CodeEmitters/StoreConstantToMemory.cs | 2 +- .../CodeEmitters/StoreRegisterToMemory.cs | 2 +- .../HOS/Tamper/Conditions/CondEQ.cs | 10 +++++--- .../HOS/Tamper/Conditions/CondGE.cs | 10 +++++--- .../HOS/Tamper/Conditions/CondGT.cs | 10 +++++--- .../HOS/Tamper/Conditions/CondLE.cs | 10 +++++--- .../HOS/Tamper/Conditions/CondLT.cs | 7 ++++++ .../HOS/Tamper/Conditions/CondNE.cs | 7 ++++++ .../HOS/Tamper/Conditions/ICondition.cs | 6 ----- .../Tamper/Conditions/IConditionFactory.cs | 10 ++++++++ .../HOS/Tamper/InstructionHelper.cs | 18 ++++++------- .../HOS/Tamper/Operations/IOperation.cs | 3 --- .../Tamper/Operations/IOperationFactory.cs | 10 ++++++++ .../HOS/Tamper/Operations/OpAdd.cs | 10 +++++--- .../HOS/Tamper/Operations/OpAnd.cs | 10 +++++--- .../HOS/Tamper/Operations/OpLsh.cs | 10 +++++--- .../HOS/Tamper/Operations/OpMov.cs | 10 +++++--- .../HOS/Tamper/Operations/OpMul.cs | 10 +++++--- .../HOS/Tamper/Operations/OpNot.cs | 10 +++++--- src/Ryujinx.HLE/HOS/Tamper/Operations/OpOr.cs | 10 +++++--- .../HOS/Tamper/Operations/OpRsh.cs | 10 +++++--- .../HOS/Tamper/Operations/OpSub.cs | 10 +++++--- .../HOS/Tamper/Operations/OpXor.cs | 10 +++++--- 30 files changed, 180 insertions(+), 98 deletions(-) create mode 100644 src/Ryujinx.HLE/HOS/Tamper/Conditions/IConditionFactory.cs create mode 100644 src/Ryujinx.HLE/HOS/Tamper/Operations/IOperationFactory.cs diff --git a/src/Ryujinx.HLE.Generators/IpcCommandGenerator.cs b/src/Ryujinx.HLE.Generators/IpcCommandGenerator.cs index b201220fe..3e77fb1fb 100644 --- a/src/Ryujinx.HLE.Generators/IpcCommandGenerator.cs +++ b/src/Ryujinx.HLE.Generators/IpcCommandGenerator.cs @@ -68,8 +68,8 @@ namespace Ryujinx.HLE.Generators public void Initialize(IncrementalGeneratorInitializationContext context) { - var predicate = (SyntaxNode node, CancellationToken _) => node is MethodDeclarationSyntax; - var transform = (GeneratorAttributeSyntaxContext ctx, CancellationToken _) => + Func predicate = (node, _) => node is MethodDeclarationSyntax; + Func transform = (ctx, _) => { var target = (IMethodSymbol)ctx.TargetSymbol; return new CommandData @@ -80,27 +80,28 @@ namespace Ryujinx.HLE.Generators CommandIds = ctx.Attributes.Select(attr => (int)attr.ConstructorArguments[0].Value!).ToImmutableArray(), }; }; - var cmifCommands = + IncrementalValuesProvider cmifCommands = context.SyntaxProvider.ForAttributeWithMetadataName("Ryujinx.HLE.HOS.Services.CommandCmifAttribute", predicate, transform ); - var tipcCommands = + IncrementalValuesProvider tipcCommands = context.SyntaxProvider.ForAttributeWithMetadataName("Ryujinx.HLE.HOS.Services.CommandTipcAttribute", predicate, transform ); - var allCommands = cmifCommands.Collect().Combine(tipcCommands.Collect()); + IncrementalValueProvider<(ImmutableArray Left, ImmutableArray Right)> allCommands = + cmifCommands.Collect().Combine(tipcCommands.Collect()); - var types = allCommands.SelectMany((commands, _) => + IncrementalValuesProvider types = allCommands.SelectMany((commands, _) => { - var cmif = commands.Left.ToLookup(c => (c.Namespace, c.TypeName)); - var tipc = commands.Right.ToLookup(c => (c.Namespace, c.TypeName)); + 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)); - var builder = ImmutableArray.CreateBuilder(); + ImmutableArray.Builder builder = ImmutableArray.CreateBuilder(); - foreach (var type in cmif.Select(c => c.Key).Union(tipc.Select(t => t.Key))) + foreach ((string Namespace, string TypeName) type in cmif.Select(c => c.Key).Union(tipc.Select(t => t.Key))) { builder.Add(new ServiceData { @@ -143,7 +144,7 @@ namespace Ryujinx.HLE.Generators { generator.EnterScope($"protected override RC Invoke{commandType}Method(int id, ServiceCtx context)"); generator.EnterScope("switch (id)"); - foreach (var command in commands) + foreach (CommandData command in commands) { generator.AppendLine($"case {string.Join(" or ", command.CommandIds)}:"); generator.IncreaseIndentation(); @@ -157,7 +158,7 @@ namespace Ryujinx.HLE.Generators generator.EnterScope($"public override int {commandType}CommandIdByMethodName(string name)"); generator.EnterScope("return name switch"); - foreach (var command in commands) + foreach (CommandData command in commands) { // just return the first command with this name generator.AppendLine($"\"{command.MethodName}\" => {command.CommandIds[0]},"); diff --git a/src/Ryujinx.HLE.Generators/UserServiceGenerator.cs b/src/Ryujinx.HLE.Generators/UserServiceGenerator.cs index ace720667..7b30988fb 100644 --- a/src/Ryujinx.HLE.Generators/UserServiceGenerator.cs +++ b/src/Ryujinx.HLE.Generators/UserServiceGenerator.cs @@ -28,12 +28,12 @@ namespace Ryujinx.HLE.Generators public void Initialize(IncrementalGeneratorInitializationContext context) { - var pipeline = context.SyntaxProvider.ForAttributeWithMetadataName("Ryujinx.HLE.HOS.Services.ServiceAttribute", + IncrementalValuesProvider 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; - var instances = ctx.Attributes.Select(attr => + 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); @@ -60,9 +60,9 @@ namespace Ryujinx.HLE.Generators generator.EnterScope("return name switch"); - foreach (var serviceImpl in data) + foreach (ServiceData serviceImpl in data) { - foreach (var instance in serviceImpl.Instances) + foreach ((string ServiceName, string ParameterValue) instance in serviceImpl.Instances) { if (instance.ParameterValue == null) { diff --git a/src/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs b/src/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs index 038eed023..19684c273 100644 --- a/src/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs +++ b/src/Ryujinx.HLE/Exceptions/ServiceNotImplementedException.cs @@ -48,7 +48,7 @@ namespace Ryujinx.HLE.Exceptions { StringBuilder sb = new(); - var commandId = Request.Type > IpcMessageType.TipcCloseSession + int commandId = Request.Type > IpcMessageType.TipcCloseSession ? Service.TipcCommandIdByMethodName(MethodName) : Service.CmifCommandIdByMethodName(MethodName); diff --git a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/Arithmetic.cs b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/Arithmetic.cs index d0a2e2aa1..b93efbe43 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/Arithmetic.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/Arithmetic.cs @@ -69,7 +69,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters throw new TamperCompilationException($"Invalid right-hand side switch {rightHandSideIsImmediate} in Atmosphere cheat"); } - void EmitCore(IOperand rhs = null) where TOp : IOperation + void EmitCore(IOperand rhs = null) where TOp : IOperationFactory { InstructionHelper.Emit(operationWidth, context, destinationRegister, leftHandSideRegister, rhs); } @@ -77,34 +77,34 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters switch (operation) { case Add: - EmitCore>(rightHandSideOperand); + EmitCore(rightHandSideOperand); break; case Sub: - EmitCore>(rightHandSideOperand); + EmitCore(rightHandSideOperand); break; case Mul: - EmitCore>(rightHandSideOperand); + EmitCore(rightHandSideOperand); break; case Lsh: - EmitCore>(rightHandSideOperand); + EmitCore(rightHandSideOperand); break; case Rsh: - EmitCore>(rightHandSideOperand); + EmitCore(rightHandSideOperand); break; case And: - EmitCore>(rightHandSideOperand); + EmitCore(rightHandSideOperand); break; case Or: - EmitCore>(rightHandSideOperand); + EmitCore(rightHandSideOperand); break; case Not: - EmitCore>(); + EmitCore(); break; case Xor: - EmitCore>(rightHandSideOperand); + EmitCore(rightHandSideOperand); break; case Mov: - EmitCore>(); + EmitCore(); break; default: throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat"); diff --git a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/LegacyArithmetic.cs b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/LegacyArithmetic.cs index df60b058d..ba1acb172 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/LegacyArithmetic.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/LegacyArithmetic.cs @@ -37,7 +37,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters ulong immediate = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, ValueImmediateSize); Value rightHandSideValue = new(immediate); - void EmitCore() where TOp : IOperation + void EmitCore() where TOp : IOperationFactory { InstructionHelper.Emit(operationWidth, context, register, register, rightHandSideValue); } @@ -45,19 +45,19 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters switch (operation) { case Add: - EmitCore>(); + EmitCore(); break; case Sub: - EmitCore>(); + EmitCore(); break; case Mul: - EmitCore>(); + EmitCore(); break; case Lsh: - EmitCore>(); + EmitCore(); break; case Rsh: - EmitCore>(); + EmitCore(); break; default: throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat"); diff --git a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/LoadRegisterWithMemory.cs b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/LoadRegisterWithMemory.cs index 183f4dd2f..45448b99d 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/LoadRegisterWithMemory.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/LoadRegisterWithMemory.cs @@ -53,7 +53,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters throw new TamperCompilationException($"Invalid source mode {useDestinationAsSourceIndex} in Atmosphere cheat"); } - InstructionHelper.Emit>(operationWidth, context, destinationRegister, sourceMemory, null); + InstructionHelper.Emit(operationWidth, context, destinationRegister, sourceMemory, null); } } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreConstantToAddress.cs b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreConstantToAddress.cs index beb61b459..25e39bd71 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreConstantToAddress.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreConstantToAddress.cs @@ -37,7 +37,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters ulong valueImmediate = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, valueImmediateSize); Value storeValue = new(valueImmediate); - InstructionHelper.Emit>(operationWidth, context, dstMem, storeValue, null); + InstructionHelper.Emit(operationWidth, context, dstMem, storeValue, null); } } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreConstantToMemory.cs b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreConstantToMemory.cs index 8426592ba..bb53f3a7b 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreConstantToMemory.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreConstantToMemory.cs @@ -51,7 +51,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters throw new TamperCompilationException($"Invalid offset mode {useOffsetRegister} in Atmosphere cheat"); } - InstructionHelper.Emit>(operationWidth, context, destinationMemory, storeValue, null); + InstructionHelper.Emit(operationWidth, context, destinationMemory, storeValue, null); switch (incrementAddressRegister) { diff --git a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreRegisterToMemory.cs b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreRegisterToMemory.cs index 3b7df67b2..a64b4ebbc 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreRegisterToMemory.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/CodeEmitters/StoreRegisterToMemory.cs @@ -79,7 +79,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters throw new TamperCompilationException($"Invalid offset type {offsetType} in Atmosphere cheat"); } - InstructionHelper.Emit>(operationWidth, context, destinationMemory, sourceRegister, null); + InstructionHelper.Emit(operationWidth, context, destinationMemory, sourceRegister, null); switch (incrementAddressRegister) { diff --git a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondEQ.cs b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondEQ.cs index e0b98e3d8..897170864 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondEQ.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondEQ.cs @@ -3,6 +3,13 @@ using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Conditions { + sealed class CondEQFactory : IConditionFactory + { + private CondEQFactory() { } + + public static ICondition CreateFor(IOperand lhs, IOperand rhs) where T : unmanaged, INumber + => new CondEQ(lhs, rhs); + } class CondEQ : ICondition where T : unmanaged, INumber { private readonly IOperand _lhs; @@ -18,8 +25,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions { return _lhs.Get() == _rhs.Get(); } - - public static ICondition CreateFor(IOperand lhs, IOperand rhs) where T1 : INumber - => new CondEQ(lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondGE.cs b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondGE.cs index 5c3ef83e6..7442d1f63 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondGE.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondGE.cs @@ -3,6 +3,13 @@ using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Conditions { + sealed class CondGEFactory : IConditionFactory + { + private CondGEFactory() { } + + public static ICondition CreateFor(IOperand lhs, IOperand rhs) where T : unmanaged, INumber + => new CondGE(lhs, rhs); + } class CondGE : ICondition where T : unmanaged, INumber { private readonly IOperand _lhs; @@ -18,8 +25,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions { return _lhs.Get() >= _rhs.Get(); } - - public static ICondition CreateFor(IOperand lhs, IOperand rhs) where T1 : INumber - => new CondGE(lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondGT.cs b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondGT.cs index 131da14bb..7b631b887 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondGT.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondGT.cs @@ -3,6 +3,13 @@ using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Conditions { + sealed class CondGTFactory : IConditionFactory + { + private CondGTFactory() { } + + public static ICondition CreateFor(IOperand lhs, IOperand rhs) where T : unmanaged, INumber + => new CondGT(lhs, rhs); + } class CondGT : ICondition where T : unmanaged, INumber { private readonly IOperand _lhs; @@ -18,8 +25,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions { return _lhs.Get() > _rhs.Get(); } - - public static ICondition CreateFor(IOperand lhs, IOperand rhs) where T1 : INumber - => new CondGT(lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondLE.cs b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondLE.cs index 2e709e243..81bdb4056 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondLE.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondLE.cs @@ -3,6 +3,13 @@ using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Conditions { + sealed class CondLEFactory : IConditionFactory + { + private CondLEFactory() { } + + public static ICondition CreateFor(IOperand lhs, IOperand rhs) where T : unmanaged, INumber + => new CondLE(lhs, rhs); + } class CondLE : ICondition where T : unmanaged, INumber { private readonly IOperand _lhs; @@ -18,8 +25,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions { return _lhs.Get() <= _rhs.Get(); } - - public static ICondition CreateFor(IOperand lhs, IOperand rhs) where T1 : INumber - => new CondLE(lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondLT.cs b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondLT.cs index 7393d9ec5..980ab8515 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondLT.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondLT.cs @@ -3,6 +3,13 @@ using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Conditions { + sealed class CondLTFactory : IConditionFactory + { + private CondLTFactory() { } + + public static ICondition CreateFor(IOperand lhs, IOperand rhs) where T : unmanaged, INumber + => new CondLT(lhs, rhs); + } class CondLT : ICondition where T : unmanaged, INumber { private readonly IOperand _lhs; diff --git a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondNE.cs b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondNE.cs index fdd0a4845..0cbd62a54 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondNE.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Conditions/CondNE.cs @@ -3,6 +3,13 @@ using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Conditions { + sealed class CondNEFactory : IConditionFactory + { + private CondNEFactory() { } + + public static ICondition CreateFor(IOperand lhs, IOperand rhs) where T : unmanaged, INumber + => new CondNE(lhs, rhs); + } class CondNE : ICondition where T : unmanaged, INumber { private readonly IOperand _lhs; diff --git a/src/Ryujinx.HLE/HOS/Tamper/Conditions/ICondition.cs b/src/Ryujinx.HLE/HOS/Tamper/Conditions/ICondition.cs index 130fb5623..f15ceffe1 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Conditions/ICondition.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Conditions/ICondition.cs @@ -1,13 +1,7 @@ -using Ryujinx.HLE.HOS.Tamper.Operations; -using System; -using System.Numerics; - namespace Ryujinx.HLE.HOS.Tamper.Conditions { interface ICondition { bool Evaluate(); - - static virtual ICondition CreateFor(IOperand lhs, IOperand rhs) where T : INumber => throw new NotImplementedException(); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Conditions/IConditionFactory.cs b/src/Ryujinx.HLE/HOS/Tamper/Conditions/IConditionFactory.cs new file mode 100644 index 000000000..af0886307 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Tamper/Conditions/IConditionFactory.cs @@ -0,0 +1,10 @@ +using Ryujinx.HLE.HOS.Tamper.Operations; +using System.Numerics; + +namespace Ryujinx.HLE.HOS.Tamper.Conditions +{ + interface IConditionFactory + { + static abstract ICondition CreateFor(IOperand lhs, IOperand rhs) where T : unmanaged, INumber; + } +} diff --git a/src/Ryujinx.HLE/HOS/Tamper/InstructionHelper.cs b/src/Ryujinx.HLE/HOS/Tamper/InstructionHelper.cs index e50a5bd7f..76409945e 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/InstructionHelper.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/InstructionHelper.cs @@ -15,14 +15,14 @@ namespace Ryujinx.HLE.HOS.Tamper context.CurrentOperations.Add(operation); } - public static void Emit(byte width, CompilationContext context, IOperand destination, IOperand lhs, IOperand rhs) where TOp : IOperation + public static void Emit(byte width, CompilationContext context, IOperand destination, IOperand lhs, IOperand rhs) where TOp : IOperationFactory { Emit(Create(width, destination, lhs, rhs), context); } public static ICondition CreateCondition(Comparison comparison, byte width, IOperand lhs, IOperand rhs) { - ICondition CreateCore() where TOp : ICondition + ICondition CreateCore() where TOp : IConditionFactory { return width switch { @@ -36,17 +36,17 @@ namespace Ryujinx.HLE.HOS.Tamper return comparison switch { - Comparison.Greater => CreateCore>(), - Comparison.GreaterOrEqual => CreateCore>(), - Comparison.Less => CreateCore>(), - Comparison.LessOrEqual => CreateCore>(), - Comparison.Equal => CreateCore>(), - Comparison.NotEqual => CreateCore>(), + Comparison.Greater => CreateCore(), + Comparison.GreaterOrEqual => CreateCore(), + Comparison.Less => CreateCore(), + Comparison.LessOrEqual => CreateCore(), + Comparison.Equal => CreateCore(), + Comparison.NotEqual => CreateCore(), _ => throw new TamperCompilationException($"Invalid comparison {comparison} in Atmosphere cheat"), }; } - public static IOperation Create(byte width, IOperand destination, IOperand lhs, IOperand rhs) where TOp : IOperation + public static IOperation Create(byte width, IOperand destination, IOperand lhs, IOperand rhs) where TOp : IOperationFactory { return width switch { diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/IOperation.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/IOperation.cs index a0af81409..7ffbb4a9a 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/IOperation.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/IOperation.cs @@ -6,8 +6,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations interface IOperation { void Execute(); - - static virtual IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger - => throw new NotImplementedException(); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/IOperationFactory.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/IOperationFactory.cs new file mode 100644 index 000000000..85f7c90c0 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/IOperationFactory.cs @@ -0,0 +1,10 @@ +using System; +using System.Numerics; + +namespace Ryujinx.HLE.HOS.Tamper.Operations +{ + interface IOperationFactory + { + static abstract IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger; + } +} diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpAdd.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpAdd.cs index 9154b20ea..9cbf44b12 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpAdd.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpAdd.cs @@ -2,6 +2,13 @@ using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Operations { + sealed class OpAddFactory : IOperationFactory + { + private OpAddFactory() { } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger + => new OpAdd(destination, lhs, rhs); + } class OpAdd : IOperation where T : unmanaged, INumber { readonly IOperand _destination; @@ -19,8 +26,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations { _destination.Set(_lhs.Get() + _rhs.Get()); } - - public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger - => new OpAdd(destination, lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpAnd.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpAnd.cs index b0a1031a5..5e623702c 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpAnd.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpAnd.cs @@ -2,6 +2,13 @@ using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Operations { + sealed class OpAndFactory : IOperationFactory + { + private OpAndFactory() { } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger + => new OpAnd(destination, lhs, rhs); + } class OpAnd : IOperation where T : unmanaged, IBinaryNumber { readonly IOperand _destination; @@ -19,8 +26,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations { _destination.Set(_lhs.Get() & _rhs.Get()); } - - public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger - => new OpAnd(destination, lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpLsh.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpLsh.cs index cb7ae2237..18156f1ff 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpLsh.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpLsh.cs @@ -2,6 +2,13 @@ using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Operations { + sealed class OpLshFactory : IOperationFactory + { + private OpLshFactory() { } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger + => new OpLsh(destination, lhs, rhs); + } class OpLsh : IOperation where T : unmanaged, IBinaryInteger { readonly IOperand _destination; @@ -19,8 +26,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations { _destination.Set(_lhs.Get() << int.CreateTruncating(_rhs.Get())); } - - public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger - => new OpLsh(destination, lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpMov.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpMov.cs index 54266b422..13c3009a3 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpMov.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpMov.cs @@ -2,6 +2,13 @@ using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Operations { + sealed class OpMovFactory : IOperationFactory + { + private OpMovFactory() { } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger + => new OpMov(destination, lhs); + } class OpMov : IOperation where T : unmanaged, INumber { readonly IOperand _destination; @@ -17,8 +24,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations { _destination.Set(_source.Get()); } - - public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger - => new OpMov(destination, lhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpMul.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpMul.cs index 14c43dd03..f760447b8 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpMul.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpMul.cs @@ -2,6 +2,13 @@ using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Operations { + sealed class OpMulFactory : IOperationFactory + { + private OpMulFactory() { } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger + => new OpMul(destination, lhs, rhs); + } class OpMul : IOperation where T : unmanaged, INumber { readonly IOperand _destination; @@ -19,8 +26,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations { _destination.Set(_lhs.Get() * _rhs.Get()); } - - public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger - => new OpMul(destination, lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpNot.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpNot.cs index 91e0f6321..56f9c3f82 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpNot.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpNot.cs @@ -2,6 +2,13 @@ using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Operations { + sealed class OpNotFactory : IOperationFactory + { + private OpNotFactory() { } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger + => new OpNot(destination, lhs); + } class OpNot : IOperation where T : unmanaged, IBinaryNumber { readonly IOperand _destination; @@ -17,8 +24,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations { _destination.Set(~_source.Get()); } - - public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger - => new OpNot(destination, lhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpOr.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpOr.cs index 704597423..4e47dacd4 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpOr.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpOr.cs @@ -2,6 +2,13 @@ using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Operations { + sealed class OpOrFactory : IOperationFactory + { + private OpOrFactory() { } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger + => new OpOr(destination, lhs, rhs); + } class OpOr : IOperation where T : unmanaged, IBinaryNumber { readonly IOperand _destination; @@ -19,8 +26,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations { _destination.Set(_lhs.Get() | _rhs.Get()); } - - public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger - => new OpOr(destination, lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpRsh.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpRsh.cs index b48c76a5c..d40b29ee8 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpRsh.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpRsh.cs @@ -2,6 +2,13 @@ using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Operations { + sealed class OpRshFactory : IOperationFactory + { + private OpRshFactory() { } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger + => new OpRsh(destination, lhs, rhs); + } class OpRsh : IOperation where T : unmanaged, IBinaryInteger { readonly IOperand _destination; @@ -19,8 +26,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations { _destination.Set(_lhs.Get() >> int.CreateTruncating(_rhs.Get())); } - - public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger - => new OpRsh(destination, lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpSub.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpSub.cs index 1092643cf..9f76b1ffd 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpSub.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpSub.cs @@ -2,6 +2,13 @@ using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Operations { + sealed class OpSubFactory : IOperationFactory + { + private OpSubFactory() { } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger + => new OpSub(destination, lhs, rhs); + } class OpSub : IOperation where T : unmanaged, INumber { readonly IOperand _destination; @@ -19,8 +26,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations { _destination.Set(_lhs.Get() - _rhs.Get()); } - - public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger - => new OpSub(destination, lhs, rhs); } } diff --git a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpXor.cs b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpXor.cs index 8fc241ced..8a820f4a1 100644 --- a/src/Ryujinx.HLE/HOS/Tamper/Operations/OpXor.cs +++ b/src/Ryujinx.HLE/HOS/Tamper/Operations/OpXor.cs @@ -2,6 +2,13 @@ using System.Numerics; namespace Ryujinx.HLE.HOS.Tamper.Operations { + sealed class OpXorFactory : IOperationFactory + { + private OpXorFactory() { } + + public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger + => new OpXor(destination, lhs, rhs); + } class OpXor : IOperation where T : unmanaged, IBinaryNumber { readonly IOperand _destination; @@ -19,8 +26,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations { _destination.Set(_lhs.Get() ^ _rhs.Get()); } - - public static IOperation CreateFor(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger - => new OpXor(destination, lhs, rhs); } } From f39f7247f13bff6c449caff80ead31d86cb455ef Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Wed, 19 Nov 2025 23:08:29 -0600 Subject: [PATCH 09/10] Oops left comment --- src/Ryujinx/Ryujinx.csproj | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Ryujinx/Ryujinx.csproj b/src/Ryujinx/Ryujinx.csproj index b67bb054b..d2e8bac5c 100644 --- a/src/Ryujinx/Ryujinx.csproj +++ b/src/Ryujinx/Ryujinx.csproj @@ -28,13 +28,6 @@ true - - From 255d3b854e28220cbd2315f79787c4356b453a0e Mon Sep 17 00:00:00 2001 From: Aaron Robinson Date: Mon, 24 Nov 2025 22:45:52 -0600 Subject: [PATCH 10/10] Fix things broken by trimming (profile panel, DiscordRPC) --- Directory.Packages.props | 2 +- src/Ryujinx/Ryujinx.csproj | 3 +++ src/Ryujinx/TrimmerRootDescriptor.xml | 3 +++ src/Ryujinx/UI/Controls/NavigationDialogHost.axaml.cs | 3 ++- src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs | 4 ++-- src/Ryujinx/Utilities/ValueFormatUtils.cs | 1 - 6 files changed, 11 insertions(+), 5 deletions(-) create mode 100644 src/Ryujinx/TrimmerRootDescriptor.xml diff --git a/Directory.Packages.props b/Directory.Packages.props index 4a74eba02..d06480674 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -23,7 +23,7 @@ - + diff --git a/src/Ryujinx/Ryujinx.csproj b/src/Ryujinx/Ryujinx.csproj index d2e8bac5c..536f84fe2 100644 --- a/src/Ryujinx/Ryujinx.csproj +++ b/src/Ryujinx/Ryujinx.csproj @@ -163,4 +163,7 @@ + + + diff --git a/src/Ryujinx/TrimmerRootDescriptor.xml b/src/Ryujinx/TrimmerRootDescriptor.xml new file mode 100644 index 000000000..7ba5de5ed --- /dev/null +++ b/src/Ryujinx/TrimmerRootDescriptor.xml @@ -0,0 +1,3 @@ + + + diff --git a/src/Ryujinx/UI/Controls/NavigationDialogHost.axaml.cs b/src/Ryujinx/UI/Controls/NavigationDialogHost.axaml.cs index fb0bd5e82..0107e6536 100644 --- a/src/Ryujinx/UI/Controls/NavigationDialogHost.axaml.cs +++ b/src/Ryujinx/UI/Controls/NavigationDialogHost.axaml.cs @@ -16,6 +16,7 @@ using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS.Services.Account.Acc; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; using UserId = Ryujinx.HLE.HOS.Services.Account.Acc.UserId; @@ -59,7 +60,7 @@ namespace Ryujinx.Ava.UI.Controls LoadProfiles(); } - public void Navigate(Type sourcePageType, object parameter) + public void Navigate([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type sourcePageType, object parameter) => ContentFrame.Navigate(sourcePageType, parameter); public static async Task Show( diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index 651dc901c..d2cccd3a9 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -1350,8 +1350,8 @@ namespace Ryujinx.Ava.UI.ViewModels public void SetGridMode() => Glyph = Glyph.Grid; - public void SetAspectRatio(AspectRatio aspectRatio) => - ConfigurationState.Instance.Graphics.AspectRatio.Value = aspectRatio; + public void SetAspectRatio(object aspectRatio) => + ConfigurationState.Instance.Graphics.AspectRatio.Value = (AspectRatio)aspectRatio; public async Task InstallFirmwareFromFile() { diff --git a/src/Ryujinx/Utilities/ValueFormatUtils.cs b/src/Ryujinx/Utilities/ValueFormatUtils.cs index 39723f511..e3d7e8a4a 100644 --- a/src/Ryujinx/Utilities/ValueFormatUtils.cs +++ b/src/Ryujinx/Utilities/ValueFormatUtils.cs @@ -1,5 +1,4 @@ using Humanizer; -using Humanizer.Localisation; using Ryujinx.Ava.Common.Locale; using System; using System.Globalization;