Subversion Repositories Kolibri OS

Rev

Rev 7416 | 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
7436 theonlymir 5
; Version 0.3.5: Oct 5, 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
@@:
56
   ;режим активации горячей клавишей?
57
   cmp byte[mode], 2 ;подписываемся на интересные нам события в зависимости от режима работы
58
   jne @f
59
   mov ebx, 00000100000000000000000000100010b    ;если да, то подписываемся на клавиши
7389 theonlymir 60
   mcall 40
7436 theonlymir 61
   jmp init02
62
@@:
63
   ; во всех остальных случаях - классический режим работы
64
   ;mode=1 классический режим работы - реакция при наведении в угол
65
   mov byte[mode], 1
66
   mov ebx, 00000100000000000000000000100000b
67
   mcall 40
68
   jmp init01
7389 theonlymir 69
 
7436 theonlymir 70
 
71
 
72
init02:
73
   mov dword[backAdr], mode02
74
   call setHotKey
75
mode02:
76
   mcall 10
77
   cmp eax, 2     ;обработка нажатия клавиши
78
   je hotkey
79
 
80
   cmp byte[keyState], 0
81
   je mode02
82
   cmp   eax, 6   ;обработка перемещений и нажатия мыши
83
   je    mouse
84
 
85
   jmp mode02
86
 
87
 
88
setHotKey:    ;установить горячую клавишу
89
   push eax ebx ecx edx
90
   xor ecx, ecx
91
   mov cl, byte[keyActivate]  ;нажатие горячей клавиши
92
   mov edx, 0x000
93
   mcall 66, 4, ecx, edx
94
 
95
   ;mov cl, byte[keyActivate]
96
   add cl, 128              ;отпускание горячей клавиши
97
   ;mov edx, 0x000
98
   mcall 66, 4, ecx, edx
99
   pop edx ecx ebx eax
100
   ret
101
 
102
 
103
hotkey:
104
   mcall 2
105
   cmp eax, 1     ;буфер клавиш пуст?
106
   je hotkey.end
107
 
108
   cmp al, 2      ;нас интересует только скан код горячей клавиши, иначе выходим
109
   jne hotkey.end
110
 
111
   cmp ah, byte[keyActivate]   ;если нажата наша горячая клавиша
112
   jne @f
113
   mov byte[keyState], 1
114
   mov byte[state], UNLOCKd
115
   jmp hotkey.end
116
@@:
117
   push edx
118
   xor edx, edx
119
   mov dl, byte[keyActivate]
120
   add dl, 128
121
   cmp ah, dl   ;если отпущена наша горячая клавиша
122
   jne @f       ;hotkey.end
123
   ;mov ecx, 0  ;строки для отладки и теста
124
   ;call run_command
125
   mov byte[keyState], 0
126
   mov byte[state], LOCKd
127
@@:
128
   pop edx
129
.end:
130
   jmp mode02
131
 
132
 
133
init01:
134
   mov dword[backAdr], mode01
135
mode01:
7389 theonlymir 136
  mov     eax, 10                 ; function 10 : wait until event
137
  mcall                           ; event type is returned in eax
138
 
139
  cmp   eax, 6           ;обработка перемещений и нажатия мыши
140
  je    mouse
141
 
7436 theonlymir 142
  jmp mode01
7389 theonlymir 143
 
7436 theonlymir 144
 
7389 theonlymir 145
mouse:
7436 theonlymir 146
   push ebx
147
   mcall 37, 0   ;получаем текущие координаты мыши
148
   pop ebx
7389 theonlymir 149
 
150
  cmp eax, 0 ;левый верхний угол
151
  jne @f
152
  ; -- здесь вызываем соотв. вызов для левого верхнего угла  (X=0, Y=0)
153
  push ecx
154
  mov ecx, 0
155
  call run_command
156
  pop ecx
157
 
7436 theonlymir 158
  jmp dword[backAdr] ;finish
7389 theonlymir 159
@@:
160
  call get_screen_size ;иначе обновляем размеры экрана
