Subversion Repositories Kolibri OS

Rev

Rev 115 | Rev 154 | 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    .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 edi
477
        xor     eax, eax
478
        ret
479
480
 
94 mario79 481
;
482
;  fs_CdExecute - LFN variant for executing from CD
483
;
484
;  esi  points to hd filename (e.g. 'dir1/name')
485
;  ebp  points to full filename (e.g. '/hd0/1/dir1/name')
486
;  dword [ebx] = flags
487
;  dword [ebx+4] = cmdline
488
;
489
;  ret ebx,edx destroyed
490
;      eax > 0 - PID, < 0 - error
491
;
492
;--------------------------------------------------------------
493
fs_CdExecute:
494
        mov     edx, [ebx]
495
        mov     ebx, [ebx+4]
496
        test    ebx, ebx
497
        jz      @f
498
        add     ebx, std_application_base_address
499
@@:
500
501
 
502
;
503
; fs_CdExecute.flags - second entry
504
;
505
;  esi  points to floppy filename (kernel address)
506
;  ebp  points to full filename
507
;  edx  flags
508
;  ebx  cmdline (kernel address)
509
;
510
;  ret  eax > 0 - PID, < 0 - error
511
;
512
;--------------------------------------------------------------
513
514
 
515
        cmp     byte [esi], 0
516
        jnz     @f
517
; cannot execute root!
518
        mov     eax, -ERROR_ACCESS_DENIED
519
        ret
520
@@:
521
        push    edi
522
        call    cd_find_lfn
523
        jnc     .found
524
        pop     edi
525
        mov     eax, -ERROR_FILE_NOT_FOUND
526
        cmp     [DevErrorCode], 0
527
        jz      @f
528
        mov     al, -11
529
@@:
530
        ret
531
.found:
532
        mov     edi,[cd_current_pointer_of_input]
533
        mov    eax,[edi+2]
534
        push    0
535
        push    eax
536
        push    dword [edi+10]          ; size
537
        push    .DoRead
538
        call    fs_execute
539
        add     esp, 16
540
        pop     edi
541
        ret
542
543
 
544
; read next block
545
; in: eax->parameters, edi->buffer
546
; out: eax = error code
547
        pushad
548
        cmp     dword [eax], 0  ; file size
549
        jz      .eof
550
        cmp     [eax+8],dword 0
551
        jne     @f
552
        mov     ecx,[eax+4]
553
        inc     dword [eax+4]
554
        mov     [CDSectorAddress],ecx
555
        mov     [CDDataBuf_pointer],CDDataBuf  ;edi
556
        call    ReadCDWRetr
557
        cmp     [DevErrorCode], 0
558
        jnz     .err
559
@@:
560
        push    esi edi ecx
561
        mov     esi,512
562
        imul    esi,[eax+8]
563
        add     esi,CDDataBuf
564
        mov     ecx,512/4
565
        cld
566
        rep     movsd
567
        pop     ecx edi esi
568
569
 
570
        mov     ecx, [eax]
571
        sub     ecx, 512
572
        jae     @f
573
        lea     edi, [edi+ecx+512]
574
        neg     ecx
575
        push    eax
576
        xor     eax, eax
577
        rep     stosb
578
        pop     eax
579
@@:
580
        mov     [eax], ecx
581
        mov     edx, [eax+8]
582
        inc     edx
583
        cmp     edx, 4  ; 2048/512=4
584
        jb      @f
585
        xor     edx, edx
586
@@:
587
        mov     [eax+8], edx
588
        popad
589
        xor     eax, eax
590
        ret
591
.eof:
592
        popad
593
        mov     eax, 6
594
        ret
595
.err:
596
        popad
597
        mov     eax, 11
598
        ret
599
600
 
87 mario79 601
; in: esi->name
602
; out: CF=1 - file not found
603
;      else CF=0 and [cd_current_pointer_of_input] direntry
604
        push eax esi
605
; 16 сектор начало набора дескрипторов томов
606
        mov  [CDSectorAddress],dword 15
607
.start:
608
        inc  dword [CDSectorAddress]
609
       mov  [CDDataBuf_pointer],CDDataBuf
610
       call  ReadCDWRetr
611
       cmp   [DevErrorCode],0
612
       jne   .access_denied
613
; проверка на вшивость
614
        cmp  [CDDataBuf+1],dword 'CD00'
615
        jne  .access_denied
616
        cmp  [CDDataBuf+5],byte '1'
617
        jne  .access_denied
618
; сектор является терминатором набор дескрипторов томов?
619
        cmp  [CDDataBuf],byte 0xff
620
        je  .access_denied
621
; сектор является дополнительным и улучшенным дескриптором тома?
622
        cmp  [CDDataBuf],byte 0x2
623
        jne  .start
624
; сектор является дополнительным дескриптором тома?
625
        cmp  [CDDataBuf+6],byte 0x1
626
        jne  .start
627
; параметры root директрории
628
        mov  eax,[CDDataBuf+0x9c+2] ; начало root директрории
629
        mov  [CDSectorAddress],eax
630
        mov  eax,[CDDataBuf+0x9c+10] ; размер root директрории
631
        cmp    byte [esi], 0
632
        jnz    @f
633
        mov   [cd_current_pointer_of_input],CDDataBuf+0x9c
634
        jmp   .done
635
@@:
636
; начинаем поиск
637
.mainloop:
638
        dec  dword [CDSectorAddress]
639
.read_to_buffer:
640
        inc  dword [CDSectorAddress]
641
        mov  [CDDataBuf_pointer],CDDataBuf
642
        call ReadCDWRetr         ; читаем сектор директории
643
        cmp   [DevErrorCode],0
644
        jne   .access_denied
645
        call cd_find_name_in_buffer
646
        jnc    .found
647
        sub  eax,2048
648
; директория закончилась?
649
        cmp  eax,0
650
        ja   .read_to_buffer
99 mario79 651
; нет искомого элемента цепочки
87 mario79 652
.access_denied:
653
        pop  esi eax
654
        stc
655
        ret
656
; искомый элемент цепочки найден
657
  .found:
658
; конец пути файла
659
        cmp    byte [esi-1], 0
94 mario79 660
        jz    .done
87 mario79 661
        mov    eax,[cd_current_pointer_of_input]
662
        add    eax,2
663
        mov    eax,[eax]
664
        mov    [CDSectorAddress],eax ; начало директории
665
        add    eax,8
666
        mov    eax,[eax]  ; размер директории
667
        jmp    .mainloop
668
; указатель файла найден
669
   .done:
670
        pop  esi eax
671
        clc
672
        ret
673
674
 
675
        mov     [cd_current_pointer_of_input_2],CDDataBuf
676
.start:
677
        call    cd_get_name
678
        jc    .not_found
679
        call    cd_compare_name
680
        jc    .start
681
.found:
682
        clc
683
        ret
684
.not_found:
685
        stc
686
        ret
687
688
 
689
        push eax
690
        mov   ebp,[cd_current_pointer_of_input_2]
691
        mov   [cd_current_pointer_of_input],ebp
692
        mov   eax,[ebp]
693
        cmp   eax,0   ; входы закончились?
694
        je    .next_sector
695
        cmp   ebp,CDDataBuf+2048     ; буфер закончился?
696
        jae   .next_sector
697
        movzx eax, byte [ebp]
698
        add   [cd_current_pointer_of_input_2],eax ; следующий вход каталога
699
        add   ebp,33 ; указатель установлен на начало имени
700
        pop   eax
701
        clc
702
        ret
703
.next_sector:
704
        pop  eax
705
        stc
706
        ret
707
708
 
709
; compares ASCIIZ-names, case-insensitive (cp866 encoding)
710
; in: esi->name, ebp->name
711
; out: if names match: ZF=1 and esi->next component of name
712
;      else: ZF=0, esi is not changed
713
; destroys eax
714
    push    esi eax edi
715
    mov     edi,ebp
716
.loop:
717
    cld
718
    lodsb
719
    push ax
720
    call char_todown
99 mario79 721
    call ansi2uni_char
87 mario79 722
    xchg ah,al
723
    cld
724
    scasw
725
    pop  ax
726
    je    .coincides
727
    call char_toupper
99 mario79 728
    call ansi2uni_char
87 mario79 729
    xchg ah,al
730
    cld
731
    sub  edi,2
732
    scasw
733
    jne   .name_not_coincide
734
.coincides:
735
    cmp   [esi],byte '/'  ; разделитель пути, конец имени текущего элемента
736
    je   .done
737
    cmp   [esi],byte 0  ; разделитель пути, конец имени текущего элемента
738
    je   .done
739
    jmp   .loop
740
.name_not_coincide:
741
    pop    edi eax esi
742
    stc
743
    ret
744
.done:
745
; проверка конца файла
746
    cmp   [edi],word 3B00h ; сепаратор конца файла ';'
747
    je   .done_1
748
; проверка для файлов не заканчивающихся сепаратором
749
    movzx   eax,byte [ebp-33]
750
    add   eax,ebp
751
    sub   eax,34
752
    cmp   edi,eax
753
    je   .done_1
754
; проверка конца папки
755
    movzx   eax,byte [ebp-1]
756
    add   eax,ebp
757
    cmp   edi,eax
758
    jne   .name_not_coincide
759
.done_1:
760
    pop   edi eax
761
    add   esp,4
762
    inc   esi
763
    clc
764
    ret
765
766
 
767
; convert character to uppercase, using cp866 encoding
768
; in: al=symbol
769
; out: al=converted symbol
770
        cmp     al, 'A'
771
        jb      .ret
772
        cmp     al, 'Z'
773
        jbe     .az
774
        cmp     al, 'Ђ'
775
        jb      .ret
776
        cmp     al, 'ђ'
777
        jb      .rus1
778
        cmp     al, 'џ'
779
        ja      .ret
780
; 0x90-0x9F -> 0xE0-0xEF
781
        add     al, 'а'-'ђ'
782
.ret:
783
        ret
784
.rus1:
785
; 0x80-0x8F -> 0xA0-0xAF
786
.az:
787
        add     al, 0x20
788
        ret
789
790
 
791
; convert UNICODE character in al to ANSI character in ax, using cp866 encoding
792
; in: ax=UNICODE character
793
; out: al=converted ANSI character
794
        cmp     ax, 0x80
795
        jb      .ascii
796
        cmp     ax, 0x401
797
        jz      .yo1
798
        cmp     ax, 0x451
799
        jz      .yo2
800
        cmp     ax, 0x410
801
        jb      .unk
802
        cmp     ax, 0x440
803
        jb      .rus1
804
        cmp     ax, 0x450
805
        jb      .rus2
806
.unk:
807
        mov     al, '_'
808
        jmp     .doit
809
.yo1:
810
        mov     al, 'р'
811
        jmp     .doit
812
.yo2:
813
        mov     al, 'с'
814
        jmp     .doit
815
.rus1:
816
; 0x410-0x43F -> 0x80-0xAF
817
        add     al, 0x70
818
        jmp     .doit
819
.rus2:
820
; 0x440-0x44F -> 0xE0-0xEF
821
        add     al, 0xA0
822
.ascii:
823
.doit:
824
        ret
825