private int ProcessMethod(MethodDef md) { List <MathInfo> Patched = new List <MathInfo>(); for (int i = 0; i < md.Body.Instructions.Count; i++) { Instruction inst = md.Body.Instructions[i]; if (inst.OpCode == OpCodes.Call && inst.Operand is MemberRef) { MemberRef mRef = inst.Operand as MemberRef; if (mRef.DeclaringType.FullName != "System.Math") { continue; } if (IgnoredMethods.Any(x => mRef.Name == x)) { Logger.Log(this, string.Format("Skipping {0} since it is ignored", mRef.Name)); continue; } // Find insts to remove // Find args MathInfo mInf = new MathInfo(); mInf.Method = mRef.Name; mInf.CallingInst = inst; mInf.ParentMethod = md; List <Instruction> paramVals = FindParamValues(i, md, mRef.MethodSig.Params.Count); paramVals.Reverse(); if (paramVals.Count == 0) { // Do something continue; } mInf.Param1 = (double)paramVals[0].Operand; if (paramVals.Count > 1) { mInf.Param2 = (double)paramVals[1].Operand; } if (paramVals.Count < mRef.MethodSig.Params.Count) { } if (paramVals.Contains(inst)) { paramVals.Remove(inst); } mInf.Remove.AddRange(paramVals); Logger.Log(this, string.Format("Solving {0}({1}{2})", mInf.Method, mInf.Param1, !double.IsNaN(mInf.Param2) ? ", " + mInf.Param2.ToString() : "")); // I have to do this immediately after so I can solve for the next call if they are packed together. if (Solve(mInf, md)) { Logger.Log(this, string.Format("Solved {0}({1}{2})", mInf.Method, mInf.Param1, !double.IsNaN(mInf.Param2) ? ", " + mInf.Param2.ToString() : "")); Patched.Add(mInf); } else { Logger.Log(this, string.Format("Failed to solve {0}({1}{2})", mInf.Method, mInf.Param1, !double.IsNaN(mInf.Param2) ? ", " + mInf.Param2.ToString() : "")); } } } return(Patched.Count); }
private bool Solve(MathInfo inf, MethodDef md) { if (double.IsNaN(inf.Param1) && double.IsNaN(inf.Param2)) { return(false); } double mResult = double.NaN; bool usedTwo = false; try { if (!double.IsNaN(inf.Param2) && !double.IsNaN(inf.Param1)) { if (inf.Method == "Pow") { mResult = Pow(inf.Param1, inf.Param2); } else { mResult = GetMathResult(inf.Param1, inf.Param2, inf.Method); } usedTwo = true; } else if (!double.IsNaN(inf.Param1) && double.IsNaN(inf.Param2)) { mResult = GetMathResult(inf.Param1, inf.Method); } } catch (Exception) { } if (double.IsNaN(mResult) || double.IsInfinity(mResult)) { return(false); } int cIndex = md.Body.Instructions.IndexOf(inf.CallingInst); if (cIndex == -1) { return(false); } if (md.Body.Instructions[cIndex].OpCode != inf.CallingInst.OpCode) { Logger.Log(this, string.Format("Original Instruction was not {0} but {1}", inf.CallingInst.OpCode, md.Body.Instructions[cIndex].OpCode)); return(false); } double rounded = Math.Round(mResult, DecimalPlaces); md.Body.Instructions[cIndex].OpCode = GetNumberType(inf.Converter); //OpCodes.Ldc_R8; md.Body.Instructions[cIndex].Operand = Round ? rounded : mResult; md.Body.UpdateInstructionOffsets(); foreach (Instruction rem in inf.Remove) { int index = md.Body.Instructions.IndexOf(rem); if (index == -1) { continue; } md.Body.Instructions[index].OpCode = OpCodes.Nop; md.Body.Instructions[index].Operand = null; md.Body.UpdateInstructionOffsets(); } return(true); }