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); } } }