Subversion Repositories Kolibri OS

Rev

Rev 71 | Rev 77 | 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. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. ; calculate fat chain
  9.  
  10. calculatefatchain:
  11.  
  12.    pushad
  13.  
  14.    mov  esi,0x100000+512
  15.    mov  edi,0x280000
  16.  
  17.  fcnew:
  18.    mov  eax,dword [esi]
  19.    mov  ebx,dword [esi+4]
  20.    mov  ecx,dword [esi+8]
  21.    mov  edx,ecx
  22.    shr  edx,4   ;8 ok
  23.    shr  dx,4    ;7 ok
  24.    xor  ch,ch
  25.    shld ecx,ebx,20 ;6 ok
  26.    shr  cx,4     ;5 ok
  27.    shld ebx,eax,12
  28.    and  ebx,0x0fffffff  ;4 ok
  29.    shr  bx,4    ;3 ok
  30.    shl  eax,4
  31.    and  eax,0x0fffffff  ;2 ok
  32.    shr  ax,4  ;1 ok
  33.    mov dword [edi],eax
  34.    add  edi,4
  35.    mov dword [edi],ebx
  36.    add  edi,4
  37.    mov dword [edi],ecx
  38.    add  edi,4
  39.    mov dword [edi],edx
  40.    add  edi,4  
  41.    add  esi,12
  42.  
  43.    cmp  edi,0x280000+2856*2   ;2849 clusters
  44.    jnz  fcnew
  45.  
  46.    popad
  47.    ret
  48.  
  49.  
  50. restorefatchain:   ; restore fat chain
  51.  
  52.    pushad
  53.  
  54.    mov  esi,0x280000
  55.    mov  edi,0x100000+512
  56.  
  57.   fcnew2:
  58.    mov  eax,dword [esi]
  59.    mov  ebx,dword [esi+4]
  60.    shl  ax,4
  61.    shl  eax,4
  62.    shl  bx,4
  63.    shr  ebx,4
  64.    shrd eax,ebx,8
  65.    shr  ebx,8
  66.    mov dword [edi],eax
  67.    add  edi,4
  68.    mov word [edi],bx
  69.    add  edi,2
  70.    add  esi,8
  71.  
  72.    cmp  edi,0x100000+512+4278     ;4274 bytes - all used FAT
  73.    jb   fcnew2
  74.  
  75.    mov  esi,0x100000+512           ; duplicate fat chain
  76.    mov  edi,0x100000+512+0x1200
  77.    mov  ecx,1069        ;4274/4
  78.    cld
  79.    rep  movsd
  80.  
  81.    popad
  82.    ret
  83.  
  84.  
  85. ramdisk_free_space:
  86. ;---------------------------------------------
  87. ;
  88. ; returns free space in edi
  89. ; rewr.by Mihasik
  90. ;---------------------------------------------
  91.  
  92.         push   eax ebx ecx
  93.  
  94.         mov  edi,0x280000 ;start of FAT
  95.         xor  ax,ax    ;Free cluster=0x0000 in FAT
  96.         xor  ebx,ebx  ;counter
  97.         mov  ecx,2849 ;2849 clusters
  98.         cld
  99.     rdfs1:
  100.         repne scasw
  101.         jnz  rdfs2    ;if last cluster not 0
  102.         inc  ebx
  103.         jcxz rdfs2    ;if last cluster=0
  104.         jmp  rdfs1    ;if not last
  105.     rdfs2:
  106.         shl  ebx,9    ;free clusters*512
  107.         mov  edi,ebx
  108.        
  109.         pop    ecx ebx eax
  110.         ret
  111.  
  112.  
  113. expand_filename:
  114. ;---------------------------------------------
  115. ;
  116. ; exapand filename with '.' to 11 character
  117. ; eax - pointer to filename
  118. ;---------------------------------------------
  119.  
  120.         push esi edi ebx
  121.  
  122.         mov  edi,esp                  ; check for '.' in the name
  123.         add  edi,12+8
  124.  
  125.         mov  esi,eax
  126.  
  127.         mov  eax,edi
  128.         mov  [eax+0],dword '    '
  129.         mov  [eax+4],dword '    '
  130.         mov  [eax+8],dword '    '
  131.  
  132.       flr1:
  133.  
  134.         cmp  [esi],byte '.'
  135.         jne  flr2
  136.         mov  edi,eax
  137.         add  edi,7
  138.         jmp  flr3
  139.  
  140.       flr2:
  141.  
  142.         mov  bl,[esi]
  143.         mov  [edi],bl
  144.  
  145.       flr3:
  146.  
  147.         inc  esi
  148.         inc  edi
  149.  
  150.         mov  ebx,eax
  151.         add  ebx,11
  152.  
  153.         cmp  edi,ebx
  154.         jbe  flr1
  155.  
  156.         pop  ebx edi esi
  157.         ret
  158.  
  159. fileread:
  160. ;----------------------------------------------------------------
  161. ;
  162. ;  fileread - sys floppy
  163. ;
  164. ;  eax  points to filename 11 chars
  165. ;  ebx  first wanted block       ; 1+ ; if 0 then set to 1
  166. ;  ecx  number of blocks to read ; 1+ ; if 0 then set to 1
  167. ;  edx  mem location to return data
  168. ;  esi  length of filename 12*X 0=root
  169. ;
  170. ;  ret ebx = size or 0xffffffff file not found
  171. ;      eax = 0 ok read or other = errormsg
  172. ;
  173. ;--------------------------------------------------------------
  174.         test   ebx,ebx ;if ebx=0 - set to 1
  175.         jnz    frfl5
  176.         inc    ebx
  177.       frfl5:
  178.         test   ecx,ecx ;if ecx=0 - set to 1
  179.         jnz    frfl6
  180.         inc    ecx
  181.       frfl6:
  182.         test   esi,esi          ; return ramdisk root
  183.         jnz    fr_noroot        ;if not root
  184.         cmp    ebx,14           ;14 clusters=root dir
  185.         ja     oorr
  186.         cmp    ecx,14
  187.         ja     oorr
  188.         jmp    fr_do
  189.       oorr:
  190.         mov    eax,5            ;out of root range (fnf)
  191.         xor    ebx,ebx
  192.         dec    ebx              ;0xffffffff
  193.         ret
  194.  
  195.       fr_do:                    ;reading rootdir
  196.         mov    edi,edx
  197.         dec    ebx
  198.         push   edx
  199.         mov    edx,ecx    
  200.         add    edx,ebx
  201.         cmp    edx,15     ;ebx+ecx=14+1
  202.         pushf
  203.         jbe    fr_do1
  204.         sub    edx,14
  205.         sub    ecx,edx
  206.       fr_do1:
  207.         shl    ebx,9
  208.         mov    esi,0x100000+512*19
  209.         add    esi,ebx
  210.         shl    ecx,7
  211.         cld
  212.         rep    movsd
  213.         popf
  214.         pop    edx
  215.         jae    fr_do2
  216.         xor    eax,eax ; ok read
  217.         xor    ebx,ebx
  218.         ret
  219.       fr_do2:        ;if last cluster
  220.         mov    eax,6  ;end of file
  221.         xor    ebx,ebx
  222.         ret
  223.  
  224.      fr_noroot:
  225.  
  226.         sub    esp,32
  227.         call   expand_filename
  228.  
  229.         dec    ebx
  230.  
  231.         push   eax
  232.  
  233.         push   eax ebx ecx edx esi edi
  234.         call   rd_findfile
  235.         je     fifound
  236.         add    esp,32+28   ;if file not found
  237.         ret
  238.  
  239.      fifound:
  240.  
  241.         mov    ebx,[edi-11+28]          ;file size
  242.         mov    [esp+20],ebx
  243.         mov    [esp+24],ebx
  244.         add    edi,0xf
  245.         movzx  eax,word [edi]
  246.         mov    edi,eax                  ;edi=cluster
  247.  
  248.       frnew:
  249.  
  250.         add    eax,31                   ;bootsector+2*fat+filenames
  251.         shl    eax,9                    ;*512
  252.         add    eax,0x100000             ;image base
  253.         mov    ebx,[esp+8]
  254.         mov    ecx,512                  ;[esp+4]
  255.  
  256.         cmp    [esp+16],dword 0         ; wanted cluster ?
  257.         jne    frfl7
  258.         call   memmove
  259.         add    [esp+8],dword 512
  260.         dec    dword [esp+12]           ; last wanted cluster ?
  261.         je     frnoread
  262.         jmp    frfl8
  263.       frfl7:
  264.         dec    dword [esp+16]
  265.       frfl8:
  266.         movzx  eax,word [edi*2+0x280000]        ; find next cluster from FAT
  267.         mov    edi,eax
  268.         cmp    edi,4095                 ;eof  - cluster
  269.         jz     frnoread2
  270.  
  271.         cmp    [esp+24],dword 512       ;eof  - size
  272.         jb     frnoread
  273.         sub    [esp+24],dword 512
  274.  
  275.         jmp    frnew
  276.  
  277.       frnoread2:
  278.  
  279.         cmp    [esp+16],dword 0         ; eof without read ?
  280.         je     frnoread
  281.  
  282.         pop    edi esi edx ecx
  283.         add    esp,4
  284.         pop    ebx     ; ebx <- eax : size of file
  285.         add    esp,36
  286.         mov    eax,6   ; end of file
  287.         ret
  288.  
  289.       frnoread:
  290.  
  291.         pop    edi esi edx ecx
  292.         add    esp,4
  293.         pop    ebx     ; ebx <- eax : size of file
  294.         add    esp,36
  295.         xor    eax,eax  ;read ok
  296.         ret
  297.  
  298. filedelete:
  299. ;--------------------------------------------
  300. ;
  301. ; filedelete - sys floppy
  302. ; in:
  303. ; eax -  pointer to filename 11 chars
  304. ;
  305. ; out:
  306. ; eax - 0 = successful, 5 = file not found
  307. ;
  308. ;--------------------------------------------
  309.  
  310.         sub    esp,32
  311.         call   expand_filename
  312.  
  313.         push   eax ebx ecx edx esi edi
  314.        
  315.         call   rd_findfile
  316.         je     fifoundd
  317.         pop    edi esi edx ecx ebx eax ;file not found
  318.         add    esp,32
  319.         mov    eax,5
  320.         ret
  321.  
  322.      fifoundd:
  323.  
  324.         mov    [edi-11],byte 0xE5       ;mark filename deleted
  325.         add    edi,0xf
  326.         movzx  eax,word [edi]
  327.         mov    edi,eax                  ;edi = cluster
  328.  
  329.       frnewd:
  330.  
  331.         shl    edi,1                    ;find next cluster from FAT
  332.         add    edi,0x280000
  333.         movzx  eax,word [edi]
  334.         mov    [edi],word 0x0           ;clear fat chain cluster
  335.         mov    edi,eax
  336.         cmp    edi,dword 0xff8          ;last cluster ?
  337.         jb     frnewd
  338.  
  339.         pop    edi esi edx ecx ebx eax
  340.         add    esp,32
  341.         xor    eax,eax       ; file found
  342.         ret
  343.  
  344.      
  345.  
  346. filesave:
  347. ;----------------------------------------------------------
  348. ;
  349. ; filesave - sys floppy
  350. ;
  351. ; eax points to filename 11 chars
  352. ;
  353. ;        eax      ; pointer to file name
  354. ;        ebx      ; buffer
  355. ;        ecx      ; count to write in bytes
  356. ;        edx      ; 0 create new , 1 append
  357. ;
  358. ;-----------------------------------------------------------
  359.  
  360.         sub  esp,32
  361.         call expand_filename
  362.         test edx,edx
  363.         jnz  fsdel
  364.         pusha
  365.         call filedelete
  366.         popa
  367.  
  368.       fsdel:
  369.  
  370.         call   ramdisk_free_space
  371.         cmp    ecx,edi
  372.         jbe    rd_do_save
  373.         add    esp,32
  374.         mov    eax,8    ;disk full
  375.         ret
  376.  
  377.       rd_do_save:
  378.  
  379.         push   eax ebx ecx edx esi edi
  380.  
  381.         mov    edi,0x100000+512*18+512  ;Point at directory
  382.         mov    edx,224 +1
  383.         ; find an empty spot for filename in the root dir
  384.      l20ds:
  385.         dec    edx
  386.         test   edx,edx
  387.         jz     frnoreadds
  388.      l21ds:
  389.         cmp    [edi],byte 0xE5
  390.         jz     fifoundds
  391.         cmp    [edi],byte 0x0
  392.         jz     fifoundds
  393.         add    edi,32                   ; Advance to next entry
  394.         jmp    l20ds
  395.      fifoundds:
  396.  
  397.         push   edi                      ; move the filename to root dir
  398.         mov    esi,[esp+4+20]
  399.         mov    ecx,11
  400.         cld
  401.         rep    movsb
  402.         pop    edi
  403.         mov    edx,edi
  404.         add    edx,11+0xf               ; edx <- cluster save position
  405.         mov    ebx,[esp+12]             ; save file size
  406.         mov    [edi+28],ebx
  407.         mov    [edi+11],byte 0x20       ; attribute
  408. ; Ivan Poddubny 11/12/2003:
  409. call get_date_for_file   ; from FAT32.INC
  410. mov [edi+24],ax          ; date
  411. call get_time_for_file   ; from FAT32.INC
  412. mov [edi+22],ax          ; time
  413. ; End
  414.         mov    edi,0x280000            ;pointer to first cluster
  415.         mov    ecx,2849
  416.         cld
  417.       frnewds:
  418.         xor    ax,ax
  419.         repne  scasw
  420.         mov    ebx,2848
  421.         sub    ebx,ecx
  422.         mov    [edx],bx                 ; save next cluster pos. to prev cl.
  423.         mov    edx,edi                  ; next save pos abs mem add
  424.         dec    edx
  425.         dec    edx
  426.         call   fdc_filesave
  427.         pusha                           ; move save to floppy cluster
  428.         add    ebx,31
  429.         shl    ebx,9
  430.         add    ebx,0x100000
  431.         mov    eax,[esp+32+16]
  432.         mov    ecx,512
  433.         call   memmove
  434.         popa
  435.  
  436.         mov    eax,[esp+12]
  437.         cmp    eax,512
  438.         jbe    flnsa
  439.         sub    eax,512
  440.         mov    [esp+12],eax
  441.         mov    eax,[esp+16]
  442.         add    eax,512
  443.         mov    [esp+16],eax
  444.         jmp    frnewds
  445.  
  446.      flnsa:
  447.         dec    edi
  448.         dec    edi
  449.         mov    [edi],word 4095          ; mark end of file - last cluster
  450.  
  451.       frnoreadds:
  452.  
  453.         pop    edi esi edx ecx ebx eax
  454.         add    esp,32
  455.  
  456. ;        pusha
  457. ;        cli
  458. ;        call   fdc_commitfile
  459. ;        sti
  460. ;        popa
  461.  
  462.         xor    eax,eax ;ok write
  463.         ret
  464.  
  465.    rd_findfile:
  466.    ;by Mihasik
  467.    ;IN: eax - pointer to filename OUT: filestring+11 in edi or notZero in flags and fnf in eax,ebx
  468.  
  469.         mov    edi,0x100000+512*18+512  ;Point at directory
  470.         cld
  471.     rd_newsearch:
  472.         mov    esi,eax
  473.         mov    ecx,11
  474.         rep    cmpsb
  475.         je     rd_ff
  476.         add    cl,21
  477.         add    edi,ecx
  478.         cmp    edi,0x100000+512*33
  479.         jb     rd_newsearch
  480.         mov    eax,5      ;if file not found - eax=5
  481.         xor    ebx,ebx
  482.         dec    ebx    ;ebx=0xffffffff and zf=0    
  483.      rd_ff:
  484.         ret            
  485.  
  486.   rd_getfileinfo:
  487.      ;get date, time, size or attributes of file
  488.      ;IN: eax - pointer to file, ebx - type of function: 12-get filesize, 13-get fileattr, 14-get filedate
  489.      ;ecx - filelengh 0=root
  490.      ;OUT: eax=0 - Ok or 5 - file not found ebx - date/time, size or attributes
  491.         test   ecx,ecx
  492.         jnz    no_getfinfo_root
  493.         mov    eax,5      ;if root - fnf
  494.         xor    ebx,ebx
  495.         dec    ebx
  496.         ret
  497.     no_getfinfo_root:     ;if not root
  498.         sub    esp,32
  499.         call   expand_filename
  500.         call   rd_findfile
  501.         je     fifoundi
  502.         add    esp,32      ;if file not found
  503.         ret
  504.     fifoundi:    
  505.         cmp    ebx,13
  506.         jne    no_rd_attr
  507.         movzx ebx,byte [edi]    ;get attributes
  508.         jmp    rd_getfileinfo_end
  509.      no_rd_attr:
  510.         cmp    ebx,14
  511.         jne    no_rd_date
  512.         mov    ebx,dword [edi+11] ;get date/time
  513.         jmp    rd_getfileinfo_end
  514.      no_rd_date:
  515.         mov    ebx,dword [edi+17] ;get size
  516.      rd_getfileinfo_end:
  517.         xor    eax,eax
  518.         add    esp,32
  519.         ret
  520.  
  521. ; \begin{diamond}
  522.  
  523. uni2ansi_str:
  524. ; convert UNICODE zero-terminated string to ASCII-string (codepage 866)
  525. ; in: esi->source, edi->buffer (may be esi=edi)
  526. ; destroys: eax,esi,edi
  527.         lodsw
  528.         test    ax, ax
  529.         jz      .done
  530.         cmp     ax, 0x80
  531.         jb      .ascii
  532.         cmp     ax, 0x401
  533.         jz      .yo1
  534.         cmp     ax, 0x451
  535.         jz      .yo2
  536.         cmp     ax, 0x410
  537.         jb      .unk
  538.         cmp     ax, 0x440
  539.         jb      .rus1
  540.         cmp     ax, 0x450
  541.         jb      .rus2
  542. .unk:
  543.         mov     al, '_'
  544.         jmp     .doit
  545. .yo1:
  546.         mov     al, 'ð'
  547.         jmp     .doit
  548. .yo2:
  549.         mov     al, 'ñ'
  550.         jmp     .doit
  551. .rus1:
  552. ; 0x410-0x43F -> 0x80-0xAF
  553.         add     al, 0x70
  554.         jmp     .doit
  555. .rus2:
  556. ; 0x440-0x44F -> 0xE0-0xEF
  557.         add     al, 0xA0
  558. .ascii:
  559. .doit:
  560.         stosb
  561.         jmp     uni2ansi_str
  562. .done:
  563.         mov     byte [edi], 0
  564.         ret
  565.  
  566. ansi2uni_char:
  567. ; convert ANSI character in al to UNICODE character in ax, using cp866 encoding
  568.         mov     ah, 0
  569. ; 0x00-0x7F - trivial map
  570.         cmp     al, 0x80
  571.         jb      .ret
  572. ; 0x80-0xAF -> 0x410-0x43F
  573.         cmp     al, 0xB0
  574.         jae     @f
  575.         add     ax, 0x410-0x80
  576. .ret:
  577.         ret
  578. @@:
  579. ; 0xE0-0xEF -> 0x440-0x44F
  580.         cmp     al, 0xE0
  581.         jb      .unk
  582.         cmp     al, 0xF0
  583.         jae     @f
  584.         add     ax, 0x440-0xE0
  585.         ret
  586. ; 0xF0 -> 0x401
  587. ; 0xF1 -> 0x451
  588. @@:
  589.         cmp     al, 'ð'
  590.         jz      .yo1
  591.         cmp     al, 'ñ'
  592.         jz      .yo2
  593. .unk:
  594.         mov     al, '_'         ; ah=0
  595.         ret
  596. .yo1:
  597.         mov     ax, 0x401
  598.         ret
  599. .yo2:
  600.         mov     ax, 0x451
  601.         ret
  602.  
  603. char_toupper:
  604. ; convert character to uppercase, using cp866 encoding
  605. ; in: al=symbol
  606. ; out: al=converted symbol
  607.         cmp     al, 'a'
  608.         jb      .ret
  609.         cmp     al, 'z'
  610.         jbe     .az
  611.         cmp     al, ' '
  612.         jb      .ret
  613.         cmp     al, 'à'
  614.         jb      .rus1
  615.         cmp     al, 'ï'
  616.         ja      .ret
  617. ; 0xE0-0xEF -> 0x90-0x9F
  618.         sub     al, 'à'-''
  619. .ret:
  620.         ret
  621. .rus1:
  622. ; 0xA0-0xAF -> 0x80-0x8F
  623. .az:
  624.         and     al, not 0x20
  625.         ret
  626.  
  627. fat_get_name:
  628. ; in: edi->FAT entry
  629. ; out: CF=1 - no valid entry
  630. ; else CF=0 and ebp->ASCIIZ-name
  631. ; (maximum length of filename is 255 (wide) symbols without trailing 0,
  632. ;  but implementation requires buffer 261 words)
  633. ; destroys eax
  634.         cmp     byte [edi], 0
  635.         jz      .no
  636.         cmp     byte [edi], 0xE5
  637.         jnz     @f
  638. .no:
  639.         stc
  640.         ret
  641. @@:
  642.         cmp     byte [edi+11], 0xF
  643.         jz      .longname
  644.         push    ecx
  645.         mov     ecx, 8
  646.         push    edi ebp ecx
  647.         cmp     byte [ebp-4], 0
  648.         jnz     .unicode_short
  649. @@:
  650.         mov     al, [edi]
  651.         inc     edi
  652.         mov     [ebp], al
  653.         inc     ebp
  654.         loop    @b
  655.         pop     ecx
  656. @@:
  657.         cmp     byte [ebp-1], ' '
  658.         jnz     @f
  659.         dec     ebp
  660.         loop    @b
  661. @@:
  662.         mov     byte [ebp], '.'
  663.         inc     ebp
  664.         mov     ecx, 3
  665.         push    ecx
  666. @@:
  667.         mov     al, [edi]
  668.         inc     edi
  669.         mov     [ebp], al
  670.         inc     ebp
  671.         loop    @b
  672.         pop     ecx
  673. @@:
  674.         cmp     byte [ebp-1], ' '
  675.         jnz     @f
  676.         dec     ebp
  677.         loop    @b
  678.         dec     ebp
  679. @@:
  680.         and     byte [ebp], 0   ; CF=0
  681.         pop     ebp edi ecx
  682.         ret
  683. .unicode_short:
  684. @@:
  685.         mov     al, [edi]
  686.         inc     edi
  687.         call    ansi2uni_char
  688.         mov     [ebp], ax
  689.         inc     ebp
  690.         inc     ebp
  691.         loop    @b
  692.         pop     ecx
  693. @@:
  694.         cmp     word [ebp-2], ' '
  695.         jnz     @f
  696.         dec     ebp
  697.         dec     ebp
  698.         loop    @b
  699. @@:
  700.         mov     word [ebp], '.'
  701.         inc     ebp
  702.         inc     ebp
  703.         mov     ecx, 3
  704.         push    ecx
  705. @@:
  706.         mov     al, [edi]
  707.         inc     edi
  708.         call    ansi2uni_char
  709.         mov     [ebp], ax
  710.         inc     ebp
  711.         inc     ebp
  712.         loop    @b
  713.         pop     ecx
  714. @@:
  715.         cmp     word [ebp-2], ' '
  716.         jnz     @f
  717.         dec     ebp
  718.         dec     ebp
  719.         loop    @b
  720.         dec     ebp
  721.         dec     ebp
  722. @@:
  723.         and     word [ebp], 0   ; CF=0
  724.         pop     ebp edi ecx
  725.         ret
  726. .longname:
  727. ; LFN
  728.         mov     al, byte [edi]
  729.         and     eax, 0x3F
  730.         dec     eax
  731.         cmp     al, 20
  732.         jae     .no     ; ignore invalid entries
  733.         mov     word [ebp+260*2], 0     ; force null-terminating for orphans
  734.         imul    eax, 13*2
  735.         add     ebp, eax
  736.         test    byte [edi], 0x40
  737.         jz      @f
  738.         mov     word [ebp+13*2], 0
  739. @@:
  740.         push    eax
  741. ; now copy name from edi to ebp ...
  742.         mov     eax, [edi+1]
  743.         mov     [ebp], eax      ; symbols 1,2
  744.         mov     eax, [edi+5]
  745.         mov     [ebp+4], eax    ; 3,4
  746.         mov     eax, [edi+9]
  747.         mov     [ebp+8], ax     ; 5
  748.         mov     eax, [edi+14]
  749.         mov     [ebp+10], eax   ; 6,7
  750.         mov     eax, [edi+18]
  751.         mov     [ebp+14], eax   ; 8,9
  752.         mov     eax, [edi+22]
  753.         mov     [ebp+18], eax   ; 10,11
  754.         mov     eax, [edi+28]
  755.         mov     [ebp+22], eax   ; 12,13
  756. ; ... done
  757.         pop     eax
  758.         sub     ebp, eax
  759.         test    eax, eax
  760.         jz      @f
  761. ; if this is not first entry, more processing required
  762.         stc
  763.         ret
  764. @@:
  765. ; if this is first entry:
  766.         cmp     byte [ebp-4], 0
  767.         jnz     .ret
  768. ; buffer at ebp contains UNICODE name, convert it to ANSI
  769.         push    esi edi
  770.         mov     esi, ebp
  771.         mov     edi, ebp
  772.         call    uni2ansi_str
  773.         pop     edi esi
  774. .ret:
  775.         clc
  776.         ret
  777.  
  778. fat_compare_name:
  779. ; compares ASCIIZ-names, case-insensitive (cp866 encoding)
  780. ; in: esi->name, ebp->name
  781. ; out: if names match: ZF=1 and esi->next component of name
  782. ;      else: ZF=0, esi is not changed
  783. ; destroys eax
  784.         push    ebp esi
  785. .loop:
  786.         mov     al, [ebp]
  787.         inc     ebp
  788.         call    char_toupper
  789.         push    eax
  790.         lodsb
  791.         call    char_toupper
  792.         cmp     al, [esp]
  793.         jnz     .done
  794.         pop     eax
  795.         test    al, al
  796.         jnz     .loop
  797.         dec     esi
  798.         pop     eax
  799.         pop     ebp
  800.         xor     eax, eax        ; set ZF flag
  801.         ret
  802. .done:
  803.         cmp     al, '/'
  804.         jnz     @f
  805.         cmp     byte [esp], 0
  806.         jnz     @f
  807.         mov     [esp+4], esi
  808. @@:
  809.         pop     eax
  810.         pop     esi ebp
  811.         ret
  812.  
  813. fat_time_to_bdfe:
  814. ; in: eax=FAT time
  815. ; out: eax=BDFE time
  816.         push    ecx edx
  817.         mov     ecx, eax
  818.         mov     edx, eax
  819.         shr     eax, 11
  820.         shl     eax, 16 ; hours
  821.         and     edx, 0x1F
  822.         add     edx, edx
  823.         mov     al, dl  ; seconds
  824.         shr     ecx, 5
  825.         and     ecx, 0x3F
  826.         mov     ah, cl  ; minutes
  827.         pop     edx ecx
  828.         ret
  829.  
  830. fat_date_to_bdfe:
  831.         push    ecx edx
  832.         mov     ecx, eax
  833.         mov     edx, eax
  834.         shr     eax, 9
  835.         add     ax, 1980
  836.         shl     eax, 16 ; year
  837.         and     edx, 0x1F
  838.         mov     al, dl  ; day
  839.         shr     ecx, 5
  840.         and     ecx, 0xF
  841.         mov     ah, cl  ; month
  842.         pop     edx ecx
  843.         ret
  844.  
  845. fat_entry_to_bdfe:
  846. ; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
  847. ; destroys eax
  848.         movzx   eax, byte [edi+11]
  849.         mov     [esi], eax      ; attributes
  850.         mov     eax, [ebp-4]
  851.         mov     [esi+4], eax    ; ASCII/UNICODE name
  852.         movzx   eax, word [edi+14]
  853.         call    fat_time_to_bdfe
  854.         mov     [esi+8], eax    ; creation time
  855.         movzx   eax, word [edi+16]
  856.         call    fat_date_to_bdfe
  857.         mov     [esi+12], eax   ; creation date
  858.         and     dword [esi+16], 0       ; last access time is not supported on FAT
  859.         movzx   eax, word [edi+18]
  860.         call    fat_date_to_bdfe
  861.         mov     [esi+20], eax   ; last access date
  862.         movzx   eax, word [edi+22]
  863.         call    fat_time_to_bdfe
  864.         mov     [esi+24], eax   ; last write time
  865.         movzx   eax, word [edi+24]
  866.         call    fat_date_to_bdfe
  867.         mov     [esi+28], eax   ; last write date
  868.         mov     eax, [edi+28]
  869.         mov     [esi+32], eax   ; file size (low dword)
  870.         xor     eax, eax
  871.         mov     [esi+36], eax   ; file size (high dword)
  872.         push    ecx edi
  873.         lea     edi, [esi+40]
  874.         mov     esi, ebp
  875.         mov     ecx, 259/2
  876.         rep     movsd
  877.         movsw
  878.         stosw
  879.         mov     esi, edi
  880.         pop     edi ecx
  881.         ret
  882.  
  883. rd_find_lfn:
  884. ; in: esi->name
  885. ; out: CF=1 - file not found
  886. ;      else CF=0 and edi->direntry
  887.         push    esi ebp edi
  888.         sub     esp, 262*2      ; allocate space for LFN
  889.         mov     ebp, esp        ; ebp points to buffer
  890.         push    0               ; for fat_get_name: read ASCII name
  891.         mov     edi, 0x100000+512*19    ; to root dir
  892. .l1:
  893.         call    fat_get_name
  894.         jc      .l2
  895.         call    fat_compare_name
  896.         jz      .found
  897. .l2:
  898.         add     edi, 0x20
  899.         cmp     edi, 0x100000+512*33
  900.         jb      .l1
  901. .notfound:
  902.         add     esp, 262*2+4
  903.         pop     edi ebp esi
  904.         stc
  905.         ret
  906. .found:
  907. ; found
  908. ; if this is LFN entry, advance to true entry
  909.         cmp     byte [edi+11], 0xF
  910.         jnz     @f
  911.         add     edi, 0x20
  912. @@:
  913. ; folders are not supported
  914.         cmp     byte [esi], 0
  915.         jnz     .notfound
  916.         add     esp, 262*2+4+4  ; CF=0
  917.         pop     ebp esi
  918.         ret
  919.  
  920. ;----------------------------------------------------------------
  921. ;
  922. ;  fs_RamdiskRead - LFN variant for reading sys floppy
  923. ;
  924. ;  esi  points to filename
  925. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  926. ;       may be ebx=0 - start from first byte
  927. ;  ecx  number of bytes to read, 0+
  928. ;  edx  mem location to return data
  929. ;
  930. ;  ret ebx = size or 0xffffffff file not found
  931. ;      eax = 0 ok read or other = errormsg
  932. ;
  933. ;--------------------------------------------------------------
  934. fs_RamdiskRead:
  935.         cmp     byte [esi], 0
  936.         jnz     @f
  937.         or      ebx, -1
  938.         mov     eax, 10         ; access denied
  939.         ret
  940. @@:
  941.         push    edi
  942.         call    rd_find_lfn
  943.         jnc     .found
  944.         pop     edi
  945.         or      ebx, -1
  946.         mov     eax, 5          ; file not found
  947.         ret
  948. .found:
  949.         test    ebx, ebx
  950.         jz      .l1
  951.         cmp     dword [ebx+4], 0
  952.         jz      @f
  953.         mov     ebx, [edi+28]
  954. .reteof:
  955.         mov     eax, 6          ; EOF
  956.         pop     edi
  957.         ret
  958. @@:
  959.         mov     ebx, [ebx]
  960. .l1:
  961.         push    dword [edi+28]          ; file size
  962.         push    dword [edi+28]
  963.         movzx   edi, word [edi+26]      ; cluster
  964.         push    ecx edx
  965. .new:
  966.         jecxz   .done
  967.         test    edi, edi
  968.         jz      .eof
  969.         cmp     edi, 0xFF8
  970.         jae     .eof
  971.         lea     eax, [edi+31]           ; bootsector+2*fat+filenames
  972.         shl     eax, 9                  ; *512
  973.         add     eax, 0x100000           ; image base
  974. ; now eax points to data of cluster
  975.         sub     ebx, 512
  976.         jae     .skip
  977.         lea     eax, [eax+ebx+512]
  978.         neg     ebx
  979.         push    ecx
  980.         cmp     ecx, ebx
  981.         jbe     @f
  982.         mov     ecx, ebx
  983. @@:
  984.         cmp     ecx, [esp+12]
  985.         jbe     @f
  986.         mov     ecx, [esp+12]
  987. @@:
  988.         mov     ebx, edx
  989.         call    memmove
  990.         add     edx, ecx
  991.         sub     [esp], ecx
  992.         sub     [esp+12], ecx
  993.         pop     ecx
  994.         xor     ebx, ebx
  995.         cmp     [esp+8], ebx
  996.         jnz     .skip
  997.         jecxz   .done
  998.         jmp     .eof
  999. .skip:
  1000.         movzx   edi, word [edi*2+0x280000]      ; find next cluster from FAT
  1001.         jmp     .new
  1002. .eof:
  1003.         pop     edx ecx ebx ebx
  1004.         jmp     .reteof
  1005. .done:
  1006.         pop     edx ecx ebx ebx edi
  1007.         xor     eax, eax
  1008.         ret
  1009.  
  1010. ;----------------------------------------------------------------
  1011. ;
  1012. ;  fs_RamdiskReadFolder - LFN variant for reading sys floppy folder
  1013. ;
  1014. ;  esi  points to filename; only root is folder on ramdisk
  1015. ;  ebx  pointer to 32-bit number = first wanted block
  1016. ;  ecx  number of blocks to read, 0+
  1017. ;  edx  mem location to return data
  1018. ;
  1019. ;  ret ebx = size or 0xffffffff file not found
  1020. ;      eax = 0 ok read or other = errormsg
  1021. ;
  1022. ;--------------------------------------------------------------
  1023. fs_RamdiskReadFolder:
  1024.         mov     ebx, [ebx]
  1025.         cmp     byte [esi], 0
  1026.         jz      @f
  1027. ; ramdisk doesn't support folders
  1028.         mov     eax, ERROR_ACCESS_DENIED
  1029.         or      ebx, -1
  1030.         ret
  1031. @@:
  1032.         push    esi edi ecx
  1033. ; init header
  1034.         push    ecx
  1035.         mov     edi, edx
  1036.         mov     ecx, 32/4
  1037.         xor     eax, eax
  1038.         rep     stosd
  1039.         mov     byte [edx], 1   ; version
  1040.         pop     ecx
  1041.         push    ebp
  1042.         sub     esp, 262*2      ; allocate space for LFN
  1043.         mov     ebp, esp
  1044.         push    1               ; for fat_get_name: read UNICODE name
  1045. ; read root
  1046.         mov     esi, edi        ; esi points to block of data of folder entry (BDFE)
  1047.         mov     edi, 0x100000+512*19
  1048. .l1:
  1049.         call    fat_get_name
  1050.         jc      .l2
  1051.         cmp     byte [edi+11], 0xF
  1052.         jnz     @f
  1053.         add     edi, 0x20
  1054. @@:
  1055.         inc     dword [edx+8]   ; new file found
  1056.         dec     ebx
  1057.         jns     .l2
  1058.         dec     ecx
  1059.         js      .l2
  1060.         inc     dword [edx+4]  ; new file block copied
  1061.         call    fat_entry_to_bdfe
  1062. .l2:
  1063.         add     edi, 0x20
  1064.         cmp     edi, 0x100000+512*33
  1065.         jb      .l1
  1066.         add     esp, 262*2+4
  1067.         pop     ebp
  1068.         mov     ebx, [edx+8]
  1069.         xor     eax, eax
  1070.         dec     ecx
  1071.         js      @f
  1072.         mov     al, ERROR_END_OF_FILE
  1073. @@:
  1074.         pop     ecx edi esi
  1075.         ret
  1076.  
  1077. ; \end{diamond}