Subversion Repositories Kolibri OS

Rev

Rev 7459 | 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  nor the names of its contributors may
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
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
 
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: