Subversion Repositories Kolibri OS

Rev

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