/// <summary>
        /// Primitive patching. Inserts a jump to 'target' at 'site'. Works even if both methods'
        /// callers have already been compiled.
        /// </summary>
        /// <param name="site"></param>
        /// <param name="target"></param>
        private static RedirectCallsState PatchJumpTo(IntPtr site, IntPtr target)
        {
            var state = new RedirectCallsState();

            // R11 is volatile.
            unsafe
            {
                var sitePtr = (byte*) site.ToPointer();
                state.a = *sitePtr;
                state.b = *(sitePtr + 1);
                state.c = *(sitePtr + 10);
                state.d = *(sitePtr + 11);
                state.e = *(sitePtr + 12);
                state.f = *(ulong*) (sitePtr + 2);

                *sitePtr = 0x49; // mov r11, target
                *(sitePtr + 1) = 0xBB;
                *(ulong*) (sitePtr + 2) = (ulong) target.ToInt64();
                *(sitePtr + 10) = 0x41; // jmp r11
                *(sitePtr + 11) = 0xFF;
                *(sitePtr + 12) = 0xE3;
            }

            return state;
        }
        public static void Deploy()
        {
            Debug.Log("Detouring Input Methods");

            if (_isPressedOriginal == null)
            {
                throw new NullReferenceException("Original IsPressed method not found");
            }

            if (_isKeyUpOriginal == null)
            {
                throw new NullReferenceException("Original IsKeyUp method not found");
            }

            if (_isPressedReplacement == null)
            {
                throw new NullReferenceException("New IsPressed method not found");
            }

            if (_isKeyUpReplacement == null)
            {
                throw new NullReferenceException("New IsKeyUp method not found");
            }

            _revertState1 = RedirectionHelper.RedirectCalls(_isPressedOriginal, _isPressedReplacement);
            _revertState2 = RedirectionHelper.RedirectCalls(_isKeyUpOriginal, _isKeyUpReplacement);
        }
        public static void Deploy()
        {
            if (_isDeployed)
                return;

            _snapDirectionRevertState = RedirectionHelper.RedirectCalls(SnapDirectionOriginalMethodInfo, SnapDirectionOverrideMethodInfo);
            _snapRevertState = RedirectionHelper.RedirectCalls(SnapOriginalMethodInfo, SnapOverrideMethodInfo);

            _isDeployed = true;
        }
        public static void Deploy()
        {
            if (_originalGetLengthSnapMethodInfo == null) {
                throw new NullReferenceException("Original GetLengthSnap method not found");
            }

            if (_newGetLengthSnapMethodInfo == null) {
                throw new NullReferenceException("New GetLengthSnap method not found");
            }

            _revertState = RedirectionHelper.RedirectCalls(_originalGetLengthSnapMethodInfo,
                _newGetLengthSnapMethodInfo);
        }
 private static void RevertJumpTo(IntPtr site, RedirectCallsState state)
 {
     unsafe
     {
         var sitePtr = (byte*) site.ToPointer();
         *sitePtr = state.a; // mov r11, target
         *(sitePtr + 1) = state.b;
         *(ulong*) (sitePtr + 2) = state.f;
         *(sitePtr + 10) = state.c; // jmp r11
         *(sitePtr + 11) = state.d;
         *(sitePtr + 12) = state.e;
     }
 }
 public static void RevertRedirect(MethodInfo from, RedirectCallsState state)
 {
     var fptr1 = from.MethodHandle.GetFunctionPointer();
     RevertJumpTo(fptr1, state);
 }