Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
94 mario79 1
 
87 mario79 2
cd_current_pointer_of_input    dd  0
3
cd_current_pointer_of_input_2  dd  0
4
cd_mem_location                dd  0
5
cd_counter_block               dd  0
6
IDE_Channel_1                  db  0
95 mario79 7
IDE_Channel_2                  db  0
8
endg
87 mario79 9
10
 
11
12
 
13
14
 
15
    cmp   [cd_status],0
16
    je    reserve_ok2
17
18
 
19
    call  change_task
20
    jmp   reserve_cd
95 mario79 21
87 mario79 22
 
23
24
 
25
    mov   eax,[0x3000]
26
    shl   eax,5
27
    mov   eax,[eax+0x3000+4]
28
    mov   [cd_status],eax
29
    pop   eax
30
    sti
31
    ret
32
95 mario79 33
 
34
    cmp   [ChannelNumber],1
35
    jne   .IDE_Channel_2
36
.IDE_Channel_1:
37
    cli
38
    cmp   [IDE_Channel_1],0
39
    je    .reserve_ok_1
40
    sti
41
    call  change_task
42
    jmp   .IDE_Channel_1
43
.IDE_Channel_2:
44
    cli
45
    cmp   [IDE_Channel_2],0
46
    je    .reserve_ok_2
47
    sti
48
    call  change_task
49
    jmp   .IDE_Channel_1
50
.reserve_ok_1:
51
    mov [IDE_Channel_1],1
52
    ret
53
.reserve_ok_2:
54
    mov [IDE_Channel_2],1
55
    ret
56
57
 
58
    cmp   [ChannelNumber],1
59
    jne   .IDE_Channel_2
60
.IDE_Channel_1:
61
    mov [IDE_Channel_1],0
62
    ret
63
.IDE_Channel_2:
64
    mov [IDE_Channel_2],0
65
    ret
66
87 mario79 67
 
68
69
 
70
;
71
;  fs_CdRead - LFN variant for reading CD disk
72
;
73
;  esi  points to filename /dir1/dir2/.../dirn/file,0
74
;  ebx  pointer to 64-bit number = first wanted byte, 0+
75
;       may be ebx=0 - start from first byte
76
;  ecx  number of bytes to read, 0+
77
;  edx  mem location to return data
78
;
79
;  ret ebx = bytes read or 0xffffffff file not found
80
;      eax = 0 ok read or other = errormsg
81
;
82
;--------------------------------------------------------------
83
fs_CdRead:
84
    push    edi
85
    cmp    byte [esi], 0
86
    jnz    @f
87
.noaccess:
88
    pop    edi
89
.noaccess_2:
90
    or    ebx, -1
91
    mov    eax, ERROR_ACCESS_DENIED
92
    ret
93
94
 
95
    pop     eax edx ecx edi
96
    jmp  .noaccess_2
97
98
 
99
    call    cd_find_lfn
100
    jnc    .found
101
    pop    edi
102
    cmp   [DevErrorCode],0
103
    jne   .noaccess_2
104
    or    ebx, -1
105
    mov    eax, ERROR_FILE_NOT_FOUND
106
    ret
107
108
 
109
    mov    edi,[cd_current_pointer_of_input]
110
    test   byte [edi+25],10b    ; do not allow read directories
111
    jnz    .noaccess
112
    test    ebx, ebx
113
    jz    .l1
114
    cmp    dword [ebx+4], 0
115
    jz    @f
116
        xor     ebx, ebx
117
.reteof:
118
    mov    eax, 6 ; end of file
119
    pop    edi
120
    ret
121
@@:
122
    mov    ebx, [ebx]
123
.l1:
124
        push    ecx edx
125
        push    0
126
        mov     eax, [edi+10] ; реальный размер файловой секции
127
        sub     eax, ebx
128
        jb      .eof
129
        cmp     eax, ecx
130
        jae     @f
