Перейти к содержанию

Ассемблер. Настройка работы хоткея.


Рекомендуемые сообщения

Всем привет. Народ, помогите настроить работу хоткея. плиз.

Суть. Собрал трейнер на Game Trainer Studio. Все работает как надо, но есть одно неудобство - срабатывание хоткея не очень удобное. То есть, если чуть передержать его, то функция успеет включиться и опять выключиться. То есть время нажатия приходиться постоянно контроллировать, а это напрягает. Короче, хочется сделать так - одно нажатие на хоткей - одно срабатывание. Но как это сделать - не знаю. Помогите, знающие!

Вот пример трейнера. Нашел строку, отвечающую за это переключение - 191-я строка:

Invoke SetTimer, hWin, 1, 100, 0 ; HotKey Timer

Вот с этой сотней миллисекунд игрался, пытался увеличивать, но тогда просто дольше нужно клавишу держать для срабатывания.

NullAlex: убрал под спойлер
; #########################################################################;; This Is My Trainer Template Created For The Game Trainer Studio (Xeta);; This Is Based On A MASM Example.;; #########################################################################.386.model flat, stdcall ; 32 bit memory modeloption casemap :none ; case sensitiveinclude trainer.inc ; local includes for this file; #########################################################################.data; ### Constants Below; ### Constants Above; ### Bytes BelowHotKey00000 db 000hdb 010hdb 000hdb 000hHotKey00001 db 001hdb 001hdb 001hdb 001h; ### Bytes Above; ### Button Messages Below; ### Button Messages AboveWindCap db "Game.exe",0szDisplayName db 'Trainer for Game',0.codestart:invoke GetModuleHandle, NULLmov hInstance, eaxinvoke GetCommandLinemov CommandLine, eaxinvoke WinMain,hInstance,NULL,CommandLine,SW_SHOWDEFAULTinvoke ExitProcess,eax; #########################################################################WinMain proc hInst :DWORD,hPrevInst :DWORD,CmdLine :DWORD,CmdShow :DWORD;====================; Put LOCALs on stack;====================LOCAL wc :WNDCLASSEXLOCAL msg :MSGLOCAL Wwd :DWORDLOCAL Wht :DWORDLOCAL Wtx :DWORDLOCAL Wty :DWORD;==================================================; Fill WNDCLASSEX structure with required variables;==================================================invoke LoadIcon,hInst,500 ; icon IDmov hIcon, eaxszText szClassName,"Trainer_Class"mov wc.cbSize, sizeof WNDCLASSEXmov wc.style, CS_HREDRAW or CS_VREDRAW \or CS_BYTEALIGNWINDOWmov wc.lpfnWndProc, offset WndProcmov wc.cbClsExtra, NULLmov wc.cbWndExtra, NULLm2m wc.hInstance, hInstmov wc.hbrBackground, COLOR_BTNFACE+1mov wc.lpszMenuName, NULLmov wc.lpszClassName, offset szClassNamem2m wc.hIcon, hIconinvoke LoadCursor,NULL,IDC_ARROWmov wc.hCursor, eaxm2m wc.hIconSm, hIconinvoke RegisterClassEx, ADDR wc;================================; Centre window at following size;================================mov Wwd, 265 ; Dialog Widthmov Wht, 145 ; Dialog Heightinvoke GetSystemMetrics,SM_CXSCREENinvoke TopXY,Wwd,eaxmov Wtx, eaxinvoke GetSystemMetrics,SM_CYSCREENinvoke TopXY,Wht,eaxmov Wty, eaxinvoke CreateWindowEx,WS_EX_LEFT,ADDR szClassName,ADDR szDisplayName,WS_MINIMIZEBOX or WS_OVERLAPPED or WS_SYSMENU,Wtx,Wty,Wwd,Wht,NULL,NULL,hInst,NULLmov hWnd,eaxinvoke ShowWindow,hWnd,SW_SHOWNORMALinvoke UpdateWindow,hWnd;===================================; Loop until PostQuitMessage is sent;===================================StartLoop:invoke GetMessage,ADDR msg,NULL,0,0cmp eax, 0je ExitLoopinvoke TranslateMessage, ADDR msginvoke DispatchMessage, ADDR msgjmp StartLoopExitLoop:return msg.wParamWinMain endp; #########################################################################WndProc proc hWin :DWORD,uMsg :DWORD,wParam :DWORD,lParam :DWORDLOCAL var :DWORDLOCAL caW :DWORDLOCAL caH :DWORDLOCAL color :DWORDLOCAL hDC :DWORDLOCAL Rct :RECTLOCAL Ps :PAINTSTRUCTLOCAL buffer1[128]:BYTELOCAL buffer2[128]:BYTELOCAL lfnt :LOGFONTLOCAL psd :PAGESETUPDLGLOCAL pd :PRINTDLGLOCAL RectB :RECT.if uMsg == WM_COMMANDMOV EAX, wParam.if wParam == 499.endif.elseif uMsg == WM_CTLCOLORSTATICJMP @WM_CTLCOLOREDIT.elseif uMsg == WM_CTLCOLOREDIT@WM_CTLCOLOREDIT:.elseif uMsg == WM_DRAWITEM.elseif uMsg == WM_CREATEMOV HotKeyMiniToggle, TRUEszText font1,'MS Sans Serif'invoke CreateFont,8,5,0,0,500,0,0,0, \DEFAULT_CHARSET,0,0,0,\DEFAULT_PITCH,ADDR font1mov hFont, eaxInvoke SetTimer, hWin, 1, 100, 0 ; HotKey TimerInvoke SetTimer, hWin, 2, 300, 0 ; EditBox Timer 1Invoke SetTimer, hWin, 3, 300, 0 ; EditBox Timer 2Invoke SetTimer, hWin, 4, 100, 0 ; EditBox Freeze Timer.elseif uMsg == WM_TIMER.If wParam == 1 ; ### Timer Below ###Invoke GetKeyState, VK_HOMEmov HotBuffer1, eax.if HotBuffer1 > 1Invoke TrainerEngineRead, NULL, Offset WindCap, 00215AF51h, 1MOV Read, EAX.If Read == 001hInvoke TrainerEngine, NULL, Offset WindCap, 00215AF51h, Offset HotKey00000, 4.ElseInvoke TrainerEngine, NULL, Offset WindCap, 00215AF51h, Offset HotKey00001, 4.EndIf.endif.Endif ; ### Timer Above ###.If wParam == 2 ; ### Timer Below ###.Endif ; ### Timer Above ###.If wParam == 3 ; ### Timer Below ###.Endif ; ### Timer Above ###.If wParam == 4 ; ### EBFreeze Timer Below ###.Endif ; ### EBFreeze Timer Above ###.elseif uMsg == WM_HOTKEY.elseif uMsg == WM_PAINTinvoke BeginPaint,hWin,ADDR Psmov hDC, eaxinvoke Paint_Proc,hWin,hDCinvoke EndPaint,hWin,ADDR Psreturn 0.elseif uMsg == WM_DESTROYinvoke PostQuitMessage,NULLreturn 0.endifinvoke DefWindowProc,hWin,uMsg,wParam,lParamretWndProc endp; ########################################################################TopXY proc wDim:DWORD, sDim:DWORDshr sDim, 1 ; divide screen dimension by 2shr wDim, 1 ; divide window dimension by 2mov eax, wDim ; copy window dimension into eaxsub sDim, eax ; sub half win dimension from half screen dimensionreturn sDimTopXY endp; #########################################################################Paint_Proc proc hWin:DWORD, hDC:DWORDLOCAL btn_hi :DWORDLOCAL btn_lo :DWORDLOCAL Rct :RECTinvoke GetSysColor,COLOR_BTNHIGHLIGHTmov btn_hi, eaxinvoke GetSysColor,COLOR_BTNSHADOWmov btn_lo, eaxreturn 0Paint_Proc endp; ########################################################################OnDrawItem proc uses ebx idCtl:DWORD,pdis:DWORD,pcol:DWORD,pbkcol:DWORDLOCAL tbuff[20h]:bytemov ebx,pdisassume ebx:ptr DRAWITEMSTRUCT.if [ebx].CtlType == ODT_BUTTON.if pbkcol == 0.elseinvoke SetBkMode,[ebx].hdc,OPAQUEInvoke SetBkColor,[ebx].hdc,pbkcolInvoke CreateSolidBrush, pbkcolinvoke FillRect,[ebx].hdc,addr [ebx].rcItem,eax.endifinvoke SetTextColor,[ebx].hdc,pcol.if ([ebx].itemState & ODS_SELECTED)invoke DrawEdge,[ebx].hdc,addr [ebx].rcItem,BDR_SUNKEN,BF_RECTinvoke OffsetRect,addr [ebx].rcItem,1,1.elseinvoke DrawEdge,[ebx].hdc,addr [ebx].rcItem,EDGE_RAISED,BF_RECT.endifinvoke GetWindowText,[ebx].hwndItem,addr tbuff,sizeof tbufflea edx,[ebx].rcItemlea ecx,tbuffinvoke DrawText,[ebx].hdc,ecx,eax,edx,DT_CENTER or DT_VCENTER or DT_SINGLELINE or DT_NOCLIP.if [ebx].itemState & ODS_FOCUSinvoke InflateRect,addr [ebx].rcItem,-4,-4invoke DrawFocusRect,[ebx].hdc,addr [ebx].rcItem.endif.endifassume ebx:nothingretOnDrawItem endp; ########################################################################end start
Ссылка на комментарий
Поделиться на другие сайты

