Subversion Repositories Kolibri OS

Rev

Rev 848 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;; RAMDISK functions                                            ;;
  7. ;; (C) 2004 Ville Turjanmaa, License: GPL                       ;;
  8. ;; Addings by M.Lisovin                                         ;;
  9. ;; LFN support by diamond                                       ;;
  10. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  11.  
  12. $Revision: 2971 $
  13.  
  14.  
  15. ; calculate fat chain
  16.  
  17. calculatefatchain:
  18.  
  19.    pushad
  20.  
  21.    mov esi, [_rd_fat]
  22.    mov  edi,RAMDISK_FAT
  23.  
  24.  fcnew:
  25.    mov  eax,dword [esi]
  26.    mov  ebx,dword [esi+4]
  27.    mov  ecx,dword [esi+8]
  28.    mov  edx,ecx
  29.    shr  edx,4   ;8 ok
  30.    shr  dx,4    ;7 ok
  31.    xor  ch,ch
  32.    shld ecx,ebx,20 ;6 ok
  33.    shr  cx,4     ;5 ok
  34.    shld ebx,eax,12
  35.    and  ebx,0x0fffffff  ;4 ok
  36.    shr  bx,4    ;3 ok
  37.    shl  eax,4
  38.    and  eax,0x0fffffff  ;2 ok
  39.    shr  ax,4  ;1 ok
  40.    mov  dword [edi],eax
  41.    mov  dword [edi+4],ebx
  42.    mov  dword [edi+8],ecx
  43.    mov  dword [edi+12],edx
  44.    add  edi,16
  45.    add  esi,12
  46.  
  47.    cmp  edi,RAMDISK_FAT+2856*2   ;2849 clusters
  48.    jnz  fcnew
  49.  
  50.    popad
  51.    ret
  52.  
  53.  
  54. restorefatchain:   ; restore fat chain
  55.  
  56.    pushad
  57.  
  58.    mov  esi,RAMDISK_FAT
  59.    mov  edi, [_rd_fat]
  60.  
  61.   fcnew2:
  62.    mov  eax,dword [esi]
  63.    mov  ebx,dword [esi+4]
  64.    shl  ax,4
  65.    shl  eax,4
  66.    shl  bx,4
  67.    shr  ebx,4
  68.    shrd eax,ebx,8
  69.    shr  ebx,8
  70.    mov  dword [edi],eax
  71.    mov  word [edi+4],bx
  72.    add  edi,6
  73.    add  esi,8
  74.  
  75.    cmp  edi, [_rd_fat_end]        ;4274 bytes - all used FAT
  76.    jb   fcnew2
  77.  
  78.    mov  esi,[_rd_fat]             ; duplicate fat chain
  79.    lea  edi,[esi+0x1200]
  80.    mov  ecx,1069        ;4274/4
  81.    cld
  82.    rep  movsd
  83.  
  84.    popad
  85.    ret
  86.  
  87.  
  88. ramdisk_free_space:
  89. ;---------------------------------------------
  90. ;
  91. ; returns free space in edi
  92. ; rewr.by Mihasik
  93. ;---------------------------------------------
  94.  
  95.         push   eax ebx ecx
  96.  
  97.         mov  edi,RAMDISK_FAT ;start of FAT
  98.         xor  ax,ax    ;Free cluster=0x0000 in FAT
  99.         xor  ebx,ebx  ;counter
  100.         mov  ecx,2849 ;2849 clusters
  101.         cld
  102.     rdfs1:
  103.         repne scasw
  104.         jnz  rdfs2    ;if last cluster not 0
  105.         inc  ebx
  106.         test    ecx, ecx
  107.         jnz     rdfs1
  108.     rdfs2:
  109.         shl  ebx,9    ;free clusters*512
  110.         mov  edi,ebx
  111.  
  112.         pop    ecx ebx eax
  113.         ret
  114.  
  115.  
  116. expand_filename:
  117. ;---------------------------------------------
  118. ;
  119. ; exapand filename with '.' to 11 character
  120. ; eax - pointer to filename
  121. ;---------------------------------------------
  122.  
  123.         push esi edi ebx
  124.  
  125.         mov  edi,esp                  ; check for '.' in the name
  126.         add  edi,12+8
  127.  
  128.         mov  esi,eax
  129.  
  130.         mov  eax,edi
  131.         mov  [eax+0],dword '    '
  132.         mov  [eax+4],dword '    '
  133.         mov  [eax+8],dword '    '
  134.  
  135.       flr1:
  136.  
  137.         cmp  [esi],byte '.'
  138.         jne  flr2
  139.         mov  edi,eax
  140.         add  edi,7
  141.         jmp  flr3
  142.  
  143.       flr2:
  144.  
  145.         mov  bl,[esi]
  146.         mov  [edi],bl
  147.  
  148.       flr3:
  149.  
  150.         inc  esi
  151.         inc  edi
  152.  
  153.         mov  ebx,eax
  154.         add  ebx,11
  155.  
  156.         cmp  edi,ebx
  157.         jbe  flr1
  158.  
  159.         pop  ebx edi esi
  160.         ret
  161.  
  162. fileread:
  163. ;----------------------------------------------------------------
  164. ;
  165. ;  fileread - sys floppy
  166. ;
  167. ;  eax  points to filename 11 chars
  168. ;  ebx  first wanted block       ; 1+ ; if 0 then set to 1
  169. ;  ecx  number of blocks to read ; 1+ ; if 0 then set to 1
  170. ;  edx  mem location to return data
  171. ;  esi  length of filename 12*X 0=root
  172. ;
  173. ;  ret ebx = size or 0xffffffff file not found
  174. ;      eax = 0 ok read or other = errormsg
  175. ;
  176. ;--------------------------------------------------------------
  177.         test   ebx,ebx ;if ebx=0 - set to 1
  178.         jnz    frfl5
  179.         inc    ebx
  180.       frfl5:
  181.         test   ecx,ecx ;if ecx=0 - set to 1
  182.         jnz    frfl6
  183.         inc    ecx
  184.       frfl6:
  185.         test   esi,esi          ; return ramdisk root
  186.         jnz    fr_noroot        ;if not root
  187.         cmp    ebx,14           ;14 clusters=root dir
  188.         ja     oorr
  189.         cmp    ecx,14
  190.         ja     oorr
  191.         jmp    fr_do
  192.       oorr:
  193.         mov    eax,5            ;out of root range (fnf)
  194.         xor    ebx,ebx
  195.         dec    ebx              ;0xffffffff
  196.         ret
  197.  
  198.       fr_do:                    ;reading rootdir
  199.         mov    edi,edx
  200.         dec    ebx
  201.         push   edx
  202.         mov    edx,ecx
  203.         add    edx,ebx
  204.         cmp    edx,15     ;ebx+ecx=14+1
  205.         pushf
  206.         jbe    fr_do1
  207.         sub    edx,14
  208.         sub    ecx,edx
  209.       fr_do1:
  210.         shl    ebx,9
  211.         mov    esi, [_rd_root]
  212.         add    esi,ebx
  213.         shl    ecx,7
  214.         cld
  215.         rep    movsd
  216.         popf
  217.         pop    edx
  218.         jae    fr_do2
  219.         xor    eax,eax ; ok read
  220.         xor    ebx,ebx
  221.         ret
  222.       fr_do2:        ;if last cluster
  223.         mov    eax,6  ;end of file
  224.         xor    ebx,ebx
  225.         ret
  226.  
  227.      fr_noroot:
  228.  
  229.         sub    esp,32
  230.         call   expand_filename
  231.  
  232.         dec    ebx
  233.  
  234.         push   eax
  235.  
  236.         push   eax ebx ecx edx esi edi
  237.         call   rd_findfile
  238.         je     fifound
  239.         add    esp,32+28   ;if file not found
  240.         ret
  241.  
  242.      fifound:
  243.  
  244.         mov    ebx,[edi-11+28]          ;file size
  245.         mov    [esp+20],ebx
  246.         mov    [esp+24],ebx
  247.         add    edi,0xf
  248.         movzx  eax,word [edi]
  249.         mov    edi,eax                  ;edi=cluster
  250.  
  251.       frnew:
  252.  
  253.         add    eax,31                   ;bootsector+2*fat+filenames
  254.         shl    eax,9                    ;*512
  255.         add    eax, [_rd_base]          ;image base
  256.         mov    ebx,[esp+8]
  257.         mov    ecx,512                  ;[esp+4]
  258.  
  259.         cmp    [esp+16],dword 0         ; wanted cluster ?
  260.         jne    frfl7
  261.         call   memmove
  262.         add    [esp+8],dword 512
  263.         dec    dword [esp+12]           ; last wanted cluster ?
  264.         je     frnoread
  265.         jmp    frfl8
  266.       frfl7:
  267.         dec    dword [esp+16]
  268.       frfl8:
  269.         movzx  eax,word [edi*2+RAMDISK_FAT]        ; find next cluster from FAT
  270.         mov    edi,eax
  271.         cmp    edi,4095                 ;eof  - cluster
  272.         jz     frnoread2
  273.  
  274.         cmp    [esp+24],dword 512       ;eof  - size
  275.         jb     frnoread
  276.         sub    [esp+24],dword 512
  277.  
  278.         jmp    frnew
  279.  
  280.       frnoread2:
  281.  
  282.         cmp    [esp+16],dword 0         ; eof without read ?
  283.         je     frnoread
  284.  
  285.         pop    edi esi edx ecx
  286.         add    esp,4
  287.         pop    ebx     ; ebx <- eax : size of file
  288.         add    esp,36
  289.         mov    eax,6   ; end of file
  290.         ret
  291.  
  292.       frnoread:
  293.  
  294.         pop    edi esi edx ecx
  295.         add    esp,4
  296.         pop    ebx     ; ebx <- eax : size of file
  297.         add    esp,36
  298.         xor    eax,eax  ;read ok
  299.         ret
  300.  
  301.  
  302.  
  303.    rd_findfile:
  304.    ;by Mihasik
  305.    ;IN: eax - pointer to filename OUT: filestring+11 in edi or notZero in flags and fnf in eax,ebx
  306.  
  307.         mov    edi, [_rd_root]      ;Point at directory
  308.         cld
  309.     rd_newsearch:
  310.         mov    esi,eax
  311.         mov    ecx,11
  312.         rep    cmpsb
  313.         je     rd_ff
  314.         add    cl,21
  315.         add    edi,ecx
  316.         cmp    edi, [_rd_root_end]
  317.         jb     rd_newsearch
  318.         mov    eax,5      ;if file not found - eax=5
  319.         xor    ebx,ebx
  320.         dec    ebx    ;ebx=0xffffffff and zf=0
  321.      rd_ff:
  322.         ret
  323.  
  324. ; \begin{diamond}
  325.  
  326. uni2ansi_str:
  327. ; convert UNICODE zero-terminated string to ASCII-string (codepage 866)
  328. ; in: esi->source, edi->buffer (may be esi=edi)
  329. ; destroys: eax,esi,edi
  330.         lodsw
  331.         test    ax, ax
  332.         jz      .done
  333.         cmp     ax, 0x80
  334.         jb      .ascii
  335.         cmp     ax, 0x401
  336.         jz      .yo1
  337.         cmp     ax, 0x451
  338.         jz      .yo2
  339.         cmp     ax, 0x410
  340.         jb      .unk
  341.         cmp     ax, 0x440
  342.         jb      .rus1
  343.         cmp     ax, 0x450
  344.         jb      .rus2
  345. .unk:
  346.         mov     al, '_'
  347.         jmp     .doit
  348. .yo1:
  349.         mov     al, 'ð'
  350.         jmp     .doit
  351. .yo2:
  352.         mov     al, 'ñ'
  353.         jmp     .doit
  354. .rus1:
  355. ; 0x410-0x43F -> 0x80-0xAF
  356.         add     al, 0x70
  357.         jmp     .doit
  358. .rus2:
  359. ; 0x440-0x44F -> 0xE0-0xEF
  360.         add     al, 0xA0
  361. .ascii:
  362. .doit:
  363.         stosb
  364.         jmp     uni2ansi_str
  365. .done:
  366.         mov     byte [edi], 0
  367.         ret
  368.  
  369. ansi2uni_char:
  370. ; convert ANSI character in al to UNICODE character in ax, using cp866 encoding
  371.         mov     ah, 0
  372. ; 0x00-0x7F - trivial map
  373.         cmp     al, 0x80
  374.         jb      .ret
  375. ; 0x80-0xAF -> 0x410-0x43F
  376.         cmp     al, 0xB0
  377.         jae     @f
  378.         add     ax, 0x410-0x80
  379. .ret:
  380.         ret
  381. @@:
  382. ; 0xE0-0xEF -> 0x440-0x44F
  383.         cmp     al, 0xE0
  384.         jb      .unk
  385.         cmp     al, 0xF0
  386.         jae     @f
  387.         add     ax, 0x440-0xE0
  388.         ret
  389. ; 0xF0 -> 0x401
  390. ; 0xF1 -> 0x451
  391. @@:
  392.         cmp     al, 'ð'
  393.         jz      .yo1
  394.         cmp     al, 'ñ'
  395.         jz      .yo2
  396. .unk:
  397.         mov     al, '_'         ; ah=0
  398.         ret
  399. .yo1:
  400.         mov     ax, 0x401
  401.         ret
  402. .yo2:
  403.         mov     ax, 0x451
  404.         ret
  405.  
  406. char_toupper:
  407. ; convert character to uppercase, using cp866 encoding
  408. ; in: al=symbol
  409. ; out: al=converted symbol
  410.         cmp     al, 'a'
  411.         jb      .ret
  412.         cmp     al, 'z'
  413.         jbe     .az
  414.         cmp     al, ' '
  415.         jb      .ret
  416.         cmp     al, 'à'
  417.         jb      .rus1
  418.         cmp     al, 'ï'
  419.         ja      .ret
  420. ; 0xE0-0xEF -> 0x90-0x9F
  421.         sub     al, 'à'-''
  422. .ret:
  423.         ret
  424. .rus1:
  425. ; 0xA0-0xAF -> 0x80-0x8F
  426. .az:
  427.         and     al, not 0x20
  428.         ret
  429.  
  430. fat_get_name:
  431. ; in: edi->FAT entry
  432. ; out: CF=1 - no valid entry
  433. ; else CF=0 and ebp->ASCIIZ-name
  434. ; (maximum length of filename is 255 (wide) symbols without trailing 0,
  435. ;  but implementation requires buffer 261 words)
  436. ; destroys eax
  437.         cmp     byte [edi], 0
  438.         jz      .no
  439.         cmp     byte [edi], 0xE5
  440.         jnz     @f
  441. .no:
  442.         stc
  443.         ret
  444. @@:
  445.         cmp     byte [edi+11], 0xF
  446.         jz      .longname
  447.         test    byte [edi+11], 8
  448.         jnz     .no
  449.         push    ecx
  450.         push    edi ebp
  451.         test    byte [ebp-4], 1
  452.         jnz     .unicode_short
  453.  
  454.         mov     eax, [edi]
  455.         mov     ecx, [edi+4]
  456.         mov     [ebp], eax
  457.         mov     [ebp+4], ecx
  458.  
  459.         mov     ecx, 8
  460. @@:
  461.         cmp     byte [ebp+ecx-1], ' '
  462.         loope    @b
  463.  
  464.         mov     eax, [edi+8]
  465.         cmp     al, ' '
  466.         je      .done
  467.         shl     eax, 8
  468.         mov     al, '.'
  469.  
  470.         lea ebp, [ebp+ecx+1]
  471.         mov     [ebp], eax
  472.         mov     ecx, 3
  473. @@:
  474.         rol eax, 8
  475.         cmp al, ' '
  476.         jne .done
  477.         loop   @b
  478.         dec ebp
  479. .done:
  480.         and     byte [ebp+ecx+1], 0   ; CF=0
  481.         pop     ebp edi ecx
  482.         ret
  483. .unicode_short:
  484.         mov     ecx, 8
  485.         push    ecx
  486. @@:
  487.         mov     al, [edi]
  488.         inc     edi
  489.         call    ansi2uni_char
  490.         mov     [ebp], ax
  491.         inc     ebp
  492.         inc     ebp
  493.         loop    @b
  494.         pop     ecx
  495. @@:
  496.         cmp     word [ebp-2], ' '
  497.         jnz     @f
  498.         dec     ebp
  499.         dec     ebp
  500.         loop    @b
  501. @@:
  502.         mov     word [ebp], '.'
  503.         inc     ebp
  504.         inc     ebp
  505.         mov     ecx, 3
  506.         push    ecx
  507. @@:
  508.         mov     al, [edi]
  509.         inc     edi
  510.         call    ansi2uni_char
  511.         mov     [ebp], ax
  512.         inc     ebp
  513.         inc     ebp
  514.         loop    @b
  515.         pop     ecx
  516. @@:
  517.         cmp     word [ebp-2], ' '
  518.         jnz     @f
  519.         dec     ebp
  520.         dec     ebp
  521.         loop    @b
  522.         dec     ebp
  523.         dec     ebp
  524. @@:
  525.         and     word [ebp], 0   ; CF=0
  526.         pop     ebp edi ecx
  527.         ret
  528. .longname:
  529. ; LFN
  530.         mov     al, byte [edi]
  531.         and     eax, 0x3F
  532.         dec     eax
  533.         cmp     al, 20
  534.         jae     .no     ; ignore invalid entries
  535.         mov     word [ebp+260*2], 0     ; force null-terminating for orphans
  536.         imul    eax, 13*2
  537.         add     ebp, eax
  538.         test    byte [edi], 0x40
  539.         jz      @f
  540.         mov     word [ebp+13*2], 0
  541. @@:
  542.         push    eax
  543. ; now copy name from edi to ebp ...
  544.         mov     eax, [edi+1]
  545.         mov     [ebp], eax      ; symbols 1,2
  546.         mov     eax, [edi+5]
  547.         mov     [ebp+4], eax    ; 3,4
  548.         mov     eax, [edi+9]
  549.         mov     [ebp+8], ax     ; 5
  550.         mov     eax, [edi+14]
  551.         mov     [ebp+10], eax   ; 6,7
  552.         mov     eax, [edi+18]
  553.         mov     [ebp+14], eax   ; 8,9
  554.         mov     eax, [edi+22]
  555.         mov     [ebp+18], eax   ; 10,11
  556.         mov     eax, [edi+28]
  557.         mov     [ebp+22], eax   ; 12,13
  558. ; ... done
  559.         pop     eax
  560.         sub     ebp, eax
  561.         test    eax, eax
  562.         jz      @f
  563. ; if this is not first entry, more processing required
  564.         stc
  565.         ret
  566. @@:
  567. ; if this is first entry:
  568.         test    byte [ebp-4], 1
  569.         jnz     .ret
  570. ; buffer at ebp contains UNICODE name, convert it to ANSI
  571.         push    esi edi
  572.         mov     esi, ebp
  573.         mov     edi, ebp
  574.         call    uni2ansi_str
  575.         pop     edi esi
  576. .ret:
  577.         clc
  578.         ret
  579.  
  580. fat_compare_name:
  581. ; compares ASCIIZ-names, case-insensitive (cp866 encoding)
  582. ; in: esi->name, ebp->name
  583. ; out: if names match: ZF=1 and esi->next component of name
  584. ;      else: ZF=0, esi is not changed
  585. ; destroys eax
  586.         push    ebp esi
  587. .loop:
  588.         mov     al, [ebp]
  589.         inc     ebp
  590.         call    char_toupper
  591.         push    eax
  592.         lodsb
  593.         call    char_toupper
  594.         cmp     al, [esp]
  595.         jnz     .done
  596.         pop     eax
  597.         test    al, al
  598.         jnz     .loop
  599.         dec     esi
  600.         pop     eax
  601.         pop     ebp
  602.         xor     eax, eax        ; set ZF flag
  603.         ret
  604. .done:
  605.         cmp     al, '/'
  606.         jnz     @f
  607.         cmp     byte [esp], 0
  608.         jnz     @f
  609.         mov     [esp+4], esi
  610. @@:
  611.         pop     eax
  612.         pop     esi ebp
  613.         ret
  614.  
  615. fat_time_to_bdfe:
  616. ; in: eax=FAT time
  617. ; out: eax=BDFE time
  618.         push    ecx edx
  619.         mov     ecx, eax
  620.         mov     edx, eax
  621.         shr     eax, 11
  622.         shl     eax, 16 ; hours
  623.         and     edx, 0x1F
  624.         add     edx, edx
  625.         mov     al, dl  ; seconds
  626.         shr     ecx, 5
  627.         and     ecx, 0x3F
  628.         mov     ah, cl  ; minutes
  629.         pop     edx ecx
  630.         ret
  631.  
  632. fat_date_to_bdfe:
  633.         push    ecx edx
  634.         mov     ecx, eax
  635.         mov     edx, eax
  636.         shr     eax, 9
  637.         add     ax, 1980
  638.         shl     eax, 16 ; year
  639.         and     edx, 0x1F
  640.         mov     al, dl  ; day
  641.         shr     ecx, 5
  642.         and     ecx, 0xF
  643.         mov     ah, cl  ; month
  644.         pop     edx ecx
  645.         ret
  646.  
  647. bdfe_to_fat_time:
  648.         push    edx
  649.         mov     edx, eax
  650.         shr     eax, 16
  651.         and     dh, 0x3F
  652.         shl     eax, 6
  653.         or      al, dh
  654.         shr     dl, 1
  655.         and     dl, 0x1F
  656.         shl     eax, 5
  657.         or      al, dl
  658.         pop     edx
  659.         ret
  660.  
  661. bdfe_to_fat_date:
  662.         push    edx
  663.         mov     edx, eax
  664.         shr     eax, 16
  665.         sub     ax, 1980
  666.         and     dh, 0xF
  667.         shl     eax, 4
  668.         or      al, dh
  669.         and     dl, 0x1F
  670.         shl     eax, 5
  671.         or      al, dl
  672.         pop     edx
  673.         ret
  674.  
  675. fat_entry_to_bdfe:
  676. ; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
  677. ; destroys eax
  678.         mov     eax, [ebp-4]
  679.         mov     [esi+4], eax    ; ASCII/UNICODE name
  680. fat_entry_to_bdfe2:
  681.         movzx   eax, byte [edi+11]
  682.         mov     [esi], eax      ; attributes
  683.         movzx   eax, word [edi+14]
  684.         call    fat_time_to_bdfe
  685.         mov     [esi+8], eax    ; creation time
  686.         movzx   eax, word [edi+16]
  687.         call    fat_date_to_bdfe
  688.         mov     [esi+12], eax   ; creation date
  689.         and     dword [esi+16], 0       ; last access time is not supported on FAT
  690.         movzx   eax, word [edi+18]
  691.         call    fat_date_to_bdfe
  692.         mov     [esi+20], eax   ; last access date
  693.         movzx   eax, word [edi+22]
  694.         call    fat_time_to_bdfe
  695.         mov     [esi+24], eax   ; last write time
  696.         movzx   eax, word [edi+24]
  697.         call    fat_date_to_bdfe
  698.         mov     [esi+28], eax   ; last write date
  699.         mov     eax, [edi+28]
  700.         mov     [esi+32], eax   ; file size (low dword)
  701.         xor     eax, eax
  702.         mov     [esi+36], eax   ; file size (high dword)
  703.         test    ebp, ebp
  704.         jz      .ret
  705.         push    ecx edi
  706.         lea     edi, [esi+40]
  707.         mov     esi, ebp
  708.         test    byte [esi-4], 1
  709.         jz      .ansi
  710.         mov     ecx, 260/2
  711.         rep     movsd
  712.         mov     [edi-2], ax
  713. @@:
  714.         mov     esi, edi
  715.         pop     edi ecx
  716. .ret:
  717.         ret
  718. .ansi:
  719.         mov     ecx, 264/4
  720.         rep     movsd
  721.         mov     [edi-1], al
  722.         jmp     @b
  723.  
  724. bdfe_to_fat_entry:
  725. ; convert BDFE at edx to FAT entry at edi
  726. ; destroys eax
  727. ; attributes byte
  728.         test    byte [edi+11], 8        ; volume label?
  729.         jnz     @f
  730.         mov     al, [edx]
  731.         and     al, 0x27
  732.         and     byte [edi+11], 0x10
  733.         or      byte [edi+11], al
  734. @@:
  735.         mov     eax, [edx+8]
  736.         call    bdfe_to_fat_time
  737.         mov     [edi+14], ax            ; creation time
  738.         mov     eax, [edx+12]
  739.         call    bdfe_to_fat_date
  740.         mov     [edi+16], ax            ; creation date
  741.         mov     eax, [edx+20]
  742.         call    bdfe_to_fat_date
  743.         mov     [edi+18], ax            ; last access date
  744.         mov     eax, [edx+24]
  745.         call    bdfe_to_fat_time
  746.         mov     [edi+22], ax            ; last write time
  747.         mov     eax, [edx+28]
  748.         call    bdfe_to_fat_date
  749.         mov     [edi+24], ax            ; last write date
  750.         ret
  751.  
  752. ramdisk_root_first:
  753.         mov     edi, [_rd_root]
  754.         clc
  755.         ret
  756. ramdisk_root_next:
  757.         add     edi, 0x20
  758.         cmp     edi, [_rd_root_end]
  759.         cmc
  760.         ret
  761.  
  762. ramdisk_root_extend_dir:
  763.         stc
  764.         ret
  765.  
  766. uglobal
  767. ; this is for delete support
  768. rd_prev_sector          dd      ?
  769. rd_prev_prev_sector     dd      ?
  770. endg
  771.  
  772. ramdisk_notroot_next:
  773.         add     edi, 0x20
  774.         test    edi, 0x1FF
  775.         jz      ramdisk_notroot_next_sector
  776.         ret     ; CF=0
  777. ramdisk_notroot_next_sector:
  778.         push    ecx
  779.         mov     ecx, [eax]
  780.         push    [rd_prev_sector]
  781.         pop     [rd_prev_prev_sector]
  782.         mov     [rd_prev_sector], ecx
  783.         mov     ecx, [ecx*2+RAMDISK_FAT]
  784.         and     ecx, 0xFFF
  785.         cmp     ecx, 2849
  786.         jae     ramdisk_notroot_first.err2
  787.         mov     [eax], ecx
  788.         pop     ecx
  789. ramdisk_notroot_first:
  790.         mov     eax, [eax]
  791.         cmp     eax, 2
  792.         jb      .err
  793.         cmp     eax, 2849
  794.         jae     .err
  795.         shl     eax, 9
  796.         lea     edi, [eax+(31 shl 9)]
  797.         add     edi, [_rd_base]
  798.         clc
  799.         ret
  800. .err2:
  801.         pop     ecx
  802. .err:
  803.         stc
  804.         ret
  805. ramdisk_notroot_next_write:
  806.         test    edi, 0x1FF
  807.         jz      ramdisk_notroot_next_sector
  808. ramdisk_root_next_write:
  809.         ret
  810.  
  811. ramdisk_notroot_extend_dir:
  812.         pusha
  813.         xor     eax, eax
  814.         mov     edi, RAMDISK_FAT
  815.         mov     ecx, 2849
  816.         repnz   scasw
  817.         jnz     .notfound
  818.         mov     word [edi-2], 0xFFF
  819.         sub     edi, RAMDISK_FAT
  820.         shr     edi, 1
  821.         dec     edi
  822.         mov     eax, [esp+28]
  823.         mov     ecx, [eax]
  824.         mov     [RAMDISK_FAT+ecx*2], di
  825.         mov     [eax], edi
  826.         shl     edi, 9
  827.         add     edi, (31 shl 9)
  828.         add     edi, [_rd_base]
  829.         mov     [esp], edi
  830.         xor     eax, eax
  831.         mov     ecx, 128
  832.         rep     stosd
  833.         popa
  834.         clc
  835.         ret
  836. .notfound:
  837.         popa
  838.         stc
  839.         ret
  840.  
  841. rd_find_lfn:
  842. ; in: esi+ebp -> name
  843. ; out: CF=1 - file not found
  844. ;      else CF=0 and edi->direntry
  845.         push    esi edi
  846.         push    0
  847.         push    ramdisk_root_first
  848.         push    ramdisk_root_next
  849. .loop:
  850.         call    fat_find_lfn
  851.         jc      .notfound
  852.         cmp     byte [esi], 0
  853.         jz      .found
  854. .continue:
  855.         test    byte [edi+11], 10h
  856.         jz      .notfound
  857.         movzx   eax, word [edi+26]
  858.         mov     [esp+8], eax
  859.         mov     dword [esp+4], ramdisk_notroot_first
  860.         mov     dword [esp], ramdisk_notroot_next
  861.         test    eax, eax
  862.         jnz     .loop
  863.         mov     dword [esp+4], ramdisk_root_first
  864.         mov     dword [esp], ramdisk_notroot_next
  865.         jmp     .loop
  866. .notfound:
  867.         add     esp, 12
  868.         pop     edi esi
  869.         stc
  870.         ret
  871. .found:
  872.         test    ebp, ebp
  873.         jz      @f
  874.         mov     esi, ebp
  875.         xor     ebp, ebp
  876.         jmp     .continue
  877. @@:
  878.         mov     eax, [esp+8]
  879.         add     esp, 16         ; CF=0
  880.         pop     esi
  881.         ret
  882.  
  883. ;----------------------------------------------------------------
  884. ;
  885. ;  fs_RamdiskRead - LFN variant for reading sys floppy
  886. ;
  887. ;  esi  points to filename
  888. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  889. ;       may be ebx=0 - start from first byte
  890. ;  ecx  number of bytes to read, 0+
  891. ;  edx  mem location to return data
  892. ;
  893. ;  ret ebx = bytes read or 0xffffffff file not found
  894. ;      eax = 0 ok read or other = errormsg
  895. ;
  896. ;--------------------------------------------------------------
  897. fs_RamdiskRead:
  898.         cmp     byte [esi], 0
  899.         jnz     @f
  900.         or      ebx, -1
  901.         mov     eax, 10         ; access denied
  902.         ret
  903. @@:
  904.         push    edi
  905.         call    rd_find_lfn
  906.         jnc     .found
  907.         pop     edi
  908.         or      ebx, -1
  909.         mov     eax, 5          ; file not found
  910.         ret
  911. .found:
  912.         test    ebx, ebx
  913.         jz      .l1
  914.         cmp     dword [ebx+4], 0
  915.         jz      @f
  916.         xor     ebx, ebx
  917. .reteof:
  918.         mov     eax, 6          ; EOF
  919.         pop     edi
  920.         ret
  921. @@:
  922.         mov     ebx, [ebx]
  923. .l1:
  924.         push    ecx edx
  925.         push    0
  926.         mov     eax, [edi+28]
  927.         sub     eax, ebx
  928.         jb      .eof
  929.         cmp     eax, ecx
  930.         jae     @f
  931.         mov     ecx, eax
  932.         mov     byte [esp], 6           ; EOF
  933. @@:
  934.         movzx   edi, word [edi+26]      ; cluster
  935. .new:
  936.         jecxz   .done
  937.         test    edi, edi
  938.         jz      .eof
  939.         cmp     edi, 0xFF8
  940.         jae     .eof
  941.         lea     eax, [edi+31]           ; bootsector+2*fat+filenames
  942.         shl     eax, 9                  ; *512
  943.         add     eax, [_rd_base]         ; image base
  944. ; now eax points to data of cluster
  945.         sub     ebx, 512
  946.         jae     .skip
  947.         lea     eax, [eax+ebx+512]
  948.         neg     ebx
  949.         push    ecx
  950.         cmp     ecx, ebx
  951.         jbe     @f
  952.         mov     ecx, ebx
  953. @@:
  954.         mov     ebx, edx
  955.         call    memmove
  956.         add     edx, ecx
  957.         sub     [esp], ecx
  958.         pop     ecx
  959.         xor     ebx, ebx
  960. .skip:
  961.         movzx   edi, word [edi*2+RAMDISK_FAT]      ; find next cluster from FAT
  962.         jmp     .new
  963. .eof:
  964.         mov     ebx, edx
  965.         pop     eax edx ecx
  966.         sub     ebx, edx
  967.         jmp     .reteof
  968. .done:
  969.         mov     ebx, edx
  970.         pop     eax edx ecx edi
  971.         sub     ebx, edx
  972.         ret
  973.  
  974. ;----------------------------------------------------------------
  975. ;
  976. ;  fs_RamdiskReadFolder - LFN variant for reading sys floppy folder
  977. ;
  978. ;  esi  points to filename; only root is folder on ramdisk
  979. ;  ebx  pointer to structure 32-bit number = first wanted block
  980. ;                          & flags (bitfields)
  981. ; flags: bit 0: 0=ANSI names, 1=UNICODE names
  982. ;  ecx  number of blocks to read, 0+
  983. ;  edx  mem location to return data
  984. ;
  985. ;  ret ebx = size or 0xffffffff file not found
  986. ;      eax = 0 ok read or other = errormsg
  987. ;
  988. ;--------------------------------------------------------------
  989. fs_RamdiskReadFolder:
  990.         push    edi
  991.         cmp     byte [esi], 0
  992.         jz      .root
  993.         call    rd_find_lfn
  994.         jnc     .found
  995.         pop     edi
  996.         or      ebx, -1
  997.         mov     eax, ERROR_FILE_NOT_FOUND
  998.         ret
  999. .found:
  1000.         test    byte [edi+11], 0x10
  1001.         jnz     .found_dir
  1002.         pop     edi
  1003.         or      ebx, -1
  1004.         mov     eax, ERROR_ACCESS_DENIED
  1005.         ret
  1006. .found_dir:
  1007.         movzx   eax, word [edi+26]
  1008.         add     eax, 31
  1009.         push    0
  1010.         jmp     .doit
  1011. .root:
  1012.         mov     eax, 19
  1013.         push    14
  1014. .doit:
  1015.         push    esi ecx ebp
  1016.         sub     esp, 262*2      ; reserve space for LFN
  1017.         mov     ebp, esp
  1018.         push    dword [ebx+4]   ; for fat_get_name: read ANSI/UNICODE names
  1019.         mov     ebx, [ebx]
  1020. ; init header
  1021.         push    eax ecx
  1022.         mov     edi, edx
  1023.         mov     ecx, 32/4
  1024.         xor     eax, eax
  1025.         rep     stosd
  1026.         mov     byte [edx], 1   ; version
  1027.         pop     ecx eax
  1028.         mov     esi, edi        ; esi points to block of data of folder entry (BDFE)
  1029. .main_loop:
  1030.         mov     edi, eax
  1031.         shl     edi, 9
  1032.         add     edi, [_rd_base]
  1033.         push    eax
  1034. .l1:
  1035.         call    fat_get_name
  1036.         jc      .l2
  1037.         cmp     byte [edi+11], 0xF
  1038.         jnz     .do_bdfe
  1039.         add     edi, 0x20
  1040.         test    edi, 0x1FF
  1041.         jnz     .do_bdfe
  1042.         pop     eax
  1043.         inc     eax
  1044.         dec     byte [esp+262*2+16]
  1045.         jz      .done
  1046.         jns     @f
  1047. ; read next sector from FAT
  1048.         mov     eax, [(eax-31-1)*2+RAMDISK_FAT]
  1049.         and     eax, 0xFFF
  1050.         cmp     eax, 0xFF8
  1051.         jae     .done
  1052.         add     eax, 31
  1053.         mov     byte [esp+262*2+16], 0
  1054. @@:
  1055.         mov     edi, eax
  1056.         shl     edi, 9
  1057.         add     edi, [_rd_base]
  1058.         push    eax
  1059. .do_bdfe:
  1060.         inc     dword [edx+8]   ; new file found
  1061.         dec     ebx
  1062.         jns     .l2
  1063.         dec     ecx
  1064.         js      .l2
  1065.         inc     dword [edx+4]  ; new file block copied
  1066.         call    fat_entry_to_bdfe
  1067. .l2:
  1068.         add     edi, 0x20
  1069.         test    edi, 0x1FF
  1070.         jnz     .l1
  1071.         pop     eax
  1072.         inc     eax
  1073.         dec     byte [esp+262*2+16]
  1074.         jz      .done
  1075.         jns     @f
  1076. ; read next sector from FAT
  1077.         mov     eax, [(eax-31-1)*2+RAMDISK_FAT]
  1078.         and     eax, 0xFFF
  1079.         cmp     eax, 0xFF8
  1080.         jae     .done
  1081.         add     eax, 31
  1082.         mov     byte [esp+262*2+16], 0
  1083. @@:
  1084.         jmp     .main_loop
  1085. .done:
  1086.         add     esp, 262*2+4
  1087.         pop     ebp
  1088.         mov     ebx, [edx+4]
  1089.         xor     eax, eax
  1090.         dec     ecx
  1091.         js      @f
  1092.         mov     al, ERROR_END_OF_FILE
  1093. @@:
  1094.         pop     ecx esi edi edi
  1095.         ret
  1096.  
  1097. iglobal
  1098. label fat_legal_chars byte
  1099. ; 0 = not allowed
  1100. ; 1 = allowed only in long names
  1101. ; 3 = allowed
  1102.         times 32 db 0
  1103. ;                 ! " # $ % & ' ( ) * + , - . /
  1104.         db      1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0
  1105. ;               0 1 2 3 4 5 6 7 8 9 : ; < = > ?
  1106.         db      3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0
  1107. ;               @ A B C D E F G H I J K L M N O
  1108.         db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
  1109. ;               P Q R S T U V W X Y Z [ \ ] ^ _
  1110.         db      3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3
  1111. ;               ` a b c d e f g h i j k l m n o
  1112.         db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
  1113. ;               p q r s t u v w x y z { | } ~
  1114.         db      3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0
  1115. endg
  1116.  
  1117. fat_name_is_legal:
  1118. ; in: esi->(long) name
  1119. ; out: CF set <=> legal
  1120. ; destroys eax
  1121.         push    esi
  1122.         xor     eax, eax
  1123. @@:
  1124.         lodsb
  1125.         test    al, al
  1126.         jz      .done
  1127.         cmp     al, 80h
  1128.         jae     .big
  1129.         test    [fat_legal_chars+eax], 1
  1130.         jnz     @b
  1131. .err:
  1132.         pop     esi
  1133.         clc
  1134.         ret
  1135. .big:
  1136. ; 0x80-0xAF, 0xE0-0xEF
  1137.         cmp     al, 0xB0
  1138.         jb      @b
  1139.         cmp     al, 0xE0
  1140.         jb      .err
  1141.         cmp     al, 0xF0
  1142.         jb      @b
  1143.         jmp     .err
  1144. .done:
  1145.         sub     esi, [esp]
  1146.         cmp     esi, 257
  1147.         pop     esi
  1148.         ret
  1149.  
  1150. fat_next_short_name:
  1151. ; in: edi->8+3 name
  1152. ; out: name corrected
  1153. ;      CF=1 <=> error
  1154.         pushad
  1155.         mov     ecx, 8
  1156.         mov     al, '~'
  1157.         std
  1158.         push    edi
  1159.         add     edi, 7
  1160.         repnz   scasb
  1161.         pop     edi
  1162.         cld
  1163.         jz      .tilde
  1164. ; tilde is not found, insert "~1" at end
  1165.         add     edi, 6
  1166.         cmp     word [edi], '  '
  1167.         jnz     .insert_tilde
  1168. @@:     dec     edi
  1169.         cmp     byte [edi], ' '
  1170.         jz      @b
  1171.         inc     edi
  1172. .insert_tilde:
  1173.         mov     word [edi], '~1'
  1174.         popad
  1175.         clc
  1176.         ret
  1177. .tilde:
  1178.         push    edi
  1179.         add     edi, 7
  1180.         xor     ecx, ecx
  1181. @@:
  1182. ; after tilde may be only digits and trailing spaces
  1183.         cmp     byte [edi], '~'
  1184.         jz      .break
  1185.         cmp     byte [edi], ' '
  1186.         jz      .space
  1187.         cmp     byte [edi], '9'
  1188.         jnz     .found
  1189.         dec     edi
  1190.         jmp     @b
  1191. .space:
  1192.         dec     edi
  1193.         inc     ecx
  1194.         jmp     @b
  1195. .found:
  1196.         inc     byte [edi]
  1197.         add     dword [esp], 8
  1198.         jmp     .zerorest
  1199. .break:
  1200.         jecxz   .noplace
  1201.         inc     edi
  1202.         mov     al, '1'
  1203. @@:
  1204.         xchg    al, [edi]
  1205.         inc     edi
  1206.         cmp     al, ' '
  1207.         mov     al, '0'
  1208.         jnz     @b
  1209. .succ:
  1210.         pop     edi
  1211.         popad
  1212.         clc
  1213.         ret
  1214. .noplace:
  1215.         dec     edi
  1216.         cmp     edi, [esp]
  1217.         jz      .err
  1218.         add     dword [esp], 8
  1219.         mov     word [edi], '~1'
  1220.         inc     edi
  1221.         inc     edi
  1222. @@:
  1223.         mov     byte [edi], '0'
  1224. .zerorest:
  1225.         inc     edi
  1226.         cmp     edi, [esp]
  1227.         jb      @b
  1228.         pop     edi
  1229.         popad
  1230.         ;clc    ; automatically
  1231.         ret
  1232. .err:
  1233.         pop     edi
  1234.         popad
  1235.         stc
  1236.         ret
  1237.  
  1238. fat_gen_short_name:
  1239. ; in: esi->long name
  1240. ;     edi->buffer (8+3=11 chars)
  1241. ; out: buffer filled
  1242.         pushad
  1243.         mov     eax, '    '
  1244.         push    edi
  1245.         stosd
  1246.         stosd
  1247.         stosd
  1248.         pop     edi
  1249.         xor     eax, eax
  1250.         push    8
  1251.         pop     ebx
  1252.         lea     ecx, [edi+8]
  1253. .loop:
  1254.         lodsb
  1255.         test    al, al
  1256.         jz      .done
  1257.         call    char_toupper
  1258.         cmp     al, ' '
  1259.         jz      .space
  1260.         cmp     al, 80h
  1261.         ja      .big
  1262.         test    [fat_legal_chars+eax], 2
  1263.         jnz     .symbol
  1264. .inv_symbol:
  1265.         mov     al, '_'
  1266.         or      bh, 1
  1267. .symbol:
  1268.         cmp     al, '.'
  1269.         jz      .dot
  1270. .normal_symbol:
  1271.         dec     bl
  1272.         jns     .store
  1273.         mov     bl, 0
  1274. .space:
  1275.         or      bh, 1
  1276.         jmp     .loop
  1277. .store:
  1278.         stosb
  1279.         jmp     .loop
  1280. .big:
  1281.         cmp     al, 0xB0
  1282.         jb      .normal_symbol
  1283.         cmp     al, 0xE0
  1284.         jb      .inv_symbol
  1285.         cmp     al, 0xF0
  1286.         jb      .normal_symbol
  1287.         jmp     .inv_symbol
  1288. .dot:
  1289.         test    bh, 2
  1290.         jz      .firstdot
  1291.         pop     ebx
  1292.         add     ebx, edi
  1293.         sub     ebx, ecx
  1294.         push    ebx
  1295.         cmp     ebx, ecx
  1296.         jb      @f
  1297.         pop     ebx
  1298.         push    ecx
  1299. @@:
  1300.         cmp     edi, ecx
  1301.         jbe     .skip
  1302. @@:
  1303.         dec     edi
  1304.         mov     al, [edi]
  1305.         dec     ebx
  1306.         mov     [ebx], al
  1307.         mov     byte [edi], ' '
  1308.         cmp     edi, ecx
  1309.         ja      @b
  1310. .skip:
  1311.         mov     bh, 3
  1312.         jmp     @f
  1313. .firstdot:
  1314.         cmp     bl, 8
  1315.         jz      .space
  1316.         push    edi
  1317.         or      bh, 2
  1318. @@:
  1319.         mov     edi, ecx
  1320.         mov     bl, 3
  1321.         jmp     .loop
  1322. .done:
  1323.         test    bh, 2
  1324.         jz      @f
  1325.         pop     edi
  1326. @@:
  1327.         lea     edi, [ecx-8]
  1328.         test    bh, 1
  1329.         jz      @f
  1330.         call    fat_next_short_name
  1331. @@:
  1332.         popad
  1333.         ret
  1334.  
  1335. ;----------------------------------------------------------------
  1336. ;
  1337. ;  fs_RamdiskRewrite - LFN variant for writing ramdisk
  1338. ;  fs_RamdiskCreateFolder - create folder on ramdisk
  1339. ;
  1340. ;  esi  points to file/folder name
  1341. ;  ebx  ignored (reserved)
  1342. ;  ecx  number of bytes to write, 0+ (ignored for folders)
  1343. ;  edx  mem location to data (ignored for folders)
  1344. ;
  1345. ;  ret ebx = number of written bytes
  1346. ;      eax = 0 ok read or other = errormsg
  1347. ;
  1348. ;--------------------------------------------------------------
  1349. @@:
  1350.         mov     eax, ERROR_ACCESS_DENIED
  1351.         xor     ebx, ebx
  1352.         ret
  1353.  
  1354. fs_RamdiskCreateFolder:
  1355.         mov     al, 1           ; create folder
  1356.         jmp     fs_RamdiskRewrite.common
  1357.  
  1358. fs_RamdiskRewrite:
  1359.         xor     eax, eax        ; create file
  1360. .common:
  1361.         cmp     byte [esi], 0
  1362.         jz      @b
  1363.         pushad
  1364.         xor     edi, edi
  1365.         push    esi
  1366.         test    ebp, ebp
  1367.         jz      @f
  1368.         mov     esi, ebp
  1369. @@:
  1370.         lodsb
  1371.         test    al, al
  1372.         jz      @f
  1373.         cmp     al, '/'
  1374.         jnz     @b
  1375.         lea     edi, [esi-1]
  1376.         jmp     @b
  1377. @@:
  1378.         pop     esi
  1379.         test    edi, edi
  1380.         jnz     .noroot
  1381.         test    ebp, ebp
  1382.         jnz     .hasebp
  1383.         push    ramdisk_root_extend_dir
  1384.         push    ramdisk_root_next_write
  1385.         push    edi
  1386.         push    ramdisk_root_first
  1387.         push    ramdisk_root_next
  1388.         jmp     .common1
  1389. .hasebp:
  1390.         mov     eax, ERROR_ACCESS_DENIED
  1391.         cmp     byte [ebp], 0
  1392.         jz      .ret1
  1393.         push    ebp
  1394.         xor     ebp, ebp
  1395.         call    rd_find_lfn
  1396.         pop     esi
  1397.         jc      .notfound0
  1398.         jmp     .common0
  1399. .noroot:
  1400.         mov     eax, ERROR_ACCESS_DENIED
  1401.         cmp     byte [edi+1], 0
  1402.         jz      .ret1
  1403. ; check existence
  1404.         mov     byte [edi], 0
  1405.         push    edi
  1406.         call    rd_find_lfn
  1407.         pop     esi
  1408.         mov     byte [esi], '/'
  1409.         jnc     @f
  1410. .notfound0:
  1411.         mov     eax, ERROR_FILE_NOT_FOUND
  1412. .ret1:
  1413.         mov     [esp+28], eax
  1414.         popad
  1415.         xor     ebx, ebx
  1416.         ret
  1417. @@:
  1418.         inc     esi
  1419. .common0:
  1420.         test    byte [edi+11], 0x10     ; must be directory
  1421.         mov     eax, ERROR_ACCESS_DENIED
  1422.         jz      .ret1
  1423.         movzx   ebp, word [edi+26]      ; ebp=cluster
  1424.         mov     eax, ERROR_FAT_TABLE
  1425.         cmp     ebp, 2
  1426.         jb      .ret1
  1427.         cmp     ebp, 2849
  1428.         jae     .ret1
  1429.         push    ramdisk_notroot_extend_dir
  1430.         push    ramdisk_notroot_next_write
  1431.         push    ebp
  1432.         push    ramdisk_notroot_first
  1433.         push    ramdisk_notroot_next
  1434. .common1:
  1435.         call    fat_find_lfn
  1436.         jc      .notfound
  1437. ; found
  1438.         test    byte [edi+11], 10h
  1439.         jz      .exists_file
  1440. ; found directory; if we are creating directory, return OK,
  1441. ;                  if we are creating file, say "access denied"
  1442.         add     esp, 20
  1443.         popad
  1444.         test    al, al
  1445.         mov     eax, ERROR_ACCESS_DENIED
  1446.         jz      @f
  1447.         mov     al, 0
  1448. @@:
  1449.         xor     ebx, ebx
  1450.         ret
  1451. .exists_file:
  1452. ; found file; if we are creating directory, return "access denied",
  1453. ;             if we are creating file, delete existing file and continue
  1454.         cmp     byte [esp+20+28], 0
  1455.         jz      @f
  1456.         add     esp, 20
  1457.         popad
  1458.         mov     eax, ERROR_ACCESS_DENIED
  1459.         xor     ebx, ebx
  1460.         ret
  1461. @@:
  1462. ; delete FAT chain
  1463.         push    edi
  1464.         xor     eax, eax
  1465.         mov     dword [edi+28], eax     ; zero size
  1466.         xchg    ax, word [edi+26]       ; start cluster
  1467.         test    eax, eax
  1468.         jz      .done1
  1469. @@:
  1470.         cmp     eax, 0xFF8
  1471.         jae     .done1
  1472.         lea     edi, [RAMDISK_FAT + eax*2] ; position in FAT
  1473.         xor     eax, eax
  1474.         xchg    ax, [edi]
  1475.         jmp     @b
  1476. .done1:
  1477.         pop     edi
  1478.         call    get_time_for_file
  1479.         mov     [edi+22], ax
  1480.         call    get_date_for_file
  1481.         mov     [edi+24], ax
  1482.         mov     [edi+18], ax
  1483.         or      byte [edi+11], 20h      ; set 'archive' attribute
  1484.         jmp     .doit
  1485. .notfound:
  1486. ; file is not found; generate short name
  1487.         call    fat_name_is_legal
  1488.         jc      @f
  1489.         add     esp, 20
  1490.         popad
  1491.         mov     eax, ERROR_FILE_NOT_FOUND
  1492.         xor     ebx, ebx
  1493.         ret
  1494. @@:
  1495.         sub     esp, 12
  1496.         mov     edi, esp
  1497.         call    fat_gen_short_name
  1498. .test_short_name_loop:
  1499.         push    esi edi ecx
  1500.         mov     esi, edi
  1501.         lea     eax, [esp+12+12+8]
  1502.         mov     [eax], ebp
  1503.         call    dword [eax-4]
  1504.         jc      .found
  1505. .test_short_name_entry:
  1506.         cmp     byte [edi+11], 0xF
  1507.         jz      .test_short_name_cont
  1508.         mov     ecx, 11
  1509.         push    esi edi
  1510.         repz    cmpsb
  1511.         pop     edi esi
  1512.         jz      .short_name_found
  1513. .test_short_name_cont:
  1514.         lea     eax, [esp+12+12+8]
  1515.         call    dword [eax-8]
  1516.         jnc     .test_short_name_entry
  1517.         jmp     .found
  1518. .short_name_found:
  1519.         pop     ecx edi esi
  1520.         call    fat_next_short_name
  1521.         jnc     .test_short_name_loop
  1522. .disk_full:
  1523.         add     esp, 12+20
  1524.         popad
  1525.         mov     eax, ERROR_DISK_FULL
  1526.         xor     ebx, ebx
  1527.         ret
  1528. .found:
  1529.         pop     ecx edi esi
  1530. ; now find space in directory
  1531. ; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
  1532.         mov     al, '~'
  1533.         push    ecx edi
  1534.         mov     ecx, 8
  1535.         repnz   scasb
  1536.         push    1
  1537.         pop     eax     ; 1 entry
  1538.         jnz     .notilde
  1539. ; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
  1540.         xor     eax, eax
  1541. @@:
  1542.         cmp     byte [esi], 0
  1543.         jz      @f
  1544.         inc     esi
  1545.         inc     eax
  1546.         jmp     @b
  1547. @@:
  1548.         sub     esi, eax
  1549.         add     eax, 12+13
  1550.         mov     ecx, 13
  1551.         push    edx
  1552.         cdq
  1553.         div     ecx
  1554.         pop     edx
  1555. .notilde:
  1556.         push    -1
  1557.         push    -1
  1558. ; find <eax> successive entries in directory
  1559.         xor     ecx, ecx
  1560.         push    eax
  1561.         lea     eax, [esp+12+8+12+8]
  1562.         mov     [eax], ebp
  1563.         call    dword [eax-4]
  1564.         pop     eax
  1565. .scan_dir:
  1566.         cmp     byte [edi], 0
  1567.         jz      .free
  1568.         cmp     byte [edi], 0xE5
  1569.         jz      .free
  1570.         xor     ecx, ecx
  1571. .scan_cont:
  1572.         push    eax
  1573.         lea     eax, [esp+12+8+12+8]
  1574.         call    dword [eax-8]
  1575.         pop     eax
  1576.         jnc     .scan_dir
  1577.         push    eax
  1578.         lea     eax, [esp+12+8+12+8]
  1579.         call    dword [eax+8]           ; extend directory
  1580.         pop     eax
  1581.         jnc     .scan_dir
  1582.         add     esp, 8+8+12+20
  1583.         popad
  1584.         mov     eax, ERROR_DISK_FULL
  1585.         xor     ebx, ebx
  1586.         ret
  1587. .free:
  1588.         test    ecx, ecx
  1589.         jnz     @f
  1590.         mov     [esp], edi
  1591.         mov     ecx, [esp+8+8+12+8]
  1592.         mov     [esp+4], ecx
  1593.         xor     ecx, ecx
  1594. @@:
  1595.         inc     ecx
  1596.         cmp     ecx, eax
  1597.         jb      .scan_cont
  1598. ; found!
  1599. ; calculate name checksum
  1600.         push    esi ecx
  1601.         mov     esi, [esp+8+8]
  1602.         mov     ecx, 11
  1603.         xor     eax, eax
  1604. @@:
  1605.         ror     al, 1
  1606.         add     al, [esi]
  1607.         inc     esi
  1608.         loop    @b
  1609.         pop     ecx esi
  1610.         pop     edi
  1611.         pop     dword [esp+8+12+8]
  1612. ; edi points to last entry in free chunk
  1613.         dec     ecx
  1614.         jz      .nolfn
  1615.         push    esi
  1616.         push    eax
  1617.         mov     al, 40h
  1618. .writelfn:
  1619.         or      al, cl
  1620.         mov     esi, [esp+4]
  1621.         push    ecx
  1622.         dec     ecx
  1623.         imul    ecx, 13
  1624.         add     esi, ecx
  1625.         stosb
  1626.         mov     cl, 5
  1627.         call    .read_symbols
  1628.         mov     ax, 0xF
  1629.         stosw
  1630.         mov     al, [esp+4]
  1631.         stosb
  1632.         mov     cl, 6
  1633.         call    .read_symbols
  1634.         xor     eax, eax
  1635.         stosw
  1636.         mov     cl, 2
  1637.         call    .read_symbols
  1638.         pop     ecx
  1639.         lea     eax, [esp+8+8+12+8]
  1640.         call    dword [eax+4]   ; next write
  1641.         xor     eax, eax
  1642.         loop    .writelfn
  1643.         pop     eax
  1644.         pop     esi
  1645. .nolfn:
  1646.         xchg    esi, [esp]
  1647.         mov     ecx, 11
  1648.         rep     movsb
  1649.         mov     word [edi], 20h         ; attributes
  1650.         sub     edi, 11
  1651.         pop     esi ecx
  1652.         add     esp, 12
  1653.         mov     byte [edi+13], 0        ; tenths of a second at file creation time
  1654.         call    get_time_for_file
  1655.         mov     [edi+14], ax            ; creation time
  1656.         mov     [edi+22], ax            ; last write time
  1657.         call    get_date_for_file
  1658.         mov     [edi+16], ax            ; creation date
  1659.         mov     [edi+24], ax            ; last write date
  1660.         mov     [edi+18], ax            ; last access date
  1661.         and     word [edi+20], 0        ; high word of cluster
  1662.         and     word [edi+26], 0        ; low word of cluster - to be filled
  1663.         and     dword [edi+28], 0       ; file size - to be filled
  1664.         cmp     byte [esp+20+28], 0
  1665.         jz      .doit
  1666. ; create directory
  1667.         mov     byte [edi+11], 10h         ; attributes: folder
  1668.         mov     ecx, 32*2
  1669.         mov     edx, edi
  1670. .doit:
  1671.         push    edx
  1672.         push    ecx
  1673.         push    edi
  1674.         add     edi, 26         ; edi points to low word of cluster
  1675.         push    edi
  1676.         jecxz   .done
  1677.         mov     ecx, 2849
  1678.         mov     edi, RAMDISK_FAT
  1679. .write_loop:
  1680. ; allocate new cluster
  1681.         xor     eax, eax
  1682.         repnz   scasw
  1683.         jnz     .disk_full2
  1684.         dec     edi
  1685.         dec     edi
  1686.  
  1687.     ;    lea     eax, [edi-(RAMDISK_FAT)]
  1688.  
  1689.         mov eax, edi
  1690.         sub eax, RAMDISK_FAT
  1691.  
  1692.         shr     eax, 1                  ; eax = cluster
  1693.         mov     word [edi], 0xFFF       ; mark as last cluster
  1694.         xchg    edi, [esp]
  1695.         stosw
  1696.         pop     edi
  1697.         push    edi
  1698.         inc     ecx
  1699. ; write data
  1700.         cmp     byte [esp+16+20+28], 0
  1701.         jnz     .writedir
  1702.         shl     eax, 9
  1703.         add     eax, 31*512
  1704.         add     eax, [_rd_base]
  1705. .writefile:
  1706.         mov     ebx, edx
  1707.         xchg    eax, ebx
  1708.         push    ecx
  1709.         mov     ecx, 512
  1710.         cmp     dword [esp+12], ecx
  1711.         jae     @f
  1712.         mov     ecx, [esp+12]
  1713. @@:
  1714.         call    memmove
  1715.         add     edx, ecx
  1716.         sub     [esp+12], ecx
  1717.         pop     ecx
  1718.         jnz     .write_loop
  1719. .done:
  1720.         mov     ebx, edx
  1721.         pop     edi edi ecx edx
  1722.         sub     ebx, edx
  1723.         mov     [edi+28], ebx
  1724.         add     esp, 20
  1725.         mov     [esp+16], ebx
  1726.         popad
  1727.         xor     eax, eax
  1728.         ret
  1729. .disk_full2:
  1730.         mov     ebx, edx
  1731.         pop     edi edi ecx edx
  1732.         sub     ebx, edx
  1733.         mov     [edi+28], ebx
  1734.         add     esp, 20
  1735.         mov     [esp+16], ebx
  1736.         popad
  1737.         push    ERROR_DISK_FULL
  1738.         pop     eax
  1739.         ret
  1740. .writedir:
  1741.         mov     edi, eax
  1742.         shl     edi, 9
  1743.         add     edi, [_rd_base]
  1744.         add     edi, 31*512
  1745.         mov     esi, edx
  1746.         mov     ecx, 32/4
  1747.         push    ecx
  1748.         rep     movsd
  1749.         mov     dword [edi-32], '.   '
  1750.         mov     dword [edi-32+4], '    '
  1751.         mov     dword [edi-32+8], '    '
  1752.         mov     byte [edi-32+11], 10h
  1753.         mov     word [edi-32+26], ax
  1754.         mov     esi, edx
  1755.         pop     ecx
  1756.         rep     movsd
  1757.         mov     dword [edi-32], '..  '
  1758.         mov     dword [edi-32+4], '    '
  1759.         mov     dword [edi-32+8], '    '
  1760.         mov     byte [edi-32+11], 10h
  1761.         mov     eax, [esp+16+8]
  1762.         mov     word [edi-32+26], ax
  1763.         xor     eax, eax
  1764.         mov     ecx, (512-32*2)/4
  1765.         rep     stosd
  1766.         pop     edi edi ecx edx
  1767.         add     esp, 20
  1768.         popad
  1769.         xor     eax, eax
  1770.         xor     ebx, ebx
  1771.         ret
  1772.  
  1773. .read_symbol:
  1774.         or      ax, -1
  1775.         test    esi, esi
  1776.         jz      .retFFFF
  1777.         lodsb
  1778.         test    al, al
  1779.         jnz     ansi2uni_char
  1780.         xor     eax, eax
  1781.         xor     esi, esi
  1782. .retFFFF:
  1783.         ret
  1784.  
  1785. .read_symbols:
  1786.         call    .read_symbol
  1787.         stosw
  1788.         loop    .read_symbols
  1789.         ret
  1790.  
  1791. ;----------------------------------------------------------------
  1792. ;
  1793. ;  fs_RamdiskWrite - LFN variant for writing to sys floppy
  1794. ;
  1795. ;  esi  points to filename
  1796. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  1797. ;       may be ebx=0 - start from first byte
  1798. ;  ecx  number of bytes to write, 0+
  1799. ;  edx  mem location to data
  1800. ;
  1801. ;  ret ebx = bytes written (maybe 0)
  1802. ;      eax = 0 ok write or other = errormsg
  1803. ;
  1804. ;--------------------------------------------------------------
  1805. @@:
  1806.         push    ERROR_ACCESS_DENIED
  1807. fs_RamdiskWrite.ret0:
  1808.         pop     eax
  1809.         xor     ebx, ebx
  1810.         ret
  1811.  
  1812. fs_RamdiskWrite:
  1813.         cmp     byte [esi], 0
  1814.         jz      @b
  1815.         pushad
  1816.         call    rd_find_lfn
  1817.         jnc     .found
  1818.         popad
  1819.         push    ERROR_FILE_NOT_FOUND
  1820.         jmp     .ret0
  1821. .found:
  1822. ; must not be directory
  1823.         test    byte [edi+11], 10h
  1824.         jz      @f
  1825.         popad
  1826.         push    ERROR_ACCESS_DENIED
  1827.         jmp     .ret0
  1828. @@:
  1829. ; FAT does not support files larger than 4GB
  1830.         test    ebx, ebx
  1831.         jz      .l1
  1832.         cmp     dword [ebx+4], 0
  1833.         jz      @f
  1834. .eof:
  1835.         popad
  1836.         push    ERROR_END_OF_FILE
  1837.         jmp     .ret0
  1838. @@:
  1839.         mov     ebx, [ebx]
  1840. .l1:
  1841. ; now edi points to direntry, ebx=start byte to write,
  1842. ; ecx=number of bytes to write, edx=data pointer
  1843.         call    fat_update_datetime
  1844.  
  1845. ; extend file if needed
  1846.         add     ecx, ebx
  1847.         jc      .eof    ; FAT does not support files larger than 4GB
  1848.         push    0       ; return value=0
  1849.         cmp     ecx, [edi+28]
  1850.         jbe     .length_ok
  1851.         cmp     ecx, ebx
  1852.         jz      .length_ok
  1853.         call    ramdisk_extend_file
  1854.         jnc     .length_ok
  1855. ; ramdisk_extend_file can return two error codes: FAT table error or disk full.
  1856. ; First case is fatal error, in second case we may write some data
  1857.         mov     [esp], eax
  1858.         cmp     al, ERROR_DISK_FULL
  1859.         jz      .disk_full
  1860.         pop     eax
  1861.         mov     [esp+28], eax
  1862.         popad
  1863.         xor     ebx, ebx
  1864.         ret
  1865. .disk_full:
  1866. ; correct number of bytes to write
  1867.         mov     ecx, [edi+28]
  1868.         cmp     ecx, ebx
  1869.         ja      .length_ok
  1870. .ret:
  1871.         pop     eax
  1872.         mov     [esp+28], eax   ; eax=return value
  1873.         sub     edx, [esp+20]
  1874.         mov     [esp+16], edx   ; ebx=number of written bytes
  1875.         popad
  1876.         ret
  1877. .length_ok:
  1878. ; now ebx=start pos, ecx=end pos, both lie inside file
  1879.         sub     ecx, ebx
  1880.         jz      .ret
  1881.         movzx   edi, word [edi+26]      ; starting cluster
  1882. .write_loop:
  1883.         sub     ebx, 0x200
  1884.         jae     .next_cluster
  1885.         push    ecx
  1886.         neg     ebx
  1887.         cmp     ecx, ebx
  1888.         jbe     @f
  1889.         mov     ecx, ebx
  1890. @@:
  1891.         mov     eax, edi
  1892.         shl     eax, 9
  1893.         add     eax, [_rd_base]
  1894.         add     eax, 31*512+0x200
  1895.         sub     eax, ebx
  1896.         mov     ebx, eax
  1897.         mov     eax, edx
  1898.         call    memmove
  1899.         xor     ebx, ebx
  1900.         add     edx, ecx
  1901.         sub     [esp], ecx
  1902.         pop     ecx
  1903.         jz      .ret
  1904. .next_cluster:
  1905.         movzx   edi, word [edi*2+RAMDISK_FAT]
  1906.         jmp     .write_loop
  1907.  
  1908. ramdisk_extend_file.zero_size:
  1909.         xor     eax, eax
  1910.         jmp     ramdisk_extend_file.start_extend
  1911.  
  1912. ; extends file on ramdisk to given size, new data area is filled by 0
  1913. ; in: edi->direntry, ecx=new size
  1914. ; out: CF=0 => OK, eax=0
  1915. ;      CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL)
  1916. ramdisk_extend_file:
  1917.         push    ecx
  1918. ; find the last cluster of file
  1919.         movzx   eax, word [edi+26]      ; first cluster
  1920.         mov     ecx, [edi+28]
  1921.         jecxz   .zero_size
  1922. @@:
  1923.         sub     ecx, 0x200
  1924.         jbe     @f
  1925.         mov     eax, [eax*2+RAMDISK_FAT]
  1926.         and     eax, 0xFFF
  1927.         jz      .fat_err
  1928.         cmp     eax, 0xFF8
  1929.         jb      @b
  1930. .fat_err:
  1931.         pop     ecx
  1932.         push    ERROR_FAT_TABLE
  1933.         pop     eax
  1934.         stc
  1935.         ret
  1936. @@:
  1937.         push    eax
  1938.         mov     eax, [eax*2+RAMDISK_FAT]
  1939.         and     eax, 0xFFF
  1940.         cmp     eax, 0xFF8
  1941.         pop     eax
  1942.         jb      .fat_err
  1943. ; set length to full number of sectors and make sure that last sector is zero-padded
  1944.         sub     [edi+28], ecx
  1945.         push    eax edi
  1946.         mov     edi, eax
  1947.         shl     edi, 9
  1948.         add edi, [_rd_base]
  1949.         lea     edi, [edi+31*512+0x200+ecx]
  1950.         neg     ecx
  1951.         xor     eax, eax
  1952.         rep     stosb
  1953.         pop     edi eax
  1954. .start_extend:
  1955.         pop     ecx
  1956. ; now do extend
  1957.         push    edx esi
  1958.         mov     esi, RAMDISK_FAT+2*2       ; start scan from cluster 2
  1959.         mov     edx, 2847               ; number of clusters to scan
  1960. .extend_loop:
  1961.         cmp     [edi+28], ecx
  1962.         jae     .extend_done
  1963. ; add new sector
  1964.         push    ecx
  1965.         mov     ecx, edx
  1966.         push    edi
  1967.         mov     edi, esi
  1968.         jecxz   .disk_full
  1969.         push    eax
  1970.         xor     eax, eax
  1971.         repnz   scasw
  1972.         pop     eax
  1973.         jnz     .disk_full
  1974.         mov     word [edi-2], 0xFFF
  1975.         mov     esi, edi
  1976.         mov     edx, ecx
  1977.         sub     edi, RAMDISK_FAT
  1978.         shr     edi, 1
  1979.         dec     edi     ; now edi=new cluster
  1980.         test    eax, eax
  1981.         jz      .first_cluster
  1982.         mov     [RAMDISK_FAT+eax*2], di
  1983.         jmp     @f
  1984. .first_cluster:
  1985.         pop     eax     ; eax->direntry
  1986.         push    eax
  1987.         mov     [eax+26], di
  1988. @@:
  1989.         push    edi
  1990.         shl     edi, 9
  1991.         add edi, [_rd_base]
  1992.         add     edi, 31*512
  1993.         xor     eax, eax
  1994.         mov     ecx, 512/4
  1995.         rep     stosd
  1996.         pop     eax     ; eax=new cluster
  1997.         pop     edi     ; edi->direntry
  1998.         pop     ecx     ; ecx=required size
  1999.         add     dword [edi+28], 0x200
  2000.         jmp     .extend_loop
  2001. .extend_done:
  2002.         mov     [edi+28], ecx
  2003.         pop     esi edx
  2004.         xor     eax, eax        ; CF=0
  2005.         ret
  2006. .disk_full:
  2007.         pop     edi ecx
  2008.         pop     esi edx
  2009.         stc
  2010.         push    ERROR_DISK_FULL
  2011.         pop     eax
  2012.         ret
  2013.  
  2014. fat_update_datetime:
  2015.         call    get_time_for_file
  2016.         mov     [edi+22], ax            ; last write time
  2017.         call    get_date_for_file
  2018.         mov     [edi+24], ax            ; last write date
  2019.         mov     [edi+18], ax            ; last access date
  2020.         ret
  2021.  
  2022. ;----------------------------------------------------------------
  2023. ;
  2024. ;  fs_RamdiskSetFileEnd - set end of file on ramdisk
  2025. ;
  2026. ;  esi  points to filename
  2027. ;  ebx  points to 64-bit number = new file size
  2028. ;  ecx  ignored (reserved)
  2029. ;  edx  ignored (reserved)
  2030. ;
  2031. ;  ret eax = 0 ok or other = errormsg
  2032. ;
  2033. ;--------------------------------------------------------------
  2034. fs_RamdiskSetFileEnd:
  2035.         cmp     byte [esi], 0
  2036.         jnz     @f
  2037. .access_denied:
  2038.         push    ERROR_ACCESS_DENIED
  2039.         jmp     .ret
  2040. @@:
  2041.         push    edi
  2042.         call    rd_find_lfn
  2043.         jnc     @f
  2044.         pop     edi
  2045.         push    ERROR_FILE_NOT_FOUND
  2046. .ret:
  2047.         pop     eax
  2048.         ret
  2049. @@:
  2050. ; must not be directory
  2051.         test    byte [edi+11], 10h
  2052.         jz      @f
  2053.         pop     edi
  2054.         jmp     .access_denied
  2055. @@:
  2056. ; file size must not exceed 4Gb
  2057.         cmp     dword [ebx+4], 0
  2058.         jz      @f
  2059.         pop     edi
  2060.         push    ERROR_END_OF_FILE
  2061.         jmp     .ret
  2062. @@:
  2063. ; set file modification date/time to current
  2064.         call    fat_update_datetime
  2065.         mov     eax, [ebx]
  2066.         cmp     eax, [edi+28]
  2067.         jb      .truncate
  2068.         ja      .expand
  2069.         pop     edi
  2070.         xor     eax, eax
  2071.         ret
  2072. .expand:
  2073.         push    ecx
  2074.         mov     ecx, eax
  2075.         call    ramdisk_extend_file
  2076.         pop     ecx
  2077.         pop     edi
  2078.         ret
  2079. .truncate:
  2080.         mov     [edi+28], eax
  2081.         push    ecx
  2082.         movzx   ecx, word [edi+26]
  2083.         test    eax, eax
  2084.         jz      .zero_size
  2085. ; find new last sector
  2086. @@:
  2087.         sub     eax, 0x200
  2088.         jbe     @f
  2089.         movzx   ecx, word [RAMDISK_FAT+ecx*2]
  2090.         jmp     @b
  2091. @@:
  2092. ; zero data at the end of last sector
  2093.         push    ecx
  2094.         mov     edi, ecx
  2095.         shl     edi, 9
  2096.         add edi, [_rd_base]
  2097.         lea     edi, [edi+31*512+eax+0x200]
  2098.         mov     ecx, eax
  2099.         neg     ecx
  2100.         xor     eax, eax
  2101.         rep     stosb
  2102.         pop     ecx
  2103. ; terminate FAT chain
  2104.         lea     ecx, [RAMDISK_FAT+ecx+ecx]
  2105.         push    dword [ecx]
  2106.         mov     word [ecx], 0xFFF
  2107.         pop     ecx
  2108.         and     ecx, 0xFFF
  2109.         jmp     .delete
  2110. .zero_size:
  2111.         and     word [edi+26], 0
  2112. .delete:
  2113. ; delete FAT chain starting with ecx
  2114. ; mark all clusters as free
  2115.         cmp     ecx, 0xFF8
  2116.         jae     .deleted
  2117.         lea     ecx, [RAMDISK_FAT+ecx+ecx]
  2118.         push    dword [ecx]
  2119.         and     word [ecx], 0
  2120.         pop     ecx
  2121.         and     ecx, 0xFFF
  2122.         jmp     .delete
  2123. .deleted:
  2124.         pop     ecx
  2125.         pop     edi
  2126.         xor     eax, eax
  2127.         ret
  2128.  
  2129. fs_RamdiskGetFileInfo:
  2130.         cmp     byte [esi], 0
  2131.         jnz     @f
  2132.         mov     eax, 2  ; unsupported
  2133.         ret
  2134. @@:
  2135.         push    edi
  2136.         call    rd_find_lfn
  2137. fs_GetFileInfo_finish:
  2138.         jnc     @f
  2139.         pop     edi
  2140.         mov     eax, ERROR_FILE_NOT_FOUND
  2141.         ret
  2142. @@:
  2143.         push    esi ebp
  2144.         xor     ebp, ebp
  2145.         mov     esi, edx
  2146.         and     dword [esi+4], 0
  2147.         call    fat_entry_to_bdfe2
  2148.         pop     ebp esi
  2149.         pop     edi
  2150.         xor     eax, eax
  2151.         ret
  2152.  
  2153. fs_RamdiskSetFileInfo:
  2154.         cmp     byte [esi], 0
  2155.         jnz     @f
  2156.         mov     eax, 2  ; unsupported
  2157.         ret
  2158. @@:
  2159.         push    edi
  2160.         call    rd_find_lfn
  2161.         jnc     @f
  2162.         pop     edi
  2163.         mov     eax, ERROR_FILE_NOT_FOUND
  2164.         ret
  2165. @@:
  2166.         call    bdfe_to_fat_entry
  2167.         pop     edi
  2168.         xor     eax, eax
  2169.         ret
  2170.  
  2171. ;----------------------------------------------------------------
  2172. ;
  2173. ;  fs_RamdiskDelete - delete file or empty folder from ramdisk
  2174. ;
  2175. ;  esi  points to filename
  2176. ;
  2177. ;  ret  eax = 0 ok or other = errormsg
  2178. ;
  2179. ;--------------------------------------------------------------
  2180. fs_RamdiskDelete:
  2181.         cmp     byte [esi], 0
  2182.         jnz     @f
  2183. ; cannot delete root!
  2184. .access_denied:
  2185.         push    ERROR_ACCESS_DENIED
  2186. .pop_ret:
  2187.         pop     eax
  2188.         ret
  2189. @@:
  2190.         and     [rd_prev_sector], 0
  2191.         and     [rd_prev_prev_sector], 0
  2192.         push    edi
  2193.         call    rd_find_lfn
  2194.         jnc     .found
  2195.         pop     edi
  2196.         push    ERROR_FILE_NOT_FOUND
  2197.         jmp     .pop_ret
  2198. .found:
  2199.         cmp     dword [edi], '.   '
  2200.         jz      .access_denied2
  2201.         cmp     dword [edi], '..  '
  2202.         jz      .access_denied2
  2203.         test    byte [edi+11], 10h
  2204.         jz      .dodel
  2205. ; we can delete only empty folders!
  2206.         movzx   eax, word [edi+26]
  2207.         push    ebx
  2208.         mov     ebx, eax
  2209.         shl     ebx, 9
  2210.         add ebx, [_rd_base]
  2211.         add     ebx, 31*0x200 + 2*0x20
  2212. .checkempty:
  2213.         cmp     byte [ebx], 0
  2214.         jz      .empty
  2215.         cmp     byte [ebx], 0xE5
  2216.         jnz     .notempty
  2217.         add     ebx, 0x20
  2218.         test    ebx, 0x1FF
  2219.         jnz     .checkempty
  2220.         movzx   eax, word [RAMDISK_FAT + eax*2]
  2221.         test    eax, eax
  2222.         jz      .empty
  2223.         mov     ebx, eax
  2224.         shl     ebx, 9
  2225.         add ebx, [_rd_base]
  2226.         add     ebx, 31*0x200
  2227.         jmp     .checkempty
  2228. .notempty:
  2229.         pop     ebx
  2230. .access_denied2:
  2231.         pop     edi
  2232.         jmp     .access_denied
  2233. .empty:
  2234.         pop     ebx
  2235. .dodel:
  2236.         movzx   eax, word [edi+26]
  2237. ; delete folder entry
  2238.         mov     byte [edi], 0xE5
  2239. ; delete LFN (if present)
  2240. .lfndel:
  2241.         test    edi, 0x1FF
  2242.         jnz     @f
  2243.         cmp     [rd_prev_sector], 0
  2244.         jz      @f
  2245.         cmp     [rd_prev_sector], -1
  2246.         jz      .lfndone
  2247.         mov     edi, [rd_prev_sector]
  2248.         push    [rd_prev_prev_sector]
  2249.         pop     [rd_prev_sector]
  2250.         or      [rd_prev_prev_sector], -1
  2251.         shl     edi, 9
  2252.         add edi, [_rd_base]
  2253.         add     edi, 31*0x200 + 0x200
  2254. @@:
  2255.         sub     edi, 0x20
  2256.         cmp     byte [edi], 0xE5
  2257.         jz      .lfndone
  2258.         cmp     byte [edi+11], 0xF
  2259.         jnz     .lfndone
  2260.         mov     byte [edi], 0xE5
  2261.         jmp     .lfndel
  2262. .lfndone:
  2263. ; delete FAT chain
  2264.         test    eax, eax
  2265.         jz      .done
  2266.         lea     eax, [RAMDISK_FAT + eax*2]
  2267.         push    dword [eax]
  2268.         and     word [eax], 0
  2269.         pop     eax
  2270.         and     eax, 0xFFF
  2271.         jmp     .lfndone
  2272. .done:
  2273.         pop     edi
  2274.         xor     eax, eax
  2275.         ret
  2276.  
  2277. ; \end{diamond}
  2278.