131
        mov     ecx, eax
132
        mov     byte [esp], 6
133
@@:
134
     mov    eax,[edi+2]
135
     mov    [CDSectorAddress],eax
136
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
137
.new_sector:
138
    test    ecx, ecx
139
    jz    .done
140
    sub    ebx, 2048
141
    jae    .new_sector
142
    add    ebx, 2048
143
    jnz    .incomplete_sector
144
    cmp    ecx, 2048
145
    jb    .incomplete_sector
146
; we may read and memmove complete sector
147
    mov  [CDDataBuf_pointer],edx
148
    call ReadCDWRetr      ; читаем сектор файла
149
    cmp   [DevErrorCode],0
150
    jne   .noaccess_3
151
    inc  dword [CDSectorAddress]
152
    add    edx, 2048
153
    sub    ecx, 2048
154
    jmp    .new_sector
155
.incomplete_sector:
156
; we must read and memmove incomplete sector
157
    mov  [CDDataBuf_pointer],CDDataBuf
158
    call ReadCDWRetr      ; читаем сектор файла
159
    cmp   [DevErrorCode],0
160
    jne   .noaccess_3
161
    inc  dword [CDSectorAddress]
162
    mov    eax,CDDataBuf
163
    add    eax, ebx
164
    push    ecx
165
    add    ecx, ebx
166
    cmp    ecx, 2048
167
    jbe    @f
168
    mov    ecx, 2048
169
@@:
170
    sub    ecx, ebx
171
     push edi esi ecx
172
     mov edi,edx
173
     mov esi,eax ;0x7000   ; CD data buffer
174
     cld
175
     rep movsb
176
     pop ecx esi edi
177
    add    edx, ecx
178
    sub    [esp], ecx
179
    pop    ecx
180
    xor    ebx, ebx
181
    jmp    .new_sector
182
183
 
184
        mov     ebx, edx
185
        pop     eax edx ecx edi
186
        sub     ebx, edx
187
        ret
188
.eof:
189
        mov     ebx, edx
190
        pop     eax edx ecx
191
        sub     ebx, edx
192
        jmp     .reteof
193
194
 
195
;
196
;  fs_CdReadFolder - LFN variant for reading CD disk folder
197
;
198
;  esi  points to filename  /dir1/dir2/.../dirn/file,0
199
;  ebx  pointer to structure 32-bit number = first wanted block, 0+
200
;                          & flags (bitfields)
201
; flags: bit 0: 0=ANSI names, 1=UNICODE names
202
;  ecx  number of blocks to read, 0+
203
;  edx  mem location to return data
204
;
205
;  ret ebx = blocks read or 0xffffffff folder not found
206
;      eax = 0 ok read or other = errormsg
207
;
208
;--------------------------------------------------------------
209
fs_CdReadFolder:
210
        push    edi
211
        call    cd_find_lfn
212
        jnc     .found
213
        pop     edi
214
        cmp   [DevErrorCode],0
215
        jne     .noaccess_1
216
        or      ebx, -1
217
        mov     eax, ERROR_FILE_NOT_FOUND
218
        ret
219
.found:
220
        mov    edi,[cd_current_pointer_of_input]
221
        test   byte [edi+25],10b    ; do not allow read directories
222
        jnz     .found_dir
223
        pop     edi
224
.noaccess_1:
225
        or      ebx, -1
226
        mov     eax, ERROR_ACCESS_DENIED
227
        ret
228
.found_dir:
229
        mov    eax,[edi+2]    ; eax=cluster
230
        mov    [CDSectorAddress],eax
231
        mov    eax,[edi+10] ; размер директрории
232
.doit:
233
; init header
234
        push    eax ecx
235
        mov     edi, edx
236
        mov     ecx, 32/4
237
        xor     eax, eax
238
        rep     stosd
239
        pop     ecx eax
240
        mov     byte [edx], 1   ; version
