Subversion Repositories Kolibri OS

Rev

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