Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2011. 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: 3908 $
  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.  
  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    FDDMotorON
  358.         call    RecalibrateFDD
  359.         cmp     [FDC_Status], 0
  360.         jne     fdc_status_error
  361.         call    SeekTrack
  362.         cmp     [FDC_Status], 0
  363.         jne     fdc_status_error
  364.         call    ReadSectWithRetr
  365.         cmp     [FDC_Status], 0
  366.         jne     fdc_status_error
  367.         mov     esi, flp_label
  368.         mov     edi, FDD_BUFF+39
  369.         mov     ecx, 15
  370.         cld
  371.         rep cmpsb
  372.         je      same_label
  373.         mov     [root_read], 0
  374.         mov     [flp_fat], 0
  375. same_label:
  376.         mov     esi, FDD_BUFF+39
  377.         mov     edi, flp_label
  378.         mov     ecx, 15
  379.         cld
  380.         rep movsb
  381.         popad
  382.         ret
  383. fdc_status_error:
  384.         popad
  385.         ret
  386.  
  387. save_flp_root:
  388.         pusha
  389.         call    check_label
  390.         cmp     [FDC_Status], 0
  391.         jne     unnecessary_root_save
  392.         cmp     [root_read], 0
  393.         je      unnecessary_root_save
  394.         mov     [FDD_Track], 0; Цилиндр
  395.         mov     [FDD_Head], 1; Сторона
  396.         mov     [FDD_Sector], 2; Сектор
  397.         mov     esi, FLOPPY_BUFF
  398.         call    SeekTrack
  399. save_flp_root_1:
  400.         push    esi
  401.         call    take_data_from_application_1
  402.         pop     esi
  403.         add     esi, 512
  404.         call    WriteSectWithRetr
  405.         cmp     [FDC_Status], 0
  406.         jne     unnecessary_root_save
  407.         inc     [FDD_Sector]
  408.         cmp     [FDD_Sector], 16
  409.         jne     save_flp_root_1
  410. unnecessary_root_save:
  411.         popa
  412.         ret
  413.  
  414. save_flp_fat:
  415.         pusha
  416.         call    check_label
  417.         cmp     [FDC_Status], 0
  418.         jne     unnecessary_flp_fat_save
  419.         cmp     [flp_fat], 0
  420.         je      unnecessary_flp_fat_save
  421.         call    restorefatchain_flp
  422.         mov     [FDD_Track], 0; Цилиндр
  423.         mov     [FDD_Head], 0; Сторона
  424.         mov     [FDD_Sector], 2; Сектор
  425.         mov     esi, FLOPPY_BUFF
  426.         call    SeekTrack
  427. save_flp_fat_1:
  428.         push    esi
  429.         call    take_data_from_application_1
  430.         pop     esi
  431.         add     esi, 512
  432.         call    WriteSectWithRetr
  433.         cmp     [FDC_Status], 0
  434.         jne     unnecessary_flp_fat_save
  435.         inc     [FDD_Sector]
  436.         cmp     [FDD_Sector], 19
  437.         jne     save_flp_fat_1
  438.         mov     [FDD_Sector], 1
  439.         mov     [FDD_Head], 1
  440.         call    take_data_from_application_1
  441.         call    WriteSectWithRetr
  442.         cmp     [FDC_Status], 0
  443.         jne     unnecessary_flp_fat_save
  444.         mov     [root_read], 0
  445. unnecessary_flp_fat_save:
  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.         test    edx, edx
  503.         jz      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, eax=error code
  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.         push    0               ; for fat_get_name: read ASCII name
  642. .l1:
  643.         lea     ebp, [esp+4]
  644.         call    fat_get_name
  645.         jc      .l2
  646.         call    fat_compare_name
  647.         jz      .found
  648. .l2:
  649.         mov     ebp, [esp+8+262*2+4]
  650.         lea     eax, [esp+0Ch+20h+262*2+4]
  651.         call    dword [eax-8]
  652.         jnc     .l1
  653.         add     esp, 262*2+4
  654. .reterr:
  655.         mov     [esp+28], eax
  656.         stc
  657.         popa
  658.         ret
  659. .found:
  660.         add     esp, 262*2+4
  661.         mov     ebp, [esp+8]
  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.         movi    eax, 1     ; 1 entry
  1312.         jnz     .notilde
  1313. ; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
  1314.         xor     eax, eax
  1315. @@:
  1316.         cmp     byte [esi], 0
  1317.         jz      @f
  1318.         inc     esi
  1319.         inc     eax
  1320.         jmp     @b
  1321. @@:
  1322.         sub     esi, eax
  1323.         add     eax, 12+13
  1324.         mov     ecx, 13
  1325.         push    edx
  1326.         cdq
  1327.         div     ecx
  1328.         pop     edx
  1329. .notilde:
  1330.         push    -1
  1331.         push    -1
  1332. ; find <eax> successive entries in directory
  1333.         xor     ecx, ecx
  1334.         push    eax
  1335.         lea     eax, [esp+12+8+12+8]
  1336.         mov     [eax], ebp
  1337.         call    dword [eax-4]
  1338.         pop     eax
  1339.         jnc     .scan_dir
  1340. .fsfrfe3:
  1341.         add     esp, 8+8+12+28
  1342.         popad
  1343.         mov     eax, 11
  1344.         xor     ebx, ebx
  1345.         ret
  1346. .scan_dir:
  1347.         cmp     byte [edi], 0
  1348.         jz      .free
  1349.         cmp     byte [edi], 0xE5
  1350.         jz      .free
  1351.         xor     ecx, ecx
  1352. .scan_cont:
  1353.         push    eax
  1354.         lea     eax, [esp+12+8+12+8]
  1355.         call    dword [eax-8]
  1356.         pop     eax
  1357.         jnc     .scan_dir
  1358.         cmp     [FDC_Status], 0
  1359.         jnz     .fsfrfe3
  1360.         push    eax
  1361.         lea     eax, [esp+12+8+12+8]
  1362.         call    dword [eax+16]          ; extend directory
  1363.         pop     eax
  1364.         jnc     .scan_dir
  1365.         add     esp, 8+8+12+28
  1366.         popad
  1367.         mov     eax, ERROR_DISK_FULL
  1368.         xor     ebx, ebx
  1369.         ret
  1370. .free:
  1371.         test    ecx, ecx
  1372.         jnz     @f
  1373.         mov     [esp], edi
  1374.         mov     ecx, [esp+8+8+12+8]
  1375.         mov     [esp+4], ecx
  1376.         xor     ecx, ecx
  1377. @@:
  1378.         inc     ecx
  1379.         cmp     ecx, eax
  1380.         jb      .scan_cont
  1381. ; found!
  1382. ; calculate name checksum
  1383.         push    esi ecx
  1384.         mov     esi, [esp+8+8]
  1385.         mov     ecx, 11
  1386.         xor     eax, eax
  1387. @@:
  1388.         ror     al, 1
  1389.         add     al, [esi]
  1390.         inc     esi
  1391.         loop    @b
  1392.         pop     ecx esi
  1393.         pop     edi
  1394.         pop     dword [esp+8+12+8]
  1395. ; edi points to first entry in free chunk
  1396.         dec     ecx
  1397.         jz      .nolfn
  1398.         push    esi
  1399.         push    eax
  1400.         lea     eax, [esp+8+8+12+8]
  1401.         call    dword [eax+4]         ; begin write
  1402.         mov     al, 40h
  1403. .writelfn:
  1404.         or      al, cl
  1405.         mov     esi, [esp+4]
  1406.         push    ecx
  1407.         dec     ecx
  1408.         imul    ecx, 13
  1409.         add     esi, ecx
  1410.         stosb
  1411.         mov     cl, 5
  1412.         call    fs_RamdiskRewrite.read_symbols
  1413.         mov     ax, 0xF
  1414.         stosw
  1415.         mov     al, [esp+4]
  1416.         stosb
  1417.         mov     cl, 6
  1418.         call    fs_RamdiskRewrite.read_symbols
  1419.         xor     eax, eax
  1420.         stosw
  1421.         mov     cl, 2
  1422.         call    fs_RamdiskRewrite.read_symbols
  1423.         pop     ecx
  1424.         lea     eax, [esp+8+8+12+8]
  1425.         call    dword [eax+8]         ; next write
  1426.         xor     eax, eax
  1427.         loop    .writelfn
  1428.         pop     eax
  1429.         pop     esi
  1430. ;        lea     eax, [esp+8+12+8]
  1431. ;        call    dword [eax+12]          ; end write
  1432. .nolfn:
  1433.         xchg    esi, [esp]
  1434.         mov     ecx, 11
  1435.         rep movsb
  1436.         mov     word [edi], 20h         ; attributes
  1437.         sub     edi, 11
  1438.         pop     esi ecx
  1439.         add     esp, 12
  1440.         mov     byte [edi+13], 0        ; tenths of a second at file creation time
  1441.         call    get_time_for_file
  1442.         mov     [edi+14], ax            ; creation time
  1443.         mov     [edi+22], ax            ; last write time
  1444.         call    get_date_for_file
  1445.         mov     [edi+16], ax            ; creation date
  1446.         mov     [edi+24], ax            ; last write date
  1447.         mov     [edi+18], ax            ; last access date
  1448.         and     word [edi+20], 0        ; high word of cluster
  1449.         and     word [edi+26], 0        ; low word of cluster - to be filled
  1450.         and     dword [edi+28], 0       ; file size - to be filled
  1451.         cmp     byte [esp+28+28], 0
  1452.         jz      .doit
  1453. ; create directory
  1454.         mov     byte [edi+11], 10h      ; attributes: folder
  1455.         mov     ecx, 32*2
  1456.         mov     edx, edi
  1457. .doit:
  1458.         lea     eax, [esp+8]
  1459.         call    dword [eax+12]  ; flush directory
  1460.         push    ecx
  1461.         push    edi
  1462.         push    0
  1463.         mov     esi, edx
  1464.         test    ecx, ecx
  1465.         jz      .done
  1466.         mov     ecx, 2849
  1467.         mov     edi, FLOPPY_FAT
  1468.         push    0       ; first cluster
  1469. .write_loop:
  1470. ; allocate new cluster
  1471.         xor     eax, eax
  1472.         repnz scasw
  1473.         mov     al, ERROR_DISK_FULL
  1474.         jnz     .ret
  1475.         dec     edi
  1476.         dec     edi
  1477.  
  1478.         mov     eax, edi
  1479.         sub     eax, FLOPPY_FAT
  1480.  
  1481.         shr     eax, 1                  ; eax = cluster
  1482.         mov     word [edi], 0xFFF       ; mark as last cluster
  1483.         xchg    edi, [esp+4]
  1484.         cmp     dword [esp], 0
  1485.         jz      .first
  1486.         stosw
  1487.         jmp     @f
  1488. .first:
  1489.         mov     [esp], eax
  1490. @@:
  1491.         mov     edi, [esp+4]
  1492.         inc     ecx
  1493. ; write data
  1494.         push    ecx edi
  1495.         mov     ecx, 512
  1496.         cmp     dword [esp+20], ecx
  1497.         jae     @f
  1498.         mov     ecx, [esp+20]
  1499. @@:
  1500.         mov     edi, FDD_BUFF
  1501.         cmp     byte [esp+24+28+28], 0
  1502.         jnz     .writedir
  1503.         push    ecx
  1504.         rep movsb
  1505.         pop     ecx
  1506. .writedircont:
  1507.         push    ecx
  1508.         sub     ecx, 512
  1509.         neg     ecx
  1510.         push    eax
  1511.         xor     eax, eax
  1512.         rep stosb
  1513.         pop     eax
  1514.         add     eax, 31
  1515.         pusha
  1516.         call    save_chs_sector
  1517.         popa
  1518.         pop     ecx
  1519.         cmp     [FDC_Status], 0
  1520.         jnz     .diskerr
  1521.         sub     [esp+20], ecx
  1522.         pop     edi ecx
  1523.         jnz     .write_loop
  1524. .done:
  1525.         xor     eax, eax
  1526. .ret:
  1527.         pop     ebx edi edi ecx
  1528.         mov     [esp+28+28], eax
  1529.         lea     eax, [esp+8]
  1530.         call    dword [eax+4]
  1531.         mov     [edi+26], bx
  1532.         mov     ebx, esi
  1533.         sub     ebx, edx
  1534.         mov     [edi+28], ebx
  1535.         call    dword [eax+12]
  1536.         mov     [esp+28+16], ebx
  1537.         test    ebp, ebp
  1538.         jnz     @f
  1539.         call    save_flp_root
  1540. @@:
  1541.         add     esp, 28
  1542.         cmp     [FDC_Status], 0
  1543.         jnz     .err3
  1544.         call    save_flp_fat
  1545.         cmp     [FDC_Status], 0
  1546.         jnz     .err3
  1547.         popa
  1548.         ret
  1549. .err3:
  1550.         popa
  1551.         mov     al, 11
  1552.         xor     ebx, ebx
  1553.         ret
  1554. .diskerr:
  1555.         sub     esi, ecx
  1556.         mov     eax, 11
  1557.         pop     edi ecx
  1558.         jmp     .ret
  1559. .writedir:
  1560.         push    ecx
  1561.         mov     ecx, 32/4
  1562.         push    ecx esi
  1563.         rep movsd
  1564.         pop     esi ecx
  1565.         mov     dword [edi-32], '.   '
  1566.         mov     dword [edi-32+4], '    '
  1567.         mov     dword [edi-32+8], '    '
  1568.         mov     byte [edi-32+11], 10h
  1569.         mov     word [edi-32+26], ax
  1570.         push    esi
  1571.         rep movsd
  1572.         pop     esi
  1573.         mov     dword [edi-32], '..  '
  1574.         mov     dword [edi-32+4], '    '
  1575.         mov     dword [edi-32+8], '    '
  1576.         mov     byte [edi-32+11], 10h
  1577.         mov     ecx, [esp+28+8]
  1578.         mov     word [edi-32+26], cx
  1579.         pop     ecx
  1580.         jmp     .writedircont
  1581.  
  1582. ;----------------------------------------------------------------
  1583. ;
  1584. ;  fs_FloppyWrite - LFN variant for writing to floppy
  1585. ;
  1586. ;  esi  points to filename
  1587. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  1588. ;       may be ebx=0 - start from first byte
  1589. ;  ecx  number of bytes to write, 0+
  1590. ;  edx  mem location to data
  1591. ;
  1592. ;  ret ebx = bytes written (maybe 0)
  1593. ;      eax = 0 ok write or other = errormsg
  1594. ;
  1595. ;--------------------------------------------------------------
  1596.  
  1597. @@:
  1598.         push    ERROR_ACCESS_DENIED
  1599. fs_FloppyWrite.ret0:
  1600.         pop     eax
  1601.         xor     ebx, ebx
  1602.         ret
  1603.  
  1604. fs_FloppyWrite.ret11:
  1605.         push    11
  1606.         jmp     fs_FloppyWrite.ret0
  1607.  
  1608. fs_FloppyWrite:
  1609.         cmp     byte [esi], 0
  1610.         jz      @b
  1611.         call    read_flp_fat
  1612.         cmp     [FDC_Status], 0
  1613.         jnz     .ret11
  1614.         pushad
  1615.         call    fd_find_lfn
  1616.         jnc     .found
  1617.         popad
  1618.         push    ERROR_FILE_NOT_FOUND
  1619.         jmp     .ret0
  1620. .found:
  1621. ; FAT does not support files larger than 4GB
  1622.         test    ebx, ebx
  1623.         jz      .l1
  1624.         cmp     dword [ebx+4], 0
  1625.         jz      @f
  1626. .eof:
  1627.         popad
  1628.         push    ERROR_END_OF_FILE
  1629.         jmp     .ret0
  1630. @@:
  1631.         mov     ebx, [ebx]
  1632. .l1:
  1633. ; now edi points to direntry, ebx=start byte to write,
  1634. ; ecx=number of bytes to write, edx=data pointer
  1635.  
  1636. ; extend file if needed
  1637.         add     ecx, ebx
  1638.         jc      .eof    ; FAT does not support files larger than 4GB
  1639.         push    eax     ; save directory cluster
  1640.         push    0       ; return value=0
  1641.  
  1642.         call    get_time_for_file
  1643.         mov     [edi+22], ax            ; last write time
  1644.         call    get_date_for_file
  1645.         mov     [edi+24], ax            ; last write date
  1646.         mov     [edi+18], ax            ; last access date
  1647.  
  1648.         push    dword [edi+28]          ; save current file size
  1649.         cmp     ecx, [edi+28]
  1650.         jbe     .length_ok
  1651.         cmp     ecx, ebx
  1652.         jz      .length_ok
  1653.         call    floppy_extend_file
  1654.         jnc     .length_ok
  1655.         mov     [esp+4], eax
  1656. ; floppy_extend_file can return two error codes: FAT table error or disk full.
  1657. ; First case is fatal error, in second case we may write some data
  1658.         cmp     al, ERROR_DISK_FULL
  1659.         jz      .disk_full
  1660.         pop     eax
  1661.         pop     eax
  1662.         mov     [esp+4+28], eax
  1663.         pop     eax
  1664.         popad
  1665.         xor     ebx, ebx
  1666.         ret
  1667. .disk_full:
  1668. ; correct number of bytes to write
  1669.         mov     ecx, [edi+28]
  1670.         cmp     ecx, ebx
  1671.         ja      .length_ok
  1672. .ret:
  1673.         pop     eax
  1674.         pop     eax
  1675.         mov     [esp+4+28], eax ; eax=return value
  1676.         pop     eax
  1677.         sub     edx, [esp+20]
  1678.         mov     [esp+16], edx   ; ebx=number of written bytes
  1679.         popad
  1680.         ret
  1681. .length_ok:
  1682. ; save FAT & directory
  1683. ; note that directory must be saved first because save_flp_fat uses buffer at 0xD000
  1684.         mov     esi, [edi+28]
  1685.         movzx   edi, word [edi+26]      ; starting cluster
  1686.         mov     eax, [esp+8]
  1687.         pusha
  1688.         call    save_chs_sector
  1689.         popa
  1690.         cmp     [FDC_Status], 0
  1691.         jnz     .device_err
  1692.         call    save_flp_fat
  1693.         cmp     [FDC_Status], 0
  1694.         jz      @f
  1695. .device_err:
  1696.         mov     byte [esp+4], 11
  1697.         jmp     .ret
  1698. @@:
  1699.  
  1700. ; now ebx=start pos, ecx=end pos, both lie inside file
  1701.         sub     ecx, ebx
  1702.         jz      .ret
  1703.  
  1704. .write_loop:
  1705. ; skip unmodified sectors
  1706.         cmp     dword [esp], 0x200
  1707.         jb      .modify
  1708.         sub     ebx, 0x200
  1709.         jae     .skip
  1710.         add     ebx, 0x200
  1711. .modify:
  1712.         lea     eax, [edi+31]   ; current sector
  1713. ; get length of data in current sector
  1714.         push    ecx
  1715.         sub     ebx, 0x200
  1716.         jb      .hasdata
  1717.         neg     ebx
  1718.         xor     ecx, ecx
  1719.         jmp     @f
  1720. .hasdata:
  1721.         neg     ebx
  1722.         cmp     ecx, ebx
  1723.         jbe     @f
  1724.         mov     ecx, ebx
  1725. @@:
  1726. ; load sector if needed
  1727.         cmp     dword [esp+4], 0        ; we don't need to read uninitialized data
  1728.         jz      .noread
  1729.         cmp     ecx, 0x200      ; we don't need to read sector if it is fully rewritten
  1730.         jz      .noread
  1731.         cmp     ecx, esi        ; (same for the last sector)
  1732.         jz      .noread
  1733.         pusha
  1734.         call    read_chs_sector
  1735.         popa
  1736.         cmp     [FDC_Status], 0
  1737.         jz      @f
  1738. .device_err2:
  1739.         pop     ecx
  1740.         jmp     .device_err
  1741. @@:
  1742. .noread:
  1743. ; zero uninitialized data if file was extended (because floppy_extend_file does not this)
  1744.         push    eax ecx edi
  1745.         xor     eax, eax
  1746.         mov     ecx, 0x200
  1747.         sub     ecx, [esp+4+12]
  1748.         jbe     @f
  1749.         mov     edi, FDD_BUFF
  1750.         add     edi, [esp+4+12]
  1751.         rep stosb
  1752. @@:
  1753. ; zero uninitialized data in the last sector
  1754.         mov     ecx, 0x200
  1755.         sub     ecx, esi
  1756.         jbe     @f
  1757.         mov     edi, FDD_BUFF
  1758.         add     edi, esi
  1759.         rep stosb
  1760. @@:
  1761.         pop     edi ecx eax
  1762. ; copy new data
  1763.         push    eax
  1764.         mov     eax, edx
  1765.         neg     ebx
  1766.         jecxz   @f
  1767.         add     ebx, FDD_BUFF+0x200
  1768.         call    memmove
  1769.         xor     ebx, ebx
  1770. @@:
  1771.         pop     eax
  1772. ; save sector
  1773.         pusha
  1774.         call    save_chs_sector
  1775.         popa
  1776.         cmp     [FDC_Status], 0
  1777.         jnz     .device_err2
  1778.         add     edx, ecx
  1779.         sub     [esp], ecx
  1780.         pop     ecx
  1781.         jz      .done
  1782. .skip:
  1783. .next_cluster:
  1784.         movzx   edi, word [edi*2+FLOPPY_FAT]
  1785.         sub     esi, 0x200
  1786.         jae     @f
  1787.         xor     esi, esi
  1788. @@:
  1789.         sub     dword [esp], 0x200
  1790.         jae     .write_loop
  1791.         and     dword [esp], 0
  1792.         jmp     .write_loop
  1793. .done:
  1794.         jmp     .ret
  1795.  
  1796. floppy_extend_file.zero_size:
  1797.         xor     eax, eax
  1798.         jmp     floppy_extend_file.start_extend
  1799.  
  1800. ; extends file on floppy to given size (new data area is undefined)
  1801. ; in: edi->direntry, ecx=new size
  1802. ; out: CF=0 => OK, eax=0
  1803. ;      CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL)
  1804. floppy_extend_file:
  1805.         push    ecx
  1806. ; find the last cluster of file
  1807.         movzx   eax, word [edi+26]      ; first cluster
  1808.         mov     ecx, [edi+28]
  1809.         jecxz   .zero_size
  1810. @@:
  1811.         sub     ecx, 0x200
  1812.         jbe     @f
  1813.         mov     eax, [eax*2+FLOPPY_FAT]
  1814.         and     eax, 0xFFF
  1815.         jz      .fat_err
  1816.         cmp     eax, 0xFF8
  1817.         jb      @b
  1818. .fat_err:
  1819.         pop     ecx
  1820.         movi    eax, ERROR_FAT_TABLE
  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.         movi    eax, ERROR_DISK_FULL
  1883.         ret
  1884.  
  1885. ;----------------------------------------------------------------
  1886. ;
  1887. ;  fs_FloppySetFileEnd - set end of file on floppy
  1888. ;
  1889. ;  esi  points to filename
  1890. ;  ebx  points to 64-bit number = new file size
  1891. ;  ecx  ignored (reserved)
  1892. ;  edx  ignored (reserved)
  1893. ;
  1894. ;  ret eax = 0 ok or other = errormsg
  1895. ;
  1896. ;--------------------------------------------------------------
  1897. fs_FloppySetFileEnd:
  1898.         call    read_flp_fat
  1899.         cmp     [FDC_Status], 0
  1900.         jnz     ret11
  1901.         cmp     byte [esi], 0
  1902.         jnz     @f
  1903. .access_denied:
  1904.         push    ERROR_ACCESS_DENIED
  1905.         jmp     .ret
  1906. @@:
  1907.         push    edi
  1908.         call    fd_find_lfn
  1909.         jnc     @f
  1910.         pop     edi
  1911.         push    ERROR_FILE_NOT_FOUND
  1912. .ret:
  1913.         pop     eax
  1914.         jmp     .doret
  1915. @@:
  1916. ; must not be directory
  1917.         test    byte [edi+11], 10h
  1918.         jz      @f
  1919.         pop     edi
  1920.         jmp     .access_denied
  1921. @@:
  1922. ; file size must not exceed 4 Gb
  1923.         cmp     dword [ebx+4], 0
  1924.         jz      @f
  1925.         pop     edi
  1926.         push    ERROR_END_OF_FILE
  1927.         jmp     .ret
  1928. @@:
  1929.         push    eax
  1930. ; set file modification date/time to current
  1931.         call    fat_update_datetime
  1932.         mov     eax, [ebx]
  1933.         cmp     eax, [edi+28]
  1934.         jb      .truncate
  1935.         ja      .expand
  1936.         pop     eax
  1937.         pushad
  1938.         call    save_chs_sector
  1939.         popad
  1940.         pop     edi
  1941.         xor     eax, eax
  1942.         cmp     [FDC_Status], 0
  1943.         jz      @f
  1944.         mov     al, 11
  1945. @@:
  1946. .doret:
  1947.         ret
  1948. .expand:
  1949.         push    ecx
  1950.         push    dword [edi+28]  ; save old size
  1951.         mov     ecx, eax
  1952.         call    floppy_extend_file
  1953.         push    eax     ; return code
  1954.         jnc     .expand_ok
  1955.         cmp     al, ERROR_DISK_FULL
  1956.         jz      .disk_full
  1957.         pop     eax ecx ecx edi edi
  1958.         jmp     .doret
  1959. .device_err:
  1960.         pop     eax
  1961. .device_err2:
  1962.         pop     ecx ecx eax edi
  1963.         push    11
  1964.         jmp     .ret
  1965. .disk_full:
  1966. .expand_ok:
  1967. ; save directory & FAT
  1968.         mov     eax, [edi+28]
  1969.         xchg    eax, [esp+12]
  1970.         movzx   edi, word [edi+26]
  1971.         pusha
  1972.         call    save_chs_sector
  1973.         popa
  1974.         cmp     [FDC_Status], 0
  1975.         jnz     .device_err
  1976.         call    save_flp_fat
  1977.         cmp     [FDC_Status], 0
  1978.         jnz     .device_err
  1979. ; now zero new data
  1980. ; edi = current cluster, [esp+12]=new size, [esp+4]=old size, [esp]=return code
  1981. .zero_loop:
  1982.         sub     dword [esp+4], 0x200
  1983.         jae     .next_cluster
  1984.         cmp     dword [esp+4], -0x200
  1985.         jz      .noread
  1986.         lea     eax, [edi+31]
  1987.         pusha
  1988.         call    read_chs_sector
  1989.         popa
  1990.         cmp     [FDC_Status], 0
  1991.         jnz     .err_next
  1992. .noread:
  1993.         mov     ecx, [esp+4]
  1994.         neg     ecx
  1995.         push    edi
  1996.         mov     edi, FDD_BUFF+0x200
  1997.         add     edi, [esp+8]
  1998.         xor     eax, eax
  1999.         mov     [esp+8], eax
  2000.         rep stosb
  2001.         pop     edi
  2002.         lea     eax, [edi+31]
  2003.         pusha
  2004.         call    save_chs_sector
  2005.         popa
  2006.         cmp     [FDC_Status], 0
  2007.         jz      .next_cluster
  2008. .err_next:
  2009.         mov     byte [esp], 11
  2010. .next_cluster:
  2011.         sub     dword [esp+12], 0x200
  2012.         jbe     .expand_done
  2013.         movzx   edi, word [FLOPPY_FAT+edi*2]
  2014.         jmp     .zero_loop
  2015. .expand_done:
  2016.         pop     eax ecx ecx edi edi
  2017.         jmp     .doret
  2018. .truncate:
  2019.         mov     [edi+28], eax
  2020.         push    ecx
  2021.         movzx   ecx, word [edi+26]
  2022.         test    eax, eax
  2023.         jz      .zero_size
  2024. ; find new last sector
  2025. @@:
  2026.         sub     eax, 0x200
  2027.         jbe     @f
  2028.         movzx   ecx, word [FLOPPY_FAT+ecx*2]
  2029.         jmp     @b
  2030. @@:
  2031. ; we will zero data at the end of last sector - remember it
  2032.         push    ecx
  2033. ; terminate FAT chain
  2034.         lea     ecx, [FLOPPY_FAT+ecx+ecx]
  2035.         push    dword [ecx]
  2036.         mov     word [ecx], 0xFFF
  2037.         pop     ecx
  2038.         and     ecx, 0xFFF
  2039.         jmp     .delete
  2040. .zero_size:
  2041.         and     word [edi+26], 0
  2042.         push    0
  2043. .delete:
  2044. ; delete FAT chain starting with ecx
  2045. ; mark all clusters as free
  2046.         cmp     ecx, 0xFF8
  2047.         jae     .deleted
  2048.         lea     ecx, [FLOPPY_FAT+ecx+ecx]
  2049.         push    dword [ecx]
  2050.         and     word [ecx], 0
  2051.         pop     ecx
  2052.         and     ecx, 0xFFF
  2053.         jmp     .delete
  2054. .deleted:
  2055.         mov     edi, [edi+28]
  2056. ; save directory & FAT
  2057.         mov     eax, [esp+8]
  2058.         pusha
  2059.         call    save_chs_sector
  2060.         popa
  2061.         cmp     [FDC_Status], 0
  2062.         jnz     .device_err2
  2063.         call    save_flp_fat
  2064.         cmp     [FDC_Status], 0
  2065.         jnz     .device_err2
  2066. ; zero last sector, ignore errors
  2067.         pop     eax
  2068.         add     eax, 31
  2069.         and     edi, 0x1FF
  2070.         jz      .truncate_done
  2071.  
  2072.         pusha
  2073.         call    read_chs_sector
  2074.         popa
  2075.         add     edi, FDD_BUFF
  2076.         mov     ecx, FDD_BUFF+0x200
  2077.         sub     ecx, edi
  2078.         push    eax
  2079.         xor     eax, eax
  2080.         rep stosb
  2081.         pop     eax
  2082.         pusha
  2083.         call    save_chs_sector
  2084.         popa
  2085. .truncate_done:
  2086.         pop     ecx eax edi
  2087.         xor     eax, eax
  2088.         jmp     .doret
  2089.  
  2090. fs_FloppyGetFileInfo:
  2091.         call    read_flp_fat
  2092.         cmp     [FDC_Status], 0
  2093.         jnz     ret11
  2094.         cmp     byte [esi], 0
  2095.         jnz     @f
  2096.         mov     eax, 2  ; unsupported
  2097.         ret
  2098. @@:
  2099.         push    edi
  2100.         call    fd_find_lfn
  2101.         jmp     fs_GetFileInfo_finish
  2102.  
  2103. ret11:
  2104.         mov     eax, 11
  2105.         ret
  2106.  
  2107. fs_FloppySetFileInfo:
  2108.         call    read_flp_fat
  2109.         cmp     [FDC_Status], 0
  2110.         jnz     ret11
  2111.         cmp     byte [esi], 0
  2112.         jnz     @f
  2113.         mov     eax, 2  ; unsupported
  2114.         ret
  2115. @@:
  2116.         push    edi
  2117.         call    fd_find_lfn
  2118.         jnc     @f
  2119.         pop     edi
  2120.         mov     eax, ERROR_FILE_NOT_FOUND
  2121.         ret
  2122. @@:
  2123.         push    eax
  2124.         call    bdfe_to_fat_entry
  2125.         pop     eax
  2126.         pusha
  2127.         call    save_chs_sector
  2128.         popa
  2129.         pop     edi
  2130.         xor     eax, eax
  2131.         cmp     [FDC_Status], al
  2132.         jz      @f
  2133.         mov     al, 11
  2134. @@:
  2135.         ret
  2136.  
  2137. ;----------------------------------------------------------------
  2138. ;
  2139. ;  fs_FloppyDelete - delete file or empty folder from floppy
  2140. ;
  2141. ;  esi  points to filename
  2142. ;
  2143. ;  ret  eax = 0 ok or other = errormsg
  2144. ;
  2145. ;--------------------------------------------------------------
  2146. fs_FloppyDelete:
  2147.         call    read_flp_fat
  2148.         cmp     [FDC_Status], 0
  2149.         jz      @f
  2150.         push    11
  2151.         jmp     .pop_ret
  2152. @@:
  2153.         cmp     byte [esi], 0
  2154.         jnz     @f
  2155. ; cannot delete root!
  2156. .access_denied:
  2157.         push    ERROR_ACCESS_DENIED
  2158. .pop_ret:
  2159.         pop     eax
  2160.         ret
  2161. @@:
  2162.         and     [fd_prev_sector], 0
  2163.         and     [fd_prev_prev_sector], 0
  2164.         push    edi
  2165.         call    fd_find_lfn
  2166.         jnc     .found
  2167.         pop     edi
  2168.         push    ERROR_FILE_NOT_FOUND
  2169.         jmp     .pop_ret
  2170. .found:
  2171.         cmp     dword [edi], '.   '
  2172.         jz      .access_denied2
  2173.         cmp     dword [edi], '..  '
  2174.         jz      .access_denied2
  2175.         test    byte [edi+11], 10h
  2176.         jz      .dodel
  2177. ; we can delete only empty folders!
  2178.         push    eax
  2179.         movzx   eax, word [edi+26]
  2180.         push    ebx
  2181.         pusha
  2182.         add     eax, 31
  2183.         call    read_chs_sector
  2184.         popa
  2185.         mov     ebx, FDD_BUFF + 2*0x20
  2186. .checkempty:
  2187.         cmp     byte [ebx], 0
  2188.         jz      .empty
  2189.         cmp     byte [ebx], 0xE5
  2190.         jnz     .notempty
  2191.         add     ebx, 0x20
  2192.         cmp     ebx, FDD_BUFF + 0x200
  2193.         jb      .checkempty
  2194.         movzx   eax, word [FLOPPY_FAT + eax*2]
  2195.         pusha
  2196.         add     eax, 31
  2197.         call    read_chs_sector
  2198.         popa
  2199.         mov     ebx, FDD_BUFF
  2200.         jmp     .checkempty
  2201. .notempty:
  2202.         pop     ebx
  2203.         pop     eax
  2204. .access_denied2:
  2205.         pop     edi
  2206.         jmp     .access_denied
  2207. .empty:
  2208.         pop     ebx
  2209.         pop     eax
  2210.         pusha
  2211.         call    read_chs_sector
  2212.         popa
  2213. .dodel:
  2214.         push    eax
  2215.         movzx   eax, word [edi+26]
  2216.         xchg    eax, [esp]
  2217. ; delete folder entry
  2218.         mov     byte [edi], 0xE5
  2219. ; delete LFN (if present)
  2220. .lfndel:
  2221.         cmp     edi, FDD_BUFF
  2222.         ja      @f
  2223.         cmp     [fd_prev_sector], 0
  2224.         jz      .lfndone
  2225.         push    [fd_prev_sector]
  2226.         push    [fd_prev_prev_sector]
  2227.         pop     [fd_prev_sector]
  2228.         and     [fd_prev_prev_sector], 0
  2229.         pusha
  2230.         call    save_chs_sector
  2231.         popa
  2232.         pop     eax
  2233.         pusha
  2234.         call    read_chs_sector
  2235.         popa
  2236.         mov     edi, FDD_BUFF+0x200
  2237. @@:
  2238.         sub     edi, 0x20
  2239.         cmp     byte [edi], 0xE5
  2240.         jz      .lfndone
  2241.         cmp     byte [edi+11], 0xF
  2242.         jnz     .lfndone
  2243.         mov     byte [edi], 0xE5
  2244.         jmp     .lfndel
  2245. .lfndone:
  2246.         pusha
  2247.         call    save_chs_sector
  2248.         popa
  2249. ; delete FAT chain
  2250.         pop     eax
  2251. @@:
  2252.         cmp     eax, 2
  2253.         jb      .done
  2254.         cmp     eax, 0xFF8
  2255.         jae     .done
  2256.         lea     eax, [FLOPPY_FAT + eax*2]
  2257.         push    dword [eax]
  2258.         and     word [eax], 0
  2259.         pop     eax
  2260.         and     eax, 0xFFF
  2261.         jmp     @b
  2262. .done:
  2263.         call    save_flp_fat
  2264.         pop     edi
  2265.         xor     eax, eax
  2266.         ret
  2267.  
  2268. ; \end{diamond}
  2269.