241
        mov     [cd_mem_location],edx
242
        add     [cd_mem_location],32
243
; начинаем переброску БДВК в УСВК
244
;.mainloop:
245
        mov  [cd_counter_block],dword 0
246
        dec  dword [CDSectorAddress]
247
        push ecx
248
.read_to_buffer:
249
        inc  dword [CDSectorAddress]
250
        mov  [CDDataBuf_pointer],CDDataBuf
251
        call ReadCDWRetr         ; читаем сектор директории
252
        cmp   [DevErrorCode],0
253
        jne   .noaccess_1
254
        call .get_names_from_buffer
255
        sub  eax,2048
256
; директория закончилась?
257
        cmp  eax,0
258
        ja   .read_to_buffer
99 mario79 259
        mov   edi,[cd_counter_block]
87 mario79 260
        mov   [edx+8],edi
261
        mov   edi,[ebx]
262
        sub   [edx+4],edi
263
        pop     ecx edi
264
        mov     ebx, [edx+4]
89 diamond 265
        mov     eax,ERROR_SUCCESS
87 mario79 266
        ret
267
268
 
269
    mov     [cd_current_pointer_of_input_2],CDDataBuf
270
    push    eax esi edi edx
271
.get_names_from_buffer_1:
272
    call    cd_get_name
273
    jc    .end_buffer
274
    inc    dword [cd_counter_block]
275
    mov    eax,[cd_counter_block]
276
    cmp    [ebx],eax
277
    jae     .get_names_from_buffer_1
278
    test    ecx, ecx
279
    jz    .get_names_from_buffer_1
280
    mov   edi,[cd_counter_block]
281
    mov   [edx+4],edi
282
    dec     ecx
283
    mov   esi,ebp
284
    mov   edi,[cd_mem_location]
285
    add   edi,40
286
    test   dword [ebx+4], 1 ; 0=ANSI, 1=UNICODE
287
    jnz    .unicode
288
;    jmp  .unicode
289
.ansi:
290
    cmp   [cd_counter_block],2
291
    jbe   .ansi_parent_directory
292
    cld
293
    lodsw
294
    xchg ah,al
295
    call uni2ansi_char
296
    cld
297
    stosb
298
; проверка конца файла
299
    mov   ax,[esi]
96 mario79 300
    cmp   ax,word 3B00h ; сепаратор конца файла ';'
301
    je   .cd_get_parameters_of_file_1
87 mario79 302
; проверка для файлов не заканчивающихся сепаратором
303
    movzx   eax,byte [ebp-33]
304
    add   eax,ebp
305
    sub   eax,34
306
    cmp   esi,eax
307
    je   .cd_get_parameters_of_file_1
308
; проверка конца папки
309
    movzx   eax,byte [ebp-1]
310
    add   eax,ebp
311
    cmp   esi,eax
312
    jb   .ansi
313
.cd_get_parameters_of_file_1:
314
    mov   [edi],byte 0
315
    call  cd_get_parameters_of_file
90 mario79 316
    add   [cd_mem_location],304
87 mario79 317
    jmp   .get_names_from_buffer_1
318
319
 
320
    cmp   [cd_counter_block],2
321
    je    @f
322
    mov   [edi],byte '.'
323
    inc   edi
324
    jmp  .cd_get_parameters_of_file_1
325
@@:
326
    mov   [edi],word '..'
327
    add   edi,2
328
    jmp  .cd_get_parameters_of_file_1
329
330
 
331
    cmp   [cd_counter_block],2
332
    jbe   .unicode_parent_directory
333
    cld
334
    movsw
335
; проверка конца файла
336
    mov   ax,[esi]
337
    cmp   ax,word 3B00h ; сепаратор конца файла ';'
338
    je   .cd_get_parameters_of_file_2
339
; проверка для файлов не заканчивающихся сепаратором
340
    movzx   eax,byte [ebp-33]
341
    add   eax,ebp
