Subversion Repositories Kolibri OS

Rev

Rev 1664 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;                                                              ;;
  2. ;; Copyright (C) KolibriOS team 2004-2009. All rights reserved. ;;
  3. ;; Distributed under terms of the GNU General Public License    ;;
  4. ;;                                                              ;;
  5. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  6.  
  7. $Revision: 1689 $
  8.  
  9.  
  10. image_of_eax EQU esp+32
  11. image_of_ebx EQU esp+20
  12.  
  13. ; System function 70 - files with long names (LFN)
  14. ; diamond, 2006
  15.  
  16. iglobal
  17. ; in this table names must be in lowercase
  18. rootdirs:
  19.         db      2,'rd'
  20.         dd      fs_OnRamdisk
  21.         dd      fs_NextRamdisk
  22.         db      7,'ramdisk'
  23.         dd      fs_OnRamdisk
  24.         dd      fs_NextRamdisk
  25.         db      2,'fd'
  26.         dd      fs_OnFloppy
  27.         dd      fs_NextFloppy
  28.         db      10,'floppydisk'
  29.         dd      fs_OnFloppy
  30.         dd      fs_NextFloppy
  31.         db      3,'hd0'
  32.         dd      fs_OnHd0
  33.         dd      fs_NextHd0
  34.         db      3,'hd1'
  35.         dd      fs_OnHd1
  36.         dd      fs_NextHd1
  37.         db      3,'hd2'
  38.         dd      fs_OnHd2
  39.         dd      fs_NextHd2
  40.         db      3,'hd3'
  41.         dd      fs_OnHd3
  42.         dd      fs_NextHd3
  43.         db      0
  44.  
  45.  
  46. virtual_root_query:
  47.         dd      fs_HasRamdisk
  48.         db      'rd',0
  49.         dd      fs_HasFloppy
  50.         db      'fd',0
  51.         dd      fs_HasHd0
  52.         db      'hd0',0
  53.         dd      fs_HasHd1
  54.         db      'hd1',0
  55.         dd      fs_HasHd2
  56.         db      'hd2',0
  57.         dd      fs_HasHd3
  58.         db      'hd3',0
  59.         dd      0
  60.  
  61. fs_additional_handlers:
  62.         dd      biosdisk_handler, biosdisk_enum_root
  63. ; add new handlers here
  64.         dd      0
  65.  
  66. endg
  67. file_system_lfn:
  68. ; in: ebx->fileinfo block
  69. ; operation codes:
  70. ; 0 : read file
  71. ; 1 : read folder
  72. ; 2 : create/rewrite file
  73. ; 3 : write/append to file
  74. ; 4 : set end of file
  75. ; 5 : get file/directory attributes structure
  76. ; 6 : set file/directory attributes structure
  77. ; 7 : start application
  78. ; 8 : delete file
  79. ; 9 : create directory
  80.  
  81. ; parse file name
  82.         lea     esi, [ebx+20]
  83.         lodsb
  84.         test    al, al
  85.         jnz     @f
  86.         mov     esi, [esi]
  87.         lodsb
  88. @@:
  89.         cmp     al, '/'
  90.         jz      .notcurdir
  91.         dec     esi
  92.         mov     ebp, esi
  93.         test    al, al
  94.         jnz     @f
  95.         xor     ebp, ebp
  96. @@:
  97.         mov     esi, [current_slot]
  98.         mov     esi, [esi+APPDATA.cur_dir]
  99.         jmp     .parse_normal
  100. .notcurdir:
  101.         cmp     byte [esi], 0
  102.         jz      .rootdir
  103.         call    process_replace_file_name
  104. .parse_normal:
  105.         cmp dword [ebx], 7
  106.         jne @F
  107.         mov edx, [ebx+4]
  108.         mov ebx, [ebx+8]
  109.         call fs_execute  ; esi+ebp, ebx, edx
  110.         mov [image_of_eax], eax
  111.         ret
  112. @@:
  113.         mov     edi, rootdirs-8
  114.         xor     ecx, ecx
  115.         push    esi
  116. .scan1:
  117.         pop     esi
  118.         add     edi, ecx
  119.         scasd
  120.         scasd
  121.         mov     cl, byte [edi]
  122.         test    cl, cl
  123.         jz      .notfound_try
  124.         inc     edi
  125.         push    esi
  126. @@:
  127.         lodsb
  128.         or      al, 20h
  129.         scasb
  130.         loopz   @b
  131.         jnz     .scan1
  132.         lodsb
  133.         cmp     al, '/'
  134.         jz      .found1
  135.         test    al, al
  136.         jnz     .scan1
  137.         pop     eax
  138. ; directory /xxx
  139. .maindir:
  140.         mov     esi, [edi+4]
  141. .maindir_noesi:
  142.         cmp     dword [ebx], 1
  143.         jnz     .access_denied
  144.         xor     eax, eax
  145.         mov     ebp, [ebx+12]                   ;êîëè÷åñòâî áëîêîâ äëÿ ñ÷èòûâàíèÿ
  146.         mov     edx, [ebx+16]                   ;êóäà çàïèñûâàòü ðóçåëüòàò
  147.     ;    add     edx, std_application_base_address
  148.         push    dword [ebx+4]   ; first block
  149.         mov     ebx, [ebx+8]    ; flags
  150. ; ebx=flags, [esp]=first block, ebp=number of blocks, edx=return area, esi='Next' handler
  151.         mov     edi, edx
  152.         push    ecx
  153.         mov     ecx, 32/4
  154.         rep     stosd
  155.         pop     ecx
  156.         mov     byte [edx], 1   ; version
  157. .maindir_loop:
  158.         call    esi
  159.         jc      .maindir_done
  160.         inc     dword [edx+8]
  161.         dec     dword [esp]
  162.         jns     .maindir_loop
  163.         dec     ebp
  164.         js      .maindir_loop
  165.         inc     dword [edx+4]
  166.         mov     dword [edi], 0x10       ; attributes: folder
  167.         mov     dword [edi+4], 1        ; name type: UNICODE
  168.         push    eax
  169.         xor     eax, eax
  170.         add     edi, 8
  171.         push    ecx
  172.         mov     ecx, 40/4-2
  173.         rep     stosd
  174.         pop     ecx
  175.         pop     eax
  176.         push    eax edx
  177. ; convert number in eax to decimal UNICODE string
  178.         push    edi
  179.         push    ecx
  180.         push    -'0'
  181.         mov     ecx, 10
  182. @@:
  183.         xor     edx, edx
  184.         div     ecx
  185.         push    edx
  186.         test    eax, eax
  187.         jnz     @b
  188. @@:
  189.         pop     eax
  190.         add     al, '0'
  191.         stosb
  192.         test    bl, 1           ; UNICODE name?
  193.         jz      .ansi2
  194.         mov     byte [edi], 0
  195.         inc     edi
  196. .ansi2:
  197.         test    al, al
  198.         jnz     @b
  199.         mov     byte [edi-1], 0
  200.         pop     ecx
  201.         pop     edi
  202. ; UNICODE name length is 520 bytes, ANSI - 264
  203.         add     edi, 520
  204.         test    bl, 1
  205.         jnz     @f
  206.         sub     edi, 520-264
  207. @@:
  208.         pop     edx eax
  209.         jmp     .maindir_loop
  210. .maindir_done:
  211.         pop     eax
  212.         mov     ebx, [edx+4]
  213.         xor     eax, eax
  214.         dec     ebp
  215.         js      @f
  216.         mov     al, ERROR_END_OF_FILE
  217. @@:
  218.         mov     [image_of_eax], eax
  219.         mov     [image_of_ebx], ebx
  220.         ret
  221. ; directory /
  222. .rootdir:
  223.         cmp     dword [ebx], 1  ; read folder?
  224.         jz      .readroot
  225. .access_denied:
  226.         mov     dword [image_of_eax], 10      ; access denied
  227.         ret
  228.  
  229. .readroot:
  230. ; virtual root folder - special handler
  231.         mov     esi, virtual_root_query
  232.         mov     ebp, [ebx+12]
  233.         mov     edx, [ebx+16]
  234.     ;    add     edx, std_application_base_address
  235.         push    dword [ebx+4]   ; first block
  236.         mov     ebx, [ebx+8]    ; flags
  237.         xor     eax, eax
  238. ; eax=0, [esp]=first block, ebx=flags, ebp=number of blocks, edx=return area
  239.         mov     edi, edx
  240.         mov     ecx, 32/4
  241.         rep     stosd
  242.         mov     byte [edx], 1   ; version
  243. .readroot_loop:
  244.         cmp     dword [esi], eax
  245.         jz      .readroot_done_static
  246.         call    dword [esi]
  247.         add     esi, 4
  248.         test    eax, eax
  249.         jnz     @f
  250. .readroot_next:
  251.         or      ecx, -1
  252.         xchg    esi, edi
  253.         repnz   scasb
  254.         xchg    esi, edi
  255.         jmp     .readroot_loop
  256. @@:
  257.         xor     eax, eax
  258.         inc     dword [edx+8]
  259.         dec     dword [esp]
  260.         jns     .readroot_next
  261.         dec     ebp
  262.         js      .readroot_next
  263.         inc     dword [edx+4]
  264.         mov     dword [edi], 0x10       ; attributes: folder
  265.         mov     dword [edi+4], ebx      ; name type: UNICODE
  266.         add     edi, 8
  267.         mov     ecx, 40/4-2
  268.         rep     stosd
  269.         push    edi
  270. @@:
  271.         lodsb
  272.         stosb
  273.         test    bl, 1
  274.         jz      .ansi
  275.         mov     byte [edi], 0
  276.         inc     edi
  277. .ansi:
  278.         test    eax, eax
  279.         jnz     @b
  280.         pop     edi
  281.         add     edi, 520
  282.         test    bl, 1
  283.         jnz     .readroot_loop
  284.         sub     edi, 520-264
  285.         jmp     .readroot_loop
  286. .readroot_done_static:
  287.         mov     esi, fs_additional_handlers-8
  288.         sub     esp, 16
  289. .readroot_ah_loop:
  290.         add     esi, 8
  291.         cmp     dword [esi], 0
  292.         jz      .readroot_done
  293.         xor     eax, eax
  294. .readroot_ah_loop2:
  295.         push    edi
  296.         lea     edi, [esp+4]
  297.         call    dword [esi+4]
  298.         pop     edi
  299.         test    eax, eax
  300.         jz      .readroot_ah_loop
  301.         inc     dword [edx+8]
  302.         dec     dword [esp+16]
  303.         jns     .readroot_ah_loop2
  304.         dec     ebp
  305.         js      .readroot_ah_loop2
  306.         push    eax
  307.         xor     eax, eax
  308.         inc     dword [edx+4]
  309.         mov     dword [edi], 0x10       ; attributes: folder
  310.         mov     dword [edi+4], ebx
  311.         add     edi, 8
  312.         mov     ecx, 40/4-2
  313.         rep     stosd
  314.         push    esi edi
  315.         lea     esi, [esp+12]
  316. @@:
  317.         lodsb
  318.         stosb
  319.         test    bl, 1
  320.         jz      .ansi3
  321.         mov     byte [edi], 0
  322.         inc     edi
  323. .ansi3:
  324.         test    al, al
  325.         jnz     @b
  326.         pop     edi esi eax
  327.         add     edi, 520
  328.         test    bl, 1
  329.         jnz     .readroot_ah_loop2
  330.         sub     edi, 520-264
  331.         jmp     .readroot_ah_loop2
  332. .readroot_done:
  333.         add     esp, 16
  334.         pop     eax
  335.         mov     ebx, [edx+4]
  336.         xor     eax, eax
  337.         dec     ebp
  338.         js      @f
  339.         mov     al, ERROR_END_OF_FILE
  340. @@:
  341.         mov     [image_of_eax], eax
  342.         mov     [image_of_ebx], ebx
  343.         ret
  344. .notfound_try:
  345.         mov     edi, fs_additional_handlers
  346. @@:
  347.         cmp     dword [edi], 0
  348.         jz      .notfound
  349.         call    dword [edi]
  350.         scasd
  351.         scasd
  352.         jmp     @b
  353. .notfound:
  354.         mov     dword [image_of_eax], ERROR_FILE_NOT_FOUND
  355.         and     dword [image_of_ebx], 0
  356.         ret
  357.  
  358. .notfounda:
  359.         cmp     edi, esp
  360.         jnz     .notfound
  361.         add     esp, 8
  362.         jmp     .notfound
  363.  
  364. .found1:
  365.         pop     eax
  366.         cmp     byte [esi], 0
  367.         jz      .maindir
  368. .found2:
  369. ; read partition number
  370.         xor     ecx, ecx
  371.         xor     eax, eax
  372. @@:
  373.         lodsb
  374.         cmp     al, '/'
  375.         jz      .done1
  376.         test    al, al
  377.         jz      .done1
  378.         sub     al, '0'
  379.         cmp     al, 9
  380.         ja      .notfounda
  381.         lea     ecx, [ecx*5]
  382.         lea     ecx, [ecx*2+eax]
  383.         jmp     @b
  384. .done1:
  385.         jecxz   .notfounda
  386.         test    al, al
  387.         jnz     @f
  388.         dec     esi
  389. @@:
  390.         cmp     byte [esi], 0
  391.         jnz     @f
  392.         test    ebp, ebp
  393.         jz      @f
  394.         mov     esi, ebp
  395.         xor     ebp, ebp
  396. @@:
  397. ; now [edi] contains handler address, ecx - partition number,
  398. ; esi points to ASCIIZ string - rest of name
  399.         jmp     dword [edi]
  400.  
  401. ; handlers for devices
  402. ; in: ecx = 0 => query virtual directory /xxx
  403. ; in: ecx = partition number
  404. ;     esi -> relative (for device) name
  405. ;     ebx -> fileinfo
  406. ;     ebp = 0 or pointer to rest of name from folder addressed by esi
  407. ; out: [image_of_eax]=image of eax, [image_of_ebx]=image of ebx
  408.  
  409. fs_OnRamdisk:
  410.         cmp     ecx, 1
  411.         jnz     file_system_lfn.notfound
  412.         mov     eax, [ebx]
  413.         cmp     eax, fs_NumRamdiskServices
  414.         jae     .not_impl
  415.         mov     ecx, [ebx+12]
  416.         mov     edx, [ebx+16]
  417.    ;     add     edx, std_application_base_address
  418.         add     ebx, 4
  419.         call    dword [fs_RamdiskServices + eax*4]
  420.         mov     [image_of_eax], eax
  421.         mov     [image_of_ebx], ebx
  422.         ret
  423. .not_impl:
  424.         mov     dword [image_of_eax], 2       ; not implemented
  425.         ret
  426.  
  427. fs_NotImplemented:
  428.         mov     eax, 2
  429.         ret
  430.  
  431. fs_RamdiskServices:
  432.         dd      fs_RamdiskRead
  433.         dd      fs_RamdiskReadFolder
  434.         dd      fs_RamdiskRewrite
  435.         dd      fs_RamdiskWrite
  436.         dd      fs_RamdiskSetFileEnd
  437.         dd      fs_RamdiskGetFileInfo
  438.         dd      fs_RamdiskSetFileInfo
  439.         dd      0
  440.         dd      fs_RamdiskDelete
  441.         dd      fs_RamdiskCreateFolder
  442. fs_NumRamdiskServices = ($ - fs_RamdiskServices)/4
  443.  
  444. fs_OnFloppy:
  445.         cmp     ecx, 2
  446.         ja      file_system_lfn.notfound
  447.         mov     eax, [ebx]
  448.         cmp     eax, fs_NumFloppyServices
  449.         jae     fs_OnRamdisk.not_impl
  450.         call    reserve_flp
  451.         mov     [flp_number], cl
  452.         mov     ecx, [ebx+12]
  453.         mov     edx, [ebx+16]
  454.    ;     add     edx, std_application_base_address
  455.         add     ebx, 4
  456.         call    dword [fs_FloppyServices + eax*4]
  457.         and     [flp_status], 0
  458.         mov     [image_of_eax], eax
  459.         mov     [image_of_ebx], ebx
  460.         ret
  461.  
  462. fs_FloppyServices:
  463.         dd      fs_FloppyRead
  464.         dd      fs_FloppyReadFolder
  465.         dd      fs_FloppyRewrite
  466.         dd      fs_FloppyWrite
  467.         dd      fs_FloppySetFileEnd
  468.         dd      fs_FloppyGetFileInfo
  469.         dd      fs_FloppySetFileInfo
  470.         dd      0
  471.         dd      fs_FloppyDelete
  472.         dd      fs_FloppyCreateFolder
  473. fs_NumFloppyServices = ($ - fs_FloppyServices)/4
  474.  
  475. fs_OnHd0:
  476.         call    reserve_hd1
  477.         mov     [hdbase], 0x1F0
  478.         mov     [hdid], 0
  479.         push    1
  480.         jmp     fs_OnHd
  481. fs_OnHd1:
  482.         call    reserve_hd1
  483.         mov     [hdbase], 0x1F0
  484.         mov     [hdid], 0x10
  485.         push    2
  486.         jmp     fs_OnHd
  487. fs_OnHd2:
  488.         call    reserve_hd1
  489.         mov     [hdbase], 0x170
  490.         mov     [hdid], 0
  491.         push    3
  492.         jmp     fs_OnHd
  493. fs_OnHd3:
  494.         call    reserve_hd1
  495.         mov     [hdbase], 0x170
  496.         mov     [hdid], 0x10
  497.         push    4
  498. fs_OnHd:
  499.         call    reserve_hd_channel
  500.         pop     eax
  501.         mov     [hdpos], eax
  502.         cmp     ecx, 0x100
  503.         jae     fs_OnHdAndBd.nf
  504.         cmp     cl, [DRIVE_DATA+1+eax]
  505. fs_OnHdAndBd:
  506.         jbe     @f
  507. .nf:
  508.         call    free_hd_channel
  509.         and     [hd1_status], 0
  510.         mov     dword [image_of_eax], 5       ; not found
  511.         ret
  512. @@:
  513.         mov     [known_part], ecx ;     mov     [fat32part], ecx
  514.         push    ebx esi
  515.         call    choice_necessity_partition_1
  516.         pop     esi ebx
  517.         mov     ecx, [ebx+12]
  518.         mov     edx, [ebx+16]
  519.     ;    add     edx, std_application_base_address
  520.         mov     eax, [ebx]
  521.         cmp     eax, fs_NumHdServices
  522.         jae     .not_impl
  523.         add     ebx, 4
  524.         call    dword [fs_HdServices + eax*4]
  525.         call    free_hd_channel
  526.         and     [hd1_status], 0
  527.         mov     [image_of_eax], eax
  528.         mov     [image_of_ebx], ebx
  529.         ret
  530. .not_impl:
  531.         call    free_hd_channel
  532.         and     [hd1_status], 0
  533.         mov     dword [image_of_eax], 2       ; not implemented
  534.         ret
  535.  
  536. fs_HdServices:
  537.         dd      fs_HdRead
  538.         dd      fs_HdReadFolder
  539.         dd      fs_HdRewrite
  540.         dd      fs_HdWrite
  541.         dd      fs_HdSetFileEnd
  542.         dd      fs_HdGetFileInfo
  543.         dd      fs_HdSetFileInfo
  544.         dd      0
  545.         dd      fs_HdDelete
  546.         dd      fs_HdCreateFolder
  547. fs_NumHdServices = ($ - fs_HdServices)/4
  548.  
  549.  
  550. fs_HasRamdisk:
  551.         mov     al, 1   ; we always have ramdisk
  552.         ret
  553.  
  554. fs_HasFloppy:
  555.         cmp     byte [DRIVE_DATA], 0
  556.         setnz   al
  557.         ret
  558.  
  559. fs_HasHd0:
  560.         mov     al, [DRIVE_DATA+1]
  561.         and     al, 11000000b
  562.         cmp     al, 01000000b
  563.         setz    al
  564.         ret
  565. fs_HasHd1:
  566.         mov     al, [DRIVE_DATA+1]
  567.         and     al, 00110000b
  568.         cmp     al, 00010000b
  569.         setz    al
  570.         ret
  571. fs_HasHd2:
  572.         mov     al, [DRIVE_DATA+1]
  573.         and     al, 00001100b
  574.         cmp     al, 00000100b
  575.         setz    al
  576.         ret
  577. fs_HasHd3:
  578.         mov     al, [DRIVE_DATA+1]
  579.         and     al, 00000011b
  580.         cmp     al, 00000001b
  581.         setz    al
  582.         ret
  583.  
  584. ;*******************************************************
  585. fs_HasCd0:
  586.         mov     al, [DRIVE_DATA+1]
  587.         and     al, 11000000b
  588.         cmp     al, 10000000b
  589.         setz    al
  590.         ret
  591. fs_HasCd1:
  592.         mov     al, [DRIVE_DATA+1]
  593.         and     al, 00110000b
  594.         cmp     al, 00100000b
  595.         setz    al
  596.         ret
  597. fs_HasCd2:
  598.         mov     al, [DRIVE_DATA+1]
  599.         and     al, 00001100b
  600.         cmp     al, 00001000b
  601.         setz    al
  602.         ret
  603. fs_HasCd3:
  604.         mov     al, [DRIVE_DATA+1]
  605.         and     al, 00000011b
  606.         cmp     al, 00000010b
  607.         setz    al
  608.         ret
  609. ;*******************************************************
  610.  
  611. ; fs_NextXXX functions:
  612. ; in: eax = partition number, from which start to scan
  613. ; out: CF=1 => no more partitions
  614. ;      CF=0 => eax=next partition number
  615.  
  616. fs_NextRamdisk:
  617. ; we always have /rd/1
  618.         test    eax, eax
  619.         stc
  620.         jnz     @f
  621.         mov     al, 1
  622.         clc
  623. @@:
  624.         ret
  625.  
  626. fs_NextFloppy:
  627. ; we have /fd/1 iff (([DRIVE_DATA] and 0xF0) != 0) and /fd/2 iff (([DRIVE_DATA] and 0x0F) != 0)
  628.         test    byte [DRIVE_DATA], 0xF0
  629.         jz      .no1
  630.         test    eax, eax
  631.         jnz     .no1
  632.         inc     eax
  633.         ret     ; CF cleared
  634. .no1:
  635.         test    byte [DRIVE_DATA], 0x0F
  636.         jz      .no2
  637.         cmp     al, 2
  638.         jae     .no2
  639.         mov     al, 2
  640.         clc
  641.         ret
  642. .no2:
  643.         stc
  644.         ret
  645.  
  646. ; on hdx, we have partitions from 1 to [0x40002+x]
  647. fs_NextHd0:
  648.         push    0
  649.         jmp     fs_NextHd
  650. fs_NextHd1:
  651.         push    1
  652.         jmp     fs_NextHd
  653. fs_NextHd2:
  654.         push    2
  655.         jmp     fs_NextHd
  656. fs_NextHd3:
  657.         push    3
  658. fs_NextHd:
  659.         pop     ecx
  660.         movzx   ecx, byte [DRIVE_DATA+2+ecx]
  661.         cmp     eax, ecx
  662.         jae     fs_NextFloppy.no2
  663.         inc     eax
  664.         clc
  665.         ret
  666.  
  667. ;*******************************************************
  668. fs_NextCd:
  669. ; we always have /cdX/1
  670.         test    eax, eax
  671.         stc
  672.         jnz     @f
  673.         mov     al, 1
  674.         clc
  675. @@:
  676.         ret
  677. ;*******************************************************
  678.  
  679. ; Additional FS handlers.
  680. ; This handler gets the control each time when fn 70 is called
  681. ; with unknown item of root subdirectory.
  682. ; in: esi -> name
  683. ;     ebp = 0 or rest of name relative to esi
  684. ; out: if the handler processes path, he must not return in file_system_lfn,
  685. ;      but instead pop return address and return directly to the caller
  686. ;      otherwise simply return
  687.  
  688. ; here we test for /bd<N>/... - BIOS disks
  689. biosdisk_handler:
  690.         cmp     [NumBiosDisks], 0
  691.         jz      .ret
  692.         mov     al, [esi]
  693.         or      al, 20h
  694.         cmp     al, 'b'
  695.         jnz     .ret
  696.         mov     al, [esi+1]
  697.         or      al, 20h
  698.         cmp     al, 'd'
  699.         jnz     .ret
  700.         push    esi
  701.         inc     esi
  702.         inc     esi
  703.         cmp     byte [esi], '0'
  704.         jb      .ret2
  705.         cmp     byte [esi], '9'
  706.         ja      .ret2
  707.         xor     edx, edx
  708. @@:
  709.         lodsb
  710.         test    al, al
  711.         jz      .ok
  712.         cmp     al, '/'
  713.         jz      .ok
  714.         sub     al, '0'
  715.         cmp     al, 9
  716.         ja      .ret2
  717.         lea     edx, [edx*5]
  718.         lea     edx, [edx*2+eax]
  719.         jmp     @b
  720. .ret2:
  721.         pop     esi
  722. .ret:
  723.         ret
  724. .ok:
  725.         cmp     al, '/'
  726.         jz      @f
  727.         dec     esi
  728. @@:
  729.         add     dl, 80h
  730.         xor     ecx, ecx
  731. @@:
  732.         cmp     dl, [BiosDisksData+ecx*4]
  733.         jz      .ok2
  734.         inc     ecx
  735.         cmp     ecx, [NumBiosDisks]
  736.         jb      @b
  737.         jmp     .ret2
  738. .ok2:
  739.         add     esp, 8
  740.         test    al, al
  741.         jnz     @f
  742.         mov     esi, fs_BdNext
  743.         jmp     file_system_lfn.maindir_noesi
  744. @@:
  745.         push    ecx
  746.         push    fs_OnBd
  747.         mov     edi, esp
  748.         jmp     file_system_lfn.found2
  749.  
  750. fs_BdNext:
  751.         cmp     eax, [BiosDiskPartitions+ecx*4]
  752.         inc     eax
  753.         cmc
  754.         ret
  755.  
  756. fs_OnBd:
  757.         pop     edx edx
  758. ; edx = disk number, ecx = partition number
  759. ; esi+ebp = name
  760.         call    reserve_hd1
  761.         add     edx, 0x80
  762.         mov     [hdpos], edx
  763.         cmp     ecx, [BiosDiskPartitions+(edx-0x80)*4]
  764.         jmp     fs_OnHdAndBd
  765.  
  766. ; This handler is called when virtual root is enumerated
  767. ; and must return all items which can be handled by this.
  768. ; It is called several times, first time with eax=0
  769. ; in: eax = 0 for first call, previously returned value for subsequent calls
  770. ; out: eax = 0 => no more items
  771. ;      eax != 0 => buffer pointed to by edi contains name of item
  772.  
  773. ; here we enumerate existing BIOS disks /bd<N>
  774. biosdisk_enum_root:
  775.         cmp     eax, [NumBiosDisks]
  776.         jae     .end
  777.         push    eax
  778.         movzx   eax, byte [BiosDisksData+eax*4]
  779.         sub     al, 80h
  780.         push    eax
  781.         mov     al, 'b'
  782.         stosb
  783.         mov     al, 'd'
  784.         stosb
  785.         pop     eax
  786.         cmp     al, 10
  787.         jae     .big
  788.         add     al, '0'
  789.         stosb
  790.         mov     byte [edi], 0
  791.         pop     eax
  792.         inc     eax
  793.         ret
  794. .end:
  795.         xor     eax, eax
  796.         ret
  797. .big:
  798.         push    ecx edx
  799.         push    -'0'
  800.         mov     ecx, 10
  801. @@:
  802.         xor     edx, edx
  803.         div     ecx
  804.         push    edx
  805.         test    eax, eax
  806.         jnz     @b
  807.         xchg    eax, edx
  808. @@:
  809.         pop     eax
  810.         add     al, '0'
  811.         stosb
  812.         jnz     @b
  813.         pop     edx ecx
  814.         pop     eax
  815.         inc     eax
  816.         ret
  817.  
  818. process_replace_file_name:
  819.         mov     ebp, [full_file_name_table]
  820.         mov     edi, [full_file_name_table.size]
  821.         dec     edi
  822.         shl     edi, 7
  823.         add     edi, ebp
  824. .loop:
  825.         cmp     edi, ebp
  826.         jb      .notfound
  827.         push    esi edi
  828. @@:
  829.         cmp     byte [edi], 0
  830.         jz      .dest_done
  831.         lodsb
  832.         test    al, al
  833.         jz      .cont
  834.         or      al, 20h
  835.         scasb
  836.         jz      @b
  837.         jmp     .cont
  838. .dest_done:
  839.         cmp     byte [esi], 0
  840.         jz      .found
  841.         cmp     byte [esi], '/'
  842.         jnz     .cont
  843.         inc     esi
  844.         jmp     .found
  845. .cont:
  846.         pop     edi esi
  847.         sub     edi, 128
  848.         jmp     .loop
  849. .found:
  850.         pop     edi eax
  851.         mov     ebp, esi
  852.         cmp     byte [esi], 0
  853.         lea     esi, [edi+64]
  854.         jnz     .ret
  855. .notfound:
  856.         xor     ebp, ebp
  857. .ret:
  858.         ret
  859.  
  860. sys_current_directory:
  861. ;       mov     esi, [current_slot]
  862. ;       mov     esi, [esi+APPDATA.cur_dir]
  863. ;       mov     edx, esi
  864.  
  865. ;get length string of appdata.cur_dir
  866.         mov     eax, [current_slot]
  867.         mov     edi, [eax+APPDATA.cur_dir]
  868.  
  869.         dec     ebx
  870.         jz      .set
  871.         dec     ebx
  872.         jz      .get
  873.         ret
  874. .get:
  875. ; sysfunction 30.2: [for app] eax=30,ebx=2,ecx->buffer,edx=len
  876. ; for our code: ebx->buffer,ecx=len
  877. max_cur_dir     equ     0x1000
  878.  
  879.         mov     ebx,edi
  880.  
  881.         push    ecx
  882.         push    edi
  883.  
  884.         xor     eax,eax
  885.         mov     ecx,max_cur_dir
  886.  
  887.         repne   scasb           ;find zerro at and string
  888.         jnz     .error          ; no zero in cur_dir: internal error, should not happen
  889.  
  890.         sub     edi,ebx         ;lenght for copy
  891.         inc     edi
  892.         mov     [esp+32+8],edi  ;return in eax
  893.  
  894.         cmp     edx, edi
  895.         jbe     @f
  896.         mov     edx, edi
  897. @@:
  898. ;source string
  899.         pop     esi
  900. ;destination string
  901.         pop     edi
  902.         cmp     edx, 1
  903.         jbe     .ret
  904.  
  905.         mov     al,'/'          ;start string with '/'
  906.         stosb
  907.         mov     ecx,edx
  908.         rep     movsb           ;copy string
  909. .ret:   ret
  910.  
  911. .error: add     esp,8
  912.         or      dword [esp+32],-1       ;error not found zerro at string ->[eax+APPDATA.cur_dir]
  913.         ret
  914. .set:
  915. ; sysfunction 30.1: [for app] eax=30,ebx=1,ecx->string
  916. ; for our code: ebx->string to set
  917. ; use generic resolver with APPDATA.cur_dir as destination
  918.         push    max_cur_dir     ;0x1000
  919.         push    edi     ;destination
  920.         mov     ebx,ecx
  921.         call    get_full_file_name
  922.         ret
  923.  
  924. ; in: ebx = file name, [esp+4] = destination, [esp+8] = sizeof destination
  925. ; destroys all registers except ebp,esp
  926. get_full_file_name:
  927.         push    ebp
  928.         mov     esi, [current_slot]
  929.         mov     esi, [esi+APPDATA.cur_dir]
  930.         mov     edx, esi
  931. @@:
  932.         inc     esi
  933.         cmp     byte [esi-1], 0
  934.         jnz     @b
  935.         dec     esi
  936.         cmp     byte [ebx], '/'
  937.         jz      .set_absolute
  938. ; string gives relative path
  939.         mov     edi, [esp+8]    ; destination
  940. .relative:
  941.         cmp     byte [ebx], 0
  942.         jz      .set_ok
  943.         cmp     word [ebx], '.'
  944.         jz      .set_ok
  945.         cmp     word [ebx], './'
  946.         jnz     @f
  947.         add     ebx, 2
  948.         jmp     .relative
  949. @@:
  950.         cmp     word [ebx], '..'
  951.         jnz     .doset_relative
  952.         cmp     byte [ebx+2], 0
  953.         jz      @f
  954.         cmp     byte [ebx+2], '/'
  955.         jnz     .doset_relative
  956. @@:
  957.         dec     esi
  958.         cmp     byte [esi], '/'
  959.         jnz     @b
  960.         add     ebx, 3
  961.         jmp     .relative
  962. .set_ok:
  963.         cmp     edx, edi        ; is destination equal to APPDATA.cur_dir?
  964.         jz      .set_ok.cur_dir
  965.         sub     esi, edx
  966.         cmp     esi, [esp+12]
  967.         jb      .set_ok.copy
  968. .fail:
  969.         mov     byte [edi], 0
  970.         xor     eax, eax        ; fail
  971.         pop     ebp
  972.         ret     8
  973. .set_ok.copy:
  974.         mov     ecx, esi
  975.         mov     esi, edx
  976.         rep     movsb
  977.         mov     byte [edi], 0
  978. .ret.ok:
  979.         mov     al, 1   ; ok
  980.         pop     ebp
  981.         ret     8
  982. .set_ok.cur_dir:
  983.         mov     byte [esi], 0
  984.         jmp     .ret.ok
  985. .doset_relative:
  986.         cmp     edx, edi
  987.         jz      .doset_relative.cur_dir
  988.         sub     esi, edx
  989.         cmp     esi, [esp+12]
  990.         jae     .fail
  991.         mov     ecx, esi
  992.         mov     esi, edx
  993.         mov     edx, edi
  994.         rep     movsb
  995.         jmp     .doset_relative.copy
  996. .doset_relative.cur_dir:
  997.         mov     edi, esi
  998. .doset_relative.copy:
  999.         add     edx, [esp+12]
  1000.         mov     byte [edi], '/'
  1001.         inc     edi
  1002.         cmp     edi, edx
  1003.         jae     .overflow
  1004. @@:
  1005.         mov     al, [ebx]
  1006.         inc     ebx
  1007.         stosb
  1008.         test    al, al
  1009.         jz      .ret.ok
  1010.         cmp     edi, edx
  1011.         jb      @b
  1012. .overflow:
  1013.         dec     edi
  1014.         jmp     .fail
  1015. .set_absolute:
  1016.         lea     esi, [ebx+1]
  1017.         call    process_replace_file_name
  1018.         mov     edi, [esp+8]
  1019.         mov     edx, [esp+12]
  1020.         add     edx, edi
  1021. .set_copy:
  1022.         lodsb
  1023.         stosb
  1024.         test    al, al
  1025.         jz      .set_part2
  1026. .set_copy_cont:
  1027.         cmp     edi, edx
  1028.         jb      .set_copy
  1029.         jmp     .overflow
  1030. .set_part2:
  1031.         mov     esi, ebp
  1032.         xor     ebp, ebp
  1033.         test    esi, esi
  1034.         jz      .ret.ok
  1035.         mov     byte [edi-1], '/'
  1036.         jmp     .set_copy_cont
  1037.  
  1038. ; ===============  moved from fs/iso9660.inc
  1039.  
  1040. char_todown:
  1041. ; convert character to uppercase, using cp866 encoding
  1042. ; in: al=symbol
  1043. ; out: al=converted symbol
  1044.         cmp     al, 'A'
  1045.         jb      .ret
  1046.         cmp     al, 'Z'
  1047.         jbe     .az
  1048.         cmp     al, '€'
  1049.         jb      .ret
  1050.         cmp     al, ''
  1051.         jb      .rus1
  1052.         cmp     al, 'Ÿ'
  1053.         ja      .ret
  1054. ; 0x90-0x9F -> 0xE0-0xEF
  1055.         add     al, 'à'-''
  1056. .ret:
  1057.         ret
  1058. .rus1:
  1059. ; 0x80-0x8F -> 0xA0-0xAF
  1060. .az:
  1061.         add     al, 0x20
  1062.         ret
  1063.  
  1064. uni2ansi_char:
  1065. ; convert UNICODE character in al to ANSI character in ax, using cp866 encoding
  1066. ; in: ax=UNICODE character
  1067. ; out: al=converted ANSI character
  1068.         cmp     ax, 0x80
  1069.         jb      .ascii
  1070.         cmp     ax, 0x401
  1071.         jz      .yo1
  1072.         cmp     ax, 0x451
  1073.         jz      .yo2
  1074.         cmp     ax, 0x410
  1075.         jb      .unk
  1076.         cmp     ax, 0x440
  1077.         jb      .rus1
  1078.         cmp     ax, 0x450
  1079.         jb      .rus2
  1080. .unk:
  1081.         mov     al, '_'
  1082.         jmp     .doit
  1083. .yo1:
  1084.         mov     al, 'ð'
  1085.         jmp     .doit
  1086. .yo2:
  1087.         mov     al, 'ñ'
  1088.         jmp     .doit
  1089. .rus1:
  1090. ; 0x410-0x43F -> 0x80-0xAF
  1091.         add     al, 0x70
  1092.         jmp     .doit
  1093. .rus2:
  1094. ; 0x440-0x44F -> 0xE0-0xEF
  1095.         add     al, 0xA0
  1096. .ascii:
  1097. .doit:
  1098.         ret
  1099.