Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
7389 | theonlymir | 1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ; Hot Angles ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
3 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
||
4 | ; Compile with FASM |
||
5 | ; Version 0.1: Sep 18, 2018 |
||
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 | |||
187 | ;этот код заменить - если адрес 0, то ничего не делать |
||
188 | cmp dword[struct70.path_adr], 0 |
||
189 | jne .next |
||
190 | mov eax, testData.ld ; |
||
191 | mov dword[struct70.path_adr], eax |
||
192 | .next: |
||
193 | ;конец кода для замены |
||
194 | |||
195 | mcall 70, struct70 |
||
196 | mov byte[state], LOCKd |
||
197 | |||
198 | pop ecx |
||
199 | pop ebx |
||
200 | pop eax |
||
201 | .end: |
||
202 | ret |
||
203 | |||
204 | struct70: ;Формат информационной структуры |
||
205 | .func dd 7 ; номер подфункции |
||
206 | .mask dd 0 |
||
207 | .param_adr dd 0 ; указатель на ASCIIZ-строку с параметрами |
||
208 | .other dd 0, 0 |
||
209 | .path db 0 ; "/rd/1/TINYPAD",0 ; путь |
||
210 | .path_adr dd 0 ;testData.lu ;0 |
||
211 | |||
212 | |||
213 | state: db 0 ; 0=unlock, 1=lock |
||
214 | |||
215 | testData: |
||
216 | .lu db '/rd/1/SHELL', 0 |
||
217 | .ld db '/rd/1/RUN', 0 |
||
218 | .ru db "/rd/1/TINYPAD", 0 |
||
219 | .rd db '/rd/1/File Managers/EOLITE', 0 |
||
220 | |||
221 | newData: ;табличка адресов командных строк |
||
222 | .lu dd 0 |
||
223 | .ld dd 0 |
||
224 | .ru dd 0 |
||
225 | .rd dd 0 |
||
226 | newDataEnd: |
||
227 | |||
228 | ;имя конфигурационного файла |
||
229 | fileName: db 'SETTINGS/HOTANGLES.CFG', 0 ;'ha.cfg', 0 |
||
230 | |||
231 | loadConfig: |
||
232 | push eax |
||
233 | push ebx |
||
234 | push ecx |
||
235 | push edx |
||
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 | |||
261 | ; символ отличен от переноса строки и возврата каретки - запоминаем его |
||
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 | |||
279 | cmp edi, newDataEnd ;newData.end ;если вся таблица адресов заполнена, то выходим из цикла |
||
280 | jb loadConfig.block |
||
281 | .fileend: |
||
282 | |||
283 | pop esi |
||
284 | pop edi |
||
285 | |||
286 | jmp loadConfig.end |
||
287 | |||
288 | .propusk: |
||
289 | mov byte[esi], 0 |
||
290 | jmp loadConfig.block |
||
291 | .exit: |
||
292 | pop edx |
||
293 | pop ecx |
||
294 | pop ebx |
||
295 | pop eax |
||
296 | mcall -1 ;закрыть эту программу |
||
297 | .end: |
||
298 | pop edx |
||
299 | pop ecx |
||
300 | pop ebx |
||
301 | pop eax |
||
302 | ret |
||
303 | |||
304 | |||
305 | |||
306 | |||
307 | ;Вынести код ниже в отдельный общий модуль |
||
308 | selfName db '@HOTANGLES',0 |
||
309 | selfNameSize = 10 ;до 11 byte |
||
310 | ; |
||
311 | compareBytes: |
||
312 | push edi esi ecx ebx |
||
313 | mov eax, 0 ;xor eax, eax |
||
314 | mov ecx, selfNameSize ;max размер строк 11 |
||
315 | @@: |
||
316 | mov bl, byte[edi] |
||
317 | cmp bl, byte[esi] |
||
318 | jne compareBytes.no |
||
319 | inc edi |
||
320 | inc esi |
||
321 | cmp ecx, 0 |
||
322 | je @f |
||
323 | dec ecx |
||
324 | jmp @b |
||
325 | .no: |
||
326 | mov eax, 1 |
||
327 | @@: |
||
328 | pop ebx ecx esi edi |
||
329 | ret |
||
330 | ; |
||
331 | slotMax dd 0 |
||
332 | selfPID dd 0 |
||
333 | buf db 1024 dup(0) |
||
334 | copyKill: |
||
335 | push eax ebx ecx esi edi |
||
336 | |||
337 | ;сперва прочтём свою информацию |
||
338 | mcall 9, buf, -1 |
||
339 | mov eax, dword[buf+30] |
||
340 | mov dword[selfPID], eax |
||
341 | |||
342 | ;указатели, которые никогда не меняются: |
||
343 | mov esi, selfName ;первая строка - имя текущего приложения |
||
344 | mov edi, buf ;вторая строка - имя текущего слота |
||
345 | add edi, 10 |
||
346 | |||
347 | mov ecx, 1 |
||
348 | @@: |
||
349 | mcall 9, buf, ecx |
||
350 | mov dword[slotMax], eax |
||
351 | |||
352 | ;если это мы сами, то пропускаем проверку |
||
353 | mov eax, dword[buf+30] |
||
354 | cmp eax, dword[selfPID] |
||
355 | je copyKill.propusk |
||
356 | |||
357 | call compareBytes ;сравниваем 11 байт строк, результат в eax |
||
358 | |||
359 | cmp eax, 0 |
||
360 | je copyKill.selfKill |
||
361 | |||
362 | .propusk: |
||
363 | inc ecx |
||
364 | cmp ecx, dword[slotMax] |
||
365 | ja @f |
||
366 | jmp @b |
||
367 | |||
368 | .selfKill: |
||
369 | pop edi esi ecx ebx eax |
||
370 | mcall -1 |
||
371 | ret |
||
372 | @@: |
||
373 | pop edi esi ecx ebx eax |
||
374 | ret |
||
375 | |||
376 | |||
377 | |||
378 | I_END: |