Subversion Repositories Kolibri OS

Rev

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

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