Subversion Repositories Kolibri OS

Rev

Rev 852 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
836 diamond 1
; Функции работы с консолью для программ КолибриОС
2
; diamond, 2006, 2007
3
 
4
 
5
format MS COFF
6
 
7
public EXPORTS
8
 
9
section '.flat' code readable align 16
10
 
11
include 'font.inc'
12
include 'conscrl.inc'
13
 
14
;void __stdcall START(dword state);
15
START:
16
; N.B. The current kernel implementation does not require
17
;      evident heap initialization, because if DLL is loaded, heap is already initialized
18
;      (if heap was not initialized, loader does this implicitly).
19
;      So this action does nothing useful, but nothing harmful.
20
        push    68
21
        pop     eax
22
        push    11
23
        pop     ebx
24
        int     0x40
25
        or      eax, -1
26
        ret     4
27
 
28
; Инициализация консоли
29
; void __stdcall con_init(dword wnd_width, dword wnd_height,
30
;       dword scr_width, dword scr_height, const char* title);
31
 
32
align 4
33
con_init:
34
        pop     eax
35
        pop     [con.wnd_width]
36
        pop     [con.wnd_height]
37
        pop     [con.scr_width]
38
        pop     [con.scr_height]
39
        pop     [con.title]
40
        push    eax
41
        mov     ecx, 4
42
        mov     eax, con.wnd_width
43
        mov     esi, con.def_wnd_width
44
.1:
45
        cmp     dword [eax], -1
46
        jnz     @f
47
        mov     ebx, [esi]
48
        mov     [eax], ebx
49
@@:
50
        add     eax, 4
51
        add     esi, 4
52
        loop    .1
53
        push    ebx
54
; allocate memory for console data & bitmap data
55
        mov     eax, [con.scr_width]
56
        mul     [con.scr_height]
57
        lea     ecx, [eax+eax]
58
        mov     eax, [con.wnd_width]
59
        mul     [con.wnd_height]
60
        imul    eax, font_width*font_height
61
        mov     ebx, eax
62
        push    ebx ecx
63
        add     ecx, eax
64
        push    68
65
        pop     eax
66
        push    12
67
        pop     ebx
68
        int     0x40
69
        pop     ecx ebx
70
        mov     edx, con.nomem_err
71
        test    eax, eax
72
        jz      con.fatal
73
        mov     [con.data], eax
74
        push    edi
75
        mov     edi, eax
76
        shr     ecx, 1
77
        mov     ax, 0x0720
78
        rep     stosw
79
        mov     ecx, ebx
80
        mov     [con.image], edi
81
        xor     eax, eax
82
        rep     stosb
83
        pop     edi
84
; create console thread
85
        push    51
86
        pop     eax
87
        xor     ebx, ebx
88
        inc     ebx
89
        mov     ecx, con.thread
90
        mov     edx, con.stack_top
91
        int     0x40
92
        mov     edx, con.thread_err
93
        test    eax, eax
94
        js      con.fatal
95
        mov     [con.console_tid], eax
96
        pop     ebx
97
        ret
98
con.fatal:
99
; output string to debug board and die
100
        mov     cl, [edx]
101
        test    cl, cl
102
        jz      @f
103
        push    63
104
        pop     eax
105
        xor     ebx, ebx
106
        inc     ebx
107
        int     0x40
108
        inc     edx
109
        jmp     con.fatal
110
@@:
111
        or      eax, -1
112
        int     0x40
113
 
114
; dword __stdcall con_get_flags(void);
115
con_get_flags:
116
        mov     eax, [con_flags]
117
        ret
118
 
119
; dword __stdcall con_set_flags(dword flags);
120
con_set_flags:
121
        mov     eax, [esp+4]
122
        xchg    eax, [con_flags]
123
        ret     4
124
 
125
; dword __stdcall con_get_font_height(void);
126
con_get_font_height:
127
        mov     eax, font_height
128
        ret
129
 
130
; int __stdcall con_get_cursor_height(void);
131
con_get_cursor_height:
132
        mov     eax, [con.cursor_height]
133
        ret
134
 
135
; int __stdcall con_set_cursor_height(int new_height);
136
con_set_cursor_height:
137
        mov     eax, [esp+4]
138
        cmp     eax, font_height
139
        jae     @f
140
        xchg    eax, [con.cursor_height]
141
        ret     4
142
@@:
143
        mov     eax, [con.cursor_height]
144
        ret     4
145
 
146
; void __stdcall con_write_asciiz(const char* string);
147
con_write_asciiz:
148
        push    ebx esi
149
        or      ebx, -1
150
        mov     esi, [esp+12]
151
        call    con.write
152
        pop     esi ebx
153
        ret     4
154
 
155
; void __stdcall con_write_string(const char* string, dword length);
156
con_write_length:
157
        push    ebx esi
158
        mov     esi, [esp+12]
159
        mov     ebx, [esp+16]
160
        call    con.write
161
        pop     esi ebx
162
        ret     8
163
 
164
; Каждый символ классифицируется как один из
165
con.printfc.normal = 0   ; нормальный символ
166
con.printfc.percent = 1  ; '%'
167
con.printfc.dot = 2      ; '.'
168
con.printfc.asterisk = 3 ; '*'
169
con.printfc.zero = 4     ; '0'
170
con.printfc.digit = 5    ; ненулевая цифра
171
con.printfc.plus = 6     ; '+'
172
con.printfc.minus = 7    ; '-'
173
con.printfc.sharp = 8    ; '#'
174
con.printfc.space = 9    ; ' '
175
con.printfc.long = 10    ; 'l' for 'long'
176
con.printfc.short = 11   ; 'h' for 'short'
177
con.printfc.dec = 12     ; 'd' = print decimal
178
con.printfc.oct = 13     ; 'o' = print octal
179
con.printfc.unsigned = 14 ; 'u' = print unsigned decimal
180
con.printfc.hex = 15     ; 'x' = print hexadecimal
181
con.printfc.pointer = 16 ; 'p' = print pointer
182
con.printfc.char = 17    ; 'c' = print char
183
con.printfc.string = 18  ; 's' = print string
184
 
