AtmosphereCompiler.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. using Ryujinx.Common.Logging;
  2. using Ryujinx.HLE.Exceptions;
  3. using Ryujinx.HLE.HOS.Tamper.CodeEmitters;
  4. using Ryujinx.HLE.HOS.Tamper.Operations;
  5. using System;
  6. using System.Collections.Generic;
  7. namespace Ryujinx.HLE.HOS.Tamper
  8. {
  9. class AtmosphereCompiler
  10. {
  11. public ITamperProgram Compile(IEnumerable<string> rawInstructions, ulong exeAddress, ulong heapAddress, ITamperedProcess process)
  12. {
  13. Logger.Debug?.Print(LogClass.TamperMachine, $"Executable address: {exeAddress:X16}");
  14. Logger.Debug?.Print(LogClass.TamperMachine, $"Heap address: {heapAddress:X16}");
  15. try
  16. {
  17. return CompileImpl(rawInstructions, exeAddress, heapAddress, process);
  18. }
  19. catch(TamperCompilationException exception)
  20. {
  21. // Just print the message without the stack trace.
  22. Logger.Error?.Print(LogClass.TamperMachine, exception.Message);
  23. }
  24. catch (Exception exception)
  25. {
  26. Logger.Error?.Print(LogClass.TamperMachine, exception.ToString());
  27. }
  28. Logger.Error?.Print(LogClass.TamperMachine, "There was a problem while compiling the Atmosphere cheat");
  29. return null;
  30. }
  31. private ITamperProgram CompileImpl(IEnumerable<string> rawInstructions, ulong exeAddress, ulong heapAddress, ITamperedProcess process)
  32. {
  33. CompilationContext context = new CompilationContext(exeAddress, heapAddress, process);
  34. context.BlockStack.Push(new OperationBlock(null));
  35. // Parse the instructions.
  36. foreach (string rawInstruction in rawInstructions)
  37. {
  38. Logger.Debug?.Print(LogClass.TamperMachine, $"Compiling instruction {rawInstruction}");
  39. byte[] instruction = InstructionHelper.ParseRawInstruction(rawInstruction);
  40. CodeType codeType = InstructionHelper.GetCodeType(instruction);
  41. switch (codeType)
  42. {
  43. case CodeType.StoreConstantToAddress:
  44. StoreConstantToAddress.Emit(instruction, context);
  45. break;
  46. case CodeType.BeginMemoryConditionalBlock:
  47. BeginConditionalBlock.Emit(instruction, context);
  48. break;
  49. case CodeType.EndConditionalBlock:
  50. EndConditionalBlock.Emit(instruction, context);
  51. break;
  52. case CodeType.StartEndLoop:
  53. StartEndLoop.Emit(instruction, context);
  54. break;
  55. case CodeType.LoadRegisterWithContant:
  56. LoadRegisterWithConstant.Emit(instruction, context);
  57. break;
  58. case CodeType.LoadRegisterWithMemory:
  59. LoadRegisterWithMemory.Emit(instruction, context);
  60. break;
  61. case CodeType.StoreConstantToMemory:
  62. StoreConstantToMemory.Emit(instruction, context);
  63. break;
  64. case CodeType.LegacyArithmetic:
  65. LegacyArithmetic.Emit(instruction, context);
  66. break;
  67. case CodeType.BeginKeypressConditionalBlock:
  68. BeginConditionalBlock.Emit(instruction, context);
  69. break;
  70. case CodeType.Arithmetic:
  71. Arithmetic.Emit(instruction, context);
  72. break;
  73. case CodeType.StoreRegisterToMemory:
  74. StoreRegisterToMemory.Emit(instruction, context);
  75. break;
  76. case CodeType.BeginRegisterConditionalBlock:
  77. BeginConditionalBlock.Emit(instruction, context);
  78. break;
  79. case CodeType.SaveOrRestoreRegister:
  80. SaveOrRestoreRegister.Emit(instruction, context);
  81. break;
  82. case CodeType.SaveOrRestoreRegisterWithMask:
  83. SaveOrRestoreRegisterWithMask.Emit(instruction, context);
  84. break;
  85. case CodeType.ReadOrWriteStaticRegister:
  86. ReadOrWriteStaticRegister.Emit(instruction, context);
  87. break;
  88. case CodeType.PauseProcess:
  89. PauseProcess.Emit(instruction, context);
  90. break;
  91. case CodeType.ResumeProcess:
  92. ResumeProcess.Emit(instruction, context);
  93. break;
  94. case CodeType.DebugLog:
  95. DebugLog.Emit(instruction, context);
  96. break;
  97. default:
  98. throw new TamperCompilationException($"Code type {codeType} not implemented in Atmosphere cheat");
  99. }
  100. }
  101. // Initialize only the registers used.
  102. Value<ulong> zero = new Value<ulong>(0UL);
  103. int position = 0;
  104. foreach (Register register in context.Registers.Values)
  105. {
  106. context.CurrentOperations.Insert(position, new OpMov<ulong>(register, zero));
  107. position++;
  108. }
  109. if (context.BlockStack.Count != 1)
  110. {
  111. throw new TamperCompilationException($"Reached end of compilation with unmatched conditional(s) or loop(s)");
  112. }
  113. return new AtmosphereProgram(process, context.PressedKeys, new Block(context.CurrentOperations));
  114. }
  115. }
  116. }