342
    sub   eax,34
343
    cmp   esi,eax
344
    je   .cd_get_parameters_of_file_2
345
; проверка конца папки
346
    movzx   eax,byte [ebp-1]
347
    add   eax,ebp
348
    cmp   esi,eax
349
    jb   .unicode
350
.cd_get_parameters_of_file_2:
351
    mov   [edi],word 0
352
    call  cd_get_parameters_of_file
90 mario79 353
    add   [cd_mem_location],560
87 mario79 354
    jmp   .get_names_from_buffer_1
355
356
 
357
    cmp   [cd_counter_block],2
358
    je    @f
359
    mov   [edi],word 2E00h ; '.'
360
    add   edi,2
361
    jmp   .cd_get_parameters_of_file_2
362
@@:
363
    mov   [edi],dword 2E002E00h ; '..'
364
    add   edi,4
365
    jmp   .cd_get_parameters_of_file_2
366
367
 
90 mario79 368
    pop   edx edi esi eax
369
    ret
370
371
 
372
    mov   edi,[cd_mem_location]
87 mario79 373
cd_get_parameters_of_file_1:
90 mario79 374
; получаем атрибуты файла
87 mario79 375
    xor   eax,eax
376
; файл не архивировался
377
    inc   al
378
    shl   eax,1
379
; это каталог?
380
    test  [ebp-8],byte 2
381
    jz    .file
382
    inc   al
383
.file:
384
; метка тома не как в FAT, в этом виде отсутсвует
385
; файл не является системным
386
    shl   eax,3
387
; файл является скрытым? (атрибут существование)
388
    test  [ebp-8],byte 1
389
    jz    .hidden
390
    inc   al
391
.hidden:
392
    shl   eax,1
393
; файл всегда только для чтения, так как это CD
394
    inc   al
395
    mov   [edi],eax
396
; получаем время для файла
397
;час
398
    movzx eax,byte [ebp-12]
399
    shl   eax,8
400
;минута
401
    mov   al,[ebp-11]
402
    shl   eax,8
403
;секунда
404
    mov   al,[ebp-10]
405
;время создания файла
406
    mov   [edi+8],eax
407
;время последнего доступа
408
    mov   [edi+16],eax
409
;время последней записи
410
    mov   [edi+24],eax
411
; получаем дату для файла
412
;год
413
    movzx eax,byte [ebp-15]
414
    add   eax,1900
415
    shl   eax,8
416
;месяц
417
    mov   al,[ebp-14]
418
    shl   eax,8
419
;день
420
    mov   al,[ebp-13]
421
;дата создания файла
422
    mov   [edi+12],eax
423
;время последнего доступа
424
    mov   [edi+20],eax
425
;время последней записи
426
    mov   [edi+28],eax
427
; получаем тип данных имени
428
    xor   eax,eax
429
    test   dword [ebx+4], 1 ; 0=ANSI, 1=UNICODE
430
    jnz    .unicode_1
431
    mov    [edi+4],eax
432
    jmp   @f
433
.unicode_1:
434
    inc    eax
435
    mov    [edi+4],eax
436
@@:
437
; получаем размер файла в байтах
438
    xor   eax,eax
439
    mov   [edi+32+4],eax
440
    mov   eax,[ebp-23]
441
    mov   [edi+32],eax
442
    ret
443
444
 
90 mario79 445
;
446
;  fs_CdGetFileInfo - LFN variant for CD
447
;                     get file/directory attributes structure
448
;
449
;----------------------------------------------------------------
450
fs_CdGetFileInfo:
451
        cmp     byte [esi], 0
452
        jnz     @f
453
        mov     eax, 2
454
        ret
455
@@:
456
        push    edi ebp
457
        call    cd_find_lfn
458
        pushfd
459
        cmp     [DevErrorCode], 0
460
        jz      @f
461
        popfd
462
        pop     ebp edi
