mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-05-28 07:59:17 +00:00
Remove dynamic usage from Ryujinx.HLE (will come back to make this not generic explode)
This commit is contained in:
@@ -1,7 +1,5 @@
|
|||||||
using Ryujinx.HLE.Exceptions;
|
using Ryujinx.HLE.Exceptions;
|
||||||
using Ryujinx.HLE.HOS.Tamper.Operations;
|
using Ryujinx.HLE.HOS.Tamper.Operations;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
|
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");
|
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 =
|
InstructionHelper.Emit<TOp>(operationWidth, context, destinationRegister, leftHandSideRegister, rhs);
|
||||||
[
|
|
||||||
destinationRegister,
|
|
||||||
leftHandSideRegister
|
|
||||||
];
|
|
||||||
|
|
||||||
if (rhs != null)
|
|
||||||
{
|
|
||||||
operandList.Add(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
InstructionHelper.Emit(operationType, operationWidth, context, operandList.ToArray());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (operation)
|
switch (operation)
|
||||||
{
|
{
|
||||||
case Add:
|
case Add:
|
||||||
Emit(typeof(OpAdd<>), rightHandSideOperand);
|
EmitCore<OpAdd<byte>>(rightHandSideOperand);
|
||||||
break;
|
break;
|
||||||
case Sub:
|
case Sub:
|
||||||
Emit(typeof(OpSub<>), rightHandSideOperand);
|
EmitCore<OpSub<byte>>(rightHandSideOperand);
|
||||||
break;
|
break;
|
||||||
case Mul:
|
case Mul:
|
||||||
Emit(typeof(OpMul<>), rightHandSideOperand);
|
EmitCore<OpMul<byte>>(rightHandSideOperand);
|
||||||
break;
|
break;
|
||||||
case Lsh:
|
case Lsh:
|
||||||
Emit(typeof(OpLsh<>), rightHandSideOperand);
|
EmitCore<OpLsh<byte>>(rightHandSideOperand);
|
||||||
break;
|
break;
|
||||||
case Rsh:
|
case Rsh:
|
||||||
Emit(typeof(OpRsh<>), rightHandSideOperand);
|
EmitCore<OpRsh<byte>>(rightHandSideOperand);
|
||||||
break;
|
break;
|
||||||
case And:
|
case And:
|
||||||
Emit(typeof(OpAnd<>), rightHandSideOperand);
|
EmitCore<OpAnd<byte>>(rightHandSideOperand);
|
||||||
break;
|
break;
|
||||||
case Or:
|
case Or:
|
||||||
Emit(typeof(OpOr<>), rightHandSideOperand);
|
EmitCore<OpOr<byte>>(rightHandSideOperand);
|
||||||
break;
|
break;
|
||||||
case Not:
|
case Not:
|
||||||
Emit(typeof(OpNot<>));
|
EmitCore<OpNot<byte>>();
|
||||||
break;
|
break;
|
||||||
case Xor:
|
case Xor:
|
||||||
Emit(typeof(OpXor<>), rightHandSideOperand);
|
EmitCore<OpXor<byte>>(rightHandSideOperand);
|
||||||
break;
|
break;
|
||||||
case Mov:
|
case Mov:
|
||||||
Emit(typeof(OpMov<>));
|
EmitCore<OpMov<byte>>();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat");
|
throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat");
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Ryujinx.HLE.Exceptions;
|
using Ryujinx.HLE.Exceptions;
|
||||||
using Ryujinx.HLE.HOS.Tamper.Operations;
|
using Ryujinx.HLE.HOS.Tamper.Operations;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
|
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");
|
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);
|
ulong immediate = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, ValueImmediateSize);
|
||||||
Value<ulong> rightHandSideValue = new(immediate);
|
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)
|
switch (operation)
|
||||||
{
|
{
|
||||||
case Add:
|
case Add:
|
||||||
Emit(typeof(OpAdd<>));
|
EmitCore<OpAdd<byte>>();
|
||||||
break;
|
break;
|
||||||
case Sub:
|
case Sub:
|
||||||
Emit(typeof(OpSub<>));
|
EmitCore<OpAdd<byte>>();
|
||||||
break;
|
break;
|
||||||
case Mul:
|
case Mul:
|
||||||
Emit(typeof(OpMul<>));
|
EmitCore<OpMul<byte>>();
|
||||||
break;
|
break;
|
||||||
case Lsh:
|
case Lsh:
|
||||||
Emit(typeof(OpLsh<>));
|
EmitCore<OpLsh<byte>>();
|
||||||
break;
|
break;
|
||||||
case Rsh:
|
case Rsh:
|
||||||
Emit(typeof(OpRsh<>));
|
EmitCore<OpRsh<byte>>();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat");
|
throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat");
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Ryujinx.HLE.Exceptions;
|
using Ryujinx.HLE.Exceptions;
|
||||||
|
using Ryujinx.HLE.HOS.Tamper.Operations;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
|
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");
|
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
|
namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -35,7 +37,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
|
|||||||
ulong valueImmediate = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, valueImmediateSize);
|
ulong valueImmediate = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, valueImmediateSize);
|
||||||
Value<ulong> storeValue = new(valueImmediate);
|
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");
|
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)
|
switch (incrementAddressRegister)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
|
|||||||
throw new TamperCompilationException($"Invalid offset type {offsetType} in Atmosphere cheat");
|
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)
|
switch (incrementAddressRegister)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
using Ryujinx.HLE.HOS.Tamper.Operations;
|
using Ryujinx.HLE.HOS.Tamper.Operations;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
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 _lhs;
|
||||||
private readonly IOperand _rhs;
|
private readonly IOperand _rhs;
|
||||||
@@ -15,7 +16,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
|||||||
|
|
||||||
public bool Evaluate()
|
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 Ryujinx.HLE.HOS.Tamper.Operations;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
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 _lhs;
|
||||||
private readonly IOperand _rhs;
|
private readonly IOperand _rhs;
|
||||||
@@ -15,7 +16,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
|||||||
|
|
||||||
public bool Evaluate()
|
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 Ryujinx.HLE.HOS.Tamper.Operations;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
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 _lhs;
|
||||||
private readonly IOperand _rhs;
|
private readonly IOperand _rhs;
|
||||||
@@ -15,7 +16,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
|||||||
|
|
||||||
public bool Evaluate()
|
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 Ryujinx.HLE.HOS.Tamper.Operations;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
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 _lhs;
|
||||||
private readonly IOperand _rhs;
|
private readonly IOperand _rhs;
|
||||||
@@ -15,7 +16,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
|||||||
|
|
||||||
public bool Evaluate()
|
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 Ryujinx.HLE.HOS.Tamper.Operations;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
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 _lhs;
|
||||||
private readonly IOperand _rhs;
|
private readonly IOperand _rhs;
|
||||||
@@ -15,7 +16,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
|||||||
|
|
||||||
public bool Evaluate()
|
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 Ryujinx.HLE.HOS.Tamper.Operations;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
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 _lhs;
|
||||||
private readonly IOperand _rhs;
|
private readonly IOperand _rhs;
|
||||||
@@ -15,7 +16,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
|||||||
|
|
||||||
public bool Evaluate()
|
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
|
namespace Ryujinx.HLE.HOS.Tamper.Conditions
|
||||||
{
|
{
|
||||||
interface ICondition
|
interface ICondition
|
||||||
{
|
{
|
||||||
bool Evaluate();
|
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);
|
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);
|
Emit(Create<TOp>(width, destination, lhs, rhs), context);
|
||||||
}
|
|
||||||
|
|
||||||
public static void EmitMov(byte width, CompilationContext context, IOperand destination, IOperand source)
|
|
||||||
{
|
|
||||||
Emit(typeof(OpMov<>), width, context, destination, source);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ICondition CreateCondition(Comparison comparison, byte width, IOperand lhs, IOperand rhs)
|
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
|
return comparison switch
|
||||||
{
|
{
|
||||||
Comparison.Greater => Create(typeof(CondGT<>)),
|
Comparison.Greater => CreateCore<CondGT<byte>>(),
|
||||||
Comparison.GreaterOrEqual => Create(typeof(CondGE<>)),
|
Comparison.GreaterOrEqual => CreateCore<CondGE<byte>>(),
|
||||||
Comparison.Less => Create(typeof(CondLT<>)),
|
Comparison.Less => CreateCore<CondLT<byte>>(),
|
||||||
Comparison.LessOrEqual => Create(typeof(CondLE<>)),
|
Comparison.LessOrEqual => CreateCore<CondLE<byte>>(),
|
||||||
Comparison.Equal => Create(typeof(CondEQ<>)),
|
Comparison.Equal => CreateCore<CondEQ<byte>>(),
|
||||||
Comparison.NotEqual => Create(typeof(CondNE<>)),
|
Comparison.NotEqual => CreateCore<CondNE<byte>>(),
|
||||||
_ => throw new TamperCompilationException($"Invalid comparison {comparison} in Atmosphere cheat"),
|
_ => 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)),
|
1 => TOp.CreateFor<byte>(destination, lhs, rhs),
|
||||||
2 => instruction.MakeGenericType(typeof(ushort)),
|
2 => TOp.CreateFor<ushort>(destination, lhs, rhs),
|
||||||
4 => instruction.MakeGenericType(typeof(uint)),
|
4 => TOp.CreateFor<uint>(destination, lhs, rhs),
|
||||||
8 => instruction.MakeGenericType(typeof(ulong)),
|
8 => TOp.CreateFor<ulong>(destination, lhs, rhs),
|
||||||
_ => throw new TamperCompilationException($"Invalid instruction width {width} in Atmosphere cheat"),
|
_ => throw new NotSupportedException(),
|
||||||
};
|
};
|
||||||
return Activator.CreateInstance(realType, operands);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ulong GetImmediate(byte[] instruction, int index, int nybbleCount)
|
public static ulong GetImmediate(byte[] instruction, int index, int nybbleCount)
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
||||||
{
|
{
|
||||||
interface IOperand
|
interface IOperand
|
||||||
{
|
{
|
||||||
public T Get<T>() where T : unmanaged;
|
public T Get<T>() where T : unmanaged, INumber<T>;
|
||||||
public void Set<T>(T value) where T : unmanaged;
|
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
|
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
||||||
{
|
{
|
||||||
interface IOperation
|
interface IOperation
|
||||||
{
|
{
|
||||||
void Execute();
|
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
|
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 _destination;
|
||||||
readonly IOperand _lhs;
|
readonly IOperand _lhs;
|
||||||
@@ -15,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
|
|||||||
|
|
||||||
public void Execute()
|
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
|
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 _destination;
|
||||||
readonly IOperand _lhs;
|
readonly IOperand _lhs;
|
||||||
@@ -15,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
|
|||||||
|
|
||||||
public void Execute()
|
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 Ryujinx.Common.Logging;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
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 int _logId;
|
||||||
readonly IOperand _source;
|
readonly IOperand _source;
|
||||||
@@ -15,7 +16,7 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
|
|||||||
|
|
||||||
public void Execute()
|
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
|
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 _destination;
|
||||||
readonly IOperand _lhs;
|
readonly IOperand _lhs;
|
||||||
@@ -15,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
|
|||||||
|
|
||||||
public void Execute()
|
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
|
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 _destination;
|
||||||
readonly IOperand _source;
|
readonly IOperand _source;
|
||||||
@@ -15,5 +17,8 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
|
|||||||
{
|
{
|
||||||
_destination.Set(_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 OpMov<T1>(destination, lhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Tamper.Operations
|
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 _destination;
|
||||||
readonly IOperand _lhs;
|
readonly IOperand _lhs;
|
||||||
@@ -15,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
|
|||||||
|
|
||||||
public void Execute()
|
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
|
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 _destination;
|
||||||
readonly IOperand _source;
|
readonly IOperand _source;
|
||||||
@@ -13,7 +15,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
|
|||||||
|
|
||||||
public void Execute()
|
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
|
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 _destination;
|
||||||
readonly IOperand _lhs;
|
readonly IOperand _lhs;
|
||||||
@@ -15,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
|
|||||||
|
|
||||||
public void Execute()
|
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
|
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 _destination;
|
||||||
readonly IOperand _lhs;
|
readonly IOperand _lhs;
|
||||||
@@ -15,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
|
|||||||
|
|
||||||
public void Execute()
|
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
|
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 _destination;
|
||||||
readonly IOperand _lhs;
|
readonly IOperand _lhs;
|
||||||
@@ -15,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
|
|||||||
|
|
||||||
public void Execute()
|
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
|
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 _destination;
|
||||||
readonly IOperand _lhs;
|
readonly IOperand _lhs;
|
||||||
@@ -15,7 +17,10 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
|
|||||||
|
|
||||||
public void Execute()
|
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.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Tamper.Operations;
|
using Ryujinx.HLE.HOS.Tamper.Operations;
|
||||||
|
using System.Numerics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Tamper
|
namespace Ryujinx.HLE.HOS.Tamper
|
||||||
@@ -15,12 +16,12 @@ namespace Ryujinx.HLE.HOS.Tamper
|
|||||||
_process = process;
|
_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>());
|
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>();
|
ulong position = _position.Get<ulong>();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.HOS.Tamper.Operations;
|
using Ryujinx.HLE.HOS.Tamper.Operations;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Tamper
|
namespace Ryujinx.HLE.HOS.Tamper
|
||||||
{
|
{
|
||||||
@@ -13,16 +14,16 @@ namespace Ryujinx.HLE.HOS.Tamper
|
|||||||
_alias = alias;
|
_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}");
|
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 Ryujinx.HLE.HOS.Tamper.Operations;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Tamper
|
namespace Ryujinx.HLE.HOS.Tamper
|
||||||
{
|
{
|
||||||
class Value<TP> : IOperand where TP : unmanaged
|
class Value<TP> : IOperand where TP : unmanaged, INumber<TP>
|
||||||
{
|
{
|
||||||
private TP _value;
|
private TP _value;
|
||||||
|
|
||||||
@@ -11,14 +12,14 @@ namespace Ryujinx.HLE.HOS.Tamper
|
|||||||
_value = value;
|
_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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user