Subversion Repositories Kolibri OS

Rev

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