463
        mov     eax, 11
464
        ret
465
@@:
466
        popfd
467
        jnc     @f
468
        pop     ebp edi
469
        mov     eax, ERROR_FILE_NOT_FOUND
470
        ret
471
@@:
472
473
 
474
        call    cd_get_parameters_of_file_1
475
        and     dword [edi+4], 0
476
        pop     ebp
477
        pop     ebp edi
478
        xor     eax, eax
479
        ret
480
481
 
94 mario79 482
;
483
;  fs_CdExecute - LFN variant for executing from CD
484
;
485
;  esi  points to hd filename (e.g. 'dir1/name')
486
;  ebp  points to full filename (e.g. '/hd0/1/dir1/name')
487
;  dword [ebx] = flags
488
;  dword [ebx+4] = cmdline
489
;
490
;  ret ebx,edx destroyed
491
;      eax > 0 - PID, < 0 - error
492
;
493
;--------------------------------------------------------------
494
fs_CdExecute:
495
        mov     edx, [ebx]
496
        mov     ebx, [ebx+4]
497
        test    ebx, ebx
498
        jz      @f
499
        add     ebx, std_application_base_address
500
@@:
501
502
 
503
;
504
; fs_CdExecute.flags - second entry
505
;
506
;  esi  points to floppy filename (kernel address)
507
;  ebp  points to full filename
508
;  edx  flags
509
;  ebx  cmdline (kernel address)
510
;
511
;  ret  eax > 0 - PID, < 0 - error
512
;
513
;--------------------------------------------------------------
514
515
 
516
        cmp     byte [esi], 0
517
        jnz     @f
518
; cannot execute root!
519
        mov     eax, -ERROR_ACCESS_DENIED
520
        ret
521
@@:
522
        push    edi
523
        call    cd_find_lfn
524
        jnc     .found
525
        pop     edi
526
        mov     eax, -ERROR_FILE_NOT_FOUND
527
        cmp     [DevErrorCode], 0
528
        jz      @f
529
        mov     al, -11
530
@@:
531
        ret
532
.found:
533
        mov     edi,[cd_current_pointer_of_input]
534
        mov    eax,[edi+2]
535
        push    0
536
        push    eax
537
        push    dword [edi+10]          ; size
538
        push    .DoRead
539
        call    fs_execute
540
        add     esp, 16
541
        pop     edi
542
        ret
543
544
 
545
; read next block
546
; in: eax->parameters, edi->buffer
547
; out: eax = error code
548
        pushad
549
        cmp     dword [eax], 0  ; file size
550
        jz      .eof
551
        cmp     [eax+8],dword 0
552
        jne     @f
553
        mov     ecx,[eax+4]
554
        inc     dword [eax+4]
555
        mov     [CDSectorAddress],ecx
556
        mov     [CDDataBuf_pointer],CDDataBuf  ;edi
557
        call    ReadCDWRetr
558
        cmp     [DevErrorCode], 0
559
        jnz     .err
560
@@:
561
        push    esi edi ecx
562
        mov     esi,512
563
        imul    esi,[eax+8]
564
        add     esi,CDDataBuf
565
        mov     ecx,512/4
566
        cld
567
        rep     movsd
568
        pop     ecx edi esi
569
570
 
571
        mov     ecx, [eax]
572
        sub     ecx, 512
573
        jae     @f
574
        lea     edi, [edi+ecx+512]
575
        neg     ecx
576
        push    eax
577
        xor     eax, eax
578
        rep     stosb
579
        pop     eax
580
@@:
581
        mov     [eax], ecx
582
        mov     edx, [eax+8]
583
        inc     edx
584
        cmp     edx, 4  ; 2048/512=4
585
        jb      @f
586
        xor     edx, edx
587
@@:
588
        mov     [eax+8], edx
589
        popad
590
        xor     eax, eax
591
        ret
592
.eof:
593
        popad
594
        mov     eax, 6
