Subversion Repositories Kolibri OS

Rev

Rev 495 | Blame | Last modification | View Log | Download | RSS feed

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