Subversion Repositories Kolibri OS

Rev

Rev 536 | Details | Compare with Previous | Last modification | View Log | RSS feed

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