Subversion Repositories Kolibri OS

Rev

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

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                                 ;;
  3. ;;  FAT32.INC                                                      ;;
  4. ;;                                                                 ;;
  5. ;;  FAT16/32 functions for MenuetOS                                ;;
  6. ;;                                                                 ;;
  7. ;;  Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it          ;;
  8. ;;                                                                 ;;
  9. ;;  See file COPYING for details                                   ;;
  10. ;;  04.05.2006 LFN read folder - diamond                           ;;
  11. ;;  29.04.2006 Elimination of hangup after the                     ;;
  12. ;;             expiration hd_wait_timeout -  Mario79               ;;          
  13. ;;  23.04.2006 LFN read file - diamond                             ;;
  14. ;;  28.01.2006 find all Fat16/32 partition in all input point      ;;
  15. ;;             to MBR, see file part_set.inc - Mario79             ;;
  16. ;;  15.01.2005 get file size/attr/date, file_append - ATV          ;;
  17. ;;  04.12.2004 skip volume label, file delete bug fixed - ATV      ;;
  18. ;;  29.11.2004 get_free_FAT changed, append dir bug fixed - ATV    ;;
  19. ;;  23.11.2004 don't allow overwrite dir with file - ATV           ;;
  20. ;;  18.11.2004 get_disk_info and more error codes - ATV            ;;
  21. ;;  17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV      ;;
  22. ;;  10.11.2004 removedir clear whole directory structure - ATV     ;;
  23. ;;  08.11.2004 rename - ATV                                        ;;
  24. ;;  30.10.2004 file_read return also dirsize in bytes - ATV        ;;
  25. ;;  20.10.2004 Makedir/Removedir - ATV                             ;;
  26. ;;  14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx)         ;;
  27. ;;  06.9.2004  Fix free space by Mario79 added - MH                ;;
  28. ;;  24.5.2004  Write back buffer for File_write -VT                ;;
  29. ;;  20.5.2004  File_read function to work with syscall 58 - VT     ;;
  30. ;;  30.3.2004  Error parameters at function return - VT            ;;
  31. ;;  01.5.2002  Bugfix in device write - VT                         ;;
  32. ;;  20.5.2002  Hd status check - VT                                ;;
  33. ;;  29.6.2002  Improved fat32 verification - VT                    ;;
  34. ;;                                                                 ;;
  35. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  36.  
  37. cache_max equ 1919      ; max. is 1919*512+0x610000=0x6ffe00
  38.  
  39. ERROR_SUCCESS        = 0
  40. ERROR_DISK_BASE      = 1
  41. ERROR_UNSUPPORTED_FS = 2
  42. ERROR_UNKNOWN_FS     = 3
  43. ERROR_PARTITION      = 4
  44. ERROR_FILE_NOT_FOUND = 5
  45. ERROR_END_OF_FILE    = 6
  46. ERROR_MEMORY_POINTER = 7
  47. ERROR_DISK_FULL      = 8
  48. ERROR_FAT_TABLE      = 9
  49. ERROR_ACCESS_DENIED  = 10
  50.  
  51. PUSHAD_EAX equ [esp+28]
  52. PUSHAD_ECX equ [esp+24]
  53. PUSHAD_EDX equ [esp+20]
  54. PUSHAD_EBX equ [esp+16]
  55. PUSHAD_EBP equ [esp+8]
  56. PUSHAD_ESI equ [esp+4]
  57. PUSHAD_EDI equ [esp+0]
  58.  
  59. cluster              dd 0       ; used by file_write,makedir,append
  60. partition_count      dd 0       ; partitions found by set_FAT32_variables
  61. longname_sec1        dd 0       ; used by analyze_directory to save 2 previous
  62. longname_sec2        dd 0       ; directory sectors for delete long filename
  63.  
  64. hd_error             dd 0       ; set by wait_for_sector_buffer
  65. hd_setup             dd 0
  66. hd_wait_timeout      dd 0
  67.  
  68. cluster_tmp          dd 0       ; used by analyze_directory
  69.                                 ; and analyze_directory_to_write
  70.  
  71. file_size            dd 0       ; used by file_read
  72.  
  73. sector_tmp           dd 0       ; used by rename,append,file_write
  74. entry_pos            dd 0       ; used by rename,append,file_write
  75.  
  76. old_filesize         dd 0       ; used by append
  77. new_filepos          dd 0       ; used by append
  78. bytes2write          dd 0       ; used by append
  79.  
  80. cache_search_start   dd 0       ; used by find_empty_slot
  81.  
  82. fat_in_cache         dd -1
  83. fat_cache:           times 512 db 0
  84.  
  85. uglobal
  86.  Sector512:                      ; label for dev_hdcd.inc
  87.   buffer:              times 512 db 0
  88.   deltree_buffer:      times 512 db 0
  89. endg
  90.  
  91. iglobal
  92.   NewDirEntry1         db ".          ",0x10
  93.                      times 20 db 0
  94.   NewDirEntry2         db "..         ",0x10
  95.                      times 20 db 0
  96. endg
  97.  
  98. uglobal
  99.   dir_entry:           times 32 db 0
  100.  
  101.   startpath:           times 255 db 0
  102.  
  103.   fat16_root           db 0       ; flag for fat16 rootdir
  104.   f_del                db 0       ; 1=overwrite fat entry
  105.   fat_change           db 0       ; 1=fat has changed
  106.  
  107. endg
  108.  
  109. reserve_hd1:
  110.  
  111.     cli
  112.     cmp   [hd1_status],0
  113.     je    reserve_ok1
  114.  
  115.     sti
  116.     call  change_task
  117.     jmp   reserve_hd1
  118.  
  119.   reserve_ok1:
  120.  
  121.     push  eax
  122.     mov   eax,[0x3000]
  123.     shl   eax,5
  124.     mov   eax,[eax+0x3000+4]
  125.     mov   [hd1_status],eax
  126.     pop   eax
  127.     sti
  128.     ret
  129.  
  130.  
  131. clear_hd_cache:
  132.  
  133.     push  eax ecx edi
  134.     mov   edi,0x600000
  135.     mov   ecx,16384
  136.     xor   eax,eax
  137.     cld
  138.     rep   stosd                 ; clear hd cache with 0
  139.     mov   [cache_search_start],eax
  140.     mov   [fat_in_cache],-1
  141.     mov   [fat_change],0
  142.     pop   edi ecx eax
  143.     ret
  144.  
  145. problem_partition db 0  ; used for partitions search
  146.  
  147. include  'part_set.inc'
  148.  
  149. set_FAT:
  150. ;--------------------------------
  151. ; input  : EAX = cluster
  152. ;          EDX = value to save
  153. ; output : EDX = old value
  154. ;--------------------------------
  155.     push  eax ebx esi
  156.  
  157.     cmp   eax,2
  158.     jb    sfc_error
  159.     cmp   eax,[LAST_CLUSTER]
  160.     ja    sfc_error
  161.     cmp   [fat_type],16
  162.     je    sfc_1
  163.     add   eax,eax
  164.   sfc_1:
  165.     add   eax,eax
  166.     mov   esi,511
  167.     and   esi,eax               ; esi = position in fat sector
  168.     shr   eax,9                 ; eax = fat sector
  169.     add   eax,[FAT_START]
  170.     mov   ebx,fat_cache
  171.  
  172.     cmp   eax,[fat_in_cache]    ; is fat sector already in memory?
  173.     je    sfc_in_cache          ; yes
  174.  
  175.     cmp   [fat_change],0        ; is fat changed?
  176.     je    sfc_no_change         ; no
  177.     call  write_fat_sector      ; yes. write it into disk
  178.     cmp   [hd_error],0
  179.     jne   sfc_error
  180.  
  181.   sfc_no_change:
  182.     mov   [fat_in_cache],eax    ; save fat sector
  183.     call  hd_read
  184.     cmp  [hd_error],0
  185.     jne  sfc_error
  186.    
  187.  
  188.   sfc_in_cache:
  189.     cmp   [fat_type],16
  190.     jne   sfc_test32
  191.  
  192.     cmp   [f_del],1             ; overwrite previous value?
  193.     je    sfc_set16             ; yes
  194.     cmp   word [ebx+esi],0      ; is cluster free?
  195.     je    sfc_set16             ; yes
  196.     mov   dword [8*0x100000],0xffffff
  197.     mov   edx,[ebx+esi]         ; get old value
  198.     jmp   sfc_nonzero
  199.  
  200.   sfc_set16:
  201.     xchg  [ebx+esi],dx          ; save new value and get old value
  202.     jmp   sfc_write
  203.  
  204.   sfc_test32:
  205.     mov   eax,[fatMASK]
  206.     cmp   [f_del],1             ; overwrite previous value?
  207.     je    sfc_set32             ; yes
  208.     test  eax,[ebx+esi]         ; is cluster free?
  209.     je    sfc_set32             ; yes
  210.     mov   dword [8*0x100000],0xffffff
  211.     mov   edx,[ebx+esi]         ; get old value
  212.     jmp   sfc_nonzero
  213.  
  214.   sfc_set32:
  215.     and   edx,eax
  216.     xor   eax,-1                ; mask for high bits
  217.     and   eax,[ebx+esi]         ; get high 4 bits
  218.     or    eax,edx
  219.     mov   edx,[ebx+esi]         ; get old value
  220.     mov   [ebx+esi],eax         ; save new value
  221.  
  222.   sfc_write:
  223.     mov   [fat_change],1        ; fat has changed
  224.  
  225.   sfc_nonzero:
  226.     and   edx,[fatMASK]
  227.  
  228.   sfc_error:
  229.     pop   esi ebx eax
  230.     ret
  231.  
  232.  
  233. get_FAT:
  234. ;--------------------------------
  235. ; input  : EAX = cluster
  236. ; output : EAX = next cluster
  237. ;--------------------------------
  238.     push  ebx esi
  239.  
  240.     cmp   [fat_type],16
  241.     je    gfc_1
  242.     add   eax,eax
  243.   gfc_1:
  244.     add   eax,eax
  245.     mov   esi,511
  246.     and   esi,eax               ; esi = position in fat sector
  247.     shr   eax,9                 ; eax = fat sector
  248.     add   eax,[FAT_START]
  249.     mov   ebx,fat_cache
  250.  
  251.     cmp   eax,[fat_in_cache]    ; is fat sector already in memory?
  252.     je    gfc_in_cache
  253.  
  254.     cmp   [fat_change],0        ; is fat changed?
  255.     je    gfc_no_change         ; no
  256.     call  write_fat_sector      ; yes. write it into disk
  257.     cmp  [hd_error],0
  258.     jne  hd_error_01
  259.  
  260.   gfc_no_change:
  261.     mov   [fat_in_cache],eax
  262.     call  hd_read
  263.     cmp  [hd_error],0
  264.     jne  hd_error_01
  265.  
  266.   gfc_in_cache:
  267.     mov   eax,[ebx+esi]
  268.     and   eax,[fatMASK]
  269.  hd_error_01:
  270.     pop   esi ebx
  271.     ret
  272.  
  273.  
  274. get_free_FAT:
  275. ;-----------------------------------------------------------
  276. ; input  : EAX = # cluster for start the searching
  277. ; output : if CARRY=0 EAX = # first cluster found free
  278. ;          if CARRY=1 disk full
  279. ; Note   : for more speed need to use fat_cache directly
  280. ;-----------------------------------------------------------
  281.     push  ecx
  282.     mov   ecx,[LAST_CLUSTER]    ; counter for full disk
  283.     sub   ecx,2
  284.  
  285.   gff_test:
  286.     cmp   eax,[LAST_CLUSTER]    ; if above last cluster start at cluster 2
  287.     jbe   gff_in_range
  288.     mov   eax,2
  289.  
  290.   gff_in_range:
  291.     push  eax
  292.     call  get_FAT               ; get cluster state
  293.     cmp   [hd_error],0
  294.     jne   gff_not_found_1
  295.  
  296.     test  eax,eax               ; is it free?
  297.     pop   eax
  298.     je    gff_found             ; yes
  299.     inc   eax                   ; next cluster
  300.     dec   ecx                   ; is all checked?
  301.     jns   gff_test              ; no
  302.  
  303.   gff_not_found_1:
  304.     add   esp,4
  305.   gff_not_found:
  306.     pop   ecx                   ; yes. disk is full
  307.     stc
  308.     ret
  309.  
  310.   gff_found:
  311.     pop   ecx
  312.     clc
  313.     ret
  314.  
  315.  
  316. write_fat_sector:
  317. ;-----------------------------------------------------------
  318. ; write changed fat to disk
  319. ;-----------------------------------------------------------
  320.     push  eax ebx ecx
  321.  
  322.     mov   [fat_change],0
  323.     mov   eax,[fat_in_cache]
  324.     cmp   eax,-1
  325.     jz    write_fat_not_used
  326.     mov   ebx,fat_cache
  327.     mov   ecx,[NUMBER_OF_FATS]
  328.  
  329.   write_next_fat:
  330.     call  hd_write
  331.     cmp   [hd_error],0
  332.     jne   write_fat_not_used
  333.  
  334.     add   eax,[SECTORS_PER_FAT]
  335.     dec   ecx
  336.     jnz   write_next_fat
  337.  
  338.   write_fat_not_used:
  339.     pop   ecx ebx eax
  340.     ret
  341.  
  342.  
  343. analyze_directory:
  344. ;-----------------------------------------------------------
  345. ; input  : EAX = first cluster of the directory
  346. ;          EBX = pointer to filename
  347. ; output : IF CARRY=0 EAX = sector where th file is found
  348. ;                     EBX = pointer in buffer
  349. ;                     [buffer .. buffer+511]
  350. ;                     ECX,EDX,ESI,EDI not changed
  351. ;          IF CARRY=1 filename not found
  352. ; Note   : if cluster=0 it's changed to read rootdir
  353. ;          save 2 previous directory sectors in longname_sec
  354. ;-----------------------------------------------------------
  355.     push  ecx edx esi edi ebx   ; ebx = [esp+0]
  356.     mov   [longname_sec1],0
  357.     mov   [longname_sec2],0
  358.  
  359.   adr_new_cluster:
  360.     mov   [cluster_tmp],eax
  361.     mov   [fat16_root],0
  362.     cmp   eax,[LAST_CLUSTER]
  363.     ja    adr_not_found         ; too big cluster number, something is wrong
  364.     cmp   eax,2
  365.     jnb   adr_data_cluster
  366.  
  367.     mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
  368.     cmp   [fat_type],16
  369.     jne   adr_data_cluster
  370.     mov   eax,[ROOT_START]
  371.     mov   edx,[ROOT_SECTORS]
  372.     mov   [fat16_root],1        ; flag for fat16 rootdir
  373.     jmp   adr_new_sector
  374.  
  375.   adr_data_cluster:
  376.     sub   eax,2
  377.     mov   edx,[SECTORS_PER_CLUSTER]
  378.     imul  eax,edx
  379.     add   eax,[DATA_START]
  380.  
  381.   adr_new_sector:
  382.     mov   ebx,buffer
  383.     call  hd_read
  384.     cmp  [hd_error],0
  385.     jne  adr_not_found
  386.  
  387.     mov   ecx,512/32            ; count of dir entrys per sector = 16
  388.  
  389.   adr_analyze:
  390.     mov   edi,[ebx+11]          ; file attribute
  391.     and   edi,0xf
  392.     cmp   edi,0xf
  393.     je    adr_long_filename
  394.     test  edi,0x8               ; skip over volume label
  395.     jne   adr_long_filename     ; Note: label can be same name as file/dir
  396.  
  397.     mov   esi,[esp+0]           ; filename need to be uppercase
  398.     mov   edi,ebx
  399.     push  ecx
  400.     mov   ecx,11
  401.     cld
  402.     rep   cmpsb                 ; compare 8+3 filename
  403.     pop   ecx
  404.     je    adr_found
  405.  
  406.   adr_long_filename:
  407.     add   ebx,32                ; position of next dir entry
  408.     dec   ecx
  409.     jnz   adr_analyze
  410.  
  411.     mov   ecx,[longname_sec1]   ; save 2 previous directory sectors
  412.     mov   [longname_sec1],eax   ; for delete long filename
  413.     mov   [longname_sec2],ecx
  414.     inc   eax                   ; next sector
  415.     dec   edx
  416.     jne   adr_new_sector
  417.     cmp   [fat16_root],1        ; end of fat16 rootdir
  418.     je    adr_not_found
  419.  
  420.   adr_next_cluster:
  421.     mov   eax,[cluster_tmp]
  422.     call  get_FAT               ; get next cluster
  423.     cmp  [hd_error],0
  424.     jne  adr_not_found
  425.  
  426.     cmp   eax,2                 ; incorrect fat chain?
  427.     jb    adr_not_found         ; yes
  428.     cmp   eax,[fatRESERVED]     ; is it end of directory?
  429.     jb    adr_new_cluster       ; no. analyse it
  430.  
  431.   adr_not_found:
  432.     pop   edi edi esi edx ecx   ; first edi will remove ebx
  433.     stc                         ; file not found
  434.     ret
  435.  
  436.   adr_found:
  437.     pop   edi edi esi edx ecx   ; first edi will remove ebx
  438.     clc                         ; file found
  439.     ret
  440.  
  441.  
  442. analyze_directory_to_write:
  443. ;-----------------------------------------------------------
  444. ; input  : EAX = first cluster of the directory
  445. ; output : IF CARRY=0 EAX = sector where the empty pos is found
  446. ;                     EBX = pointer in buffer
  447. ;                     [buffer .. buffer+511]
  448. ;                     ECX,EDX,ESI,EDI not changed
  449. ;          IF CARRY=1 disk full or fat corrupted
  450. ; Note   : if cluster=0 it's changed to read rootdir
  451. ;-----------------------------------------------------------
  452.     push  ecx edx edi
  453.  
  454.   adw_new_cluster:
  455.     mov   [cluster_tmp],eax
  456.     mov   [fat16_root],0
  457.     cmp   eax,[LAST_CLUSTER]
  458.     ja    adw_not_found         ; too big cluster number, something is wrong
  459.     cmp   eax,2
  460.     jnb   adw_data_cluster
  461.  
  462.     mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
  463.     cmp   [fat_type],16
  464.     jne   adw_data_cluster
  465.     mov   eax,[ROOT_START]
  466.     mov   edx,[ROOT_SECTORS]
  467.     mov   [fat16_root],1        ; flag for fat16 rootdir
  468.     jmp   adw_new_sector
  469.  
  470.   adw_data_cluster:
  471.     sub   eax,2
  472.     mov   edx,[SECTORS_PER_CLUSTER]
  473.     imul  eax,edx
  474.     add   eax,[DATA_START]
  475.  
  476.   adw_new_sector:
  477.     mov   ebx,buffer
  478.     call  hd_read
  479.     cmp  [hd_error],0
  480.     jne  adw_not_found
  481.  
  482.     mov   ecx,512/32            ; count of dir entrys per sector = 16
  483.  
  484.   adw_analyze:
  485.     cmp   byte [ebx],0x00       ; is free entry?
  486.     je    adw_found             ; yes
  487.     cmp   byte [ebx],0xe5       ; is deleted entry?
  488.     je    adw_found             ; yes
  489.     add   ebx,32                ; position of next dir entry
  490.     dec   ecx
  491.     jnz   adw_analyze
  492.  
  493.     inc   eax                   ; next sector
  494.     dec   edx
  495.     jne   adw_new_sector
  496.     cmp   [fat16_root],1        ; end of fat16 rootdir
  497.     je    adw_not_found
  498.  
  499.     mov   eax,[cluster_tmp]
  500.     call  get_FAT               ; get next cluster
  501.     cmp   [hd_error],0
  502.     jne   adw_not_found
  503.  
  504.     cmp   eax,2                 ; incorrect fat chain?
  505.     jb    adw_not_found         ; yes
  506.     cmp   eax,[fatRESERVED]     ; is it end of directory?
  507.     jb    adw_new_cluster       ; no. analyse it
  508.  
  509.     mov   eax,2                 ; this block of code add a new cluster
  510.     call  get_free_FAT          ; for the directory because the directory
  511.     jc    adw_not_found         ; is full
  512.  
  513.     mov   edx,[fatEND]          ; new end for directory
  514.     call  set_FAT
  515.     cmp  [hd_error],0
  516.     jne  adw_not_found
  517.  
  518.     push  eax                   ; save new cluster
  519.     mov   edx,eax
  520.     mov   eax,[cluster_tmp]     ; change last cluster to point new cluster
  521.     mov   [f_del],1
  522.     call  set_FAT
  523.     cmp  [hd_error],0
  524.     jne  adw_not_found_1
  525.  
  526.     mov   [f_del],0
  527.  
  528.     mov   ecx,-1                ; remove 1 cluster from free disk space
  529.     call  add_disk_free_space
  530.     cmp  [hd_error],0
  531.     jne    adw_not_found_1
  532.  
  533.     mov   ecx,512/4
  534.     xor   eax,eax
  535.     mov   edi,buffer
  536.     cld
  537.     rep   stosd                 ; clear new directory cluster
  538.     pop   eax
  539.  
  540.     sub   eax,2
  541.     mov   ecx,[SECTORS_PER_CLUSTER]
  542.     imul  eax,ecx
  543.     add   eax,[DATA_START]
  544.     mov   ebx,buffer
  545.     push  eax                   ; save sector number
  546.  
  547.   adw_set_empty_directory:
  548.     call  hd_write
  549.     cmp   [hd_error],0
  550.     jne   adw_not_found_1
  551.  
  552.     inc   eax                   ; next sector
  553.     dec   ecx
  554.     jnz   adw_set_empty_directory
  555.  
  556.     pop   eax
  557.  
  558.   adw_found:
  559.     pop   edi edx ecx
  560.     clc                         ; free space found
  561.     ret
  562.   adw_not_found_1:
  563.     add  esp,4
  564.   adw_not_found:
  565.     pop   edi edx ecx
  566.     stc                         ; free space not found
  567.     ret
  568.  
  569.  
  570. get_data_cluster:
  571. ;-----------------------------------------------------------
  572. ; input  : EAX = cluster
  573. ;          EBX = pointer to buffer
  574. ;          EDX = # blocks to read in buffer
  575. ;          ESI = # blocks to skip over
  576. ; output : if CARRY=0 ok EBX/EDX/ESI updated
  577. ;          if CARRY=1 cluster out of range
  578. ; Note   : if cluster=0 it's changed to read rootdir
  579. ;-----------------------------------------------------------
  580.     push  eax ecx
  581.  
  582.     mov   [fat16_root],0
  583.     cmp   eax,[LAST_CLUSTER]
  584.     ja    gdc_error             ; too big cluster number, something is wrong
  585.     cmp   eax,2
  586.     jnb   gdc_cluster
  587.  
  588.     mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
  589.     cmp   [fat_type],16
  590.     jne   gdc_cluster
  591.     mov   eax,[ROOT_START]
  592.     mov   ecx,[ROOT_SECTORS]    ; Note: not cluster size
  593.     mov   [fat16_root],1        ; flag for fat16 rootdir
  594.     jmp   gdc_read
  595.  
  596.   gdc_cluster:
  597.     sub   eax,2
  598.     mov   ecx,[SECTORS_PER_CLUSTER]
  599.     imul  eax,ecx
  600.     add   eax,[DATA_START]
  601.  
  602.   gdc_read:
  603.     test  esi,esi               ; first wanted block
  604.     je    gdcl1                 ; yes, skip count is 0
  605.     dec   esi
  606.     jmp   gdcl2
  607.  
  608.   gdcl1:
  609.     call  hd_read
  610.     cmp  [hd_error],0
  611.     jne  gdc_error    
  612.  
  613.     add   ebx,512               ; update pointer
  614.     dec   edx
  615.  
  616.   gdcl2:
  617.     test  edx,edx               ; is all read?
  618.     je    out_of_read
  619.  
  620.     inc   eax                   ; next sector
  621.     dec   ecx
  622.     jnz   gdc_read
  623.  
  624.   out_of_read:
  625.     pop   ecx eax
  626.     clc
  627.     ret
  628.  
  629.   gdc_error:
  630.     pop   ecx eax
  631.     stc
  632.     ret
  633.  
  634.  
  635. set_data_cluster:
  636. ;-----------------------------------------------------------
  637. ; input  : EAX = cluster
  638. ;          EBX = pointer to buffer
  639. ; output : if CARRY=0 ok
  640. ;          if CARRY=1 cluster out of range
  641. ;-----------------------------------------------------------
  642.     push  eax ebx edx
  643.  
  644.     cmp   eax,[LAST_CLUSTER]
  645.     ja    sdc_error             ; too big cluster number, something is wrong
  646.     sub   eax,2
  647.     jb    sdc_error             ; don't allow rootdir write
  648.  
  649.     mov   edx,[SECTORS_PER_CLUSTER]
  650.     imul  eax,edx
  651.     add   eax,[DATA_START]
  652.  
  653.   sdc_write:
  654.     call  hd_write
  655.     cmp   [hd_error],0
  656.     jne   sdc_error
  657.  
  658.     add   ebx,512               ; update pointer
  659.     inc   eax
  660.     dec   edx
  661.     jnz   sdc_write
  662.     pop   edx ebx eax
  663.     clc
  664.     ret
  665.  
  666.   sdc_error:
  667.     pop   edx ebx eax
  668.     stc
  669.     ret
  670.  
  671.  
  672. get_cluster_of_a_path:
  673. ;---------------------------------------------------------
  674. ; input  : EBX = pointer to a path string
  675. ;          (example: the path "/files/data/document" become
  676. ;                             "files......data.......document...0"
  677. ;          '.' = space char
  678. ;          '0' = char(0) (ASCII=0) !!! )
  679. ; output : if (CARRY=1) -> ERROR in the PATH
  680. ;          if (CARRY=0) -> EAX=cluster
  681. ;---------------------------------------------------------
  682.     push  ebx edx
  683.  
  684.     mov   eax,[ROOT_CLUSTER]
  685.     mov   edx,ebx
  686.  
  687. search_end_of_path:
  688.     cmp   byte [edx],0
  689.     je    found_end_of_path
  690.  
  691.     inc   edx ; '/'
  692.     mov   ebx,edx
  693.     call  analyze_directory
  694.     jc    directory_not_found
  695.  
  696.     mov   eax,[ebx+20-2]        ; read the HIGH 16bit cluster field
  697.     mov   ax,[ebx+26]           ; read the LOW 16bit cluster field
  698.     and   eax,[fatMASK]
  699.     add   edx,11                ; 8+3 (name+extension)
  700.     jmp   search_end_of_path
  701.  
  702. found_end_of_path:
  703.     pop   edx ebx
  704.     clc                         ; no errors
  705.     ret
  706.  
  707. directory_not_found:
  708.     pop   edx ebx
  709.     stc                         ; errors occour
  710.     ret
  711.  
  712.  
  713. bcd2bin:
  714. ;----------------------------------
  715. ; input  : AL=BCD number (eg. 0x11)
  716. ; output : AH=0
  717. ;          AL=decimal number (eg. 11)
  718. ;----------------------------------
  719.     xor   ah,ah
  720.     shl   ax,4
  721.     shr   al,4
  722.     aad
  723.     ret
  724.  
  725.  
  726. get_date_for_file:
  727. ;-----------------------------------------------------
  728. ; Get date from CMOS and pack day,month,year in AX
  729. ; DATE   bits  0..4   : day of month 0..31
  730. ;              5..8   : month of year 1..12
  731. ;              9..15  : count of years from 1980
  732. ;-----------------------------------------------------
  733.     mov   al,0x7        ;day
  734.     out   0x70,al
  735.     in    al,0x71
  736.     call  bcd2bin
  737.     ror   eax,5
  738.  
  739.     mov   al,0x8        ;month
  740.     out   0x70,al
  741.     in    al,0x71
  742.     call  bcd2bin
  743.     ror   eax,4
  744.  
  745.     mov   al,0x9        ;year
  746.     out   0x70,al
  747.     in    al,0x71
  748.     call  bcd2bin
  749.     add   ax,20         ;because CMOS return only the two last
  750.                         ;digit (eg. 2000 -> 00 , 2001 -> 01) and we
  751.     rol   eax,9         ;need the difference with 1980 (eg. 2001-1980)
  752.     ret
  753.  
  754.  
  755. get_time_for_file:
  756. ;-----------------------------------------------------
  757. ; Get time from CMOS and pack hour,minute,second in AX
  758. ; TIME   bits  0..4   : second (the low bit is lost)
  759. ;              5..10  : minute 0..59
  760. ;              11..15 : hour 0..23
  761. ;-----------------------------------------------------
  762.     mov   al,0x0        ;second
  763.     out   0x70,al
  764.     in    al,0x71
  765.     call  bcd2bin
  766.     ror   eax,6
  767.  
  768.     mov   al,0x2        ;minute
  769.     out   0x70,al
  770.     in    al,0x71
  771.     call  bcd2bin
  772.     ror   eax,6
  773.  
  774.     mov   al,0x4        ;hour
  775.     out   0x70,al
  776.     in    al,0x71
  777.     call  bcd2bin
  778.     rol   eax,11
  779.     ret
  780.  
  781.  
  782. set_current_time_for_entry:
  783. ;-----------------------------------------------------
  784. ; Set current time/date for file entry
  785. ; input  : ebx = file entry pointer
  786. ;-----------------------------------------------------
  787.     push  eax
  788.     call  get_time_for_file     ; update files date/time
  789.     mov   [ebx+22],ax
  790.     call  get_date_for_file
  791.     mov   [ebx+24],ax
  792.     pop   eax
  793.     ret
  794.  
  795.  
  796. makedir:
  797. ;-----------------------------------------------------
  798. ; input  : eax = directory name
  799. ;          edx = path
  800. ; output : eax = 0 - ok
  801. ;                3 - unknown FS
  802. ;                5 - file not found
  803. ;                8 - disk full
  804. ;               10 - access denied
  805. ; Note   : can only make one directory at time
  806. ;-----------------------------------------------------
  807.     cmp   [fat_type],0
  808.     jnz   make_dir_fat_ok
  809.     mov   eax,ERROR_UNKNOWN_FS
  810.     ret
  811.  
  812.   make_dir_fat_ok:
  813. ;    call  reserve_hd1
  814.  
  815.     pushad
  816.  
  817.     mov   ebx,edx
  818.     call  get_cluster_of_a_path
  819.     jnc   make_dir_found_path
  820.     cmp   [hd_error],0
  821.     jne   make_dir_error_1
  822.  
  823.   make_dir_path_not_found:
  824.     popad
  825.     call  update_disk           ; write all of cache and fat to hd
  826.     cmp   [hd_error],0
  827.     jne   make_dir_error_2
  828.  
  829.     mov   [hd1_status],0
  830.     mov   eax,ERROR_FILE_NOT_FOUND
  831.     ret
  832.  
  833.   make_dir_disk_full:
  834.     cmp  [hd_error],0
  835.     jne   make_dir_error_1
  836.     popad
  837.     call  update_disk           ; write all of cache and fat to hd
  838.     cmp   [hd_error],0
  839.     jne   make_dir_error_2
  840.  
  841.     mov   [hd1_status],0
  842.     mov   eax,ERROR_DISK_FULL
  843.     ret
  844.  
  845.   make_dir_already_exist:
  846.     cmp  [hd_error],0
  847.     jne   make_dir_error_1    
  848.     mov   eax,[cluster]         ; directory cluster
  849.     xor   edx,edx               ; free
  850.     mov   [f_del],1
  851.     call  set_FAT
  852.     cmp  [hd_error],0
  853.     jne   make_dir_error_1
  854.  
  855.     mov   [f_del],0
  856.  
  857.     popad
  858.     call  update_disk           ; write all of cache and fat to hd
  859.   make_dir_error_2:
  860.     mov   [hd1_status],0
  861.     mov   eax,ERROR_ACCESS_DENIED
  862.     ret
  863.  
  864.   make_dir_error_1:
  865.     popad
  866.     jmp   make_dir_error_2
  867.  
  868.   make_dir_error_3:
  869.     add  esp,4
  870.     jmp   make_dir_error_1
  871.  
  872.   make_dir_found_path:
  873.     cmp   eax,[ROOT_CLUSTER]
  874.     jnz   make_dir_not_root
  875.     xor   eax,eax
  876.  
  877.   make_dir_not_root:
  878.     mov   ecx,eax               ; directorys start cluster
  879.     mov   word [NewDirEntry2+26],cx ; 16 bits low of cluster
  880.     shr   ecx,16
  881.     mov   word [NewDirEntry2+20],cx ; 16 bits high of cluster (=0 fat16)
  882.  
  883.     push  eax                   ; save parent directory cluster
  884.     mov   eax,2
  885.     call  get_free_FAT
  886.     mov   [cluster],eax         ; first free cluster
  887.     pop   eax
  888.     jc    make_dir_disk_full
  889.  
  890.     push  eax
  891.     mov   eax,[cluster]         ; directory cluster
  892.     mov   edx,[fatEND]          ; end for directory
  893.     call  set_FAT
  894.     cmp  [hd_error],0
  895.     jne   make_dir_error_3
  896.     pop   eax
  897.  
  898.     mov   ebx,PUSHAD_EAX        ; dir name
  899.     push  eax
  900.     call  analyze_directory     ; check if directory already exist
  901.     cmp   [hd_error],0
  902.     jne   make_dir_error_1
  903.  
  904.     pop   eax
  905.     jnc   make_dir_already_exist ; need to free allocated cluster!
  906.  
  907.     call  analyze_directory_to_write
  908.     jc    make_dir_already_exist ; need to free allocated cluster!
  909.  
  910.     mov   esi,PUSHAD_EAX        ; dir name
  911.     mov   edi,ebx               ; pointer in buffer
  912.     mov   ecx,11
  913.     cld
  914.     rep   movsb
  915.  
  916.     mov   dword [ebx+28],0      ; dir size is always 0
  917.     mov   ecx,[cluster]
  918.     mov   [ebx+26],cx           ; 16 bits low of cluster
  919.     mov   word [NewDirEntry1+26],cx
  920.     shr   ecx,16
  921.     mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
  922.     mov   word [NewDirEntry1+20],cx
  923.     mov   byte [ebx+11],0x10    ; attribute = directory
  924.  
  925.     call  set_current_time_for_entry
  926.     mov   ecx,[ebx+22]
  927.     mov   dword [NewDirEntry1+22],ecx
  928.     mov   dword [NewDirEntry2+22],ecx
  929.  
  930.     mov   ebx,buffer            ; save the directory name,length,cluster
  931.     call  hd_write
  932.     cmp   [hd_error],0
  933.     jne   make_dir_error_1
  934.  
  935.     mov   ecx,512/4
  936.     xor   eax,eax
  937.     mov   edi,buffer
  938.     cld
  939.     rep   stosd                 ; clear new directory cluster
  940.  
  941.     mov   eax,[cluster]         ; new directory cluster
  942.     sub   eax,2
  943.     mov   edx,[SECTORS_PER_CLUSTER]
  944.     imul  eax,edx
  945.     add   eax,[DATA_START]
  946.     mov   ebx,buffer
  947.     add   eax,edx               ; start from last sector
  948.  
  949.   dir_set_empty_directory:
  950.     dec   eax                   ; next sector
  951.     cmp   edx,1                 ; is first directory sector?
  952.     jnz   not_first_sector      ; no. write empty sector
  953.     mov   esi,NewDirEntry1
  954.     mov   edi,buffer
  955.     mov   ecx,64/4
  956.     cld
  957.     rep   movsd                 ; copy 2 first directory entrys "." and ".."
  958.  
  959.   not_first_sector:
  960.     call  hd_write
  961.     cmp   [hd_error],0
  962.     jne   make_dir_error_1
  963.  
  964.     dec   edx
  965.     jnz   dir_set_empty_directory
  966.  
  967.     mov   ecx,-1                ; remove 1 cluster from free disk space
  968.     call  add_disk_free_space
  969.     cmp  [hd_error],0
  970.     jne   make_dir_error_1
  971.  
  972.     popad
  973.     call  update_disk           ; write all of cache and fat to hd
  974.     cmp   [hd_error],0
  975.     jne   make_dir_error_2
  976.     mov   [hd1_status],0
  977.     xor   eax,eax
  978.     ret
  979.  
  980.  
  981. removedir:
  982. ;-----------------------------------------------------
  983. ; input  : eax = file/directory name
  984. ;          edx = path
  985. ; output : eax = 0 - ok
  986. ;                3 - unknown FS
  987. ;                5 - file not found
  988. ;               10 - access denied
  989. ;-----------------------------------------------------
  990.     cmp   [fat_type],0
  991.     jnz   remove_dir_fat_ok
  992.     mov   eax,ERROR_UNKNOWN_FS
  993.     ret
  994.  
  995.   remove_dir_fat_ok:
  996. ;    call  reserve_hd1
  997.  
  998.     push  edi
  999.     mov   edi,1                 ; allow directory remove
  1000.     call  file_delete
  1001.     cmp   [hd_error],0
  1002.     jne   @f
  1003.  
  1004.     pop   edi
  1005.  
  1006.     call  update_disk           ; write all of cache and fat to hd
  1007.   @@:
  1008.     mov   [hd1_status],0
  1009.     ret
  1010.    
  1011.  
  1012. add_disk_free_space:
  1013. ;-----------------------------------------------------
  1014. ; input  : ecx = cluster count
  1015. ; Note   : negative = remove clusters from free space
  1016. ;          positive = add clusters to free space
  1017. ;-----------------------------------------------------
  1018.     test  ecx,ecx               ; no change
  1019.     je    add_dfs_no
  1020.     cmp   [fat_type],32         ; free disk space only used by fat32
  1021.     jne   add_dfs_no
  1022.  
  1023.     push  eax ebx
  1024.     mov   eax,[ADR_FSINFO]
  1025.     mov   ebx,buffer
  1026.     call  hd_read
  1027.     cmp  [hd_error],0
  1028.     jne  add_not_fs
  1029.  
  1030.     cmp   dword [ebx+0x1fc],0xaa550000 ; check sector id
  1031.     jne   add_not_fs
  1032.  
  1033.     add   [ebx+0x1e8],ecx
  1034.     call  hd_write
  1035.     cmp   [hd_error],0
  1036.     jne   add_not_fs
  1037.  
  1038.   add_not_fs:
  1039.     pop   ebx eax
  1040.  
  1041.   add_dfs_no:
  1042.     ret
  1043.  
  1044.  
  1045. file_append:
  1046. ;-----------------------------------------------------
  1047. ; input  : eax = file name
  1048. ;          edx = path
  1049. ;          ecx = pointer to buffer
  1050. ;          ebx = bytes to write (0 = truncate file)
  1051. ;          esi = start position (-1 = end of file)
  1052. ; output : eax = 0 - ok
  1053. ;                3 - unknown FS
  1054. ;                5 - file not found
  1055. ;                6 - end of file
  1056. ;                8 - disk full
  1057. ;                9 - fat table corrupted
  1058. ;               10 - access denied
  1059. ;          ebx = bytes written
  1060. ;-----------------------------------------------------
  1061.     cmp   [fat_type],0
  1062.     jnz   append_fat_ok
  1063.     mov   eax,ERROR_UNKNOWN_FS
  1064.     ret
  1065.  
  1066.   append_fat_ok:
  1067. ;    call  reserve_hd1
  1068.  
  1069.     pushad
  1070.  
  1071.     mov   ebx,edx
  1072.     call  get_cluster_of_a_path
  1073.     jc    append_not_found
  1074.  
  1075.     mov   ebx,PUSHAD_EAX        ; file name
  1076.     call  analyze_directory
  1077.     jc    append_not_found
  1078.  
  1079.     mov   [sector_tmp],eax
  1080.     mov   [entry_pos],ebx
  1081.  
  1082.     test  byte [ebx+11],0x10    ; is it directory?
  1083.     jnz   append_access         ; yes
  1084.  
  1085.     mov   ecx,[ebx+28]          ; file size
  1086.     mov   edi,PUSHAD_ESI        ; write position
  1087.     cmp   edi,-1                ; -1 = eof
  1088.     jnz   append_inside_file
  1089.     mov   edi,ecx               ; file size
  1090.  
  1091.   append_inside_file:
  1092.     cmp   edi,ecx               ; start above old file size?
  1093.     ja    append_eof            ; yes
  1094.  
  1095.     mov   [old_filesize],ecx
  1096.     mov   [new_filepos],edi
  1097.  
  1098.     mov   ecx,PUSHAD_EBX        ; bytes to write
  1099.     test  ecx,ecx               ; truncate?
  1100.     jz    append_truncate       ; yes
  1101.  
  1102.     mov   [bytes2write],ecx     ; bytes to write
  1103.     mov   esi,PUSHAD_ECX        ; pointer to buffer
  1104.     mov   eax,[ebx+20-2]        ; FAT entry
  1105.     mov   ax,[ebx+26]
  1106.     and   eax,[fatMASK]
  1107.     jnz   append_find_pos       ; first cluster <> 0
  1108.  
  1109.     mov   eax,2
  1110.     call  get_free_FAT
  1111.     jc    append_disk_full
  1112.     mov   ecx,eax               ; set files first cluster
  1113.     mov   [ebx+26],cx           ; 16 bits low of cluster
  1114.     shr   ecx,16
  1115.     mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
  1116.     mov   edx,[fatEND]          ; new end for cluster chain
  1117.     call  set_FAT
  1118.     cmp  [hd_error],0
  1119.     jne   append_access
  1120.  
  1121.     push  eax                   ; save first cluster
  1122.     mov   eax,[sector_tmp]
  1123.     mov   ebx,buffer
  1124.     call  hd_write              ; write new file entry back to disk
  1125.     cmp   [hd_error],0
  1126.     jne   append_access_1
  1127.  
  1128.     pop   eax
  1129.  
  1130.   append_remove_free:
  1131.     mov   ecx,-1                ; remove 1 cluster from free disk space
  1132.     call  add_disk_free_space   ; Note: uses buffer
  1133.     cmp  [hd_error],0
  1134.     jne   append_access
  1135.  
  1136.   append_found_cluster:
  1137.     mov   [cluster],eax
  1138.     sub   eax,2
  1139.     mov   ecx,[SECTORS_PER_CLUSTER]
  1140.     imul  eax,ecx
  1141.     add   eax,[DATA_START]
  1142.     xor   edi,edi
  1143.  
  1144.   append_new_sector:
  1145.     cmp   [hd_error],0
  1146.     jne   append_access    
  1147.     push  ecx
  1148.     mov   ecx,[bytes2write]     ; bytes left in buffer
  1149.     mov   ebx,512
  1150.     sub   ebx,edi               ; bytes left in sector
  1151.     cmp   ecx,ebx
  1152.     jb    append_bytes_ok
  1153.     mov   ecx,ebx
  1154.  
  1155.   append_bytes_ok:
  1156.     cmp   ecx,512               ; overwrite full sector?
  1157.     jz    append_full_sector    ; yes
  1158.     mov   ebx,buffer            ; overwrite part of sector
  1159.     call  hd_read               ; read old sector
  1160.     cmp  [hd_error],0
  1161.     jne  append_access_1
  1162.  
  1163.   append_full_sector:
  1164.     sub   [bytes2write],ecx
  1165.     add   [new_filepos],ecx
  1166.     add   edi,buffer
  1167.     cld
  1168.     rep   movsb
  1169.     pop   ecx
  1170.  
  1171.     mov   ebx,buffer
  1172.     call  hd_write
  1173.     cmp   [hd_error],0
  1174.     jne   append_access
  1175.  
  1176.     cmp   [bytes2write],0       ; is all done?
  1177.     jz    append_done
  1178.     xor   edi,edi
  1179.     inc   eax
  1180.     dec   ecx
  1181.     jnz   append_new_sector
  1182.  
  1183.     mov   eax,[cluster]
  1184.     call  get_FAT
  1185.     cmp   [hd_error],0
  1186.     jne   append_access
  1187.  
  1188.     cmp   eax,2
  1189.     jb    append_fat
  1190.     cmp   eax,[LAST_CLUSTER]
  1191.     jbe   append_found_cluster
  1192.  
  1193.   append_alloc_cluster:
  1194.     mov   eax,2                 ; ToDo: use temp array to keep track
  1195.     call  get_free_FAT          ;       of last free cluster
  1196.     jc    append_disk_full
  1197.     push  eax                   ; save new cluster
  1198.     mov   edx,[fatEND]          ; new end for cluster chain
  1199.     call  set_FAT
  1200.     cmp  [hd_error],0
  1201.     jne  append_access_1
  1202.      
  1203.     mov   edx,eax
  1204.     mov   eax,[cluster]
  1205.     mov   [f_del],1
  1206.     call  set_FAT               ; update previous cluster
  1207.     cmp  [hd_error],0
  1208.     jne  append_access_1
  1209.  
  1210.     mov   [f_del],0
  1211.     pop   eax
  1212.     jmp   append_remove_free
  1213.  
  1214.   append_find_pos:
  1215.     call  find_filepos
  1216.     mov   [cluster],ebx
  1217.     jnc   append_new_sector
  1218.     test  edi,edi
  1219.     jz    append_alloc_cluster
  1220.  
  1221.   append_fat:
  1222.     mov   eax,ERROR_FAT_TABLE
  1223.     jmp   append_ret_code
  1224.                        
  1225.   append_disk_full:
  1226.     cmp  [hd_error],0
  1227.     jne  append_access
  1228.     mov   eax,ERROR_DISK_FULL
  1229.     jmp   append_ret_code
  1230.  
  1231.   append_done:
  1232.     xor   eax,eax
  1233.  
  1234.   append_ret_code:
  1235.     mov   PUSHAD_EAX,eax        ; return code
  1236.  
  1237.     mov   eax,[sector_tmp]      ; update directory entry
  1238.     mov   ebx,buffer
  1239.     call  hd_read
  1240.     cmp  [hd_error],0
  1241.     jne  append_access
  1242.      
  1243.     mov   ebx,[entry_pos]
  1244.     mov   ecx,[new_filepos]
  1245.     cmp   ecx,[old_filesize]    ; is file pos above old size?
  1246.     jbe   append_size_ok        ; no
  1247.     mov   [ebx+28],ecx          ; new file size
  1248.  
  1249.   append_size_ok:
  1250.     call  set_current_time_for_entry
  1251.     mov   ebx,buffer
  1252.     call  hd_write              ; write new file entry back to disk
  1253.     cmp   [hd_error],0
  1254.     jne   append_access
  1255.  
  1256.     sub   ecx,PUSHAD_ESI        ; start position
  1257.     mov   PUSHAD_EBX,ecx        ; bytes written
  1258.     popad
  1259.     call  update_disk           ; write all of cache and fat to hd
  1260.     cmp   [hd_error],0
  1261.     jne   append_access_2
  1262.  
  1263.     mov   [hd1_status],0
  1264.     ret
  1265.  
  1266.   append_eof:
  1267.     popad
  1268.     mov   [hd1_status],0
  1269.     xor   ebx,ebx
  1270.     mov   eax,ERROR_END_OF_FILE
  1271.     ret
  1272.  
  1273.   append_not_found:
  1274.     cmp  [hd_error],0
  1275.     jne   append_access
  1276.     popad
  1277.     mov   [hd1_status],0
  1278.     xor   ebx,ebx
  1279.     mov   eax,ERROR_FILE_NOT_FOUND
  1280.     ret        
  1281.   append_access_1:
  1282.     add   esp,4
  1283.   append_access:
  1284.     popad
  1285.   append_access_2:
  1286.     mov   [hd1_status],0
  1287.     xor   ebx,ebx
  1288.     mov   eax,ERROR_ACCESS_DENIED
  1289.     ret
  1290.  
  1291.   append_truncate:
  1292.     mov   edx,[ebx+20-2]        ; FAT entry
  1293.     mov   dx,[ebx+26]
  1294.     and   edx,[fatMASK]
  1295.     mov   [ebx+28],edi          ; set new file size
  1296.     test  edi,edi               ; 0 length file?
  1297.     jnz   truncate_save_size    ; no
  1298.     mov   [ebx+20],di           ; FAT entry = 0
  1299.     mov   [ebx+26],di
  1300.  
  1301.   truncate_save_size:
  1302.     call  set_current_time_for_entry
  1303.     mov   ebx,buffer
  1304.     call  hd_write
  1305.     cmp   [hd_error],0
  1306.     jne   append_access
  1307.  
  1308.     mov   eax,edx               ; first cluster
  1309.     test  edi,edi               ; 0 length file?
  1310.     jz    truncate_clear_chain
  1311.  
  1312.     imul  esi,[SECTORS_PER_CLUSTER],512 ; esi = cluster size in bytes
  1313.  
  1314.   truncate_new_cluster:
  1315.     cmp   eax,2                 ; incorrect fat chain?
  1316.     jb    truncate_eof          ; yes
  1317.     cmp   eax,[fatRESERVED]     ; is it end of file?
  1318.     jnb   truncate_eof          ; yes
  1319.     sub   edi,esi
  1320.     jbe   truncate_pos_found
  1321.     call  get_FAT               ; get next cluster
  1322.     cmp   [hd_error],0
  1323.     jne   append_access
  1324.  
  1325.     jmp   truncate_new_cluster
  1326.  
  1327.   truncate_pos_found:
  1328.     mov   edx,[fatEND]          ; new end for cluster chain
  1329.     mov   [f_del],1
  1330.     call  set_FAT
  1331.     cmp  [hd_error],0
  1332.     jne  append_access
  1333.  
  1334.     mov   [f_del],0
  1335.     mov   eax,edx               ; clear rest of chain
  1336.  
  1337.   truncate_clear_chain:
  1338.     call  clear_cluster_chain
  1339.     cmp  [hd_error],0
  1340.     jne  append_access
  1341.  
  1342.   truncate_eof:
  1343.     popad
  1344.     call  update_disk           ; write all of cache and fat to hd
  1345.     cmp   [hd_error],0
  1346.     jne   append_access_2
  1347.  
  1348.     mov   [hd1_status],0
  1349.     xor   ebx,ebx
  1350.     xor   eax,eax
  1351.     ret
  1352.  
  1353.  
  1354. find_filepos:
  1355. ;-----------------------------------------------------
  1356. ; input  : eax = first cluster
  1357. ;          edi = bytes to skip over (start position)
  1358. ; output : if CARRY=0 file position found
  1359. ;          if CARRY=1 end of file found
  1360. ;          eax = current file sector
  1361. ;          ebx = last cluster
  1362. ;          ecx = sector count in last cluster
  1363. ;          edi = bytes to skip over (sector position)
  1364. ;-----------------------------------------------------
  1365.     push  esi
  1366.     mov   ecx,[SECTORS_PER_CLUSTER]
  1367.     imul  esi,ecx,512           ; esi = cluster size in bytes
  1368.     mov   ebx,eax
  1369.  
  1370.   filepos_new_cluster:
  1371.     cmp   eax,2                 ; incorrect fat chain?
  1372.     jb    filepos_eof           ; yes
  1373.     cmp   eax,[fatRESERVED]     ; is it end of file?
  1374.     jnb   filepos_eof           ; yes
  1375.  
  1376.     mov   ebx,eax
  1377.     cmp   edi,esi               ; skip over full cluster?
  1378.     jb    filepos_cluster_ok    ; no
  1379.  
  1380.     sub   edi,esi
  1381.     call  get_FAT               ; get next cluster
  1382.     cmp   [hd_error],0
  1383.     jne   filepos_eof
  1384.  
  1385.     jmp   filepos_new_cluster
  1386.  
  1387.   filepos_cluster_ok:
  1388.     sub   eax,2
  1389.     imul  eax,ecx
  1390.     add   eax,[DATA_START]
  1391.  
  1392.   filepos_new_sector:
  1393.     cmp   edi,512               ; skip over full sector?
  1394.     jb    filepos_sector_ok     ; no
  1395.     sub   edi,512
  1396.     inc   eax
  1397.     dec   ecx
  1398.     jnz   filepos_new_sector
  1399.  
  1400.   filepos_eof:
  1401.     pop   esi
  1402.     stc
  1403.     ret
  1404.  
  1405.   filepos_sector_ok:
  1406.     pop   esi
  1407.     clc
  1408.     ret
  1409.  
  1410.  
  1411. file_write:
  1412. ;--------------------------------------------------------------------------
  1413. ;   INPUT : user-reg  register-in-this  meaning      symbol-in-this-routine
  1414. ;
  1415. ;            EAX        EDI            system call to write    /
  1416. ;            EBX        EAX   (PAR0)   pointer to file-name    PAR0
  1417. ;            EDX        ECX   (PAR1)   pointer to buffer       PAR1
  1418. ;            ECX        EBX   (PAR2)   file size               PAR2
  1419. ;            ESI        EDX   (PAR3)   pointer to path         PAR3
  1420. ;
  1421. ; output : eax = 0 - ok
  1422. ;                3 - unknown FS
  1423. ;                5 - file not found
  1424. ;                8 - disk full
  1425. ;               10 - access denied
  1426. ;--------------------------------------------------------------------------
  1427.     cmp   [fat_type],0
  1428.     jnz   fat_ok_for_writing
  1429.     mov   eax,ERROR_UNKNOWN_FS
  1430.     ret
  1431.  
  1432.   fat_ok_for_writing:
  1433. ;    call  reserve_hd1
  1434.  
  1435.     pushad
  1436.  
  1437.     xor   edi,edi               ; don't allow directory remove
  1438.     call  file_delete           ; try to delete the file first
  1439.     cmp   [hd_error],0
  1440.     jne   exit_write_access_1
  1441.  
  1442.     test  eax,eax
  1443.     jz    old_deleted           ; deleted ok
  1444.     cmp   eax,ERROR_FILE_NOT_FOUND
  1445.     jnz   exit_write_access     ; it exist but can't delete
  1446.  
  1447.   old_deleted:
  1448.     mov   ebx,PUSHAD_EDX
  1449.     call  get_cluster_of_a_path
  1450.     jnc   found_directory_for_writing
  1451.     cmp   [hd_error],0
  1452.     jne   exit_write_access
  1453.  
  1454.   exit_writing_with_error:
  1455.     popad
  1456.     call  update_disk           ; write all of cache and fat to hd
  1457.     cmp   [hd_error],0
  1458.     jne   exit_write_access_2
  1459.  
  1460.     mov   [hd1_status],0
  1461.     mov   eax,ERROR_FILE_NOT_FOUND
  1462.     ret
  1463.  
  1464.   exit_writing_disk_full_clear:
  1465.     cmp  [hd_error],0
  1466.     jne  exit_write_access_1
  1467.     mov   eax,[sector_tmp]
  1468.     mov   ebx,buffer
  1469.     call  hd_read               ; read directory sector
  1470.     cmp  [hd_error],0
  1471.     jne  exit_write_access_1
  1472.  
  1473.     mov   edx,[entry_pos]
  1474.     mov   byte [edx],0xe5       ; mark as deleted
  1475.     call  hd_write
  1476.     cmp   [hd_error],0
  1477.     jne   exit_write_access_1
  1478.  
  1479.     mov   eax,[edx+20-2]        ; FAT entry
  1480.     mov   ax,[edx+26]
  1481.     and   eax,[fatMASK]
  1482.     call  clear_cluster_chain
  1483.  
  1484.   exit_writing_disk_full:
  1485.     cmp  [hd_error],0
  1486.     jne  exit_write_access_1
  1487.     popad
  1488.     call  update_disk           ; write all of cache and fat to hd
  1489.     cmp   [hd_error],0
  1490.     jne   exit_write_access_2
  1491.     mov   [hd1_status],0
  1492.     mov   eax,ERROR_DISK_FULL
  1493.     ret
  1494.  
  1495.   exit_write_access:
  1496.     popad
  1497.     call  update_disk           ; write all of cache and fat to hd
  1498.     mov   [hd1_status],0
  1499.     mov   eax,ERROR_ACCESS_DENIED
  1500.     ret
  1501.  
  1502.   exit_write_access_1:
  1503.     popad
  1504.   exit_write_access_2:
  1505.     mov   [hd1_status],0
  1506.     mov   eax,ERROR_ACCESS_DENIED
  1507.     ret
  1508.  
  1509. found_directory_for_writing:
  1510.     call  analyze_directory_to_write
  1511.     jc    exit_writing_disk_full
  1512.  
  1513.     mov   [sector_tmp],eax
  1514.     mov   [entry_pos],ebx
  1515.     push  eax                   ; save directory sector
  1516.     mov   eax,2
  1517.     call  get_free_FAT
  1518.     mov   [cluster],eax         ; first free cluster
  1519.     pop   eax
  1520.     jc    exit_writing_disk_full
  1521.  
  1522.     mov   esi,PUSHAD_EAX        ; file name
  1523.     mov   edi,ebx               ; pointer in buffer
  1524.     mov   ecx,11
  1525.     cld
  1526.     rep   movsb
  1527.  
  1528.     mov   esi,PUSHAD_EBX        ; file size (bytes left)
  1529.     mov   [ebx+28],esi          ; file size
  1530.     mov   ecx,[cluster]
  1531.     mov   [ebx+26],cx           ; 16 bits low of cluster
  1532.     shr   ecx,16
  1533.     mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
  1534.     mov   byte [ebx+11],0x20    ; attribute = archive
  1535.  
  1536.     call  set_current_time_for_entry
  1537.  
  1538.     mov   ebx,buffer            ; save the directory name,length,cluster
  1539.     call  hd_write
  1540.     cmp   [hd_error],0
  1541.     jne   exit_write_access_1
  1542.  
  1543.     imul  edi,[SECTORS_PER_CLUSTER],512 ; edi = cluster size in bytes
  1544.     xor   ecx,ecx               ; cluster count
  1545.     mov   ebx,PUSHAD_ECX        ; ebx = buffer
  1546.  
  1547. hd_new_block_write:
  1548.  
  1549.     mov   eax,[cluster]         ; eax = block
  1550.     call  set_data_cluster
  1551.     cmp   [hd_error],0
  1552.     jne   exit_write_access_1
  1553.  
  1554.     sub   esi,edi               ; sub wrote bytes
  1555.     jbe   file_saved_OK         ; end if all done
  1556.     add   ebx,edi               ; update buffer position
  1557.  
  1558.     inc   eax
  1559.     call  get_free_FAT          ; next free in FAT
  1560.     jc    exit_writing_disk_full_clear
  1561.  
  1562.     mov   edx,eax
  1563.     xchg  eax,[cluster]         ; get old cluster and save new cluster
  1564.     call  set_FAT               ; add it in cluster chain
  1565.     cmp  [hd_error],0
  1566.     jne   exit_write_access_1
  1567.  
  1568.     dec   ecx                   ; update cluster count
  1569.     jmp   hd_new_block_write
  1570.  
  1571. file_saved_OK:
  1572.  
  1573.     mov   edx,[fatEND]          ; new end for cluster chain
  1574.     call  set_FAT
  1575.     cmp  [hd_error],0
  1576.     jne   exit_write_access_1
  1577.  
  1578.     dec   ecx                   ; update cluster count
  1579.  
  1580.     call  add_disk_free_space   ; remove clusters from free disk space
  1581.     cmp  [hd_error],0
  1582.     jne   exit_write_access_1
  1583.  
  1584.     popad
  1585.     call  update_disk           ; write all of cache and fat to hd
  1586.     cmp   [hd_error],0
  1587.     jne   exit_write_access_2
  1588.     mov   [hd1_status],0
  1589.     xor   eax,eax
  1590.     ret
  1591.  
  1592.  
  1593. file_read:
  1594. ;--------------------------------------------------------------------------
  1595. ;   INPUT :  user-register register-in-this  meaning         symbol-in-this
  1596. ;
  1597. ;            EAX           EDI               system call to write   /
  1598. ;            EBX           EAX   (PAR0)      pointer to file-name   PAR0
  1599. ;            EDX           ECX   (PAR1)      pointer to buffer      PAR1
  1600. ;            ECX           EBX   (PAR2)   vt file blocks to read    PAR2
  1601. ;            ESI           EDX   (PAR3)      pointer to path        PAR3
  1602. ;            EDI           ESI            vt first 512 block to read
  1603. ;                          EDI               if 0 - read root
  1604. ;
  1605. ; output : eax = 0 - ok
  1606. ;                3 - unknown FS
  1607. ;                5 - file not found
  1608. ;                6 - end of file
  1609. ;                9 - fat table corrupted
  1610. ;               10 - access denied
  1611. ;          ebx = size of file/directory
  1612. ;--------------------------------------------------------------------------
  1613.     cmp   [fat_type],0
  1614.     jnz   fat_ok_for_reading
  1615.     xor   ebx,ebx
  1616.     mov   eax,ERROR_UNKNOWN_FS
  1617.     mov   [hd1_status], ebx
  1618.     ret
  1619.  
  1620.   fat_ok_for_reading:
  1621. ;    call  reserve_hd1
  1622.  
  1623.     pushad
  1624.  
  1625.     mov   ebx,edx
  1626.     call  get_cluster_of_a_path
  1627.     jc    file_to_read_not_found
  1628.  
  1629.     test  edi,edi               ; read rootdir
  1630.     jne   no_read_root
  1631.  
  1632.     xor   eax,eax
  1633.     call  get_dir_size          ; return rootdir size
  1634.     cmp   [hd_error],0
  1635.     jne   file_access_denied
  1636.  
  1637.     mov   [file_size],eax
  1638.     mov   eax,[ROOT_CLUSTER]
  1639.     jmp   file_read_start
  1640.  
  1641.   no_read_root:
  1642.     mov   ebx,PUSHAD_EAX        ; file name
  1643.     call  analyze_directory
  1644.     jc    file_to_read_not_found
  1645.  
  1646.     mov   eax,[ebx+28]          ; file size
  1647.     test  byte [ebx+11],0x10    ; is it directory?
  1648.     jz    read_set_size         ; no
  1649.  
  1650.     mov   eax,[ebx+20-2]        ; FAT entry
  1651.     mov   ax,[ebx+26]
  1652.     and   eax,[fatMASK]
  1653.     call  get_dir_size
  1654.     cmp   [hd_error],0
  1655.     jne   file_access_denied
  1656.  
  1657.   read_set_size:
  1658.     mov   [file_size],eax
  1659.  
  1660.     mov   eax,[ebx+20-2]        ; FAT entry
  1661.     mov   ax,[ebx+26]
  1662.     and   eax,[fatMASK]
  1663.  
  1664.   file_read_start:
  1665.     mov   ebx,PUSHAD_ECX        ; pointer to buffer
  1666.     mov   edx,PUSHAD_EBX        ; file blocks to read
  1667.     mov   esi,PUSHAD_ESI        ; first 512 block to read
  1668.  
  1669.   file_read_new_cluster:
  1670.     call  get_data_cluster
  1671.     jc    file_read_eof         ; end of file or cluster out of range
  1672.  
  1673.     test  edx,edx               ; is all read?
  1674.     je    file_read_OK          ; yes
  1675.  
  1676.     call  get_FAT               ; get next cluster
  1677.     cmp   [hd_error],0
  1678.     jne   file_access_denied
  1679.  
  1680.     cmp   eax,[fatRESERVED]     ; end of file
  1681.     jnb   file_read_eof
  1682.     cmp   eax,2                 ; incorrect fat chain
  1683.     jnb   file_read_new_cluster
  1684.  
  1685.     popad
  1686.     mov   [hd1_status],0
  1687.     mov   ebx,[file_size]
  1688.     mov   eax,ERROR_FAT_TABLE
  1689.     ret
  1690.  
  1691.   file_read_eof:
  1692.     cmp   [hd_error],0
  1693.     jne   file_access_denied
  1694.     popad
  1695.     mov   [hd1_status],0
  1696.     mov   ebx,[file_size]
  1697.     mov   eax,ERROR_END_OF_FILE
  1698.     ret
  1699.  
  1700.   file_read_OK:
  1701.     popad
  1702.     mov   [hd1_status],0
  1703.     mov   ebx,[file_size]
  1704.     xor   eax,eax
  1705.     ret
  1706.  
  1707.   file_to_read_not_found:
  1708.     cmp   [hd_error],0
  1709.     jne   file_access_denied
  1710.     popad
  1711.     mov   [hd1_status],0
  1712.     xor   ebx,ebx
  1713.     mov   eax,ERROR_FILE_NOT_FOUND
  1714.     ret
  1715.  
  1716.   file_access_denied:
  1717.     popad
  1718.     mov   [hd1_status],0
  1719.     xor   ebx,ebx
  1720.     mov   eax,ERROR_ACCESS_DENIED
  1721.     ret
  1722.  
  1723. get_dir_size:
  1724. ;-----------------------------------------------------
  1725. ; input  : eax = first cluster (0=rootdir)
  1726. ; output : eax = directory size in bytes
  1727. ;-----------------------------------------------------
  1728.     push  edx
  1729.     xor   edx,edx               ; count of directory clusters
  1730.     test  eax,eax
  1731.     jnz   dir_size_next
  1732.  
  1733.     mov   eax,[ROOT_SECTORS]
  1734.     shl   eax,9                 ; fat16 rootdir size in bytes
  1735.     cmp   [fat_type],16
  1736.     je    dir_size_ret
  1737.     mov   eax,[ROOT_CLUSTER]
  1738.  
  1739.   dir_size_next:
  1740.     cmp   eax,2                 ; incorrect fat chain
  1741.     jb    dir_size_end
  1742.     cmp   eax,[fatRESERVED]     ; end of directory
  1743.     ja    dir_size_end
  1744.     call  get_FAT               ; get next cluster
  1745.     cmp   [hd_error],0
  1746.     jne   dir_size_ret
  1747.  
  1748.     inc   edx
  1749.     jmp   dir_size_next
  1750.  
  1751.   dir_size_end:
  1752.     imul  eax,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
  1753.     imul  eax,edx
  1754.  
  1755.   dir_size_ret:
  1756.     pop   edx
  1757.     ret
  1758.  
  1759.  
  1760. file_delete:
  1761. ;-----------------------------------------------------
  1762. ; input  : eax = file/directory name
  1763. ;          edx = path
  1764. ;          edi = 1 - allow directory remove else don't remove directory
  1765. ; output : eax = 0 - ok
  1766. ;                3 - unknown FS
  1767. ;                5 - file not found
  1768. ;               10 - access denied
  1769. ;-----------------------------------------------------
  1770.     cmp   [fat_type],0
  1771.     jnz   file_del_fat_ok
  1772.     mov   eax,ERROR_UNKNOWN_FS
  1773.     ret
  1774.  
  1775.   file_del_fat_ok:
  1776.     pushad
  1777.  
  1778.     mov   ebx,edx
  1779.     call  get_cluster_of_a_path
  1780.     jc    file_to_delete_not_found
  1781.  
  1782.     mov   ebx,PUSHAD_EAX        ; file/directory name
  1783.     call  analyze_directory
  1784.     jc    file_to_delete_not_found
  1785.  
  1786.     test  byte [ebx+11],0x10    ; is it directory?
  1787.     jz    delete_notdir         ; no. it's file
  1788.     cmp   edi,1                 ; allow directory remove
  1789.     jnz   delete_no_access      ; no
  1790.  
  1791.     push  eax                   ; save directory sector
  1792.     mov   eax,[ebx+20-2]        ; first cluster of file
  1793.     mov   ax,[ebx+26]           ; 0 length files start cluster = 0
  1794.     and   eax,[fatMASK]
  1795.     xor   ebp,ebp               ; counter for directory deepnes
  1796.     call  clear_directory
  1797.     pop   eax
  1798.     jc    delete_no_access
  1799.  
  1800.     push  ebx                   ; save directory pointer in buffer
  1801.     mov   ebx,buffer
  1802.     call  hd_read               ; read directory sector
  1803.     cmp  [hd_error],0
  1804.     jne  delete_no_access_1
  1805.     pop   ebx
  1806.  
  1807.   delete_notdir:
  1808.     call  delete_entry_name
  1809.     cmp   [hd_error],0
  1810.     jne   delete_no_access
  1811.  
  1812.     mov   eax,ecx               ; first cluster of file
  1813.     call  clear_cluster_chain
  1814.     cmp   [hd_error],0
  1815.     jne   delete_no_access
  1816.  
  1817.     popad
  1818.     xor   eax,eax
  1819.     ret
  1820.  
  1821.   delete_no_access_1:
  1822.      add esp,4
  1823.   delete_no_access:
  1824.     popad
  1825.     mov   eax,ERROR_ACCESS_DENIED
  1826.     ret
  1827.  
  1828.   file_to_delete_not_found:
  1829.     cmp  [hd_error],0
  1830.     jne  delete_no_access
  1831.     popad
  1832.     mov   eax,ERROR_FILE_NOT_FOUND
  1833.     ret
  1834.  
  1835.  
  1836. clear_cluster_chain:
  1837. ;-----------------------------------------------------
  1838. ; input  : eax = first cluster
  1839. ;-----------------------------------------------------
  1840.     push  eax ecx edx
  1841.     xor   ecx,ecx               ; cluster count
  1842.     mov   [f_del],1             ; delete on
  1843.  
  1844.   clean_new_chain:
  1845.     cmp   eax,[LAST_CLUSTER]    ; end of file
  1846.     ja    delete_OK
  1847.     cmp   eax,2                 ; unfinished fat chain or zero length file
  1848.     jb    delete_OK
  1849.     cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
  1850.     jz    delete_OK
  1851.  
  1852.     xor   edx,edx
  1853.     call  set_FAT               ; clear fat entry
  1854.     cmp  [hd_error],0
  1855.     jne  access_denied_01
  1856.  
  1857.     inc   ecx                   ; update cluster count
  1858.     mov   eax,edx               ; old cluster
  1859.     jmp   clean_new_chain
  1860.  
  1861.   delete_OK:
  1862.     call  add_disk_free_space   ; add clusters to free disk space
  1863.   access_denied_01:
  1864.     mov   [f_del],0
  1865.     pop   edx ecx eax
  1866.     ret
  1867.  
  1868.  
  1869. clear_directory:
  1870. ;-----------------------------------------------------
  1871. ; input  : eax = directory cluster
  1872. ;          ebp = directory deepnes
  1873. ; Note   : use recursive call
  1874. ;-----------------------------------------------------
  1875.     pushad
  1876.     inc   ebp
  1877.     cmp   ebp,64                ; if over 63 directory deep
  1878.     jnb   clear_error           ; something must be wrong
  1879.  
  1880.   clear_new_cluster:
  1881.     cmp   eax,[LAST_CLUSTER]
  1882.     ja    clear_end
  1883.     cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
  1884.     jz    clear_end
  1885.     mov   esi,eax               ; esi = current directory cluster
  1886.     sub   eax,2
  1887.     jb    clear_end
  1888.     mov   ecx,[SECTORS_PER_CLUSTER]
  1889.     imul  eax,ecx
  1890.     add   eax,[DATA_START]
  1891.  
  1892.   clear_new_sector:
  1893.     mov   edi,eax               ; edi = current directory sector
  1894.     mov   ebx,deltree_buffer
  1895.     call  hd_read
  1896.     cmp  [hd_error],0
  1897.     jne  clear_error    
  1898.  
  1899.     mov   edx,512/32            ; count of dir entrys per sector = 16
  1900.  
  1901.   clear_analyze:
  1902.     mov   al,[ebx+11]           ; file attribute
  1903.     and   al,0xf
  1904.     cmp   al,0xf
  1905.     je    clear_long_filename
  1906.  
  1907.     cmp   byte [ebx],'.'        ; parent or current directory
  1908.     je    clear_next_entry
  1909.     cmp   byte [ebx],0xe5       ; deleted
  1910.     je    clear_next_entry
  1911.     cmp   byte [ebx],0          ; empty
  1912.     je    clear_write_last
  1913.     ;je    clear_next_entry
  1914.  
  1915.     mov   eax,[ebx+20-2]        ; first cluster of entry
  1916.     mov   ax,[ebx+26]
  1917.     and   eax,[fatMASK]
  1918.  
  1919.     test  byte [ebx+11],0x10    ; is it directory?
  1920.     jz    clear_file            ; no
  1921.  
  1922.     push  eax ebx
  1923.     mov   eax,edi
  1924.     mov   ebx,deltree_buffer    ; save buffer over recursive call
  1925.     call  hd_write              ; write directory sector to disk
  1926.     cmp   [hd_error],0
  1927.     jne   clear_error    
  1928.  
  1929.     pop   ebx eax
  1930.  
  1931.     call  clear_directory       ; recursive call !!!
  1932.     jc    clear_error           ; exit if error found
  1933.  
  1934.     push  eax ebx
  1935.     mov   eax,edi
  1936.     mov   ebx,deltree_buffer
  1937.     call  hd_read               ; read directory sector again
  1938.     cmp  [hd_error],0
  1939.     jne   clear_error_1
  1940.  
  1941.     pop   ebx eax
  1942.  
  1943.   clear_file:
  1944.     call  clear_cluster_chain
  1945.     cmp  [hd_error],0
  1946.     jne   clear_error
  1947.  
  1948.   clear_long_filename:
  1949.     mov   byte [ebx],0xe5
  1950.  
  1951.   clear_next_entry:
  1952.     add   ebx,32                ; position of next dir entry
  1953.     dec   edx
  1954.     jnz   clear_analyze
  1955.  
  1956.     mov   eax,edi
  1957.     mov   ebx,deltree_buffer
  1958.     call  hd_write              ; write directory sector to disk
  1959.     cmp   [hd_error],0
  1960.     jne   clear_error
  1961.  
  1962.     inc   eax                   ; next sector
  1963.     dec   ecx
  1964.     jnz   clear_new_sector
  1965.  
  1966.     mov   eax,esi
  1967.     call  get_FAT               ; get next cluster
  1968.     cmp   [hd_error],0
  1969.     jne   clear_error
  1970.  
  1971.     jmp   clear_new_cluster     ; clear it
  1972.  
  1973.   clear_write_last:
  1974.     mov   eax,edi
  1975.     mov   ebx,deltree_buffer
  1976.     call  hd_write              ; write directory sector to disk
  1977.     cmp   [hd_error],0
  1978.     jne   clear_error
  1979.  
  1980.   clear_end:
  1981.     popad
  1982.     clc
  1983.     ret
  1984. clear_error_1:
  1985.     add  esp,8
  1986.   clear_error:
  1987.     popad
  1988.     stc
  1989.     ret
  1990.  
  1991.  
  1992. delete_entry_name:
  1993. ;-----------------------------------------------------
  1994. ; input  : eax = directory sector
  1995. ;          ebx = directory pointer in buffer
  1996. ;          longname_sec = 2 previous directory sectors
  1997. ; output : ecx = first cluster
  1998. ; change : eax,ebx,edx
  1999. ;-----------------------------------------------------
  2000.     mov   byte [ebx],0xe5
  2001.     mov   ecx,[ebx+20-2]        ; first cluster of file
  2002.     mov   cx,[ebx+26]           ; 0 length files start cluster = 0
  2003.     and   ecx,[fatMASK]
  2004.  
  2005.   delete_empty:
  2006.     sub   ebx,32
  2007.     cmp   ebx,buffer
  2008.     jnb   delete_test_long
  2009.  
  2010.     mov   ebx,buffer
  2011.     call  hd_write              ; write directory sector back
  2012.     cmp   [hd_error],0
  2013.     jne   delete_name_end
  2014.  
  2015.     xor   eax,eax
  2016.     xchg  eax,[longname_sec2]
  2017.     xchg  eax,[longname_sec1]
  2018.     test  eax,eax               ; is there previous directory sector?
  2019.     jz    delete_name_end       ; no
  2020.  
  2021.     mov   ebx,buffer
  2022.     call  hd_read               ; read previous sector
  2023.     cmp  [hd_error],0
  2024.     jne  delete_name_end    
  2025.  
  2026.     mov   ebx,buffer+0x1e0      ; start from last entry
  2027.  
  2028.   delete_test_long:
  2029.     mov   dh,[ebx+11]           ; file attribute
  2030.     and   dh,0xf
  2031.     cmp   dh,0xf
  2032.     jne   delete_write_buffer
  2033.  
  2034.     cmp   byte [ebx],0x40       ; end of long dir entry?
  2035.     mov   byte [ebx],0xe5
  2036.     jb    delete_empty
  2037.  
  2038.   delete_write_buffer:
  2039.     mov   ebx,buffer
  2040.     call  hd_write              ; write directory sector back
  2041.  
  2042.   delete_name_end:
  2043.     ret
  2044.  
  2045.  
  2046. rename:
  2047. ;-----------------------------------------------------------
  2048. ; input  : eax = source directory name
  2049. ;          edx = source path
  2050. ;          ebx = dest directory name
  2051. ;          edi = dest path
  2052. ; output : eax = 0 - ok
  2053. ;                3 - unknown FS
  2054. ;                5 - file not found
  2055. ;                8 - disk full
  2056. ;               10 - access denied
  2057. ;-----------------------------------------------------------
  2058.     cmp   [fat_type],0
  2059.     jnz   fat_ok_for_rename
  2060.     mov   eax,ERROR_UNKNOWN_FS
  2061.     ret
  2062.  
  2063.   fat_ok_for_rename:
  2064. ;    call  reserve_hd1
  2065.  
  2066.     pushad
  2067.  
  2068.     mov   ebx,edx               ; source path
  2069.     call  get_cluster_of_a_path
  2070.     jc    rename_entry_not_found
  2071.  
  2072.     mov   ebx,PUSHAD_EAX        ; source directory name
  2073.     call  analyze_directory
  2074.     jc    rename_entry_not_found
  2075.  
  2076.     mov   [sector_tmp],eax      ; save source sector
  2077.     mov   [entry_pos],ebx
  2078.     mov   esi,ebx
  2079.     mov   edi,dir_entry
  2080.     mov   ecx,32/4
  2081.     cld
  2082.     rep   movsd                 ; save entry
  2083.  
  2084.     mov   ebx,PUSHAD_EDI        ; dest path
  2085.     call  get_cluster_of_a_path
  2086.     jc    rename_entry_not_found
  2087.  
  2088.     mov   edx,eax               ; save dest directory cluster
  2089.     mov   ebx,PUSHAD_EBX        ; dest directory name
  2090.     push  [longname_sec1]
  2091.     push  [longname_sec2]
  2092.     call  analyze_directory     ; check if entry already exist
  2093.     cmp  [hd_error],0
  2094.     jne  rename_entry_already_exist_1
  2095.  
  2096.     pop   [longname_sec2]
  2097.     pop   [longname_sec1]
  2098.     jnc   rename_entry_already_exist
  2099.  
  2100.     mov   eax,edx
  2101.     call  analyze_directory_to_write
  2102.     jc    rename_disk_full
  2103.  
  2104.     mov   esi,dir_entry
  2105.     mov   edi,ebx
  2106.     mov   ecx,32/4
  2107.     cld
  2108.     rep   movsd                 ; copy entry
  2109.     mov   esi,PUSHAD_EBX        ; dest directory name
  2110.     mov   edi,ebx
  2111.     mov   ecx,11
  2112.     rep   movsb                 ; copy name
  2113.  
  2114.     mov   ebx,buffer            ; save the directory name,length,cluster
  2115.     call  hd_write
  2116.  
  2117.     test  byte [dir_entry+11],0x10 ; is it directory?
  2118.     jz    rename_not_dir           ; no
  2119.     mov   eax,[dir_entry+20-2]     ; FAT entry
  2120.     mov   ax,[dir_entry+26]
  2121.     and   eax,[fatMASK]
  2122.     call  change_2dot_cluster
  2123.     cmp   [hd_error],0
  2124.     jne   rename_entry_already_exist
  2125.  
  2126.   rename_not_dir:
  2127.     cmp   [hd_error],0
  2128.     jne   rename_entry_already_exist
  2129.     mov   eax,[sector_tmp]
  2130.     mov   ebx,buffer
  2131.     call  hd_read               ; read source directory sector
  2132.     cmp  [hd_error],0
  2133.     jne  rename_entry_already_exist
  2134.  
  2135.     mov   ebx,[entry_pos]
  2136.     call  delete_entry_name
  2137.     cmp   [hd_error],0
  2138.     jne   rename_entry_already_exist
  2139.  
  2140.     popad
  2141.     call  update_disk           ; write all of cache and fat to hd
  2142.     cmp   [hd_error],0
  2143.     jne   rename_entry_already_exist_2
  2144.     mov   [hd1_status],0
  2145.     xor   eax,eax
  2146.     ret
  2147.  
  2148.   rename_entry_not_found:
  2149.     cmp  [hd_error],0
  2150.     jne  rename_entry_already_exist
  2151.     popad
  2152.     mov   [hd1_status],0
  2153.     mov   eax,ERROR_FILE_NOT_FOUND
  2154.     ret
  2155.  
  2156.   rename_entry_already_exist_1:
  2157.     add   esp,8
  2158.   rename_entry_already_exist:
  2159.     popad
  2160.   rename_entry_already_exist_2:
  2161.     mov   [hd1_status],0
  2162.     mov   eax,ERROR_ACCESS_DENIED
  2163.     ret
  2164.  
  2165.   rename_disk_full:
  2166.     cmp  [hd_error],0
  2167.     jne  rename_entry_already_exist
  2168.     popad
  2169.     mov   [hd1_status],0
  2170.     mov   eax,ERROR_DISK_FULL
  2171.     ret
  2172.  
  2173.  
  2174. change_2dot_cluster:
  2175. ;-----------------------------------------------------------
  2176. ; input  : eax = directory cluster
  2177. ;          edx = value to save
  2178. ; change : eax,ebx,edx
  2179. ;-----------------------------------------------------------
  2180.     cmp   eax,[LAST_CLUSTER]
  2181.     ja    not_2dot              ; too big cluster number, something is wrong
  2182.     sub   eax,2
  2183.     jb    not_2dot
  2184.  
  2185.     imul  eax,[SECTORS_PER_CLUSTER]
  2186.     add   eax,[DATA_START]
  2187.     mov   ebx,buffer
  2188.     call  hd_read
  2189.     cmp  [hd_error],0
  2190.     jne  not_2dot
  2191.  
  2192.     cmp   dword [ebx+32],'..  '
  2193.     jnz   not_2dot
  2194.  
  2195.     cmp   edx,[ROOT_CLUSTER]    ; is rootdir cluster?
  2196.     jne   not_2dot_root
  2197.     xor   edx,edx               ; yes. set it zero
  2198.  
  2199.   not_2dot_root:
  2200.     mov   [ebx+32+26],dx        ; 16 bits low of cluster
  2201.     shr   edx,16
  2202.     mov   [ebx+32+20],dx        ; 16 bits high of cluster (=0 fat16)
  2203.     call  hd_write
  2204.  
  2205.   not_2dot:
  2206.     ret
  2207.  
  2208.  
  2209. get_filesize:
  2210. ;-----------------------------------------------------------
  2211. ; input  : eax = file name
  2212. ;          edx = path
  2213. ;          edi = if 0 - read rootdir else normal dir/file size
  2214. ; output : eax = 0 - ok
  2215. ;                3 - unknown FS
  2216. ;                5 - file not found
  2217. ;               10 - access denied
  2218. ;          ebx = file size
  2219. ;-----------------------------------------------------------
  2220.     cmp   [fat_type],0
  2221.     jnz   get_filesize_fat_ok
  2222.     xor   ebx,ebx
  2223.     mov   eax,ERROR_UNKNOWN_FS
  2224.     ret
  2225.  
  2226.   get_filesize_fat_ok:
  2227. ;    call  reserve_hd1
  2228.  
  2229.     pushad
  2230.     xor   eax,eax
  2231.     test  edi,edi               ; is read rootdir?
  2232.     je    get_filesize_dirsize  ; yes
  2233.  
  2234.   get_filesize_no_root:
  2235.     mov   ebx,edx
  2236.     call  get_cluster_of_a_path
  2237.     jc    get_filesize_not_found
  2238.  
  2239.     mov   ebx,PUSHAD_EAX        ; file name
  2240.     call  analyze_directory
  2241.     jc    get_filesize_not_found
  2242.  
  2243.     mov   eax,[ebx+28]          ; file size
  2244.     test  byte [ebx+11],0x10    ; is it directory?
  2245.     jz    get_filesize_set_size ; no
  2246.  
  2247.     mov   eax,[ebx+20-2]        ; FAT entry
  2248.     mov   ax,[ebx+26]
  2249.     and   eax,[fatMASK]
  2250.  
  2251.   get_filesize_dirsize:
  2252.     call  get_dir_size
  2253.     cmp   [hd_error],0
  2254.     jne   get_filesize_access_denied
  2255.  
  2256.   get_filesize_set_size:
  2257.     mov   PUSHAD_EBX,eax
  2258.     popad
  2259.     mov   [hd1_status],0
  2260.     xor   eax,eax
  2261.     ret
  2262.  
  2263.   get_filesize_not_found:
  2264.     cmp   [hd_error],0
  2265.     jne   get_filesize_access_denied
  2266.     popad
  2267.     mov   [hd1_status],0
  2268.     xor   ebx,ebx
  2269.     mov   eax,ERROR_FILE_NOT_FOUND
  2270.     ret
  2271.  
  2272.   get_filesize_access_denied:
  2273.     popad
  2274.     mov   [hd1_status],0
  2275.     xor   ebx,ebx
  2276.     mov   eax,ERROR_ACCESS_DENIED
  2277.     ret
  2278.  
  2279. get_fileattr:
  2280. ;-----------------------------------------------------------
  2281. ; input  : eax = file name
  2282. ;          edx = path
  2283. ; output : eax = 0 - ok
  2284. ;                3 - unknown FS
  2285. ;                5 - file not found
  2286. ;               10 - access denied
  2287. ;          ebx = file attribute
  2288. ;-----------------------------------------------------------
  2289.     cmp   [fat_type],0
  2290.     jnz   get_fileattr_fat_ok
  2291.     xor   ebx,ebx
  2292.     mov   eax,ERROR_UNKNOWN_FS
  2293.     ret
  2294.  
  2295.   get_fileattr_fat_ok:
  2296. ;    call  reserve_hd1
  2297.  
  2298.     pushad
  2299.     mov   ebx,edx
  2300.     call  get_cluster_of_a_path
  2301.     jc    get_fileattr_not_found
  2302.  
  2303.     mov   ebx,PUSHAD_EAX        ; file name
  2304.     call  analyze_directory
  2305.     jc    get_fileattr_not_found
  2306.  
  2307.     movzx eax,byte [ebx+11]     ; file attribute
  2308.     mov   PUSHAD_EBX,eax
  2309.     popad
  2310.     mov   [hd1_status],0
  2311.     xor   eax,eax
  2312.     ret
  2313.  
  2314.   get_fileattr_not_found:
  2315.     cmp   [hd_error],0
  2316.     jne   get_fileattr_access_denied
  2317.     popad
  2318.     mov   [hd1_status],0
  2319.     xor   ebx,ebx
  2320.     mov   eax,ERROR_FILE_NOT_FOUND
  2321.     ret
  2322.  
  2323.   get_fileattr_access_denied:
  2324.     popad
  2325.     mov   [hd1_status],0
  2326.     xor   ebx,ebx
  2327.     mov   eax,ERROR_ACCESS_DENIED
  2328.     ret
  2329.  
  2330. get_filedate:
  2331. ;-----------------------------------------------------------
  2332. ; input  : eax = file name
  2333. ;          edx = path
  2334. ; output : eax = 0 - ok
  2335. ;                3 - unknown FS
  2336. ;                5 - file not found
  2337. ;               10 - access denied
  2338. ;          ebx = file date/time
  2339. ;                bits 31..25 = year-1980
  2340. ;                bits 24..21 = month
  2341. ;                bits 20..16 = day
  2342. ;                bits 15..11 = hour
  2343. ;                bits 10..5  = minute
  2344. ;                bits 4..0   = second/2
  2345. ;-----------------------------------------------------------
  2346.     cmp   [fat_type],0
  2347.     jnz   get_filedate_fat_ok
  2348.     xor   ebx,ebx
  2349.     mov   eax,ERROR_UNKNOWN_FS
  2350.     ret
  2351.  
  2352.   get_filedate_fat_ok:
  2353. ;    call  reserve_hd1
  2354.  
  2355.     pushad
  2356.     mov   ebx,edx
  2357.     call  get_cluster_of_a_path
  2358.     jc    get_filedate_not_found
  2359.  
  2360.     mov   ebx,PUSHAD_EAX        ; file name
  2361.     call  analyze_directory
  2362.     jc    get_filedate_not_found
  2363.  
  2364.     mov   eax,[ebx+22]          ; file date/time
  2365.     mov   PUSHAD_EBX,eax
  2366.     popad
  2367.     mov   [hd1_status],0
  2368.     xor   eax,eax
  2369.     ret
  2370.  
  2371.   get_filedate_not_found:
  2372.     cmp   [hd_error],0
  2373.     jne   get_filedate_access_denied
  2374.     popad
  2375.     mov   [hd1_status],0
  2376.     xor   ebx,ebx
  2377.     mov   eax,ERROR_FILE_NOT_FOUND
  2378.     ret
  2379.  
  2380.   get_filedate_access_denied:
  2381.     popad
  2382.     mov   [hd1_status],0
  2383.     xor   ebx,ebx
  2384.     mov   eax,ERROR_ACCESS_DENIED
  2385.     ret
  2386.  
  2387. get_hd_info:
  2388. ;-----------------------------------------------------------
  2389. ; output : eax = 0 - ok
  2390. ;                3 - unknown FS
  2391. ;               10 - access denied
  2392. ;          edx = cluster size in bytes
  2393. ;          ebx = total clusters on disk
  2394. ;          ecx = free clusters on disk
  2395. ;-----------------------------------------------------------
  2396.     cmp   [fat_type],0
  2397.     jnz   info_fat_ok
  2398.     xor   edx,edx
  2399.     xor   ebx,ebx
  2400.     xor   ecx,ecx
  2401.     mov   eax,ERROR_UNKNOWN_FS
  2402.     ret
  2403.  
  2404.   info_fat_ok:
  2405. ;    call  reserve_hd1
  2406.  
  2407.     xor   ecx,ecx               ; count of free clusters
  2408.     mov   eax,2
  2409.     mov   ebx,[LAST_CLUSTER]
  2410.  
  2411.   info_cluster:
  2412.     push  eax
  2413.     call  get_FAT               ; get cluster info
  2414.     cmp   [hd_error],0
  2415.     jne   info_access_denied
  2416.  
  2417.     test  eax,eax               ; is it free?
  2418.     jnz   info_used             ; no
  2419.     inc   ecx
  2420.  
  2421.   info_used:
  2422.     pop   eax
  2423.     inc   eax
  2424.     cmp   eax,ebx               ; is above last cluster?
  2425.     jbe   info_cluster          ; no. test next cluster
  2426.  
  2427.     dec   ebx                   ; cluster count
  2428.     imul  edx,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
  2429.     mov   [hd1_status],0
  2430.     xor   eax,eax
  2431.     ret
  2432.  
  2433.   info_access_denied:
  2434.     add   esp,4
  2435.     xor   edx,edx
  2436.     xor   ebx,ebx
  2437.     xor   ecx,ecx
  2438.     mov   eax,ERROR_ACCESS_DENIED
  2439.     ret
  2440.  
  2441. update_disk:
  2442. ;-----------------------------------------------------------
  2443. ; write changed fat and cache to disk
  2444. ;-----------------------------------------------------------
  2445.     cmp   [fat_change],0        ; is fat changed?
  2446.     je    upd_no_change
  2447.  
  2448.     call  write_fat_sector
  2449.     cmp   [hd_error],0
  2450.     jne   update_disk_acces_denied
  2451.  
  2452.   upd_no_change:
  2453.  
  2454.     call  write_cache
  2455.   update_disk_acces_denied:
  2456.     ret
  2457.  
  2458.  
  2459. ;**************************************************************************
  2460. ;
  2461. ;   0x600008  - first entry in cache list
  2462. ;
  2463. ;            +0   - lba sector
  2464. ;            +4   - state of cache sector
  2465. ;                   0 = empty
  2466. ;                   1 = used for read  ( same as in hd )
  2467. ;                   2 = used for write ( differs from hd )
  2468. ;
  2469. ;      +65536 - cache entries
  2470. ;
  2471. ;**************************************************************************
  2472.  
  2473.  
  2474. hd_read:
  2475. ;-----------------------------------------------------------
  2476. ; input  : eax = block to read
  2477. ;          ebx = destination
  2478. ;-----------------------------------------------------------
  2479.     push  ecx esi edi           ; scan cache
  2480.  
  2481.     mov   ecx,cache_max         ; entries in cache
  2482.     mov   esi,0x600000+8
  2483.     mov   edi,1
  2484.  
  2485.   hdreadcache:
  2486.  
  2487.     cmp   dword [esi+4],0       ; empty
  2488.     je    nohdcache
  2489.  
  2490.     cmp   [esi],eax             ; correct sector
  2491.     je    yeshdcache
  2492.  
  2493.   nohdcache:
  2494.  
  2495.     add   esi,8
  2496.     inc   edi
  2497.     dec   ecx
  2498.     jnz   hdreadcache
  2499.  
  2500.     call  find_empty_slot       ; ret in edi
  2501.     cmp   [hd_error],0
  2502.     jne   return_01
  2503.  
  2504.     push  eax edx
  2505.  
  2506.     call  wait_for_hd_idle
  2507.     cmp   [hd_error],0
  2508.     jne   hd_read_error    
  2509.  
  2510.     cli
  2511.     xor   eax,eax
  2512.     mov   edx,[hdbase]
  2513.     inc   edx
  2514.     out   dx,al   ; ATAFeatures  ¥£ð¡¢  "®¡®¡¥­­®¡¢¥©"
  2515.     inc   edx
  2516.     inc   eax
  2517.     out   dx,al   ; ATASectorCount ¡§¥¢§ðª ¡¥ª¢® ®¢
  2518.     inc   edx
  2519.     mov   eax,[esp+4]
  2520.     out   dx,al   ; ATASectorNumber  ¥£ð¡¢  ­®¬¥   ¡¥ª¢®  
  2521.     shr   eax,8
  2522.     inc   edx
  2523.     out   dx,al   ; ATACylinder ­®¬¥  ¦ð«ð­¤   (¬« ¤¨ð© ¡ ©¢)
  2524.     shr   eax,8
  2525.     inc   edx
  2526.     out   dx,al   ; ­®¬¥  ¦ð«ð­¤   (¡¢  ¨ð© ¡ ©¢)
  2527.     shr   eax,8
  2528.     inc   edx
  2529.     and   al,1+2+4+8
  2530.     add   al,byte [hdid]
  2531.     add   al,128+64+32
  2532.     out   dx,al   ; ­®¬¥  £®«®¢ªð/­®¬¥  ¤ð¡ª 
  2533.     inc   edx
  2534.     mov   al,20h
  2535.     out   dx,al   ; ATACommand  ¥£ð¡¢  ª®¬ ­¤
  2536.     sti
  2537.  
  2538.     call  wait_for_sector_buffer
  2539.  
  2540.     cmp   [hd_error],0
  2541.     jne   hd_read_error
  2542.  
  2543.     cli
  2544.     push  edi
  2545.     shl   edi,9
  2546.     add   edi,0x600000+65536
  2547.     mov   ecx,256
  2548.     mov   edx,[hdbase]
  2549.     cld
  2550.     rep   insw
  2551.     pop   edi
  2552.     sti
  2553.  
  2554.     pop   edx eax
  2555.  blok_read_2:
  2556.     lea   esi,[edi*8+0x600000]
  2557.     mov   [esi],eax             ; sector number
  2558.     mov   dword [esi+4],1       ; hd read - mark as same as in hd
  2559.  
  2560.   yeshdcache:
  2561.  
  2562.     mov   esi,edi
  2563.     shl   esi,9
  2564.     add   esi,0x600000+65536
  2565.     mov   edi,ebx
  2566.     mov   ecx,512/4
  2567.     cld
  2568.     rep   movsd                 ; move data
  2569.  return_01:
  2570.     pop   edi esi ecx
  2571.     ret
  2572.    
  2573.  
  2574. hd_write:
  2575. ;-----------------------------------------------------------
  2576. ; input  : eax = block
  2577. ;          ebx = pointer to memory
  2578. ;-----------------------------------------------------------
  2579.     push  ecx esi edi
  2580.  
  2581.     ; check if the cache already has the sector and overwrite it
  2582.  
  2583.     mov   ecx,cache_max
  2584.     mov   esi,0x600000+8
  2585.     mov   edi,1
  2586.  
  2587.   hdwritecache:
  2588.  
  2589.     cmp   dword [esi+4],0       ; if cache slot is empty
  2590.     je    not_in_cache_write
  2591.  
  2592.     cmp   [esi],eax             ; if the slot has the sector
  2593.     je    yes_in_cache_write
  2594.  
  2595.   not_in_cache_write:
  2596.  
  2597.     add   esi,8
  2598.     inc   edi
  2599.     dec   ecx
  2600.     jnz   hdwritecache
  2601.  
  2602.     ; sector not found in cache
  2603.     ; write the block to a new location
  2604.  
  2605.     call  find_empty_slot       ; ret in edi
  2606.     cmp   [hd_error],0
  2607.     jne   hd_write_access_denied
  2608.  
  2609.     lea   esi,[edi*8+0x600000]
  2610.     mov   [esi],eax             ; sector number
  2611.  
  2612.   yes_in_cache_write:
  2613.  
  2614.     mov   dword [esi+4],2       ; write - differs from hd
  2615.  
  2616.     shl   edi,9
  2617.     add   edi,0x600000+65536
  2618.     mov   esi,ebx
  2619.     mov   ecx,512/4
  2620.     cld
  2621.     rep   movsd                 ; move data
  2622.  hd_write_access_denied:
  2623.     pop   edi esi ecx
  2624.     ret
  2625.  
  2626.  
  2627. write_cache:
  2628. ;-----------------------------------------------------------
  2629. ; write all changed sectors to disk
  2630. ;-----------------------------------------------------------
  2631.     push  eax ecx edx esi edi
  2632.  
  2633.     ; write difference ( 2 ) from cache to hd
  2634.  
  2635.     mov   ecx,cache_max
  2636.     mov   esi,0x600000+8
  2637.     mov   edi,1
  2638.  
  2639.   write_cache_more:
  2640.  
  2641.     cmp   dword [esi+4],2       ; if cache slot is not different
  2642.     jne   does_not_need_writing
  2643.  
  2644.     mov   dword [esi+4],1       ; same as in hd
  2645.     mov   eax,[esi]             ; eax = sector to write
  2646.  
  2647.     cmp   eax,[PARTITION_START]
  2648.     jb    danger
  2649.     cmp   eax,[PARTITION_END]
  2650.     ja    danger
  2651.  
  2652.     call  wait_for_hd_idle
  2653.     cmp   [hd_error],0
  2654.     jne   hd_write_error
  2655.  
  2656.     cli
  2657.     xor   eax,eax
  2658.     mov   edx,[hdbase]
  2659.     inc   edx
  2660.     out   dx,al
  2661.     inc   edx
  2662.     inc   eax
  2663.     out   dx,al
  2664.     inc   edx
  2665.     mov   eax,[esi]             ; eax = sector to write
  2666.     out   dx,al
  2667.     shr   eax,8
  2668.     inc   edx
  2669.     out   dx,al
  2670.     shr   eax,8
  2671.     inc   edx
  2672.     out   dx,al
  2673.     shr   eax,8
  2674.     inc   edx
  2675.     and   al,1+2+4+8
  2676.     add   al,byte [hdid]
  2677.     add   al,128+64+32
  2678.     out   dx,al
  2679.     inc   edx
  2680.     mov   al,30h
  2681.     out   dx,al
  2682.     sti
  2683.  
  2684.     call  wait_for_sector_buffer
  2685.  
  2686.     cmp   [hd_error],0
  2687.     jne   hd_write_error
  2688.  
  2689.     push  ecx esi
  2690.  
  2691.     cli
  2692.     mov   esi,edi
  2693.     shl   esi,9
  2694.     add   esi,0x600000+65536    ; esi = from memory position
  2695.     mov   ecx,256
  2696.     mov   edx,[hdbase]
  2697.     cld
  2698.     rep   outsw
  2699.     sti
  2700.  
  2701.     pop   esi ecx
  2702.  
  2703.   danger:
  2704.   does_not_need_writing:
  2705.  
  2706.     add   esi,8
  2707.     inc   edi
  2708.     dec   ecx
  2709.     jnz   write_cache_more
  2710.  return_02:
  2711.     pop   edi esi edx ecx eax
  2712.     ret
  2713.  
  2714.  
  2715. find_empty_slot:
  2716. ;-----------------------------------------------------------
  2717. ; find empty or read slot, flush cache if next 10% is used by write
  2718. ; output : edi = cache slot
  2719. ;-----------------------------------------------------------
  2720.     push  ecx esi
  2721.  
  2722.   search_again:
  2723.  
  2724.     mov   ecx,cache_max*10/100
  2725.     mov   edi,[cache_search_start]
  2726.  
  2727.   search_for_empty:
  2728.  
  2729.     inc   edi
  2730.     cmp   edi,cache_max
  2731.     jbe   inside_cache
  2732.     mov   edi,1
  2733.  
  2734.   inside_cache:
  2735.  
  2736.     cmp   dword [edi*8+0x600000+4],2    ; get cache slot info
  2737.     jb    found_slot                    ; it's empty or read
  2738.     dec   ecx
  2739.     jnz   search_for_empty
  2740.  
  2741.     call  write_cache                   ; no empty slots found, write all
  2742.     cmp   [hd_error],0
  2743.     jne   found_slot_access_denied
  2744.  
  2745.     jmp   search_again                  ; and start again
  2746.  
  2747.   found_slot:
  2748.  
  2749.     mov   [cache_search_start],edi
  2750.   found_slot_access_denied:
  2751.     pop   esi ecx
  2752.     ret
  2753.  
  2754.  
  2755. save_hd_wait_timeout:
  2756.  
  2757.     push  eax
  2758.     mov   eax,[timer_ticks];[0xfdf0]
  2759.     add   eax,300               ; 3 sec timeout
  2760.     mov   [hd_wait_timeout],eax
  2761.     pop   eax
  2762.     ret
  2763.  
  2764.  
  2765. check_hd_wait_timeout:
  2766.  
  2767.     push  eax
  2768.     mov   eax,[hd_wait_timeout]
  2769.     cmp   [timer_ticks], eax ;[0xfdf0],eax
  2770.     jg    hd_timeout_error
  2771.     pop   eax
  2772.     mov   [hd_error],0
  2773.     ret
  2774.  
  2775. iglobal
  2776.   hd_timeout_str   db 'K : FS - HD timeout',13,10,0
  2777.   hd_read_str      db 'K : FS - HD read error',13,10,0
  2778.   hd_write_str     db 'K : FS - HD write error',13,10,0
  2779.   hd_lba_str       db 'K : FS - HD LBA error',13,10,0
  2780. endg
  2781.  
  2782. hd_timeout_error:
  2783.  
  2784.     call  clear_hd_cache
  2785.     call  clear_application_table_status
  2786.     mov   esi,hd_timeout_str
  2787.     call  sys_msg_board_str
  2788. ;    jmp   $
  2789.     mov   [hd_error],1
  2790.     pop   eax
  2791.     ret
  2792.  
  2793. hd_read_error:
  2794.  
  2795.     call  clear_hd_cache
  2796.     call  clear_application_table_status
  2797.     mov   esi,hd_read_str
  2798.     call  sys_msg_board_str
  2799.     pop   edx eax
  2800.     jmp    return_01
  2801. ;    jmp   $
  2802.  
  2803. hd_write_error:
  2804.  
  2805.     call  clear_hd_cache
  2806.     call  clear_application_table_status
  2807.     mov   esi,hd_write_str
  2808.     call  sys_msg_board_str
  2809.     jmp    return_02
  2810. ;    jmp   $
  2811.  
  2812. hd_lba_error:
  2813.     call  clear_hd_cache
  2814.     call  clear_application_table_status
  2815.     mov   esi,hd_lba_str
  2816.     call  sys_msg_board_str
  2817.     jmp   LBA_read_ret
  2818.  
  2819.  
  2820. wait_for_hd_idle:
  2821.  
  2822.     push  eax edx
  2823.  
  2824.     call  save_hd_wait_timeout
  2825.  
  2826.     mov   edx,[hdbase]
  2827.     add   edx,0x7
  2828.  
  2829.   wfhil1:
  2830.  
  2831.     call  check_hd_wait_timeout
  2832.     cmp   [hd_error],0
  2833.     jne   @f
  2834.  
  2835.     in    al,dx
  2836.     test  al,128
  2837.     jnz   wfhil1
  2838.  
  2839.  @@:
  2840.  
  2841.     pop   edx eax
  2842.     ret
  2843.  
  2844.  
  2845.  
  2846. wait_for_sector_buffer:
  2847.  
  2848.     push  eax edx
  2849.  
  2850.     mov   edx,[hdbase]
  2851.     add   edx,0x7
  2852.  
  2853.     call  save_hd_wait_timeout
  2854.  
  2855.   hdwait_sbuf:                  ; wait for sector buffer to be ready
  2856.  
  2857.     call  check_hd_wait_timeout
  2858.     cmp   [hd_error],0
  2859.     jne   @f
  2860.  
  2861.     in    al,dx
  2862.     test  al,8
  2863.     jz    hdwait_sbuf
  2864.  
  2865.     mov   [hd_error],0
  2866.  
  2867.     cmp   [hd_setup],1          ; do not mark error for setup request
  2868.     je    buf_wait_ok
  2869.  
  2870.     test  al,1                  ; previous command ended up with an error
  2871.     jz    buf_wait_ok
  2872.  @@:
  2873.     mov   [hd_error],1
  2874.  
  2875.   buf_wait_ok:
  2876.  
  2877.     pop   edx eax
  2878.     ret
  2879.  
  2880.  
  2881.  
  2882. read_hd_file:
  2883. ;-----------------------------------------------------------------
  2884. ;
  2885. ; Converting old reading function for hd-application start.
  2886. ;
  2887. ; IN:
  2888. ;
  2889. ; eax - pointer to file (0 = read only first sector of drive: eg 'label')
  2890. ; ebx - file lenght
  2891. ; ecx - start 512 byte block number
  2892. ; edx - number of blocks to read
  2893. ; esi - pointer to return/work area (atleast 20 000 bytes)
  2894. ;
  2895. ; For new read function
  2896. ;
  2897. ; EAX   (PAR0)      pointer to file-name
  2898. ; ECX   (PAR1)      pointer to buffer
  2899. ; EBX   (PAR2)   vt file blocks to read
  2900. ; EDX   (PAR3)      pointer to path
  2901. ; ESI            vt first 512 block to read
  2902. ; EDI               if 0 - return root
  2903. ;--------------------------------------------------------------------------
  2904.  
  2905.     push  ecx esi edi
  2906.     mov   esi,eax
  2907.     mov   edi,startpath
  2908.     mov   ecx,250
  2909.     cld
  2910.     rep   movsb
  2911.     pop   edi esi ecx
  2912.  
  2913.     mov   eax,startpath
  2914.     mov   [eax+ebx-12],byte 0
  2915.  
  2916.     push  eax ebx ecx edx esi
  2917.  
  2918.     pop   ecx ; pointer to buffer
  2919.     add   ecx,1024
  2920.     pop   ebx ; number of blocks to read
  2921.     pop   esi ; first block to read
  2922.     dec   esi
  2923.     pop   eax ; file length
  2924.     pop   edx ; pointer to path
  2925.  
  2926.     mov   edi,12
  2927.     lea   eax,[eax+edx-12+1]
  2928.     call  file_read
  2929.  
  2930.     ret
  2931.  
  2932. ; \begin{diamond}
  2933. hd_find_lfn:
  2934. ; in: esi->name
  2935. ; out: CF=1 - file not found
  2936. ;      else CF=0 and edi->direntry
  2937.         pusha
  2938.         sub     esp, 262*2      ; allocate space for LFN
  2939.         mov     ebp, esp
  2940.         push    0               ; for fat_get_name: read ASCII name
  2941.     mov    eax, [ROOT_CLUSTER]    ; start from root
  2942. .mainloop:
  2943. .new_cluster:
  2944.     mov    [cluster_tmp], eax
  2945.     mov    [fat16_root], 0
  2946.     cmp    eax, [LAST_CLUSTER]
  2947.     ja    .notfound
  2948.     cmp    eax, 2
  2949.     jae    .data_cluster
  2950.     cmp    [fat_type], 16
  2951.     jnz    .notfound
  2952.     mov    eax, [ROOT_START]
  2953.     mov    ecx, [ROOT_SECTORS]
  2954.     mov    [fat16_root], 1
  2955.     jmp    .new_sector
  2956. .data_cluster:
  2957.     dec    eax
  2958.     dec    eax
  2959.     mov    ecx, [SECTORS_PER_CLUSTER]
  2960.     mul    ecx
  2961.     add    eax, [DATA_START]
  2962. .new_sector:
  2963.     mov    ebx, buffer
  2964.     call    hd_read
  2965.     cmp  [hd_error],0
  2966.     jne  .notfound
  2967.  
  2968.     mov    edi, ebx
  2969.     add    ebx, 512
  2970.     push    eax
  2971. .l1:
  2972.     call    fat_get_name
  2973.     jc    .l2
  2974.     call    fat_compare_name
  2975.     jz    .found
  2976. .l2:
  2977.     add    edi, 0x20
  2978.     cmp    edi, ebx
  2979.     jb    .l1
  2980.     pop    eax
  2981.     inc    eax
  2982.     loop    .new_sector
  2983.     cmp    [fat16_root], 0
  2984.     jnz    .notfound
  2985.     mov    eax, [cluster_tmp]
  2986.     call    get_FAT
  2987.     cmp   [hd_error],0
  2988.     jne   .notfound
  2989.  
  2990.     cmp    eax, 2
  2991.     jb    .notfound
  2992.     cmp    eax, [fatRESERVED]
  2993.     jb    .new_cluster
  2994. .notfound:
  2995.     add    esp, 262*2+4
  2996.     popa
  2997.     stc
  2998.     ret
  2999. .found:
  3000.     pop    eax
  3001. ; if this is LFN entry, advance to true entry
  3002.     cmp    byte [edi+11], 0xF
  3003.     jnz    .entryfound
  3004.     add    edi, 0x20
  3005.     cmp    edi, ebx
  3006.     jb    .entryfound
  3007.     inc    eax
  3008.     dec    ecx
  3009.     jnz    .read_entry
  3010.     cmp    [fat16_root], 0
  3011.     jnz    .notfound
  3012.     mov    eax, [cluster_tmp]
  3013.     call    get_FAT
  3014.     cmp   [hd_error],0
  3015.     jne   .notfound
  3016.  
  3017.     cmp    eax, 2
  3018.     jb    .notfound
  3019.     cmp    eax, [fatRESERVED]
  3020.     jae    .notfound
  3021.     dec    eax
  3022.     dec    eax
  3023.     mul    [SECTORS_PER_CLUSTER]
  3024.     add    eax, [DATA_START]
  3025. .read_entry:
  3026.     mov    ebx, [buffer]
  3027.     call    hd_read
  3028.     cmp  [hd_error],0
  3029.     jne  .notfound
  3030.  
  3031.     mov    edi, ebx
  3032. .entryfound:
  3033.     cmp    byte [esi], 0
  3034.     jz    .done
  3035.     test    byte [edi+11], 10h    ; is a directory?
  3036.     jz    .notfound
  3037.     mov    eax, [edi+20-2]
  3038.     mov    ax, [edi+26]
  3039.     jmp    .mainloop
  3040. .done:
  3041.     add    esp, 262*2+4+4    ; CF=0
  3042.     push    edi
  3043.     popad
  3044.     ret
  3045.  
  3046. ;----------------------------------------------------------------
  3047. ;
  3048. ;  fs_HdRead - LFN variant for reading hard disk
  3049. ;
  3050. ;  esi  points to filename
  3051. ;  ebx  pointer to 64-bit number = first wanted byte, 0+
  3052. ;       may be ebx=0 - start from first byte
  3053. ;  ecx  number of bytes to read, 0+
  3054. ;  edx  mem location to return data
  3055. ;
  3056. ;  ret ebx = bytes read or 0xffffffff file not found
  3057. ;      eax = 0 ok read or other = errormsg
  3058. ;
  3059. ;--------------------------------------------------------------
  3060. fs_HdRead:
  3061.     cmp    [fat_type], 0
  3062.     jnz    @f
  3063.     or    ebx, -1
  3064.     mov    eax, ERROR_UNKNOWN_FS
  3065.     ret
  3066. @@:
  3067.     push    edi
  3068.     cmp    byte [esi], 0
  3069.     jnz    @f
  3070. .noaccess:
  3071.     pop    edi
  3072. .noaccess_2:
  3073.     or    ebx, -1
  3074.     mov    eax, ERROR_ACCESS_DENIED
  3075.     ret
  3076.  
  3077. .noaccess_3:
  3078.     add esp,4
  3079. .noaccess_1:
  3080.     add esp,4
  3081. .noaccess_4:
  3082.     add esp,4*5
  3083.     jmp  .noaccess_2
  3084.  
  3085. @@:
  3086.     call    hd_find_lfn
  3087.     jnc    .found
  3088.     pop    edi
  3089.     cmp   [hd_error],0
  3090.     jne   .noaccess_2
  3091.     or    ebx, -1
  3092.     mov    eax, ERROR_FILE_NOT_FOUND
  3093.     ret
  3094.  
  3095. .found:
  3096.     test    byte [edi+11], 0x10    ; do not allow read directories
  3097.     jnz    .noaccess
  3098.     test    ebx, ebx
  3099.     jz    .l1
  3100.     cmp    dword [ebx+4], 0
  3101.     jz    @f
  3102.         xor     ebx, ebx
  3103. .reteof:
  3104.     mov    eax, 6
  3105.     pop    edi
  3106.     ret
  3107. @@:
  3108.     mov    ebx, [ebx]
  3109. .l1:
  3110.         push    ecx edx
  3111.         push    0
  3112.         mov     eax, [edi+28]
  3113.         sub     eax, ebx
  3114.         jb      .eof
  3115.         cmp     eax, ecx
  3116.         jae     @f
  3117.         mov     ecx, eax
  3118.         mov     byte [esp], 6
  3119. @@:
  3120.     mov    eax, [edi+20-2]
  3121.     mov    ax, [edi+26]
  3122. ; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
  3123. .new_cluster:
  3124.     jecxz    .new_sector
  3125.     test    eax, eax
  3126.     jz    .eof
  3127.     cmp    eax, [fatRESERVED]
  3128.     jae    .eof
  3129.     mov    [cluster_tmp], eax
  3130.     dec    eax
  3131.     dec    eax
  3132.     mov    edi, [SECTORS_PER_CLUSTER]
  3133.     imul    eax, edi
  3134.     add    eax, [DATA_START]
  3135. .new_sector:
  3136.     test    ecx, ecx
  3137.     jz    .done
  3138.     sub    ebx, 512
  3139.     jae    .skip
  3140.     add    ebx, 512
  3141.     jnz    .force_buf
  3142.     cmp    ecx, 512
  3143.     jb    .force_buf
  3144. ; we may read directly to given buffer
  3145.     push    ebx
  3146.     mov    ebx, edx
  3147.     call    hd_read
  3148.     cmp  [hd_error],0
  3149.     jne  .noaccess_1    
  3150.     pop    ebx
  3151.     add    edx, 512
  3152.     sub    ecx, 512
  3153.     jmp    .skip
  3154. .force_buf:
  3155. ; we must read sector to temporary buffer and then copy it to destination
  3156.     push    eax ebx
  3157.     mov    ebx, buffer
  3158.     call    hd_read
  3159.     cmp  [hd_error],0
  3160.     jne  .noaccess_3
  3161.  
  3162.     mov    eax, ebx
  3163.     pop    ebx
  3164.     add    eax, ebx
  3165.     push    ecx
  3166.     add    ecx, ebx
  3167.     cmp    ecx, 512
  3168.     jbe    @f
  3169.     mov    ecx, 512
  3170. @@:
  3171.     sub    ecx, ebx
  3172.     mov    ebx, edx
  3173.     call    memmove
  3174.     add    edx, ecx
  3175.     sub    [esp], ecx
  3176.     pop    ecx
  3177.     pop    eax
  3178.     xor    ebx, ebx
  3179. .skip:
  3180.     inc    eax
  3181.     dec    edi
  3182.     jnz    .new_sector
  3183.     mov    eax, [cluster_tmp]
  3184.     call    get_FAT
  3185.     cmp   [hd_error],0
  3186.     jne   .noaccess_4
  3187.  
  3188.     jmp    .new_cluster
  3189. .done:
  3190.         mov     ebx, edx
  3191.         pop     eax edx ecx edi
  3192.         sub     ebx, edx
  3193.         ret
  3194. .eof:
  3195.         mov     ebx, edx
  3196.         pop     eax edx ecx
  3197.         sub     ebx, edx
  3198.         jmp     .reteof
  3199.  
  3200. ;----------------------------------------------------------------
  3201. ;
  3202. ;  fs_HdReadFolder - LFN variant for reading hard disk folder
  3203. ;
  3204. ;  esi  points to filename
  3205. ;  ebx  pointer to structure 32-bit number = first wanted block, 0+
  3206. ;                          & flags (bitfields)
  3207. ; flags: bit 0: 0=ANSI names, 1=UNICODE names
  3208. ;  ecx  number of blocks to read, 0+
  3209. ;  edx  mem location to return data
  3210. ;
  3211. ;  ret ebx = blocks read or 0xffffffff folder not found
  3212. ;      eax = 0 ok read or other = errormsg
  3213. ;
  3214. ;--------------------------------------------------------------
  3215. fs_HdReadFolder:
  3216.         mov     eax, [ROOT_CLUSTER]
  3217.         push    edi
  3218.         cmp     byte [esi], 0
  3219.         jz      .doit
  3220.         call    hd_find_lfn
  3221.         jnc     .found
  3222.         pop     edi
  3223.         or      ebx, -1
  3224.         mov     eax, ERROR_FILE_NOT_FOUND
  3225.         ret
  3226. .found:
  3227.         test    byte [edi+11], 0x10     ; do not allow read files
  3228.         jnz     .found_dir
  3229.         pop     edi
  3230.         or      ebx, -1
  3231.         mov     eax, ERROR_ACCESS_DENIED
  3232.         ret
  3233. .found_dir:
  3234.         mov     eax, [edi+20-2]
  3235.         mov     ax, [edi+26]    ; eax=cluster
  3236. .doit:
  3237.         push    esi ecx
  3238.         push    ebp
  3239.         sub     esp, 262*2      ; reserve space for LFN
  3240.         mov     ebp, esp
  3241.         push    dword [ebx+4]   ; for fat_get_name: read ANSI/UNICODE name
  3242.         mov     ebx, [ebx]
  3243. ; init header
  3244.         push    eax ecx
  3245.         mov     edi, edx
  3246.         mov     ecx, 32/4
  3247.         xor     eax, eax
  3248.         rep     stosd
  3249.         pop     ecx eax
  3250.         mov     byte [edx], 1   ; version
  3251.         mov     esi, edi        ; esi points to BDFE
  3252. .new_cluster:
  3253.         mov     [cluster_tmp], eax
  3254.         test    eax, eax
  3255.         jnz     @f
  3256.         cmp     [fat_type], 32
  3257.         jz      .notfound
  3258.         mov     eax, [ROOT_START]
  3259.         push    [ROOT_SECTORS]
  3260.         push    ebx
  3261.         jmp     .new_sector
  3262. @@:
  3263.         dec     eax
  3264.         dec     eax
  3265.         imul    eax, [SECTORS_PER_CLUSTER]
  3266.         push    [SECTORS_PER_CLUSTER]
  3267.         add     eax, [DATA_START]
  3268.         push    ebx
  3269. .new_sector:
  3270.         mov     ebx, buffer
  3271.         mov     edi, ebx
  3272.         call    hd_read
  3273.         cmp     [hd_error], 0
  3274.         jnz     .notfound2
  3275.         add     ebx, 512
  3276.         push    eax
  3277. .l1:
  3278.         call    fat_get_name
  3279.         jc      .l2
  3280.         cmp     byte [edi+11], 0xF
  3281.         jnz     .do_bdfe
  3282.         add     edi, 0x20
  3283.         cmp     edi, ebx
  3284.         jb      .do_bdfe
  3285.         pop     eax
  3286.         inc     eax
  3287.         dec     dword [esp+4]
  3288.         jnz     @f
  3289.         mov     eax, [cluster_tmp]
  3290.         test    eax, eax
  3291.         jz      .done
  3292.         call    get_FAT
  3293.         cmp     [hd_error], 0
  3294.         jnz     .notfound2
  3295.         cmp     eax, 2
  3296.         jb      .done
  3297.         cmp     eax, [fatRESERVED]
  3298.         jae     .done
  3299.         push    eax
  3300.         mov     eax, [SECTORS_PER_CLUSTER]
  3301.         mov     [esp+8], eax
  3302.         pop     eax
  3303.         mov     [cluster_tmp], eax
  3304.         dec     eax
  3305.         dec     eax
  3306.         imul    eax, [SECTORS_PER_CLUSTER]
  3307.         add     eax, [DATA_START]
  3308. @@:
  3309.         mov     ebx, buffer
  3310.         mov     edi, ebx
  3311.         call    hd_read
  3312.         cmp     [hd_error], 0
  3313.         jnz     .notfound2
  3314.         add     ebx, 512
  3315.         push    eax
  3316. .do_bdfe:
  3317.         inc     dword [edx+8]   ; new file found
  3318.         dec     dword [esp+4]
  3319.         jns     .l2
  3320.         dec     ecx
  3321.         js      .l2
  3322.         inc     dword [edx+4]   ; new file block copied
  3323.         call    fat_entry_to_bdfe
  3324. .l2:
  3325.         add     edi, 0x20
  3326.         cmp     edi, ebx
  3327.         jb      .l1
  3328.         pop     eax
  3329.         inc     eax
  3330.         dec     dword [esp+4]
  3331.         jnz     .new_sector
  3332.         mov     eax, [cluster_tmp]
  3333.         test    eax, eax
  3334.         jz      .done
  3335.         call    get_FAT
  3336.         cmp     [hd_error], 0
  3337.         jnz     .notfound2
  3338.         cmp     eax, 2
  3339.         jb      .done
  3340.         cmp     eax, [fatRESERVED]
  3341.         jae     .done
  3342.         push    eax
  3343.         mov     eax, [SECTORS_PER_CLUSTER]
  3344.         mov     [esp+8], eax
  3345.         pop     eax
  3346.         pop     ebx
  3347.         add     esp, 4
  3348.         jmp     .new_cluster
  3349. .notfound2:
  3350.         add     esp, 8
  3351. .notfound:
  3352.         add     esp, 262*2+4
  3353.         pop     ebp ecx esi edi
  3354.         mov     eax, ERROR_FILE_NOT_FOUND
  3355.         or      ebx, -1
  3356.         ret
  3357. .done:
  3358.         add     esp, 262*2+4+8
  3359.         pop     ebp
  3360.         mov     ebx, [edx+4]
  3361.         xor     eax, eax
  3362.         dec     ecx
  3363.         js      @f
  3364.         mov     al, ERROR_END_OF_FILE
  3365. @@:
  3366.         pop     ecx esi edi
  3367.         ret
  3368.  
  3369. ; \end{diamond}
  3370.