161
 
162
  cmp ax, word[screen.height]    ;Ymouse = Yscreen ?
163
  je Ytrue
164
  ;если Y не равны, то нас интересует Y=0 и X=ScreenWidth (правый верхний угол)
165
 
166
  cmp ax, 0
167
  jne unlockend
168
  shr eax, 16
169
  cmp ax, word[screen.width]
170
  jne unlockend
171
  ; -- здесь вызываем для правого верхенего угла
172
  push ecx
173
  mov ecx, 2
174
  call run_command
175
  pop ecx
176
 
7436 theonlymir 177
  jmp dword[backAdr]
7389 theonlymir 178
Ytrue:
179
  ;если Y равны, то нас интересует X=0 (левый нижний угол) или X=ScreenWidth (правый нижний)
180
  shr eax, 16
181
  cmp ax, 0
182
  jne @f
183
  ; -- X=0, Y = Height  (левый нижний угол)
184
  push ecx
185
  mov ecx, 1
186
  call run_command
187
  pop ecx
7436 theonlymir 188
  jmp dword[backAdr]
7389 theonlymir 189
@@:
190
  cmp ax, word[screen.width]
191
  jne unlockend
192
  ; -- (правый нижний угол)
193
  push ecx
194
  mov ecx, 3
195
  call run_command
196
  pop ecx
197
 
7436 theonlymir 198
  jmp dword[backAdr]
7389 theonlymir 199
 
200
unlockend:
201
  mov byte[state], UNLOCKd
7436 theonlymir 202
  jmp dword[backAdr]
7389 theonlymir 203
 
204
 
7436 theonlymir 205
 
7389 theonlymir 206
;получить размер экрана
207
get_screen_size:
208
   push eax
209
   mcall 14
210
   ;теперь в eax = [xsize]*65536 + [ysize]
211
   ;mov dword[screen], eax
212
   mov word[screen.height], ax
213
   shr eax, 16
214
   mov word[screen.width], ax
215
   pop eax
216
   ret
217
 
218
 
219
 
220
 
7436 theonlymir 221
 
7389 theonlymir 222
;запуск приложения: ecx - активный угол: lu=0, ld=1, ru=2, rd=3
223
run_command:
224
   cmp byte[state], UNLOCKd
225
   jne run_command.end
226
 
7436 theonlymir 227
;   cmp byte[mode], 2     ;если режим второй
228
;   jne @f
7389 theonlymir 229
 
7436 theonlymir 230
   push eax ebx ecx
7389 theonlymir 231
 
232
   cmp ecx, 0
233
   jne @f
7436 theonlymir 234
   mov eax, dword[newData.lu]
7389 theonlymir 235
   mov dword[struct70.path_adr], eax
236
   jmp .end_set_path
237
@@:
238
   cmp ecx, 1
239
   jne @f
240
   mov eax, dword[newData.ld]
241
   mov dword[struct70.path_adr], eax
242
   jmp .end_set_path
243
@@:
244
   cmp ecx, 2
245
   jne @f
246
   mov eax, dword[newData.ru]
247
   mov dword[struct70.path_adr], eax
248
   jmp .end_set_path
249
@@:
250
   cmp ecx, 3
251
   jne .end_set_path
252
   mov eax, dword[newData.rd]
253
   mov dword[struct70.path_adr], eax
254
   jmp .end_set_path
255
.end_set_path:
256
 
257
   ;параметры
258
   ;mov dword[struct.adr],
259
 
7416 theonlymir 260
;если адрес 0, то ничего не делать
7389 theonlymir 261
   cmp dword[struct70.path_adr], 0
262
   jne .next
7416 theonlymir 263
   ;mov eax, testData.ld
264
   ;mov dword[struct70.path_adr], eax
265
   jmp @f
7389 theonlymir 266
.next:
267
;конец кода для замены
268
 
269
   mcall 70, struct70
7416 theonlymir 270
@@:
7389 theonlymir 271
   mov byte[state], LOCKd
