public Debugger(IDebugClient5Fixed client)
        {
            Client     = client;
            Control    = (IDebugControl6)Client;
            DataSpaces = (IDebugDataSpaces4)Client;
            Registers  = (IDebugRegisters2Fixed)Client;

            Client.SetOutputCallbacksWide(this);
            Client.SetEventCallbacksWide(this);
        }
        public static void Run(Process clProcess)
        {
            ProcessModuleCollection clProcessModules = clProcess.Modules;



            /////////////////////////////////
            Guid guid = typeof(IDebugClient).GUID;

            // create debug client object
            //object obj;
            //CheckHr(Native.NativeMethods.DbgEng.DebugCreate(ref guid, out obj));
            IntPtr pObj = IntPtr.Zero;

            CheckHr(Native.NativeMethods.DbgEng.DebugCreate(ref guid, ref pObj));
            IDebugClient5Fixed    client     = (IDebugClient5Fixed)Marshal.GetTypedObjectForIUnknown(pObj, typeof(IDebugClient5Fixed));
            IDebugDataSpaces4     dataSpaces = client as IDebugDataSpaces4;
            IDebugRegisters2Fixed registers  = client as IDebugRegisters2Fixed;

            //IDebugClient5Fixed client = obj as IDebugClient5Fixed;
            IDebugControl6 control = client as IDebugControl6;
            var            events  = new EventCallbacks(control);

            client.SetEventCallbacksWide(events);
            client.SetOutputCallbacksWide(new OutputCallbacks());
            Console.CancelKeyPress += (s, e) => {
                e.Cancel = true;

                //control.SetInterrupt(DEBUG_INTERRUPT.ACTIVE);
            };
            CheckHr(client.AttachProcess(0, (uint)clProcess.Id, DEBUG_ATTACH.DEFAULT));

            ///////////
            ProcessModule progModule = null;

            foreach (ProcessModule module in clProcessModules)
            {
                if (module.ModuleName == "prog.dll")
                {
                    progModule = module;
                    break;
                }
            }

            Console.WriteLine(
                $"Module: {progModule.ModuleName}\r\n" +
                $"  BaseAddress: {progModule.BaseAddress.FormatAsHex()}\r\n" +
                $"  EntryPointAddress: {progModule.EntryPointAddress.FormatAsHex()}\r\n" +
                $"  ModuleMemorySize: 0x{progModule.ModuleMemorySize:X8}\r\n" +
                $"");


            //callbackProvider = new UnmanagedCodeSupplier((PickUpWeaponDelegate)ttExecutionCallback, IntPtr.Size == sizeof(int) ? x86CodeForFastcallWrapperForExecutionDelegate : x64CodeForFastcallWrapperForExecutionDelegate, IntPtr.Size == sizeof(int) ? new UIntPtr(0xF0F0F0F0) : new UIntPtr(0xF0F0F0F0F0F0F0F0));

            //byte[] progMemory = new byte[progModule.ModuleMemorySize];

            //return;


            ////////

            CheckHr(control.WaitForEvent(DEBUG_WAIT.DEFAULT, 5000));


            byte[] progMemory = new byte[progModule.ModuleMemorySize];
            uint   readMemoryBytes;

            ulong validbase;
            uint  validsize;

            CheckHr(dataSpaces.GetValidRegionVirtual((ulong)progModule.BaseAddress, (uint)progMemory.Length, out validbase, out validsize));


            //Console.WriteLine($"Read {readMemoryBytes} bytes");


            byte[] pickUpWeaponSignature;
            byte[] wildcard;
            ParseSearchPattern(
                "55 8B EC 83 E4 F8 80 3D A9 0F ?? 0F 00 56 57 8B F2 8B F9 75 23 80 3D 9A 0E ?? 0F 00 75 1A 56 E8 9C 94 F9 FF 83 FE 0F 75 0F 83 F8 32 7C 0A B9 D4",
                out pickUpWeaponSignature,
                out wildcard
                );
            //wildcard[3] = 1;
            ulong matchOffset;

            CheckHr(dataSpaces.ReadVirtualUncached((ulong)progModule.BaseAddress, progMemory, (uint)progMemory.Length, out readMemoryBytes));
            fixed(void *progMemoryPtr = progMemory, pickUpWeaponSignaturePtr = pickUpWeaponSignature, wildcardPtr = wildcard)
            {
                //pickUpWeaponAddress = (IntPtr) IndexOfUnchecked(progMemoryPtr, progMemory.Length, pickUpWeaponSignaturePtr, pickUpWeaponSignature.Length, wildcardPtr);
                int pickUpWeaponAddressOffset =
                    IndexOfUnchecked(progMemoryPtr, progMemory.Length, pickUpWeaponSignaturePtr, pickUpWeaponSignature.Length, wildcardPtr);

                Console.WriteLine($"PickUpWeapon offset: 0x{pickUpWeaponAddressOffset:X8}");
                if (pickUpWeaponAddressOffset == -1)
                {
                    throw new Exception("Pattern not found!");
                }

                pickUpWeaponAddress = new IntPtr(pickUpWeaponAddressOffset + (int)progModule.BaseAddress);
            }

            //dataSpaces.SearchVirtual((ulong) progModule.BaseAddress, (ulong) progModule.ModuleMemorySize, pickUpWeaponSignature, (uint) pickUpWeaponSignature.Length, 1, out matchOffset);
            //pickUpWeaponAddress = (IntPtr) matchOffset;
            Console.WriteLine($"PickUpWeapon address: {pickUpWeaponAddress.FormatAsHex()}");

            control.AddBreakpoint2(DEBUG_BREAKPOINT_TYPE.CODE, uint.MaxValue, out pickUpWeaponBreakpoint);
            pickUpWeaponBreakpoint.SetOffset((ulong)pickUpWeaponAddress);
            pickUpWeaponBreakpoint.SetFlags(DEBUG_BREAKPOINT_FLAG.ENABLED);

            pickUpWeaponBreakpoint.SetCommandWide(".echo WEAPON PICKUP!");

            // fixed (void* progMemoryPtr = progMemory, pickUpWeaponSignaturePtr = pickUpWeaponSignature) {
            //     int pickUpWeaponAddressOffset =
            //         IndexOfUnchecked(progMemoryPtr, progMemory.Length, pickUpWeaponSignaturePtr, pickUpWeaponSignature.Length);
            //     Console.WriteLine($"PickUpWeapon offset: 0x{pickUpWeaponAddressOffset:X8}");
            //     if (pickUpWeaponAddressOffset == -1)
            //         throw new Exception("Pattern not found!");
            //
            //     pickUpWeaponAddress = new IntPtr(pickUpWeaponAddressOffset + (int) progModule.BaseAddress);
            //     Console.WriteLine($"PickUpWeapon address: {pickUpWeaponAddress.FormatAsHex()}");
            // }

            control.SetExecutionStatus(DEBUG_STATUS.GO);

            File.WriteAllBytes("dump.bin", progMemory);

            DEBUG_STATUS status;
            int          hr;

            while (true)
            {
                CheckHr(control.GetExecutionStatus(out status));
                if (status == DEBUG_STATUS.NO_DEBUGGEE)
                {
                    Console.WriteLine("No Target");
                    break;
                }

                if (status == DEBUG_STATUS.GO || status == DEBUG_STATUS.STEP_BRANCH ||
                    status == DEBUG_STATUS.STEP_INTO ||
                    status == DEBUG_STATUS.STEP_OVER)
                {
                    hr = control.WaitForEvent(DEBUG_WAIT.DEFAULT, uint.MaxValue);
                    continue;
                }

                if (events.StateChanged)
                {
                    Console.WriteLine();
                    events.StateChanged = false;
                    if (events.BreakpointHit)
                    {
                        control.OutputCurrentState(DEBUG_OUTCTL.THIS_CLIENT,
                                                   DEBUG_CURRENT.DEFAULT);
                        events.BreakpointHit = false;
                    }
                }


                control.OutputPromptWide(DEBUG_OUTCTL.THIS_CLIENT, null);
                Console.Write(" ");
                Console.ForegroundColor = ConsoleColor.Gray;
                string command = Console.ReadLine();
                if (command == ".detach")
                {
                    client.DetachCurrentProcess();
                }
                else
                {
                    control.ExecuteWide(DEBUG_OUTCTL.THIS_CLIENT, command,
                                        DEBUG_EXECUTE.DEFAULT);
                }
            }
        }