185
macro set char,type
186
{store byte con.printfc.#type at con.charcodes + char - ' '}
187
 
188
con.charcodes:
189
times 'x'-' '+1         db      con.printfc.normal
190
        set     '%', percent
191
        set     '.', dot
192
        set     '*', asterisk
193
        set     '0', zero
194
        set     '1', digit
195
        set     '2', digit
196
        set     '3', digit
197
        set     '4', digit
198
        set     '5', digit
199
        set     '6', digit
200
        set     '7', digit
201
        set     '8', digit
202
        set     '9', digit
203
        set     ' ', space
204
        set     '#', sharp
205
        set     '+', plus
206
        set     '-', minus
207
        set     'X', hex
208
        set     'x', hex
209
        set     'c', char
210
        set     'd', dec
211
        set     'h', short
212
        set     'i', dec
213
        set     'l', long
214
        set     'o', oct
215
        set     'p', pointer
216
        set     's', string
217
        set     'u', unsigned
218
purge set
219
align 4
220
con.charjump    dd      con_printf.normal
221
        dd      con_printf.percent
222
        dd      con_printf.dot
223
        dd      con_printf.asterisk
224
        dd      con_printf.zero
225
        dd      con_printf.digit
226
        dd      con_printf.plus
227
        dd      con_printf.minus
228
        dd      con_printf.sharp
229
        dd      con_printf.space
230
        dd      con_printf.long
231
        dd      con_printf.short
232
        dd      con_printf.dec
233
        dd      con_printf.oct
234
        dd      con_printf.unsigned
235
        dd      con_printf.hex
236
        dd      con_printf.pointer
237
        dd      con_printf.char
238
        dd      con_printf.string
239
 
240
; int __cdecl con_printf(const char* format, ...)
241
con_printf:
242
        xor     eax, eax
243
        pushad
244
        call    con.get_data_ptr
245
        lea     ebp, [esp+20h+8]
246
        mov     esi, [ebp-4]
247
        sub     esp, 64         ; reserve space for buffer
248
.loop:
249
        xor     eax, eax
250
        lodsb
251
        test    al, al
252
        jz      .done
253
        cmp     al, '%'
254
        jz      .spec_begin
255
.normal:
256
        call    con.write_char_ex
257
        inc     dword [esp+64+28]
258
        jmp     .loop
259
.errspec:
260
.percent:
261
        add     esp, 12
262
        jmp     .normal
263
.spec_begin:
264
        xor     ebx, ebx
265
; bl = тип позиции:
266
; 0 = начало
267
; 1 = прочитан ведущий 0 в спецификации формата
268
; 2 = читаем поле ширины
269
; 3 = читаем поле точности
270
; 4 = прочитано поле размера аргумента
271
; 5 = читаем поле типа
272
; bh = флаги:
273
; 1 = флаг '#', выводить 0/0x/0X
274
; 2 = флаг '-', выравнивание влево
275
; 4 = флаг '0', дополнение нулями
276
; 8 = флаг 'h', короткий аргумент
277
        push    -1
278
; dword [esp+8] = precision
279
        push    -1
280
; dword [esp+4] = width
281
        push    0
282
; byte [esp] = флаг 0/'+'/' '
283
.spec:
284
        xor     eax, eax
285
        lodsb
286
        test    al, al
287
        jz      .done
288
        cmp     al, ' '
289
        jb      .normal
290
        cmp     al, 'x'
291
        ja      .normal
292
        movzx   ecx, byte [con.charcodes + eax - ' ']
293
        jmp     [con.charjump + ecx*4]
294
 
295
.sharp:
296
        test    bl, bl
297
        jnz     .errspec
298
        or      bh, 1
299
        jmp     .spec
300
.minus:
301
        test    bl, bl
302
        jnz     .errspec
303
        or      bh, 2
304
        jmp     .spec
305
.plus:
306
.space:
307
        test    bl, bl
308
        jnz     .errspec
309
        cmp     byte [esp], '+'
310
        jz      .spec
311
        mov     byte [esp], al
312
        jmp     .spec
313
.zero:
314
        test    bl, bl
315
        jnz     .digit
316
        test    bh, 2
317
        jnz     .spec
318
        or      bh, 4
319
        inc     ebx
320
        jmp     .spec
321
.digit:
322
        sub     al, '0'
323
        cmp     bl, 2
324
        ja      .precision
325
        mov     bl, 2
326
        xchg    eax, [esp+4]
327
        test    eax, eax
328
        js      .spec
329
        lea     eax, [eax*5]
330
        add     eax, eax
331
        add     [esp+4], eax
332
        jmp     .spec
333
.precision:
334
        cmp     bl, 3
335
        jnz     .errspec
336
        xchg    eax, [esp+8]
337
        lea     eax, [eax*5]
338
        add     eax, eax
339
        add     [esp+8], eax
340
        jmp     .spec
341
.asterisk:
342
        mov     eax, [ebp]
343
        add     ebp, 4
344
        cmp     bl, 2
345
        ja      .asterisk_precision
346
        test    eax, eax
347
        jns     @f
348
        neg     eax
349
        or      bh, 2
350
@@:
351
        mov     [esp+4], eax
352
        mov     bl, 3
353
        jmp     .spec
354
.asterisk_precision:
355
        cmp     bl, 3
356
        jnz     .errspec
357
        mov     [esp+8], eax
358
        inc     ebx
359
        jmp     .spec
360
.dot:
361
        cmp     bl, 2
362
        ja      .errspec
363
        mov     bl, 3
364
        and     dword [esp+8], 0
365
        jmp     .spec
366
.long:
367
        cmp     bl, 3
368
        ja      .errspec
369
        mov     bl, 4
370
        jmp     .spec
371
.short:
372
        cmp     bl, 3
373
        ja      .errspec
374
        mov     bl, 4
375
        or      bh, 8
376
        jmp     .spec
377
.unsigned:
378
.dec:
379
        push    10
380
        jmp     .write_number
381
.pointer:
382
        mov     dword [esp+12], 8
383
        or      bh, 4
384
        and     bh, not 8
385
.hex:
386
        push    16
387
        jmp     @f
388
.oct:
389
        push    8
390
@@:
391
        mov     byte [esp+4], 0
392
.write_number:
393
        pop     ecx
394
        push    edi
395
        lea     edi, [esp+16+64-1]      ; edi -> end of buffer
396
        mov     byte [edi], 0
397
        push    edx
398
        push    eax
399
        mov     eax, [ebp]
400
        add     ebp, 4
401
        test    bh, 8
402
        jz      @f
403
        movzx   eax, ax
404
        cmp     byte [esp], 'd'
405
        jnz     @f
406
        movsx   eax, ax
407
@@:
408
        xor     edx, edx
409
        test    eax, eax
410
        jns     @f
411
        cmp     byte [esp], 'd'
412
        jnz     @f
413
        inc     edx
414
        neg     eax
415
@@:
416
        push    edx
417
        xor     edx, edx
418
; число в eax, основание системы счисления в ecx
419
@@:
420
        cmp     dword [esp+16+8], 0
421
        jnz     .print_num
422
        test    eax, eax
423
        jz      .zeronum
424
.print_num:
425
        div     ecx
426
        xchg    eax, edx
427
        cmp     al, 10
428
        sbb     al, 69h
429
        das
430
        cmp     byte [esp+4], 'x'
431
        jnz     @f
432
        or      al, 20h
433
@@:
434
        dec     edi
435
        mov     [edi], al
436
        xor     eax, eax
437
        xchg    eax, edx
438
        test    eax, eax
439
        jnz     .print_num
440
.zeronum:
441
        push    0
442
        mov     edx, [esp+12]
443
        lea     eax, [esp+32+64-1]
444
        sub     eax, edi
445
        cmp     dword [esp+20+8], -1
446
        jz      .noprec1
447
        cmp     eax, [esp+20+8]
448
        jae     .len_found1
449
        mov     eax, [esp+20+8]
450
        jmp     .len_found1
451
.noprec1:
452
        test    bh, 4
453
        jnz     .do_print_num
454
.len_found1:
455
        test    bh, 2
456
        jnz     .do_print_num
457
        cmp     byte [esp+20], 0
458
        jz      @f
459
        inc     eax
460
@@:
461
        cmp     byte [esp+20], 0
462
        jnz     @f
463
        cmp     byte [esp+4], 0
464
        jz      @f
465
        inc     eax
466
@@:
467
        test    bh, 1
468
        jz      .nosharp1
469
        cmp     cl, 8
470
        jnz     @f
471
        inc     eax
472
        jmp     .nosharp1
473
@@:
474
        cmp     cl, 16
475
        jnz     .nosharp1
476
        inc     eax
477
        inc     eax
478
.nosharp1:
479
        cmp     dword [esp+20+4], -1
480
        jz      .do_print_num
481
        sub     eax, [esp+20+4]
482
        jae     .do_print_num
483
        push    ecx
484
        mov     ecx, eax
485
        mov     al, ' '
486
@@:
487
        xchg    edi, [esp+20]
488
        call    con.write_char_ex
489
        inc     dword [esp+24+12+64+28]
490
        xchg    edi, [esp+20]
491
        inc     dword [esp+4]
492
        inc     ecx
493
        jnz     @b
494
        pop     ecx
495
.do_print_num:
496
        mov     al, '-'
497
        cmp     byte [esp+4], 0
498
        jnz     .write_sign
499
        mov     al, [esp+20]
500
        test    al, al
501
        jz      .sign_written
502
.write_sign:
503
        call    .num_write_char
504
.sign_written:
505
        test    bh, 1
506
        jz      .nosharp2
507
        mov     al, '0'
508
        cmp     cl, 8
509
        jz      @f
510
        cmp     cl, 16
511
        jnz     .nosharp2
512
        call    .num_write_char
513
        mov     al, [esp+8]
514
@@:
515
        call    .num_write_char
516
.nosharp2:
517
        lea     ecx, [esp+32+64-1]
518
        sub     ecx, edi
519
        cmp     dword [esp+20+8], -1
520
        jz      .noprec2
521
        sub     ecx, [esp+20+8]
522
        jmp     .lead_zeroes
523
.noprec2:
524
        test    bh, 4
525
        jz      .do_print_num2
526
        add     ecx, [esp]
527
        sub     ecx, [esp+20+4]
528
.lead_zeroes:
529
        jae     .do_print_num2
530
@@:
531
        mov     al, '0'
532
        call    .num_write_char
533
        inc     ecx
534
        jnz     @b
535
.do_print_num2:
536
        mov     al, [edi]
537
        test    al, al
538
        jz      .num_written
539
        call    .num_write_char
540
        inc     edi
541
        jmp     .do_print_num2
542
.num_written:
543
        pop     ecx
544
        mov     edi, [esp+12]
545
        cmp     dword [esp+16+4], -1
546
        jz      .num_written2
547
@@:
548
        cmp     ecx, [esp+16+4]
549
        jae     .num_written2
550
        mov     al, ' '
551
        call    con.write_char
552
        inc     ecx
553
        jmp     @b
554
.num_written2:
555
        add     esp, 16
556
.spec_done:
557
        add     esp, 12
558
        jmp     .loop
559
.char:
560
        mov     ecx, [esp+4]
561
        cmp     ecx, -1
562
        jnz     @f
563
        inc     ecx
564
@@:
565
        test    ecx, ecx
566
        jnz     @f
567
        inc     ecx
568
@@:
569
        test    bh, 2
570
        jnz     .char_left_pad
571
        mov     al, ' '
572
        dec     ecx
573
        jz      .nowidth
574
        add     [esp+12+64+28], ecx
575
@@:
576
        call    con.write_char
577
        loop    @b
578
.nowidth:
579
        mov     al, [ebp]
580
        add     ebp, 4
581
        jmp     .percent
582
.char_left_pad:
583
        mov     al, [ebp]
584
        add     ebp, 4
585
        call    con.write_char_ex
586
        add     [esp+12+64+28], ecx
587
        dec     ecx
588
        jz      .nowidth2
589
        mov     al, ' '
590
@@:
591
        call    con.write_char
592
        loop    @b
593
.nowidth2:
594
        jmp     .spec_done
595
.string:
596
        push    esi
597
        mov     esi, [ebp]
598
        test    esi, esi
599
        jnz     @f
600
        mov     esi, con.aNull
601
@@:
602
        add     ebp, 4
603
        or      ecx, -1
604
@@:
605
        inc     ecx
606
        cmp     byte [esi+ecx], 0
607
        jnz     @b
608
        cmp     ecx, [esp+12]
609
        jb      @f
610
        mov     ecx, [esp+12]
611
@@:
612
        test    bh, 2
613
        jnz     .write_string
614
        cmp     dword [esp+8], -1
615
        jz      .write_string
616
        push    ecx
617
        sub     ecx, [esp+12]
618
        jae     .nospace
619
        mov     al, ' '
620
@@:
621
        call    con.write_char
622
        inc     dword [esp+20+64+28]
623
        inc     ecx
624
        jnz     @b
625
.nospace:
626
        pop     ecx
627
.write_string:
628
        jecxz   .string_written
629
        add     dword [esp+16+64+28], ecx
630
        push    ecx
631
@@:
632
        lodsb
633
        call    con.write_char_ex
634
        loop    @b
635
        pop     ecx
636
.string_written:
637
        pop     esi
638
        test    bh, 2
639
        jz      .spec_done
640
        cmp     dword [esp+4], -1
641
        jz      .spec_done
642
        sub     ecx, [esp+4]
643
        jae     .spec_done
644
        mov     al, ' '
645
@@:
646
        call    con.write_char
647
        inc     dword [esp+12+64+28]
648
        inc     ecx
649
        jnz     @b
650
        jmp     .spec_done
651
.done:
652
        add     esp, 64
653
        popad
654
        jmp     con.update_screen
655
.num_write_char:
656
        xchg    edi, [esp+20]
657
        call    con.write_char_ex
658
        inc     dword [esp+24+12+64+28]
659
        xchg    edi, [esp+20]
660
        inc     dword [esp+4]
661
        ret
662
 
663
con.write:
664
; esi = string, ebx = length (ebx=-1 for ASCIIZ strings)
665
        push    edi
666
        call    con.get_data_ptr
667
        test    ebx, ebx
668
        jz      .done
669
.loop:
670
        lodsb
671
        cmp     ebx, -1
672
        jnz     @f
673
        test    al, al
674
        jz      .done
675
@@:
676
        call    con.write_char_ex
677
.next:
678
        cmp     ebx, -1
679
        jz      .loop
680
        dec     ebx
681
        jnz     .loop
682
.done:
683
        pop     edi
684
        jmp     con.update_screen
685
 
686
con.get_data_ptr:
687
        mov     edi, [con.cur_y]
688
        imul    edi, [con.scr_width]
689
        add     edi, [con.cur_x]
690
        add     edi, edi
691
        add     edi, [con.data]
692
        ret
693
 
694
con.write_char_ex:
695
        test    byte [con_flags+1], 1
696
        jz      con.write_special_char
697
 
698
con.write_char:
699
        push    eax
700
        stosb
701
        mov     al, byte [con_flags]
702
        stosb
703
        mov     eax, [con.cur_x]
704
        inc     eax
705
        mov     [con.cur_x], eax
706
        cmp     eax, [con.scr_width]
707
        jb      @f
708
        and     [con.cur_x], 0
709
        call    con.newline
710
@@:
711
        pop     eax
712
        ret
713
 
714
con.write_special_char:
715
        cmp     [con_esc], 0
716
        jnz     .esc_mode
717
.normal_mode:
718
        cmp     al, 10
719
        jz      .write_lf
720
        cmp     al, 13
721
        jz      .write_cr
722
        cmp     al, 27
723
        jz      .write_esc
724
        cmp     al, 8
725
        jz      .write_bs
726
        cmp     al, 9
727
        jnz     con.write_char
728
.write_tab:
729
        mov     al, ' '
730
        call    con.write_char
731
        test    [con.cur_x], 7
732
        jnz     .write_tab
733
        ret
734
.write_cr:
735
        and     [con.cur_x], 0
736
        jmp     con.get_data_ptr
737
.write_lf:
738
        and     [con.cur_x], 0
739
        jmp     con.newline
740
.write_bs:
741
        cmp     [con.cur_x], 0
742
        jz      @f
743
        dec     [con.cur_x]
744
        dec     edi
745
        dec     edi
746
        ret
747
@@:
748
        push    eax
749
        mov     eax, [con.cur_y]
750
        dec     eax
751
        js      @f
752
        mov     [con.cur_y], eax
753
        mov     eax, [con.scr_width]
754
        dec     eax
755
        mov     [con.cur_x], eax
756
        dec     edi
757
        dec     edi
758
@@:
759
        pop     eax
760
        ret
761
.write_esc:
762
        mov     [con_esc], 1
763
        mov     [con_esc_attr_n], 1
764
        and     [con_esc_attrs], 0
765
        ret
766
.esc_mode:
767
        cmp     [con_sci], 0
768
        jnz     .esc_sci
769
        cmp     al, '['
770
        jnz     @f
771
        mov     [con_sci], 1
772
        ret
773
@@:
774
        push    eax
775
        mov     al, 27
776
        call    con.write_char
777
        pop     eax
778
        jmp     con.write_char
779
.esc_sci:
780
; this is real Esc sequence
781
        cmp     al, ';'
782
        jz      .next_arg
783
        cmp     al, '0'
784
        jb      .not_digit
785
        cmp     al, '9'
786
        ja      .not_digit
787
        push    eax ecx edx
788
        sub     al, '0'
789
        movzx   eax, al
790
        mov     ecx, [con_esc_attr_n]
791
        mov     edx, [con_esc_attrs+(ecx-1)*4]
792
        lea     edx, [edx*5]
793
        lea     edx, [edx*2+eax]
794
        mov     [con_esc_attrs+(ecx-1)*4], edx
795
        pop     edx ecx eax
796
        ret
797
.next_arg:
798
        push    eax
799
        mov     eax, [con_esc_attr_n]
800
        inc     eax
801
        cmp     al, 4
802
        jbe     @f
803
        dec     eax
804
@@:
805
        mov     [con_esc_attr_n], eax
806
        and     [con_esc_attrs+(eax-1)*4], 0
807
        pop     eax
808
        ret
809
.not_digit:
810
        mov     [con_esc], 0
811
        mov     [con_sci], 0    ; in any case, leave Esc mode
812
        cmp     al, 'm'
813
        jz      .set_attr
814
        ret     ; simply skip unknown sequences
815
.set_attr:
816
        push    eax ecx edx
817
        xor     ecx, ecx
818
.set_one_attr:
819
        mov     eax, [con_esc_attrs+ecx*4]
820
        cmp     al, 0
821
        jz      .attr_normal
822
        cmp     al, 1
823
        jz      .attr_bold
824
        cmp     al, 5
825
        jz      .attr_bgr_bold
826
        cmp     al, 7
827
        jz      .attr_reversed
828
        xor     edx, edx
829
        cmp     al, 30
830
        jz      .attr_color
831
        mov     dl, 4
832
        cmp     al, 31
833
        jz      .attr_color
834
        mov     dl, 2
835
        cmp     al, 32
836
        jz      .attr_color
837
        mov     dl, 6
838
        cmp     al, 33
839
        jz      .attr_color
840
        mov     dl, 1
841
        cmp     al, 34
842
        jz      .attr_color
843
        mov     dl, 5
844
        cmp     al, 35
845
        jz      .attr_color
846
        mov     dl, 3
847
        cmp     al, 36
848
        jz      .attr_color
849
        mov     dl, 7
850
        cmp     al, 37
851
        jz      .attr_color
852
        xor     edx, edx
853
        cmp     al, 40
854
        jz      .attr_bgr_color
855
        mov     dl, 0x40
856
        cmp     al, 41
857
        jz      .attr_bgr_color
858
        mov     dl, 0x20
859
        cmp     al, 42
860
        jz      .attr_bgr_color
861
        mov     dl, 0x60
862
        cmp     al, 43
863
        jz      .attr_bgr_color
864
        mov     dl, 0x10
865
        cmp     al, 44
866
        jz      .attr_bgr_color
867
        mov     dl, 0x50
868
        cmp     al, 45
869
        jz      .attr_bgr_color
870
        mov     dl, 0x30
871
        cmp     al, 46
872
        jz      .attr_bgr_color
873
        mov     dl, 0x70
874
        cmp     al, 47
875
        jnz     .attr_continue
876
.attr_bgr_color:
877
        mov     eax, [con_flags]
878
        and     al, 0x8F
879
        or      al, dl
880
        mov     [con_flags], eax
881
        jmp     .attr_continue
882
.attr_color:
883
        mov     eax, [con_flags]
884
        and     al, 0xF8
885
        or      al, dl
886
        mov     [con_flags], eax
887
        jmp     .attr_continue
888
.attr_normal:
889
        mov     byte [con_flags], 7
890
        jmp     .attr_continue
891
.attr_reversed:
892
        mov     byte [con_flags], 0x70
893
        jmp     .attr_continue
894
.attr_bold:
895
        or      byte [con_flags], 8
896
        jmp     .attr_continue
897
.attr_bgr_bold:
898
        or      byte [con_flags], 0x80
899
.attr_continue:
900
        inc     ecx
901
        cmp     ecx, [con_esc_attr_n]
902
        jb      .set_one_attr
903
        pop     edx ecx eax
904
        ret
905
 
906
con.newline:
907
        mov     eax, [con.cur_y]
908
        inc     eax
909
        mov     [con.cur_y], eax
910
        cmp     eax, [con.scr_height]
911
        jb      @f
912
        call    con.scr_scroll_up
913
@@:
914
        call    con.get_data_ptr
915
        ret
916
 
917
con.scr_scroll_up:
918
        pushad
919
        mov     edi, [con.data]
920
        mov     esi, edi
921
        add     esi, [con.scr_width]
922
        add     esi, [con.scr_width]
923
        dec     [con.cur_y]
924
        mov     ecx, [con.scr_height]
925
        dec     ecx
926
        imul    ecx, [con.scr_width]
927
        shr     ecx, 1
928
        rep     movsd
929
        adc     ecx, ecx
930
        rep     movsw
931
        mov     ax, 0x0720
932
        mov     ecx, [con.scr_width]
933
        rep     stosw
934
        popad
935
        ret
936
 
937
con.data2image:
938
        pushad
939
        mov     edi, [con.image]
940
        mov     esi, [con.data]
941
        mov     eax, [con.wnd_ypos]
942
        mul     [con.scr_width]
943
        add     eax, [con.wnd_xpos]
944
        lea     esi, [esi+eax*2]
945
        mov     ecx, [con.wnd_height]
946
.lh:
947
        push    ecx
948
        mov     ecx, [con.wnd_width]
949
.lw:
950
        push    ecx edi
951
        xor     eax, eax
952
        mov     al, [esi+1]
953
        push    eax
954
        and     al, 0xF
955
        mov     ebx, eax                ; цвет текста
956
        pop     eax
957
        shr     al, 4
958
        mov     ebp, eax                ; цвет фона
959
        sub     ebx, ebp
960
        lodsb
961
        inc     esi
962
if font_width > 8
963
        lea     edx, [eax+eax+font]
964
else
965
        lea     edx, [eax+font]
966
end if
967
.sh:
968
        mov     ecx, [edx]
969
repeat font_width
970
        shr     ecx, 1
971
        sbb     eax, eax
972
        and     eax, ebx
973
        add     eax, ebp
974
        mov     [edi+%-1], al
975
end repeat
976
        mov     eax, [con.wnd_width]
977
;        imul    eax, font_width
978
;        add     edi, eax
979
if font_width = 6
980
        lea     eax, [eax*2+eax]
981
        lea     edi, [edi+eax*2]
982
else if font_width = 7
983
        lea     edi, [edi+eax*8]
984
        sub     edi, eax
985
else if font_width = 8
986
        lea     edi, [edi+eax*8]
987
else if font_width = 9
988
        lea     edi, [edi+eax*8]
989
        add     edi, eax
990
else if font_width = 10
991
        lea     eax, [eax*4+eax]
992
        lea     edi, [edi+eax*2]
993
else
994
Unknown font_width value!
995
end if
996
if font_width > 8
997
        add     edx, 256*2
998
        cmp     edx, font+256*2*font_height
999
else
1000
        add     edx, 256
1001
        cmp     edx, font+256*font_height
1002
end if
1003
        jb      .sh
1004
        pop     edi ecx
1005
        add     edi, font_width
1006
        sub     ecx, 1
1007
        jnz     .lw
1008
        mov     eax, [con.wnd_width]
1009
        imul    eax, (font_height-1)*font_width
1010
        add     edi, eax
1011
        pop     ecx
1012
        mov     eax, [con.scr_width]
1013
        sub     eax, [con.wnd_width]
1014
        lea     esi, [esi+eax*2]
1015
        dec     ecx
1016
        jnz     .lh
1017
        mov     eax, [con.cur_y]
1018
        sub     eax, [con.wnd_ypos]
1019
        jb      .nocursor
1020
        cmp     eax, [con.wnd_height]
1021
        jae     .nocursor
1022
        inc     eax
1023
        mul     [con.wnd_width]
1024
        imul    eax, font_height*font_width
1025
        mov     edx, [con.cur_x]
1026
        sub     edx, [con.wnd_xpos]
1027
        jb      .nocursor
1028
        cmp     edx, [con.wnd_width]
1029
        jae     .nocursor
1030
        inc     edx
1031
        imul    edx, font_width
1032
        add     eax, edx
1033
        add     eax, [con.image]
1034
        mov     edx, [con.wnd_width]
1035
        imul    edx, font_width
1036
        neg     edx
1037
        mov     ecx, [con.cursor_height]
1038
        jecxz   .nocursor
1039
.cursor_loop:
1040
        push    ecx
1041
        mov     ecx, font_width
1042
        add     eax, edx
1043
        push    eax
1044
@@:
1045
        xor     byte [eax-1], 7
1046
        dec     eax
1047
        loop    @b
1048
        pop     eax
1049
        pop     ecx
1050
        loop    .cursor_loop
1051
.nocursor:
1052
        popad
1053
        ret
1054
 
1055
con_exit:
1056
        cmp     byte [esp+4], 0
1057
        jz      .noexit
1058
        mov     [con.thread_op], 1
1059
        call    con.wake
1060
        ret     4
1061
.noexit:
1062
        push    esi
1063
        mov     esi, [con.title]
1064
        mov     edx, con.finished_title
1065
        mov     ecx, 255
1066
        call    .strcpy
1067
        mov     esi, con.aFinished
1068
        call    .strcpy
1069
        mov     byte [edx], 0
1070
        pop     esi
1071
        and     [con.cursor_height], 0
1072
        push    con.finished_title
1073
        call    con_set_title
1074
        ret     4
1075
.strcpy:
1076
        jecxz   .ret
1077
@@:
1078
        lodsb
1079
        test    al, al
1080
        jz      .ret
1081
        mov     [edx], al
1082
        inc     edx
1083
        loop    @b
1084
.ret:
1085
        ret
1086
 
1087
con_set_title:
1088
        mov     eax, [esp+4]
1089
        mov     [con.title], eax
1090
        mov     [con.thread_op], 2
1091
        call    con.wake
1092
        ret     4
1093
 
1094
; int __stdcall con_kbhit(void);
1095
con_kbhit:
1096
        mov     eax, [con.input_start]
1097
        cmp     eax, [con.input_end]
1098
        setnz   al
1099
        movzx   eax, al
1100
        ret
1101
 
1102
con.force_entered_char:
1103
        cmp     [con.entered_char], -1
1104
        jnz     .ret
1105
        mov     [con.thread_op], 4
1106
        call    con.wake
1107
; wait for response
1108
        push    ebx
1109
        push    5
1110
        pop     eax
1111
        push    2
1112
        pop     ebx
1113
@@:
1114
        int     0x40
1115
        cmp     [con.entered_char], -1
1116
        jz      @b
1117
        pop     ebx
1118
.ret:
1119
        ret
1120
 
1121
; int __stdcall con_getch(void);
1122
con_getch:
1123
        call    con.force_entered_char
1124
        movzx   eax, byte [con.entered_char]
1125
        sar     [con.entered_char], 8
1126
        mov     byte [con.entered_char+1], 0xFF
1127
        test    al, al
1128
        jz      @f
1129
        mov     byte [con.entered_char], 0xFF
1130
@@:
1131
        ret
1132
 
1133
; int __stdcall con_getch2(void);
1134
con_getch2:
1135
        call    con.force_entered_char
1136
        mov     eax, 0xFFFF
1137
        xchg    ax, [con.entered_char]
1138
        ret
1139
 
1140
; void __stdcall con_gets(char* str, int n);
1141
con_gets:
1142
        pushad
1143
        mov     esi, [esp+20h+4]        ; str
1144
        mov     ebx, [esp+20h+8]        ; n
1145
        sub     ebx, 1
1146
        jle     .ret
1147
        mov     byte [esi], 0
1148
        xor     ecx, ecx                ; длина уже введённой строки
1149
        call    con.get_data_ptr
1150
.loop:
1151
        call    con_getch
1152
        test    al, al
1153
        jz      .extended
1154
        cmp     al, 8
1155
        jz      .backspace
1156
        cmp     al, 27
1157
        jz      .esc
1158
        cmp     al, 13
1159
        jz      .enter
1160
        inc     ecx
1161
        mov     dl, al
1162
        call    con.write_char_ex
1163
        push    [con.cur_x]
1164
        push    [con.cur_y]
1165
        push    edi
1166
        push    esi
1167
@@:
1168
        lodsb
1169
        mov     [esi-1], dl
1170
        mov     dl, al
1171
        test    al, al
1172
        jz      @f
1173
        call    con.write_char_ex
1174
        jmp     @b
1175
@@:
1176
        mov     [esi], dl
1177
        pop     esi
1178
        inc     esi
1179
        pop     edi
1180
        pop     [con.cur_y]
1181
        pop     [con.cur_x]
1182
.update_screen_and_loop:
1183
        call    con.update_screen
1184
        cmp     ecx, ebx
1185
        jb      .loop
1186
        mov     edx, [con.cur_x]
1187
@@:
1188
        lodsb
1189
        test    al, al
1190
        jz      @f
1191
        inc     edx
1192
        cmp     edx, [con.scr_width]
1193
        jb      @b
1194
        xor     edx, edx
1195
        call    con.newline
1196
        jmp     @b
1197
@@:
1198
        mov     [con.cur_x], edx
1199
        call    con.get_data_ptr
1200
        call    con.update_screen
1201
        jmp     .ret
1202
.esc:
1203
        mov     edx, [con.cur_x]
1204
@@:
1205
        lodsb
1206
        test    al, al
1207
        jz      @f
1208
        inc     edx
1209
        cmp     edx, [con.scr_width]
1210
        jb      @b
1211
        xor     edx, edx
1212
        call    con.newline
1213
        jmp     @b
1214
@@:
1215
        mov     [con.cur_x], edx
1216
        call    con.get_data_ptr
1217
        dec     esi
1218
        xor     ecx, ecx
1219
@@:
1220
        mov     byte [esi], 0
1221
        cmp     esi, [esp+20h+4]
1222
        jbe     .update_screen_and_loop
1223
        mov     al, 8
1224
        call    con.write_special_char
1225
        mov     al, ' '
1226
        call    con.write_char
1227
        mov     al, 8
1228
        call    con.write_special_char
1229
        dec     esi
1230
        jmp     @b
1231
.delete:
1232
        cmp     byte [esi], 0
1233
        jz      .loop
1234
        lodsb
1235
        call    con.write_char_ex
1236
.backspace:
1237
        cmp     esi, [esp+20h+4]
1238
        jbe     .loop
1239
        push    esi
1240
        mov     edx, [con.cur_x]
1241
@@:
1242
        lodsb
1243
        test    al, al
1244
        jz      @f
1245
        inc     edx
1246
        cmp     edx, [con.scr_width]
1247
        jb      @b
1248
        xor     edx, edx
1249
        call    con.newline
1250
        jmp     @b
1251
@@:
1252
        mov     [con.cur_x], edx
1253
        call    con.get_data_ptr
1254
        dec     esi
1255
        mov     al, 8
1256
        call    con.write_special_char
1257
        mov     al, ' '
1258
        call    con.write_char
1259
        mov     al, 8
1260
        call    con.write_special_char
1261
        mov     dl, 0
1262
@@:
1263
        cmp     esi, [esp]
1264
        jbe     @f
1265
        mov     al, 8
1266
        call    con.write_special_char
1267
        dec     esi
1268
        xchg    dl, [esi]
1269
        mov     al, dl
1270
        call    con.write_char
1271
        mov     al, 8
1272
        call    con.write_special_char
1273
        jmp     @b
1274
@@:
1275
        pop     esi
1276
        dec     esi
1277
        mov     [esi], dl
1278
        dec     ecx
1279
        jmp     .update_screen_and_loop
1280
.enter:
1281
        mov     edx, [con.cur_x]
1282
@@:
1283
        lodsb
1284
        test    al, al
1285
        jz      @f
1286
        inc     edx
1287
        cmp     edx, [con.scr_width]
1288
        jb      @b
1289
        xor     edx, edx
1290
        call    con.newline
1291
        jmp     @b
1292
@@:
1293
        mov     [con.cur_x], edx
1294
        call    con.get_data_ptr
1295
        mov     al, 10
1296
        mov     [esi-1], al
1297
        mov     byte [esi], 0
1298
        call    con.write_special_char
1299
        call    con.update_screen
1300
        jmp     .ret
1301
.extended:
1302
        call    con_getch
1303
        cmp     al, 0x4B
1304
        jz      .left
1305
        cmp     al, 0x4D
1306
        jz      .right
1307
        cmp     al, 0x47
1308
        jz      .home
1309
        cmp     al, 0x4F
1310
        jz      .end
1311
        cmp     al, 0x53
1312
        jz      .delete
1313
        jmp     .loop
1314
.left:
1315
        cmp     esi, [esp+20h+4]
1316
        jbe     .loop
1317
        dec     esi
1318
        mov     al, 8
1319
        call    con.write_special_char
1320
        jmp     .update_screen_and_loop
1321
.right:
1322
        cmp     byte [esi], 0
1323
        jz      .loop
1324
        lodsb
1325
        call    con.write_char_ex
1326
        jmp     .update_screen_and_loop
1327
.home:
1328
        cmp     esi, [esp+20h+4]
1329
        jz      .update_screen_and_loop
1330
        dec     esi
1331
        mov     al, 8
1332
        call    con.write_special_char
1333
        jmp     .home
1334
.end:
1335
        lodsb
1336
        test    al, al
1337
        jz      @f
1338
        call    con.write_char_ex
1339
        jmp     .end
1340
@@:
1341
        dec     esi
1342
        jmp     .update_screen_and_loop
1343
.ret:
1344
        popad
1345
        ret     8
1346
 
1347
con.update_screen:
1348
        push    eax
1349
        mov     eax, [con.cur_y]
1350
        sub     eax, [con.wnd_ypos]
1351
        jb      .up
1352
        cmp     eax, [con.wnd_height]
1353
        jb      .done
1354
        mov     eax, [con.cur_y]
1355
        sub     eax, [con.wnd_height]
1356
        inc     eax
1357
        jmp     .set
1358
.up:
1359
        mov     eax, [con.cur_y]
1360
.set:
1361
        mov     [con.wnd_ypos], eax
1362
.done:
1363
        pop     eax
1364
        mov     [con.thread_op], 3
1365
 
1366
con.wake:
1367
        pushad
1368
        mov     al, [con.thread_op]
1369
        cmp     al, byte [con.ipc_buf+0x10]
1370
        jz      .ret
1371
@@:
1372
        push    60
1373
        pop     eax
1374
        push    2
1375
        pop     ebx
1376
        mov     ecx, [con.console_tid]
1377
        mov     edx, con.thread_op
1378
        push    1
1379
        pop     esi
1380
        int     0x40
1381
        test    eax, eax
1382
        jz      @f
1383
        push    5
1384
        pop     eax
1385
        mov     bl, 1
1386
        int     0x40
1387
        jmp     @b
1388
@@:
1389
.ret:
1390
        popad
1391
        ret
1392
 
1393
; Поток окна консоли. Обрабатывает ввод и вывод.
1394
con.thread:
1395
; Поток реагирует на IPC, которое используется только для того, чтобы его можно было "разбудить"
1396
        push    40
1397
        pop     eax
1398
        push    0x67
1399
        pop     ebx
1400
        int     0x40
1401
        mov     al, 60
1402
        mov     bl, 1
1403
        mov     ecx, con.ipc_buf
1404
        push    0x11
1405
        pop     edx
1406
        int     0x40
1407
        mov     al, 66
1408
        mov     bl, 1
1409
        mov     ecx, ebx
1410
        int     0x40
1411
con.redraw:
1412
        call    con.draw_window
1413
con.msg_loop:
1414
        cmp     dword [con.bUpPressed], 0
1415
        jnz     .wait_timeout
1416
        push    10
1417
        pop     eax
1418
        jmp     @f
1419
.wait_timeout:
1420
        push    23
1421
        pop     eax
1422
        push    5
1423
        pop     ebx
1424
@@:
1425
        int     0x40
1426
        dec     eax
1427
        jz      con.redraw
1428
        dec     eax
1429
        jz      con.key
1430
        dec     eax
1431
        jz      con.button
1432
        cmp     al, 4
1433
        jz      con.ipc
1434
        jmp     con.mouse
1435
con.button:
1436
; we have only one button, close
1437
con.thread_exit:
1438
        or      eax, -1
1439
        int     0x40
1440
con.key:
1441
        mov     al, 2
1442
        int     0x40
1443
; ah = scancode
1444
        cmp     ah, 0xE0
1445
        jnz     @f
1446
        mov     [con.bWasE0], 1
1447
        jmp     con.msg_loop
1448
@@:
1449
        shr     eax, 8
1450
        xchg    ah, [con.bWasE0]
1451
        test    al, al
1452
        jle     con.msg_loop
1453
        cmp     al, 0x1D
1454
        jz      con.msg_loop
1455
        cmp     al, 0x2A
1456
        jz      con.msg_loop
1457
        cmp     al, 0x36
1458
        jz      con.msg_loop
1459
        cmp     al, 0x38
1460
        jz      con.msg_loop
1461
        cmp     al, 0x3A
1462
        jz      con.msg_loop
1463
        cmp     al, 0x45
1464
        jz      con.msg_loop
1465
        cmp     al, 0x46
1466
        jz      con.msg_loop
1467
        mov     edx, eax
1468
        push    66
1469
        pop     eax
1470
        push    3
1471
        pop     ebx
1472
        int     0x40    ; eax = control key state
1473
        test    dh, dh
1474
        jnz     .extended
1475
        bt      [scan_has_ascii], edx
1476
        jnc     .extended
1477
        test    al, 0x30
1478
        jnz     .extended
1479
; key has ASCII code
1480
        push    eax edx
1481
        push    2
1482
        pop     ecx
1483
        test    al, 3
1484
        jnz     @f
1485
        dec     ecx
1486
@@:
1487
        push    26
1488
        pop     eax
1489
        mov     bl, 2
1490
        mov     edx, con.kbd_layout
1491
        int     0x40
1492
        pop     edx eax
1493
        mov     dh, [con.kbd_layout+edx]
1494
        test    al, 0xC
1495
        jz      @f
1496
        sub     dh, 0x60
1497
        jmp     @f
1498
.extended:
1499
        mov     dh, 0   ; no ASCII code
1500
@@:
1501
; dh contains ASCII-code; now convert scancode to extended key code
1502
        mov     ecx, con.extended_alt
1503
        test    al, 0x30
1504
        jnz     .xlat
1505
        mov     ecx, con.extended_shift
1506
        test    al, 3
1507
        jnz     .xlat
1508
        mov     ecx, con.extended_ctrl
1509
        test    al, 0xC
1510
        jnz     .xlat
1511
        xchg    dl, dh
1512
        cmp     dh, 0x57
1513
        jz      @f
1514
        cmp     dh, 0x58
1515
        jnz     .gotcode
1516
@@:
1517
        add     dh, 0x85-0x57
1518
        jmp     .gotcode
1519
.xlat:
1520
        movzx   eax, dl
1521
        mov     dl, dh
1522
        mov     dh, [eax+ecx]
1523
.gotcode:
1524
        test    dh, dh
1525
        jz      con.msg_loop
1526
        cmp     dh, 0x94
1527
        jnz     @f
1528
        mov     dl, 0
1529
@@:
1530
; dx contains full keycode
1531
        cmp     [con.bGetchRequested], 0
1532
        jz      @f
1533
        mov     [con.entered_char], dx
1534
        jmp     con.msg_loop
1535
@@:
1536
        mov     eax, [con.input_end]
1537
        mov     ecx, eax
1538
        add     eax, 2
1539
        cmp     eax, con.input_buffer_end
1540
        jnz     @f
1541
        mov     eax, con.input_buffer
1542
@@:
1543
        cmp     eax, [con.input_start]
1544
        jnz     @f
1545
; buffer overflow, make beep and continue
1546
        push    55
1547
        pop     eax
1548
        mov     ebx, eax
1549
        mov     esi, con.beep
1550
        int     0x40
1551
        jmp     con.msg_loop
1552
@@:
1553
        mov     [ecx], dx
1554
        mov     [con.input_end], eax
1555
        jmp     con.msg_loop
1556
con.ipc:
1557
        movzx   eax, byte [con.ipc_buf+0x10]
1558
        mov     byte [con.ipc_buf+4], 8
1559
        mov     byte [con.ipc_buf+0x10], 0
1560
        dec     eax
1561
        jz      con.thread_exit
1562
        dec     eax
1563
        jz      con.set_title
1564
        dec     eax
1565
        jz      con.redraw_image
1566
        dec     eax
1567
        jz      con.getch
1568
        jmp     con.msg_loop
1569
con.set_title:
1570
        push    71
1571
        pop     eax
1572
        push    1
1573
        pop     ebx
1574
        mov     ecx, [con.title]
1575
        int     0x40
1576
        jmp     con.msg_loop
1577
con.redraw_image:
1578
        call    con.data2image
1579
        call    con.draw_image
1580
        jmp     con.msg_loop
1581
con.getch:
1582
        mov     eax, [con.input_start]
1583
        cmp     eax, [con.input_end]
1584
        jz      .noinput
1585
        mov     ecx, [eax]
1586
        mov     [con.entered_char], cx
1587
        inc     eax
1588
        inc     eax
1589
        cmp     eax, con.input_buffer_end
1590
        jnz     @f
1591
        mov     eax, con.input_buffer
1592
@@:
1593
        mov     [con.input_start], eax
1594
        jmp     con.msg_loop
1595
.noinput:
1596
        mov     [con.bGetchRequested], 1
1597
        jmp     con.msg_loop
1598
con.mouse:
1599
        xor     eax, eax
1600
        xchg    eax, dword [con.bUpPressed]
1601
        mov     dword [con.bUpPressed_saved], eax
1602
        push    37
1603
        pop     eax
1604
        push    2
1605
        pop     ebx
1606
        int     0x40
1607
        test    al, 1
1608
        jnz     @f
1609
        cmp     [con.vscroll_pt], -1
1610
        jz      .redraw_if_needed
1611
        or      [con.vscroll_pt], -1
1612
.redraw_if_needed:
1613
        cmp     dword [con.bUpPressed_saved], 0
1614
        jnz     con.redraw_image
1615
        jmp     con.msg_loop
1616
@@:
1617
        mov     al, 37
1618
        dec     ebx
1619
        int     0x40
1620
        movsx   ebx, ax
1621
        sar     eax, 16
1622
        cmp     [con.vscroll_pt], -1
1623
        jnz     .vscrolling
1624
        test    ebx, ebx
1625
        js      .redraw_if_needed
1626
        sub     ax, [con.data_width]
1627
        jb      .redraw_if_needed
1628
        cmp     eax, con.vscroll_width
1629
        jae     .redraw_if_needed
1630
        cmp     ebx, con.vscroll_btn_height
1631
        jb      .up
1632
        sub     bx, [con.data_height]
1633
        jae     .redraw_if_needed
1634
        cmp     bx, -con.vscroll_btn_height
1635
        jge     .down
1636
        add     bx, [con.data_height]
1637
        sub     bx, word [con.vscrollbar_pos]
1638
        jl      .vscroll_up
1639
        cmp     bx, word [con.vscrollbar_size]
1640
        jl      .vscroll
1641
.vscroll_down:
1642
        cmp     [con.bScrollingDown_saved], 0
1643
        jz      .vscroll_down_first
1644
        cmp     [con.bScrollingDown_saved], 1
1645
        jz      .vscroll_down_wasfirst
1646
        mov     [con.bScrollingDown], 2
1647
.vscroll_down_do:
1648
        mov     eax, [con.wnd_ypos]
1649
        add     eax, [con.wnd_height]
1650
        dec     eax
1651
        mov     ebx, [con.scr_height]
1652
        sub     ebx, [con.wnd_height]
1653
        cmp     eax, ebx
1654
        jb      @f
1655
        mov     eax, ebx
1656
@@:
1657
        mov     [con.wnd_ypos], eax
1658
        jmp     con.redraw_image
1659
.vscroll_down_first:
1660
        push    26
1661
        pop     eax
1662
        push    9
1663
        pop     ebx
1664
        int     0x40
1665
        mov     [con.scroll_down_first_time], eax
1666
        mov     [con.bScrollingDown], 1
1667
        jmp     .vscroll_down_do
1668
.vscroll_down_wasfirst:
1669
        push    26
1670
        pop     eax
1671
        push    9
1672
        pop     ebx
1673
        int     0x40
1674
        sub     eax, [con.scroll_down_first_time]
1675
        cmp     eax, 25
1676
        jb      @f
1677
        mov     [con.bScrollingDown], 2
1678
        jmp     .vscroll_down_do
1679
@@:
1680
        mov     [con.bScrollingDown], 1
1681
        jmp     con.msg_loop
1682
.vscroll_up:
1683
        cmp     [con.bScrollingUp_saved], 0
1684
        jz      .vscroll_up_first
1685
        cmp     [con.bScrollingUp_saved], 1
1686
        jz      .vscroll_up_wasfirst
1687
        mov     [con.bScrollingUp], 2
1688
.vscroll_up_do:
1689
        mov     eax, [con.wnd_ypos]
1690
        inc     eax
1691
        sub     eax, [con.wnd_height]
1692
        jns     @f
1693
        xor     eax, eax
1694
@@:
1695
        mov     [con.wnd_ypos], eax
1696
        jmp     con.redraw_image
1697
.vscroll_up_first:
1698
        push    26
1699
        pop     eax
1700
        push    9
1701
        pop     ebx
1702
        int     0x40
1703
        mov     [con.scroll_up_first_time], eax
1704
        mov     [con.bScrollingUp], 1
1705
        jmp     .vscroll_up_do
1706
.vscroll_up_wasfirst:
1707
        push    26
1708
        pop     eax
1709
        push    9
1710
        pop     ebx
1711
        int     0x40
1712
        sub     eax, [con.scroll_up_first_time]
1713
        cmp     eax, 25
1714
        jb      @f
1715
        mov     [con.bScrollingUp], 2
1716
        jmp     .vscroll_up_do
1717
@@:
1718
        mov     [con.bScrollingUp], 1
1719
        jmp     con.msg_loop
1720
.up:
1721
        cmp     [con.bUpPressed_saved], 0
1722
        jz      .up_first
1723
        cmp     [con.bUpPressed_saved], 1
1724
        jz      .up_wasfirst
1725
        mov     [con.bUpPressed], 2
1726
.up_do:
1727
        mov     eax, [con.wnd_ypos]
1728
        dec     eax
1729
        js      @f
1730
        mov     [con.wnd_ypos], eax
1731
@@:
1732
        jmp     con.redraw_image
1733
.up_first:
1734
        push    26
1735
        pop     eax
1736
        push    9
1737
        pop     ebx
1738
        int     0x40
1739
        mov     [con.up_first_time], eax
1740
        mov     [con.bUpPressed], 1
1741
        jmp     .up_do
1742
.up_wasfirst:
1743
        push    26
1744
        pop     eax
1745
        push    9
1746
        pop     ebx
1747
        int     0x40
1748
        sub     eax, [con.up_first_time]
1749
        cmp     eax, 25
1750
        jb      @f
1751
        mov     [con.bUpPressed], 2
1752
        jmp     .up_do
1753
@@:
1754
        mov     [con.bUpPressed], 1
1755
        jmp     con.msg_loop
1756
.down:
1757
        cmp     [con.bDownPressed_saved], 0
1758
        jz      .down_first
1759
        cmp     [con.bDownPressed_saved], 1
1760
        jz      .down_wasfirst
1761
        mov     [con.bDownPressed], 2
1762
.down_do:
1763
        mov     eax, [con.scr_height]
1764
        sub     eax, [con.wnd_height]
1765
        jbe     con.redraw_image
1766
        cmp     [con.wnd_ypos], eax
1767
        jae     con.redraw_image
1768
        inc     [con.wnd_ypos]
1769
        jmp     con.redraw_image
1770
.down_first:
1771
        push    26
1772
        pop     eax
1773
        push    9
1774
        pop     ebx
1775
        int     0x40
1776
        mov     [con.down_first_time], eax
1777
        mov     [con.bDownPressed], 1
1778
        jmp     .down_do
1779
.down_wasfirst:
1780
        push    26
1781
        pop     eax
1782
        push    9
1783
        pop     ebx
1784
        int     0x40
1785
        sub     eax, [con.down_first_time]
1786
        cmp     eax, 25
1787
        jb      @f
1788
        mov     [con.bDownPressed], 2
1789
        jmp     .down_do
1790
@@:
1791
        mov     [con.bDownPressed], 1
1792
        jmp     con.msg_loop
1793
.vscroll:
1794
        mov     [con.vscroll_pt], ebx
1795
        call    con.draw_image
1796
        jmp     con.msg_loop
1797
.vscrolling:
1798
        sub     ebx, [con.vscroll_pt]
1799
        sub     ebx, con.vscroll_btn_height
1800
        jge     @f
1801
        xor     ebx, ebx
1802
@@:
1803
        movzx   eax, [con.data_height]
1804
        sub     eax, 2*con.vscroll_btn_height
1805
        sub     eax, [con.vscrollbar_size]
1806
        cmp     ebx, eax
1807
        jb      @f
1808
        lea     ebx, [eax-1]
1809
@@:
1810
        xchg    eax, ebx
1811
        mov     edx, [con.scr_height]
1812
        sub     edx, [con.wnd_height]
1813
        inc     edx
1814
        mul     edx
1815
        div     ebx
1816
        cmp     [con.wnd_ypos], eax
1817
        jz      con.msg_loop
1818
        mov     [con.wnd_ypos], eax
1819
        jmp     con.redraw_image
1820
 
1821
con.draw_window:
1822
        push    12
1823
        pop     eax
1824
        xor     ebx, ebx
1825
        inc     ebx
1826
        int     0x40
1827
        mov     al, 48
1828
        mov     bl, 4
1829
        int     0x40
1830
        mov     ebx, [con.def_wnd_x-2]
1831
        mov     bx, word [con.wnd_width]
1832
        imul    bx, font_width
1833
        add     bx, 5+5-1
1834
        mov     ecx, [con.def_wnd_y-2]
1835
        mov     cx, word [con.wnd_height]
1836
        imul    cx, font_height
1837
        lea     ecx, [ecx+eax+5-1]
1838
        mov     edx, 0x33000000
1839
        mov     edi, [con.title]
1840
; place for scrollbar
1841
        mov     eax, [con.wnd_height]
1842
        cmp     eax, [con.scr_height]
1843
        jae     @f
1844
        add     ebx, con.vscroll_width
1845
@@:
1846
        xor     eax, eax
1847
        int     0x40
1848
        call    con.draw_image
1849
        push    12
1850
        pop     eax
1851
        push    2
1852
        pop     ebx
1853
        int     0x40
1854
        ret
1855
 
1856
con.draw_image:
1857
        xor     edx, edx
1858
        mov     ecx, [con.wnd_width]
1859
        imul    ecx, font_width
1860
        mov     [con.data_width], cx
1861
        shl     ecx, 16
1862
        mov     cx, word [con.wnd_height]
1863
        imul    cx, font_height
1864
        mov     [con.data_height], cx
1865
        mov     ebx, [con.image]
1866
        push    65
1867
        pop     eax
1868
        xor     ebp, ebp
1869
        mov     edi, con.colors
1870
        push    8
1871
        pop     esi
1872
        int     0x40
1873
        mov     al, 7
1874
        mov     edx, [con.wnd_height]
1875
        cmp     edx, [con.scr_height]
1876
        jae     .skip_vscroll
1877
        push    ecx
1878
        mov     edx, ecx
1879
        xor     dx, dx
1880
        mov     ebx, con.vscroll_btn3
1881
        cmp     [con.bUpPressed], 0
1882
        jnz     @f
1883
        mov     ebx, con.vscroll_btn1
1884
@@:
1885
        mov     ecx, con.vscroll_width*65536 + con.vscroll_btn_height
1886
        int     0x40
1887
        pop     edx
1888
        sub     dx, con.vscroll_btn_height
1889
        mov     ebx, con.vscroll_btn4
1890
        cmp     [con.bDownPressed], 0
1891
        jnz     @f
1892
        mov     ebx, con.vscroll_btn2
1893
@@:
1894
        int     0x40
1895
        push    edx
1896
; Вычисляем высоту бегунка
1897
        mov     ax, dx
1898
        sub     eax, con.vscroll_btn_height
1899
        mov     ecx, eax
1900
        mul     [con.wnd_height]
1901
        div     [con.scr_height]
1902
        cmp     eax, 5
1903
        jae     @f
1904
        mov     al, 5
1905
@@:
1906
; eax = высота бегунка. Вычисляем положение бегунка
1907
        mov     [con.vscrollbar_size], eax
1908
        xchg    eax, ecx
1909
        sub     eax, ecx
1910
        mul     [con.wnd_ypos]
1911
        mov     ebx, [con.scr_height]
1912
        sub     ebx, [con.wnd_height]
1913
        div     ebx
1914
        pop     edx
1915
        push    edx
1916
; ecx = высота бегунка, eax = положение
1917
        add     eax, con.vscroll_btn_height
1918
        mov     [con.vscrollbar_pos], eax
1919
        mov     ebx, con.vscroll_bgr2
1920
        cmp     [con.bScrollingUp], 0
1921
        jnz     @f
1922
        mov     ebx, con.vscroll_bgr1
1923
@@:
1924
        mov     ecx, con.vscroll_width*65536 + con.vscroll_bgr_height
1925
        push    eax
1926
        push    7
1927
        pop     eax
1928
        mov     dx, con.vscroll_btn_height
1929
        call    .vpattern
1930
        mov     dx, word [con.vscrollbar_pos]
1931
        add     dx, word [con.vscrollbar_size]
1932
        mov     cx, con.vscroll_bgr_height
1933
        mov     ebx, con.vscroll_bgr2
1934
        cmp     [con.bScrollingDown], 0
1935
        jnz     @f
1936
        mov     ebx, con.vscroll_bgr1
1937
@@:
1938
        call    .vpattern
1939
        mov     ecx, [con.vscrollbar_pos]
1940
        mov     dx, cx
1941
        add     ecx, [con.vscrollbar_size]
1942
        sub     ecx, con.vscroll_bar_height3
1943
        push    ecx
1944
        mov     ebx, con.vscroll_bar1
1945
        mov     ecx, con.vscroll_width*65536 + con.vscroll_bar_height1
1946
        int     0x40
1947
        add     dx, cx
1948
        mov     cx, con.vscroll_bar_height2
1949
        mov     ebx, con.vscroll_bar2
1950
        call    .vpattern
1951
        mov     ebx, con.vscroll_bar3
1952
        mov     cx, con.vscroll_bar_height3
1953
        int     0x40
1954
.skip_vscroll:
1955
        ret
1956
 
1957
.vpattern:
1958
        push    edx
1959
        add     dx, cx
1960
        cmp     dx, [esp+8]
1961
        pop     edx
1962
        jbe     @f
1963
        mov     cx, [esp+4]
1964
        sub     cx, dx
1965
        jz      .ret
1966
@@:
1967
        int     0x40
1968
        add     dx, cx
1969
        cmp     dx, [esp+4]
1970
        jb      .vpattern
1971
.ret:
1972
        ret     4
1973
 
1974
align 4
1975
con.colors      dd      0x000000, 0x000080, 0x008000, 0x008080
1976
                dd      0x800000, 0x800080, 0x808000, 0xC0C0C0
1977
                dd      0x808080, 0x0000FF, 0x00FF00, 0x00FFFF
1978
                dd      0xFF0000, 0xFF00FF, 0xFFFF00, 0xFFFFFF
1979
 
1980
scan_has_ascii:
1981
        dd      11011111111111111111111111111110b
1982
        dd      00000010001111111111101111111111b
1983
        dd      00000000000000000000000000000000b
1984
        dd      0
1985
 
1986
con.extended_alt:
1987
        db      00h,01h,78h,79h,7Ah,7Bh,7Ch,7Dh,7Eh,7Fh,80h,81h,82h,83h,0Eh,0A5h
1988
        db      10h,11h,12h,13h,14h,15h,16h,17h,18h,19h,1Ah,1Bh,1Ch,00h,1Eh,1Fh
1989
        db      20h,21h,22h,23h,24h,25h,26h,27h,28h,29h,00h,2Bh,2Ch,2Dh,2Eh,2Fh
1990
        db      30h,31h,32h,33h,34h,35h,00h,37h,00h,39h,00h,68h,69h,6Ah,6Bh,6Ch
1991
        db      6Dh,6Eh,6Fh,70h,71h,00h,00h,97h,98h,99h,4Ah,9Bh,9Ch,9Dh,4Eh,9Fh
1992
        db      0A0h,0A1h,0A2h,0A3h,00h,00h,00h,8Bh,8Ch,00h,00h,00h,00h,00h,00h,00h
1993
        times 20h db 0
1994
con.extended_ctrl:
1995
        times 0Fh db %-1
1996
        db      0x94
1997
        times 2Bh db %-1
1998
        db      5Eh,5Fh,60h,61h,62h,63h,64h,65h,66h,67h,00h,00h
1999
        db      77h,8Dh,84h,8Eh,73h,8Fh,74h,90h,75h,91h,76h,92h,93h,00h,00h,00h,89h,8Ah
2000
        times 0x80-0x59 db 0
2001
con.extended_shift:
2002
        times 3Bh db %-1
2003
        db      54h,55h,56h,57h,58h,59h,5Ah,5Bh,5Ch,5Dh,00h,00h
2004
        db      47h,48h,49h,4Ah,4Bh,4Ch,4Dh,4Eh,4Fh,50h,51h,52h,53h,00h,00h,00h,87h,88h
2005
        times 0x80-0x59 db 0
2006
 
2007
; В текущей реализации значения по умолчанию таковы.
2008
; В будущем они, возможно, будут считываться как параметры из ini-файла console.ini.
2009
con.def_wnd_width   dd    80
2010
con.def_wnd_height  dd    25
2011
con.def_scr_width   dd    80
2012
con.def_scr_height  dd    300
2013
con.def_wnd_x       dd    200
2014
con.def_wnd_y       dd    50
2015
 
2016
con.vscroll_pt      dd    -1
2017
 
2018
align 16
2019
EXPORTS:
2020
        dd      szStart,                START
2021
        dd      szVersion,              0x00020003
2022
        dd      szcon_init,             con_init
2023
        dd      szcon_write_asciiz,     con_write_asciiz
2024
        dd      szcon_printf,           con_printf
2025
        dd      szcon_exit,             con_exit
2026
        dd      szcon_get_flags,        con_get_flags
2027
        dd      szcon_set_flags,        con_set_flags
2028
        dd      szcon_kbhit,            con_kbhit
2029
        dd      szcon_getch,            con_getch
2030
        dd      szcon_getch2,           con_getch2
2031
        dd      szcon_gets,             con_gets
2032
        dd      szcon_get_font_height,  con_get_font_height
2033
        dd      szcon_get_cursor_height,con_get_cursor_height
2034
        dd      szcon_set_cursor_height,con_set_cursor_height
2035
        dd      0
2036
 
2037
con_flags       dd      7
2038
con.cursor_height dd    (15*font_height+50)/100
2039
con.input_start dd      con.input_buffer
2040
con.input_end   dd      con.input_buffer
2041
 
2042
con_esc_attr_n  dd      0
2043
con_esc_attrs   dd      0,0,0,0
2044
con_esc         db      0
2045
con_sci         db      0
2046
 
2047
con.entered_char dw     -1
2048
con.bGetchRequested db  0
2049
con.bWasE0       db     0
2050
 
2051
szStart                 db 'START',0
2052
 
2053
szcon_init              db 'con_init',0
2054
szcon_write_asciiz      db 'con_write_asciiz',0
2055
szcon_printf            db 'con_printf',0
2056
szcon_exit              db 'con_exit',0
2057
szVersion               db 'version',0
2058
szcon_get_flags         db 'con_get_flags',0
2059
szcon_set_flags         db 'con_set_flags',0
2060
szcon_kbhit             db 'con_kbhit',0
2061
szcon_getch             db 'con_getch',0
2062
szcon_getch2            db 'con_getch2',0
2063
szcon_gets              db 'con_gets',0
2064
szcon_get_font_height   db 'con_get_font_height',0
2065
szcon_get_cursor_height db 'con_get_cursor_height',0
2066
szcon_set_cursor_height db 'con_set_cursor_height',0
2067
 
2068
con.thread_err      db 'Cannot create console thread!',13,10,0
2069
con.nomem_err       db 'Not enough memory!',13,10,0
2070
con.aFinished       db ' [Finished]',0
2071
con.aNull           db '(null)',0
2072
con.beep                db      0x90, 0x3C, 0x00
2073
con.ipc_buf         dd 0,8,0,0
2074
                    db 0
2075
 
2076
section '.data' data readable writable align 16
2077
 
2078
con.finished_title          rb 256
2079
 
2080
con.cur_x                   rd 1
2081
con.cur_y                   rd 1
2082
con.wnd_xpos                rd 1
2083
con.wnd_ypos                rd 1
2084
 
2085
con.wnd_width               rd 1
2086
con.wnd_height              rd 1
2087
con.scr_width               rd 1
2088
con.scr_height              rd 1
2089
con.title                   rd 1
2090
con.data                    rd 1
2091
con.image                   rd 1
2092
con.console_tid             rd 1
2093
con.data_width              rw 1
2094
con.data_height             rw 1
2095
con.vscrollbar_size         rd 1
2096
con.vscrollbar_pos          rd 1
2097
con.up_first_time           rd 1
2098
con.down_first_time         rd 1
2099
con.scroll_up_first_time    rd 1
2100
con.scroll_down_first_time  rd 1
2101
con.bUpPressed_saved        rb 1
2102
con.bDownPressed_saved      rb 1
2103
con.bScrollingUp_saved      rb 1
2104
con.bScrollingDown_saved    rb 1
2105
 
2106
con.input_buffer                rw      128
2107
con.input_buffer_end = $
2108
 
2109
con.kbd_layout          rb      128
2110
 
2111
; 1 = exit, 2 = set title, 3 = redraw, 4 = getch
2112
con.thread_op               rb 1
2113
con.bUpPressed              rb 1
2114
con.bDownPressed            rb 1
2115
con.bScrollingUp            rb 1
2116
con.bScrollingDown          rb 1
2117
 
2118
con.stack                   rb 1024
2119
con.stack_top = $