Subversion Repositories Kolibri OS

Rev

Rev 7436 | 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
7443 theonlymir 5
; Version 0.3.6: Oct 9, 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
7389 theonlymir 34
 
35
; заголовок
36
db 'MENUET01'     ;магический идентификатор
37
dd 0x01           ;версия
7436 theonlymir 38
dd START_DEBUG    ;адрес точки старта программы
7389 theonlymir 39
dd I_END          ;адрес конца, по факту размер файла программы
40
dd 0x100000       ;требуемое кол-во памяти для загрузки программы
41
dd 0x7fff0        ;начальное значение регистра esp - адрес конца области стэка так как стэк растет в сторону меньших адресов
42
dd 0, 0           ;адрес строки параметров и адрес строки пути исполняемого файла
43
 
44
 
45
include '../../macros.inc'
46
 
47
START_DEBUG:
48
   call copyKill         ;простейшая защита от повторного запуска
49
   mcall  68, 11         ;инициализация кучи
50
   call loadConfig       ;загружаем конфигурацию приложения
7436 theonlymir 51
 
52
   cmp byte[mode], 0     ;функция отключена - выход
53
   jne @f
54
   mcall -1
55
@@:
7443 theonlymir 56
   ;режим жеста по горячей клавише?
57
   cmp byte[mode], 3 ;подписываемся на интересные нам события в зависимости от режима работы
58
   jne @f
59
   mov ebx, 00000100000000000000000000100010b    ;если да, то подписываемся на клавиши
60
   mcall 40
61
   jmp init03
62
@@:
7436 theonlymir 63
   ;режим активации горячей клавишей?
64
   cmp byte[mode], 2 ;подписываемся на интересные нам события в зависимости от режима работы
65
   jne @f
66
   mov ebx, 00000100000000000000000000100010b    ;если да, то подписываемся на клавиши
7389 theonlymir 67
   mcall 40
7436 theonlymir 68
   jmp init02
69
@@:
70
   ; во всех остальных случаях - классический режим работы
71
   ;mode=1 классический режим работы - реакция при наведении в угол
72
   mov byte[mode], 1
73
   mov ebx, 00000100000000000000000000100000b
74
   mcall 40
75
   jmp init01
7389 theonlymir 76
 
7436 theonlymir 77
 
78
 
79
init02:
80
   mov dword[backAdr], mode02
81
   call setHotKey
82
mode02:
83
   mcall 10
84
   cmp eax, 2     ;обработка нажатия клавиши
85
   je hotkey
86
 
87
   cmp byte[keyState], 0
88
   je mode02
89
   cmp   eax, 6   ;обработка перемещений и нажатия мыши
90
   je    mouse
91
 
92
   jmp mode02
93
 
94
 
95
setHotKey:    ;установить горячую клавишу
96
   push eax ebx ecx edx
97
   xor ecx, ecx
98
   mov cl, byte[keyActivate]  ;нажатие горячей клавиши
99
   mov edx, 0x000
100
   mcall 66, 4, ecx, edx
101
 
102
   ;mov cl, byte[keyActivate]
103
   add cl, 128              ;отпускание горячей клавиши
104
   ;mov edx, 0x000
105
   mcall 66, 4, ecx, edx
106
   pop edx ecx ebx eax
107
   ret
108
 
109
 
110
hotkey:
111
   mcall 2
112
   cmp eax, 1     ;буфер клавиш пуст?
113
   je hotkey.end
114
 
115
   cmp al, 2      ;нас интересует только скан код горячей клавиши, иначе выходим
116
   jne hotkey.end
117
 
118
   cmp ah, byte[keyActivate]   ;если нажата наша горячая клавиша
119
   jne @f
7443 theonlymir 120
 
121
;for mode 3 [
122
   cmp byte[keyState], 1
123
   je hotkey.e
124
 
125
   push eax ebx
126
   mcall 37, 0 ;запоминаем текущие(начальные) координаты мыши
127
   ;mov dword[o.x], eax
128
   mov word[o.y], ax
129
   shr eax, 16
130
   mov word[o.x], ax
131
   pop ebx eax
132
 
7436 theonlymir 133
   mov byte[keyState], 1
134
   mov byte[state], UNLOCKd
7443 theonlymir 135
.e:
136
;]
137
   ;mov byte[state], UNLOCKd
7436 theonlymir 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
146
   ;mov ecx, 0  ;строки для отладки и теста
147
   ;call run_command
148
   mov byte[keyState], 0
149
   mov byte[state], LOCKd
150
@@:
151
   pop edx
