unsafe void ApplyPatch(string[] list)
    {
        int
            baseAddr    = (int)Process.GetCurrentProcess().MainModule.BaseAddress,
            codeInjAddr = baseAddr + codeInjOffset,
            mpqFuncAddr = baseAddr + mpqFuncOffset;

        if (!Check(codeInjAddr, mpqFuncAddr))
        {
            Log.Error("LoadMPQ: Patch pattern mismatch (wrong game version?)");
            return;
        }

        Log.Information("LoadMPQ: Injecting mpq archives");

        int
            extSz        = sizeof(JmpOp) + ((sizeof(JmpOp) + sizeof(MovEspDwordOp)) * list.Length) + sizeof(JmpOp),
            codeDestAddr = (int)Marshal.AllocHGlobal(extSz);

        VirtualProtect(codeInjAddr, sizeof(JmpOp), erwFlag, out outPtr);
        JmpOp.Write(codeInjAddr, codeDestAddr, false);

        VirtualProtect(codeDestAddr, extSz, erwFlag, out outPtr);
        var writeAddr = codeDestAddr;

        JmpOp.Write(writeAddr, mpqFuncAddr, true);
        writeAddr += sizeof(JmpOp);

        for (int i = 0; i < list.Length; i++)
        {
            MovEspDwordOp.Write(writeAddr, (int)Marshal.StringToHGlobalAnsi(list[i]));
            writeAddr += sizeof(MovEspDwordOp);
            JmpOp.Write(writeAddr, mpqFuncAddr, true);
            writeAddr += sizeof(JmpOp);
        }

        JmpOp.Write(writeAddr, codeInjAddr + sizeof(JmpOp), false);
    }
 unsafe bool Check(int codeInjAddr, int mpqFuncAddr)
 {
     return(JmpOp.Compare(*(JmpOp *)codeInjAddr, new JmpOp(mpqFuncAddr - (codeInjAddr + sizeof(JmpOp)), true)));
 }
 public static unsafe bool Compare(JmpOp opA, JmpOp opB)
 {
     return((opA.OpCode == opB.OpCode) && (opA.Offset == opB.Offset));
 }