Subversion Repositories Kolibri OS

Rev

Rev 133 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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