152
.end:
7443 theonlymir 153
   jmp dword[backAdr]
7436 theonlymir 154
 
155
 
156
init01:
157
   mov dword[backAdr], mode01
158
mode01:
7389 theonlymir 159
  mov     eax, 10                 ; function 10 : wait until event
160
  mcall                           ; event type is returned in eax
161
 
162
  cmp   eax, 6           ;обработка перемещений и нажатия мыши
163
  je    mouse
164
 
7436 theonlymir 165
  jmp mode01
7389 theonlymir 166
 
7436 theonlymir 167
 
7389 theonlymir 168
mouse:
7436 theonlymir 169
   push ebx
170
   mcall 37, 0   ;получаем текущие координаты мыши
171
   pop ebx
7389 theonlymir 172
 
173
  cmp eax, 0 ;левый верхний угол
174
  jne @f
175
  ; -- здесь вызываем соотв. вызов для левого верхнего угла  (X=0, Y=0)
176
  push ecx
177
  mov ecx, 0
178
  call run_command
179
  pop ecx
180
 
7436 theonlymir 181
  jmp dword[backAdr] ;finish
7389 theonlymir 182
@@:
183
  call get_screen_size ;иначе обновляем размеры экрана
184
 
185
  cmp ax, word[screen.height]    ;Ymouse = Yscreen ?
186
  je Ytrue
187
  ;если Y не равны, то нас интересует Y=0 и X=ScreenWidth (правый верхний угол)
188
 
189
  cmp ax, 0
190
  jne unlockend
191
  shr eax, 16
192
  cmp ax, word[screen.width]
193
  jne unlockend
194
  ; -- здесь вызываем для правого верхенего угла
195
  push ecx
196
  mov ecx, 2
197
  call run_command
198
  pop ecx
199
 
7436 theonlymir 200
  jmp dword[backAdr]
7389 theonlymir 201
Ytrue:
202
  ;если Y равны, то нас интересует X=0 (левый нижний угол) или X=ScreenWidth (правый нижний)
203
  shr eax, 16
204
  cmp ax, 0
205
  jne @f
206
  ; -- X=0, Y = Height  (левый нижний угол)
207
  push ecx
208
  mov ecx, 1
209
  call run_command
210
  pop ecx
7436 theonlymir 211
  jmp dword[backAdr]
7389 theonlymir 212
@@:
213
  cmp ax, word[screen.width]
214
  jne unlockend
215
  ; -- (правый нижний угол)
216
  push ecx
217
  mov ecx, 3
218
  call run_command
219
  pop ecx
220
 
7436 theonlymir 221
  jmp dword[backAdr]
7389 theonlymir 222
 
223
unlockend:
224
  mov byte[state], UNLOCKd
7436 theonlymir 225
  jmp dword[backAdr]
7389 theonlymir 226
 
227
 
7436 theonlymir 228
 
7389 theonlymir 229
;получить размер экрана
230
get_screen_size:
231
   push eax
232
   mcall 14
233
   ;теперь в eax = [xsize]*65536 + [ysize]
234
   ;mov dword[screen], eax
235
   mov word[screen.height], ax
236
   shr eax, 16
237
   mov word[screen.width], ax
238
   pop eax
239
   ret
240
 
241
 
242
 
243
 
7436 theonlymir 244
 
7389 theonlymir 245
;запуск приложения: ecx - активный угол: lu=0, ld=1, ru=2, rd=3
246
run_command:
247
   cmp byte[state], UNLOCKd
248
   jne run_command.end
249
 
7436 theonlymir 250
;   cmp byte[mode], 2     ;если режим второй
251
;   jne @f
7389 theonlymir 252
 
7436 theonlymir 253
   push eax ebx ecx
7389 theonlymir 254
 
255
   cmp ecx, 0
256
   jne @f
7436 theonlymir 257
   mov eax, dword[newData.lu]
7389 theonlymir 258
   mov dword[struct70.path_adr], eax
259
   jmp .end_set_path
260
@@:
261
   cmp ecx, 1
262
   jne @f
263
   mov eax, dword[newData.ld]
264
   mov dword[struct70.path_adr], eax
265
   jmp .end_set_path
266
@@:
267
   cmp ecx, 2
268
   jne @f
269
   mov eax, dword[newData.ru]
270
   mov dword[struct70.path_adr], eax
271
   jmp .end_set_path
272
@@:
273
   cmp ecx, 3
274
   jne .end_set_path
275
   mov eax, dword[newData.rd]
276
   mov dword[struct70.path_adr], eax
