diff options
author | Caian Benedicto <caianbene@gmail.com> | 2021-08-04 17:05:17 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-04 22:05:17 +0200 |
commit | ff8849671af5ac14fc9cc9d37da30f53d3f13d89 (patch) | |
tree | 636e4e249084b20b871c158fdb8ff4f2b03f36e0 /Ryujinx.HLE/HOS/Tamper/CodeEmitters/EndConditionalBlock.cs | |
parent | a27986c31167d8ce60efcee7e901da241f63ed08 (diff) |
Update TamperMachine and disable write-to-code prevention (#2506)
* Enable write to memory and improve logging
* Update tamper machine opcodes and improve reporting
* Add Else support
* Add missing private statement
Diffstat (limited to 'Ryujinx.HLE/HOS/Tamper/CodeEmitters/EndConditionalBlock.cs')
-rw-r--r-- | Ryujinx.HLE/HOS/Tamper/CodeEmitters/EndConditionalBlock.cs | 55 |
1 files changed, 48 insertions, 7 deletions
diff --git a/Ryujinx.HLE/HOS/Tamper/CodeEmitters/EndConditionalBlock.cs b/Ryujinx.HLE/HOS/Tamper/CodeEmitters/EndConditionalBlock.cs index 4a01992c..a25dddde 100644 --- a/Ryujinx.HLE/HOS/Tamper/CodeEmitters/EndConditionalBlock.cs +++ b/Ryujinx.HLE/HOS/Tamper/CodeEmitters/EndConditionalBlock.cs @@ -10,32 +10,73 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters /// </summary> class EndConditionalBlock { + const int TerminationTypeIndex = 1; + + private const byte End = 0; // True end of the conditional. + private const byte Else = 1; // End of the 'then' block and beginning of 'else' block. + public static void Emit(byte[] instruction, CompilationContext context) { - // 20000000 + Emit(instruction, context, null); + } + + private static void Emit(byte[] instruction, CompilationContext context, IEnumerable<IOperation> operationsElse) + { + // 2X000000 + // X: End type (0 = End, 1 = Else). + + byte terminationType = instruction[TerminationTypeIndex]; + + switch (terminationType) + { + case End: + break; + case Else: + // Start a new operation block with the 'else' instruction to signal that there is the 'then' block just above it. + context.BlockStack.Push(new OperationBlock(instruction)); + return; + default: + throw new TamperCompilationException($"Unknown conditional termination type {terminationType}"); + } // Use the conditional begin instruction stored in the stack. - instruction = context.CurrentBlock.BaseInstruction; - CodeType codeType = InstructionHelper.GetCodeType(instruction); + var upperInstruction = context.CurrentBlock.BaseInstruction; + CodeType codeType = InstructionHelper.GetCodeType(upperInstruction); // Pop the current block of operations from the stack so control instructions // for the conditional can be emitted in the upper block. IEnumerable<IOperation> operations = context.CurrentOperations; context.BlockStack.Pop(); + // If the else operations are already set, then the upper block must not be another end. + if (operationsElse != null && codeType == CodeType.EndConditionalBlock) + { + throw new TamperCompilationException($"Expected an upper 'if' conditional instead of 'end conditional'"); + } + ICondition condition; switch (codeType) { case CodeType.BeginMemoryConditionalBlock: - condition = MemoryConditional.Emit(instruction, context); + condition = MemoryConditional.Emit(upperInstruction, context); break; case CodeType.BeginKeypressConditionalBlock: - condition = KeyPressConditional.Emit(instruction, context); + condition = KeyPressConditional.Emit(upperInstruction, context); break; case CodeType.BeginRegisterConditionalBlock: - condition = RegisterConditional.Emit(instruction, context); + condition = RegisterConditional.Emit(upperInstruction, context); break; + case CodeType.EndConditionalBlock: + terminationType = upperInstruction[TerminationTypeIndex]; + // If there is an end instruction above then it must be an else. + if (terminationType != Else) + { + throw new TamperCompilationException($"Expected an upper 'else' conditional instead of {terminationType}"); + } + // Re-run the Emit with the else operations set. + Emit(instruction, context, operations); + return; default: throw new TamperCompilationException($"Conditional end does not match code type {codeType} in Atmosphere cheat"); } @@ -43,7 +84,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters // Create a conditional block with the current operations and nest it in the upper // block of the stack. - IfBlock block = new IfBlock(condition, operations); + IfBlock block = new IfBlock(condition, operations, operationsElse); context.CurrentOperations.Add(block); } } |