7436 theonlymir 272
   ;mov byte[keyState], 0
7389 theonlymir 273
 
7436 theonlymir 274
   pop ecx ebx eax
7389 theonlymir 275
.end:
276
   ret
277
 
278
struct70: ;Формат информационной структуры
279
  .func       dd 7 ; номер подфункции
280
  .mask       dd 0
281
  .param_adr  dd 0 ; указатель на ASCIIZ-строку с параметрами
282
  .other      dd 0, 0
283
  .path       db 0 ; "/rd/1/TINYPAD",0 ; путь
7416 theonlymir 284
  .path_adr   dd 0 ;testData.lu
7389 theonlymir 285
 
286
;имя конфигурационного файла
7416 theonlymir 287
fileName: db 'SETTINGS/HOTANGLES.CFG', 0
7389 theonlymir 288
 
289
loadConfig:
7416 theonlymir 290
   push eax ebx ecx edx
7389 theonlymir 291
   mcall 68, 27, fileName   ;загружаем конфигурационный файл в ОЗУ
292
   cmp eax, 0
293
   je loadConfig.exit       ;если файла конфигурации нет, то завершаем работу приложения
294
   ;иначе данные загружены в ОЗУ, размер в edx
295
   cmp edx, 0               ;если файл пуст, в нём нет данных, то завершаем работу
296
   je loadConfig.exit
297
 
298
   add edx, eax             ;иначе кладём в edx - адрес конца файла
299
 
7436 theonlymir 300
   mov byte[mode], 0
301
   cmp byte[eax], '0' ;121 ;'y'  ;если параметр активности приложения имеет статус: не активно
302
   je loadConfig.exit      ;то завершаем работу приложения
303
   cmp byte[eax], 110 ;'n'
304
   je loadConfig.exit
7389 theonlymir 305
 
7436 theonlymir 306
   ;иначе выставляем режим
307
   cmp byte[eax], '2'       ;режим активации по горячей клавише
308
   jne @f
309
   mov byte[mode], 2
310
   jmp loadConfig.modeEnd
311
@@:
312
   cmp byte[eax], '3'       ;режим жеста при зажатой клавише
313
   jne @f
314
   mov byte[mode], 3
315
   jmp loadConfig.modeEnd
316
@@:
317
   mov byte[mode], 1        ;во всех остальных случаях - классический режим
318
.modeEnd:
319
 
7389 theonlymir 320
   push edi
321
   push esi
322
   ; сохраняем в edi указатель на начало таблицы адресов наших команд
323
   mov edi, newData
324
   ; сохраняем адреса строк и добавляем 0 в конце
325
   mov esi, eax
326
.block:
327
   inc esi
328
   cmp byte[esi], 10         ;если очередной код символа 10 или 13, то пропускаем символы
329
   je loadConfig.propusk     ;до первого отличного от них
330
   cmp byte[esi], 13
331
   je loadConfig.propusk
332
 
7416 theonlymir 333
   ; символ отличен от переноса строки и возврата каретки - если это на знак минус, то запоминаем его
7389 theonlymir 334
   mov dword[edi], esi
335
   add edi, 4
336
 
337
   ;идём до конца этой строки: пока не встретим очередной 10, 13, 0 или file end
338
.while:
339
   inc esi
340
   cmp esi, edx           ;тут будет проблема - тк файл закончился, а нуля не было !!! исправить
341
   jae loadConfig.fileend
342
   cmp byte[esi], 10
343
   je loadConfig.ura
344
   cmp byte[esi], 0
345
   je loadConfig.ura
346
   cmp byte[esi], 13
347
   jne loadConfig.while
348
.ura:
349
   mov byte[esi], 0
350
 
7416 theonlymir 351
   ;cmp byte[esi-1], '-'
352
   ;jne @f
353
   push esi  ;если это был знак минус, то меняем адрес на ноль
354
   mov esi, dword[edi-4]
355
   cmp byte[esi], '-'
356
   jne @f
357
   cmp byte[esi+1], 0
