Rev 7443 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
7389 | theonlymir | 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ; Hot Angles ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
3 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
4 | ; Compile with FASM |
||
7459 | theonlymir | 5 | ; Version 0.3.7: Oct 14, 2018 |
7389 | theonlymir | 6 | |
7 | ; Copyright (c) 2018, Efremenkov Sergey aka TheOnlyMirage |
||
8 | ; All rights reserved. |
||
9 | ; Redistribution and use in source and binary forms, with or without modification, |
||
10 | ; are permitted provided that the following conditions are met: |
||
11 | ; * Redistributions of source code must retain the above copyright notice, this |
||
12 | ; list of conditions and the following disclaimer. |
||
13 | ; * Redistributions in binary form must reproduce the above copyright notice, |
||
14 | ; this list of conditions and the following disclaimer in the documentation and/or |
||
15 | ; other materials provided with the distribution. |
||
16 | ; * Neither the name of the |
||
17 | ; be used to endorse or promote products derived from this software without |
||
18 | ; specific prior written permission. |
||
19 | |||
20 | ; THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
||
21 | ; INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A |
||
22 | ; PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT |
||
23 | ; HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||
24 | ; OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
||
25 | ; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
26 | ; -------------------------------------------------------------------------------------- |
||
27 | |||
28 | format binary as "" ;"kex" |
||
29 | use32 |
||
30 | org 0x0 ; базовый адрес размещения кода, всегда 0x0 |
||
31 | |||
32 | UNLOCKd = 0 |
||
7436 | theonlymir | 33 | LOCKd = 1 |
7459 | theonlymir | 34 | SUPERLOCKd = 2 |
7389 | theonlymir | 35 | |
36 | ; заголовок |
||
37 | db 'MENUET01' ;магический идентификатор |
||
38 | dd 0x01 ;версия |
||
7436 | theonlymir | 39 | dd START_DEBUG ;адрес точки старта программы |
7389 | theonlymir | 40 | dd I_END ;адрес конца, по факту размер файла программы |
41 | dd 0x100000 ;требуемое кол-во памяти для загрузки программы |
||
42 | dd 0x7fff0 ;начальное значение регистра esp - адрес конца области стэка так как стэк растет в сторону меньших адресов |
||
43 | dd 0, 0 ;адрес строки параметров и адрес строки пути исполняемого файла |
||
44 | |||
45 | |||
46 | include '../../macros.inc' |
||
47 | |||
48 | START_DEBUG: |
||
49 | call copyKill ;простейшая защита от повторного запуска |
||
50 | mcall 68, 11 ;инициализация кучи |
||
51 | call loadConfig ;загружаем конфигурацию приложения |
||
7436 | theonlymir | 52 | |
53 | cmp byte[mode], 0 ;функция отключена - выход |
||
54 | jne @f |
||
55 | mcall -1 |
||
56 | @@: |
||
7443 | theonlymir | 57 | ;режим жеста по горячей клавише? |
58 | cmp byte[mode], 3 ;подписываемся на интересные нам события в зависимости от режима работы |
||
59 | jne @f |
||
60 | mov ebx, 00000100000000000000000000100010b ;если да, то подписываемся на клавиши |
||
61 | mcall 40 |
||
62 | jmp init03 |
||
63 | @@: |
||
7436 | theonlymir | 64 | ;режим активации горячей клавишей? |
65 | cmp byte[mode], 2 ;подписываемся на интересные нам события в зависимости от режима работы |
||
66 | jne @f |
||
67 | mov ebx, 00000100000000000000000000100010b ;если да, то подписываемся на клавиши |
||
7389 | theonlymir | 68 | mcall 40 |
7436 | theonlymir | 69 | jmp init02 |
70 | @@: |
||
71 | ; во всех остальных случаях - классический режим работы |
||
72 | ;mode=1 классический режим работы - реакция при наведении в угол |
||
73 | mov byte[mode], 1 |
||
74 | mov ebx, 00000100000000000000000000100000b |
||
75 | mcall 40 |
||
76 | jmp init01 |
||
7389 | theonlymir | 77 | |
7436 | theonlymir | 78 | |
79 | |||
80 | init02: |
||
81 | mov dword[backAdr], mode02 |
||
82 | call setHotKey |
||
83 | mode02: |
||
84 | mcall 10 |
||
85 | cmp eax, 2 ;обработка нажатия клавиши |
||
86 | je hotkey |
||
87 | |||
88 | cmp byte[keyState], 0 |
||
89 | je mode02 |
||
90 | cmp eax, 6 ;обработка перемещений и нажатия мыши |
||
91 | je mouse |
||
92 | |||
93 | jmp mode02 |
||
94 | |||
95 | |||
96 | setHotKey: ;установить горячую клавишу |
||
97 | push eax ebx ecx edx |
||
98 | xor ecx, ecx |
||
99 | mov cl, byte[keyActivate] ;нажатие горячей клавиши |
||
100 | mov edx, 0x000 |
||
101 | mcall 66, 4, ecx, edx |
||
102 | |||
103 | ;mov cl, byte[keyActivate] |
||
104 | add cl, 128 ;отпускание горячей клавиши |
||
105 | ;mov edx, 0x000 |
||
106 | mcall 66, 4, ecx, edx |
||
107 | pop edx ecx ebx eax |
||
108 | ret |
||
109 | |||
110 | |||
111 | hotkey: |
||
112 | mcall 2 |
||
113 | cmp eax, 1 ;буфер клавиш пуст? |
||
114 | je hotkey.end |
||
115 | |||
116 | cmp al, 2 ;нас интересует только скан код горячей клавиши, иначе выходим |
||
117 | jne hotkey.end |
||
118 | |||
119 | cmp ah, byte[keyActivate] ;если нажата наша горячая клавиша |
||
120 | jne @f |
||
7443 | theonlymir | 121 | |
7459 | theonlymir | 122 | ;проверки для mode 3 |
123 | cmp byte[state], SUPERLOCKd |
||
124 | je hotkey.end |
||
7443 | theonlymir | 125 | cmp byte[keyState], 1 |
7459 | theonlymir | 126 | je hotkey.end |
7443 | theonlymir | 127 | |
128 | push eax ebx |
||
129 | mcall 37, 0 ;запоминаем текущие(начальные) координаты мыши |
||
130 | ;mov dword[o.x], eax |
||
131 | mov word[o.y], ax |
||
132 | shr eax, 16 |
||
133 | mov word[o.x], ax |
||
134 | pop ebx eax |
||
135 | |||
7436 | theonlymir | 136 | mov byte[keyState], 1 |
137 | mov byte[state], UNLOCKd |
||
138 | jmp hotkey.end |
||
139 | @@: |
||
140 | push edx |
||
141 | xor edx, edx |
||
142 | mov dl, byte[keyActivate] |
||
143 | add dl, 128 |
||
144 | cmp ah, dl ;если отпущена наша горячая клавиша |
||
145 | jne @f ;hotkey.end |
||
7459 | theonlymir | 146 | |
7436 | theonlymir | 147 | mov byte[keyState], 0 |
148 | mov byte[state], LOCKd |
||
149 | @@: |
||
150 | pop edx |
||
151 | .end: |
||
7443 | theonlymir | 152 | jmp dword[backAdr] |
7436 | theonlymir | 153 | |
154 | |||
155 | init01: |
||
156 | mov dword[backAdr], mode01 |
||
157 | mode01: |
||
7389 | theonlymir | 158 | mov eax, 10 ; function 10 : wait until event |
159 | mcall ; event type is returned in eax |
||
160 | |||
161 | cmp eax, 6 ;обработка перемещений и нажатия мыши |
||
162 | je mouse |
||
163 | |||
7436 | theonlymir | 164 | jmp mode01 |
7389 | theonlymir | 165 | |
7436 | theonlymir | 166 | |
7389 | theonlymir | 167 | mouse: |
7436 | theonlymir | 168 | push ebx |
169 | mcall 37, 0 ;получаем текущие координаты мыши |
||
170 | pop ebx |
||
7389 | theonlymir | 171 | |
172 | cmp eax, 0 ;левый верхний угол |
||
173 | jne @f |
||
174 | ; -- здесь вызываем соотв. вызов для левого верхнего угла (X=0, Y=0) |
||
175 | push ecx |
||
176 | mov ecx, 0 |
||
177 | call run_command |
||
178 | pop ecx |
||
179 | |||
7436 | theonlymir | 180 | jmp dword[backAdr] ;finish |
7389 | theonlymir | 181 | @@: |
182 | call get_screen_size ;иначе обновляем размеры экрана |
||
183 | |||
184 | cmp ax, word[screen.height] ;Ymouse = Yscreen ? |
||
185 | je Ytrue |
||
186 | ;если Y не равны, то нас интересует Y=0 и X=ScreenWidth (правый верхний угол) |
||
187 | |||
188 | cmp ax, 0 |
||
189 | jne unlockend |
||
190 | shr eax, 16 |
||
191 | cmp ax, word[screen.width] |
||
192 | jne unlockend |
||
193 | ; -- здесь вызываем для правого верхенего угла |
||
194 | push ecx |
||
195 | mov ecx, 2 |
||
196 | call run_command |
||
197 | pop ecx |
||
198 | |||
7436 | theonlymir | 199 | jmp dword[backAdr] |
7389 | theonlymir | 200 | Ytrue: |
201 | ;если Y равны, то нас интересует X=0 (левый нижний угол) или X=ScreenWidth (правый нижний) |
||
202 | shr eax, 16 |
||
203 | cmp ax, 0 |
||
204 | jne @f |
||
205 | ; -- X=0, Y = Height (левый нижний угол) |
||
206 | push ecx |
||
207 | mov ecx, 1 |
||
208 | call run_command |
||
209 | pop ecx |
||
7436 | theonlymir | 210 | jmp dword[backAdr] |
7389 | theonlymir | 211 | @@: |
212 | cmp ax, word[screen.width] |
||
213 | jne unlockend |
||
214 | ; -- (правый нижний угол) |
||
215 | push ecx |
||
216 | mov ecx, 3 |
||
217 | call run_command |
||
218 | pop ecx |
||
219 | |||
7436 | theonlymir | 220 | jmp dword[backAdr] |
7389 | theonlymir | 221 | |
222 | unlockend: |
||
223 | mov byte[state], UNLOCKd |
||
7436 | theonlymir | 224 | jmp dword[backAdr] |
7389 | theonlymir | 225 | |
226 | |||
7436 | theonlymir | 227 | |
7389 | theonlymir | 228 | ;получить размер экрана |
229 | get_screen_size: |
||
230 | push eax |
||
231 | mcall 14 |
||
232 | ;теперь в eax = [xsize]*65536 + [ysize] |
||
233 | ;mov dword[screen], eax |
||
234 | mov word[screen.height], ax |
||
235 | shr eax, 16 |
||
236 | mov word[screen.width], ax |
||
237 | pop eax |
||
238 | ret |
||
239 | |||
240 | |||
241 | |||
242 | |||
7436 | theonlymir | 243 | |
7389 | theonlymir | 244 | ;запуск приложения: ecx - активный угол: lu=0, ld=1, ru=2, rd=3 |
245 | run_command: |
||
246 | cmp byte[state], UNLOCKd |
||
247 | jne run_command.end |
||
248 | |||
7436 | theonlymir | 249 | push eax ebx ecx |
7389 | theonlymir | 250 | |
251 | cmp ecx, 0 |
||
252 | jne @f |
||
7459 | theonlymir | 253 | mov eax, apps.path1 ;dword[newData.lu] |
254 | cmp byte[eax], 0 ;если по адресу пусто (или лежал символ '-'), то адрес 0 |
||
255 | je .set0 |
||
7389 | theonlymir | 256 | mov dword[struct70.path_adr], eax |
7459 | theonlymir | 257 | mov eax, apps.param1 |
258 | mov dword[struct70.param_adr], eax |
||
7389 | theonlymir | 259 | jmp .end_set_path |
260 | @@: |
||
261 | cmp ecx, 1 |
||
262 | jne @f |
||
7459 | theonlymir | 263 | mov eax, apps.path2 ;dword[newData.ld] |
264 | cmp byte[eax], 0 ;если по адресу пусто (или лежал символ '-'), то адрес 0 |
||
265 | je .set0 |
||
7389 | theonlymir | 266 | mov dword[struct70.path_adr], eax |
7459 | theonlymir | 267 | mov eax, apps.param2 |
268 | mov dword[struct70.param_adr], eax |
||
7389 | theonlymir | 269 | jmp .end_set_path |
270 | @@: |
||
271 | cmp ecx, 2 |
||
272 | jne @f |
||
7459 | theonlymir | 273 | mov eax, apps.path3 ;dword[newData.ru] |
274 | cmp byte[eax], 0 ;если по адресу пусто (или лежал символ '-'), то адрес 0 |
||
275 | je .set0 |
||
7389 | theonlymir | 276 | mov dword[struct70.path_adr], eax |
7459 | theonlymir | 277 | mov eax, apps.param3 |
278 | mov dword[struct70.param_adr], eax |
||
7389 | theonlymir | 279 | jmp .end_set_path |
280 | @@: |
||
281 | cmp ecx, 3 |
||
7459 | theonlymir | 282 | jne .set0 ;.end_set_path |
283 | mov eax, apps.path4 ;dword[newData.rd] |
||
284 | cmp byte[eax], 0 ;если по адресу пусто (или лежал символ '-'), то адрес 0 |
||
285 | je .set0 |
||
7389 | theonlymir | 286 | mov dword[struct70.path_adr], eax |
7459 | theonlymir | 287 | mov eax, apps.param4 |
288 | mov dword[struct70.param_adr], eax |
||
7389 | theonlymir | 289 | jmp .end_set_path |
7459 | theonlymir | 290 | .set0: |
291 | ;mov dword[struct70.path_adr], 0 |
||
292 | ;mov dword[struct70.param_adr], 0 |
||
293 | jmp @f |
||
7389 | theonlymir | 294 | .end_set_path: |
295 | mcall 70, struct70 |
||
7416 | theonlymir | 296 | @@: |
7389 | theonlymir | 297 | mov byte[state], LOCKd |
7436 | theonlymir | 298 | ;mov byte[keyState], 0 |
299 | pop ecx ebx eax |
||
7389 | theonlymir | 300 | .end: |
301 | ret |
||
302 | |||
303 | struct70: ;Формат информационной структуры |
||
304 | .func dd 7 ; номер подфункции |
||
305 | .mask dd 0 |
||
306 | .param_adr dd 0 ; указатель на ASCIIZ-строку с параметрами |
||
307 | .other dd 0, 0 |
||
7459 | theonlymir | 308 | .path db 0 |
309 | .path_adr dd 0 ; указатель на строку с путём |
||
7389 | theonlymir | 310 | |
311 | ;имя конфигурационного файла |
||
7416 | theonlymir | 312 | fileName: db 'SETTINGS/HOTANGLES.CFG', 0 |
7389 | theonlymir | 313 | |
7459 | theonlymir | 314 | |
315 | ;проходим до конца текущей строки |
||
316 | gotoEndString: |
||
317 | cmp eax, edx ;если файл закончился, то |
||
318 | ja @f ;выходим |
||
319 | cmp byte[eax], 10 |
||
320 | je @f |
||
321 | cmp byte[eax], 0 |
||
322 | je @f |
||
323 | cmp byte[eax], 13 |
||
324 | je @f |
||
325 | ;иначе переходим на следующий символ |
||
326 | inc eax |
||
327 | jmp gotoEndString |
||
328 | @@: |
||
329 | ret |
||
330 | |||
331 | ;пропускаем переносы в начале строки до первого адекватного символа |
||
332 | gotoStartString: |
||
333 | cmp eax, edx ;если файл закончился, то |
||
334 | ja @f ;выходим |
||
335 | cmp byte[eax], 10 |
||
336 | je .next |
||
337 | cmp byte[eax], 0 |
||
338 | je .next |
||
339 | cmp byte[eax], 13 |
||
340 | je .next |
||
341 | jmp @f ;если это другой символ, то выходим |
||
342 | .next: ;переходим на следующий символ |
||
343 | inc eax |
||
344 | jmp gotoStartString |
||
345 | @@: |
||
346 | ret |
||
347 | |||
348 | |||
349 | sep: db '|' ;символ разделитель строки пути + параметры запуска |
||
350 | readPath: |
||
351 | push ebx esi edi |
||
352 | mov bh, 0 ; 0 - знак того, что параметры ещё не встречались |
||
353 | mov byte[esi], 0 ;проинициализируем буферы-строки пустотой (на всякий случай) |
||
354 | mov byte[edi], 0 |
||
355 | @@: |
||
356 | cmp eax, edx ;если файл закончился, то |
||
357 | ja @f ;выходим |
||
358 | mov bl, byte[eax] |
||
359 | ;если очередной символ не конец строки |
||
360 | cmp bl, 10 |
||
361 | je @f ;иначе выход |
||
362 | cmp bl, 0 |
||
363 | je @f |
||
364 | cmp bl, 13 |
||
365 | je @f |
||
366 | ;и не начало параметров |
||
367 | cmp bl, byte[sep] |
||
368 | jne .read |
||
369 | ;если sep уже встречали ранее, то |
||
370 | cmp bh, 0 |
||
371 | jne .read ;просто продолжаем считывать параметры дальше (в них может быть что угодно) |
||
372 | ;иначе кладём завершающий 0 и переходим к буферу с параметрами |
||
373 | mov byte[esi], 0 |
||
374 | call trim ;ещё не забудем убрать лишние табуляции и пробелы на конце нашей строки |
||
375 | mov esi, edi |
||
376 | mov bh, 1 |
||
377 | inc eax |
||
378 | jmp @b |
||
379 | .read: ;то записываем символ в наш буфер и переходим на следующий символ |
||
380 | mov byte[esi], bl |
||
381 | inc esi |
||
382 | inc eax |
||
383 | jmp @b |
||
384 | @@: |
||
385 | mov byte[esi], 0 ;кладём завершающий ноль |
||
386 | pop edi esi ebx |
||
387 | ret |
||
388 | |||
389 | trim: ;esi - последний нулевой символ строки |
||
390 | ;push esi |
||
391 | mov byte[esi], 0 |
||
392 | dec esi |
||
393 | cmp byte[esi], 8 |
||
394 | je trim |
||
395 | cmp byte[esi], 32 |
||
396 | je trim |
||
397 | inc esi |
||
398 | ;pop esi |
||
399 | ret |
||
400 | |||
401 | |||
402 | cfgFileAdr: dd 0 ;адрес конфигурационного файла в памяти |
||
403 | |||
7389 | theonlymir | 404 | loadConfig: |
7416 | theonlymir | 405 | push eax ebx ecx edx |
7389 | theonlymir | 406 | mcall 68, 27, fileName ;загружаем конфигурационный файл в ОЗУ |
7459 | theonlymir | 407 | mov dword[cfgFileAdr], eax |
7389 | theonlymir | 408 | cmp eax, 0 |
409 | je loadConfig.exit ;если файла конфигурации нет, то завершаем работу приложения |
||
410 | ;иначе данные загружены в ОЗУ, размер в edx |
||
411 | cmp edx, 0 ;если файл пуст, в нём нет данных, то завершаем работу |
||
412 | je loadConfig.exit |
||
413 | |||
414 | add edx, eax ;иначе кладём в edx - адрес конца файла |
||
415 | |||
7436 | theonlymir | 416 | mov byte[mode], 0 |
7459 | theonlymir | 417 | cmp byte[eax], '0' ;если параметр активности приложения имеет статус: не активно |
418 | je loadConfig.exit ;то завершаем работу приложения |
||
7436 | theonlymir | 419 | cmp byte[eax], 110 ;'n' |
420 | je loadConfig.exit |
||
7389 | theonlymir | 421 | |
7436 | theonlymir | 422 | ;иначе выставляем режим |
7459 | theonlymir | 423 | cmp byte[eax], 121 ;'y' ;классический режим |
424 | jne @f |
||
425 | mov byte[mode], 1 |
||
426 | jmp loadConfig.modeEnd |
||
427 | @@: |
||
428 | cmp byte[eax], '1' ;классический режим |
||
429 | jne @f |
||
430 | mov byte[mode], 1 |
||
431 | jmp loadConfig.modeEnd |
||
432 | @@: |
||
7436 | theonlymir | 433 | cmp byte[eax], '2' ;режим активации по горячей клавише |
434 | jne @f |
||
435 | mov byte[mode], 2 |
||
436 | jmp loadConfig.modeEnd |
||
437 | @@: |
||
438 | cmp byte[eax], '3' ;режим жеста при зажатой клавише |
||
439 | jne @f |
||
440 | mov byte[mode], 3 |
||
441 | jmp loadConfig.modeEnd |
||
442 | @@: |
||
7459 | theonlymir | 443 | mov byte[mode], 0 ;во всех остальных случаях - отключено |
444 | jmp loadConfig.exit |
||
7436 | theonlymir | 445 | .modeEnd: |
446 | |||
7459 | theonlymir | 447 | ;идём до конца этой строки |
448 | call gotoEndString |
||
449 | ;находим начало следующей строки |
||
450 | call gotoStartString |
||
7389 | theonlymir | 451 | |
7459 | theonlymir | 452 | push esi edi |
7389 | theonlymir | 453 | |
7459 | theonlymir | 454 | ;считываем путь для левого верхнего угла |
455 | mov esi, apps.path1 |
||
456 | mov edi, apps.param1 |
||
457 | call readPath |
||
458 | call gotoStartString ;находим начало следующей строки |
||
7389 | theonlymir | 459 | |
7459 | theonlymir | 460 | ;считываем путь для левого нижнего угла |
461 | mov esi, apps.path2 |
||
462 | mov edi, apps.param2 |
||
463 | call readPath |
||
464 | call gotoStartString |
||
7416 | theonlymir | 465 | |
7459 | theonlymir | 466 | ;считываем путь для правого верхнего угла |
467 | mov esi, apps.path3 |
||
468 | mov edi, apps.param3 |
||
469 | call readPath |
||
470 | call gotoStartString |
||
7389 | theonlymir | 471 | |
7459 | theonlymir | 472 | ;считываем путь для правого нижнего угла |
473 | mov esi, apps.path4 |
||
474 | mov edi, apps.param4 |
||
475 | call readPath |
||
476 | call gotoStartString |
||
7389 | theonlymir | 477 | |
7459 | theonlymir | 478 | ;call checkAdr ;проверим строки на '-' и пустоту и выставим битовую маску |
479 | call checkPathAdr |
||
7389 | theonlymir | 480 | |
7459 | theonlymir | 481 | pop edi esi |
482 | |||
483 | ;пропускаем строку с именем клавиши |
||
484 | call gotoEndString |
||
485 | call gotoStartString |
||
486 | |||
487 | ;считываем сканкод активационной клавиши |
||
488 | ;call readKey |
||
489 | ;call gotoEndString |
||
490 | push esi edi ecx |
||
491 | mov esi, keystr |
||
492 | mov edi, keystr |
||
493 | call readPath |
||
494 | ;преобразуем строку в число |
||
495 | mov esi, keystr |
||
496 | call strToInteger |
||
497 | mov byte[keyActivate], cl |
||
498 | pop ecx edi esi |
||
499 | call gotoStartString |
||
500 | |||
501 | ;считываем радиус |
||
502 | push esi edi ecx |
||
503 | mov esi, radstr |
||
504 | mov edi, radstr |
||
505 | call readPath |
||
506 | ;преобразуем строку в число |
||
507 | mov esi, radstr |
||
508 | call strToInteger |
||
509 | ;теперь ecx - значение радиуса |
||
510 | ;!!! добавить проверку, чтобы число не было больше области экрана |
||
511 | ;нас интересует квадрат числа |
||
512 | push eax edx |
||
513 | mov eax, ecx ;dword[radius2] |
||
514 | mul ecx |
||
515 | mov dword[radius2], eax |
||
516 | pop edx eax |
||
517 | |||
518 | pop ecx edi esi |
||
519 | |||
520 | ;считывать размер элементов интерфейса нам не нужно (пока что этот параметр только для конфига) |
||
521 | jmp .end |
||
7389 | theonlymir | 522 | .exit: |
7416 | theonlymir | 523 | pop edx ecx ebx eax |
7389 | theonlymir | 524 | mcall -1 ;закрыть эту программу |
525 | .end: |
||
7459 | theonlymir | 526 | mov ecx, dword[cfgFileAdr] ;если файл был загружен, то |
527 | cmp ecx, 0 |
||
528 | je @f |
||
529 | mcall 68, 13, ecx ;выгружаем файл из памяти |
||
530 | @@: |
||
7416 | theonlymir | 531 | pop edx ecx ebx eax |
7389 | theonlymir | 532 | ret |
533 | |||
534 | |||
7459 | theonlymir | 535 | ;readKey: |
536 | ;читаем клавишу и выходим |
||
537 | ; cmp dword[eax], 'Ctrl' |
||
538 | ; jne .notCtrl |
||
539 | ; mov byte[keyActivate], 3 |
||
540 | ; jmp .end |
||
541 | ;.notCtrl: |
||
542 | ; cmp dword[eax], 'Shif' |
||
543 | ; jne .notShift |
||
544 | ; mov byte[keyActivate], 2 |
||
545 | ; jmp .end |
||
546 | ;.notShift: |
||
547 | ; cmp dword[eax], 'Spac' |
||
548 | ; jne .notSpace |
||
549 | ; mov byte[keyActivate], 32 |
||
550 | ; jmp .end |
||
551 | ;.notSpace: |
||
552 | ; cmp word[eax], 'Al' |
||
553 | ; jne .notAlt |
||
554 | ; mov byte[keyActivate], 1 |
||
555 | ; jmp .end |
||
556 | ;.notAlt: |
||
557 | ;убедимся, что там 1 символ, а не строка |
||
558 | ; cmp byte[eax+1], 10 |
||
559 | ; je .oneSymb |
||
560 | ; cmp byte[eax+1], 0 |
||
561 | ; je .oneSymb |
||
562 | ; cmp byte[eax+1], 13 |
||
563 | ; je .oneSymb |
||
564 | ; jmp .default ;в любом другом случае ошибка конфига - выход |
||
565 | ;.oneSymb: |
||
566 | ;проверяем, что символ разрешённый !!! доделать |
||
7389 | theonlymir | 567 | |
7459 | theonlymir | 568 | ;добавляем символ как есть |
569 | ; push ebx |
||
570 | ; ;xor ebx, ebx |
||
571 | ; mov bl, byte[eax] |
||
572 | ; mov byte[keyActivate], bl |
||
573 | ; pop ebx |
||
7389 | theonlymir | 574 | |
7459 | theonlymir | 575 | ; jmp .end |
576 | ;.default: |
||
577 | ; mcall -1 |
||
578 | ; ;mov byte[keyActivate], 2 |
||
579 | ;.end: |
||
580 | ; ret |
||
581 | |||
582 | |||
583 | checkPathAdr: |
||
584 | push eax ebx |
||
585 | xor eax, eax |
||
586 | |||
587 | mov ebx, apps.path1 |
||
588 | cmp byte[ebx], '-' |
||
589 | jne @f |
||
590 | ;cmp byte[ebx+1], 0 |
||
591 | ;jne @f |
||
592 | mov byte[ebx], 0 |
||
593 | @@: |
||
594 | mov ebx, apps.path2 |
||
595 | cmp byte[ebx], '-' |
||
596 | jne @f |
||
597 | ;cmp byte[ebx+1], 0 |
||
598 | ;jne @f |
||
599 | mov byte[ebx], 0 |
||
600 | @@: |
||
601 | mov ebx, apps.path3 |
||
602 | cmp byte[ebx], '-' |
||
603 | jne @f |
||
604 | ;cmp byte[ebx+1], 0 |
||
605 | ;jne @f |
||
606 | mov byte[ebx], 0 |
||
607 | @@: |
||
608 | mov ebx, apps.path4 |
||
609 | cmp byte[ebx], '-' |
||
610 | jne @f |
||
611 | ;cmp byte[ebx+1], 0 |
||
612 | ;jne @f |
||
613 | mov byte[ebx], 0 |
||
614 | @@: |
||
615 | pop ebx eax |
||
616 | ret |
||
617 | |||
618 | |||
619 | checkAdr: |
||
620 | push eax ebx |
||
621 | xor eax, eax |
||
622 | |||
623 | mov ebx, apps.path1 |
||
624 | cmp byte[ebx], '-' |
||
625 | jne @f |
||
626 | inc eax |
||
627 | @@: |
||
628 | mov ebx, apps.path2 |
||
629 | cmp byte[ebx], '-' |
||
630 | jne @f |
||
631 | add eax, 2 |
||
632 | @@: |
||
633 | mov ebx, apps.path3 |
||
634 | cmp byte[ebx], '-' |
||
635 | jne @f |
||
636 | add eax, 4 |
||
637 | @@: |
||
638 | mov ebx, apps.path4 |
||
639 | cmp byte[ebx], '-' |
||
640 | jne @f |
||
641 | add eax, 8 |
||
642 | @@: |
||
643 | |||
644 | mov ebx, apps.param1 |
||
645 | cmp byte[ebx], '-' |
||
646 | jne @f |
||
647 | add eax, 16 |
||
648 | @@: |
||
649 | mov ebx, apps.param2 |
||
650 | cmp byte[ebx], '-' |
||
651 | jne @f |
||
652 | add eax, 32 |
||
653 | @@: |
||
654 | mov ebx, apps.param3 |
||
655 | cmp byte[ebx], '-' |
||
656 | jne @f |
||
657 | add eax, 64 |
||
658 | @@: |
||
659 | mov ebx, apps.param4 |
||
660 | cmp byte[ebx], '-' |
||
661 | jne @f |
||
662 | add eax, 128 |
||
663 | @@: |
||
664 | |||
665 | mov byte[apps.bits], al |
||
666 | pop ebx eax |
||
667 | ret |
||
668 | |||
669 | |||
670 | |||
671 | ;преобразование строки в целое число |
||
672 | strToInteger: ;вход: esi - указатель на строку с десятичной записью числа, выход: eсx - число |
||
673 | push eax ebx edx edi |
||
674 | xor eax, eax ;обнуляем eax |
||
675 | xor ecx, ecx |
||
676 | mov edi, esi |
||
677 | .get_last_symbol: |
||
678 | ;читаем очередной символ |
||
679 | mov al, byte[edi] |
||
680 | |||
681 | ;если это ноль, то строка закончилась |
||
682 | cmp al, 0 |
||
683 | je @f |
||
684 | |||
685 | ;иначе переходим на следующий символ |
||
686 | inc edi |
||
687 | jmp .get_last_symbol |
||
688 | @@: ;дошли до последнего символа и кладём адрес на него в edi |
||
689 | dec edi |
||
690 | |||
691 | cmp edi, esi ;адрес последнего символа должен быть дальше адреса первого символа |
||
692 | jae @f |
||
693 | jmp .error ;иначе ошибка |
||
694 | @@: |
||
695 | ;теперь в edi последний символ, а esi указывает на начало строки (на первй символ строки) |
||
696 | mov cl, byte[edi] |
||
697 | sub cl, 48 ;0x30 ;'0' |
||
698 | dec edi ;переходим на след символ от конца |
||
699 | mov ebx, 10 ;множитель степени |
||
700 | .tranform_cicle: |
||
701 | cmp edi, esi ;если больше нет символов строке, то число преобразовали - выходим |
||
702 | jb .end |
||
703 | |||
704 | mov eax, 0 |
||
705 | mov al, byte[edi] |
||
706 | sub al, 48 ;'0' |
||
707 | cmp al, 9 ;0x39 ;если число больше 9, то видимо в строке было что-то не так |
||
708 | ja .error |
||
709 | cmp al, 0 ;0x30 ;если число меньше 0, то видимо в строке было что-то не так |
||
710 | jb .error |
||
711 | mov edx, 0 |
||
712 | mul ebx |
||
713 | |||
714 | add ecx, eax |
||
715 | |||
716 | dec edi |
||
717 | mov edx, 0 |
||
718 | mov eax, 10 |
||
719 | mul ebx |
||
720 | mov ebx, eax |
||
721 | jmp .tranform_cicle |
||
722 | .error: |
||
723 | mov ecx, 0 |
||
724 | .end: |
||
725 | pop edi edx ebx eax |
||
726 | ret |
||
727 | |||
728 | |||
7389 | theonlymir | 729 | ;Вынести код ниже в отдельный общий модуль |
730 | selfName db '@HOTANGLES',0 |
||
731 | selfNameSize = 10 ;до 11 byte |
||
732 | ; |
||
733 | compareBytes: |
||
734 | push edi esi ecx ebx |
||
7436 | theonlymir | 735 | xor eax, eax |
7389 | theonlymir | 736 | mov ecx, selfNameSize ;max размер строк 11 |
737 | @@: |
||
738 | mov bl, byte[edi] |
||
739 | cmp bl, byte[esi] |
||
740 | jne compareBytes.no |
||
741 | inc edi |
||
742 | inc esi |
||
743 | cmp ecx, 0 |
||
744 | je @f |
||
745 | dec ecx |
||
746 | jmp @b |
||
747 | .no: |
||
748 | mov eax, 1 |
||
749 | @@: |
||
750 | pop ebx ecx esi edi |
||
751 | ret |
||
752 | ; |
||
753 | copyKill: |
||
754 | push eax ebx ecx esi edi |
||
755 | |||
756 | ;сперва прочтём свою информацию |
||
757 | mcall 9, buf, -1 |
||
758 | mov eax, dword[buf+30] |
||
759 | mov dword[selfPID], eax |
||
760 | |||
761 | ;указатели, которые никогда не меняются: |
||
762 | mov esi, selfName ;первая строка - имя текущего приложения |
||
763 | mov edi, buf ;вторая строка - имя текущего слота |
||
764 | add edi, 10 |
||
765 | |||
766 | mov ecx, 1 |
||
767 | @@: |
||
768 | mcall 9, buf, ecx |
||
769 | mov dword[slotMax], eax |
||
770 | |||
771 | ;если это мы сами, то пропускаем проверку |
||
772 | mov eax, dword[buf+30] |
||
773 | cmp eax, dword[selfPID] |
||
774 | je copyKill.propusk |
||
775 | |||
776 | call compareBytes ;сравниваем 11 байт строк, результат в eax |
||
777 | |||
778 | cmp eax, 0 |
||
779 | je copyKill.selfKill |
||
780 | |||
781 | .propusk: |
||
782 | inc ecx |
||
783 | cmp ecx, dword[slotMax] |
||
784 | ja @f |
||
785 | jmp @b |
||
786 | |||
787 | .selfKill: |
||
788 | pop edi esi ecx ebx eax |
||
789 | mcall -1 |
||
790 | ret |
||
791 | @@: |
||
792 | pop edi esi ecx ebx eax |
||
793 | ret |
||
794 | |||
795 | |||
7443 | theonlymir | 796 | ;MODE 3 |
797 | init03: |
||
7459 | theonlymir | 798 | ;mov dword[radius2], 100; 10*10 |
7443 | theonlymir | 799 | mov dword[backAdr], mode03 |
800 | call setHotKey |
||
801 | mode03: |
||
802 | mcall 10 |
||
803 | cmp eax, 2 ;обработка нажатия клавиши |
||
804 | je hotkey |
||
805 | |||
806 | ;cmp byte[keyState], 0 |
||
807 | ;je mode03 |
||
808 | cmp eax, 6 ;обработка перемещений и нажатия мыши |
||
809 | je mouse03 |
||
810 | |||
811 | jmp mode03 |
||
812 | |||
813 | mouse03: |
||
814 | cmp byte[keyState], 0 ;если клавиша не зажата, то обновим начальные координаты |
||
815 | je mouse03.updateCoord |
||
816 | |||
817 | cmp byte[state], LOCKd ;если угол заблокирован, то обновим начальные координаты |
||
818 | je mouse03.updateCoord |
||
819 | |||
7459 | theonlymir | 820 | cmp byte[state], SUPERLOCKd ;если действие было выполнено и получили блокировку, то ждём отпускания клавиши активации |
821 | je @f |
||
822 | |||
7443 | theonlymir | 823 | call checkPointInCircle ;иначе если преодолели радиус активации, то вызываем действие нужного угла |
824 | jmp @f |
||
825 | .updateCoord: |
||
826 | push eax ebx |
||
827 | mcall 37, 0 ;запоминаем текущие(начальные) координаты мыши |
||
828 | ;mov dword[o.x], eax |
||
829 | mov word[o.y], ax |
||
830 | shr eax, 16 |
||
831 | mov word[o.x], ax |
||
832 | pop ebx eax |
||
833 | @@: |
||
834 | jmp dword[backAdr] |
||
835 | |||
836 | |||
837 | radius2 dd 0 ;квадрат радиуса для mode 3 |
||
838 | o: ;координаты начальной и текущей точки |
||
839 | .x: dw 0 |
||
840 | .y: dw 0 |
||
841 | .cx: dw 0 |
||
842 | .cy: dw 0 |
||
843 | |||
844 | ;проверка выхода за пределы круга |
||
845 | ; sqrt( (x2-x1)^2 + (y2-y1)^2 ) <= radius |
||
846 | ; (x2-x1)^2 + (y2-y1)^2 <= radius^2 |
||
847 | checkPointInCircle: |
||
848 | push eax ebx ecx edx |
||
849 | mcall 37, 0 ;получаем текущие координаты мыши |
||
850 | ;mov dword[o.cx], eax |
||
851 | mov word[o.cy], ax |
||
852 | shr eax, 16 |
||
853 | mov word[o.cx], ax |
||
854 | |||
855 | xor eax, eax |
||
856 | xor edx, edx |
||
857 | mov ax, word[o.x] |
||
858 | mov dx, word[o.cx] |
||
859 | cmp dx, ax |
||
860 | jae @f |
||
861 | sub ax, dx |
||
862 | mov dx, ax |
||
863 | jmp .xend |
||
864 | @@: |
||
865 | sub dx, ax |
||
866 | .xend: |
||
867 | mov eax, edx |
||
868 | mul dx |
||
869 | |||
870 | mov ebx, eax |
||
871 | |||
872 | xor eax, eax |
||
873 | xor edx, edx |
||
874 | mov ax, word[o.y] |
||
875 | mov dx, word[o.cy] |
||
876 | cmp dx, ax |
||
877 | jae @f |
||
878 | sub ax, dx |
||
879 | mov dx, ax |
||
880 | jmp .yend |
||
881 | @@: |
||
882 | sub dx, ax |
||
883 | .yend: |
||
884 | mov eax, edx |
||
885 | mul dx |
||
886 | |||
887 | add ebx, eax |
||
888 | |||
889 | cmp ebx, dword[radius2] |
||
890 | jbe @f |
||
891 | call activateCorner ;иначе активируем нужный угол |
||
892 | @@: |
||
893 | pop edx ecx ebx eax |
||
894 | ret |
||
895 | |||
896 | ;выяснить в сторону какого угла ушли и активировать его |
||
897 | activateCorner: |
||
898 | push eax ecx |
||
899 | xor eax, eax |
||
900 | |||
901 | mov ax, word[o.cx] |
||
902 | cmp ax, word[o.x] |
||
903 | je activateCorner.end ;если координата равна, то выходим (такого быть не должно) |
||
904 | ja activateCorner.right |
||
905 | |||
906 | ;иначе левая сторона |
||
907 | mov ax, word[o.cy] |
||
908 | cmp ax, word[o.y] |
||
909 | je activateCorner.end ;если координата равна, то выходим (такого быть не должно) |
||
910 | jb activateCorner.leftup |
||
911 | |||
912 | ;иначе левый нижний угол |
||
913 | mov ecx, 1 |
||
914 | call run_command |
||
915 | mov byte[keyState], 0 |
||
7459 | theonlymir | 916 | mov byte[state], SUPERLOCKd |
7443 | theonlymir | 917 | jmp activateCorner.end |
918 | |||
919 | .leftup: |
||
920 | ;левый верхний угол |
||
921 | mov ecx, 0 |
||
922 | call run_command |
||
923 | mov byte[keyState], 0 |
||
7459 | theonlymir | 924 | mov byte[state], SUPERLOCKd |
7443 | theonlymir | 925 | jmp activateCorner.end |
926 | |||
927 | .right: ;правая сторона экрана |
||
928 | mov ax, word[o.cy] |
||
929 | cmp ax, word[o.y] |
||
930 | je activateCorner.end ;если координата равна, то выходим (такого быть не должно) |
||
931 | jb activateCorner.rightup |
||
932 | |||
933 | ;иначе правый нижний угол |
||
934 | mov ecx, 3 |
||
935 | call run_command |
||
936 | mov byte[keyState], 0 |
||
7459 | theonlymir | 937 | mov byte[state], SUPERLOCKd |
7443 | theonlymir | 938 | jmp activateCorner.end |
939 | |||
940 | .rightup: |
||
941 | ;правый верхний угол |
||
942 | mov ecx, 2 |
||
943 | call run_command |
||
944 | mov byte[keyState], 0 |
||
7459 | theonlymir | 945 | mov byte[state], SUPERLOCKd |
7443 | theonlymir | 946 | jmp activateCorner.end |
947 | |||
948 | .end: |
||
949 | pop ecx eax |
||
950 | ret |
||
951 | |||
952 | |||
953 | |||
7436 | theonlymir | 954 | keyActivate db 41 ;16 ;'Q' ;клавиша активации |
7443 | theonlymir | 955 | keyState db 0 ;0-клавиша не активна, 1 - клавиша активна |
7389 | theonlymir | 956 | |
7443 | theonlymir | 957 | backAdr rd 1 ;адрес для возврата из проверки мыши |
7436 | theonlymir | 958 | slotMax rd 1 |
959 | selfPID rd 1 |
||
960 | buf rb 1024 |
||
961 | |||
962 | ;структурка данных для хранения параметров экрана |
||
963 | screen: |
||
7443 | theonlymir | 964 | .width rw 1 |
965 | .height rw 1 |
||
7436 | theonlymir | 966 | |
7459 | theonlymir | 967 | state: rb 1 ;состояние: 0=unlock, 1=lock, 2=superlock for mode 3 |
7436 | theonlymir | 968 | mode: rb 1 ;режим работы приложения: 0=не работает, 1=классический, 2=по горячей клавише |
969 | |||
970 | |||
7459 | theonlymir | 971 | keystr: rb 4 ;строка со значением сканкода активационной клавиши |
972 | radstr: rb 5 ;строка со значением радиуса |
||
973 | apps: |
||
974 | .bits: rb 1 |
||
975 | .path1: rb 512 |
||
976 | .path2: rb 512 |
||
977 | .path3: rb 512 |
||
978 | .path4: rb 512 |
||
979 | .param1: rb 512 |
||
980 | .param2: rb 512 |
||
981 | .param3: rb 512 |
||
982 | .param4: rb 512 |
||
983 | appsEnd: |
||
984 | |||
985 | |||
7389 | theonlymir | 986 | I_END:=>=> |