Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
7389 | theonlymir | 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ; Hot Angles ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
3 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
4 | ; Compile with FASM |
||
7416 | theonlymir | 5 | ; Version 0.3.3: Sep 25, 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 |
||
33 | LOCKd = 1 |
||
34 | |||
35 | ; заголовок |
||
36 | db 'MENUET01' ;магический идентификатор |
||
37 | dd 0x01 ;версия |
||
38 | dd START_DEBUG ;адрес точки старта программы |
||
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 ;загружаем конфигурацию приложения |
||
51 | mov ebx, 00000100000000000000000000100000b ;подписываемся на интересные нам события |
||
52 | mcall 40 |
||
53 | |||
54 | START: |
||
55 | mov eax, 10 ; function 10 : wait until event |
||
56 | mcall ; event type is returned in eax |
||
57 | |||
58 | cmp eax, 6 ;обработка перемещений и нажатия мыши |
||
59 | je mouse |
||
60 | |||
61 | jmp START |
||
62 | |||
63 | mouse: |
||
64 | ;основной цикл программы |
||
65 | call get_mouse_pos ;получаем текущие координаты мыши |
||
66 | |||
67 | cmp eax, 0 ;левый верхний угол |
||
68 | jne @f |
||
69 | ; -- здесь вызываем соотв. вызов для левого верхнего угла (X=0, Y=0) |
||
70 | push ecx |
||
71 | mov ecx, 0 |
||
72 | call run_command |
||
73 | pop ecx |
||
74 | |||
75 | jmp START ;finish |
||
76 | @@: |
||
77 | call get_screen_size ;иначе обновляем размеры экрана |
||
78 | |||
79 | cmp ax, word[screen.height] ;Ymouse = Yscreen ? |
||
80 | je Ytrue |
||
81 | ;если Y не равны, то нас интересует Y=0 и X=ScreenWidth (правый верхний угол) |
||
82 | |||
83 | cmp ax, 0 |
||
84 | jne unlockend |
||
85 | shr eax, 16 |
||
86 | cmp ax, word[screen.width] |
||
87 | jne unlockend |
||
88 | ; -- здесь вызываем для правого верхенего угла |
||
89 | push ecx |
||
90 | mov ecx, 2 |
||
91 | call run_command |
||
92 | pop ecx |
||
93 | |||
94 | jmp START |
||
95 | Ytrue: |
||
96 | ;если Y равны, то нас интересует X=0 (левый нижний угол) или X=ScreenWidth (правый нижний) |
||
97 | shr eax, 16 |
||
98 | cmp ax, 0 |
||
99 | jne @f |
||
100 | ; -- X=0, Y = Height (левый нижний угол) |
||
101 | push ecx |
||
102 | mov ecx, 1 |
||
103 | call run_command |
||
104 | pop ecx |
||
105 | jmp START |
||
106 | @@: |
||
107 | cmp ax, word[screen.width] |
||
108 | jne unlockend |
||
109 | ; -- (правый нижний угол) |
||
110 | push ecx |
||
111 | mov ecx, 3 |
||
112 | call run_command |
||
113 | pop ecx |
||
114 | |||
115 | jmp START |
||
116 | |||
117 | unlockend: |
||
118 | mov byte[state], UNLOCKd |
||
119 | jmp START |
||
120 | |||
121 | |||
122 | ;структурка данных для хранения параметров экрана |
||
123 | screen: |
||
124 | .width dw 0 |
||
125 | .height dw 0 |
||
126 | ;получить размер экрана |
||
127 | get_screen_size: |
||
128 | push eax |
||
129 | mcall 14 |
||
130 | ;теперь в eax = [xsize]*65536 + [ysize] |
||
131 | ;mov dword[screen], eax |
||
132 | mov word[screen.height], ax |
||
133 | shr eax, 16 |
||
134 | mov word[screen.width], ax |
||
135 | pop eax |
||
136 | ret |
||
137 | |||
138 | |||
139 | ;получить позицию мыши |
||
140 | get_mouse_pos: |
||
141 | ;push eax |
||
142 | push ebx |
||
143 | mcall 37, 0 |
||
144 | pop ebx |
||
145 | ;pop eax |
||
146 | ret |
||
147 | |||
148 | |||
149 | ;запуск приложения: ecx - активный угол: lu=0, ld=1, ru=2, rd=3 |
||
150 | run_command: |
||
151 | cmp byte[state], UNLOCKd |
||
152 | jne run_command.end |
||
153 | |||
154 | push eax |
||
155 | push ebx |
||
156 | push ecx |
||
157 | |||
158 | |||
159 | cmp ecx, 0 |
||
160 | jne @f |
||
161 | mov eax, dword[newData.lu] ;testData.lu |
||
162 | mov dword[struct70.path_adr], eax |
||
163 | jmp .end_set_path |
||
164 | @@: |
||
165 | cmp ecx, 1 |
||
166 | jne @f |
||
167 | mov eax, dword[newData.ld] |
||
168 | mov dword[struct70.path_adr], eax |
||
169 | jmp .end_set_path |
||
170 | @@: |
||
171 | cmp ecx, 2 |
||
172 | jne @f |
||
173 | mov eax, dword[newData.ru] |
||
174 | mov dword[struct70.path_adr], eax |
||
175 | jmp .end_set_path |
||
176 | @@: |
||
177 | cmp ecx, 3 |
||
178 | jne .end_set_path |
||
179 | mov eax, dword[newData.rd] |
||
180 | mov dword[struct70.path_adr], eax |
||
181 | jmp .end_set_path |
||
182 | .end_set_path: |
||
183 | |||
184 | ;параметры |
||
185 | ;mov dword[struct.adr], |
||
186 | |||
7416 | theonlymir | 187 | ;если адрес 0, то ничего не делать |
7389 | theonlymir | 188 | cmp dword[struct70.path_adr], 0 |
189 | jne .next |
||
7416 | theonlymir | 190 | ;mov eax, testData.ld |
191 | ;mov dword[struct70.path_adr], eax |
||
192 | jmp @f |
||
7389 | theonlymir | 193 | .next: |
194 | ;конец кода для замены |
||
195 | |||
196 | mcall 70, struct70 |
||
7416 | theonlymir | 197 | @@: |
7389 | theonlymir | 198 | mov byte[state], LOCKd |
199 | |||
200 | pop ecx |
||
201 | pop ebx |
||
202 | pop eax |
||
203 | .end: |
||
204 | ret |
||
205 | |||
206 | struct70: ;Формат информационной структуры |
||
207 | .func dd 7 ; номер подфункции |
||
208 | .mask dd 0 |
||
209 | .param_adr dd 0 ; указатель на ASCIIZ-строку с параметрами |
||
210 | .other dd 0, 0 |
||
211 | .path db 0 ; "/rd/1/TINYPAD",0 ; путь |
||
7416 | theonlymir | 212 | .path_adr dd 0 ;testData.lu |
7389 | theonlymir | 213 | |
214 | |||
215 | state: db 0 ; 0=unlock, 1=lock |
||
7416 | theonlymir | 216 | mode: db 0 ;режим работы (для будущего расширения функционала) |
7389 | theonlymir | 217 | |
7416 | theonlymir | 218 | ;testData: |
219 | ; .lu db '/rd/1/SHELL', 0 |
||
220 | ; .ld db '/rd/1/RUN', 0 |
||
221 | ; .ru db "/rd/1/TINYPAD", 0 |
||
222 | ; .rd db '/rd/1/File Managers/EOLITE', 0 |
||
7389 | theonlymir | 223 | |
224 | newData: ;табличка адресов командных строк |
||
225 | .lu dd 0 |
||
226 | .ld dd 0 |
||
227 | .ru dd 0 |
||
228 | .rd dd 0 |
||
229 | newDataEnd: |
||
230 | |||
231 | ;имя конфигурационного файла |
||
7416 | theonlymir | 232 | fileName: db 'SETTINGS/HOTANGLES.CFG', 0 |
7389 | theonlymir | 233 | |
234 | loadConfig: |
||
7416 | theonlymir | 235 | push eax ebx ecx edx |
7389 | theonlymir | 236 | mcall 68, 27, fileName ;загружаем конфигурационный файл в ОЗУ |
237 | cmp eax, 0 |
||
238 | je loadConfig.exit ;если файла конфигурации нет, то завершаем работу приложения |
||
239 | ;иначе данные загружены в ОЗУ, размер в edx |
||
240 | cmp edx, 0 ;если файл пуст, в нём нет данных, то завершаем работу |
||
241 | je loadConfig.exit |
||
242 | |||
243 | add edx, eax ;иначе кладём в edx - адрес конца файла |
||
244 | |||
245 | cmp byte[eax], 121 ;'y' ;если параметр активности приложения имеет статус: не активно |
||
246 | jne loadConfig.exit ;то завершаем работу приложения |
||
247 | |||
248 | push edi |
||
249 | push esi |
||
250 | ; сохраняем в edi указатель на начало таблицы адресов наших команд |
||
251 | mov edi, newData |
||
252 | ; сохраняем адреса строк и добавляем 0 в конце |
||
253 | mov esi, eax |
||
254 | .block: |
||
255 | inc esi |
||
256 | cmp byte[esi], 10 ;если очередной код символа 10 или 13, то пропускаем символы |
||
257 | je loadConfig.propusk ;до первого отличного от них |
||
258 | cmp byte[esi], 13 |
||
259 | je loadConfig.propusk |
||
260 | |||
7416 | theonlymir | 261 | ; символ отличен от переноса строки и возврата каретки - если это на знак минус, то запоминаем его |
7389 | theonlymir | 262 | mov dword[edi], esi |
263 | add edi, 4 |
||
264 | |||
265 | ;идём до конца этой строки: пока не встретим очередной 10, 13, 0 или file end |
||
266 | .while: |
||
267 | inc esi |
||
268 | cmp esi, edx ;тут будет проблема - тк файл закончился, а нуля не было !!! исправить |
||
269 | jae loadConfig.fileend |
||
270 | cmp byte[esi], 10 |
||
271 | je loadConfig.ura |
||
272 | cmp byte[esi], 0 |
||
273 | je loadConfig.ura |
||
274 | cmp byte[esi], 13 |
||
275 | jne loadConfig.while |
||
276 | .ura: |
||
277 | mov byte[esi], 0 |
||
278 | |||
7416 | theonlymir | 279 | ;cmp byte[esi-1], '-' |
280 | ;jne @f |
||
281 | push esi ;если это был знак минус, то меняем адрес на ноль |
||
282 | mov esi, dword[edi-4] |
||
283 | cmp byte[esi], '-' |
||
284 | jne @f |
||
285 | cmp byte[esi+1], 0 |
||
286 | jne @f |
||
287 | mov dword[edi-4], 0 |
||
288 | @@: |
||
289 | pop esi |
||
290 | |||
7389 | theonlymir | 291 | cmp edi, newDataEnd ;newData.end ;если вся таблица адресов заполнена, то выходим из цикла |
292 | jb loadConfig.block |
||
293 | .fileend: |
||
294 | |||
295 | pop esi |
||
296 | pop edi |
||
297 | |||
298 | jmp loadConfig.end |
||
299 | |||
300 | .propusk: |
||
301 | mov byte[esi], 0 |
||
302 | jmp loadConfig.block |
||
303 | .exit: |
||
7416 | theonlymir | 304 | pop edx ecx ebx eax |
7389 | theonlymir | 305 | mcall -1 ;закрыть эту программу |
306 | .end: |
||
7416 | theonlymir | 307 | pop edx ecx ebx eax |
7389 | theonlymir | 308 | ret |
309 | |||
310 | |||
311 | |||
312 | |||
313 | ;Вынести код ниже в отдельный общий модуль |
||
314 | selfName db '@HOTANGLES',0 |
||
315 | selfNameSize = 10 ;до 11 byte |
||
316 | ; |
||
317 | compareBytes: |
||
318 | push edi esi ecx ebx |
||
319 | mov eax, 0 ;xor eax, eax |
||
320 | mov ecx, selfNameSize ;max размер строк 11 |
||
321 | @@: |
||
322 | mov bl, byte[edi] |
||
323 | cmp bl, byte[esi] |
||
324 | jne compareBytes.no |
||
325 | inc edi |
||
326 | inc esi |
||
327 | cmp ecx, 0 |
||
328 | je @f |
||
329 | dec ecx |
||
330 | jmp @b |
||
331 | .no: |
||
332 | mov eax, 1 |
||
333 | @@: |
||
334 | pop ebx ecx esi edi |
||
335 | ret |
||
336 | ; |
||
337 | slotMax dd 0 |
||
338 | selfPID dd 0 |
||
339 | buf db 1024 dup(0) |
||
340 | copyKill: |
||
341 | push eax ebx ecx esi edi |
||
342 | |||
343 | ;сперва прочтём свою информацию |
||
344 | mcall 9, buf, -1 |
||
345 | mov eax, dword[buf+30] |
||
346 | mov dword[selfPID], eax |
||
347 | |||
348 | ;указатели, которые никогда не меняются: |
||
349 | mov esi, selfName ;первая строка - имя текущего приложения |
||
350 | mov edi, buf ;вторая строка - имя текущего слота |
||
351 | add edi, 10 |
||
352 | |||
353 | mov ecx, 1 |
||
354 | @@: |
||
355 | mcall 9, buf, ecx |
||
356 | mov dword[slotMax], eax |
||
357 | |||
358 | ;если это мы сами, то пропускаем проверку |
||
359 | mov eax, dword[buf+30] |
||
360 | cmp eax, dword[selfPID] |
||
361 | je copyKill.propusk |
||
362 | |||
363 | call compareBytes ;сравниваем 11 байт строк, результат в eax |
||
364 | |||
365 | cmp eax, 0 |
||
366 | je copyKill.selfKill |
||
367 | |||
368 | .propusk: |
||
369 | inc ecx |
||
370 | cmp ecx, dword[slotMax] |
||
371 | ja @f |
||
372 | jmp @b |
||
373 | |||
374 | .selfKill: |
||
375 | pop edi esi ecx ebx eax |
||
376 | mcall -1 |
||
377 | ret |
||
378 | @@: |
||
379 | pop edi esi ecx ebx eax |
||
380 | ret |
||
381 | |||
382 | |||
383 | |||
384 | I_END: |