595
        ret
596
.err:
597
        popad
598
        mov     eax, 11
599
        ret
600
601
 
87 mario79 602
; in: esi->name
603
; out: CF=1 - file not found
604
;      else CF=0 and [cd_current_pointer_of_input] direntry
605
        push eax esi
606
; 16 сектор начало набора дескрипторов томов
607
        mov  [CDSectorAddress],dword 15
608
.start:
609
        inc  dword [CDSectorAddress]
610
       mov  [CDDataBuf_pointer],CDDataBuf
611
       call  ReadCDWRetr
612
       cmp   [DevErrorCode],0
613
       jne   .access_denied
614
; проверка на вшивость
615
        cmp  [CDDataBuf+1],dword 'CD00'
616
        jne  .access_denied
617
        cmp  [CDDataBuf+5],byte '1'
618
        jne  .access_denied
619
; сектор является терминатором набор дескрипторов томов?
620
        cmp  [CDDataBuf],byte 0xff
621
        je  .access_denied
622
; сектор является дополнительным и улучшенным дескриптором тома?
623
        cmp  [CDDataBuf],byte 0x2
624
        jne  .start
625
; сектор является дополнительным дескриптором тома?
626
        cmp  [CDDataBuf+6],byte 0x1
627
        jne  .start
628
; параметры root директрории
629
        mov  eax,[CDDataBuf+0x9c+2] ; начало root директрории
630
        mov  [CDSectorAddress],eax
631
        mov  eax,[CDDataBuf+0x9c+10] ; размер root директрории
632
        cmp    byte [esi], 0
633
        jnz    @f
634
        mov   [cd_current_pointer_of_input],CDDataBuf+0x9c
635
        jmp   .done
636
@@:
637
; начинаем поиск
638
.mainloop:
639
        dec  dword [CDSectorAddress]
640
.read_to_buffer:
641
        inc  dword [CDSectorAddress]
642
        mov  [CDDataBuf_pointer],CDDataBuf
643
        call ReadCDWRetr         ; читаем сектор директории
644
        cmp   [DevErrorCode],0
645
        jne   .access_denied
646
        call cd_find_name_in_buffer
647
        jnc    .found
648
        sub  eax,2048
649
; директория закончилась?
650
        cmp  eax,0
651
        ja   .read_to_buffer
99 mario79 652
; нет искомого элемента цепочки
87 mario79 653
.access_denied:
654
        pop  esi eax
655
        stc
656
        ret
657
; искомый элемент цепочки найден
658
  .found:
659
; конец пути файла
660
        cmp    byte [esi-1], 0
94 mario79 661
        jz    .done
87 mario79 662
        mov    eax,[cd_current_pointer_of_input]
663
        add    eax,2
664
        mov    eax,[eax]
665
        mov    [CDSectorAddress],eax ; начало директории
666
        add    eax,8
667
        mov    eax,[eax]  ; размер директории
668
        jmp    .mainloop
669
; указатель файла найден
670
   .done:
671
        pop  esi eax
672
        clc
673
        ret
674
675
 
676
        mov     [cd_current_pointer_of_input_2],CDDataBuf
677
.start:
678
        call    cd_get_name
679
        jc    .not_found
680
        call    cd_compare_name
681
        jc    .start
682
.found:
683
        clc
684
        ret
685
.not_found:
686
        stc
687
        ret
688
689
 
690
        push eax
691
        mov   ebp,[cd_current_pointer_of_input_2]
692
        mov   [cd_current_pointer_of_input],ebp
693
        mov   eax,[ebp]
694
        cmp   eax,0   ; входы закончились?
695
        je    .next_sector
696
        cmp   ebp,CDDataBuf+2048     ; буфер закончился?
697
        jae   .next_sector
698
        movzx eax, byte [ebp]
699
        add   [cd_current_pointer_of_input_2],eax ; следующий вход каталога