277
   jmp .end_set_path
278
.end_set_path:
279
 
280
   ;параметры
281
   ;mov dword[struct.adr],
282
 
7416 theonlymir 283
;если адрес 0, то ничего не делать
7389 theonlymir 284
   cmp dword[struct70.path_adr], 0
285
   jne .next
7416 theonlymir 286
   ;mov eax, testData.ld
287
   ;mov dword[struct70.path_adr], eax
288
   jmp @f
7389 theonlymir 289
.next:
290
;конец кода для замены
291
 
292
   mcall 70, struct70
7416 theonlymir 293
@@:
7389 theonlymir 294
   mov byte[state], LOCKd
7436 theonlymir 295
   ;mov byte[keyState], 0
7389 theonlymir 296
 
7436 theonlymir 297
   pop ecx ebx eax
7389 theonlymir 298
.end:
299
   ret
300
 
301
struct70: ;Формат информационной структуры
302
  .func       dd 7 ; номер подфункции
303
  .mask       dd 0
304
  .param_adr  dd 0 ; указатель на ASCIIZ-строку с параметрами
305
  .other      dd 0, 0
306
  .path       db 0 ; "/rd/1/TINYPAD",0 ; путь
7416 theonlymir 307
  .path_adr   dd 0 ;testData.lu
7389 theonlymir 308
 
309
;имя конфигурационного файла
7416 theonlymir 310
fileName: db 'SETTINGS/HOTANGLES.CFG', 0
7389 theonlymir 311
 
312
loadConfig:
7416 theonlymir 313
   push eax ebx ecx edx
7389 theonlymir 314
   mcall 68, 27, fileName   ;загружаем конфигурационный файл в ОЗУ
315
   cmp eax, 0
316
   je loadConfig.exit       ;если файла конфигурации нет, то завершаем работу приложения
317
   ;иначе данные загружены в ОЗУ, размер в edx
318
   cmp edx, 0               ;если файл пуст, в нём нет данных, то завершаем работу
319
   je loadConfig.exit
320
 
321
   add edx, eax             ;иначе кладём в edx - адрес конца файла
322
 
7436 theonlymir 323
   mov byte[mode], 0
324
   cmp byte[eax], '0' ;121 ;'y'  ;если параметр активности приложения имеет статус: не активно
325
   je loadConfig.exit      ;то завершаем работу приложения
326
   cmp byte[eax], 110 ;'n'
327
   je loadConfig.exit
7389 theonlymir 328
 
7436 theonlymir 329
   ;иначе выставляем режим
330
   cmp byte[eax], '2'       ;режим активации по горячей клавише
331
   jne @f
332
   mov byte[mode], 2
333
   jmp loadConfig.modeEnd
334
@@:
335
   cmp byte[eax], '3'       ;режим жеста при зажатой клавише
336
   jne @f
337
   mov byte[mode], 3
338
   jmp loadConfig.modeEnd
339
@@:
340
   mov byte[mode], 1        ;во всех остальных случаях - классический режим
341
.modeEnd:
342
 
7389 theonlymir 343
   push edi
344
   push esi
345
   ; сохраняем в edi указатель на начало таблицы адресов наших команд
346
   mov edi, newData
347
   ; сохраняем адреса строк и добавляем 0 в конце
348
   mov esi, eax
349
.block:
350
   inc esi
351
   cmp byte[esi], 10         ;если очередной код символа 10 или 13, то пропускаем символы
352
   je loadConfig.propusk     ;до первого отличного от них
353
   cmp byte[esi], 13
354
   je loadConfig.propusk
355
 
7416 theonlymir 356
   ; символ отличен от переноса строки и возврата каретки - если это на знак минус, то запоминаем его
7389 theonlymir 357
   mov dword[edi], esi
358
   add edi, 4
359
 
360
   ;идём до конца этой строки: пока не встретим очередной 10, 13, 0 или file end
361
.while:
362
   inc esi
363
   cmp esi, edx           ;тут будет проблема - тк файл закончился, а нуля не было !!! исправить
364
   jae loadConfig.fileend
365
   cmp byte[esi], 10
366
   je loadConfig.ura
367
   cmp byte[esi], 0
368
   je loadConfig.ura
369
   cmp byte[esi], 13
370
   jne loadConfig.while
371
.ura:
372
   mov byte[esi], 0
373
 
7416 theonlymir 374
   ;cmp byte[esi-1], '-'
375
   ;jne @f
376
   push esi  ;если это был знак минус, то меняем адрес на ноль
377
   mov esi, dword[edi-4]
