mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2026-03-11 20:35:34 +00:00
Remove dynamic usage from Ryujinx.HLE (will come back to make this not generic explode)
This commit is contained in:
parent
4f5eea3417
commit
00021121ea
31 changed files with 198 additions and 106 deletions
|
|
@ -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<TOp>(IOperand rhs = null) where TOp : IOperation
|
||||
{
|
||||
List<IOperand> operandList =
|
||||
[
|
||||
destinationRegister,
|
||||
leftHandSideRegister
|
||||
];
|
||||
|
||||
if (rhs != null)
|
||||
{
|
||||
operandList.Add(rhs);
|
||||
}
|
||||
|
||||
InstructionHelper.Emit(operationType, operationWidth, context, operandList.ToArray());
|
||||
InstructionHelper.Emit<TOp>(operationWidth, context, destinationRegister, leftHandSideRegister, rhs);
|
||||
}
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case Add:
|
||||
Emit(typeof(OpAdd<>), rightHandSideOperand);
|
||||
EmitCore<OpAdd<byte>>(rightHandSideOperand);
|
||||
break;
|
||||
case Sub:
|
||||
Emit(typeof(OpSub<>), rightHandSideOperand);
|
||||
EmitCore<OpSub<byte>>(rightHandSideOperand);
|
||||
break;
|
||||
case Mul:
|
||||
Emit(typeof(OpMul<>), rightHandSideOperand);
|
||||
EmitCore<OpMul<byte>>(rightHandSideOperand);
|
||||
break;
|
||||
case Lsh:
|
||||
Emit(typeof(OpLsh<>), rightHandSideOperand);
|
||||
EmitCore<OpLsh<byte>>(rightHandSideOperand);
|
||||
break;
|
||||
case Rsh:
|
||||
Emit(typeof(OpRsh<>), rightHandSideOperand);
|
||||
EmitCore<OpRsh<byte>>(rightHandSideOperand);
|
||||
break;
|
||||
case And:
|
||||
Emit(typeof(OpAnd<>), rightHandSideOperand);
|
||||
EmitCore<OpAnd<byte>>(rightHandSideOperand);
|
||||
break;
|
||||
case Or:
|
||||
Emit(typeof(OpOr<>), rightHandSideOperand);
|
||||
EmitCore<OpOr<byte>>(rightHandSideOperand);
|
||||
break;
|
||||
case Not:
|
||||
Emit(typeof(OpNot<>));
|
||||
EmitCore<OpNot<byte>>();
|
||||
break;
|
||||
case Xor:
|
||||
Emit(typeof(OpXor<>), rightHandSideOperand);
|
||||
EmitCore<OpXor<byte>>(rightHandSideOperand);
|
||||
break;
|
||||
case Mov:
|
||||
Emit(typeof(OpMov<>));
|
||||
EmitCore<OpMov<byte>>();
|
||||
break;
|
||||
default:
|
||||
throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat");
|
||||
|
|
|
|||
|
|
@ -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<byte>(logId, sourceOperand),
|
||||
2 => new OpLog<ushort>(logId, sourceOperand),
|
||||
4 => new OpLog<uint>(logId, sourceOperand),
|
||||
8 => new OpLog<ulong>(logId, sourceOperand),
|
||||
_ => throw new NotSupportedException(),
|
||||
};
|
||||
InstructionHelper.Emit(op, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,27 +37,27 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
|
|||
ulong immediate = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, ValueImmediateSize);
|
||||
Value<ulong> rightHandSideValue = new(immediate);
|
||||
|
||||
void Emit(Type operationType)
|
||||
void EmitCore<TOp>() where TOp : IOperation
|
||||
{
|
||||
InstructionHelper.Emit(operationType, operationWidth, context, register, register, rightHandSideValue);
|
||||
InstructionHelper.Emit<TOp>(operationWidth, context, register, register, rightHandSideValue);
|
||||
}
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case Add:
|
||||
Emit(typeof(OpAdd<>));
|
||||
EmitCore<OpAdd<byte>>();
|
||||
break;
|
||||
case Sub:
|
||||
Emit(typeof(OpSub<>));
|
||||
EmitCore<OpAdd<byte>>();
|
||||
break;
|
||||
case Mul:
|
||||
Emit(typeof(OpMul<>));
|
||||
EmitCore<OpMul<byte>>();
|
||||
break;
|
||||
case Lsh:
|
||||
Emit(typeof(OpLsh<>));
|
||||
EmitCore<OpLsh<byte>>();
|
||||
break;
|
||||
case Rsh:
|
||||
Emit(typeof(OpRsh<>));
|
||||
EmitCore<OpRsh<byte>>();
|
||||
break;
|
||||
default:
|
||||
throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat");
|
||||
|
|
|
|||
|
|
@ -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<OpMov<byte>>(operationWidth, context, destinationRegister, sourceMemory, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
using Ryujinx.HLE.HOS.Tamper.Operations;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
|
||||
{
|
||||
/// <summary>
|
||||
|
|
@ -35,7 +37,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
|
|||
ulong valueImmediate = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, valueImmediateSize);
|
||||
Value<ulong> storeValue = new(valueImmediate);
|
||||
|
||||
InstructionHelper.EmitMov(operationWidth, context, dstMem, storeValue);
|
||||
InstructionHelper.Emit<OpMov<byte>>(operationWidth, context, dstMem, storeValue, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<OpMov<byte>>(operationWidth, context, destinationMemory, storeValue, null);
|
||||
|
||||
switch (incrementAddressRegister)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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<OpMov<byte>>(operationWidth, context, destinationMemory, sourceRegister, null);
|
||||
|
||||
switch (incrementAddressRegister)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
using Ryujinx.HLE.HOS.Tamper.Operations;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
||||
{
|
||||
class CondEQ<T> : ICondition where T : unmanaged
|
||||
class CondEQ<T> : ICondition where T : unmanaged, INumber<T>
|
||||
{
|
||||
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<T>() == (dynamic)_rhs.Get<T>();
|
||||
return _lhs.Get<T>() == _rhs.Get<T>();
|
||||
}
|
||||
|
||||
public static ICondition CreateFor<T1>(IOperand lhs, IOperand rhs) where T1 : INumber<T1>
|
||||
=> new CondEQ<T>(lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
using Ryujinx.HLE.HOS.Tamper.Operations;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
||||
{
|
||||
class CondGE<T> : ICondition where T : unmanaged
|
||||
class CondGE<T> : ICondition where T : unmanaged, INumber<T>
|
||||
{
|
||||
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<T>() >= (dynamic)_rhs.Get<T>();
|
||||
return _lhs.Get<T>() >= _rhs.Get<T>();
|
||||
}
|
||||
|
||||
public static ICondition CreateFor<T1>(IOperand lhs, IOperand rhs) where T1 : INumber<T1>
|
||||
=> new CondGE<T>(lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
using Ryujinx.HLE.HOS.Tamper.Operations;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
||||
{
|
||||
class CondGT<T> : ICondition where T : unmanaged
|
||||
class CondGT<T> : ICondition where T : unmanaged, INumber<T>
|
||||
{
|
||||
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<T>() > (dynamic)_rhs.Get<T>();
|
||||
return _lhs.Get<T>() > _rhs.Get<T>();
|
||||
}
|
||||
|
||||
public static ICondition CreateFor<T1>(IOperand lhs, IOperand rhs) where T1 : INumber<T1>
|
||||
=> new CondGT<T>(lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
using Ryujinx.HLE.HOS.Tamper.Operations;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
||||
{
|
||||
class CondLE<T> : ICondition where T : unmanaged
|
||||
class CondLE<T> : ICondition where T : unmanaged, INumber<T>
|
||||
{
|
||||
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<T>() <= (dynamic)_rhs.Get<T>();
|
||||
return _lhs.Get<T>() <= _rhs.Get<T>();
|
||||
}
|
||||
|
||||
public static ICondition CreateFor<T1>(IOperand lhs, IOperand rhs) where T1 : INumber<T1>
|
||||
=> new CondLE<T>(lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
using Ryujinx.HLE.HOS.Tamper.Operations;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
||||
{
|
||||
class CondLT<T> : ICondition where T : unmanaged
|
||||
class CondLT<T> : ICondition where T : unmanaged, INumber<T>
|
||||
{
|
||||
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<T>() < (dynamic)_rhs.Get<T>();
|
||||
return _lhs.Get<T>() < _rhs.Get<T>();
|
||||
}
|
||||
|
||||
public static ICondition CreateFor<T1>(IOperand lhs, IOperand rhs) where T1 : INumber<T1>
|
||||
=> new CondLT<T>(lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
using Ryujinx.HLE.HOS.Tamper.Operations;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
||||
{
|
||||
class CondNE<T> : ICondition where T : unmanaged
|
||||
class CondNE<T> : ICondition where T : unmanaged, INumber<T>
|
||||
{
|
||||
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<T>() != (dynamic)_rhs.Get<T>();
|
||||
return _lhs.Get<T>() != _rhs.Get<T>();
|
||||
}
|
||||
|
||||
public static ICondition CreateFor<T1>(IOperand lhs, IOperand rhs) where T1 : INumber<T1>
|
||||
=> new CondNE<T>(lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<T>(IOperand lhs, IOperand rhs) where T : INumber<T> => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<TOp>(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<TOp>(width, destination, lhs, rhs), context);
|
||||
}
|
||||
|
||||
public static ICondition CreateCondition(Comparison comparison, byte width, IOperand lhs, IOperand rhs)
|
||||
{
|
||||
ICondition Create(Type conditionType)
|
||||
ICondition CreateCore<TOp>() where TOp : ICondition
|
||||
{
|
||||
return (ICondition)InstructionHelper.Create(conditionType, width, lhs, rhs);
|
||||
return width switch
|
||||
{
|
||||
1 => TOp.CreateFor<byte>(lhs, rhs),
|
||||
2 => TOp.CreateFor<ushort>(lhs, rhs),
|
||||
4 => TOp.CreateFor<uint>(lhs, rhs),
|
||||
8 => TOp.CreateFor<ulong>(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<CondGT<byte>>(),
|
||||
Comparison.GreaterOrEqual => CreateCore<CondGE<byte>>(),
|
||||
Comparison.Less => CreateCore<CondLT<byte>>(),
|
||||
Comparison.LessOrEqual => CreateCore<CondLE<byte>>(),
|
||||
Comparison.Equal => CreateCore<CondEQ<byte>>(),
|
||||
Comparison.NotEqual => CreateCore<CondNE<byte>>(),
|
||||
_ => throw new TamperCompilationException($"Invalid comparison {comparison} in Atmosphere cheat"),
|
||||
};
|
||||
}
|
||||
|
||||
public static Object Create(Type instruction, byte width, params Object[] operands)
|
||||
public static IOperation Create<TOp>(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<byte>(destination, lhs, rhs),
|
||||
2 => TOp.CreateFor<ushort>(destination, lhs, rhs),
|
||||
4 => TOp.CreateFor<uint>(destination, lhs, rhs),
|
||||
8 => TOp.CreateFor<ulong>(destination, lhs, rhs),
|
||||
_ => throw new NotSupportedException(),
|
||||
};
|
||||
return Activator.CreateInstance(realType, operands);
|
||||
}
|
||||
|
||||
public static ulong GetImmediate(byte[] instruction, int index, int nybbleCount)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
||||
{
|
||||
interface IOperand
|
||||
{
|
||||
public T Get<T>() where T : unmanaged;
|
||||
public void Set<T>(T value) where T : unmanaged;
|
||||
public T Get<T>() where T : unmanaged, INumber<T>;
|
||||
public void Set<T>(T value) where T : unmanaged, INumber<T>;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
using System;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
||||
{
|
||||
interface IOperation
|
||||
{
|
||||
void Execute();
|
||||
|
||||
static virtual IOperation CreateFor<T>(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger<T>
|
||||
=> throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
||||
{
|
||||
class OpAdd<T> : IOperation where T : unmanaged
|
||||
class OpAdd<T> : IOperation where T : unmanaged, INumber<T>
|
||||
{
|
||||
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<T>() + (dynamic)_rhs.Get<T>()));
|
||||
_destination.Set(_lhs.Get<T>() + _rhs.Get<T>());
|
||||
}
|
||||
|
||||
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
|
||||
=> new OpAdd<T1>(destination, lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
||||
{
|
||||
class OpAnd<T> : IOperation where T : unmanaged
|
||||
class OpAnd<T> : IOperation where T : unmanaged, IBinaryNumber<T>
|
||||
{
|
||||
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<T>() & (dynamic)_rhs.Get<T>()));
|
||||
_destination.Set(_lhs.Get<T>() & _rhs.Get<T>());
|
||||
}
|
||||
|
||||
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
|
||||
=> new OpAnd<T1>(destination, lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
using Ryujinx.Common.Logging;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
||||
{
|
||||
class OpLog<T> : IOperation where T : unmanaged
|
||||
class OpLog<T> : IOperation where T : unmanaged, INumber<T>
|
||||
{
|
||||
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<T>():X}");
|
||||
Logger.Debug?.Print(LogClass.TamperMachine, $"Tamper debug log id={_logId} value={_source.Get<T>():X}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
||||
{
|
||||
class OpLsh<T> : IOperation where T : unmanaged
|
||||
class OpLsh<T> : IOperation where T : unmanaged, IBinaryInteger<T>
|
||||
{
|
||||
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<T>() << (dynamic)_rhs.Get<T>()));
|
||||
_destination.Set(_lhs.Get<T>() << int.CreateTruncating(_rhs.Get<T>()));
|
||||
}
|
||||
|
||||
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
|
||||
=> new OpLsh<T1>(destination, lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
||||
{
|
||||
class OpMov<T> : IOperation where T : unmanaged
|
||||
class OpMov<T> : IOperation where T : unmanaged, INumber<T>
|
||||
{
|
||||
readonly IOperand _destination;
|
||||
readonly IOperand _source;
|
||||
|
|
@ -15,5 +17,8 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
|
|||
{
|
||||
_destination.Set(_source.Get<T>());
|
||||
}
|
||||
|
||||
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
|
||||
=> new OpMov<T1>(destination, lhs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
||||
{
|
||||
class OpMul<T> : IOperation where T : unmanaged
|
||||
class OpMul<T> : IOperation where T : unmanaged, INumber<T>
|
||||
{
|
||||
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<T>() * (dynamic)_rhs.Get<T>()));
|
||||
_destination.Set(_lhs.Get<T>() * _rhs.Get<T>());
|
||||
}
|
||||
|
||||
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
|
||||
=> new OpMul<T1>(destination, lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
||||
{
|
||||
class OpNot<T> : IOperation where T : unmanaged
|
||||
class OpNot<T> : IOperation where T : unmanaged, IBinaryNumber<T>
|
||||
{
|
||||
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<T>()));
|
||||
_destination.Set(~_source.Get<T>());
|
||||
}
|
||||
|
||||
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
|
||||
=> new OpNot<T1>(destination, lhs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
||||
{
|
||||
class OpOr<T> : IOperation where T : unmanaged
|
||||
class OpOr<T> : IOperation where T : unmanaged, IBinaryNumber<T>
|
||||
{
|
||||
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<T>() | (dynamic)_rhs.Get<T>()));
|
||||
_destination.Set(_lhs.Get<T>() | _rhs.Get<T>());
|
||||
}
|
||||
|
||||
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
|
||||
=> new OpOr<T1>(destination, lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
||||
{
|
||||
class OpRsh<T> : IOperation where T : unmanaged
|
||||
class OpRsh<T> : IOperation where T : unmanaged, IBinaryInteger<T>
|
||||
{
|
||||
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<T>() >> (dynamic)_rhs.Get<T>()));
|
||||
_destination.Set(_lhs.Get<T>() >> int.CreateTruncating(_rhs.Get<T>()));
|
||||
}
|
||||
|
||||
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
|
||||
=> new OpRsh<T1>(destination, lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
||||
{
|
||||
class OpSub<T> : IOperation where T : unmanaged
|
||||
class OpSub<T> : IOperation where T : unmanaged, INumber<T>
|
||||
{
|
||||
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<T>() - (dynamic)_rhs.Get<T>()));
|
||||
_destination.Set(_lhs.Get<T>() - _rhs.Get<T>());
|
||||
}
|
||||
|
||||
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
|
||||
=> new OpSub<T1>(destination, lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
||||
{
|
||||
class OpXor<T> : IOperation where T : unmanaged
|
||||
class OpXor<T> : IOperation where T : unmanaged, IBinaryNumber<T>
|
||||
{
|
||||
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<T>() ^ (dynamic)_rhs.Get<T>()));
|
||||
_destination.Set(_lhs.Get<T>() ^ _rhs.Get<T>());
|
||||
}
|
||||
|
||||
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
|
||||
=> new OpXor<T1>(destination, lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<T>() where T : unmanaged
|
||||
public T Get<T>() where T : unmanaged, INumber<T>
|
||||
{
|
||||
return _process.ReadMemory<T>(_position.Get<ulong>());
|
||||
}
|
||||
|
||||
public void Set<T>(T value) where T : unmanaged
|
||||
public void Set<T>(T value) where T : unmanaged, INumber<T>
|
||||
{
|
||||
ulong position = _position.Get<ulong>();
|
||||
|
||||
|
|
|
|||
|
|
@ -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<T>() where T : unmanaged
|
||||
public T Get<T>() where T : unmanaged, INumber<T>
|
||||
{
|
||||
return (T)(dynamic)_register;
|
||||
return T.CreateTruncating(_register);
|
||||
}
|
||||
|
||||
public void Set<T>(T value) where T : unmanaged
|
||||
public void Set<T>(T value) where T : unmanaged, INumber<T>
|
||||
{
|
||||
Logger.Debug?.Print(LogClass.TamperMachine, $"{_alias}: {value}");
|
||||
|
||||
_register = (ulong)(dynamic)value;
|
||||
_register = ulong.CreateTruncating(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
using Ryujinx.HLE.HOS.Tamper.Operations;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Tamper
|
||||
{
|
||||
class Value<TP> : IOperand where TP : unmanaged
|
||||
class Value<TP> : IOperand where TP : unmanaged, INumber<TP>
|
||||
{
|
||||
private TP _value;
|
||||
|
||||
|
|
@ -11,14 +12,14 @@ namespace Ryujinx.HLE.HOS.Tamper
|
|||
_value = value;
|
||||
}
|
||||
|
||||
public T Get<T>() where T : unmanaged
|
||||
public T Get<T>() where T : unmanaged, INumber<T>
|
||||
{
|
||||
return (T)(dynamic)_value;
|
||||
return T.CreateTruncating(_value);
|
||||
}
|
||||
|
||||
public void Set<T>(T value) where T : unmanaged
|
||||
public void Set<T>(T value) where T : unmanaged, INumber<T>
|
||||
{
|
||||
_value = (TP)(dynamic)value;
|
||||
_value = TP.CreateTruncating(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue