Subversion Repositories Kolibri OS

Rev

Rev 836 | Rev 853 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
836 diamond 1
; Функции работы с консолью для программ КолибриОС
852 diamond 2
; diamond, 2006-2008
836 diamond 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:
852 diamond 1142
        pop     eax
1143
        push    0
1144
        push    eax
1145
; void __stdcall con_gets2(con_gets2_callback callback, char* str, int n);
1146
con_gets2:
836 diamond 1147
        pushad
852 diamond 1148
        mov     esi, [esp+20h+8]        ; str
1149
        mov     ebx, [esp+20h+12]       ; n
836 diamond 1150
        sub     ebx, 1
1151
        jle     .ret
1152
        mov     byte [esi], 0
1153
        xor     ecx, ecx                ; длина уже введённой строки
1154
        call    con.get_data_ptr
1155
.loop:
852 diamond 1156
        call    con_getch2
836 diamond 1157
        test    al, al
1158
        jz      .extended
1159
        cmp     al, 8
1160
        jz      .backspace
1161
        cmp     al, 27
1162
        jz      .esc
1163
        cmp     al, 13
1164
        jz      .enter
852 diamond 1165
        cmp     al, 9
1166
        jz      .tab
836 diamond 1167
        inc     ecx
1168
        mov     dl, al
1169
        call    con.write_char_ex
1170
        push    [con.cur_x]
1171
        push    [con.cur_y]
1172
        push    edi
1173
        push    esi
1174
@@:
1175
        lodsb
1176
        mov     [esi-1], dl
1177
        mov     dl, al
1178
        test    al, al
1179
        jz      @f
1180
        call    con.write_char_ex
1181
        jmp     @b
1182
@@:
1183
        mov     [esi], dl
1184
        pop     esi
1185
        inc     esi
1186
        pop     edi
1187
        pop     [con.cur_y]
1188
        pop     [con.cur_x]
1189
.update_screen_and_loop:
1190
        call    con.update_screen
1191
        cmp     ecx, ebx
1192
        jb      .loop
852 diamond 1193
.ret_us:
836 diamond 1194
        mov     edx, [con.cur_x]
1195
@@:
1196
        lodsb
1197
        test    al, al
1198
        jz      @f
1199
        inc     edx
1200
        cmp     edx, [con.scr_width]
1201
        jb      @b
1202
        xor     edx, edx
1203
        call    con.newline
1204
        jmp     @b
1205
@@:
1206
        mov     [con.cur_x], edx
1207
        call    con.get_data_ptr
1208
        call    con.update_screen
1209
        jmp     .ret
1210
.esc:
1211
        mov     edx, [con.cur_x]
1212
@@:
1213
        lodsb
1214
        test    al, al
1215
        jz      @f
1216
        inc     edx
1217
        cmp     edx, [con.scr_width]
1218
        jb      @b
1219
        xor     edx, edx
1220
        call    con.newline
1221
        jmp     @b
1222
@@:
1223
        mov     [con.cur_x], edx
1224
        call    con.get_data_ptr
1225
        dec     esi
1226
        xor     ecx, ecx
1227
@@:
1228
        mov     byte [esi], 0
852 diamond 1229
        cmp     esi, [esp+20h+8]
836 diamond 1230
        jbe     .update_screen_and_loop
1231
        mov     al, 8
1232
        call    con.write_special_char
1233
        mov     al, ' '
1234
        call    con.write_char
1235
        mov     al, 8
1236
        call    con.write_special_char
1237
        dec     esi
1238
        jmp     @b
1239
.delete:
1240
        cmp     byte [esi], 0
1241
        jz      .loop
1242
        lodsb
1243
        call    con.write_char_ex
1244
.backspace:
852 diamond 1245
        cmp     esi, [esp+20h+8]
836 diamond 1246
        jbe     .loop
1247
        push    esi
1248
        mov     edx, [con.cur_x]
1249
@@:
1250
        lodsb
1251
        test    al, al
1252
        jz      @f
1253
        inc     edx
1254
        cmp     edx, [con.scr_width]
1255
        jb      @b
1256
        xor     edx, edx
1257
        call    con.newline
1258
        jmp     @b
1259
@@:
1260
        mov     [con.cur_x], edx
1261
        call    con.get_data_ptr
1262
        dec     esi
1263
        mov     al, 8
1264
        call    con.write_special_char
1265
        mov     al, ' '
1266
        call    con.write_char
1267
        mov     al, 8
1268
        call    con.write_special_char
1269
        mov     dl, 0
1270
@@:
1271
        cmp     esi, [esp]
1272
        jbe     @f
1273
        mov     al, 8
1274
        call    con.write_special_char
1275
        dec     esi
1276
        xchg    dl, [esi]
1277
        mov     al, dl
1278
        call    con.write_char
1279
        mov     al, 8
1280
        call    con.write_special_char
1281
        jmp     @b
1282
@@:
1283
        pop     esi
1284
        dec     esi
1285
        mov     [esi], dl
1286
        dec     ecx
1287
        jmp     .update_screen_and_loop
1288
.enter:
1289
        mov     edx, [con.cur_x]
1290
@@:
1291
        lodsb
1292
        test    al, al
1293
        jz      @f
1294
        inc     edx
1295
        cmp     edx, [con.scr_width]
1296
        jb      @b
1297
        xor     edx, edx
1298
        call    con.newline
1299
        jmp     @b
1300
@@:
1301
        mov     [con.cur_x], edx
1302
        call    con.get_data_ptr
1303
        mov     al, 10
1304
        mov     [esi-1], al
1305
        mov     byte [esi], 0
1306
        call    con.write_special_char
1307
        call    con.update_screen
1308
        jmp     .ret
852 diamond 1309
.tab:
1310
        mov     al, 0
1311
        mov     ah, 0xF
836 diamond 1312
.extended:
852 diamond 1313
        xchg    al, ah
836 diamond 1314
        cmp     al, 0x4B
1315
        jz      .left
1316
        cmp     al, 0x4D
1317
        jz      .right
1318
        cmp     al, 0x47
1319
        jz      .home
1320
        cmp     al, 0x4F
1321
        jz      .end
1322
        cmp     al, 0x53
1323
        jz      .delete
852 diamond 1324
; give control to callback function
1325
        cmp     dword [esp+20h+4], 0
1326
        jz      .loop
1327
; remember length of text before and length of text after
1328
; and advance cursor to the end of line
1329
        push    ecx
1330
        push    eax
1331
        lea     edx, [esi+1]
1332
@@:
1333
        lodsb
1334
        test    al, al
1335
        jz      @f
1336
        call    con.write_char_ex
1337
        jmp     @b
1338
@@:
1339
        sub     esi, edx
1340
        pop     eax
1341
        push    esi
1342
        dec     edx
1343
        sub     edx, [esp+28h+8]
1344
        push    edx
1345
        push    esp             ; ppos
1346
        mov     ecx, [esp+30h+4]
1347
        lea     edx, [esp+30h+12]
1348
        push    edx             ; pn
1349
        lea     edx, [esp+34h+8]
1350
        push    edx             ; pstr
1351
        push    eax             ; keycode
1352
        call    ecx
1353
        call    con.get_data_ptr
1354
        dec     eax
1355
        js      .callback_nochange
1356
        jz      .callback_del
1357
        dec     eax
1358
        jz      .callback_output
1359
; callback returned 2 - exit
1360
        add     esp, 12
1361
        jmp     .ret
1362
.callback_nochange:
1363
; callback returned 0 - string was not changed, only restore cursor position
1364
        pop     esi
1365
        pop     ecx
1366
        test    ecx, ecx
1367
        jz      .cncs
1368
@@:
1369
        mov     al, 8
1370
        call    con.write_special_char
1371
        loop    @b
1372
.cncs:
1373
        pop     ecx
1374
        add     esi, [esp+20h+8]
1375
        jmp     .callback_done
1376
.callback_del:
1377
; callback returned 1 - string was changed, delete old string and output new
1378
        mov     ecx, [esp+8]
1379
        test    ecx, ecx
1380
        jz      .cds
1381
@@:
1382
        mov     al, 8
1383
        call    con.write_special_char
1384
        mov     al, ' '
1385
        call    con.write_char_ex
1386
        mov     al, 8
1387
        call    con.write_special_char
1388
        loop    @b
1389
.cds:
1390
.callback_output:
1391
; callback returned 2 - string was changed, output new string
1392
        pop     edx
1393
        pop     esi
1394
        pop     ecx
1395
        mov     esi, [esp+20h+8]
1396
        xor     ecx, ecx
1397
@@:
1398
        lodsb
1399
        test    al, al
1400
        jz      @f
1401
        call    con.write_char_ex
1402
        inc     ecx
1403
        jmp     @b
1404
@@:
1405
        dec     esi
1406
        push    ecx
1407
        sub     ecx, edx
1408
        jz      .cos
1409
@@:
1410
        mov     al, 8
1411
        call    con.write_special_char
1412
        dec     esi
1413
        loop    @b
1414
.cos:
1415
        pop     ecx
1416
.callback_done:
1417
        call    con.update_screen
1418
        mov     ebx, [esp+20h+12]
1419
        dec     ebx
1420
        cmp     ecx, ebx
1421
        jae     .ret_us
836 diamond 1422
        jmp     .loop
1423
.left:
852 diamond 1424
        cmp     esi, [esp+20h+8]
836 diamond 1425
        jbe     .loop
1426
        dec     esi
1427
        mov     al, 8
1428
        call    con.write_special_char
1429
        jmp     .update_screen_and_loop
1430
.right:
1431
        cmp     byte [esi], 0
1432
        jz      .loop
1433
        lodsb
1434
        call    con.write_char_ex
1435
        jmp     .update_screen_and_loop
1436
.home:
852 diamond 1437
        cmp     esi, [esp+20h+8]
836 diamond 1438
        jz      .update_screen_and_loop
1439
        dec     esi
1440
        mov     al, 8
1441
        call    con.write_special_char
1442
        jmp     .home
1443
.end:
1444
        lodsb
1445
        test    al, al
1446
        jz      @f
1447
        call    con.write_char_ex
1448
        jmp     .end
1449
@@:
1450
        dec     esi
1451
        jmp     .update_screen_and_loop
1452
.ret:
1453
        popad
852 diamond 1454
        ret     12
836 diamond 1455
 
1456
con.update_screen:
1457
        push    eax
1458
        mov     eax, [con.cur_y]
1459
        sub     eax, [con.wnd_ypos]
1460
        jb      .up
1461
        cmp     eax, [con.wnd_height]
1462
        jb      .done
1463
        mov     eax, [con.cur_y]
1464
        sub     eax, [con.wnd_height]
1465
        inc     eax
1466
        jmp     .set
1467
.up:
1468
        mov     eax, [con.cur_y]
1469
.set:
1470
        mov     [con.wnd_ypos], eax
1471
.done:
1472
        pop     eax
1473
        mov     [con.thread_op], 3
1474
 
1475
con.wake:
1476
        pushad
1477
        mov     al, [con.thread_op]
1478
        cmp     al, byte [con.ipc_buf+0x10]
1479
        jz      .ret
1480
@@:
1481
        push    60
1482
        pop     eax
1483
        push    2
1484
        pop     ebx
1485
        mov     ecx, [con.console_tid]
1486
        mov     edx, con.thread_op
1487
        push    1
1488
        pop     esi
1489
        int     0x40
1490
        test    eax, eax
1491
        jz      @f
1492
        push    5
1493
        pop     eax
1494
        mov     bl, 1
1495
        int     0x40
1496
        jmp     @b
1497
@@:
1498
.ret:
1499
        popad
1500
        ret
1501
 
1502
; Поток окна консоли. Обрабатывает ввод и вывод.
1503
con.thread:
1504
; Поток реагирует на IPC, которое используется только для того, чтобы его можно было "разбудить"
1505
        push    40
1506
        pop     eax
1507
        push    0x67
1508
        pop     ebx
1509
        int     0x40
1510
        mov     al, 60
1511
        mov     bl, 1
1512
        mov     ecx, con.ipc_buf
1513
        push    0x11
1514
        pop     edx
1515
        int     0x40
1516
        mov     al, 66
1517
        mov     bl, 1
1518
        mov     ecx, ebx
1519
        int     0x40
1520
con.redraw:
1521
        call    con.draw_window
1522
con.msg_loop:
1523
        cmp     dword [con.bUpPressed], 0
1524
        jnz     .wait_timeout
1525
        push    10
1526
        pop     eax
1527
        jmp     @f
1528
.wait_timeout:
1529
        push    23
1530
        pop     eax
1531
        push    5
1532
        pop     ebx
1533
@@:
1534
        int     0x40
1535
        dec     eax
1536
        jz      con.redraw
1537
        dec     eax
1538
        jz      con.key
1539
        dec     eax
1540
        jz      con.button
1541
        cmp     al, 4
1542
        jz      con.ipc
1543
        jmp     con.mouse
1544
con.button:
1545
; we have only one button, close
1546
con.thread_exit:
1547
        or      eax, -1
1548
        int     0x40
1549
con.key:
1550
        mov     al, 2
1551
        int     0x40
1552
; ah = scancode
1553
        cmp     ah, 0xE0
1554
        jnz     @f
1555
        mov     [con.bWasE0], 1
1556
        jmp     con.msg_loop
1557
@@:
1558
        shr     eax, 8
1559
        xchg    ah, [con.bWasE0]
1560
        test    al, al
1561
        jle     con.msg_loop
1562
        cmp     al, 0x1D
1563
        jz      con.msg_loop
1564
        cmp     al, 0x2A
1565
        jz      con.msg_loop
1566
        cmp     al, 0x36
1567
        jz      con.msg_loop
1568
        cmp     al, 0x38
1569
        jz      con.msg_loop
1570
        cmp     al, 0x3A
1571
        jz      con.msg_loop
1572
        cmp     al, 0x45
1573
        jz      con.msg_loop
1574
        cmp     al, 0x46
1575
        jz      con.msg_loop
1576
        mov     edx, eax
1577
        push    66
1578
        pop     eax
1579
        push    3
1580
        pop     ebx
1581
        int     0x40    ; eax = control key state
1582
        test    dh, dh
1583
        jnz     .extended
1584
        bt      [scan_has_ascii], edx
1585
        jnc     .extended
1586
        test    al, 0x30
1587
        jnz     .extended
1588
; key has ASCII code
1589
        push    eax edx
1590
        push    2
1591
        pop     ecx
1592
        test    al, 3
1593
        jnz     @f
1594
        dec     ecx
1595
@@:
1596
        push    26
1597
        pop     eax
1598
        mov     bl, 2
1599
        mov     edx, con.kbd_layout
1600
        int     0x40
1601
        pop     edx eax
1602
        mov     dh, [con.kbd_layout+edx]
1603
        test    al, 0xC
1604
        jz      @f
1605
        sub     dh, 0x60
1606
        jmp     @f
1607
.extended:
1608
        mov     dh, 0   ; no ASCII code
1609
@@:
1610
; dh contains ASCII-code; now convert scancode to extended key code
1611
        mov     ecx, con.extended_alt
1612
        test    al, 0x30
1613
        jnz     .xlat
1614
        mov     ecx, con.extended_shift
1615
        test    al, 3
1616
        jnz     .xlat
1617
        mov     ecx, con.extended_ctrl
1618
        test    al, 0xC
1619
        jnz     .xlat
1620
        xchg    dl, dh
1621
        cmp     dh, 0x57
1622
        jz      @f
1623
        cmp     dh, 0x58
1624
        jnz     .gotcode
1625
@@:
1626
        add     dh, 0x85-0x57
1627
        jmp     .gotcode
1628
.xlat:
1629
        movzx   eax, dl
1630
        mov     dl, dh
1631
        mov     dh, [eax+ecx]
1632
.gotcode:
1633
        test    dh, dh
1634
        jz      con.msg_loop
1635
        cmp     dh, 0x94
1636
        jnz     @f
1637
        mov     dl, 0
1638
@@:
1639
; dx contains full keycode
1640
        cmp     [con.bGetchRequested], 0
1641
        jz      @f
1642
        mov     [con.entered_char], dx
1643
        jmp     con.msg_loop
1644
@@:
1645
        mov     eax, [con.input_end]
1646
        mov     ecx, eax
1647
        add     eax, 2
1648
        cmp     eax, con.input_buffer_end
1649
        jnz     @f
1650
        mov     eax, con.input_buffer
1651
@@:
1652
        cmp     eax, [con.input_start]
1653
        jnz     @f
1654
; buffer overflow, make beep and continue
1655
        push    55
1656
        pop     eax
1657
        mov     ebx, eax
1658
        mov     esi, con.beep
1659
        int     0x40
1660
        jmp     con.msg_loop
1661
@@:
1662
        mov     [ecx], dx
1663
        mov     [con.input_end], eax
1664
        jmp     con.msg_loop
1665
con.ipc:
1666
        movzx   eax, byte [con.ipc_buf+0x10]
1667
        mov     byte [con.ipc_buf+4], 8
1668
        mov     byte [con.ipc_buf+0x10], 0
1669
        dec     eax
1670
        jz      con.thread_exit
1671
        dec     eax
1672
        jz      con.set_title
1673
        dec     eax
1674
        jz      con.redraw_image
1675
        dec     eax
1676
        jz      con.getch
1677
        jmp     con.msg_loop
1678
con.set_title:
1679
        push    71
1680
        pop     eax
1681
        push    1
1682
        pop     ebx
1683
        mov     ecx, [con.title]
1684
        int     0x40
1685
        jmp     con.msg_loop
1686
con.redraw_image:
1687
        call    con.data2image
1688
        call    con.draw_image
1689
        jmp     con.msg_loop
1690
con.getch:
1691
        mov     eax, [con.input_start]
1692
        cmp     eax, [con.input_end]
1693
        jz      .noinput
1694
        mov     ecx, [eax]
1695
        mov     [con.entered_char], cx
1696
        inc     eax
1697
        inc     eax
1698
        cmp     eax, con.input_buffer_end
1699
        jnz     @f
1700
        mov     eax, con.input_buffer
1701
@@:
1702
        mov     [con.input_start], eax
1703
        jmp     con.msg_loop
1704
.noinput:
1705
        mov     [con.bGetchRequested], 1
1706
        jmp     con.msg_loop
1707
con.mouse:
1708
        xor     eax, eax
1709
        xchg    eax, dword [con.bUpPressed]
1710
        mov     dword [con.bUpPressed_saved], eax
1711
        push    37
1712
        pop     eax
1713
        push    2
1714
        pop     ebx
1715
        int     0x40
1716
        test    al, 1
1717
        jnz     @f
1718
        cmp     [con.vscroll_pt], -1
1719
        jz      .redraw_if_needed
1720
        or      [con.vscroll_pt], -1
1721
.redraw_if_needed:
1722
        cmp     dword [con.bUpPressed_saved], 0
1723
        jnz     con.redraw_image
1724
        jmp     con.msg_loop
1725
@@:
1726
        mov     al, 37
1727
        dec     ebx
1728
        int     0x40
1729
        movsx   ebx, ax
1730
        sar     eax, 16
1731
        cmp     [con.vscroll_pt], -1
1732
        jnz     .vscrolling
1733
        test    ebx, ebx
1734
        js      .redraw_if_needed
1735
        sub     ax, [con.data_width]
1736
        jb      .redraw_if_needed
1737
        cmp     eax, con.vscroll_width
1738
        jae     .redraw_if_needed
1739
        cmp     ebx, con.vscroll_btn_height
1740
        jb      .up
1741
        sub     bx, [con.data_height]
1742
        jae     .redraw_if_needed
1743
        cmp     bx, -con.vscroll_btn_height
1744
        jge     .down
1745
        add     bx, [con.data_height]
1746
        sub     bx, word [con.vscrollbar_pos]
1747
        jl      .vscroll_up
1748
        cmp     bx, word [con.vscrollbar_size]
1749
        jl      .vscroll
1750
.vscroll_down:
1751
        cmp     [con.bScrollingDown_saved], 0
1752
        jz      .vscroll_down_first
1753
        cmp     [con.bScrollingDown_saved], 1
1754
        jz      .vscroll_down_wasfirst
1755
        mov     [con.bScrollingDown], 2
1756
.vscroll_down_do:
1757
        mov     eax, [con.wnd_ypos]
1758
        add     eax, [con.wnd_height]
1759
        dec     eax
1760
        mov     ebx, [con.scr_height]
1761
        sub     ebx, [con.wnd_height]
1762
        cmp     eax, ebx
1763
        jb      @f
1764
        mov     eax, ebx
1765
@@:
1766
        mov     [con.wnd_ypos], eax
1767
        jmp     con.redraw_image
1768
.vscroll_down_first:
1769
        push    26
1770
        pop     eax
1771
        push    9
1772
        pop     ebx
1773
        int     0x40
1774
        mov     [con.scroll_down_first_time], eax
1775
        mov     [con.bScrollingDown], 1
1776
        jmp     .vscroll_down_do
1777
.vscroll_down_wasfirst:
1778
        push    26
1779
        pop     eax
1780
        push    9
1781
        pop     ebx
1782
        int     0x40
1783
        sub     eax, [con.scroll_down_first_time]
1784
        cmp     eax, 25
1785
        jb      @f
1786
        mov     [con.bScrollingDown], 2
1787
        jmp     .vscroll_down_do
1788
@@:
1789
        mov     [con.bScrollingDown], 1
1790
        jmp     con.msg_loop
1791
.vscroll_up:
1792
        cmp     [con.bScrollingUp_saved], 0
1793
        jz      .vscroll_up_first
1794
        cmp     [con.bScrollingUp_saved], 1
1795
        jz      .vscroll_up_wasfirst
1796
        mov     [con.bScrollingUp], 2
1797
.vscroll_up_do:
1798
        mov     eax, [con.wnd_ypos]
1799
        inc     eax
1800
        sub     eax, [con.wnd_height]
1801
        jns     @f
1802
        xor     eax, eax
1803
@@:
1804
        mov     [con.wnd_ypos], eax
1805
        jmp     con.redraw_image
1806
.vscroll_up_first:
1807
        push    26
1808
        pop     eax
1809
        push    9
1810
        pop     ebx
1811
        int     0x40
1812
        mov     [con.scroll_up_first_time], eax
1813
        mov     [con.bScrollingUp], 1
1814
        jmp     .vscroll_up_do
1815
.vscroll_up_wasfirst:
1816
        push    26
1817
        pop     eax
1818
        push    9
1819
        pop     ebx
1820
        int     0x40
1821
        sub     eax, [con.scroll_up_first_time]
1822
        cmp     eax, 25
1823
        jb      @f
1824
        mov     [con.bScrollingUp], 2
1825
        jmp     .vscroll_up_do
1826
@@:
1827
        mov     [con.bScrollingUp], 1
1828
        jmp     con.msg_loop
1829
.up:
1830
        cmp     [con.bUpPressed_saved], 0
1831
        jz      .up_first
1832
        cmp     [con.bUpPressed_saved], 1
1833
        jz      .up_wasfirst
1834
        mov     [con.bUpPressed], 2
1835
.up_do:
1836
        mov     eax, [con.wnd_ypos]
1837
        dec     eax
1838
        js      @f
1839
        mov     [con.wnd_ypos], eax
1840
@@:
1841
        jmp     con.redraw_image
1842
.up_first:
1843
        push    26
1844
        pop     eax
1845
        push    9
1846
        pop     ebx
1847
        int     0x40
1848
        mov     [con.up_first_time], eax
1849
        mov     [con.bUpPressed], 1
1850
        jmp     .up_do
1851
.up_wasfirst:
1852
        push    26
1853
        pop     eax
1854
        push    9
1855
        pop     ebx
1856
        int     0x40
1857
        sub     eax, [con.up_first_time]
1858
        cmp     eax, 25
1859
        jb      @f
1860
        mov     [con.bUpPressed], 2
1861
        jmp     .up_do
1862
@@:
1863
        mov     [con.bUpPressed], 1
1864
        jmp     con.msg_loop
1865
.down:
1866
        cmp     [con.bDownPressed_saved], 0
1867
        jz      .down_first
1868
        cmp     [con.bDownPressed_saved], 1
1869
        jz      .down_wasfirst
1870
        mov     [con.bDownPressed], 2
1871
.down_do:
1872
        mov     eax, [con.scr_height]
1873
        sub     eax, [con.wnd_height]
1874
        jbe     con.redraw_image
1875
        cmp     [con.wnd_ypos], eax
1876
        jae     con.redraw_image
1877
        inc     [con.wnd_ypos]
1878
        jmp     con.redraw_image
1879
.down_first:
1880
        push    26
1881
        pop     eax
1882
        push    9
1883
        pop     ebx
1884
        int     0x40
1885
        mov     [con.down_first_time], eax
1886
        mov     [con.bDownPressed], 1
1887
        jmp     .down_do
1888
.down_wasfirst:
1889
        push    26
1890
        pop     eax
1891
        push    9
1892
        pop     ebx
1893
        int     0x40
1894
        sub     eax, [con.down_first_time]
1895
        cmp     eax, 25
1896
        jb      @f
1897
        mov     [con.bDownPressed], 2
1898
        jmp     .down_do
1899
@@:
1900
        mov     [con.bDownPressed], 1
1901
        jmp     con.msg_loop
1902
.vscroll:
1903
        mov     [con.vscroll_pt], ebx
1904
        call    con.draw_image
1905
        jmp     con.msg_loop
1906
.vscrolling:
1907
        sub     ebx, [con.vscroll_pt]
1908
        sub     ebx, con.vscroll_btn_height
1909
        jge     @f
1910
        xor     ebx, ebx
1911
@@:
1912
        movzx   eax, [con.data_height]
1913
        sub     eax, 2*con.vscroll_btn_height
1914
        sub     eax, [con.vscrollbar_size]
1915
        cmp     ebx, eax
1916
        jb      @f
1917
        lea     ebx, [eax-1]
1918
@@:
1919
        xchg    eax, ebx
1920
        mov     edx, [con.scr_height]
1921
        sub     edx, [con.wnd_height]
1922
        inc     edx
1923
        mul     edx
1924
        div     ebx
1925
        cmp     [con.wnd_ypos], eax
1926
        jz      con.msg_loop
1927
        mov     [con.wnd_ypos], eax
1928
        jmp     con.redraw_image
1929
 
1930
con.draw_window:
1931
        push    12
1932
        pop     eax
1933
        xor     ebx, ebx
1934
        inc     ebx
1935
        int     0x40
1936
        mov     al, 48
1937
        mov     bl, 4
1938
        int     0x40
1939
        mov     ebx, [con.def_wnd_x-2]
1940
        mov     bx, word [con.wnd_width]
1941
        imul    bx, font_width
1942
        add     bx, 5+5-1
1943
        mov     ecx, [con.def_wnd_y-2]
1944
        mov     cx, word [con.wnd_height]
1945
        imul    cx, font_height
1946
        lea     ecx, [ecx+eax+5-1]
1947
        mov     edx, 0x33000000
1948
        mov     edi, [con.title]
1949
; place for scrollbar
1950
        mov     eax, [con.wnd_height]
1951
        cmp     eax, [con.scr_height]
1952
        jae     @f
1953
        add     ebx, con.vscroll_width
1954
@@:
1955
        xor     eax, eax
1956
        int     0x40
1957
        call    con.draw_image
1958
        push    12
1959
        pop     eax
1960
        push    2
1961
        pop     ebx
1962
        int     0x40
1963
        ret
1964
 
1965
con.draw_image:
1966
        xor     edx, edx
1967
        mov     ecx, [con.wnd_width]
1968
        imul    ecx, font_width
1969
        mov     [con.data_width], cx
1970
        shl     ecx, 16
1971
        mov     cx, word [con.wnd_height]
1972
        imul    cx, font_height
1973
        mov     [con.data_height], cx
1974
        mov     ebx, [con.image]
1975
        push    65
1976
        pop     eax
1977
        xor     ebp, ebp
1978
        mov     edi, con.colors
1979
        push    8
1980
        pop     esi
1981
        int     0x40
1982
        mov     al, 7
1983
        mov     edx, [con.wnd_height]
1984
        cmp     edx, [con.scr_height]
1985
        jae     .skip_vscroll
1986
        push    ecx
1987
        mov     edx, ecx
1988
        xor     dx, dx
1989
        mov     ebx, con.vscroll_btn3
1990
        cmp     [con.bUpPressed], 0
1991
        jnz     @f
1992
        mov     ebx, con.vscroll_btn1
1993
@@:
1994
        mov     ecx, con.vscroll_width*65536 + con.vscroll_btn_height
1995
        int     0x40
1996
        pop     edx
1997
        sub     dx, con.vscroll_btn_height
1998
        mov     ebx, con.vscroll_btn4
1999
        cmp     [con.bDownPressed], 0
2000
        jnz     @f
2001
        mov     ebx, con.vscroll_btn2
2002
@@:
2003
        int     0x40
2004
        push    edx
2005
; Вычисляем высоту бегунка
2006
        mov     ax, dx
2007
        sub     eax, con.vscroll_btn_height
2008
        mov     ecx, eax
2009
        mul     [con.wnd_height]
2010
        div     [con.scr_height]
2011
        cmp     eax, 5
2012
        jae     @f
2013
        mov     al, 5
2014
@@:
2015
; eax = высота бегунка. Вычисляем положение бегунка
2016
        mov     [con.vscrollbar_size], eax
2017
        xchg    eax, ecx
2018
        sub     eax, ecx
2019
        mul     [con.wnd_ypos]