378
   cmp byte[esi], '-'
379
   jne @f
380
   cmp byte[esi+1], 0
381
   jne @f
382
   mov dword[edi-4], 0
383
@@:
384
   pop esi
385
 
7389 theonlymir 386
   cmp edi, newDataEnd ;newData.end      ;если вся таблица адресов заполнена, то выходим из цикла
387
   jb loadConfig.block
388
.fileend:
389
 
390
   pop esi
391
   pop edi
392
 
393
   jmp loadConfig.end
394
 
395
.propusk:
396
   mov byte[esi], 0
397
   jmp loadConfig.block
398
.exit:
7416 theonlymir 399
   pop edx ecx ebx eax
7389 theonlymir 400
   mcall -1 ;закрыть эту программу
401
.end:
7416 theonlymir 402
   pop edx ecx ebx eax
7389 theonlymir 403
   ret
404
 
405
 
406
 
407
 
408
;Вынести код ниже в отдельный общий модуль
409
selfName db '@HOTANGLES',0
410
selfNameSize = 10 ;до 11 byte
411
;
412
compareBytes:
413
   push edi esi ecx ebx
7436 theonlymir 414
   xor eax, eax
7389 theonlymir 415
   mov ecx, selfNameSize    ;max размер строк 11
416
@@:
417
   mov bl, byte[edi]
418
   cmp bl, byte[esi]
419
   jne compareBytes.no
420
   inc edi
421
   inc esi
422
   cmp ecx, 0
423
   je @f
424
   dec ecx
425
   jmp @b
426
.no:
427
   mov eax, 1
428
@@:
429
   pop ebx ecx esi edi
430
   ret
431
;
432
copyKill:
433
   push eax ebx ecx esi edi
434
 
435
   ;сперва прочтём свою информацию
436
   mcall 9, buf, -1
437
   mov eax, dword[buf+30]
438
   mov dword[selfPID], eax
439
 
440
   ;указатели, которые никогда не меняются:
441
   mov esi, selfName       ;первая строка - имя текущего приложения
442
   mov edi, buf            ;вторая строка - имя текущего слота
443
   add edi, 10
444
 
445
   mov ecx, 1
446
@@:
447
   mcall 9, buf, ecx
448
   mov dword[slotMax], eax
449
 
450
   ;если это мы сами, то пропускаем проверку
451
   mov eax, dword[buf+30]
452
   cmp eax, dword[selfPID]
453
   je copyKill.propusk
454
 
455
   call compareBytes   ;сравниваем 11 байт строк, результат в eax
456
 
457
   cmp eax, 0
458
   je copyKill.selfKill
459
 
460
.propusk:
461
   inc ecx
462
   cmp ecx, dword[slotMax]
463
   ja @f
464
   jmp @b
465
 
466
.selfKill:
467
   pop edi esi ecx ebx eax
468
   mcall -1
469
   ret
470
@@:
471
   pop edi esi ecx ebx eax
472
   ret
473
 
474
 
7443 theonlymir 475
;MODE 3
476
init03:
477
   mov dword[radius2], 100; 10*10
478
   mov dword[backAdr], mode03
479
   call setHotKey
480
mode03:
481
   mcall 10
482
   cmp eax, 2     ;обработка нажатия клавиши
483
   je hotkey
484
 
485
   ;cmp byte[keyState], 0
486
   ;je mode03
487
   cmp   eax, 6   ;обработка перемещений и нажатия мыши
488
   je    mouse03
489
 
490
   jmp mode03
491
 
492
mouse03:
493
   cmp byte[keyState], 0     ;если клавиша не зажата, то обновим начальные координаты
494
   je mouse03.updateCoord
495
 
496
   cmp byte[state], LOCKd    ;если угол заблокирован, то обновим начальные координаты
497
   je mouse03.updateCoord
498
 
499
   call checkPointInCircle   ;иначе если преодолели радиус активации, то вызываем действие нужного угла
500
   jmp @f
501
.updateCoord:
502
   push eax ebx
503
   mcall 37, 0 ;запоминаем текущие(начальные) координаты мыши
504
   ;mov dword[o.x], eax
505
   mov word[o.y], ax
506
   shr eax, 16
507
   mov word[o.x], ax
508
   pop ebx eax
509
@@:
510
   jmp dword[backAdr]
511
 
512
 
513
radius2 dd 0  ;квадрат радиуса для mode 3
514
o:            ;координаты начальной и текущей точки
515
 .x:   dw 0
516
 .y:   dw 0
517
 .cx:  dw 0
518
 .cy:  dw 0
