Subversion Repositories Kolibri OS

Rev

Rev 83 | Rev 88 | Go to most recent revision | Blame | Compare with Previous | 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,0x100000+512
  16.    mov  edi,0x280000
  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,0x280000+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,0x280000
  53.    mov  edi,0x100000+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,0x100000+512+4278     ;4274 bytes - all used FAT
  70.    jb   fcnew2
  71.  
  72.    mov  esi,0x100000+512           ; duplicate fat chain
  73.    mov  edi,0x100000+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,0x280000 ;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,0x100000+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,0x100000             ;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+0x280000]        ; 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,0x280000
  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,0x100000+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,0x280000            ;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,0x100000
  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,0x100000+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,0x100000+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.   rd_getfileinfo:
  479.      ;get date, time, size or attributes of file
  480.      ;IN: eax - pointer to file, ebx - type of function: 12-get filesize, 13-get fileattr, 14-get filedate
  481.      ;ecx - filelengh 0=root
  482.      ;OUT: eax=0 - Ok or 5 - file not found ebx - date/time, size or attributes
  483.         test   ecx,ecx
  484.         jnz    no_getfinfo_root
  485.         mov    eax,5      ;if root - fnf
  486.         xor    ebx,ebx
  487.         dec    ebx
  488.         ret
  489.     no_getfinfo_root:     ;if not root
  490.         sub    esp,32
  491.         call   expand_filename
  492.         call   rd_findfile
  493.         je     fifoundi
  494.         add    esp,32      ;if file not found
  495.         ret
  496.     fifoundi:    
  497.         cmp    ebx,13
  498.         jne    no_rd_attr
  499.         movzx ebx,byte [edi]    ;get attributes
  500.         jmp    rd_getfileinfo_end
  501.      no_rd_attr:
  502.         cmp    ebx,14
  503.         jne    no_rd_date
  504.         mov    ebx,dword [edi+11] ;get date/time
  505.         jmp    rd_getfileinfo_end
  506.      no_rd_date:
  507.         mov    ebx,dword [edi+17] ;get size
  508.      rd_getfileinfo_end:
  509.         xor    eax,eax
  510.         add    esp,32
  511.         ret
  512.  
  513. ; \begin{diamond}
  514.  
  515. uni2ansi_str:
  516. ; convert UNICODE zero-terminated string to ASCII-string (codepage 866)
  517. ; in: esi->source, edi->buffer (may be esi=edi)
  518. ; destroys: eax,esi,edi
  519.         lodsw
  520.         test    ax, ax
  521.         jz      .done
  522.         cmp     ax, 0x80
  523.         jb      .ascii
  524.         cmp     ax, 0x401
  525.         jz      .yo1
  526.         cmp     ax, 0x451
  527.         jz      .yo2
  528.         cmp     ax, 0x410
  529.         jb      .unk
  530.         cmp     ax, 0x440
  531.         jb      .rus1
  532.         cmp     ax, 0x450
  533.         jb      .rus2
  534. .unk:
  535.         mov     al, '_'
  536.         jmp     .doit
  537. .yo1:
  538.         mov     al, 'ð'
  539.         jmp     .doit
  540. .yo2:
  541.         mov     al, 'ñ'
  542.         jmp     .doit
  543. .rus1:
  544. ; 0x410-0x43F -> 0x80-0xAF
  545.         add     al, 0x70
  546.         jmp     .doit
  547. .rus2:
  548. ; 0x440-0x44F -> 0xE0-0xEF
  549.         add     al, 0xA0
  550. .ascii:
  551. .doit:
  552.         stosb
  553.         jmp     uni2ansi_str
  554. .done:
  555.         mov     byte [edi], 0
  556.         ret
  557.  
  558. ansi2uni_char:
  559. ; convert ANSI character in al to UNICODE character in ax, using cp866 encoding
  560.         mov     ah, 0
  561. ; 0x00-0x7F - trivial map
  562.         cmp     al, 0x80
  563.         jb      .ret
  564. ; 0x80-0xAF -> 0x410-0x43F
  565.         cmp     al, 0xB0
  566.         jae     @f
  567.         add     ax, 0x410-0x80
  568. .ret:
  569.         ret
  570. @@:
  571. ; 0xE0-0xEF -> 0x440-0x44F
  572.         cmp     al, 0xE0
  573.         jb      .unk
  574.         cmp     al, 0xF0
  575.         jae     @f
  576.         add     ax, 0x440-0xE0
  577.         ret
  578. ; 0xF0 -> 0x401
  579. ; 0xF1 -> 0x451
  580. @@:
  581.         cmp     al, 'ð'
  582.         jz      .yo1
  583.         cmp     al, 'ñ'
  584.         jz      .yo2
  585. .unk:
  586.         mov     al, '_'         ; ah=0
  587.         ret
  588. .yo1:
  589.         mov     ax, 0x401
  590.         ret
  591. .yo2:
  592.         mov     ax, 0x451
  593.         ret
  594.  
  595. char_toupper:
  596. ; convert character to uppercase, using cp866 encoding
  597. ; in: al=symbol
  598. ; out: al=converted symbol
  599.         cmp     al, 'a'
  600.         jb      .ret
  601.         cmp     al, 'z'
  602.         jbe     .az
  603.         cmp     al, ' '
  604.         jb      .ret
  605.         cmp     al, 'à'
  606.         jb      .rus1
  607.         cmp     al, 'ï'
  608.         ja      .ret
  609. ; 0xE0-0xEF -> 0x90-0x9F
  610.         sub     al, 'à'-''
  611. .ret:
  612.         ret
  613. .rus1:
  614. ; 0xA0-0xAF -> 0x80-0x8F
  615. .az:
  616.         and     al, not 0x20
  617.         ret
  618.  
  619. fat_get_name:
  620. ; in: edi->FAT entry
  621. ; out: CF=1 - no valid entry
  622. ; else CF=0 and ebp->ASCIIZ-name
  623. ; (maximum length of filename is 255 (wide) symbols without trailing 0,
  624. ;  but implementation requires buffer 261 words)
  625. ; destroys eax
  626.         cmp     byte [edi], 0
  627.         jz      .no
  628.         cmp     byte [edi], 0xE5
  629.         jnz     @f
  630. .no:
  631.         stc
  632.         ret
  633. @@:
  634.         cmp     byte [edi+11], 0xF
  635.         jz      .longname
  636.         push    ecx
  637.         mov     ecx, 8
  638.         push    edi ebp ecx
  639.         test    byte [ebp-4], 1
  640.         jnz     .unicode_short
  641. @@:
  642.         mov     al, [edi]
  643.         inc     edi
  644.         mov     [ebp], al
  645.         inc     ebp
  646.         loop    @b
  647.         pop     ecx
  648. @@:
  649.         cmp     byte [ebp-1], ' '
  650.         jnz     @f
  651.         dec     ebp
  652.         loop    @b
  653. @@:
  654.         mov     byte [ebp], '.'
  655.         inc     ebp
  656.         mov     ecx, 3
  657.         push    ecx
  658. @@:
  659.         mov     al, [edi]
  660.         inc     edi
  661.         mov     [ebp], al
  662.         inc     ebp
  663.         loop    @b
  664.         pop     ecx
  665. @@:
  666.         cmp     byte [ebp-1], ' '
  667.         jnz     @f
  668.         dec     ebp
  669.         loop    @b
  670.         dec     ebp
  671. @@:
  672.         and     byte [ebp], 0   ; CF=0
  673.         pop     ebp edi ecx
  674.         ret
  675. .unicode_short:
  676. @@:
  677.         mov     al, [edi]
  678.         inc     edi
  679.         call    ansi2uni_char
  680.         mov     [ebp], ax
  681.         inc     ebp
  682.         inc     ebp
  683.         loop    @b
  684.         pop     ecx
  685. @@:
  686.         cmp     word [ebp-2], ' '
  687.         jnz     @f
  688.         dec     ebp
  689.         dec     ebp
  690.         loop    @b
  691. @@:
  692.         mov     word [ebp], '.'
  693.         inc     ebp
  694.         inc     ebp
  695.         mov     ecx, 3
  696.         push    ecx
  697. @@:
  698.         mov     al, [edi]
  699.         inc     edi
  700.         call    ansi2uni_char
  701.         mov     [ebp], ax
  702.         inc     ebp
  703.         inc     ebp
  704.         loop    @b
  705.         pop     ecx
  706. @@:
  707.         cmp     word [ebp-2], ' '
  708.         jnz     @f
  709.         dec     ebp
  710.         dec     ebp
  711.         loop    @b
  712.         dec     ebp
  713.         dec     ebp
  714. @@:
  715.         and     word [ebp], 0   ; CF=0
  716.         pop     ebp edi ecx
  717.         ret
  718. .longname:
  719. ; LFN
  720.         mov     al, byte [edi]
  721.         and     eax, 0x3F
  722.         dec     eax
  723.         cmp     al, 20
  724.         jae     .no     ; ignore invalid entries
  725.         mov     word [ebp+260*2], 0     ; force null-terminating for orphans
  726.         imul    eax, 13*2
  727.         add     ebp, eax
  728.         test    byte [edi], 0x40
  729.         jz      @f
  730.         mov     word [ebp+13*2], 0
  731. @@:
  732.         push    eax
  733. ; now copy name from edi to ebp ...
  734.         mov     eax, [edi+1]
  735.         mov     [ebp], eax      ; symbols 1,2
  736.         mov     eax, [edi+5]
  737.         mov     [ebp+4], eax    ; 3,4
  738.         mov     eax, [edi+9]
  739.         mov     [ebp+8], ax     ; 5
  740.         mov     eax, [edi+14]
  741.         mov     [ebp+10], eax   ; 6,7
  742.         mov     eax, [edi+18]
  743.         mov     [ebp+14], eax   ; 8,9
  744.         mov     eax, [edi+22]
  745.         mov     [ebp+18], eax   ; 10,11
  746.         mov     eax, [edi+28]
  747.         mov     [ebp+22], eax   ; 12,13
  748. ; ... done
  749.         pop     eax
  750.         sub     ebp, eax
  751.         test    eax, eax
  752.         jz      @f
  753. ; if this is not first entry, more processing required
  754.         stc
  755.         ret
  756. @@:
  757. ; if this is first entry:
  758.         test    byte [ebp-4], 1
  759.         jnz     .ret
  760. ; buffer at ebp contains UNICODE name, convert it to ANSI
  761.         push    esi edi
  762.         mov     esi, ebp
  763.         mov     edi, ebp
  764.         call    uni2ansi_str
  765.         pop     edi esi
  766. .ret:
  767.         clc
  768.         ret
  769.  
  770. fat_compare_name:
  771. ; compares ASCIIZ-names, case-insensitive (cp866 encoding)
  772. ; in: esi->name, ebp->name
  773. ; out: if names match: ZF=1 and esi->next component of name
  774. ;      else: ZF=0, esi is not changed
  775. ; destroys eax
  776.         push    ebp esi
  777. .loop:
  778.         mov     al, [ebp]
  779.         inc     ebp
  780.         call    char_toupper
  781.         push    eax
  782.         lodsb
  783.         call    char_toupper
  784.         cmp     al, [esp]
  785.         jnz     .done
  786.         pop     eax
  787.         test    al, al
  788.         jnz     .loop
  789.         dec     esi
  790.         pop     eax
  791.         pop     ebp
  792.         xor     eax, eax        ; set ZF flag
  793.         ret
  794. .done:
  795.         cmp     al, '/'
  796.         jnz     @f
  797.         cmp     byte [esp], 0
  798.         jnz     @f
  799.         mov     [esp+4], esi
  800. @@:
  801.         pop     eax
  802.         pop     esi ebp
  803.         ret
  804.  
  805. fat_time_to_bdfe:
  806. ; in: eax=FAT time
  807. ; out: eax=BDFE time
  808.         push    ecx edx
  809.         mov     ecx, eax
  810.         mov     edx, eax
  811.         shr     eax, 11
  812.         shl     eax, 16 ; hours
  813.         and     edx, 0x1F
  814.         add     edx, edx
  815.         mov     al, dl  ; seconds
  816.         shr     ecx, 5
  817.         and     ecx, 0x3F
  818.         mov     ah, cl  ; minutes
  819.         pop     edx ecx
  820.         ret
  821.  
  822. fat_date_to_bdfe:
  823.         push    ecx edx
  824.         mov     ecx, eax
  825.         mov     edx, eax
  826.         shr     eax, 9
  827.         add     ax, 1980
  828.         shl     eax, 16 ; year
  829.         and     edx, 0x1F
  830.         mov     al, dl  ; day
  831.         shr     ecx, 5
  832.         and     ecx, 0xF
  833.         mov     ah, cl  ; month
  834.         pop     edx ecx
  835.         ret
  836.  
  837. bdfe_to_fat_time:
  838.         push    edx
  839.         mov     edx, eax
  840.         shr     eax, 16
  841.         and     dh, 0x3F
  842.         shl     eax, 6
  843.         or      al, dh
  844.         shr     dl, 1
  845.         and     dl, 0x1F
  846.         shl     eax, 5
  847.         or      al, dl
  848.         pop     edx
  849.         ret
  850.  
  851. bdfe_to_fat_date:
  852.         push    edx
  853.         mov     edx, eax
  854.         shr     eax, 16
  855.         sub     ax, 1980
  856.         and     dh, 0xF
  857.         shl     eax, 4
  858.         or      al, dh
  859.         and     dl, 0x1F
  860.         shl     eax, 5
  861.         or      al, dl
  862.         pop     edx
  863.         ret
  864.  
  865. fat_entry_to_bdfe:
  866. ; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
  867. ; destroys eax
  868.         mov     eax, [ebp-4]
  869.         mov     [esi+4], eax    ; ASCII/UNICODE name
  870. fat_entry_to_bdfe2:
  871.         movzx   eax, byte [edi+11]
  872.         mov     [esi], eax      ; attributes
  873.         movzx   eax, word [edi+14]
  874.         call    fat_time_to_bdfe
  875.         mov     [esi+8], eax    ; creation time
  876.         movzx   eax, word [edi+16]
  877.         call    fat_date_to_bdfe
  878.         mov     [esi+12], eax   ; creation date
  879.         and     dword [esi+16], 0       ; last access time is not supported on FAT
  880.         movzx   eax, word [edi+18]
  881.         call    fat_date_to_bdfe
  882.         mov     [esi+20], eax   ; last access date
  883.         movzx   eax, word [edi+22]
  884.         call    fat_time_to_bdfe
  885.         mov     [esi+24], eax   ; last write time
  886.         movzx   eax, word [edi+24]
  887.         call    fat_date_to_bdfe
  888.         mov     [esi+28], eax   ; last write date
  889.         mov     eax, [edi+28]
  890.         mov     [esi+32], eax   ; file size (low dword)
  891.         xor     eax, eax
  892.         mov     [esi+36], eax   ; file size (high dword)
  893.         test    ebp, ebp
  894.         jz      .ret
  895.         push    ecx edi
  896.         lea     edi, [esi+40]
  897.         mov     esi, ebp
  898.         test    byte [esi-4], 1
  899.         jz      .ansi
  900.         mov     ecx, 260/2
  901.         rep     movsd
  902.         mov     [edi-2], ax
  903. @@:
  904.         mov     esi, edi
  905.         pop     edi ecx
  906. .ret:
  907.         ret
  908. .ansi:
  909.         mov     ecx, 264/4
  910.         rep     movsd
  911.         mov     [edi-1], al
  912.         jmp     @b
  913.  
  914. bdfe_to_fat_entry:
  915. ; convert BDFE at edx to FAT entry at edi
  916. ; destroys eax
  917. ; attributes byte
  918.         test    byte [edi+11], 8        ; volume label?
  919.         jnz     @f
  920.         mov     al, [edx]
  921.         and     al, 0x27
  922.         and     byte [edi+11], 0x10
  923.         or      byte [edi+11], al
  924. @@:
  925.         mov     eax, [edx+8]
  926.         call    bdfe_to_fat_time
  927.         mov     [edi+14], ax            ; creation time
  928.         mov     eax, [edx+12]
  929.         call    bdfe_to_fat_date
  930.         mov     [edi+16], ax            ; creation date
  931.         mov     eax, [edx+20]
  932.         call    bdfe_to_fat_date
  933.         mov     [edi+18], ax            ; last access date
  934.         mov     eax, [edx+24]
  935.         call    bdfe_to_fat_time
  936.         mov     [edi+22], ax            ; last write time
  937.         mov     eax, [edx+28]
  938.         call    bdfe_to_fat_date
  939.         mov     [edi+24], ax            ; last write date
  940.         ret
  941.  
  942. ramdisk_root_first:
  943.         mov     edi, 0x100000+512*19
  944.         clc
  945.         ret
  946. ramdisk_root_next:
  947.         add     edi, 0x20
  948.         cmp     edi, 0x100000+512*33
  949.         cmc
  950.         ret
  951.  
  952. rd_find_lfn:
  953. ; in: esi->name
  954. ; out: CF=1 - file not found
  955. ;      else CF=0 and edi->direntry
  956.         push    esi edi
  957.         push    ramdisk_root_first
  958.         push    ramdisk_root_next
  959.         call    fat_find_lfn
  960.         jc      .notfound
  961.         cmp     byte [esi], 0
  962.         jnz     .notfound
  963.         add     esp, 12
  964.         pop     esi
  965.         ret     ; CF=0
  966. .notfound:
  967.         add     esp, 8
  968.         pop     edi esi
  969.         stc
  970.         ret
  971.  
  972. ;----------------------------------------------------------------
  973. ;
  974. ;  fs_RamdiskRead - LFN variant for reading sys floppy
  975. ;
  976. ;  esi  points to filename
  977. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  978. ;       may be ebx=0 - start from first byte
  979. ;  ecx  number of bytes to read, 0+
  980. ;  edx  mem location to return data
  981. ;
  982. ;  ret ebx = bytes read or 0xffffffff file not found
  983. ;      eax = 0 ok read or other = errormsg
  984. ;
  985. ;--------------------------------------------------------------
  986. fs_RamdiskRead:
  987.         cmp     byte [esi], 0
  988.         jnz     @f
  989.         or      ebx, -1
  990.         mov     eax, 10         ; access denied
  991.         ret
  992. @@:
  993.         push    edi
  994.         call    rd_find_lfn
  995.         jnc     .found
  996.         pop     edi
  997.         or      ebx, -1
  998.         mov     eax, 5          ; file not found
  999.         ret
  1000. .found:
  1001.         test    ebx, ebx
  1002.         jz      .l1
  1003.         cmp     dword [ebx+4], 0
  1004.         jz      @f
  1005.         xor     ebx, ebx
  1006. .reteof:
  1007.         mov     eax, 6          ; EOF
  1008.         pop     edi
  1009.         ret
  1010. @@:
  1011.         mov     ebx, [ebx]
  1012. .l1:
  1013.         push    ecx edx
  1014.         push    0
  1015.         mov     eax, [edi+28]
  1016.         sub     eax, ebx
  1017.         jb      .eof
  1018.         cmp     eax, ecx
  1019.         jae     @f
  1020.         mov     ecx, eax
  1021.         mov     byte [esp], 6           ; EOF
  1022. @@:
  1023.         movzx   edi, word [edi+26]      ; cluster
  1024. .new:
  1025.         jecxz   .done
  1026.         test    edi, edi
  1027.         jz      .eof
  1028.         cmp     edi, 0xFF8
  1029.         jae     .eof
  1030.         lea     eax, [edi+31]           ; bootsector+2*fat+filenames
  1031.         shl     eax, 9                  ; *512
  1032.         add     eax, 0x100000           ; image base
  1033. ; now eax points to data of cluster
  1034.         sub     ebx, 512
  1035.         jae     .skip
  1036.         lea     eax, [eax+ebx+512]
  1037.         neg     ebx
  1038.         push    ecx
  1039.         cmp     ecx, ebx
  1040.         jbe     @f
  1041.         mov     ecx, ebx
  1042. @@:
  1043.         mov     ebx, edx
  1044.         call    memmove
  1045.         add     edx, ecx
  1046.         sub     [esp], ecx
  1047.         pop     ecx
  1048.         xor     ebx, ebx
  1049. .skip:
  1050.         movzx   edi, word [edi*2+0x280000]      ; find next cluster from FAT
  1051.         jmp     .new
  1052. .eof:
  1053.         mov     ebx, edx
  1054.         pop     eax edx ecx
  1055.         sub     ebx, edx
  1056.         jmp     .reteof
  1057. .done:
  1058.         mov     ebx, edx
  1059.         pop     eax edx ecx edi
  1060.         sub     ebx, edx
  1061.         ret
  1062.  
  1063. ;----------------------------------------------------------------
  1064. ;
  1065. ;  fs_RamdiskReadFolder - LFN variant for reading sys floppy folder
  1066. ;
  1067. ;  esi  points to filename; only root is folder on ramdisk
  1068. ;  ebx  pointer to structure 32-bit number = first wanted block
  1069. ;                          & flags (bitfields)
  1070. ; flags: bit 0: 0=ANSI names, 1=UNICODE names
  1071. ;  ecx  number of blocks to read, 0+
  1072. ;  edx  mem location to return data
  1073. ;
  1074. ;  ret ebx = size or 0xffffffff file not found
  1075. ;      eax = 0 ok read or other = errormsg
  1076. ;
  1077. ;--------------------------------------------------------------
  1078. fs_RamdiskReadFolder:
  1079.         cmp     byte [esi], 0
  1080.         jz      @f
  1081. ; ramdisk doesn't support folders
  1082.         mov     eax, ERROR_ACCESS_DENIED
  1083.         or      ebx, -1
  1084.         ret
  1085. @@:
  1086.         push    esi edi ecx
  1087. ; init header
  1088.         push    ecx
  1089.         mov     edi, edx
  1090.         mov     ecx, 32/4
  1091.         xor     eax, eax
  1092.         rep     stosd
  1093.         mov     byte [edx], 1   ; version
  1094.         pop     ecx
  1095.         push    ebp
  1096.         sub     esp, 262*2      ; allocate space for LFN
  1097.         mov     ebp, esp
  1098.         push    dword [ebx+4]   ; for fat_get_name: read ANSI/UNICODE name
  1099.         mov     ebx, [ebx]
  1100. ; read root
  1101.         mov     esi, edi        ; esi points to block of data of folder entry (BDFE)
  1102.         mov     edi, 0x100000+512*19
  1103. .l1:
  1104.         call    fat_get_name
  1105.         jc      .l2
  1106.         cmp     byte [edi+11], 0xF
  1107.         jnz     @f
  1108.         add     edi, 0x20
  1109. @@:
  1110.         inc     dword [edx+8]   ; new file found
  1111.         dec     ebx
  1112.         jns     .l2
  1113.         dec     ecx
  1114.         js      .l2
  1115.         inc     dword [edx+4]  ; new file block copied
  1116.         call    fat_entry_to_bdfe
  1117. .l2:
  1118.         add     edi, 0x20
  1119.         cmp     edi, 0x100000+512*33
  1120.         jb      .l1
  1121.         add     esp, 262*2+4
  1122.         pop     ebp
  1123.         mov     ebx, [edx+4]
  1124.         xor     eax, eax
  1125.         dec     ecx
  1126.         js      @f
  1127.         mov     al, ERROR_END_OF_FILE
  1128. @@:
  1129.         pop     ecx edi esi
  1130.         ret
  1131.  
  1132. iglobal
  1133. label fat_legal_chars byte
  1134. ; 0 = not allowed
  1135. ; 1 = allowed only in long names
  1136. ; 3 = allowed
  1137.         times 32 db 0
  1138. ;                 ! " # $ % & ' ( ) * + , - . /
  1139.         db      1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0
  1140. ;               0 1 2 3 4 5 6 7 8 9 : ; < = > ?
  1141.         db      3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0
  1142. ;               @ A B C D E F G H I J K L M N O
  1143.         db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
  1144. ;               P Q R S T U V W X Y Z [ \ ] ^ _
  1145.         db      3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3
  1146. ;               ` a b c d e f g h i j k l m n o
  1147.         db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
  1148. ;               p q r s t u v w x y z { | } ~
  1149.         db      3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0
  1150. endg
  1151.  
  1152. fat_name_is_legal:
  1153. ; in: esi->(long) name
  1154. ; out: CF set <=> legal
  1155. ; destroys eax
  1156.         push    esi
  1157.         xor     eax, eax
  1158. @@:
  1159.         lodsb
  1160.         test    al, al
  1161.         jz      .done
  1162.         cmp     al, 80h
  1163.         jae     .big
  1164.         test    [fat_legal_chars+eax], 1
  1165.         jnz     @b
  1166. .err:
  1167.         pop     esi
  1168.         clc
  1169.         ret
  1170. .big:
  1171. ; 0x80-0xAF, 0xE0-0xEF
  1172.         cmp     al, 0xB0
  1173.         jb      @b
  1174.         cmp     al, 0xE0
  1175.         jb      .err
  1176.         cmp     al, 0xF0
  1177.         jb      @b
  1178.         jmp     .err
  1179. .done:
  1180.         sub     esi, [esp]
  1181.         cmp     esi, 257
  1182.         pop     esi
  1183.         ret
  1184.  
  1185. fat_next_short_name:
  1186. ; in: edi->8+3 name
  1187. ; out: name corrected
  1188. ;      CF=1 <=> error
  1189.         pushad
  1190.         mov     ecx, 8
  1191.         mov     al, '~'
  1192.         std
  1193.         push    edi
  1194.         add     edi, 7
  1195.         repnz   scasb
  1196.         pop     edi
  1197.         cld
  1198.         jz      .tilde
  1199. ; tilde is not found, insert "~1" at end
  1200.         add     edi, 6
  1201.         cmp     word [edi], '  '
  1202.         jnz     .insert_tilde
  1203. @@:     dec     edi
  1204.         cmp     byte [edi], ' '
  1205.         jz      @b
  1206.         inc     edi
  1207. .insert_tilde:
  1208.         mov     word [edi], '~1'
  1209.         popad
  1210. ;       clc     ; CF already cleared
  1211.         ret
  1212. .tilde:
  1213.         push    edi
  1214.         add     edi, 7
  1215.         xor     ecx, ecx
  1216. @@:
  1217. ; after tilde may be only digits and trailing spaces
  1218.         cmp     byte [edi], '~'
  1219.         jz      .break
  1220.         cmp     byte [edi], ' '
  1221.         jz      .space
  1222.         cmp     byte [edi], '9'
  1223.         jnz     .found
  1224.         dec     edi
  1225.         jmp     @b
  1226. .space:
  1227.         dec     edi
  1228.         inc     ecx
  1229.         jmp     @b
  1230. .found:
  1231.         inc     byte [edi]
  1232. .succ:
  1233.         pop     edi
  1234.         popad
  1235.         clc
  1236.         ret
  1237. .break:
  1238.         jecxz   .noplace
  1239.         inc     edi
  1240.         mov     al, '1'
  1241. @@:
  1242.         xchg    al, [edi]
  1243.         inc     edi
  1244.         cmp     al, ' '
  1245.         mov     al, '0'
  1246.         jnz     @b
  1247.         jmp     .succ
  1248. .noplace:
  1249.         dec     edi
  1250.         cmp     edi, [esp]
  1251.         jz      .err
  1252.         add     dword [esp], 8
  1253.         mov     word [edi], '~1'
  1254.         inc     edi
  1255.         inc     edi
  1256. @@:
  1257.         mov     byte [edi], '0'
  1258.         inc     edi
  1259.         cmp     edi, [esp]
  1260.         jb      @b
  1261.         pop     edi
  1262.         popad
  1263.         ;clc    ; automatically
  1264.         ret
  1265. .err:
  1266.         pop     edi
  1267.         popad
  1268.         stc
  1269.         ret
  1270.  
  1271. fat_gen_short_name:
  1272. ; in: esi->long name
  1273. ;     edi->buffer (8+3=11 chars)
  1274. ; out: buffer filled
  1275.         pushad
  1276.         mov     eax, '    '
  1277.         push    edi
  1278.         stosd
  1279.         stosd
  1280.         stosd
  1281.         pop     edi
  1282.         xor     eax, eax
  1283.         push    8
  1284.         pop     ebx
  1285.         lea     ecx, [edi+8]
  1286. .loop:
  1287.         lodsb
  1288.         test    al, al
  1289.         jz      .done
  1290.         call    char_toupper
  1291.         cmp     al, ' '
  1292.         jz      .space
  1293.         cmp     al, 80h
  1294.         ja      .big
  1295.         test    [fat_legal_chars+eax], 2
  1296.         jnz     .symbol
  1297. .inv_symbol:
  1298.         mov     al, '_'
  1299.         or      bh, 1
  1300. .symbol:
  1301.         cmp     al, '.'
  1302.         jz      .dot
  1303. .normal_symbol:
  1304.         dec     bl
  1305.         jns     .store
  1306.         mov     bl, 0
  1307. .space:
  1308.         or      bh, 1
  1309.         jmp     .loop
  1310. .store:
  1311.         stosb
  1312.         jmp     .loop
  1313. .big:
  1314.         cmp     al, 0xB0
  1315.         jb      .normal_symbol
  1316.         cmp     al, 0xE0
  1317.         jb      .inv_symbol
  1318.         cmp     al, 0xF0
  1319.         jb      .normal_symbol
  1320.         jmp     .inv_symbol
  1321. .dot:
  1322.         test    bh, 2
  1323.         jz      .firstdot
  1324.         pop     ebx
  1325.         add     ebx, edi
  1326.         sub     ebx, ecx
  1327.         push    ebx
  1328.         cmp     edi, ecx
  1329.         jbe     .skip
  1330. @@:
  1331.         dec     edi
  1332.         mov     al, ' '
  1333.         xchg    al, [edi]
  1334.         dec     ebx
  1335.         mov     [ebx], al
  1336.         cmp     edi, ecx
  1337.         ja      @b
  1338. .skip:
  1339.         mov     bh, 3
  1340.         jmp     @f
  1341. .firstdot:
  1342.         cmp     bl, 8
  1343.         jz      .space
  1344.         push    edi
  1345.         or      bh, 2
  1346. @@:
  1347.         mov     edi, ecx
  1348.         mov     bl, 3
  1349.         jmp     .loop
  1350. .done:
  1351.         test    bh, 2
  1352.         jz      @f
  1353.         pop     edi
  1354. @@:
  1355.         lea     edi, [ecx-8]
  1356.         test    bh, 1
  1357.         jz      @f
  1358.         call    fat_next_short_name
  1359. @@:
  1360.         popad
  1361.         ret
  1362.  
  1363. ;----------------------------------------------------------------
  1364. ;
  1365. ;  fs_RamdiskRewrite - LFN variant for writing sys floppy
  1366. ;
  1367. ;  esi  points to filename
  1368. ;  ebx  ignored (reserved)
  1369. ;  ecx  number of bytes to write, 0+
  1370. ;  edx  mem location to data
  1371. ;
  1372. ;  ret ebx = number of written bytes
  1373. ;      eax = 0 ok read or other = errormsg
  1374. ;
  1375. ;--------------------------------------------------------------
  1376. @@:
  1377.         mov     eax, ERROR_ACCESS_DENIED
  1378.         xor     ebx, ebx
  1379.         ret
  1380.  
  1381. fs_RamdiskRewrite:
  1382.         cmp     byte [esi], 0
  1383.         jz      @b
  1384. ; ramdisk doesn't support folders
  1385.         push    esi
  1386. @@:
  1387.         lodsb
  1388.         test    al, al
  1389.         jz      @f
  1390.         cmp     al, '/'
  1391.         jnz     @b
  1392.         pop     esi
  1393. .err5:
  1394.         mov     eax, 5  ; file not found
  1395.         xor     ebx, ebx
  1396.         ret
  1397. @@:
  1398.         pop     esi
  1399. ; check existence
  1400.         push    edi
  1401.         call    rd_find_lfn
  1402.         jc      .notfound
  1403. ; found, delete FAT chain
  1404.         push    edi
  1405.         xor     eax, eax
  1406.         mov     dword [edi+28], eax     ; zero size
  1407.         xchg    ax, word [edi+26]       ; start cluster
  1408.         test    eax, eax
  1409.         jz      .done1
  1410. @@:
  1411.         cmp     eax, 0xFF8
  1412.         jae     .done1
  1413.         lea     edi, [0x280000 + eax*2] ; position in FAT
  1414.         xor     eax, eax
  1415.         xchg    ax, [edi]
  1416.         jmp     @b
  1417. .done1:
  1418.         pop     edi
  1419.         call    get_time_for_file
  1420.         mov     [edi+22], ax
  1421.         call    get_date_for_file
  1422.         mov     [edi+24], ax
  1423.         mov     [edi+18], ax
  1424.         or      byte [edi+11], 20h      ; set 'archive' attribute
  1425.         jmp     .doit
  1426. .notfound:
  1427. ; file is not found; generate short name
  1428.         call    fat_name_is_legal
  1429.         jc      @f
  1430.         pop     edi
  1431.         jmp     .err5
  1432. @@:
  1433.         sub     esp, 12
  1434.         mov     edi, esp
  1435.         call    fat_gen_short_name
  1436. .test_short_name_loop:
  1437.         push    esi ecx
  1438.         mov     esi, 0x100000+512*19
  1439. .test_short_name_entry:
  1440.         cmp     byte [esi+11], 0xF
  1441.         jz      .test_short_name_cont
  1442.         mov     ecx, 11
  1443.         push    esi edi
  1444.         repz    cmpsb
  1445.         pop     edi esi
  1446.         jz      .short_name_found
  1447. .test_short_name_cont:
  1448.         add     esi, 20h
  1449.         cmp     esi, 0x100000+512*33
  1450.         jb      .test_short_name_entry
  1451.         pop     ecx esi
  1452.         jmp     .found
  1453. .short_name_found:
  1454.         call    fat_next_short_name
  1455.         pop     ecx esi
  1456.         jnc     .test_short_name_loop
  1457. .disk_full:
  1458.         add     esp, 12
  1459.         pop     edi
  1460.         mov     eax, ERROR_DISK_FULL
  1461.         xor     ebx, ebx
  1462.         ret
  1463. .found:
  1464. ; now find space in directory
  1465. ; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
  1466.         mov     al, '~'
  1467.         push    ecx edi
  1468.         mov     ecx, 8
  1469.         repnz   scasb
  1470.         push    1
  1471.         pop     eax     ; 1 entry
  1472.         jnz     .notilde
  1473. ; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
  1474.         xor     eax, eax
  1475. @@:
  1476.         cmp     byte [esi], 0
  1477.         jz      @f
  1478.         inc     esi
  1479.         inc     eax
  1480.         jmp     @b
  1481. @@:
  1482.         sub     esi, eax
  1483.         add     eax, 12+13
  1484.         mov     ecx, 13
  1485.         push    edx
  1486.         cdq
  1487.         div     ecx
  1488.         pop     edx
  1489. .notilde:
  1490. ; find <eax> successive entries in directory
  1491.         xor     ecx, ecx
  1492.         mov     edi, 0x100000+512*19
  1493. .scan_dir:
  1494.         cmp     byte [edi], 0
  1495.         jz      .free
  1496.         cmp     byte [edi], 0xE5
  1497.         jz      .free
  1498.         xor     ecx, ecx
  1499. .scan_cont:
  1500.         add     edi, 0x20
  1501.         cmp     edi, 0x100000+512*33
  1502.         jb      .scan_dir
  1503.         pop     edi ecx
  1504.         jmp     .disk_full
  1505. .free:
  1506.         inc     ecx
  1507.         cmp     ecx, eax
  1508.         jb      .scan_cont
  1509. ; found!
  1510. ; calculate name checksum
  1511.         push    esi ecx
  1512.         mov     esi, [esp+8]
  1513.         mov     ecx, 11
  1514.         xor     eax, eax
  1515. @@:
  1516.         ror     al, 1
  1517.         add     al, [esi]
  1518.         inc     esi
  1519.         loop    @b
  1520.         pop     ecx esi
  1521. ; edi points to last entry in free chunk
  1522.         dec     ecx
  1523.         jz      .nolfn
  1524.         push    esi
  1525.         push    edi
  1526. .writelfn:
  1527.         sub     edi, 20h
  1528.         push    ecx eax
  1529.         mov     eax, [esp+8]
  1530.         sub     eax, edi
  1531.         shr     eax, 5
  1532.         cmp     ecx, 1
  1533.         jnz     @f
  1534.         or      al, 40h
  1535. @@:
  1536.         stosb
  1537.         mov     cl, 5
  1538.         call    .read_symbols
  1539.         mov     ax, 0xF
  1540.         stosw
  1541.         pop     eax
  1542.         stosb
  1543.         push    eax
  1544.         mov     cl, 6
  1545.         call    .read_symbols
  1546.         xor     eax, eax
  1547.         stosw
  1548.         mov     cl, 2
  1549.         call    .read_symbols
  1550.         pop     eax ecx
  1551.         sub     edi, 0x20
  1552.         loop    .writelfn
  1553.         pop     edi
  1554.         pop     esi
  1555. .nolfn:
  1556.         xchg    esi, [esp]
  1557.         mov     ecx, 11
  1558.         rep     movsb
  1559.         mov     word [edi], 20h         ; attributes
  1560.         sub     edi, 11
  1561.         pop     esi ecx
  1562.         add     esp, 12
  1563.         mov     byte [edi+13], 0        ; tenths of a second at file creation time
  1564.         call    get_time_for_file
  1565.         mov     [edi+14], ax            ; creation time
  1566.         mov     [edi+22], ax            ; last write time
  1567.         call    get_date_for_file
  1568.         mov     [edi+16], ax            ; creation date
  1569.         mov     [edi+24], ax            ; last write date
  1570.         mov     [edi+18], ax            ; last access date
  1571.         and     word [edi+20], 0        ; high word of cluster
  1572.         and     word [edi+26], 0        ; low word of cluster - to be filled
  1573.         and     dword [edi+28], 0       ; file size - to be filled
  1574. .doit:
  1575.         push    ecx edx
  1576.         push    ecx
  1577.         push    edi
  1578.         add     edi, 26         ; edi points to low word of cluster
  1579.         push    edi
  1580.         jecxz   .done
  1581.         mov     ecx, 2849
  1582.         mov     edi, 0x280000
  1583. .write_loop:
  1584. ; allocate new cluster
  1585.         xor     eax, eax
  1586.         repnz   scasw
  1587.         jnz     .disk_full2
  1588.         dec     edi
  1589.         dec     edi
  1590.         lea     eax, [edi-0x280000]
  1591.         shr     eax, 1                  ; eax = cluster
  1592.         mov     word [edi], 0xFFF       ; mark as last cluster
  1593.         xchg    edi, [esp]
  1594.         stosw
  1595.         pop     edi
  1596.         push    edi
  1597.         inc     ecx
  1598. ; write data
  1599.         shl     eax, 9
  1600.         add     eax, 0x100000+31*512
  1601.         mov     ebx, edx
  1602.         xchg    eax, ebx
  1603.         push    ecx
  1604.         mov     ecx, 512
  1605.         cmp     dword [esp+12], ecx
  1606.         jae     @f
  1607.         mov     ecx, [esp+12]
  1608. @@:
  1609.         call    memmove
  1610.         add     edx, ecx
  1611.         sub     [esp+12], ecx
  1612.         pop     ecx
  1613.         jnz     .write_loop
  1614. .done:
  1615.         mov     ebx, edx
  1616.         pop     edi edi ecx edx ecx
  1617.         sub     ebx, edx
  1618.         mov     [edi+28], ebx
  1619.         pop     edi
  1620.         xor     eax, eax
  1621.         ret
  1622. .disk_full2:
  1623.         mov     ebx, edx
  1624.         pop     edi edi ecx edx ecx
  1625.         sub     ebx, edx
  1626.         mov     [edi+28], ebx
  1627.         pop     edi
  1628.         push    ERROR_DISK_FULL
  1629.         pop     eax
  1630.         ret
  1631.  
  1632. .read_symbol:
  1633.         or      ax, -1
  1634.         test    esi, esi
  1635.         jz      .retFFFF
  1636.         lodsb
  1637.         test    al, al
  1638.         jnz     ansi2uni_char
  1639.         xor     eax, eax
  1640.         xor     esi, esi
  1641. .retFFFF:
  1642.         ret
  1643.  
  1644. .read_symbols:
  1645.         call    .read_symbol
  1646.         stosw
  1647.         loop    .read_symbols
  1648.         ret
  1649.  
  1650. fs_RamdiskGetFileInfo:
  1651.         cmp     byte [esi], 0
  1652.         jnz     @f
  1653.         mov     eax, 2  ; unsupported
  1654.         ret
  1655. @@:
  1656.         push    edi
  1657.         call    rd_find_lfn
  1658. fs_GetFileInfo_finish:
  1659.         jnc     @f
  1660.         pop     edi
  1661.         mov     eax, ERROR_FILE_NOT_FOUND
  1662.         ret
  1663. @@:
  1664.         push    esi ebp
  1665.         xor     ebp, ebp
  1666.         mov     esi, edx
  1667.         and     dword [esi+4], 0
  1668.         call    fat_entry_to_bdfe2
  1669.         pop     ebp esi
  1670.         pop     edi
  1671.         xor     eax, eax
  1672.         ret
  1673.  
  1674. fs_RamdiskSetFileInfo:
  1675.         cmp     byte [esi], 0
  1676.         jnz     @f
  1677.         mov     eax, 2  ; unsupported
  1678.         ret
  1679. @@:
  1680.         push    edi
  1681.         call    rd_find_lfn
  1682.         jnc     @f
  1683.         pop     edi
  1684.         mov     eax, ERROR_FILE_NOT_FOUND
  1685.         ret
  1686. @@:
  1687.         call    bdfe_to_fat_entry
  1688.         pop     edi
  1689.         xor     eax, eax
  1690.         ret
  1691.  
  1692. ; \end{diamond}
  1693.