То есть, если чуть передержать его, то функция успеет включиться и опять выключиться.

Может тогда проще разделить хоткеи.

Ну например:

активировать - F1

деактивировать - CtrL F1. 

И не париться с таймером.

Ссылка на комментарий
Поделиться на другие сайты

Может тогда проще разделить хоткеи. Ну например: активировать - F1 деактивировать - CtrL F1. И не париться с таймером.

Не-не, нужно именно что один хоткей на вкл-выкл.

 

Надо GetAsyncKeyState, иначе хоткеи будут работать только при активном окне трейнера.

Да все, вроде, работает и при свернутом. Нет, в этом смысле проблем нет.

Ссылка на комментарий
Поделиться на другие сайты

Привет! Думаю, состояние таймера можно тем или иным образом контролировать. Самый простой вариант - поставить не 100мс, а 500, чтобы исключить "повторные" нажатия. А вообще, подумай как следует и напиши, что конкретно ты хочешь чтобы оно делало и как работало. Тогда будет проще придумать.
Ссылка на комментарий
Поделиться на другие сайты

Самый простой вариант - поставить не 100мс, а 500, чтобы исключить "повторные" нажатия. А вообще, подумай как следует и напиши, что конкретно ты хочешь чтобы оно делало и как работало. Тогда будет проще придумать.

Так я говорил, что игрался уже с этим значением, увеличивал до 500 и 1000. При его увеличении для срабатывания требуется дольше жать хоткей, это тоже неудобно.

Мне нужно, чтобы на одно нажатие было ОДНО срабатывание. НЕЗАВИСИМО от длительности нажатия.

Ссылка на комментарий
Поделиться на другие сайты

Карочи! Ты такой:

int flag = 0; /* объявляем флажок */ if ( GetAsyncKeyState(0x20) & 0x8000 && !flag ) { /* Если кнопка в нижнем положении и флажок == 0 */    flag = 1; /* Ставим флажок в 1 */    /* Выполняем нужный код */} else if ( !GetAsyncKeyState(0x20) ) { /* Иначе, если кнопка НЕ нажата */    flag = 0; /* Снимаем флажок */}

Заметь, что перед 0x8000 стоит логическое И. В чем суть? В том, что функция GetAsyncKeyState возвращает значение типа SHORT. SHORT - это два байта. Младший показывает состояние кнопки (нажата - не нажата), а старший - подробности. Эти самые подробности в бинарном виде выглядят так:

 

0000 0000 0000 0000 // Кнопка вверху и не нажата
1000 0000 0000 0001 // Кнопку нажали и она теперь внизу
1000 0000 0000 0000
1000 0000 0000 0000 // Кнопка все еще внизу
1000 0000 0000 0000
1000 0000 0000 0000
0000 0000 0000 0000 // Кнопка отжалась обратно

 

То же, но в 16-ричном формате:

 

0x0000
0x8001
0x8000
0x8000
0x8000
0x8000
0x0000

 

Итого:

 

0x0000
0x8001

 

OnKeyDown - нажали кнопку и держим ее так.

 

0x8000 ИЛИ 0x8001

 

OnKeyPressed - нажали и отпустили, НО предыдущяя проверка должна была вернуть 0.

 

0x8001

 

OnKeyHold - с момента предыдущей провери кнопка все еще нажата. В духе: "ABCDDDDDDDDDDD".

 

0x8000 ИЛИ 0x8001
0x0000

 

OnKeyUp - то есть кнопка отпустилась из предыдущего своего состояния.

 

Такая вот штуковина! =D

  • Плюс 1
Ссылка на комментарий
Поделиться на другие сайты

int flag = 0; /* объявляем флажок */ if ( GetAsyncKeyState(0x20) & 0x8000 && !flag ) { /* Если кнопка в нижнем положении и флажок == 0 */    flag = 1; /* Ставим флажок в 1 */    /* Выполняем нужный код */} else if ( !GetAsyncKeyState(0x20) ) { /* Иначе, если кнопка НЕ нажата */    flag = 0; /* Снимаем флажок */}

Ага, и куда этот код вставлять? И вместо какого?

А то я спец тот еще :-[ . За меня почти все всякие билдеры делают.

Ссылка на комментарий
Поделиться на другие сайты

Мне нужно, чтобы на одно нажатие было ОДНО срабатывание. НЕЗАВИСИМО от длительности нажатия.

Если бы на ассемблер СЕ, я бы написал так:

pushadpush 97                 // VK_NUMPAD1 = 97     call GetAsyncKeyState   // Проверка - нажата ли клавиша?     shr ax,#15cmp ax,1popadjne exit                // если не нажата - выходимcmp byte ptr [flag],1   // Проверяем значение flaga, при включении скрипта он равен 1. jne Deactivate          // Если не равен 1, то деактивируем скрипт.mov byte ptr[flag],0    // Делаем flag не равным 1.Activate:               // Если flag равен 1, то выполняем // код                  // код скрипта.flag:                   // Объявляем flag.db 1exit:

Это часть скрипта.

  • Плюс 1
Ссылка на комментарий
Поделиться на другие сайты

Ребят, вы делайте скидку на то, что я дуб в программировании почти полный. Ну так, совсем по мелочи вершков кое-каких нахватался. Разжевывайте, пожалуйста, куда пихать эти коды. А так получается будто мне предлагают прочитать какой-то текст, а я только две буквы из алфавита знаю :-[ 

Ссылка на комментарий
Поделиться на другие сайты

Извиняюсь, я задумался не о том, пока отвечал. С утра распишу подробнее.

P.S.: Скоро у меня на канале начнется курс по программированию трейнеров. С полнейшего нуля, ага.

  • Плюс 2
Ссылка на комментарий
Поделиться на другие сайты

Извиняюсь, я задумался не о том, пока отвечал. С утра распишу подробнее.

Ок, жду.

 

Скоро у меня на канале начнется курс по программированию трейнеров. С полнейшего нуля, ага.

Буду следить. Сейчас зашел, почитал, понравилось. Доступно объяснять тоже уметь надо.

Ссылка на комментарий
Поделиться на другие сайты

Извиняюсь, я задумался не о том, пока отвечал. С утра распишу подробнее.

P.S.: Скоро у меня на канале начнется курс по программированию трейнеров. С полнейшего нуля, ага.

 

Ассемблер? Или С? Раз будет у тебя, я у себя такой курс тогда начинать не буду, зачем одно и то же делать. Буду углубляться все больше во взлом игр.

Ссылка на комментарий
Поделиться на другие сайты

ууууу старый долбаный масм32

тот код выше легко переписать на fasm или yasm ;)

 

наверно так, только в masm вместо = <> наверно == и =! ....короче проверишь

invoke GetAsyncKeyState,VK_HOMEshr eax,1.if [KeySwitch01] <> ahmov [KeySwitch01],ah.if ah.if [KeyStatus01] = almov [KeyStatus01],ahinvoke TrainerEngine, NULL, Offset WindCap, 00215AF51h, Offset HotKey00000, 4.elsemov [KeyStatus01],alinvoke  TrainerEngine, NULL, Offset WindCap, 00215AF51h, Offset HotKey00001, 4.endif.endif.endif

ps там в .дата влепи

KeySwitch01 db 0

KeyStatus01 db 0

Изменено пользователем gmz
  • Плюс 1
Ссылка на комментарий
Поделиться на другие сайты

наверно так, только в masm вместо = <> наверно == и =! ....короче проверишь

...

ps там в .дата влепи KeySwitch01 db 0 KeyStatus01 db 0

Не работает. Заменил у себя

Invoke GetKeyState, VK_HOMEmov HotBuffer1, eax.if HotBuffer1 > 1Invoke TrainerEngineRead, NULL, Offset WindCap, 00215AF51h, 1MOV Read, EAX.If Read == 001hInvoke TrainerEngine, NULL, Offset WindCap, 00215AF51h, Offset HotKey00000, 4.ElseInvoke TrainerEngine, NULL, Offset WindCap, 00215AF51h, Offset HotKey00001, 4.EndIf.endif

на твое

invoke GetAsyncKeyState,VK_HOMEshr eax,1.if [KeySwitch01] <> ahmov [KeySwitch01],ah.if ah.if [KeyStatus01] = almov [KeyStatus01],ahinvoke TrainerEngine, NULL, Offset WindCap, 00215AF51h, Offset HotKey00000, 4.elsemov [KeyStatus01],alinvoke  TrainerEngine, NULL, Offset WindCap, 00215AF51h, Offset HotKey00001, 4.endif.endif.endif

Без изменений.

Ссылка на комментарий
Поделиться на другие сайты

Может, в этом причина? Но тут я не понял что и где влепить.

в секцию .data

.if ah вроде надо на .if ah == ah

масм собрал без ошибок?

 

конс. пример. кнопка INSERT

http://rghost.ru/private/8Gdgbkty4/44f5d12e1a4096228849124b97b9316c

  • Плюс 1
Ссылка на комментарий
Поделиться на другие сайты

в секцию .data

.if ah вроде надо на .if ah == ah

масм собрал без ошибок?

Без ошибок. Но когда вставил в секцию .data

KeySwitch01 db 0

KeyStatus01 db 0

тогда:

06a32bc8c257.jpg

Не туда вставил, похоже. А, он же мне строки с ошибками указывает, только сейчас дошло :-D

А пример работает именно так, как надо.

 

Может, лучше просто мой пример в шапке исправить так, как надо. Более наглядно будет.

Изменено пользователем Japonamat
Ссылка на комментарий
Поделиться на другие сайты

Может, лучше просто мой пример в шапке исправить так, как надо. Более наглядно будет.

Lol его проще на фасм переписать

 

в .data

KeySwitch01 db 0

KeyStatus01 db 0

invoke GetAsyncKeyState,VK_HOMEshr eax,1.if KeySwitch01 != ahmov KeySwitch01,ah.if ah.if KeyStatus01 == almov KeyStatus01,ahinvoke TrainerEngine, NULL, Offset WindCap, 00215AF51h, Offset HotKey00000, 4.elsemov KeyStatus01,alinvoke  TrainerEngine, NULL, Offset WindCap, 00215AF51h, Offset HotKey00001, 4.endif.endif.endif

вот. это точно ОК спецом этот говномасм распаковал и проверил.

  • Плюс 1
Ссылка на комментарий
Поделиться на другие сайты

вот. это точно ОК спецом этот говномасм распаковал и проверил.

"Ура, заработало!!!" (с) :-D - кот Матроскин.

Все как доктор прописал. Огромное спасибо за помощь, дружище!

 

Последний вопрос. Вот эти строки

KeySwitch01 db 0

KeyStatus01 db 0

критично куда прописывать с секции дата? Где она, собственно, кончается, эта секция? Каких-то закрывающих тегов не нашел. Извиняюсь за, возможно, дурацкий вопрос, но я в этом деле дуб :-[

Ссылка на комментарий
Поделиться на другие сайты

По идее, одна секция заканчивается там, где начинается следующая. У тебя .data идет первой, потом идет .code, так что везде между .data и до .code - секция .data.
  • Плюс 1
Ссылка на комментарий
Поделиться на другие сайты

Ага, ясно, спасибо, буду знать. Они же, вроде, все языки более-менее похожи, вот я и ждал, что будут закрывающие теги, типа как в html. А их нет. Замуровали, демоны :-D

Ссылка на комментарий
Поделиться на другие сайты

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.