519
 
520
;проверка выхода за пределы круга
521
; sqrt( (x2-x1)^2 + (y2-y1)^2 ) <= radius
522
; (x2-x1)^2 + (y2-y1)^2 <= radius^2
523
checkPointInCircle:
524
   push eax ebx ecx edx
525
   mcall 37, 0 ;получаем текущие координаты мыши
526
   ;mov dword[o.cx], eax
527
   mov word[o.cy], ax
528
   shr eax, 16
529
   mov word[o.cx], ax
530
 
531
   xor eax, eax
532
   xor edx, edx
533
   mov ax, word[o.x]
534
   mov dx, word[o.cx]
535
   cmp dx, ax
536
   jae @f
537
   sub ax, dx
538
   mov dx, ax
539
   jmp .xend
540
@@:
541
   sub dx, ax
542
.xend:
543
   mov eax, edx
544
   mul dx
545
 
546
   mov ebx, eax
547
 
548
   xor eax, eax
549
   xor edx, edx
550
   mov ax, word[o.y]
551
   mov dx, word[o.cy]
552
   cmp dx, ax
553
   jae @f
554
   sub ax, dx
555
   mov dx, ax
556
   jmp .yend
557
@@:
558
   sub dx, ax
559
.yend:
560
   mov eax, edx
561
   mul dx
562
 
563
   add ebx, eax
564
 
565
   cmp ebx, dword[radius2]
566
   jbe @f
567
   call activateCorner ;иначе активируем нужный угол
568
 @@:
569
   pop edx ecx ebx eax
570
   ret
571
 
572
;выяснить в сторону какого угла ушли и активировать его
573
activateCorner:
574
   push eax ecx
575
   xor eax, eax
576
 
577
   mov ax, word[o.cx]
578
   cmp ax, word[o.x]
579
   je activateCorner.end       ;если координата равна, то выходим (такого быть не должно)
580
   ja activateCorner.right
581
 
582
   ;иначе левая сторона
583
   mov ax, word[o.cy]
584
   cmp ax, word[o.y]
585
   je activateCorner.end       ;если координата равна, то выходим (такого быть не должно)
586
   jb activateCorner.leftup
587
 
588
   ;иначе левый нижний угол
589
   mov ecx, 1
590
   call run_command
591
   mov byte[keyState], 0
592
   mov byte[state], LOCKd
593
   jmp activateCorner.end
594
 
595
.leftup:
596
   ;левый верхний угол
597
   mov ecx, 0
598
   call run_command
599
   mov byte[keyState], 0
600
   mov byte[state], LOCKd
601
   jmp activateCorner.end
602
 
603
.right: ;правая сторона экрана
604
   mov ax, word[o.cy]
605
   cmp ax, word[o.y]
606
   je activateCorner.end       ;если координата равна, то выходим (такого быть не должно)
607
   jb activateCorner.rightup
608
 
609
   ;иначе правый нижний угол
610
   mov ecx, 3
611
   call run_command
612
   mov byte[keyState], 0
613
   mov byte[state], LOCKd
614
   jmp activateCorner.end
615
 
616
.rightup:
617
   ;правый верхний угол
618
   mov ecx, 2
619
   call run_command
620
   mov byte[keyState], 0
621
   mov byte[state], LOCKd
622
   jmp activateCorner.end
623
 
624
.end:
625
   pop ecx eax
626
   ret
627
 
628
 
629
 
7436 theonlymir 630
keyActivate db 41 ;16 ;'Q' ;клавиша активации
7443 theonlymir 631
keyState    db 0  ;0-клавиша не активна, 1 - клавиша активна
7389 theonlymir 632
 
7443 theonlymir 633
backAdr rd 1      ;адрес для возврата из проверки мыши
7436 theonlymir 634
 
635
;slotMax dd 0
636
;selfPID dd 0
637
;buf db 1024 dup(0)
638
slotMax rd 1
639
selfPID rd 1
640
buf rb 1024
641
 
642
;структурка данных для хранения параметров экрана
643
screen:
7443 theonlymir 644
  .width  rw 1
645
  .height rw 1
7436 theonlymir 646
 
647
state: rb 1  ;состояние: 0=unlock, 1=lock
648
mode:  rb 1  ;режим работы приложения: 0=не работает, 1=классический, 2=по горячей клавише
649
 
650
newData:  ;табличка адресов командных строк
651
  .lu rd 1
652
  .ld rd 1
653
  .ru rd 1
654
  .rd rd 1
655
newDataEnd:
656
 
7389 theonlymir 657
I_END: