Subversion Repositories Kolibri OS

Rev

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

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