2020
        mov     ebx, [con.scr_height]
2021
        sub     ebx, [con.wnd_height]
2022
        div     ebx
2023
        pop     edx
2024
        push    edx
2025
; ecx = высота бегунка, eax = положение
2026
        add     eax, con.vscroll_btn_height
2027
        mov     [con.vscrollbar_pos], eax
2028
        mov     ebx, con.vscroll_bgr2
2029
        cmp     [con.bScrollingUp], 0
2030
        jnz     @f
2031
        mov     ebx, con.vscroll_bgr1
2032
@@:
2033
        mov     ecx, con.vscroll_width*65536 + con.vscroll_bgr_height
2034
        push    eax
2035
        push    7
2036
        pop     eax
2037
        mov     dx, con.vscroll_btn_height
2038
        call    .vpattern
2039
        mov     dx, word [con.vscrollbar_pos]
2040
        add     dx, word [con.vscrollbar_size]
2041
        mov     cx, con.vscroll_bgr_height
2042
        mov     ebx, con.vscroll_bgr2
2043
        cmp     [con.bScrollingDown], 0
2044
        jnz     @f
2045
        mov     ebx, con.vscroll_bgr1
2046
@@:
2047
        call    .vpattern
2048
        mov     ecx, [con.vscrollbar_pos]
2049
        mov     dx, cx
2050
        add     ecx, [con.vscrollbar_size]
2051
        sub     ecx, con.vscroll_bar_height3
2052
        push    ecx
2053
        mov     ebx, con.vscroll_bar1
2054
        mov     ecx, con.vscroll_width*65536 + con.vscroll_bar_height1
2055
        int     0x40
2056
        add     dx, cx
2057
        mov     cx, con.vscroll_bar_height2
2058
        mov     ebx, con.vscroll_bar2
2059
        call    .vpattern
2060
        mov     ebx, con.vscroll_bar3
2061
        mov     cx, con.vscroll_bar_height3
2062
        int     0x40
2063
.skip_vscroll:
2064
        ret
2065
 
2066
.vpattern:
2067
        push    edx
2068
        add     dx, cx
2069
        cmp     dx, [esp+8]
2070
        pop     edx
2071
        jbe     @f
2072
        mov     cx, [esp+4]
2073
        sub     cx, dx
2074
        jz      .ret
2075
@@:
2076
        int     0x40
2077
        add     dx, cx
2078
        cmp     dx, [esp+4]
2079
        jb      .vpattern
2080
.ret:
2081
        ret     4
2082
 
2083
align 4
2084
con.colors      dd      0x000000, 0x000080, 0x008000, 0x008080
2085
                dd      0x800000, 0x800080, 0x808000, 0xC0C0C0
2086
                dd      0x808080, 0x0000FF, 0x00FF00, 0x00FFFF
2087
                dd      0xFF0000, 0xFF00FF, 0xFFFF00, 0xFFFFFF
2088
 
2089
scan_has_ascii:
2090
        dd      11011111111111111111111111111110b
2091
        dd      00000010001111111111101111111111b
2092
        dd      00000000000000000000000000000000b
2093
        dd      0
2094
 
2095
con.extended_alt:
2096
        db      00h,01h,78h,79h,7Ah,7Bh,7Ch,7Dh,7Eh,7Fh,80h,81h,82h,83h,0Eh,0A5h
2097
        db      10h,11h,12h,13h,14h,15h,16h,17h,18h,19h,1Ah,1Bh,1Ch,00h,1Eh,1Fh
2098
        db      20h,21h,22h,23h,24h,25h,26h,27h,28h,29h,00h,2Bh,2Ch,2Dh,2Eh,2Fh
2099
        db      30h,31h,32h,33h,34h,35h,00h,37h,00h,39h,00h,68h,69h,6Ah,6Bh,6Ch
2100
        db      6Dh,6Eh,6Fh,70h,71h,00h,00h,97h,98h,99h,4Ah,9Bh,9Ch,9Dh,4Eh,9Fh
2101
        db      0A0h,0A1h,0A2h,0A3h,00h,00h,00h,8Bh,8Ch,00h,00h,00h,00h,00h,00h,00h
2102
        times 20h db 0
2103
con.extended_ctrl:
2104
        times 0Fh db %-1
2105
        db      0x94
2106
        times 2Bh db %-1
2107
        db      5Eh,5Fh,60h,61h,62h,63h,64h,65h,66h,67h,00h,00h
2108
        db      77h,8Dh,84h,8Eh,73h,8Fh,74h,90h,75h,91h,76h,92h,93h,00h,00h,00h,89h,8Ah
2109
        times 0x80-0x59 db 0
2110
con.extended_shift:
2111
        times 3Bh db %-1
2112
        db      54h,55h,56h,57h,58h,59h,5Ah,5Bh,5Ch,5Dh,00h,00h
2113
        db      47h,48h,49h,4Ah,4Bh,4Ch,4Dh,4Eh,4Fh,50h,51h,52h,53h,00h,00h,00h,87h,88h
2114
        times 0x80-0x59 db 0
2115
 
2116
; В текущей реализации значения по умолчанию таковы.
2117
; В будущем они, возможно, будут считываться как параметры из ini-файла console.ini.
2118
con.def_wnd_width   dd    80
2119
con.def_wnd_height  dd    25
2120
con.def_scr_width   dd    80
2121
con.def_scr_height  dd    300
2122
con.def_wnd_x       dd    200
2123
con.def_wnd_y       dd    50
2124
 
2125
con.vscroll_pt      dd    -1
2126
 
2127
align 16
2128
EXPORTS:
2129
        dd      szStart,                START
852 diamond 2130
        dd      szVersion,              0x00020004
836 diamond 2131
        dd      szcon_init,             con_init
2132
        dd      szcon_write_asciiz,     con_write_asciiz
2133
        dd      szcon_printf,           con_printf
2134
        dd      szcon_exit,             con_exit
2135
        dd      szcon_get_flags,        con_get_flags
2136
        dd      szcon_set_flags,        con_set_flags
2137
        dd      szcon_kbhit,            con_kbhit
2138
        dd      szcon_getch,            con_getch
2139
        dd      szcon_getch2,           con_getch2
2140
        dd      szcon_gets,             con_gets
852 diamond 2141
        dd      szcon_gets2,            con_gets2
836 diamond 2142
        dd      szcon_get_font_height,  con_get_font_height
2143
        dd      szcon_get_cursor_height,con_get_cursor_height
2144
        dd      szcon_set_cursor_height,con_set_cursor_height
2145
        dd      0
2146
 
2147
con_flags       dd      7
2148
con.cursor_height dd    (15*font_height+50)/100
2149
con.input_start dd      con.input_buffer
2150
con.input_end   dd      con.input_buffer
2151
 
2152
con_esc_attr_n  dd      0
2153
con_esc_attrs   dd      0,0,0,0
2154
con_esc         db      0
2155
con_sci         db      0
2156
 
2157
con.entered_char dw     -1
2158
con.bGetchRequested db  0
2159
con.bWasE0       db     0
2160
 
2161
szStart                 db 'START',0
2162
 
2163
szcon_init              db 'con_init',0
2164
szcon_write_asciiz      db 'con_write_asciiz',0
2165
szcon_printf            db 'con_printf',0
2166
szcon_exit              db 'con_exit',0
2167
szVersion               db 'version',0
2168
szcon_get_flags         db 'con_get_flags',0
2169
szcon_set_flags         db 'con_set_flags',0
2170
szcon_kbhit             db 'con_kbhit',0
2171
szcon_getch             db 'con_getch',0
2172
szcon_getch2            db 'con_getch2',0
2173
szcon_gets              db 'con_gets',0
852 diamond 2174
szcon_gets2             db 'con_gets2',0
836 diamond 2175
szcon_get_font_height   db 'con_get_font_height',0
2176
szcon_get_cursor_height db 'con_get_cursor_height',0
2177
szcon_set_cursor_height db 'con_set_cursor_height',0
2178
 
2179
con.thread_err      db 'Cannot create console thread!',13,10,0
2180
con.nomem_err       db 'Not enough memory!',13,10,0
2181
con.aFinished       db ' [Finished]',0
2182
con.aNull           db '(null)',0
2183
con.beep                db      0x90, 0x3C, 0x00
2184
con.ipc_buf         dd 0,8,0,0
2185
                    db 0
2186
 
2187
section '.data' data readable writable align 16
2188
 
2189
con.finished_title          rb 256
2190
 
2191
con.cur_x                   rd 1
2192
con.cur_y                   rd 1
2193
con.wnd_xpos                rd 1
2194
con.wnd_ypos                rd 1
2195
 
2196
con.wnd_width               rd 1
2197
con.wnd_height              rd 1
2198
con.scr_width               rd 1
2199
con.scr_height              rd 1
2200
con.title                   rd 1
2201
con.data                    rd 1
2202
con.image                   rd 1
2203
con.console_tid             rd 1
2204
con.data_width              rw 1
2205
con.data_height             rw 1
2206
con.vscrollbar_size         rd 1
2207
con.vscrollbar_pos          rd 1
2208
con.up_first_time           rd 1
2209
con.down_first_time         rd 1
2210
con.scroll_up_first_time    rd 1
2211
con.scroll_down_first_time  rd 1
2212
con.bUpPressed_saved        rb 1
2213
con.bDownPressed_saved      rb 1
2214
con.bScrollingUp_saved      rb 1
2215
con.bScrollingDown_saved    rb 1
2216
 
2217
con.input_buffer                rw      128
2218
con.input_buffer_end = $
2219
 
2220
con.kbd_layout          rb      128
2221
 
2222
; 1 = exit, 2 = set title, 3 = redraw, 4 = getch
2223
con.thread_op               rb 1
2224
con.bUpPressed              rb 1
2225
con.bDownPressed            rb 1
2226
con.bScrollingUp            rb 1
2227
con.bScrollingDown          rb 1
2228
 
2229
con.stack                   rb 1024
2230
con.stack_top = $