358
   jne @f
359
   mov dword[edi-4], 0
360
@@:
361
   pop esi
362
 
7389 theonlymir 363
   cmp edi, newDataEnd ;newData.end      ;если вся таблица адресов заполнена, то выходим из цикла
364
   jb loadConfig.block
365
.fileend:
366
 
367
   pop esi
368
   pop edi
369
 
370
   jmp loadConfig.end
371
 
372
.propusk:
373
   mov byte[esi], 0
374
   jmp loadConfig.block
375
.exit:
7416 theonlymir 376
   pop edx ecx ebx eax
7389 theonlymir 377
   mcall -1 ;закрыть эту программу
378
.end:
7416 theonlymir 379
   pop edx ecx ebx eax
7389 theonlymir 380
   ret
381
 
382
 
383
 
384
 
385
;Вынести код ниже в отдельный общий модуль
386
selfName db '@HOTANGLES',0
387
selfNameSize = 10 ;до 11 byte
388
;
389
compareBytes:
390
   push edi esi ecx ebx
7436 theonlymir 391
   xor eax, eax
7389 theonlymir 392
   mov ecx, selfNameSize    ;max размер строк 11
393
@@:
394
   mov bl, byte[edi]
395
   cmp bl, byte[esi]
396
   jne compareBytes.no
397
   inc edi
398
   inc esi
399
   cmp ecx, 0
400
   je @f
401
   dec ecx
402
   jmp @b
403
.no:
404
   mov eax, 1
405
@@:
406
   pop ebx ecx esi edi
407
   ret
408
;
409
copyKill:
410
   push eax ebx ecx esi edi
411
 
412
   ;сперва прочтём свою информацию
413
   mcall 9, buf, -1
414
   mov eax, dword[buf+30]
415
   mov dword[selfPID], eax
416
 
417
   ;указатели, которые никогда не меняются:
418
   mov esi, selfName       ;первая строка - имя текущего приложения
419
   mov edi, buf            ;вторая строка - имя текущего слота
420
   add edi, 10
421
 
422
   mov ecx, 1
423
@@:
424
   mcall 9, buf, ecx
425
   mov dword[slotMax], eax
426
 
427
   ;если это мы сами, то пропускаем проверку
428
   mov eax, dword[buf+30]
429
   cmp eax, dword[selfPID]
430
   je copyKill.propusk
431
 
432
   call compareBytes   ;сравниваем 11 байт строк, результат в eax
433
 
434
   cmp eax, 0
435
   je copyKill.selfKill
436
 
437
.propusk:
438
   inc ecx
439
   cmp ecx, dword[slotMax]
440
   ja @f
441
   jmp @b
442
 
443
.selfKill:
444
   pop edi esi ecx ebx eax
445
   mcall -1
446
   ret
447
@@:
448
   pop edi esi ecx ebx eax
449
   ret
450
 
451
 
7436 theonlymir 452
keyActivate db 41 ;16 ;'Q' ;клавиша активации
453
keyState db 0 ;0-клавиша не активна, 1 - клавиша активна
7389 theonlymir 454
 
7436 theonlymir 455
backAdr rd 1 ;dd 0 ; адрес для возврата из проверки мыши
456
 
457
;slotMax dd 0
458
;selfPID dd 0
459
;buf db 1024 dup(0)
460
slotMax rd 1
461
selfPID rd 1
462
buf rb 1024
463
 
464
;структурка данных для хранения параметров экрана
465
screen:
466
  .width  rw 1 ;dw 0
467
  .height rw 1 ;dw 0
468
 
469
state: rb 1  ;состояние: 0=unlock, 1=lock
470
mode:  rb 1  ;режим работы приложения: 0=не работает, 1=классический, 2=по горячей клавише
471
 
472
newData:  ;табличка адресов командных строк
473
  .lu rd 1
474
  .ld rd 1
475
  .ru rd 1
476
  .rd rd 1
477
newDataEnd:
478
 
7389 theonlymir 479
I_END: