Subversion Repositories Kolibri OS

Rev

Rev 77 | Rev 83 | 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.    mov  dword [edi+4],ebx
  35.    mov  dword [edi+8],ecx
  36.    mov  dword [edi+12],edx
  37.    add  edi,16
  38.    add  esi,12
  39.  
  40.    cmp  edi,0x280000+2856*2   ;2849 clusters
  41.    jnz  fcnew
  42.  
  43.    popad
  44.    ret
  45.  
  46.  
  47. restorefatchain:   ; restore fat chain
  48.  
  49.    pushad
  50.  
  51.    mov  esi,0x280000
  52.    mov  edi,0x100000+512
  53.  
  54.   fcnew2:
  55.    mov  eax,dword [esi]
  56.    mov  ebx,dword [esi+4]
  57.    shl  ax,4
  58.    shl  eax,4
  59.    shl  bx,4
  60.    shr  ebx,4
  61.    shrd eax,ebx,8
  62.    shr  ebx,8
  63.    mov  dword [edi],eax
  64.    mov  word [edi+4],bx
  65.    add  edi,6
  66.    add  esi,8
  67.  
  68.    cmp  edi,0x100000+512+4278     ;4274 bytes - all used FAT
  69.    jb   fcnew2
  70.  
  71.    mov  esi,0x100000+512           ; duplicate fat chain
  72.    mov  edi,0x100000+512+0x1200
  73.    mov  ecx,1069        ;4274/4
  74.    cld
  75.    rep  movsd
  76.  
  77.    popad
  78.    ret
  79.  
  80.  
  81. ramdisk_free_space:
  82. ;---------------------------------------------
  83. ;
  84. ; returns free space in edi
  85. ; rewr.by Mihasik
  86. ;---------------------------------------------
  87.  
  88.         push   eax ebx ecx
  89.  
  90.         mov  edi,0x280000 ;start of FAT
  91.         xor  ax,ax    ;Free cluster=0x0000 in FAT
  92.         xor  ebx,ebx  ;counter
  93.         mov  ecx,2849 ;2849 clusters
  94.         cld
  95.     rdfs1:
  96.         repne scasw
  97.         jnz  rdfs2    ;if last cluster not 0
  98.         inc  ebx
  99.         test    ecx, ecx
  100.         jnz     rdfs1
  101.     rdfs2:
  102.         shl  ebx,9    ;free clusters*512
  103.         mov  edi,ebx
  104.        
  105.         pop    ecx ebx eax
  106.         ret
  107.  
  108.  
  109. expand_filename:
  110. ;---------------------------------------------
  111. ;
  112. ; exapand filename with '.' to 11 character
  113. ; eax - pointer to filename
  114. ;---------------------------------------------
  115.  
  116.         push esi edi ebx
  117.  
  118.         mov  edi,esp                  ; check for '.' in the name
  119.         add  edi,12+8
  120.  
  121.         mov  esi,eax
  122.  
  123.         mov  eax,edi
  124.         mov  [eax+0],dword '    '
  125.         mov  [eax+4],dword '    '
  126.         mov  [eax+8],dword '    '
  127.  
  128.       flr1:
  129.  
  130.         cmp  [esi],byte '.'
  131.         jne  flr2
  132.         mov  edi,eax
  133.         add  edi,7
  134.         jmp  flr3
  135.  
  136.       flr2:
  137.  
  138.         mov  bl,[esi]
  139.         mov  [edi],bl
  140.  
  141.       flr3:
  142.  
  143.         inc  esi
  144.         inc  edi
  145.  
  146.         mov  ebx,eax
  147.         add  ebx,11
  148.  
  149.         cmp  edi,ebx
  150.         jbe  flr1
  151.  
  152.         pop  ebx edi esi
  153.         ret
  154.  
  155. fileread:
  156. ;----------------------------------------------------------------
  157. ;
  158. ;  fileread - sys floppy
  159. ;
  160. ;  eax  points to filename 11 chars
  161. ;  ebx  first wanted block       ; 1+ ; if 0 then set to 1
  162. ;  ecx  number of blocks to read ; 1+ ; if 0 then set to 1
  163. ;  edx  mem location to return data
  164. ;  esi  length of filename 12*X 0=root
  165. ;
  166. ;  ret ebx = size or 0xffffffff file not found
  167. ;      eax = 0 ok read or other = errormsg
  168. ;
  169. ;--------------------------------------------------------------
  170.         test   ebx,ebx ;if ebx=0 - set to 1
  171.         jnz    frfl5
  172.         inc    ebx
  173.       frfl5:
  174.         test   ecx,ecx ;if ecx=0 - set to 1
  175.         jnz    frfl6
  176.         inc    ecx
  177.       frfl6:
  178.         test   esi,esi          ; return ramdisk root
  179.         jnz    fr_noroot        ;if not root
  180.         cmp    ebx,14           ;14 clusters=root dir
  181.         ja     oorr
  182.         cmp    ecx,14
  183.         ja     oorr
  184.         jmp    fr_do
  185.       oorr:
  186.         mov    eax,5            ;out of root range (fnf)
  187.         xor    ebx,ebx
  188.         dec    ebx              ;0xffffffff
  189.         ret
  190.  
  191.       fr_do:                    ;reading rootdir
  192.         mov    edi,edx
  193.         dec    ebx
  194.         push   edx
  195.         mov    edx,ecx    
  196.         add    edx,ebx
  197.         cmp    edx,15     ;ebx+ecx=14+1
  198.         pushf
  199.         jbe    fr_do1
  200.         sub    edx,14
  201.         sub    ecx,edx
  202.       fr_do1:
  203.         shl    ebx,9
  204.         mov    esi,0x100000+512*19
  205.         add    esi,ebx
  206.         shl    ecx,7
  207.         cld
  208.         rep    movsd
  209.         popf
  210.         pop    edx
  211.         jae    fr_do2
  212.         xor    eax,eax ; ok read
  213.         xor    ebx,ebx
  214.         ret
  215.       fr_do2:        ;if last cluster
  216.         mov    eax,6  ;end of file
  217.         xor    ebx,ebx
  218.         ret
  219.  
  220.      fr_noroot:
  221.  
  222.         sub    esp,32
  223.         call   expand_filename
  224.  
  225.         dec    ebx
  226.  
  227.         push   eax
  228.  
  229.         push   eax ebx ecx edx esi edi
  230.         call   rd_findfile
  231.         je     fifound
  232.         add    esp,32+28   ;if file not found
  233.         ret
  234.  
  235.      fifound:
  236.  
  237.         mov    ebx,[edi-11+28]          ;file size
  238.         mov    [esp+20],ebx
  239.         mov    [esp+24],ebx
  240.         add    edi,0xf
  241.         movzx  eax,word [edi]
  242.         mov    edi,eax                  ;edi=cluster
  243.  
  244.       frnew:
  245.  
  246.         add    eax,31                   ;bootsector+2*fat+filenames
  247.         shl    eax,9                    ;*512
  248.         add    eax,0x100000             ;image base
  249.         mov    ebx,[esp+8]
  250.         mov    ecx,512                  ;[esp+4]
  251.  
  252.         cmp    [esp+16],dword 0         ; wanted cluster ?
  253.         jne    frfl7
  254.         call   memmove
  255.         add    [esp+8],dword 512
  256.         dec    dword [esp+12]           ; last wanted cluster ?
  257.         je     frnoread
  258.         jmp    frfl8
  259.       frfl7:
  260.         dec    dword [esp+16]
  261.       frfl8:
  262.         movzx  eax,word [edi*2+0x280000]        ; find next cluster from FAT
  263.         mov    edi,eax
  264.         cmp    edi,4095                 ;eof  - cluster
  265.         jz     frnoread2
  266.  
  267.         cmp    [esp+24],dword 512       ;eof  - size
  268.         jb     frnoread
  269.         sub    [esp+24],dword 512
  270.  
  271.         jmp    frnew
  272.  
  273.       frnoread2:
  274.  
  275.         cmp    [esp+16],dword 0         ; eof without read ?
  276.         je     frnoread
  277.  
  278.         pop    edi esi edx ecx
  279.         add    esp,4
  280.         pop    ebx     ; ebx <- eax : size of file
  281.         add    esp,36
  282.         mov    eax,6   ; end of file
  283.         ret
  284.  
  285.       frnoread:
  286.  
  287.         pop    edi esi edx ecx
  288.         add    esp,4
  289.         pop    ebx     ; ebx <- eax : size of file
  290.         add    esp,36
  291.         xor    eax,eax  ;read ok
  292.         ret
  293.  
  294. filedelete:
  295. ;--------------------------------------------
  296. ;
  297. ; filedelete - sys floppy
  298. ; in:
  299. ; eax -  pointer to filename 11 chars
  300. ;
  301. ; out:
  302. ; eax - 0 = successful, 5 = file not found
  303. ;
  304. ;--------------------------------------------
  305.  
  306.         sub    esp,32
  307.         call   expand_filename
  308.  
  309.         push   eax ebx ecx edx esi edi
  310.        
  311.         call   rd_findfile
  312.         je     fifoundd
  313.         pop    edi esi edx ecx ebx eax ;file not found
  314.         add    esp,32
  315.         mov    eax,5
  316.         ret
  317.  
  318.      fifoundd:
  319.  
  320.         mov    [edi-11],byte 0xE5       ;mark filename deleted
  321.         add    edi,0xf
  322.         movzx  eax,word [edi]
  323.         mov    edi,eax                  ;edi = cluster
  324.  
  325.       frnewd:
  326.  
  327.         shl    edi,1                    ;find next cluster from FAT
  328.         add    edi,0x280000
  329.         movzx  eax,word [edi]
  330.         mov    [edi],word 0x0           ;clear fat chain cluster
  331.         mov    edi,eax
  332.         cmp    edi,dword 0xff8          ;last cluster ?
  333.         jb     frnewd
  334.  
  335.         pop    edi esi edx ecx ebx eax
  336.         add    esp,32
  337.         xor    eax,eax       ; file found
  338.         ret
  339.  
  340.      
  341.  
  342. filesave:
  343. ;----------------------------------------------------------
  344. ;
  345. ; filesave - sys floppy
  346. ;
  347. ; eax points to filename 11 chars
  348. ;
  349. ;        eax      ; pointer to file name
  350. ;        ebx      ; buffer
  351. ;        ecx      ; count to write in bytes
  352. ;        edx      ; 0 create new , 1 append
  353. ;
  354. ;-----------------------------------------------------------
  355.  
  356.         sub  esp,32
  357.         call expand_filename
  358.         test edx,edx
  359.         jnz  fsdel
  360.         pusha
  361.         call filedelete
  362.         popa
  363.  
  364.       fsdel:
  365.  
  366.         call   ramdisk_free_space
  367.         cmp    ecx,edi
  368.         jbe    rd_do_save
  369.         add    esp,32
  370.         mov    eax,8    ;disk full
  371.         ret
  372.  
  373.       rd_do_save:
  374.  
  375.         push   eax ebx ecx edx esi edi
  376.  
  377.         mov    edi,0x100000+512*18+512  ;Point at directory
  378.         mov    edx,224 +1
  379.         ; find an empty spot for filename in the root dir
  380.      l20ds:
  381.         dec    edx
  382.         test   edx,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. fat_entry_to_bdfe:
  838. ; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
  839. ; destroys eax
  840.         movzx   eax, byte [edi+11]
  841.         mov     [esi], eax      ; attributes
  842.         mov     eax, [ebp-4]
  843.         mov     [esi+4], eax    ; ASCII/UNICODE name
  844.         movzx   eax, word [edi+14]
  845.         call    fat_time_to_bdfe
  846.         mov     [esi+8], eax    ; creation time
  847.         movzx   eax, word [edi+16]
  848.         call    fat_date_to_bdfe
  849.         mov     [esi+12], eax   ; creation date
  850.         and     dword [esi+16], 0       ; last access time is not supported on FAT
  851.         movzx   eax, word [edi+18]
  852.         call    fat_date_to_bdfe
  853.         mov     [esi+20], eax   ; last access date
  854.         movzx   eax, word [edi+22]
  855.         call    fat_time_to_bdfe
  856.         mov     [esi+24], eax   ; last write time
  857.         movzx   eax, word [edi+24]
  858.         call    fat_date_to_bdfe
  859.         mov     [esi+28], eax   ; last write date
  860.         mov     eax, [edi+28]
  861.         mov     [esi+32], eax   ; file size (low dword)
  862.         xor     eax, eax
  863.         mov     [esi+36], eax   ; file size (high dword)
  864.         push    ecx edi
  865.         lea     edi, [esi+40]
  866.         mov     esi, ebp
  867.         test    byte [esi-4], 1
  868.         jz      .ansi
  869.         mov     ecx, 260/2
  870.         rep     movsd
  871.         mov     [edi-2], ax
  872. @@:
  873.         mov     esi, edi
  874.         pop     edi ecx
  875.         ret
  876. .ansi:
  877.         mov     ecx, 264/4
  878.         rep     movsd
  879.         mov     [edi-1], al
  880.         jmp     @b
  881.  
  882. rd_find_lfn:
  883. ; in: esi->name
  884. ; out: CF=1 - file not found
  885. ;      else CF=0 and edi->direntry
  886.         push    esi ebp edi
  887.         sub     esp, 262*2      ; allocate space for LFN
  888.         mov     ebp, esp        ; ebp points to buffer
  889.         push    0               ; for fat_get_name: read ASCII name
  890.         mov     edi, 0x100000+512*19    ; to root dir
  891. .l1:
  892.         call    fat_get_name
  893.         jc      .l2
  894.         call    fat_compare_name
  895.         jz      .found
  896. .l2:
  897.         add     edi, 0x20
  898.         cmp     edi, 0x100000+512*33
  899.         jb      .l1
  900. .notfound:
  901.         add     esp, 262*2+4
  902.         pop     edi ebp esi
  903.         stc
  904.         ret
  905. .found:
  906. ; found
  907. ; if this is LFN entry, advance to true entry
  908.         cmp     byte [edi+11], 0xF
  909.         jnz     @f
  910.         add     edi, 0x20
  911. @@:
  912. ; folders are not supported
  913.         cmp     byte [esi], 0
  914.         jnz     .notfound
  915.         add     esp, 262*2+4+4  ; CF=0
  916.         pop     ebp esi
  917.         ret
  918.  
  919. ;----------------------------------------------------------------
  920. ;
  921. ;  fs_RamdiskRead - LFN variant for reading sys floppy
  922. ;
  923. ;  esi  points to filename
  924. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  925. ;       may be ebx=0 - start from first byte
  926. ;  ecx  number of bytes to read, 0+
  927. ;  edx  mem location to return data
  928. ;
  929. ;  ret ebx = bytes read or 0xffffffff file not found
  930. ;      eax = 0 ok read or other = errormsg
  931. ;
  932. ;--------------------------------------------------------------
  933. fs_RamdiskRead:
  934.         cmp     byte [esi], 0
  935.         jnz     @f
  936.         or      ebx, -1
  937.         mov     eax, 10         ; access denied
  938.         ret
  939. @@:
  940.         push    edi
  941.         call    rd_find_lfn
  942.         jnc     .found
  943.         pop     edi
  944.         or      ebx, -1
  945.         mov     eax, 5          ; file not found
  946.         ret
  947. .found:
  948.         test    ebx, ebx
  949.         jz      .l1
  950.         cmp     dword [ebx+4], 0
  951.         jz      @f
  952.         xor     ebx, ebx
  953. .reteof:
  954.         mov     eax, 6          ; EOF
  955.         pop     edi
  956.         ret
  957. @@:
  958.         mov     ebx, [ebx]
  959. .l1:
  960.         push    ecx edx
  961.         push    0
  962.         mov     eax, [edi+28]
  963.         sub     eax, ebx
  964.         jb      .eof
  965.         cmp     eax, ecx
  966.         jae     @f
  967.         mov     ecx, eax
  968.         mov     byte [esp], 6           ; EOF
  969. @@:
  970.         movzx   edi, word [edi+26]      ; cluster
  971. .new:
  972.         jecxz   .done
  973.         test    edi, edi
  974.         jz      .eof
  975.         cmp     edi, 0xFF8
  976.         jae     .eof
  977.         lea     eax, [edi+31]           ; bootsector+2*fat+filenames
  978.         shl     eax, 9                  ; *512
  979.         add     eax, 0x100000           ; image base
  980. ; now eax points to data of cluster
  981.         sub     ebx, 512
  982.         jae     .skip
  983.         lea     eax, [eax+ebx+512]
  984.         neg     ebx
  985.         push    ecx
  986.         cmp     ecx, ebx
  987.         jbe     @f
  988.         mov     ecx, ebx
  989. @@:
  990.         mov     ebx, edx
  991.         call    memmove
  992.         add     edx, ecx
  993.         sub     [esp], ecx
  994.         pop     ecx
  995.         xor     ebx, ebx
  996. .skip:
  997.         movzx   edi, word [edi*2+0x280000]      ; find next cluster from FAT
  998.         jmp     .new
  999. .eof:
  1000.         mov     ebx, edx
  1001.         pop     eax edx ecx
  1002.         sub     ebx, edx
  1003.         jmp     .reteof
  1004. .done:
  1005.         mov     ebx, edx
  1006.         pop     eax edx ecx edi
  1007.         sub     ebx, edx
  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 structure 32-bit number = first wanted block
  1016. ;                          & flags (bitfields)
  1017. ; flags: bit 0: 0=ANSI names, 1=UNICODE names
  1018. ;  ecx  number of blocks to read, 0+
  1019. ;  edx  mem location to return data
  1020. ;
  1021. ;  ret ebx = size or 0xffffffff file not found
  1022. ;      eax = 0 ok read or other = errormsg
  1023. ;
  1024. ;--------------------------------------------------------------
  1025. fs_RamdiskReadFolder:
  1026.         cmp     byte [esi], 0
  1027.         jz      @f
  1028. ; ramdisk doesn't support folders
  1029.         mov     eax, ERROR_ACCESS_DENIED
  1030.         or      ebx, -1
  1031.         ret
  1032. @@:
  1033.         push    esi edi ecx
  1034. ; init header
  1035.         push    ecx
  1036.         mov     edi, edx
  1037.         mov     ecx, 32/4
  1038.         xor     eax, eax
  1039.         rep     stosd
  1040.         mov     byte [edx], 1   ; version
  1041.         pop     ecx
  1042.         push    ebp
  1043.         sub     esp, 262*2      ; allocate space for LFN
  1044.         mov     ebp, esp
  1045.         push    dword [ebx+4]   ; for fat_get_name: read ANSI/UNICODE name
  1046.         mov     ebx, [ebx]
  1047. ; read root
  1048.         mov     esi, edi        ; esi points to block of data of folder entry (BDFE)
  1049.         mov     edi, 0x100000+512*19
  1050. .l1:
  1051.         call    fat_get_name
  1052.         jc      .l2
  1053.         cmp     byte [edi+11], 0xF
  1054.         jnz     @f
  1055.         add     edi, 0x20
  1056. @@:
  1057.         inc     dword [edx+8]   ; new file found
  1058.         dec     ebx
  1059.         jns     .l2
  1060.         dec     ecx
  1061.         js      .l2
  1062.         inc     dword [edx+4]  ; new file block copied
  1063.         call    fat_entry_to_bdfe
  1064. .l2:
  1065.         add     edi, 0x20
  1066.         cmp     edi, 0x100000+512*33
  1067.         jb      .l1
  1068.         add     esp, 262*2+4
  1069.         pop     ebp
  1070.         mov     ebx, [edx+4]
  1071.         xor     eax, eax
  1072.         dec     ecx
  1073.         js      @f
  1074.         mov     al, ERROR_END_OF_FILE
  1075. @@:
  1076.         pop     ecx edi esi
  1077.         ret
  1078.  
  1079. ; \end{diamond}
  1080.