Rev 7460 | 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 |
||
7460 | theonlymir | 253 | mov eax, apps.path1 |
7459 | theonlymir | 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 |
||
7460 | theonlymir | 263 | mov eax, apps.path2 |
7459 | theonlymir | 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 |
||
7460 | theonlymir | 273 | mov eax, apps.path3 |
7459 | theonlymir | 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 |
7460 | theonlymir | 283 | mov eax, apps.path4 |
7459 | theonlymir | 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 |
||
7461 | theonlymir | 393 | cmp byte[esi], 9 ;tab |
7459 | theonlymir | 394 | je trim |
7461 | theonlymir | 395 | cmp byte[esi], 32 ;space |
7459 | theonlymir | 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 | |
7460 | theonlymir | 478 | ;проверим строки на '-' |
7459 | theonlymir | 479 | call checkPathAdr |
7389 | theonlymir | 480 | |
7459 | theonlymir | 481 | pop edi esi |
482 | |||
483 | ;пропускаем строку с именем клавиши |
||
484 | call gotoEndString |
||
485 | call gotoStartString |
||
486 | |||
487 | ;считываем сканкод активационной клавиши |
||
488 | push esi edi ecx |
||
489 | mov esi, keystr |
||
490 | mov edi, keystr |
||
491 | call readPath |
||
492 | ;преобразуем строку в число |
||
493 | mov esi, keystr |
||
494 | call strToInteger |
||
495 | mov byte[keyActivate], cl |
||
496 | pop ecx edi esi |
||
497 | call gotoStartString |
||
498 | |||
499 | ;считываем радиус |
||
500 | push esi edi ecx |
||
501 | mov esi, radstr |
||
502 | mov edi, radstr |
||
503 | call readPath |
||
504 | ;преобразуем строку в число |
||
505 | mov esi, radstr |
||
506 | call strToInteger |
||
507 | ;теперь ecx - значение радиуса |
||
508 | ;!!! добавить проверку, чтобы число не было больше области экрана |
||
509 | ;нас интересует квадрат числа |
||
510 | push eax edx |
||
511 | mov eax, ecx ;dword[radius2] |
||
512 | mul ecx |
||
513 | mov dword[radius2], eax |
||
514 | pop edx eax |
||
515 | |||
516 | pop ecx edi esi |
||
517 | |||
518 | ;считывать размер элементов интерфейса нам не нужно (пока что этот параметр только для конфига) |
||
519 | jmp .end |
||
7389 | theonlymir | 520 | .exit: |
7416 | theonlymir | 521 | pop edx ecx ebx eax |
7389 | theonlymir | 522 | mcall -1 ;закрыть эту программу |
523 | .end: |
||
7459 | theonlymir | 524 | mov ecx, dword[cfgFileAdr] ;если файл был загружен, то |
525 | cmp ecx, 0 |
||
526 | je @f |
||
527 | mcall 68, 13, ecx ;выгружаем файл из памяти |
||
528 | @@: |
||
7416 | theonlymir | 529 | pop edx ecx ebx eax |
7389 | theonlymir | 530 | ret |
531 | |||
532 | |||
7459 | theonlymir | 533 | checkPathAdr: |
534 | push eax ebx |
||
535 | xor eax, eax |
||
536 | |||
537 | mov ebx, apps.path1 |
||
538 | cmp byte[ebx], '-' |
||
539 | jne @f |
||
540 | ;cmp byte[ebx+1], 0 |
||
541 | ;jne @f |
||
542 | mov byte[ebx], 0 |
||
543 | @@: |
||
544 | mov ebx, apps.path2 |
||
545 | cmp byte[ebx], '-' |
||
546 | jne @f |
||
547 | ;cmp byte[ebx+1], 0 |
||
548 | ;jne @f |
||
549 | mov byte[ebx], 0 |
||
550 | @@: |
||
551 | mov ebx, apps.path3 |
||
552 | cmp byte[ebx], '-' |
||
553 | jne @f |
||
554 | ;cmp byte[ebx+1], 0 |
||
555 | ;jne @f |
||
556 | mov byte[ebx], 0 |
||
557 | @@: |
||
558 | mov ebx, apps.path4 |
||
559 | cmp byte[ebx], '-' |
||
560 | jne @f |
||
561 | ;cmp byte[ebx+1], 0 |
||
562 | ;jne @f |
||
563 | mov byte[ebx], 0 |
||
564 | @@: |
||
565 | pop ebx eax |
||
566 | ret |
||
567 | |||
568 | ;преобразование строки в целое число |
||
569 | strToInteger: ;вход: esi - указатель на строку с десятичной записью числа, выход: eсx - число |
||
570 | push eax ebx edx edi |
||
571 | xor eax, eax ;обнуляем eax |
||
572 | xor ecx, ecx |
||
573 | mov edi, esi |
||
574 | .get_last_symbol: |
||
575 | ;читаем очередной символ |
||
576 | mov al, byte[edi] |
||
577 | |||
578 | ;если это ноль, то строка закончилась |
||
579 | cmp al, 0 |
||
580 | je @f |
||
581 | |||
582 | ;иначе переходим на следующий символ |
||
583 | inc edi |
||
584 | jmp .get_last_symbol |
||
585 | @@: ;дошли до последнего символа и кладём адрес на него в edi |
||
586 | dec edi |
||
587 | |||
588 | cmp edi, esi ;адрес последнего символа должен быть дальше адреса первого символа |
||
589 | jae @f |
||
590 | jmp .error ;иначе ошибка |
||
591 | @@: |
||
592 | ;теперь в edi последний символ, а esi указывает на начало строки (на первй символ строки) |
||
593 | mov cl, byte[edi] |
||
594 | sub cl, 48 ;0x30 ;'0' |
||
595 | dec edi ;переходим на след символ от конца |
||
596 | mov ebx, 10 ;множитель степени |
||
597 | .tranform_cicle: |
||
598 | cmp edi, esi ;если больше нет символов строке, то число преобразовали - выходим |
||
599 | jb .end |
||
600 | |||
601 | mov eax, 0 |
||
602 | mov al, byte[edi] |
||
603 | sub al, 48 ;'0' |
||
604 | cmp al, 9 ;0x39 ;если число больше 9, то видимо в строке было что-то не так |
||
605 | ja .error |
||
606 | cmp al, 0 ;0x30 ;если число меньше 0, то видимо в строке было что-то не так |
||
607 | jb .error |
||
608 | mov edx, 0 |
||
609 | mul ebx |
||
610 | |||
611 | add ecx, eax |
||
612 | |||
613 | dec edi |
||
614 | mov edx, 0 |
||
615 | mov eax, 10 |
||
616 | mul ebx |
||
617 | mov ebx, eax |
||
618 | jmp .tranform_cicle |
||
619 | .error: |
||
620 | mov ecx, 0 |
||
621 | .end: |
||
622 | pop edi edx ebx eax |
||
623 | ret |
||
624 | |||
625 | |||
7389 | theonlymir | 626 | ;Вынести код ниже в отдельный общий модуль |
627 | selfName db '@HOTANGLES',0 |
||
628 | selfNameSize = 10 ;до 11 byte |
||
629 | ; |
||
630 | compareBytes: |
||
631 | push edi esi ecx ebx |
||
7436 | theonlymir | 632 | xor eax, eax |
7389 | theonlymir | 633 | mov ecx, selfNameSize ;max размер строк 11 |
634 | @@: |
||
635 | mov bl, byte[edi] |
||
636 | cmp bl, byte[esi] |
||
637 | jne compareBytes.no |
||
638 | inc edi |
||
639 | inc esi |
||
640 | cmp ecx, 0 |
||
641 | je @f |
||
642 | dec ecx |
||
643 | jmp @b |
||
644 | .no: |
||
645 | mov eax, 1 |
||
646 | @@: |
||
647 | pop ebx ecx esi edi |
||
648 | ret |
||
649 | ; |
||
650 | copyKill: |
||
651 | push eax ebx ecx esi edi |
||
652 | |||
653 | ;сперва прочтём свою информацию |
||
654 | mcall 9, buf, -1 |
||
655 | mov eax, dword[buf+30] |
||
656 | mov dword[selfPID], eax |
||
657 | |||
658 | ;указатели, которые никогда не меняются: |
||
659 | mov esi, selfName ;первая строка - имя текущего приложения |
||
660 | mov edi, buf ;вторая строка - имя текущего слота |
||
661 | add edi, 10 |
||
662 | |||
663 | mov ecx, 1 |
||
664 | @@: |
||
665 | mcall 9, buf, ecx |
||
666 | mov dword[slotMax], eax |
||
667 | |||
668 | ;если это мы сами, то пропускаем проверку |
||
669 | mov eax, dword[buf+30] |
||
670 | cmp eax, dword[selfPID] |
||
671 | je copyKill.propusk |
||
672 | |||
673 | call compareBytes ;сравниваем 11 байт строк, результат в eax |
||
674 | |||
675 | cmp eax, 0 |
||
676 | je copyKill.selfKill |
||
677 | |||
678 | .propusk: |
||
679 | inc ecx |
||
680 | cmp ecx, dword[slotMax] |
||
681 | ja @f |
||
682 | jmp @b |
||
683 | |||
684 | .selfKill: |
||
685 | pop edi esi ecx ebx eax |
||
686 | mcall -1 |
||
687 | ret |
||
688 | @@: |
||
689 | pop edi esi ecx ebx eax |
||
690 | ret |
||
691 | |||
692 | |||
7443 | theonlymir | 693 | ;MODE 3 |
694 | init03: |
||
7459 | theonlymir | 695 | ;mov dword[radius2], 100; 10*10 |
7443 | theonlymir | 696 | mov dword[backAdr], mode03 |
697 | call setHotKey |
||
698 | mode03: |
||
699 | mcall 10 |
||
700 | cmp eax, 2 ;обработка нажатия клавиши |
||
701 | je hotkey |
||
702 | |||
703 | ;cmp byte[keyState], 0 |
||
704 | ;je mode03 |
||
705 | cmp eax, 6 ;обработка перемещений и нажатия мыши |
||
706 | je mouse03 |
||
707 | |||
708 | jmp mode03 |
||
709 | |||
710 | mouse03: |
||
711 | cmp byte[keyState], 0 ;если клавиша не зажата, то обновим начальные координаты |
||
712 | je mouse03.updateCoord |
||
713 | |||
714 | cmp byte[state], LOCKd ;если угол заблокирован, то обновим начальные координаты |
||
715 | je mouse03.updateCoord |
||
716 | |||
7459 | theonlymir | 717 | cmp byte[state], SUPERLOCKd ;если действие было выполнено и получили блокировку, то ждём отпускания клавиши активации |
718 | je @f |
||
719 | |||
7443 | theonlymir | 720 | call checkPointInCircle ;иначе если преодолели радиус активации, то вызываем действие нужного угла |
721 | jmp @f |
||
722 | .updateCoord: |
||
723 | push eax ebx |
||
724 | mcall 37, 0 ;запоминаем текущие(начальные) координаты мыши |
||
725 | ;mov dword[o.x], eax |
||
726 | mov word[o.y], ax |
||
727 | shr eax, 16 |
||
728 | mov word[o.x], ax |
||
729 | pop ebx eax |
||
730 | @@: |
||
731 | jmp dword[backAdr] |
||
732 | |||
733 | |||
734 | radius2 dd 0 ;квадрат радиуса для mode 3 |
||
735 | o: ;координаты начальной и текущей точки |
||
736 | .x: dw 0 |
||
737 | .y: dw 0 |
||
738 | .cx: dw 0 |
||
739 | .cy: dw 0 |
||
740 | |||
741 | ;проверка выхода за пределы круга |
||
742 | ; sqrt( (x2-x1)^2 + (y2-y1)^2 ) <= radius |
||
743 | ; (x2-x1)^2 + (y2-y1)^2 <= radius^2 |
||
744 | checkPointInCircle: |
||
745 | push eax ebx ecx edx |
||
746 | mcall 37, 0 ;получаем текущие координаты мыши |
||
747 | ;mov dword[o.cx], eax |
||
748 | mov word[o.cy], ax |
||
749 | shr eax, 16 |
||
750 | mov word[o.cx], ax |
||
751 | |||
752 | xor eax, eax |
||
753 | xor edx, edx |
||
754 | mov ax, word[o.x] |
||
755 | mov dx, word[o.cx] |
||
756 | cmp dx, ax |
||
757 | jae @f |
||
758 | sub ax, dx |
||
759 | mov dx, ax |
||
760 | jmp .xend |
||
761 | @@: |
||
762 | sub dx, ax |
||
763 | .xend: |
||
764 | mov eax, edx |
||
765 | mul dx |
||
766 | |||
767 | mov ebx, eax |
||
768 | |||
769 | xor eax, eax |
||
770 | xor edx, edx |
||
771 | mov ax, word[o.y] |
||
772 | mov dx, word[o.cy] |
||
773 | cmp dx, ax |
||
774 | jae @f |
||
775 | sub ax, dx |
||
776 | mov dx, ax |
||
777 | jmp .yend |
||
778 | @@: |
||
779 | sub dx, ax |
||
780 | .yend: |
||
781 | mov eax, edx |
||
782 | mul dx |
||
783 | |||
784 | add ebx, eax |
||
785 | |||
786 | cmp ebx, dword[radius2] |
||
787 | jbe @f |
||
788 | call activateCorner ;иначе активируем нужный угол |
||
789 | @@: |
||
790 | pop edx ecx ebx eax |
||
791 | ret |
||
792 | |||
793 | ;выяснить в сторону какого угла ушли и активировать его |
||
794 | activateCorner: |
||
795 | push eax ecx |
||
796 | xor eax, eax |
||
797 | |||
798 | mov ax, word[o.cx] |
||
799 | cmp ax, word[o.x] |
||
800 | je activateCorner.end ;если координата равна, то выходим (такого быть не должно) |
||
801 | ja activateCorner.right |
||
802 | |||
803 | ;иначе левая сторона |
||
804 | mov ax, word[o.cy] |
||
805 | cmp ax, word[o.y] |
||
806 | je activateCorner.end ;если координата равна, то выходим (такого быть не должно) |
||
807 | jb activateCorner.leftup |
||
808 | |||
809 | ;иначе левый нижний угол |
||
810 | mov ecx, 1 |
||
811 | call run_command |
||
812 | mov byte[keyState], 0 |
||
7459 | theonlymir | 813 | mov byte[state], SUPERLOCKd |
7443 | theonlymir | 814 | jmp activateCorner.end |
815 | |||
816 | .leftup: |
||
817 | ;левый верхний угол |
||
818 | mov ecx, 0 |
||
819 | call run_command |
||
820 | mov byte[keyState], 0 |
||
7459 | theonlymir | 821 | mov byte[state], SUPERLOCKd |
7443 | theonlymir | 822 | jmp activateCorner.end |
823 | |||
824 | .right: ;правая сторона экрана |
||
825 | mov ax, word[o.cy] |
||
826 | cmp ax, word[o.y] |
||
827 | je activateCorner.end ;если координата равна, то выходим (такого быть не должно) |
||
828 | jb activateCorner.rightup |
||
829 | |||
830 | ;иначе правый нижний угол |
||
831 | mov ecx, 3 |
||
832 | call run_command |
||
833 | mov byte[keyState], 0 |
||
7459 | theonlymir | 834 | mov byte[state], SUPERLOCKd |
7443 | theonlymir | 835 | jmp activateCorner.end |
836 | |||
837 | .rightup: |
||
838 | ;правый верхний угол |
||
839 | mov ecx, 2 |
||
840 | call run_command |
||
841 | mov byte[keyState], 0 |
||
7459 | theonlymir | 842 | mov byte[state], SUPERLOCKd |
7443 | theonlymir | 843 | jmp activateCorner.end |
844 | |||
845 | .end: |
||
846 | pop ecx eax |
||
847 | ret |
||
848 | |||
849 | |||
850 | |||
7436 | theonlymir | 851 | keyActivate db 41 ;16 ;'Q' ;клавиша активации |
7443 | theonlymir | 852 | keyState db 0 ;0-клавиша не активна, 1 - клавиша активна |
7389 | theonlymir | 853 | |
7443 | theonlymir | 854 | backAdr rd 1 ;адрес для возврата из проверки мыши |
7436 | theonlymir | 855 | slotMax rd 1 |
856 | selfPID rd 1 |
||
857 | buf rb 1024 |
||
858 | |||
859 | ;структурка данных для хранения параметров экрана |
||
860 | screen: |
||
7443 | theonlymir | 861 | .width rw 1 |
862 | .height rw 1 |
||
7436 | theonlymir | 863 | |
7459 | theonlymir | 864 | state: rb 1 ;состояние: 0=unlock, 1=lock, 2=superlock for mode 3 |
7436 | theonlymir | 865 | mode: rb 1 ;режим работы приложения: 0=не работает, 1=классический, 2=по горячей клавише |
866 | |||
867 | |||
7459 | theonlymir | 868 | keystr: rb 4 ;строка со значением сканкода активационной клавиши |
869 | radstr: rb 5 ;строка со значением радиуса |
||
870 | apps: |
||
871 | .path1: rb 512 |
||
872 | .path2: rb 512 |
||
873 | .path3: rb 512 |
||
874 | .path4: rb 512 |
||
875 | .param1: rb 512 |
||
876 | .param2: rb 512 |
||
877 | .param3: rb 512 |
||
878 | .param4: rb 512 |
||
879 | appsEnd: |
||
880 | |||
881 | |||
7389 | theonlymir | 882 | I_END:=>=> |