700
        add   ebp,33 ; указатель установлен на начало имени
701
        pop   eax
702
        clc
703
        ret
704
.next_sector:
705
        pop  eax
706
        stc
707
        ret
708
709
 
710
; compares ASCIIZ-names, case-insensitive (cp866 encoding)
711
; in: esi->name, ebp->name
712
; out: if names match: ZF=1 and esi->next component of name
713
;      else: ZF=0, esi is not changed
714
; destroys eax
715
    push    esi eax edi
716
    mov     edi,ebp
717
.loop:
718
    cld
719
    lodsb
720
    push ax
721
    call char_todown
99 mario79 722
    call ansi2uni_char
87 mario79 723
    xchg ah,al
724
    cld
725
    scasw
726
    pop  ax
727
    je    .coincides
728
    call char_toupper
99 mario79 729
    call ansi2uni_char
87 mario79 730
    xchg ah,al
731
    cld
732
    sub  edi,2
733
    scasw
734
    jne   .name_not_coincide
735
.coincides:
736
    cmp   [esi],byte '/'  ; разделитель пути, конец имени текущего элемента
737
    je   .done
738
    cmp   [esi],byte 0  ; разделитель пути, конец имени текущего элемента
739
    je   .done
740
    jmp   .loop
741
.name_not_coincide:
742
    pop    edi eax esi
743
    stc
744
    ret
745
.done:
746
; проверка конца файла
747
    cmp   [edi],word 3B00h ; сепаратор конца файла ';'
748
    je   .done_1
749
; проверка для файлов не заканчивающихся сепаратором
750
    movzx   eax,byte [ebp-33]
751
    add   eax,ebp
752
    sub   eax,34
753
    cmp   edi,eax
754
    je   .done_1
755
; проверка конца папки
756
    movzx   eax,byte [ebp-1]
757
    add   eax,ebp
758
    cmp   edi,eax
759
    jne   .name_not_coincide
760
.done_1:
761
    pop   edi eax
762
    add   esp,4
763
    inc   esi
764
    clc
765
    ret
766
767
 
768
; convert character to uppercase, using cp866 encoding
769
; in: al=symbol
770
; out: al=converted symbol
771
        cmp     al, 'A'
772
        jb      .ret
773
        cmp     al, 'Z'
774
        jbe     .az
775
        cmp     al, 'Ђ'
776
        jb      .ret
777
        cmp     al, 'ђ'
778
        jb      .rus1
779
        cmp     al, 'џ'
780
        ja      .ret
781
; 0x90-0x9F -> 0xE0-0xEF
782
        add     al, 'а'-'ђ'
783
.ret:
784
        ret
785
.rus1:
786
; 0x80-0x8F -> 0xA0-0xAF
787
.az:
788
        add     al, 0x20
789
        ret
790
791
 
792
; convert UNICODE character in al to ANSI character in ax, using cp866 encoding
793
; in: ax=UNICODE character
794
; out: al=converted ANSI character
795
        cmp     ax, 0x80
796
        jb      .ascii
797
        cmp     ax, 0x401
798
        jz      .yo1
799
        cmp     ax, 0x451
800
        jz      .yo2
801
        cmp     ax, 0x410
802
        jb      .unk
803
        cmp     ax, 0x440
804
        jb      .rus1
805
        cmp     ax, 0x450
806
        jb      .rus2
807
.unk:
808
        mov     al, '_'
809
        jmp     .doit
810
.yo1:
811
        mov     al, 'р'
812
        jmp     .doit
813
.yo2:
814
        mov     al, 'с'
815
        jmp     .doit
816
.rus1:
817
; 0x410-0x43F -> 0x80-0xAF
818
        add     al, 0x70
819
        jmp     .doit
820
.rus2:
821
; 0x440-0x44F -> 0xE0-0xEF
822
        add     al, 0xA0
823
.ascii:
824
.doit:
825
        ret
826