Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                      ;;
  3. ;; FAT12.INC                                                            ;;
  4. ;; (C) 2005 Mario79, License: GPL                                       ;;
  5. ;;                                                                      ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. n_sector    dd 0  ; temporary save for sector value
  9. flp_status  dd 0
  10. clust_tmp_flp dd 0  ; used by analyze_directory and analyze_directory_to_write
  11. path_pointer_flp dd 0
  12. pointer_file_name_flp dd 0
  13. save_root_flag db 0
  14. save_flag   db 0
  15. root_read   db 0  ; 0-necessary to load root, 1-not to load root
  16. flp_fat     db 0  ; 0-necessary to load fat, 1-not to load fat
  17. flp_number  db 0  ; 1- Floppy A, 2-Floppy B
  18. old_track   db 0  ; old value track
  19. flp_label   rb 15 ; Label and ID of inserted floppy disk
  20.  
  21. reserve_flp:
  22.  
  23.     cli
  24.     cmp   [flp_status],0
  25.     je    reserve_flp_ok
  26.  
  27.     sti
  28.     call  change_task
  29.     jmp   reserve_flp
  30.  
  31.   reserve_flp_ok:
  32.  
  33.     push  eax
  34.     mov   eax,[CURRENT_TASK]
  35.     shl   eax,5
  36.     mov   eax,[eax+CURRENT_TASK+TASKDATA.pid]
  37.     mov   [flp_status],eax
  38.     pop   eax
  39.     sti
  40.     ret
  41.  
  42. floppy_free_space:
  43. ;---------------------------------------------
  44. ;
  45. ; returns free space in edi
  46. ;
  47. ;---------------------------------------------
  48.     push   eax ebx ecx
  49.     call   read_flp_fat
  50.     cmp    [FDC_Status],0
  51.     jne    fdc_status_error_2
  52.     mov    eax,0x282004
  53.     xor    edi,edi
  54.     mov    ecx,2847   ;1448000/512
  55. rdfs1_1:
  56.     mov    ebx,[eax]
  57.     and    ebx,4095
  58.     jne    rdfs2_1
  59.     add    edi,512
  60. rdfs2_1:
  61.     add    eax,2
  62.     loop   rdfs1_1
  63. fdc_status_error_2:
  64.     pop    ecx ebx eax
  65.     ret
  66.  
  67.  
  68.  
  69.  
  70. floppy_fileread:
  71. ;----------------------------------------------------------------
  72. ;
  73. ;  fileread - sys floppy
  74. ;
  75. ;  eax  points to filename 11 chars  - for root directory
  76. ;  ebx  first wanted block       ; 1+ ; if 0 then set to 1
  77. ;  ecx  number of blocks to read ; 1+ ; if 0 then set to 1
  78. ;  edx  mem location to return data
  79. ;  esi  length of filename 12*X
  80. ;  edi  pointer to path   /fd/1/......  - for all files in nested directories
  81. ;
  82. ;  ret ebx = size or 0xffffffff file not found
  83. ;      eax = 0 ok read or other = errormsg
  84. ;            10 = access denied
  85. ;--------------------------------------------------------------
  86.  
  87.     mov    [save_flag],0
  88.     mov    [path_pointer_flp],edi
  89.     cmp    esi,0           ; return ramdisk root
  90.     jne    fr_noroot_1
  91.     cmp    ebx,224/16
  92.     jbe    fr_do_1
  93.     mov    eax,5
  94.     mov    ebx,0
  95.     mov   [flp_status],0
  96.     ret
  97.  
  98. fr_do_1:
  99.     push ebx ecx edx
  100.     call  read_flp_root
  101.     pop edx ecx ebx
  102.     cmp    [FDC_Status],0
  103.     jne    fdc_status_error_1
  104.     mov    edi,edx
  105.     dec    ebx
  106.     shl    ebx,9
  107.     mov    esi,FLOPPY_BUFF
  108.     add    esi,ebx
  109.     shl    ecx,9
  110.     cld
  111.     rep    movsb
  112.     mov    eax,0 ; ok read
  113.     mov    ebx,0
  114.     mov   [flp_status],0
  115.     ret
  116. fdc_status_error_1:
  117.     mov   [flp_status],0
  118.     mov    eax,10
  119.     mov    ebx,-1
  120.     ret
  121.  
  122. fr_noroot_1:
  123.     sub    esp,32
  124.     call   expand_filename
  125. frfloppy_1:
  126.     cmp    ebx,0
  127.     jne    frfl5_1
  128.     mov    ebx,1
  129. frfl5_1:
  130.     cmp    ecx,0
  131.     jne    frfl6_1
  132.     mov    ecx,1
  133. frfl6_1:
  134.     dec    ebx
  135.     push   eax
  136.     push   eax ebx ecx edx esi edi
  137.     call   read_flp_fat
  138.     cmp    [FDC_Status],0
  139.     jne    fdc_status_error_3_1
  140.     mov    [FDD_Track],0      ; Öèëèíäð
  141.     mov    [FDD_Head],1      ; Ñòîðîíà
  142.     mov    [FDD_Sector],2      ; Ñåêòîð
  143.     call    SeekTrack
  144.     mov     dh,14
  145. l.20_1:
  146.     call    ReadSectWithRetr
  147.     cmp    [FDC_Status],0
  148.     jne    fdc_status_error_3_1
  149.     mov     dl,16
  150.     mov     edi,FDD_BUFF
  151.     inc     [FDD_Sector]
  152. l.21_1:
  153.     mov    esi,eax            ;Name of file we want
  154.     mov    ecx,11
  155.     cld
  156.     rep    cmpsb            ;Found the file?
  157.     je     fifound_1          ;Yes
  158.     add    ecx,21
  159.     add    edi, ecx         ;Advance to next entry
  160.     dec    dl
  161.     cmp    dl,0
  162.     jne    l.21_1
  163.     dec    dh
  164.     cmp    dh,0
  165.     jne    l.20_1
  166. fdc_status_error_3:
  167.     mov    eax,5            ; file not found ?
  168.     mov    ebx,-1
  169.     add    esp,32+28
  170.     mov   [flp_status],0
  171.     ret
  172. fdc_status_error_3_2:
  173.     cmp    [FDC_Status],0
  174.     je    fdc_status_error_3
  175. fdc_status_error_3_1:
  176.     add    esp,32+28
  177.     jmp    fdc_status_error_1
  178.  
  179. fifound_1:
  180.     mov    eax,[path_pointer_flp]
  181.     cmp    [eax+36],byte 0
  182.     je     fifound_2
  183.     add    edi,0xf
  184.     mov    eax,[edi]
  185.     and    eax,65535
  186.     mov    ebx,[path_pointer_flp]
  187.     add    ebx,36
  188.     call   get_cluster_of_a_path_flp
  189.     jc     fdc_status_error_3_2
  190.     mov    ebx,[ebx-11+28]        ;file size
  191.     mov    [esp+20],ebx
  192.     mov    [esp+24],ebx
  193.     jmp     fifound_3
  194. fifound_2:
  195.     mov    ebx,[edi-11+28]        ;file size
  196.     mov    [esp+20],ebx
  197.     mov    [esp+24],ebx
  198.     add    edi,0xf
  199.     mov    eax,[edi]
  200. fifound_3:
  201.     and    eax,65535
  202.     mov    [n_sector],eax            ;eax=cluster
  203. frnew_1:
  204.     add    eax,31            ;bootsector+2*fat+filenames
  205.     cmp    [esp+16],dword 0     ; wanted cluster ?
  206.     jne    frfl7_1
  207.     call   read_chs_sector
  208.     cmp    [FDC_Status],0
  209.     jne    fdc_status_error_5
  210.     mov    edi,[esp+8]
  211.     call    give_back_application_data_1
  212.     add    [esp+8],dword 512
  213.     dec    dword [esp+12]        ; last wanted cluster ?
  214.     cmp    [esp+12],dword 0
  215.     je     frnoread_1
  216.     jmp    frfl8_1
  217. frfl7_1:
  218.     dec    dword [esp+16]
  219. frfl8_1:
  220.     mov    edi,[n_sector]
  221.     shl    edi,1            ;find next cluster from FAT
  222.     add    edi,0x282000
  223.     mov    eax,[edi]
  224.     and    eax,4095
  225.     mov    edi,eax
  226.     mov    [n_sector],edi
  227.     cmp    edi,4095         ;eof  - cluster
  228.     jz     frnoread2_1
  229.     cmp    [esp+24],dword 512    ;eof  - size
  230.     jb     frnoread_1
  231.     sub    [esp+24],dword 512
  232.     jmp    frnew_1
  233.  
  234. read_chs_sector:
  235.     call    calculate_chs
  236.     call    ReadSectWithRetr
  237.     ret
  238.  
  239. frnoread2_1:
  240.     cmp    [esp+16],dword 0     ; eof without read ?
  241.     je     frnoread_1
  242.     mov    [fdc_irq_func],fdc_null
  243.     pop    edi esi edx ecx
  244.     add    esp,4
  245.     pop    ebx     ; ebx <- eax : size of file
  246.     add    esp,36
  247.     mov    eax,6   ; end of file
  248.     mov    [flp_status],0
  249.     ret
  250.  
  251. frnoread_1:
  252.     pop    edi esi edx ecx
  253.     add    esp,4
  254.     pop    ebx     ; ebx <- eax : size of file
  255.     add    esp,36
  256.     mov    eax,0
  257.     mov    [flp_status],0
  258.     ret
  259.  
  260. fdc_status_error_5:
  261.     pop    edi esi edx ecx
  262.     add    esp,4
  263.     pop    ebx     ; ebx <- eax : size of file
  264.     add    esp,36
  265.     jmp    fdc_status_error_1
  266.  
  267. read_flp_root:
  268.     pusha
  269.     call  check_label
  270.     cmp    [FDC_Status],0
  271.     jne    unnecessary_root_read
  272.     cmp   [root_read],1
  273.     je    unnecessary_root_read
  274.     mov    [FDD_Track],0      ; Öèëèíäð
  275.     mov    [FDD_Head],1      ; Ñòîðîíà
  276.     mov    [FDD_Sector],2      ; Ñåêòîð
  277.     mov    edi,FLOPPY_BUFF
  278.     call   SeekTrack
  279. read_flp_root_1:
  280.     call   ReadSectWithRetr
  281.     cmp    [FDC_Status],0
  282.     jne    unnecessary_root_read
  283.     push   edi
  284.     call   give_back_application_data_1
  285.     pop    edi
  286.     add    edi,512
  287.     inc    [FDD_Sector]
  288.     cmp    [FDD_Sector],16
  289.     jne    read_flp_root_1
  290.     mov    [root_read],1
  291. unnecessary_root_read:
  292.     popa
  293.     ret
  294.  
  295.  
  296. read_flp_fat:
  297.     pusha
  298.     call  check_label
  299.     cmp    [FDC_Status],0
  300.     jne    unnecessary_flp_fat
  301.     cmp   [flp_fat],1
  302.     je    unnecessary_flp_fat
  303.     mov    [FDD_Track],0      ; Öèëèíäð
  304.     mov    [FDD_Head],0      ; Ñòîðîíà
  305.     mov    [FDD_Sector],2      ; Ñåêòîð
  306.     mov    edi,FLOPPY_BUFF
  307.     call   SeekTrack
  308. read_flp_fat_1:
  309.     call   ReadSectWithRetr
  310.     cmp    [FDC_Status],0
  311.     jne    unnecessary_flp_fat
  312.     push   edi
  313.     call   give_back_application_data_1
  314.     pop    edi
  315.     add    edi,512
  316.     inc    [FDD_Sector]
  317.     cmp    [FDD_Sector],19
  318.     jne    read_flp_fat_1
  319.     mov    [FDD_Sector],1
  320.     mov    [FDD_Head],1
  321.     call   ReadSectWithRetr
  322.     cmp    [FDC_Status],0
  323.     jne    unnecessary_flp_fat
  324.     call   give_back_application_data_1
  325.     call   calculatefatchain_flp
  326.     mov    [root_read],0
  327.     mov    [flp_fat],1
  328. unnecessary_flp_fat:
  329.     popa
  330.     ret
  331.  
  332. calculatefatchain_flp:
  333.    pushad
  334.  
  335.    mov  esi,FLOPPY_BUFF
  336.    mov  edi,0x282000
  337.  
  338.  fcnew_1:
  339.    mov  eax,dword [esi]
  340.    mov  ebx,dword [esi+4]
  341.    mov  ecx,dword [esi+8]
  342.    mov  edx,ecx
  343.    shr  edx,4   ;8 ok
  344.    shr  dx,4    ;7 ok
  345.    xor  ch,ch
  346.    shld ecx,ebx,20 ;6 ok
  347.    shr  cx,4     ;5 ok
  348.    shld ebx,eax,12
  349.    and  ebx,0x0fffffff  ;4 ok
  350.    shr  bx,4    ;3 ok
  351.    shl  eax,4
  352.    and  eax,0x0fffffff  ;2 ok
  353.    shr  ax,4  ;1 ok
  354.    mov dword [edi],eax
  355.    add  edi,4
  356.    mov dword [edi],ebx
  357.    add  edi,4
  358.    mov dword [edi],ecx
  359.    add  edi,4
  360.    mov dword [edi],edx
  361.    add  edi,4
  362.    add  esi,12
  363.  
  364.    cmp  edi,0x282000+2856*2   ;2849 clusters
  365.    jnz  fcnew_1
  366.  
  367.    popad
  368.    ret
  369.  
  370. check_label:
  371.     pushad
  372.     mov    [FDD_Track],0      ; Öèëèíäð
  373.     mov    [FDD_Head],0      ; Ñòîðîíà
  374.     mov    [FDD_Sector],1      ; Ñåêòîð
  375.     call   SetUserInterrupts
  376.     call   FDDMotorON
  377.     call   RecalibrateFDD
  378.     cmp    [FDC_Status],0
  379.     jne    fdc_status_error
  380.     call   SeekTrack
  381.     cmp    [FDC_Status],0
  382.     jne    fdc_status_error
  383.     call   ReadSectWithRetr
  384.     cmp    [FDC_Status],0
  385.     jne    fdc_status_error
  386.     mov    esi,flp_label
  387.     mov    edi,FDD_BUFF+39
  388.     mov    ecx,15
  389.     cld
  390.     rep    cmpsb
  391.     je     same_label
  392.     mov    [root_read],0
  393.     mov    [flp_fat],0
  394. same_label:
  395.     mov    esi,FDD_BUFF+39
  396.     mov    edi,flp_label
  397.     mov    ecx,15
  398.     cld
  399.     rep    movsb
  400.     popad
  401.     ret
  402. fdc_status_error:
  403.     popad
  404.     ret
  405.  
  406. save_flp_root:
  407.     pusha
  408.     call  check_label
  409.     cmp    [FDC_Status],0
  410.     jne    unnecessary_root_save
  411.     cmp   [root_read],0
  412.     je    unnecessary_root_save
  413.     mov    [FDD_Track],0      ; Öèëèíäð
  414.     mov    [FDD_Head],1      ; Ñòîðîíà
  415.     mov    [FDD_Sector],2      ; Ñåêòîð
  416.     mov    esi,FLOPPY_BUFF
  417.     call   SeekTrack
  418. save_flp_root_1:
  419.     push   esi
  420.     call   take_data_from_application_1
  421.     pop    esi
  422.     add    esi,512
  423.     call   WriteSectWithRetr
  424.     cmp    [FDC_Status],0
  425.     jne    unnecessary_root_save
  426.     inc    [FDD_Sector]
  427.     cmp    [FDD_Sector],16
  428.     jne    save_flp_root_1
  429. unnecessary_root_save:
  430.     mov    [fdc_irq_func],fdc_null
  431.     popa
  432.     ret
  433.  
  434. save_flp_fat:
  435.     pusha
  436.     call  check_label
  437.     cmp    [FDC_Status],0
  438.     jne    unnecessary_flp_fat_save
  439.     cmp   [flp_fat],0
  440.     je    unnecessary_flp_fat_save
  441.     call   restorefatchain_flp
  442.     mov    [FDD_Track],0      ; Öèëèíäð
  443.     mov    [FDD_Head],0      ; Ñòîðîíà
  444.     mov    [FDD_Sector],2      ; Ñåêòîð
  445.     mov    esi,FLOPPY_BUFF
  446.     call   SeekTrack
  447. save_flp_fat_1:
  448.     push   esi
  449.     call   take_data_from_application_1
  450.     pop    esi
  451.     add    esi,512
  452.     call   WriteSectWithRetr
  453.     cmp    [FDC_Status],0
  454.     jne    unnecessary_flp_fat_save
  455.     inc    [FDD_Sector]
  456.     cmp    [FDD_Sector],19
  457.     jne    save_flp_fat_1
  458.     mov    [FDD_Sector],1
  459.     mov    [FDD_Head],1
  460.     call   take_data_from_application_1
  461.     call   WriteSectWithRetr
  462.     cmp    [FDC_Status],0
  463.     jne    unnecessary_flp_fat_save
  464.     mov    [root_read],0
  465. unnecessary_flp_fat_save:
  466.     mov    [fdc_irq_func],fdc_null
  467.     popa
  468.     ret
  469.  
  470.  
  471. restorefatchain_flp:   ; restore fat chain
  472.    pushad
  473.  
  474.    mov  esi,0x282000
  475.    mov  edi,FLOPPY_BUFF
  476.  
  477.   fcnew2_1:
  478.    mov  eax,dword [esi]
  479.    mov  ebx,dword [esi+4]
  480.    shl  ax,4
  481.    shl  eax,4
  482.    shl  bx,4
  483.    shr  ebx,4
  484.    shrd eax,ebx,8
  485.    shr  ebx,8
  486.    mov dword [edi],eax
  487.    add  edi,4
  488.    mov word [edi],bx
  489.    add  edi,2
  490.    add  esi,8
  491.  
  492.    cmp  edi,FLOPPY_BUFF+0x1200     ;4274 bytes - all used FAT
  493.    jb   fcnew2_1
  494.  
  495.    mov  esi,FLOPPY_BUFF           ; duplicate fat chain
  496.    mov  edi,FLOPPY_BUFF+0x1200
  497.    mov  ecx,0x1200/4
  498.    cld
  499.    rep  movsd
  500.  
  501.    popad
  502.    ret
  503.  
  504.  
  505. floppy_filedelete:
  506. ;--------------------------------------------
  507. ;
  508. ; filedelete - sys floppy
  509. ; in:
  510. ; eax - filename 11 chars - for root directory
  511. ; edi  pointer to path   /fd/1/...... - for all files in nested directories
  512. ;
  513. ; out:
  514. ; eax - 0 = successful, 1 = file not found, 10 = access denied
  515. ;
  516. ;--------------------------------------------
  517.     mov    [path_pointer_flp],edi
  518.     mov    [save_flag],0
  519.     mov    ebp,1  ; file not found as default
  520. filedelete_newtry_1:
  521.     sub    esp,32
  522.     call   expand_filename
  523.     push   eax ebx ecx edx esi edi
  524.     call   read_flp_fat
  525.     cmp    [FDC_Status],0
  526.     jne    frnoreadd_1
  527.     mov    [FDD_Track],0      ; Öèëèíäð
  528.     mov    [FDD_Head],1      ; Ñòîðîíà
  529.     mov    [FDD_Sector],2      ; Ñåêòîð
  530.     call    SeekTrack
  531.     mov     dh,14
  532. l.20_2:
  533.     call    ReadSectWithRetr
  534.     cmp    [FDC_Status],0
  535.     jne    fdc_status_error_4
  536.     mov     dl,16
  537.     mov     edi,FDD_BUFF
  538.     inc     [FDD_Sector]
  539. l.21_2:
  540.     mov    esi,eax            ;Name of file we want
  541.     mov    ecx,11
  542.     cld
  543.     rep    cmpsb            ;Found the file?
  544.     je     fifoundd_1          ;Yes
  545.     add    ecx,21
  546.     add    edi, ecx         ;Advance to next entry
  547.     dec    dl
  548.     jne    l.21_2
  549.     dec    dh
  550.     jne    l.20_2
  551.     jmp    frnoreadd_1
  552.  
  553. fdc_status_error_4:
  554.     pop    edi esi edx ecx ebx eax
  555.     add    esp,32
  556.     jmp    fdc_status_error_1
  557.  
  558. fifoundd_1:
  559.     mov    eax,[path_pointer_flp]
  560.     cmp    [eax+36],byte 0
  561.     je    fifoundd_2
  562.     movzx  eax, word [edi+0xf]
  563.     mov    ebx,[path_pointer_flp]
  564.     add    ebx,36
  565.     call   get_cluster_of_a_path_flp
  566.     jc     frnoreadd_1_1
  567.     mov    edi,ebx
  568.     add    edi,11
  569.     jmp    fifoundd_2_1
  570. fifoundd_2:
  571.     dec    [FDD_Sector]
  572. fifoundd_2_1:
  573.     mov    [edi-11],byte 0xE5    ;mark filename deleted
  574.         movzx   edi, word [edi+0xf] ;edi = cluster
  575. frnewd_1:
  576.     shl    edi,1            ;find next cluster from FAT
  577.     add    edi,0x282000
  578.     mov    eax,[edi]
  579.     mov    [edi],word 0x0        ;clear fat chain cluster
  580.     and    eax,4095
  581.     mov    edi,eax
  582.     cmp    edi,dword 4095        ;last cluster ?
  583.     jz     frnoreadd2_1
  584.     jmp    frnewd_1
  585.  
  586. frnoreadd2_1:
  587.     call   WriteSectWithRetr
  588.     cmp    [FDC_Status],0
  589.     jne    fdc_status_error_4
  590.     call   save_flp_fat
  591.     cmp    [FDC_Status],0
  592.     jne    fdc_status_error_4
  593. ;    pop    edi esi edx ecx ebx eax
  594. ;    add    esp,32
  595.     mov    ebp,0       ; file found
  596. ;    jmp    filedelete_newtry_1
  597.     jmp    frnoreadd_1
  598.  
  599. frnoreadd_1_1:
  600.     cmp    [FDC_Status],0
  601.     jne    fdc_status_error_4
  602. frnoreadd_1:
  603.     pop    edi esi edx ecx ebx eax
  604.     add    esp,32
  605.     mov    eax,ebp
  606.     ret
  607.  
  608. floppy_filesave:
  609. ;----------------------------------------------------------
  610. ;
  611. ; filesave - sys floppy
  612. ;
  613. ; eax      ; pointer to file name 11 chars - for root directory
  614. ; ebx      ; buffer
  615. ; ecx      ; count to write in bytes
  616. ; edx      ; 0 create new , 1 append
  617. ; edi  pointer to path   /fd/1/......  - for all files in nested directories
  618. ;
  619. ; output : eax = 0 - ok
  620. ;                5 - file not found / directory not found
  621. ;                8 - disk full
  622. ;               10 - access denied
  623. ;-----------------------------------------------------------
  624.     mov    [path_pointer_flp],edi
  625.     sub  esp,32
  626.     call expand_filename
  627.     cmp  edx,0
  628.     jnz  fsdel_1
  629.     pusha
  630.     call floppy_filedelete
  631.     cmp    [FDC_Status],0
  632.     jne    fdc_status_error_6
  633.     popa
  634.     mov    [save_flag],1
  635. fsdel_1:
  636.     call   floppy_free_space
  637.     cmp    [FDC_Status],0
  638.     jne    fdc_status_error_6
  639.     cmp    ecx,edi
  640.     jb     rd_do_save_1
  641.     add    esp,32
  642.     mov    eax,8    ; not enough free space
  643.     mov   [flp_status],0
  644.     ret
  645.  
  646. fdc_status_error_6:
  647.     popa
  648.     add    esp,32
  649.     jmp    fdc_status_error_1
  650.  
  651. rd_do_save_1:
  652.     push   eax ebx ecx edx esi edi
  653.     call   read_flp_fat
  654.     cmp    [FDC_Status],0
  655.     jne    fdc_status_error_7
  656.     push   eax
  657.     mov    eax,[path_pointer_flp]
  658.     cmp    [eax+36],byte 0
  659.     jne    fifoundds_2
  660.     pop    eax
  661.     mov    [save_root_flag],1
  662.     call   read_flp_root
  663.     cmp    [FDC_Status],0
  664.     jne    fdc_status_error_7
  665.     mov    edi,FLOPPY_BUFF   ;Point at directory
  666.     mov    edx,224 +1
  667.     ; find an empty spot for filename in the root dir
  668. l20ds_1:
  669.     sub    edx,1
  670.     jz     frnoreadds_1
  671. l21ds_1:
  672.     cmp    [edi],byte 0xE5
  673.     jz     fifoundds_1
  674.     cmp    [edi],byte 0x0
  675.     jz     fifoundds_1
  676.     add    edi,32            ; Advance to next entry
  677.     jmp    l20ds_1
  678.  
  679. fifoundds_2:
  680.     pop    eax
  681.     mov    [save_root_flag],0
  682.     mov    [FDD_Track],0      ; Öèëèíäð
  683.     mov    [FDD_Head],1       ; Ñòîðîíà
  684.     mov    [FDD_Sector],2      ; Ñåêòîð
  685.     call   SeekTrack
  686.     mov    dh,14
  687. l.20_3:
  688.     call    ReadSectWithRetr
  689.     cmp    [FDC_Status],0
  690.     jne    fdc_status_error_7
  691.     mov    dl,16
  692.     mov    edi,FDD_BUFF
  693.     inc     [FDD_Sector]
  694. l.21_3:
  695.     mov    esi,eax            ;Name of file we want
  696.     mov    ecx,11
  697.     cld
  698.     rep    cmpsb            ;Found the file?
  699.     je     fifoundds_3          ;Yes
  700.     add    ecx,21
  701.     add    edi, ecx         ;Advance to next entry
  702.     dec    dl
  703.     jne    l.21_3
  704.     dec    dh
  705.     jne    l.20_3
  706. fdc_status_error_8:
  707.     pop     edi esi edx ecx ebx eax
  708.     mov    eax,5            ; file not found ?
  709.     mov    ebx,-1
  710.     add    esp,32
  711.     mov    [flp_status],0
  712.     ret
  713.  
  714. fifoundds_3:
  715.     add    edi,0xf
  716.     mov    eax,[edi]
  717.     and    eax,65535
  718.     mov    ebx,[path_pointer_flp]
  719.     add    ebx,36
  720.     call   get_cluster_of_a_path_flp
  721.     jc     fdc_status_error_7_1
  722. found_directory_for_writing_flp:
  723.     call   analyze_directory_to_write_flp
  724.     jc     fdc_status_error_7_1
  725.     mov    edi,ebx
  726. fifoundds_1:
  727.     push   edi            ; move the filename to root dir
  728.     mov    esi,[esp+4+20]
  729.     cmp    [save_root_flag],0
  730.     jne    fifoundds_4
  731.     mov    esi,[pointer_file_name_flp]
  732. fifoundds_4:
  733.     mov    ecx,11
  734.     cld
  735.     rep    movsb
  736.     pop    edi
  737.     mov    edx,edi
  738.     add    edx,11+0xf        ; edx <- cluster save position
  739.     mov    ebx,[esp+12]        ; save file size
  740.     mov    [edi+28],ebx
  741.     mov    [edi+11],byte 0x20    ; attribute
  742.     call   get_date_for_file     ; from FAT32.INC
  743.     mov    [edi+24],ax      ; date
  744.     mov    [edi+18],ax      ; date
  745.     call   get_time_for_file     ; from FAT32.INC
  746.     mov    [edi+22],ax      ; time
  747.     xor    ax,ax
  748.     mov    [edi+20],ax
  749.     mov    ebx,1            ; first cluster
  750.     cmp    [save_root_flag],0
  751.     jne    frnewds_1
  752.     call   frnewds_2
  753.     pusha
  754.     call   WriteSectWithRetr
  755.     popa
  756.     cmp    [FDC_Status],0
  757.     jne    fdc_status_error_7
  758.     jmp    frnewds_3
  759.  
  760. frnewds_1:
  761.     call   frnewds_2
  762. frnewds_3:
  763.     pusha                ; move save to floppy cluster
  764.     add    ebx,31
  765.     mov    eax,ebx
  766.     mov    esi,[esp+32+16]
  767.     call   take_data_from_application_1
  768.     call   save_chs_sector
  769.     cmp    [FDC_Status],0
  770.     jne    fdc_status_error_7
  771.     popa
  772.     mov    eax,[esp+12]
  773.     cmp    eax,512
  774.     jb     flnsa_1
  775.     sub    eax,512
  776.     mov    [esp+12],eax
  777.     mov    eax,[esp+16]
  778.     add    eax,512
  779.     mov    [esp+16],eax
  780.     jmp    frnewds_1
  781.  
  782. frnewds_2:
  783.     add    ebx,1
  784.     mov    edi,ebx            ; find free cluster in FAT
  785.     shl    edi,1
  786.     add    edi,0x282000
  787.     mov    eax,[edi]
  788.     and    eax,4095
  789.     jnz    frnewds_2
  790.     mov    [edx],bx         ; save next cluster pos. to prev cl.
  791.     mov    edx,edi            ; next save pos abs mem add
  792.     ret
  793.  
  794. flnsa_1:
  795.     mov    [edi],word 4095        ; mark end of file - last cluster
  796.     cmp    [save_root_flag],1
  797.     jne    flnsa_2
  798.     call   save_flp_root
  799.     cmp    [FDC_Status],0
  800.     jne    fdc_status_error_7
  801. flnsa_2:
  802.     call   save_flp_fat
  803.     cmp    [FDC_Status],0
  804.     jne    fdc_status_error_7
  805. frnoreadds_1:
  806.     pop    edi esi edx ecx ebx eax
  807.     add    esp,32
  808.     mov    eax,0
  809.     mov   [flp_status],0
  810.     ret
  811.  
  812. fdc_status_error_7_1:
  813.     cmp    [FDC_Status],0
  814.     je    fdc_status_error_8
  815. fdc_status_error_7:
  816.     pop    edi esi edx ecx ebx eax
  817.     add    esp,32
  818.     jmp    fdc_status_error_1
  819.  
  820. save_chs_sector:
  821.     call    calculate_chs
  822.     call    WriteSectWithRetr
  823.     ret
  824.  
  825. calculate_chs:
  826.     mov    bl,[FDD_Track]
  827.     mov    [old_track],bl
  828.     mov    ebx,18
  829.     xor    edx,edx
  830.     div    ebx
  831.     inc    edx
  832.     mov    [FDD_Sector],dl
  833.     xor    edx,edx
  834.     mov    ebx,2
  835.     div    ebx
  836.     mov    [FDD_Track],al
  837.     mov    [FDD_Head],0
  838.     cmp    edx,0
  839.     je     no_head_2
  840.     inc    [FDD_Head]
  841. no_head_2:
  842.     mov     dl,[old_track]
  843.     cmp     dl,[FDD_Track]
  844.     je      no_seek_track_1
  845.     call    SeekTrack
  846. no_seek_track_1:
  847.     ret
  848.  
  849.  
  850. get_cluster_of_a_path_flp:
  851. ;---------------------------------------------------------
  852. ; input  : EBX = pointer to a path string
  853. ;          (example: the path "/files/data/document" become
  854. ;                             "files......data.......document...0"
  855. ;          '.' = space char
  856. ;          '0' = char(0) (ASCII=0) !!! )
  857. ; output : if (CARRY=1) -> ERROR in the PATH
  858. ;          if (CARRY=0) -> EAX=cluster
  859. ;---------------------------------------------------------
  860.  
  861.     push  edx
  862.     mov   edx,ebx
  863.  
  864. search_end_of_path_flp:
  865.     cmp   [save_flag],0
  866.     jne   search_end_of_path_flp_1
  867.     cmp   byte [edx],0
  868.     je    found_end_of_path_flp
  869.     jmp   search_end_of_path_flp_2
  870. search_end_of_path_flp_1:
  871.     cmp   byte [edx+12],0
  872.     je    found_end_of_path_flp
  873. search_end_of_path_flp_2:
  874.     inc   edx ; '/'
  875.     call  analyze_directory_flp
  876.     jc    directory_not_found_flp
  877.  
  878.     mov   eax,[ebx+20-2]        ; read the HIGH 16bit cluster field
  879.     mov   ax,[ebx+26]           ; read the LOW 16bit cluster field
  880.     and   eax,0xfff           ;[fatMASK]
  881.     add   edx,11                ; 8+3 (name+extension)
  882.     jmp   search_end_of_path_flp
  883.  
  884. found_end_of_path_flp:
  885.     inc   edx
  886.     mov   [pointer_file_name_flp],edx
  887.     pop   edx
  888.     clc                         ; no errors
  889.     ret
  890.  
  891. directory_not_found_flp:
  892.     pop   edx
  893.     stc                         ; errors occour
  894.     ret
  895.  
  896. analyze_directory_flp:
  897. ;--------------------------------
  898. ; input  : EAX = first cluster of the directory
  899. ;          EBX = pointer to filename
  900. ; output : IF CARRY=0 EAX = sector where th file is found
  901. ;                     EBX = pointer in buffer
  902. ;                     [buffer .. buffer+511]
  903. ;                     ECX,EDX,EDI,EDI not changed
  904. ;          IF CARRY=1
  905. ;--------------------------------
  906.    push ebx ;[esp+16]
  907.    push ecx
  908.    push edx
  909.    push esi
  910.    push edi
  911.  
  912.  
  913. adr56_flp:
  914.    mov [clust_tmp_flp],eax
  915.    add    eax,31
  916.    pusha
  917.    call   read_chs_sector
  918.    popa
  919.    cmp    [FDC_Status],0
  920.    jne    not_found_file_analyze_flp
  921.  
  922.    mov ecx,512/32
  923.    mov ebx,FDD_BUFF
  924.  
  925. adr1_analyze_flp:
  926.    mov esi,edx   ;[esp+16]
  927.    mov edi,ebx
  928.    cld
  929.    push ecx
  930.    mov ecx,11
  931.    rep cmpsb
  932.    pop ecx
  933.    je found_file_analyze_flp
  934.  
  935.    add ebx,32
  936.    loop adr1_analyze_flp
  937.  
  938.     mov eax,[clust_tmp_flp]
  939.     shl    eax,1            ;find next cluster from FAT
  940.     add    eax,0x282000
  941.     mov    eax,[eax]
  942.     and    eax,4095
  943.     cmp eax,0x0ff8
  944.     jb  adr56_flp
  945. not_found_file_analyze_flp:
  946.    pop edi
  947.    pop esi
  948.    pop edx
  949.    pop ecx
  950.    add esp,4
  951.    stc        ;file not found
  952.    ret
  953.  
  954. found_file_analyze_flp:
  955.    pop edi
  956.    pop esi
  957.    pop edx
  958.    pop ecx
  959.    add esp,4
  960.    clc        ;file found
  961.    ret
  962.  
  963.  
  964. analyze_directory_to_write_flp:
  965. ;--------------------------------
  966. ; input  : EAX = first cluster of the directory
  967. ; output : IF CARRY=0 EAX = sector where the file is found
  968. ;                     EBX = pointer in buffer
  969. ;                     [buffer .. buffer+511]
  970. ;                     ECX,EDX,EDI,EDI not changed
  971. ;          IF CARRY=1
  972. ;--------------------------------
  973.  
  974.    push ecx
  975.    push edx
  976.    push esi
  977.  
  978. adr561:
  979.    mov [clust_tmp_flp],eax
  980.    add    eax,31
  981.    pusha
  982.    call   read_chs_sector
  983.    popa
  984.    cmp    [FDC_Status],0
  985.    jne    error_found_file_analyze1
  986.  
  987.    mov ecx,512/32
  988.    mov ebx,FDD_BUFF
  989.  
  990. adr1_analyze1:
  991.    cmp byte [ebx],0x00
  992.    je  found_file_analyze1
  993.    cmp byte [ebx],0xe5
  994.    je  found_file_analyze1
  995.  
  996. avanti:
  997.    add ebx,32
  998.    loop adr1_analyze1
  999.  
  1000.    mov eax,[clust_tmp_flp]
  1001.    shl    eax,1            ;find next cluster from FAT
  1002.    add    eax,0x282000
  1003.    mov    eax,[eax]
  1004.    and    eax,4095
  1005.    cmp eax,0x0ff8
  1006.    jb  adr561
  1007.  
  1008.    call get_free_FAT               ;this block of code add a new cluster
  1009.                                    ;for the directory because the directory
  1010.                                    ;is full
  1011.  
  1012.    mov [edi],word 0x0fff
  1013.  
  1014.    mov eax,[clust_tmp_flp]
  1015.    shl    eax,1            ;find next cluster from FAT
  1016.    add    eax,0x282000
  1017.    sub    edi,0x282000
  1018.    mov    [eax],di
  1019.  
  1020.    pusha
  1021.    mov ecx,512/4
  1022.    xor eax,eax
  1023.    mov edi,FDD_BUFF
  1024.    cld
  1025.    rep stosd
  1026.    popa
  1027.  
  1028.    mov    eax,edi
  1029.    add    eax,31
  1030.    pusha
  1031.    call   save_chs_sector
  1032.    popa
  1033.    cmp    [FDC_Status],0
  1034.    jne    error_found_file_analyze1
  1035.    mov    ebx,FDD_BUFF
  1036.  
  1037. found_file_analyze1:
  1038.  
  1039.    pop esi
  1040.    pop edx
  1041.    pop ecx
  1042.    clc        ;file found
  1043.    ret
  1044.  
  1045. error_found_file_analyze1:
  1046.    pop esi
  1047.    pop edx
  1048.    pop ecx
  1049.    stc
  1050.    ret
  1051.  
  1052. get_free_FAT_flp:
  1053. ;------------------------------------------
  1054. ; input  :  EAX = # cluster for start the searching
  1055. ; output :  EAX = # first cluster found free
  1056. ;-------------------------------------------
  1057.    push ebx
  1058.  
  1059.     mov    ebx,1
  1060. check_new_flp:
  1061.     add    ebx,1
  1062.     mov    edi,ebx            ; find free cluster in FAT
  1063.     shl    edi,1
  1064.     add    edi,0x282000
  1065.     mov    eax,[edi]
  1066.     and    eax,4095
  1067.     cmp    eax,0x0
  1068.     jnz    check_new_flp
  1069.  
  1070.    pop ebx
  1071.    ret
  1072.  
  1073. ; \begin{diamond}
  1074. fat_find_lfn:
  1075. ; in: esi->name
  1076. ;     [esp+4] = next
  1077. ;     [esp+8] = first
  1078. ;     [esp+C]... - possibly parameters for first and next
  1079. ; out: CF=1 - file not found
  1080. ;      else CF=0, esi->next name component, edi->direntry
  1081.         pusha
  1082.         lea     eax, [esp+0Ch+20h]
  1083.         call    dword [eax-4]
  1084.         jc      .reterr
  1085.         sub     esp, 262*2      ; reserve place for LFN
  1086.         mov     ebp, esp
  1087.         push    0               ; for fat_get_name: read ASCII name
  1088. .l1:
  1089.         call    fat_get_name
  1090.         jc      .l2
  1091.         call    fat_compare_name
  1092.         jz      .found
  1093. .l2:
  1094.         lea     eax, [esp+0Ch+20h+262*2+4]
  1095.         call    dword [eax-8]
  1096.         jnc     .l1
  1097.         add     esp, 262*2+4
  1098. .reterr:
  1099.         stc
  1100.         popa
  1101.         ret
  1102. .found:
  1103.         add     esp, 262*2+4
  1104. ; if this is LFN entry, advance to true entry
  1105.         cmp     byte [edi+11], 0xF
  1106.         jnz     @f
  1107.         lea     eax, [esp+0Ch+20h]
  1108.         call    dword [eax-8]
  1109.         jc      .reterr
  1110. @@:
  1111.         add     esp, 8          ; CF=0
  1112.         push    esi
  1113.         push    edi
  1114.         popa
  1115.         ret
  1116.  
  1117. uglobal
  1118. ; this is for delete support
  1119. fd_prev_sector          dd      ?
  1120. fd_prev_prev_sector     dd      ?
  1121. endg
  1122.  
  1123. flp_root_next:
  1124.         cmp     edi, 0xD200-0x20
  1125.         jae     @f
  1126.         add     edi, 0x20
  1127.         ret     ; CF=0
  1128. @@:
  1129. ; read next sector
  1130.         inc     dword [eax]
  1131.         cmp     dword [eax], 14
  1132.         jae     flp_root_first.readerr
  1133.         push    [fd_prev_sector]
  1134.         pop     [fd_prev_prev_sector]
  1135.         push    eax
  1136.         mov     eax, [eax]
  1137.         add     eax, 19-1
  1138.         mov     [fd_prev_sector], eax
  1139.         pop     eax
  1140. flp_root_first:
  1141.         mov     eax, [eax]
  1142.         pusha
  1143.         add     eax, 19
  1144.         call    read_chs_sector
  1145.         popa
  1146.         cmp     [FDC_Status], 0
  1147.         jnz     .readerr
  1148.         mov     edi, FDD_BUFF
  1149.         ret     ; CF=0
  1150. .readerr:
  1151.         stc
  1152.         ret
  1153.  
  1154. flp_rootmem_first:
  1155.         mov     edi, FLOPPY_BUFF
  1156.         clc
  1157.         ret
  1158. flp_rootmem_next:
  1159.         add     edi, 0x20
  1160.         cmp     edi, FLOPPY_BUFF+14*0x200
  1161.         cmc
  1162. flp_rootmem_next_write:
  1163. flp_rootmem_begin_write:
  1164. flp_rootmem_end_write:
  1165.         ret
  1166. flp_rootmem_extend_dir:
  1167.         stc
  1168.         ret
  1169.  
  1170. flp_notroot_next:
  1171.         cmp     edi, 0xD200-0x20
  1172.         jae     flp_notroot_next_sector
  1173.         add     edi, 0x20
  1174.         ret     ; CF=0
  1175. flp_notroot_next_sector:
  1176.         push    ecx
  1177.         mov     ecx, [eax]
  1178.         push    [fd_prev_sector]
  1179.         pop     [fd_prev_prev_sector]
  1180.         add     ecx, 31
  1181.         mov     [fd_prev_sector], ecx
  1182.         mov     ecx, [(ecx-31)*2+0x282000]
  1183.         and     ecx, 0xFFF
  1184.         cmp     ecx, 2849
  1185.         jae     flp_notroot_first.err2
  1186.         mov     [eax], ecx
  1187.         pop     ecx
  1188. flp_notroot_first:
  1189.         mov     eax, [eax]
  1190.         cmp     eax, 2
  1191.         jb      .err
  1192.         cmp     eax, 2849
  1193.         jae     .err
  1194.         pusha
  1195.         add     eax, 31
  1196.         call    read_chs_sector
  1197.         popa
  1198.         mov     edi, FDD_BUFF
  1199.         cmp     [FDC_Status], 0
  1200.         jnz     .err
  1201.         ret     ; CF=0
  1202. .err2:
  1203.         pop     ecx
  1204. .err:
  1205.         stc
  1206.         ret
  1207. flp_notroot_begin_write:
  1208.         pusha
  1209.         mov     eax, [eax]
  1210.         add     eax, 31
  1211.         call    read_chs_sector
  1212.         popa
  1213.         ret
  1214. flp_notroot_end_write:
  1215.         pusha
  1216.         mov     eax, [eax]
  1217.         add     eax, 31
  1218.         call    save_chs_sector
  1219.         popa
  1220.         ret
  1221. flp_notroot_next_write:
  1222.         cmp     edi, 0xD200
  1223.         jae     @f
  1224.         ret
  1225. @@:
  1226.         call    flp_notroot_end_write
  1227.         jmp     flp_notroot_next_sector
  1228. flp_notroot_extend_dir:
  1229. ; find free cluster in FAT
  1230.         pusha
  1231.         xor     eax, eax
  1232.         mov     edi, 0x282000
  1233.         mov     ecx, 2849
  1234.         repnz   scasw
  1235.         jnz     .notfound
  1236.         mov     word [edi-2], 0xFFF     ; mark as last cluster
  1237.         sub     edi, 0x282000
  1238.         shr     edi, 1
  1239.         dec     edi
  1240.         mov     eax, [esp+28]
  1241.         mov     ecx, [eax]
  1242.         mov     [0x282000+ecx*2], di
  1243.         mov     [eax], edi
  1244.         xor     eax, eax
  1245.         mov     edi, FDD_BUFF
  1246.         mov     ecx, 128
  1247.         rep     stosd
  1248.         popa
  1249.         call    flp_notroot_end_write
  1250.         mov     edi, FDD_BUFF
  1251.         clc
  1252.         ret
  1253. .notfound:
  1254.         popa
  1255.         stc
  1256.         ret
  1257.  
  1258. fd_find_lfn:
  1259. ; in: esi->name
  1260. ; out: CF=1 - file not found
  1261. ;      else CF=0 and edi->direntry, eax=directory cluster (0 for root)
  1262.         push    esi edi
  1263.         push    0
  1264.         push    flp_root_first
  1265.         push    flp_root_next
  1266. .loop:
  1267.         call    fat_find_lfn
  1268.         jc      .notfound
  1269.         cmp     byte [esi], 0
  1270.         jz      .found
  1271.         test    byte [edi+11], 10h
  1272.         jz      .notfound
  1273.         movzx   eax, word [edi+26]      ; cluster
  1274.         mov     [esp+8], eax
  1275.         mov     dword [esp+4], flp_notroot_first
  1276.         mov     dword [esp], flp_notroot_next
  1277.         jmp     .loop
  1278. .notfound:
  1279.         add     esp, 12
  1280.         pop     edi esi
  1281.         stc
  1282.         ret
  1283. .found:
  1284.         mov     eax, [esp+8]
  1285.         add     eax, 31
  1286.         cmp     dword [esp], flp_root_next
  1287.         jnz     @f
  1288.         add     eax, -31+19
  1289. @@:
  1290.         add     esp, 16         ; CF=0
  1291.         pop     esi
  1292.         ret
  1293.  
  1294. ;----------------------------------------------------------------
  1295. ;
  1296. ;  fs_FloppyRead - LFN variant for reading floppy
  1297. ;
  1298. ;  esi  points to filename
  1299. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  1300. ;       may be ebx=0 - start from first byte
  1301. ;  ecx  number of bytes to read, 0+
  1302. ;  edx  mem location to return data
  1303. ;
  1304. ;  ret ebx = bytes read or 0xffffffff file not found
  1305. ;      eax = 0 ok read or other = errormsg
  1306. ;
  1307. ;--------------------------------------------------------------
  1308. fs_FloppyRead:
  1309.         call    read_flp_fat
  1310.         cmp     byte [esi], 0
  1311.         jnz     @f
  1312.         or      ebx, -1
  1313.         mov     eax, 10         ; access denied
  1314.         ret
  1315. @@:
  1316.         push    edi
  1317.         call    fd_find_lfn
  1318.         jnc     .found
  1319.         pop     edi
  1320.         or      ebx, -1
  1321.         mov     eax, 5          ; file not found
  1322.         ret
  1323. .found:
  1324.         test    ebx, ebx
  1325.         jz      .l1
  1326.         cmp     dword [ebx+4], 0
  1327.         jz      @f
  1328.         xor     ebx, ebx
  1329. .reteof:
  1330.         mov     eax, 6          ; EOF
  1331.         pop     edi
  1332.         ret
  1333. @@:
  1334.         mov     ebx, [ebx]
  1335. .l1:
  1336.         push    ecx edx
  1337.         push    0
  1338.         mov     eax, [edi+28]
  1339.         sub     eax, ebx
  1340.         jb      .eof
  1341.         cmp     eax, ecx
  1342.         jae     @f
  1343.         mov     ecx, eax
  1344.         mov     byte [esp], 6           ; EOF
  1345. @@:
  1346.         movzx   edi, word [edi+26]
  1347. .new:
  1348.         jecxz   .done
  1349.         test    edi, edi
  1350.         jz      .eof
  1351.         cmp     edi, 0xFF8
  1352.         jae     .eof
  1353.         sub     ebx, 512
  1354.         jae     .skip
  1355.         lea     eax, [edi+31]
  1356.         pusha
  1357.         call    read_chs_sector
  1358.         popa
  1359.         cmp     [FDC_Status], 0
  1360.         jnz     .err
  1361.         lea     eax, [FDD_BUFF+ebx+512]
  1362.         neg     ebx
  1363.         push    ecx
  1364.         cmp     ecx, ebx
  1365.         jbe     @f
  1366.         mov     ecx, ebx
  1367. @@:
  1368.         mov     ebx, edx
  1369.         call    memmove
  1370.         add     edx, ecx
  1371.         sub     [esp], ecx
  1372.         pop     ecx
  1373.         xor     ebx, ebx
  1374. .skip:
  1375.         movzx   edi, word [edi*2+0x282000]
  1376.         jmp     .new
  1377. .done:
  1378.         mov     ebx, edx
  1379.         pop     eax edx ecx edi
  1380.         sub     ebx, edx
  1381.         ret
  1382. .eof:
  1383.         mov     ebx, edx
  1384.         pop     eax edx ecx
  1385.         jmp     .reteof
  1386. .err:
  1387.         mov     ebx, edx
  1388.         pop     eax edx ecx edi
  1389.         sub     ebx, edx
  1390.         mov     al, 11
  1391.         ret
  1392.  
  1393. ;----------------------------------------------------------------
  1394. ;
  1395. ;  fs_FloppyReadFolder - LFN variant for reading floppy folders
  1396. ;
  1397. ;  esi  points to filename
  1398. ;  ebx  pointer to structure: 32-bit number = first wanted block, 0+
  1399. ;                           & flags (bitfields)
  1400. ; flags: bit 0: 0=ANSI names, 1=UNICODE names
  1401. ;  ecx  number of blocks to read, 0+
  1402. ;  edx  mem location to return data
  1403. ;
  1404. ;  ret ebx = blocks read or 0xffffffff folder not found
  1405. ;      eax = 0 ok read or other = errormsg
  1406. ;
  1407. ;--------------------------------------------------------------
  1408. fs_FloppyReadFolder:
  1409.         call    read_flp_fat
  1410.         push    edi
  1411.         cmp     byte [esi], 0
  1412.         jz      .root
  1413.         call    fd_find_lfn
  1414.         jnc     .found
  1415.         pop     edi
  1416.         or      ebx, -1
  1417.         mov     eax, ERROR_FILE_NOT_FOUND
  1418.         ret
  1419. .found:
  1420.         test    byte [edi+11], 0x10     ; do not allow read files
  1421.         jnz     .found_dir
  1422.         pop     edi
  1423.         or      ebx, -1
  1424.         mov     eax, ERROR_ACCESS_DENIED
  1425.         ret
  1426. .found_dir:
  1427.         movzx   eax, word [edi+26]
  1428.         add     eax, 31
  1429.         push    0
  1430.         jmp     .doit
  1431. .root:
  1432.         mov     eax, 19
  1433.         push    14
  1434. .doit:
  1435.         push    ecx ebp
  1436.         sub     esp, 262*2      ; reserve space for LFN
  1437.         mov     ebp, esp
  1438.         push    dword [ebx+4]   ; for fat_get_name: read ANSI/UNICODE names
  1439.         mov     ebx, [ebx]
  1440. ; init header
  1441.         push    eax ecx
  1442.         mov     edi, edx
  1443.         mov     ecx, 32/4
  1444.         xor     eax, eax
  1445.         rep     stosd
  1446.         pop     ecx eax
  1447.         mov     byte [edx], 1   ; version
  1448.         mov     esi, edi        ; esi points to BDFE
  1449. .main_loop:
  1450.         pusha
  1451.         call    read_chs_sector
  1452.         popa
  1453.         cmp     [FDC_Status], 0
  1454.         jnz     .error
  1455.         mov     edi, FDD_BUFF
  1456.         push    eax
  1457. .l1:
  1458.         call    fat_get_name
  1459.         jc      .l2
  1460.         cmp     byte [edi+11], 0xF
  1461.         jnz     .do_bdfe
  1462.         add     edi, 0x20
  1463.         cmp     edi, 0xD200
  1464.         jb      .do_bdfe
  1465.         pop     eax
  1466.         inc     eax
  1467.         dec     byte [esp+262*2+12]
  1468.         jz      .done
  1469.         jns     @f
  1470. ; read next sector from FAT
  1471.         mov     eax, [(eax-31-1)*2+0x282000]
  1472.         and     eax, 0xFFF
  1473.         cmp     eax, 0xFF8
  1474.         jae     .done
  1475.         add     eax, 31
  1476.         mov     byte [esp+262*2+12], 0
  1477. @@:
  1478.         pusha
  1479.         call    read_chs_sector
  1480.         popa
  1481.         cmp     [FDC_Status], 0
  1482.         jnz     .error
  1483.         mov     edi, FDD_BUFF
  1484.         push    eax
  1485. .do_bdfe:
  1486.         inc     dword [edx+8]   ; new file found
  1487.         dec     ebx
  1488.         jns     .l2
  1489.         dec     ecx
  1490.         js      .l2
  1491.         inc     dword [edx+4]   ; new file block copied
  1492.         call    fat_entry_to_bdfe
  1493. .l2:
  1494.         add     edi, 0x20
  1495.         cmp     edi, 0xD200
  1496.         jb      .l1
  1497.         pop     eax
  1498.         inc     eax
  1499.         dec     byte [esp+262*2+12]
  1500.         jz      .done
  1501.         jns     @f
  1502. ; read next sector from FAT
  1503.         mov     eax, [(eax-31-1)*2+0x282000]
  1504.         and     eax, 0xFFF
  1505.         cmp     eax, 0xFF8
  1506.         jae     .done
  1507.         add     eax, 31
  1508.         mov     byte [esp+262*2+12], 0
  1509. @@:
  1510.         jmp     .main_loop
  1511. .error:
  1512.         add     esp, 262*2+4
  1513.         pop     ebp ecx edi edi
  1514.         or      ebx, -1
  1515.         mov     eax, ERROR_FILE_NOT_FOUND
  1516.         ret
  1517. .done:
  1518.         add     esp, 262*2+4
  1519.         pop     ebp
  1520.         mov     ebx, [edx+4]
  1521.         xor     eax, eax
  1522.         dec     ecx
  1523.         js      @f
  1524.         mov     al, ERROR_END_OF_FILE
  1525. @@:
  1526.         pop     ecx edi edi
  1527.         ret
  1528.  
  1529. ;----------------------------------------------------------------
  1530. ;
  1531. ;  fs_FloppyRewrite - LFN variant for writing sys floppy
  1532. ;
  1533. ;  esi  points to filename
  1534. ;  ebx  ignored (reserved)
  1535. ;  ecx  number of bytes to write, 0+
  1536. ;  edx  mem location to data
  1537. ;
  1538. ;  ret ebx = number of written bytes
  1539. ;      eax = 0 ok read or other = errormsg
  1540. ;
  1541. ;--------------------------------------------------------------
  1542. @@:
  1543.         mov     eax, ERROR_ACCESS_DENIED
  1544.         xor     ebx, ebx
  1545.         ret
  1546. fsfrfe2:
  1547.         popad
  1548. fsfrfe:
  1549.         mov     eax, 11
  1550.         xor     ebx, ebx
  1551.         ret
  1552.  
  1553. fs_FloppyCreateFolder:
  1554.         mov     al, 1
  1555.         jmp     fs_FloppyRewrite.common
  1556.  
  1557. fs_FloppyRewrite:
  1558.         xor     eax, eax
  1559. .common:
  1560.         cmp     byte [esi], 0
  1561.         jz      @b
  1562.         call    read_flp_fat
  1563.         cmp     [FDC_Status], 0
  1564.         jnz     fsfrfe
  1565.         pushad
  1566.         xor     ebp, ebp
  1567.         push    esi
  1568. @@:
  1569.         lodsb
  1570.         test    al, al
  1571.         jz      @f
  1572.         cmp     al, '/'
  1573.         jnz     @b
  1574.         lea     ebp, [esi-1]
  1575.         jmp     @b
  1576. @@:
  1577.         pop     esi
  1578.         test    ebp, ebp
  1579.         jnz     .noroot
  1580.         call    read_flp_root
  1581.         cmp     [FDC_Status], 0
  1582.         jnz     fsfrfe2
  1583.         push    flp_rootmem_extend_dir
  1584.         push    flp_rootmem_end_write
  1585.         push    flp_rootmem_next_write
  1586.         push    flp_rootmem_begin_write
  1587.         xor     ebp, ebp
  1588.         push    ebp
  1589.         push    flp_rootmem_first
  1590.         push    flp_rootmem_next
  1591.         jmp     .common1
  1592. .noroot:
  1593.         mov     eax, ERROR_ACCESS_DENIED
  1594.         cmp     byte [ebp+1], 0
  1595.         jz      .ret1
  1596. ; check existence
  1597.         mov     byte [ebp], 0
  1598.         call    fd_find_lfn
  1599.         mov     byte [ebp], '/'
  1600.         lea     esi, [ebp+1]
  1601.         jnc     @f
  1602.         mov     eax, ERROR_FILE_NOT_FOUND
  1603. .ret1:
  1604.         mov     [esp+28], eax
  1605.         popad
  1606.         xor     ebx, ebx
  1607.         ret
  1608. @@:
  1609.         test    byte [edi+11], 0x10     ; must be directory
  1610.         mov     eax, ERROR_ACCESS_DENIED
  1611.         jz      .ret1
  1612.         movzx   ebp, word [edi+26]      ; ebp=cluster
  1613.         mov     eax, ERROR_FAT_TABLE
  1614.         cmp     ebp, 2
  1615.         jb      .ret1
  1616.         cmp     ebp, 2849
  1617.         jae     .ret1
  1618.         push    flp_notroot_extend_dir
  1619.         push    flp_notroot_end_write
  1620.         push    flp_notroot_next_write
  1621.         push    flp_notroot_begin_write
  1622.         push    ebp
  1623.         push    flp_notroot_first
  1624.         push    flp_notroot_next
  1625. .common1:
  1626.         call    fat_find_lfn
  1627.         jc      .notfound
  1628. ; found
  1629.         test    byte [edi+11], 10h
  1630.         jz      .exists_file
  1631. ; found directory; if we are creating directory, return OK,
  1632. ;                  if we are creating file, say "access denied"
  1633.         add     esp, 28
  1634.         popad
  1635.         test    al, al
  1636.         mov     eax, ERROR_ACCESS_DENIED
  1637.         jz      @f
  1638.         mov     al, 0
  1639. @@:
  1640.         xor     ebx, ebx
  1641.         ret
  1642. .exists_file:
  1643. ; found file; if we are creating directory, return "access denied",
  1644. ;             if we are creating file, delete existing file and continue
  1645.         cmp     byte [esp+28+28], 0
  1646.         jz      @f
  1647.         add     esp, 28
  1648.         popad
  1649.         mov     eax, ERROR_ACCESS_DENIED
  1650.         xor     ebx, ebx
  1651.         ret
  1652. @@:
  1653. ; delete FAT chain
  1654.         push    edi
  1655.         xor     eax, eax
  1656.         mov     dword [edi+28], eax     ; zero size
  1657.         xchg    ax, word [edi+26]       ; start cluster
  1658.         test    eax, eax
  1659.         jz      .done1
  1660. @@:
  1661.         cmp     eax, 0xFF8
  1662.         jae     .done1
  1663.         lea     edi, [FLOPPY_FAT + eax*2] ; position in FAT
  1664.         xor     eax, eax
  1665.         xchg    ax, [edi]
  1666.         jmp     @b
  1667. .done1:
  1668.         pop     edi
  1669.         call    get_time_for_file
  1670.         mov     [edi+22], ax
  1671.         call    get_date_for_file
  1672.         mov     [edi+24], ax
  1673.         mov     [edi+18], ax
  1674.         or      byte [edi+11], 20h      ; set 'archive' attribute
  1675.         jmp     .doit
  1676. .notfound:
  1677. ; file is not found; generate short name
  1678.         call    fat_name_is_legal
  1679.         jc      @f
  1680.         add     esp, 28
  1681.         popad
  1682.         mov     eax, ERROR_FILE_NOT_FOUND
  1683.         xor     ebx, ebx
  1684.         ret
  1685. @@:
  1686.         sub     esp, 12
  1687.         mov     edi, esp
  1688.         call    fat_gen_short_name
  1689. .test_short_name_loop:
  1690.         push    esi edi ecx
  1691.         mov     esi, edi
  1692.         lea     eax, [esp+12+12+8]
  1693.         mov     [eax], ebp
  1694.         call    dword [eax-4]
  1695.         jc      .found
  1696. .test_short_name_entry:
  1697.         cmp     byte [edi+11], 0xF
  1698.         jz      .test_short_name_cont
  1699.         mov     ecx, 11
  1700.         push    esi edi
  1701.         repz    cmpsb
  1702.         pop     edi esi
  1703.         jz      .short_name_found
  1704. .test_short_name_cont:
  1705.         lea     eax, [esp+12+12+8]
  1706.         call    dword [eax-8]
  1707.         jnc     .test_short_name_entry
  1708.         jmp     .found
  1709. .short_name_found:
  1710.         pop     ecx edi esi
  1711.         call    fat_next_short_name
  1712.         jnc     .test_short_name_loop
  1713. .disk_full:
  1714.         add     esp, 12+28
  1715.         popa
  1716.         mov     eax, ERROR_DISK_FULL
  1717.         xor     ebx, ebx
  1718.         ret
  1719. .found:
  1720.         pop     ecx edi esi
  1721. ; now find space in directory
  1722. ; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
  1723.         mov     al, '~'
  1724.         push    ecx edi
  1725.         mov     ecx, 8
  1726.         repnz   scasb
  1727.         push    1
  1728.         pop     eax     ; 1 entry
  1729.         jnz     .notilde
  1730. ; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
  1731.         xor     eax, eax
  1732. @@:
  1733.         cmp     byte [esi], 0
  1734.         jz      @f
  1735.         inc     esi
  1736.         inc     eax
  1737.         jmp     @b
  1738. @@:
  1739.         sub     esi, eax
  1740.         add     eax, 12+13
  1741.         mov     ecx, 13
  1742.         push    edx
  1743.         cdq
  1744.         div     ecx
  1745.         pop     edx
  1746. .notilde:
  1747.         push    -1
  1748.         push    -1
  1749. ; find <eax> successive entries in directory
  1750.         xor     ecx, ecx
  1751.         push    eax
  1752.         lea     eax, [esp+12+8+12+8]
  1753.         mov     [eax], ebp
  1754.         call    dword [eax-4]
  1755.         pop     eax
  1756.         jnc     .scan_dir
  1757. .fsfrfe3:
  1758.         add     esp, 8+8+12+28
  1759.         popad
  1760.         mov     eax, 11
  1761.         xor     ebx, ebx
  1762.         ret
  1763. .scan_dir:
  1764.         cmp     byte [edi], 0
  1765.         jz      .free
  1766.         cmp     byte [edi], 0xE5
  1767.         jz      .free
  1768.         xor     ecx, ecx
  1769. .scan_cont:
  1770.         push    eax
  1771.         lea     eax, [esp+12+8+12+8]
  1772.         call    dword [eax-8]
  1773.         pop     eax
  1774.         jnc     .scan_dir
  1775.         cmp     [FDC_Status], 0
  1776.         jnz     .fsfrfe3
  1777.         push    eax
  1778.         lea     eax, [esp+12+8+12+8]
  1779.         call    dword [eax+16]          ; extend directory
  1780.         pop     eax
  1781.         jnc     .scan_dir
  1782.         add     esp, 8+8+12+28
  1783.         popad
  1784.         mov     eax, ERROR_DISK_FULL
  1785.         xor     ebx, ebx
  1786.         ret
  1787. .free:
  1788.         test    ecx, ecx
  1789.         jnz     @f
  1790.         mov     [esp], edi
  1791.         mov     ecx, [esp+8+8+12+8]
  1792.         mov     [esp+4], ecx
  1793.         xor     ecx, ecx
  1794. @@:
  1795.         inc     ecx
  1796.         cmp     ecx, eax
  1797.         jb      .scan_cont
  1798. ; found!
  1799. ; calculate name checksum
  1800.         push    esi ecx
  1801.         mov     esi, [esp+8+8]
  1802.         mov     ecx, 11
  1803.         xor     eax, eax
  1804. @@:
  1805.         ror     al, 1
  1806.         add     al, [esi]
  1807.         inc     esi
  1808.         loop    @b
  1809.         pop     ecx esi
  1810.         pop     edi
  1811.         pop     dword [esp+8+12+8]
  1812. ; edi points to first entry in free chunk
  1813.         dec     ecx
  1814.         jz      .nolfn
  1815.         push    esi
  1816.         push    eax
  1817.         lea     eax, [esp+8+8+12+8]
  1818.         call    dword [eax+4]         ; begin write
  1819.         mov     al, 40h
  1820. .writelfn:
  1821.         or      al, cl
  1822.         mov     esi, [esp+4]
  1823.         push    ecx
  1824.         dec     ecx
  1825.         imul    ecx, 13
  1826.         add     esi, ecx
  1827.         stosb
  1828.         mov     cl, 5
  1829.         call    fs_RamdiskRewrite.read_symbols
  1830.         mov     ax, 0xF
  1831.         stosw
  1832.         mov     al, [esp+4]
  1833.         stosb
  1834.         mov     cl, 6
  1835.         call    fs_RamdiskRewrite.read_symbols
  1836.         xor     eax, eax
  1837.         stosw
  1838.         mov     cl, 2
  1839.         call    fs_RamdiskRewrite.read_symbols
  1840.         pop     ecx
  1841.         lea     eax, [esp+8+8+12+8]
  1842.         call    dword [eax+8]         ; next write
  1843.         xor     eax, eax
  1844.         loop    .writelfn
  1845.         pop     eax
  1846.         pop     esi
  1847. ;        lea     eax, [esp+8+12+8]
  1848. ;        call    dword [eax+12]          ; end write
  1849. .nolfn:
  1850.         xchg    esi, [esp]
  1851.         mov     ecx, 11
  1852.         rep     movsb
  1853.         mov     word [edi], 20h         ; attributes
  1854.         sub     edi, 11
  1855.         pop     esi ecx
  1856.         add     esp, 12
  1857.         mov     byte [edi+13], 0        ; tenths of a second at file creation time
  1858.         call    get_time_for_file
  1859.         mov     [edi+14], ax            ; creation time
  1860.         mov     [edi+22], ax            ; last write time
  1861.         call    get_date_for_file
  1862.         mov     [edi+16], ax            ; creation date
  1863.         mov     [edi+24], ax            ; last write date
  1864.         mov     [edi+18], ax            ; last access date
  1865.         and     word [edi+20], 0        ; high word of cluster
  1866.         and     word [edi+26], 0        ; low word of cluster - to be filled
  1867.         and     dword [edi+28], 0       ; file size - to be filled
  1868.         cmp     byte [esp+28+28], 0
  1869.         jz      .doit
  1870. ; create directory
  1871.         mov     byte [edi+11], 10h      ; attributes: folder
  1872.         mov     ecx, 32*2
  1873.         mov     edx, edi
  1874. .doit:
  1875.         lea     eax, [esp+8]
  1876.         call    dword [eax+12]  ; flush directory
  1877.         push    ecx
  1878.         push    edi
  1879.         push    0
  1880.         mov     esi, edx
  1881.         test    ecx, ecx
  1882.         jz      .done
  1883.         mov     ecx, 2849
  1884.         mov     edi, FLOPPY_FAT
  1885.         push    0       ; first cluster
  1886. .write_loop:
  1887. ; allocate new cluster
  1888.         xor     eax, eax
  1889.         repnz   scasw
  1890.         mov     al, ERROR_DISK_FULL
  1891.         jnz     .ret
  1892.         dec     edi
  1893.         dec     edi
  1894.         lea     eax, [edi-(FLOPPY_FAT)]
  1895.         shr     eax, 1                  ; eax = cluster
  1896.         mov     word [edi], 0xFFF       ; mark as last cluster
  1897.         xchg    edi, [esp+4]
  1898.         cmp     dword [esp], 0
  1899.         jz      .first
  1900.         stosw
  1901.         jmp     @f
  1902. .first:
  1903.         mov     [esp], eax
  1904. @@:
  1905.         mov     edi, [esp+4]
  1906.         inc     ecx
  1907. ; write data
  1908.         push    ecx edi
  1909.         mov     ecx, 512
  1910.         cmp     dword [esp+20], ecx
  1911.         jae     @f
  1912.         mov     ecx, [esp+20]
  1913. @@:
  1914.         mov     edi, FDD_BUFF
  1915.         cmp     byte [esp+24+28+28], 0
  1916.         jnz     .writedir
  1917.         push    ecx
  1918.         rep     movsb
  1919.         pop     ecx
  1920. .writedircont:
  1921.         push    ecx
  1922.         sub     ecx, 512
  1923.         neg     ecx
  1924.         push    eax
  1925.         xor     eax, eax
  1926.         rep     stosb
  1927.         pop     eax
  1928.         add     eax, 31
  1929.         pusha
  1930.         call    save_chs_sector
  1931.         popa
  1932.         pop     ecx
  1933.         cmp     [FDC_Status], 0
  1934.         jnz     .diskerr
  1935.         sub     [esp+20], ecx
  1936.         pop     edi ecx
  1937.         jnz     .write_loop
  1938. .done:
  1939.         xor     eax, eax
  1940. .ret:
  1941.         pop     ebx edi edi ecx
  1942.         mov     [esp+28+28], eax
  1943.         lea     eax, [esp+8]
  1944.         call    dword [eax+4]
  1945.         mov     [edi+26], bx
  1946.         mov     ebx, esi
  1947.         sub     ebx, edx
  1948.         mov     [edi+28], ebx
  1949.         call    dword [eax+12]
  1950.         mov     [esp+28+16], ebx
  1951.         test    ebp, ebp
  1952.         jnz     @f
  1953.         call    save_flp_root
  1954. @@:
  1955.         add     esp, 28
  1956.         cmp     [FDC_Status], 0
  1957.         jnz     .err3
  1958.         call    save_flp_fat
  1959.         cmp     [FDC_Status], 0
  1960.         jnz     .err3
  1961.         popa
  1962.         ret
  1963. .err3:
  1964.         popa
  1965.         mov     al, 11
  1966.         xor     ebx, ebx
  1967.         ret
  1968. .diskerr:
  1969.         sub     esi, ecx
  1970.         mov     eax, 11
  1971.         pop     edi ecx
  1972.         jmp     .ret
  1973. .writedir:
  1974.         push    ecx
  1975.         mov     ecx, 32/4
  1976.         push    ecx esi
  1977.         rep     movsd
  1978.         pop     esi ecx
  1979.         mov     dword [edi-32], '.   '
  1980.         mov     dword [edi-32+4], '    '
  1981.         mov     dword [edi-32+8], '    '
  1982.         mov     byte [edi-32+11], 10h
  1983.         mov     word [edi-32+26], ax
  1984.         push    esi
  1985.         rep     movsd
  1986.         pop     esi
  1987.         mov     dword [edi-32], '..  '
  1988.         mov     dword [edi-32+4], '    '
  1989.         mov     dword [edi-32+8], '    '
  1990.         mov     byte [edi-32+11], 10h
  1991.         mov     ecx, [esp+28+8]
  1992.         mov     word [edi-32+26], cx
  1993.         pop     ecx
  1994.         jmp     .writedircont
  1995.  
  1996. ;----------------------------------------------------------------
  1997. ;
  1998. ;  fs_FloppyWrite - LFN variant for writing to floppy
  1999. ;
  2000. ;  esi  points to filename
  2001. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  2002. ;       may be ebx=0 - start from first byte
  2003. ;  ecx  number of bytes to write, 0+
  2004. ;  edx  mem location to data
  2005. ;
  2006. ;  ret ebx = bytes written (maybe 0)
  2007. ;      eax = 0 ok write or other = errormsg
  2008. ;
  2009. ;--------------------------------------------------------------
  2010.  
  2011. @@:
  2012.         push    ERROR_ACCESS_DENIED
  2013. fs_FloppyWrite.ret0:
  2014.         pop     eax
  2015.         xor     ebx, ebx
  2016.         ret
  2017.  
  2018. fs_FloppyWrite.ret11:
  2019.         push    11
  2020.         jmp     fs_FloppyWrite.ret0
  2021.  
  2022. fs_FloppyWrite:
  2023.         cmp     byte [esi], 0
  2024.         jz      @b
  2025.         call    read_flp_fat
  2026.         cmp     [FDC_Status], 0
  2027.         jnz     .ret11
  2028.         pushad
  2029.         call    fd_find_lfn
  2030.         jnc     .found
  2031.         popad
  2032.         push    ERROR_FILE_NOT_FOUND
  2033.         jmp     .ret0
  2034. .found:
  2035. ; FAT does not support files larger than 4GB
  2036.         test    ebx, ebx
  2037.         jz      .l1
  2038.         cmp     dword [ebx+4], 0
  2039.         jz      @f
  2040. .eof:
  2041.         popad
  2042.         push    ERROR_END_OF_FILE
  2043.         jmp     .ret0
  2044. @@:
  2045.         mov     ebx, [ebx]
  2046. .l1:
  2047. ; now edi points to direntry, ebx=start byte to write,
  2048. ; ecx=number of bytes to write, edx=data pointer
  2049.  
  2050. ; extend file if needed
  2051.         add     ecx, ebx
  2052.         jc      .eof    ; FAT does not support files larger than 4GB
  2053.         push    eax     ; save directory cluster
  2054.         push    0       ; return value=0
  2055.  
  2056.         call    get_time_for_file
  2057.         mov     [edi+22], ax            ; last write time
  2058.         call    get_date_for_file
  2059.         mov     [edi+24], ax            ; last write date
  2060.         mov     [edi+18], ax            ; last access date
  2061.  
  2062.         push    dword [edi+28]          ; save current file size
  2063.         cmp     ecx, [edi+28]
  2064.         jbe     .length_ok
  2065.         cmp     ecx, ebx
  2066.         jz      .length_ok
  2067.         call    floppy_extend_file
  2068.         jnc     .length_ok
  2069.         mov     [esp+4], eax
  2070. ; floppy_extend_file can return two error codes: FAT table error or disk full.
  2071. ; First case is fatal error, in second case we may write some data
  2072.         cmp     al, ERROR_DISK_FULL
  2073.         jz      .disk_full
  2074.         pop     eax
  2075.         pop     eax
  2076.         mov     [esp+4+28], eax
  2077.         pop     eax
  2078.         popad
  2079.         xor     ebx, ebx
  2080.         ret
  2081. .disk_full:
  2082. ; correct number of bytes to write
  2083.         mov     ecx, [edi+28]
  2084.         cmp     ecx, ebx
  2085.         ja      .length_ok
  2086. .ret:
  2087.         pop     eax
  2088.         pop     eax
  2089.         mov     [esp+4+28], eax ; eax=return value
  2090.         pop     eax
  2091.         sub     edx, [esp+20]
  2092.         mov     [esp+16], edx   ; ebx=number of written bytes
  2093.         popad
  2094.         ret
  2095. .length_ok:
  2096. ; save FAT & directory
  2097. ; note that directory must be saved first because save_flp_fat uses buffer at 0xD000
  2098.         mov     esi, [edi+28]
  2099.         movzx   edi, word [edi+26]      ; starting cluster
  2100.         mov     eax, [esp+8]
  2101.         pusha
  2102.         call    save_chs_sector
  2103.         popa
  2104.         cmp     [FDC_Status], 0
  2105.         jnz     .device_err
  2106.         call    save_flp_fat
  2107.         cmp     [FDC_Status], 0
  2108.         jz      @f
  2109. .device_err:
  2110.         mov     byte [esp+4], 11
  2111.         jmp     .ret
  2112. @@:
  2113.  
  2114. ; now ebx=start pos, ecx=end pos, both lie inside file
  2115.         sub     ecx, ebx
  2116.         jz      .ret
  2117.         call    SetUserInterrupts
  2118. .write_loop:
  2119. ; skip unmodified sectors
  2120.         cmp     dword [esp], 0x200
  2121.         jb      .modify
  2122.         sub     ebx, 0x200
  2123.         jae     .skip
  2124.         add     ebx, 0x200
  2125. .modify:
  2126.         lea     eax, [edi+31]   ; current sector
  2127. ; get length of data in current sector
  2128.         push    ecx
  2129.         sub     ebx, 0x200
  2130.         jb      .hasdata
  2131.         neg     ebx
  2132.         xor     ecx, ecx
  2133.         jmp     @f
  2134. .hasdata:
  2135.         neg     ebx
  2136.         cmp     ecx, ebx
  2137.         jbe     @f
  2138.         mov     ecx, ebx
  2139. @@:
  2140. ; load sector if needed
  2141.         cmp     dword [esp+4], 0        ; we don't need to read uninitialized data
  2142.         jz      .noread
  2143.         cmp     ecx, 0x200      ; we don't need to read sector if it is fully rewritten
  2144.         jz      .noread
  2145.         cmp     ecx, esi        ; (same for the last sector)
  2146.         jz      .noread
  2147.         pusha
  2148.         call    read_chs_sector
  2149.         popa
  2150.         cmp     [FDC_Status], 0
  2151.         jz      @f
  2152. .device_err2:
  2153.         pop     ecx
  2154.         jmp     .device_err
  2155. @@:
  2156. .noread:
  2157. ; zero uninitialized data if file was extended (because floppy_extend_file does not this)
  2158.         push    eax ecx edi
  2159.         xor     eax, eax
  2160.         mov     ecx, 0x200
  2161.         sub     ecx, [esp+4+12]
  2162.         jbe     @f
  2163.         mov     edi, FDD_BUFF
  2164.         add     edi, [esp+4+12]
  2165.         rep     stosb
  2166. @@:
  2167. ; zero uninitialized data in the last sector
  2168.         mov     ecx, 0x200
  2169.         sub     ecx, esi
  2170.         jbe     @f
  2171.         mov     edi, FDD_BUFF
  2172.         add     edi, esi
  2173.         rep     stosb
  2174. @@:
  2175.         pop     edi ecx eax
  2176. ; copy new data
  2177.         push    eax
  2178.         mov     eax, edx
  2179.         neg     ebx
  2180.         jecxz   @f
  2181.         add     ebx, FDD_BUFF+0x200
  2182.         call    memmove
  2183.         xor     ebx, ebx
  2184. @@:
  2185.         pop     eax
  2186. ; save sector
  2187.         pusha
  2188.         call    save_chs_sector
  2189.         popa
  2190.         cmp     [FDC_Status], 0
  2191.         jnz     .device_err2
  2192.         add     edx, ecx
  2193.         sub     [esp], ecx
  2194.         pop     ecx
  2195.         jz      .done
  2196. .skip:
  2197. .next_cluster:
  2198.         movzx   edi, word [edi*2+0x282000]
  2199.         sub     esi, 0x200
  2200.         jae     @f
  2201.         xor     esi, esi
  2202. @@:
  2203.         sub     dword [esp], 0x200
  2204.         jae     .write_loop
  2205.         and     dword [esp], 0
  2206.         jmp     .write_loop
  2207. .done:
  2208.         mov     [fdc_irq_func], fdc_null
  2209.         jmp     .ret
  2210.  
  2211. floppy_extend_file.zero_size:
  2212.         xor     eax, eax
  2213.         jmp     floppy_extend_file.start_extend
  2214.  
  2215. ; extends file on floppy to given size (new data area is undefined)
  2216. ; in: edi->direntry, ecx=new size
  2217. ; out: CF=0 => OK, eax=0
  2218. ;      CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL)
  2219. floppy_extend_file:
  2220.         push    ecx
  2221. ; find the last cluster of file
  2222.         movzx   eax, word [edi+26]      ; first cluster
  2223.         mov     ecx, [edi+28]
  2224.         jecxz   .zero_size
  2225. @@:
  2226.         sub     ecx, 0x200
  2227.         jbe     @f
  2228.         mov     eax, [eax*2+0x282000]
  2229.         and     eax, 0xFFF
  2230.         jz      .fat_err
  2231.         cmp     eax, 0xFF8
  2232.         jb      @b
  2233. .fat_err:
  2234.         pop     ecx
  2235.         push    ERROR_FAT_TABLE
  2236.         pop     eax
  2237.         stc
  2238.         ret
  2239. @@:
  2240.         push    eax
  2241.         mov     eax, [eax*2+0x282000]
  2242.         and     eax, 0xFFF
  2243.         cmp     eax, 0xFF8
  2244.         pop     eax
  2245.         jb      .fat_err
  2246. ; set length to full number of sectors
  2247.         sub     [edi+28], ecx
  2248. .start_extend:
  2249.         pop     ecx
  2250. ; now do extend
  2251.         push    edx esi
  2252.         mov     esi, 0x282000+2*2       ; start scan from cluster 2
  2253.         mov     edx, 2847               ; number of clusters to scan
  2254. .extend_loop:
  2255.         cmp     [edi+28], ecx
  2256.         jae     .extend_done
  2257. ; add new sector
  2258.         push    ecx
  2259.         push    edi
  2260. .scan:
  2261.         mov     ecx, edx
  2262.         mov     edi, esi
  2263.         jecxz   .disk_full
  2264.         push    eax
  2265.         xor     eax, eax
  2266.         repnz   scasw
  2267.         pop     eax
  2268.         jnz     .disk_full
  2269.         mov     word [edi-2], 0xFFF
  2270.         mov     esi, edi
  2271.         mov     edx, ecx
  2272.         sub     edi, 0x282000
  2273.         shr     edi, 1
  2274.         dec     edi     ; now edi=new cluster
  2275.         test    eax, eax
  2276.         jz      .first_cluster
  2277.         mov     [0x282000+eax*2], di
  2278.         jmp     @f
  2279. .first_cluster:
  2280.         pop     eax             ; eax->direntry
  2281.         push    eax
  2282.         mov     [eax+26], di
  2283. @@:
  2284.         mov     eax, edi        ; eax=new cluster
  2285.         pop     edi             ; edi->direntry
  2286.         pop     ecx             ; ecx=required size
  2287.         add     dword [edi+28], 0x200
  2288.         jmp     .extend_loop
  2289. .extend_done:
  2290.         mov     [edi+28], ecx
  2291.         pop     esi edx
  2292.         xor     eax, eax        ; CF=0
  2293.         ret
  2294. .disk_full:
  2295.         pop     edi ecx
  2296.         pop     esi edx
  2297.         stc
  2298.         push    ERROR_DISK_FULL
  2299.         pop     eax
  2300.         ret
  2301.  
  2302. ;----------------------------------------------------------------
  2303. ;
  2304. ;  fs_FloppySetFileEnd - set end of file on floppy
  2305. ;
  2306. ;  esi  points to filename
  2307. ;  ebx  points to 64-bit number = new file size
  2308. ;  ecx  ignored (reserved)
  2309. ;  edx  ignored (reserved)
  2310. ;
  2311. ;  ret eax = 0 ok or other = errormsg
  2312. ;
  2313. ;--------------------------------------------------------------
  2314. fs_FloppySetFileEnd:
  2315.         call    read_flp_fat
  2316.         cmp     [FDC_Status], 0
  2317.         jnz     ret11
  2318.         cmp     byte [esi], 0
  2319.         jnz     @f
  2320. .access_denied:
  2321.         push    ERROR_ACCESS_DENIED
  2322.         jmp     .ret
  2323. @@:
  2324.         push    edi
  2325.         call    fd_find_lfn
  2326.         jnc     @f
  2327.         pop     edi
  2328.         push    ERROR_FILE_NOT_FOUND
  2329. .ret:
  2330.         pop     eax
  2331.         jmp     .doret
  2332. @@:
  2333. ; must not be directory
  2334.         test    byte [edi+11], 10h
  2335.         jz      @f
  2336.         pop     edi
  2337.         jmp     .access_denied
  2338. @@:
  2339. ; file size must not exceed 4 Gb
  2340.         cmp     dword [ebx+4], 0
  2341.         jz      @f
  2342.         pop     edi
  2343.         push    ERROR_END_OF_FILE
  2344.         jmp     .ret
  2345. @@:
  2346.         push    eax
  2347. ; set file modification date/time to current
  2348.         call    fat_update_datetime
  2349.         mov     eax, [ebx]
  2350.         cmp     eax, [edi+28]
  2351.         jb      .truncate
  2352.         ja      .expand
  2353.         pop     eax
  2354.         pushad
  2355.         call    save_chs_sector
  2356.         popad
  2357.         pop     edi
  2358.         xor     eax, eax
  2359.         cmp     [FDC_Status], 0
  2360.         jz      @f
  2361.         mov     al, 11
  2362. @@:
  2363. .doret:
  2364.         mov     [fdc_irq_func], fdc_null
  2365.         ret
  2366. .expand:
  2367.         push    ecx
  2368.         push    dword [edi+28]  ; save old size
  2369.         mov     ecx, eax
  2370.         call    floppy_extend_file
  2371.         push    eax     ; return code
  2372.         jnc     .expand_ok
  2373.         cmp     al, ERROR_DISK_FULL
  2374.         jz      .disk_full
  2375.         pop     eax ecx ecx edi edi
  2376.         jmp     .doret
  2377. .device_err:
  2378.         pop     eax
  2379. .device_err2:
  2380.         pop     ecx ecx eax edi
  2381.         push    11
  2382.         jmp     .ret
  2383. .disk_full:
  2384. .expand_ok:
  2385. ; save directory & FAT
  2386.         mov     eax, [edi+28]
  2387.         xchg    eax, [esp+12]
  2388.         movzx   edi, word [edi+26]
  2389.         pusha
  2390.         call    save_chs_sector
  2391.         popa
  2392.         cmp     [FDC_Status], 0
  2393.         jnz     .device_err
  2394.         call    save_flp_fat
  2395.         cmp     [FDC_Status], 0
  2396.         jnz     .device_err
  2397.         call    SetUserInterrupts
  2398. ; now zero new data
  2399. ; edi = current cluster, [esp+12]=new size, [esp+4]=old size, [esp]=return code
  2400. .zero_loop:
  2401.         sub     dword [esp+4], 0x200
  2402.         jae     .next_cluster
  2403.         cmp     dword [esp+4], -0x200
  2404.         jz      .noread
  2405.         lea     eax, [edi+31]
  2406.         pusha
  2407.         call    read_chs_sector
  2408.         popa
  2409.         cmp     [FDC_Status], 0
  2410.         jnz     .err_next
  2411. .noread:
  2412.         mov     ecx, [esp+4]
  2413.         neg     ecx
  2414.         push    edi
  2415.         mov     edi, FDD_BUFF+0x200
  2416.         add     edi, [esp+8]
  2417.         xor     eax, eax
  2418.         mov     [esp+8], eax
  2419.         rep     stosb
  2420.         pop     edi
  2421.         lea     eax, [edi+31]
  2422.         pusha
  2423.         call    save_chs_sector
  2424.         popa
  2425.         cmp     [FDC_Status], 0
  2426.         jz      .next_cluster
  2427. .err_next:
  2428.         mov     byte [esp], 11
  2429. .next_cluster:
  2430.         sub     dword [esp+12], 0x200
  2431.         jbe     .expand_done
  2432.         movzx   edi, word [0x282000+edi*2]
  2433.         jmp     .zero_loop
  2434. .expand_done:
  2435.         pop     eax ecx ecx edi edi
  2436.         jmp     .doret
  2437. .truncate:
  2438.         mov     [edi+28], eax
  2439.         push    ecx
  2440.         movzx   ecx, word [edi+26]
  2441.         test    eax, eax
  2442.         jz      .zero_size
  2443. ; find new last sector
  2444. @@:
  2445.         sub     eax, 0x200
  2446.         jbe     @f
  2447.         movzx   ecx, word [0x282000+ecx*2]
  2448.         jmp     @b
  2449. @@:
  2450. ; we will zero data at the end of last sector - remember it
  2451.         push    ecx
  2452. ; terminate FAT chain
  2453.         lea     ecx, [0x282000+ecx+ecx]
  2454.         push    dword [ecx]
  2455.         mov     word [ecx], 0xFFF
  2456.         pop     ecx
  2457.         and     ecx, 0xFFF
  2458.         jmp     .delete
  2459. .zero_size:
  2460.         and     word [edi+26], 0
  2461.         push    0
  2462. .delete:
  2463. ; delete FAT chain starting with ecx
  2464. ; mark all clusters as free
  2465.         cmp     ecx, 0xFF8
  2466.         jae     .deleted
  2467.         lea     ecx, [0x282000+ecx+ecx]
  2468.         push    dword [ecx]
  2469.         and     word [ecx], 0
  2470.         pop     ecx
  2471.         and     ecx, 0xFFF
  2472.         jmp     .delete
  2473. .deleted:
  2474.         mov     edi, [edi+28]
  2475. ; save directory & FAT
  2476.         mov     eax, [esp+8]
  2477.         pusha
  2478.         call    save_chs_sector
  2479.         popa
  2480.         cmp     [FDC_Status], 0
  2481.         jnz     .device_err2
  2482.         call    save_flp_fat
  2483.         cmp     [FDC_Status], 0
  2484.         jnz     .device_err2
  2485. ; zero last sector, ignore errors
  2486.         pop     eax
  2487.         add     eax, 31
  2488.         and     edi, 0x1FF
  2489.         jz      .truncate_done
  2490.         call    SetUserInterrupts
  2491.         pusha
  2492.         call    read_chs_sector
  2493.         popa
  2494.         add     edi, FDD_BUFF
  2495.         mov     ecx, FDD_BUFF+0x200
  2496.         sub     ecx, edi
  2497.         push    eax
  2498.         xor     eax, eax
  2499.         rep     stosb
  2500.         pop     eax
  2501.         pusha
  2502.         call    save_chs_sector
  2503.         popa
  2504. .truncate_done:
  2505.         pop     ecx eax edi
  2506.         xor     eax, eax
  2507.         jmp     .doret
  2508.  
  2509. fs_FloppyGetFileInfo:
  2510.         call    read_flp_fat
  2511.         cmp     [FDC_Status], 0
  2512.         jnz     ret11
  2513.         cmp     byte [esi], 0
  2514.         jnz     @f
  2515.         mov     eax, 2  ; unsupported
  2516.         ret
  2517. @@:
  2518.         push    edi
  2519.         call    fd_find_lfn
  2520.         jmp     fs_GetFileInfo_finish
  2521.  
  2522. ret11:
  2523.         mov     eax, 11
  2524.         ret
  2525.  
  2526. fs_FloppySetFileInfo:
  2527.         call    read_flp_fat
  2528.         cmp     [FDC_Status], 0
  2529.         jnz     ret11
  2530.         cmp     byte [esi], 0
  2531.         jnz     @f
  2532.         mov     eax, 2  ; unsupported
  2533.         ret
  2534. @@:
  2535.         push    edi
  2536.         call    fd_find_lfn
  2537.         jnc     @f
  2538.         pop     edi
  2539.         mov     eax, ERROR_FILE_NOT_FOUND
  2540.         ret
  2541. @@:
  2542.         push    eax
  2543.         call    bdfe_to_fat_entry
  2544.         pop     eax
  2545.         pusha
  2546.         call    save_chs_sector
  2547.         popa
  2548.         pop     edi
  2549.         xor     eax, eax
  2550.         cmp     [FDC_Status], 0
  2551.         jz      @f
  2552.         mov     al, 11
  2553. @@:
  2554.         ret
  2555.  
  2556. if 0
  2557. ;----------------------------------------------------------------
  2558. ;
  2559. ;  fs_FloppyExecute - LFN variant for executing from floppy
  2560. ;
  2561. ;  esi  points to floppy filename (e.g. 'dir1/name')
  2562. ;  ebp  points to full filename (e.g. '/fd/1/dir1/name')
  2563. ;  dword [ebx] = flags
  2564. ;  dword [ebx+4] = cmdline
  2565. ;
  2566. ;  ret ebx,edx destroyed
  2567. ;      eax > 0 - PID, < 0 - error
  2568. ;
  2569. ;--------------------------------------------------------------
  2570. fs_FloppyExecute:
  2571.         mov     edx, [ebx]
  2572.         mov     ebx, [ebx+4]
  2573.         test    ebx, ebx
  2574.         jz      @f
  2575.         add     ebx, std_application_base_address
  2576. @@:
  2577.  
  2578. ;----------------------------------------------------------------
  2579. ;
  2580. ; fs_FloppyExecute.flags - second entry
  2581. ;
  2582. ;  esi  points to floppy filename (kernel address)
  2583. ;  ebp  points to full filename
  2584. ;  edx  flags
  2585. ;  ebx  cmdline (kernel address)
  2586. ;
  2587. ;  ret  eax > 0 - PID, < 0 - error
  2588. ;
  2589. ;--------------------------------------------------------------
  2590.  
  2591. .flags:
  2592.         call    read_flp_fat
  2593.         cmp     byte [esi], 0
  2594.         jnz     @f
  2595. ; cannot execute root!
  2596.         mov     eax, -ERROR_ACCESS_DENIED
  2597.         ret
  2598. @@:
  2599.         push    edi
  2600.         call    fd_find_lfn
  2601.         jnc     .found
  2602.         pop     edi
  2603.         mov     eax, -ERROR_FILE_NOT_FOUND
  2604.         ret
  2605. .found:
  2606.         movzx   eax, word [edi+26]      ; cluster
  2607.         push    eax
  2608.         push    dword [edi+28]          ; size
  2609.         push    .DoRead
  2610.         call    fs_execute
  2611.         add     esp, 12
  2612.         pop     edi
  2613.         ret
  2614.  
  2615. .DoRead:
  2616. ; read next block
  2617. ; in: eax->parameters, edi->buffer
  2618. ; out: eax = error code
  2619.         pushad
  2620.         cmp     dword [eax], 0  ; file size
  2621.         jz      .eof
  2622.         mov     eax, [eax+4]    ; cluster
  2623.         add     eax, 31
  2624.         call    read_chs_sector
  2625.         cmp     [FDC_Status], 0
  2626.         jnz     .err
  2627.         pop     edi
  2628.         mov     esi, FDD_BUFF
  2629.         push    edi
  2630.         mov     ecx, 512/4
  2631.         rep     movsd
  2632.         mov     eax, [esp+28]
  2633.         mov     ecx, [eax]
  2634.         sub     ecx, 512
  2635.         jae     @f
  2636.         add     edi, ecx
  2637.         neg     ecx
  2638.         push    eax
  2639.         xor     eax, eax
  2640.         rep     stosb
  2641.         pop     eax
  2642. @@:
  2643.         mov     [eax], ecx
  2644.         mov     edx, [eax+4]
  2645.         mov     dx, [edx*2+0x282000]
  2646.         mov     [eax+4], dx     ; high word is already zero
  2647.         popad
  2648.         xor     eax, eax
  2649.         ret
  2650. .eof:
  2651.         popad
  2652.         mov     eax, 6
  2653.         ret
  2654. .err:
  2655.         popad
  2656.         mov     eax, 11
  2657.         ret
  2658. end if
  2659.  
  2660. ;----------------------------------------------------------------
  2661. ;
  2662. ;  fs_FloppyDelete - delete file or empty folder from floppy
  2663. ;
  2664. ;  esi  points to filename
  2665. ;
  2666. ;  ret  eax = 0 ok or other = errormsg
  2667. ;
  2668. ;--------------------------------------------------------------
  2669. fs_FloppyDelete:
  2670.         call    read_flp_fat
  2671.         cmp     [FDC_Status], 0
  2672.         jz      @f
  2673.         push    11
  2674.         jmp     .pop_ret
  2675. @@:
  2676.         cmp     byte [esi], 0
  2677.         jnz     @f
  2678. ; cannot delete root!
  2679. .access_denied:
  2680.         push    ERROR_ACCESS_DENIED
  2681. .pop_ret:
  2682.         pop     eax
  2683.         ret
  2684. @@:
  2685.         and     [fd_prev_sector], 0
  2686.         and     [fd_prev_prev_sector], 0
  2687.         push    edi
  2688.         call    fd_find_lfn
  2689.         jnc     .found
  2690.         pop     edi
  2691.         push    ERROR_FILE_NOT_FOUND
  2692.         jmp     .pop_ret
  2693. .found:
  2694.         cmp     dword [edi], '.   '
  2695.         jz      .access_denied2
  2696.         cmp     dword [edi], '..  '
  2697.         jz      .access_denied2
  2698.         test    byte [edi+11], 10h
  2699.         jz      .dodel
  2700. ; we can delete only empty folders!
  2701.         push    eax
  2702.         movzx   eax, word [edi+26]
  2703.         push    ebx
  2704.         pusha
  2705.         add     eax, 31
  2706.         call    read_chs_sector
  2707.         popa
  2708.         mov     ebx, FDD_BUFF + 2*0x20
  2709. .checkempty:
  2710.         cmp     byte [ebx], 0
  2711.         jz      .empty
  2712.         cmp     byte [ebx], 0xE5
  2713.         jnz     .notempty
  2714.         add     ebx, 0x20
  2715.         cmp     ebx, FDD_BUFF + 0x200
  2716.         jb      .checkempty
  2717.         movzx   eax, word [FLOPPY_FAT + eax*2]
  2718.         pusha
  2719.         add     eax, 31
  2720.         call    read_chs_sector
  2721.         popa
  2722.         mov     ebx, FDD_BUFF
  2723.         jmp     .checkempty
  2724. .notempty:
  2725.         pop     ebx
  2726.         pop     eax
  2727. .access_denied2:
  2728.         pop     edi
  2729.         jmp     .access_denied
  2730. .empty:
  2731.         pop     ebx
  2732.         pop     eax
  2733.         pusha
  2734.         call    read_chs_sector
  2735.         popa
  2736. .dodel:
  2737.         push    eax
  2738.         movzx   eax, word [edi+26]
  2739.         xchg    eax, [esp]
  2740. ; delete folder entry
  2741.         mov     byte [edi], 0xE5
  2742. ; delete LFN (if present)
  2743. .lfndel:
  2744.         cmp     edi, FDD_BUFF
  2745.         ja      @f
  2746.         cmp     [fd_prev_sector], 0
  2747.         jz      .lfndone
  2748.         push    [fd_prev_sector]
  2749.         push    [fd_prev_prev_sector]
  2750.         pop     [fd_prev_sector]
  2751.         and     [fd_prev_prev_sector], 0
  2752.         pusha
  2753.         call    save_chs_sector
  2754.         popa
  2755.         pop     eax
  2756.         pusha
  2757.         call    read_chs_sector
  2758.         popa
  2759.         mov     edi, FDD_BUFF+0x200
  2760. @@:
  2761.         sub     edi, 0x20
  2762.         cmp     byte [edi], 0xE5
  2763.         jz      .lfndone
  2764.         cmp     byte [edi+11], 0xF
  2765.         jnz     .lfndone
  2766.         mov     byte [edi], 0xE5
  2767.         jmp     .lfndel
  2768. .lfndone:
  2769.         pusha
  2770.         call    save_chs_sector
  2771.         popa
  2772. ; delete FAT chain
  2773.         pop     eax
  2774.         test    eax, eax
  2775.         jz      .done
  2776. @@:
  2777.         lea     eax, [FLOPPY_FAT + eax*2]
  2778.         push    dword [eax]
  2779.         and     word [eax], 0
  2780.         pop     eax
  2781.         and     eax, 0xFFF
  2782.         jnz     @b
  2783. .done:
  2784.         call    save_flp_fat
  2785.         pop     edi
  2786.         xor     eax, eax
  2787.         ret
  2788.  
  2789. ; \end{diamond}
  2790.