Subversion Repositories Kolibri OS

Rev

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

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