Subversion Repositories Kolibri OS

Rev

Rev 63 | Go to most recent revision | 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. ;;                                                                 ;;
  11. ;;  28.01.2006 find all Fat16/32 partition in all input point      ;;
  12. ;;             to MBR, see file part_set.inc - Mario79             ;;
  13. ;;  15.01.2005 get file size/attr/date, file_append - ATV          ;;
  14. ;;  04.12.2004 skip volume label, file delete bug fixed - ATV      ;;
  15. ;;  29.11.2004 get_free_FAT changed, append dir bug fixed - ATV    ;;
  16. ;;  23.11.2004 don't allow overwrite dir with file - ATV           ;;
  17. ;;  18.11.2004 get_disk_info and more error codes - ATV            ;;
  18. ;;  17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV      ;;
  19. ;;  10.11.2004 removedir clear whole directory structure - ATV     ;;
  20. ;;  08.11.2004 rename - ATV                                        ;;
  21. ;;  30.10.2004 file_read return also dirsize in bytes - ATV        ;;
  22. ;;  20.10.2004 Makedir/Removedir - ATV                             ;;
  23. ;;  14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx)         ;;
  24. ;;  06.9.2004  Fix free space by Mario79 added - MH                ;;
  25. ;;  24.5.2004  Write back buffer for File_write -VT                ;;
  26. ;;  20.5.2004  File_read function to work with syscall 58 - VT     ;;
  27. ;;  30.3.2004  Error parameters at function return - VT            ;;
  28. ;;  01.5.2002  Bugfix in device write - VT                         ;;
  29. ;;  20.5.2002  Hd status check - VT                                ;;
  30. ;;  29.6.2002  Improved fat32 verification - VT                    ;;
  31. ;;                                                                 ;;
  32. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  33.  
  34. cache_max equ 1919      ; max. is 1919*512+0x610000=0x6ffe00
  35.  
  36. ERROR_SUCCESS        = 0
  37. ERROR_DISK_BASE      = 1
  38. ERROR_UNSUPPORTED_FS = 2
  39. ERROR_UNKNOWN_FS     = 3
  40. ERROR_PARTITION      = 4
  41. ERROR_FILE_NOT_FOUND = 5
  42. ERROR_END_OF_FILE    = 6
  43. ERROR_MEMORY_POINTER = 7
  44. ERROR_DISK_FULL      = 8
  45. ERROR_FAT_TABLE      = 9
  46. ERROR_ACCESS_DENIED  = 10
  47.  
  48. PUSHAD_EAX equ [esp+28]
  49. PUSHAD_ECX equ [esp+24]
  50. PUSHAD_EDX equ [esp+20]
  51. PUSHAD_EBX equ [esp+16]
  52. PUSHAD_EBP equ [esp+8]
  53. PUSHAD_ESI equ [esp+4]
  54. PUSHAD_EDI equ [esp+0]
  55.  
  56. cluster              dd 0       ; used by file_write,makedir,append
  57. partition_count      dd 0       ; partitions found by set_FAT32_variables
  58. longname_sec1        dd 0       ; used by analyze_directory to save 2 previous
  59. longname_sec2        dd 0       ; directory sectors for delete long filename
  60.  
  61. hd_error             dd 0       ; set by wait_for_sector_buffer
  62. hd_setup             dd 0
  63. hd_wait_timeout      dd 0
  64.  
  65. cluster_tmp          dd 0       ; used by analyze_directory
  66.                                 ; and analyze_directory_to_write
  67.  
  68. file_size            dd 0       ; used by file_read
  69.  
  70. sector_tmp           dd 0       ; used by rename,append,file_write
  71. entry_pos            dd 0       ; used by rename,append,file_write
  72.  
  73. old_filesize         dd 0       ; used by append
  74. new_filepos          dd 0       ; used by append
  75. bytes2write          dd 0       ; used by append
  76.  
  77. cache_search_start   dd 0       ; used by find_empty_slot
  78.  
  79. fat_in_cache         dd -1
  80. fat_cache:           times 512 db 0
  81.  
  82. uglobal
  83.  Sector512:                      ; label for dev_hdcd.inc
  84.   buffer:              times 512 db 0
  85.   deltree_buffer:      times 512 db 0
  86. endg
  87.  
  88. iglobal
  89.   NewDirEntry1         db ".          ",0x10
  90.                      times 20 db 0
  91.   NewDirEntry2         db "..         ",0x10
  92.                      times 20 db 0
  93. endg
  94.  
  95. uglobal
  96.   dir_entry:           times 32 db 0
  97.  
  98.   startpath:           times 255 db 0
  99.  
  100.   fat16_root           db 0       ; flag for fat16 rootdir
  101.   f_del                db 0       ; 1=overwrite fat entry
  102.   fat_change           db 0       ; 1=fat has changed
  103.  
  104. endg
  105.  
  106. reserve_hd1:
  107.  
  108.     cli
  109.     cmp   [hd1_status],0
  110.     je    reserve_ok1
  111.  
  112.     sti
  113.     call  change_task
  114.     jmp   reserve_hd1
  115.  
  116.   reserve_ok1:
  117.  
  118.     push  eax
  119.     mov   eax,[0x3000]
  120.     shl   eax,5
  121.     mov   eax,[eax+0x3000+4]
  122.     mov   [hd1_status],eax
  123.     pop   eax
  124.     sti
  125.     ret
  126.  
  127.  
  128. clear_hd_cache:
  129.  
  130.     push  eax ecx edi
  131.     mov   edi,0x600000
  132.     mov   ecx,16384
  133.     xor   eax,eax
  134.     cld
  135.     rep   stosd                 ; clear hd cache with 0
  136.     mov   [cache_search_start],eax
  137.     mov   [fat_in_cache],-1
  138.     mov   [fat_change],0
  139.     pop   edi ecx eax
  140.     ret
  141.  
  142. problem_partition db 0  ; used for partitions search
  143.  
  144. include  'part_set.inc'
  145.  
  146. set_FAT:
  147. ;--------------------------------
  148. ; input  : EAX = cluster
  149. ;          EDX = value to save
  150. ; output : EDX = old value
  151. ;--------------------------------
  152.     push  eax ebx esi
  153.  
  154.     cmp   eax,2
  155.     jb    sfc_error
  156.     cmp   eax,[LAST_CLUSTER]
  157.     ja    sfc_error
  158.     cmp   [fat_type],16
  159.     je    sfc_1
  160.     add   eax,eax
  161.   sfc_1:
  162.     add   eax,eax
  163.     mov   esi,511
  164.     and   esi,eax               ; esi = position in fat sector
  165.     shr   eax,9                 ; eax = fat sector
  166.     add   eax,[FAT_START]
  167.     mov   ebx,fat_cache
  168.  
  169.     cmp   eax,[fat_in_cache]    ; is fat sector already in memory?
  170.     je    sfc_in_cache          ; yes
  171.  
  172.     cmp   [fat_change],0        ; is fat changed?
  173.     je    sfc_no_change         ; no
  174.     call  write_fat_sector      ; yes. write it into disk
  175.  
  176.   sfc_no_change:
  177.     mov   [fat_in_cache],eax    ; save fat sector
  178.     call  hd_read
  179.  
  180.   sfc_in_cache:
  181.     cmp   [fat_type],16
  182.     jne   sfc_test32
  183.  
  184.     cmp   [f_del],1             ; overwrite previous value?
  185.     je    sfc_set16             ; yes
  186.     cmp   word [ebx+esi],0      ; is cluster free?
  187.     je    sfc_set16             ; yes
  188.     mov   dword [8*0x100000],0xffffff
  189.     mov   edx,[ebx+esi]         ; get old value
  190.     jmp   sfc_nonzero
  191.  
  192.   sfc_set16:
  193.     xchg  [ebx+esi],dx          ; save new value and get old value
  194.     jmp   sfc_write
  195.  
  196.   sfc_test32:
  197.     mov   eax,[fatMASK]
  198.     cmp   [f_del],1             ; overwrite previous value?
  199.     je    sfc_set32             ; yes
  200.     test  eax,[ebx+esi]         ; is cluster free?
  201.     je    sfc_set32             ; yes
  202.     mov   dword [8*0x100000],0xffffff
  203.     mov   edx,[ebx+esi]         ; get old value
  204.     jmp   sfc_nonzero
  205.  
  206.   sfc_set32:
  207.     and   edx,eax
  208.     xor   eax,-1                ; mask for high bits
  209.     and   eax,[ebx+esi]         ; get high 4 bits
  210.     or    eax,edx
  211.     mov   edx,[ebx+esi]         ; get old value
  212.     mov   [ebx+esi],eax         ; save new value
  213.  
  214.   sfc_write:
  215.     mov   [fat_change],1        ; fat has changed
  216.  
  217.   sfc_nonzero:
  218.     and   edx,[fatMASK]
  219.  
  220.   sfc_error:
  221.     pop   esi ebx eax
  222.     ret
  223.  
  224.  
  225. get_FAT:
  226. ;--------------------------------
  227. ; input  : EAX = cluster
  228. ; output : EAX = next cluster
  229. ;--------------------------------
  230.     push  ebx esi
  231.  
  232.     cmp   [fat_type],16
  233.     je    gfc_1
  234.     add   eax,eax
  235.   gfc_1:
  236.     add   eax,eax
  237.     mov   esi,511
  238.     and   esi,eax               ; esi = position in fat sector
  239.     shr   eax,9                 ; eax = fat sector
  240.     add   eax,[FAT_START]
  241.     mov   ebx,fat_cache
  242.  
  243.     cmp   eax,[fat_in_cache]    ; is fat sector already in memory?
  244.     je    gfc_in_cache
  245.  
  246.     cmp   [fat_change],0        ; is fat changed?
  247.     je    gfc_no_change         ; no
  248.     call  write_fat_sector      ; yes. write it into disk
  249.  
  250.   gfc_no_change:
  251.     mov   [fat_in_cache],eax
  252.     call  hd_read
  253.  
  254.   gfc_in_cache:
  255.     mov   eax,[ebx+esi]
  256.     and   eax,[fatMASK]
  257.     pop   esi ebx
  258.     ret
  259.  
  260.  
  261. get_free_FAT:
  262. ;-----------------------------------------------------------
  263. ; input  : EAX = # cluster for start the searching
  264. ; output : if CARRY=0 EAX = # first cluster found free
  265. ;          if CARRY=1 disk full
  266. ; Note   : for more speed need to use fat_cache directly
  267. ;-----------------------------------------------------------
  268.     push  ecx
  269.     mov   ecx,[LAST_CLUSTER]    ; counter for full disk
  270.     sub   ecx,2
  271.  
  272.   gff_test:
  273.     cmp   eax,[LAST_CLUSTER]    ; if above last cluster start at cluster 2
  274.     jbe   gff_in_range
  275.     mov   eax,2
  276.  
  277.   gff_in_range:
  278.     push  eax
  279.     call  get_FAT               ; get cluster state
  280.     test  eax,eax               ; is it free?
  281.     pop   eax
  282.     je    gff_found             ; yes
  283.     inc   eax                   ; next cluster
  284.     dec   ecx                   ; is all checked?
  285.     jns   gff_test              ; no
  286.  
  287.   gff_not_found:
  288.     pop   ecx                   ; yes. disk is full
  289.     stc
  290.     ret
  291.  
  292.   gff_found:
  293.     pop   ecx
  294.     clc
  295.     ret
  296.  
  297.  
  298. write_fat_sector:
  299. ;-----------------------------------------------------------
  300. ; write changed fat to disk
  301. ;-----------------------------------------------------------
  302.     push  eax ebx ecx
  303.  
  304.     mov   [fat_change],0
  305.     mov   eax,[fat_in_cache]
  306.     cmp   eax,-1
  307.     jz    write_fat_not_used
  308.     mov   ebx,fat_cache
  309.     mov   ecx,[NUMBER_OF_FATS]
  310.  
  311.   write_next_fat:
  312.     call  hd_write
  313.     add   eax,[SECTORS_PER_FAT]
  314.     dec   ecx
  315.     jnz   write_next_fat
  316.  
  317.   write_fat_not_used:
  318.     pop   ecx ebx eax
  319.     ret
  320.  
  321.  
  322. analyze_directory:
  323. ;-----------------------------------------------------------
  324. ; input  : EAX = first cluster of the directory
  325. ;          EBX = pointer to filename
  326. ; output : IF CARRY=0 EAX = sector where th file is found
  327. ;                     EBX = pointer in buffer
  328. ;                     [buffer .. buffer+511]
  329. ;                     ECX,EDX,ESI,EDI not changed
  330. ;          IF CARRY=1 filename not found
  331. ; Note   : if cluster=0 it's changed to read rootdir
  332. ;          save 2 previous directory sectors in longname_sec
  333. ;-----------------------------------------------------------
  334.     push  ecx edx esi edi ebx   ; ebx = [esp+0]
  335.     mov   [longname_sec1],0
  336.     mov   [longname_sec2],0
  337.  
  338.   adr_new_cluster:
  339.     mov   [cluster_tmp],eax
  340.     mov   [fat16_root],0
  341.     cmp   eax,[LAST_CLUSTER]
  342.     ja    adr_not_found         ; too big cluster number, something is wrong
  343.     cmp   eax,2
  344.     jnb   adr_data_cluster
  345.  
  346.     mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
  347.     cmp   [fat_type],16
  348.     jne   adr_data_cluster
  349.     mov   eax,[ROOT_START]
  350.     mov   edx,[ROOT_SECTORS]
  351.     mov   [fat16_root],1        ; flag for fat16 rootdir
  352.     jmp   adr_new_sector
  353.  
  354.   adr_data_cluster:
  355.     sub   eax,2
  356.     mov   edx,[SECTORS_PER_CLUSTER]
  357.     imul  eax,edx
  358.     add   eax,[DATA_START]
  359.  
  360.   adr_new_sector:
  361.     mov   ebx,buffer
  362.     call  hd_read
  363.     mov   ecx,512/32            ; count of dir entrys per sector = 16
  364.  
  365.   adr_analyze:
  366.     mov   edi,[ebx+11]          ; file attribute
  367.     and   edi,0xf
  368.     cmp   edi,0xf
  369.     je    adr_long_filename
  370.     test  edi,0x8               ; skip over volume label
  371.     jne   adr_long_filename     ; Note: label can be same name as file/dir
  372.  
  373.     mov   esi,[esp+0]           ; filename need to be uppercase
  374.     mov   edi,ebx
  375.     push  ecx
  376.     mov   ecx,11
  377.     cld
  378.     rep   cmpsb                 ; compare 8+3 filename
  379.     pop   ecx
  380.     je    adr_found
  381.  
  382.   adr_long_filename:
  383.     add   ebx,32                ; position of next dir entry
  384.     dec   ecx
  385.     jnz   adr_analyze
  386.  
  387.     mov   ecx,[longname_sec1]   ; save 2 previous directory sectors
  388.     mov   [longname_sec1],eax   ; for delete long filename
  389.     mov   [longname_sec2],ecx
  390.     inc   eax                   ; next sector
  391.     dec   edx
  392.     jne   adr_new_sector
  393.     cmp   [fat16_root],1        ; end of fat16 rootdir
  394.     je    adr_not_found
  395.  
  396.   adr_next_cluster:
  397.     mov   eax,[cluster_tmp]
  398.     call  get_FAT               ; get next cluster
  399.     cmp   eax,2                 ; incorrect fat chain?
  400.     jb    adr_not_found         ; yes
  401.     cmp   eax,[fatRESERVED]     ; is it end of directory?
  402.     jb    adr_new_cluster       ; no. analyse it
  403.  
  404.   adr_not_found:
  405.     pop   edi edi esi edx ecx   ; first edi will remove ebx
  406.     stc                         ; file not found
  407.     ret
  408.  
  409.   adr_found:
  410.     pop   edi edi esi edx ecx   ; first edi will remove ebx
  411.     clc                         ; file found
  412.     ret
  413.  
  414.  
  415. analyze_directory_to_write:
  416. ;-----------------------------------------------------------
  417. ; input  : EAX = first cluster of the directory
  418. ; output : IF CARRY=0 EAX = sector where the empty pos is found
  419. ;                     EBX = pointer in buffer
  420. ;                     [buffer .. buffer+511]
  421. ;                     ECX,EDX,ESI,EDI not changed
  422. ;          IF CARRY=1 disk full or fat corrupted
  423. ; Note   : if cluster=0 it's changed to read rootdir
  424. ;-----------------------------------------------------------
  425.     push  ecx edx edi
  426.  
  427.   adw_new_cluster:
  428.     mov   [cluster_tmp],eax
  429.     mov   [fat16_root],0
  430.     cmp   eax,[LAST_CLUSTER]
  431.     ja    adw_not_found         ; too big cluster number, something is wrong
  432.     cmp   eax,2
  433.     jnb   adw_data_cluster
  434.  
  435.     mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
  436.     cmp   [fat_type],16
  437.     jne   adw_data_cluster
  438.     mov   eax,[ROOT_START]
  439.     mov   edx,[ROOT_SECTORS]
  440.     mov   [fat16_root],1        ; flag for fat16 rootdir
  441.     jmp   adw_new_sector
  442.  
  443.   adw_data_cluster:
  444.     sub   eax,2
  445.     mov   edx,[SECTORS_PER_CLUSTER]
  446.     imul  eax,edx
  447.     add   eax,[DATA_START]
  448.  
  449.   adw_new_sector:
  450.     mov   ebx,buffer
  451.     call  hd_read
  452.     mov   ecx,512/32            ; count of dir entrys per sector = 16
  453.  
  454.   adw_analyze:
  455.     cmp   byte [ebx],0x00       ; is free entry?
  456.     je    adw_found             ; yes
  457.     cmp   byte [ebx],0xe5       ; is deleted entry?
  458.     je    adw_found             ; yes
  459.     add   ebx,32                ; position of next dir entry
  460.     dec   ecx
  461.     jnz   adw_analyze
  462.  
  463.     inc   eax                   ; next sector
  464.     dec   edx
  465.     jne   adw_new_sector
  466.     cmp   [fat16_root],1        ; end of fat16 rootdir
  467.     je    adw_not_found
  468.  
  469.     mov   eax,[cluster_tmp]
  470.     call  get_FAT               ; get next cluster
  471.     cmp   eax,2                 ; incorrect fat chain?
  472.     jb    adw_not_found         ; yes
  473.     cmp   eax,[fatRESERVED]     ; is it end of directory?
  474.     jb    adw_new_cluster       ; no. analyse it
  475.  
  476.     mov   eax,2                 ; this block of code add a new cluster
  477.     call  get_free_FAT          ; for the directory because the directory
  478.     jc    adw_not_found         ; is full
  479.  
  480.     mov   edx,[fatEND]          ; new end for directory
  481.     call  set_FAT
  482.  
  483.     push  eax                   ; save new cluster
  484.     mov   edx,eax
  485.     mov   eax,[cluster_tmp]     ; change last cluster to point new cluster
  486.     mov   [f_del],1
  487.     call  set_FAT
  488.     mov   [f_del],0
  489.  
  490.     mov   ecx,-1                ; remove 1 cluster from free disk space
  491.     call  add_disk_free_space
  492.  
  493.     mov   ecx,512/4
  494.     xor   eax,eax
  495.     mov   edi,buffer
  496.     cld
  497.     rep   stosd                 ; clear new directory cluster
  498.     pop   eax
  499.  
  500.     sub   eax,2
  501.     mov   ecx,[SECTORS_PER_CLUSTER]
  502.     imul  eax,ecx
  503.     add   eax,[DATA_START]
  504.     mov   ebx,buffer
  505.     push  eax                   ; save sector number
  506.  
  507.   adw_set_empty_directory:
  508.     call  hd_write
  509.     inc   eax                   ; next sector
  510.     dec   ecx
  511.     jnz   adw_set_empty_directory
  512.  
  513.     pop   eax
  514.  
  515.   adw_found:
  516.     pop   edi edx ecx
  517.     clc                         ; free space found
  518.     ret
  519.  
  520.   adw_not_found:
  521.     pop   edi edx ecx
  522.     stc                         ; free space not found
  523.     ret
  524.  
  525.  
  526. get_data_cluster:
  527. ;-----------------------------------------------------------
  528. ; input  : EAX = cluster
  529. ;          EBX = pointer to buffer
  530. ;          EDX = # blocks to read in buffer
  531. ;          ESI = # blocks to skip over
  532. ; output : if CARRY=0 ok EBX/EDX/ESI updated
  533. ;          if CARRY=1 cluster out of range
  534. ; Note   : if cluster=0 it's changed to read rootdir
  535. ;-----------------------------------------------------------
  536.     push  eax ecx
  537.  
  538.     mov   [fat16_root],0
  539.     cmp   eax,[LAST_CLUSTER]
  540.     ja    gdc_error             ; too big cluster number, something is wrong
  541.     cmp   eax,2
  542.     jnb   gdc_cluster
  543.  
  544.     mov   eax,[ROOT_CLUSTER]    ; if cluster < 2 then read rootdir
  545.     cmp   [fat_type],16
  546.     jne   gdc_cluster
  547.     mov   eax,[ROOT_START]
  548.     mov   ecx,[ROOT_SECTORS]    ; Note: not cluster size
  549.     mov   [fat16_root],1        ; flag for fat16 rootdir
  550.     jmp   gdc_read
  551.  
  552.   gdc_cluster:
  553.     sub   eax,2
  554.     mov   ecx,[SECTORS_PER_CLUSTER]
  555.     imul  eax,ecx
  556.     add   eax,[DATA_START]
  557.  
  558.   gdc_read:
  559.     test  esi,esi               ; first wanted block
  560.     je    gdcl1                 ; yes, skip count is 0
  561.     dec   esi
  562.     jmp   gdcl2
  563.  
  564.   gdcl1:
  565.     call  hd_read
  566.     add   ebx,512               ; update pointer
  567.     dec   edx
  568.  
  569.   gdcl2:
  570.     test  edx,edx               ; is all read?
  571.     je    out_of_read
  572.  
  573.     inc   eax                   ; next sector
  574.     dec   ecx
  575.     jnz   gdc_read
  576.  
  577.   out_of_read:
  578.     pop   ecx eax
  579.     clc
  580.     ret
  581.  
  582.   gdc_error:
  583.     pop   ecx eax
  584.     stc
  585.     ret
  586.  
  587.  
  588. set_data_cluster:
  589. ;-----------------------------------------------------------
  590. ; input  : EAX = cluster
  591. ;          EBX = pointer to buffer
  592. ; output : if CARRY=0 ok
  593. ;          if CARRY=1 cluster out of range
  594. ;-----------------------------------------------------------
  595.     push  eax ebx edx
  596.  
  597.     cmp   eax,[LAST_CLUSTER]
  598.     ja    sdc_error             ; too big cluster number, something is wrong
  599.     sub   eax,2
  600.     jb    sdc_error             ; don't allow rootdir write
  601.  
  602.     mov   edx,[SECTORS_PER_CLUSTER]
  603.     imul  eax,edx
  604.     add   eax,[DATA_START]
  605.  
  606.   sdc_write:
  607.     call  hd_write
  608.     add   ebx,512               ; update pointer
  609.     inc   eax
  610.     dec   edx
  611.     jnz   sdc_write
  612.     pop   edx ebx eax
  613.     clc
  614.     ret
  615.  
  616.   sdc_error:
  617.     pop   edx ebx eax
  618.     stc
  619.     ret
  620.  
  621.  
  622. get_cluster_of_a_path:
  623. ;---------------------------------------------------------
  624. ; input  : EBX = pointer to a path string
  625. ;          (example: the path "/files/data/document" become
  626. ;                             "files......data.......document...0"
  627. ;          '.' = space char
  628. ;          '0' = char(0) (ASCII=0) !!! )
  629. ; output : if (CARRY=1) -> ERROR in the PATH
  630. ;          if (CARRY=0) -> EAX=cluster
  631. ;---------------------------------------------------------
  632.     push  ebx edx
  633.  
  634.     mov   eax,[ROOT_CLUSTER]
  635.     mov   edx,ebx
  636.  
  637. search_end_of_path:
  638.     cmp   byte [edx],0
  639.     je    found_end_of_path
  640.  
  641.     inc   edx ; '/'
  642.     mov   ebx,edx
  643.     call  analyze_directory
  644.     jc    directory_not_found
  645.  
  646.     mov   eax,[ebx+20-2]        ; read the HIGH 16bit cluster field
  647.     mov   ax,[ebx+26]           ; read the LOW 16bit cluster field
  648.     and   eax,[fatMASK]
  649.     add   edx,11                ; 8+3 (name+extension)
  650.     jmp   search_end_of_path
  651.  
  652. found_end_of_path:
  653.     pop   edx ebx
  654.     clc                         ; no errors
  655.     ret
  656.  
  657. directory_not_found:
  658.     pop   edx ebx
  659.     stc                         ; errors occour
  660.     ret
  661.  
  662.  
  663. bcd2bin:
  664. ;----------------------------------
  665. ; input  : AL=BCD number (eg. 0x11)
  666. ; output : AH=0
  667. ;          AL=decimal number (eg. 11)
  668. ;----------------------------------
  669.     xor   ah,ah
  670.     shl   ax,4
  671.     shr   al,4
  672.     aad
  673.     ret
  674.  
  675.  
  676. get_date_for_file:
  677. ;-----------------------------------------------------
  678. ; Get date from CMOS and pack day,month,year in AX
  679. ; DATE   bits  0..4   : day of month 0..31
  680. ;              5..8   : month of year 1..12
  681. ;              9..15  : count of years from 1980
  682. ;-----------------------------------------------------
  683.     mov   al,0x7        ;day
  684.     out   0x70,al
  685.     in    al,0x71
  686.     call  bcd2bin
  687.     ror   eax,5
  688.  
  689.     mov   al,0x8        ;month
  690.     out   0x70,al
  691.     in    al,0x71
  692.     call  bcd2bin
  693.     ror   eax,4
  694.  
  695.     mov   al,0x9        ;year
  696.     out   0x70,al
  697.     in    al,0x71
  698.     call  bcd2bin
  699.     add   ax,20         ;because CMOS return only the two last
  700.                         ;digit (eg. 2000 -> 00 , 2001 -> 01) and we
  701.     rol   eax,9         ;need the difference with 1980 (eg. 2001-1980)
  702.     ret
  703.  
  704.  
  705. get_time_for_file:
  706. ;-----------------------------------------------------
  707. ; Get time from CMOS and pack hour,minute,second in AX
  708. ; TIME   bits  0..4   : second (the low bit is lost)
  709. ;              5..10  : minute 0..59
  710. ;              11..15 : hour 0..23
  711. ;-----------------------------------------------------
  712.     mov   al,0x0        ;second
  713.     out   0x70,al
  714.     in    al,0x71
  715.     call  bcd2bin
  716.     ror   eax,6
  717.  
  718.     mov   al,0x2        ;minute
  719.     out   0x70,al
  720.     in    al,0x71
  721.     call  bcd2bin
  722.     ror   eax,6
  723.  
  724.     mov   al,0x4        ;hour
  725.     out   0x70,al
  726.     in    al,0x71
  727.     call  bcd2bin
  728.     rol   eax,11
  729.     ret
  730.  
  731.  
  732. set_current_time_for_entry:
  733. ;-----------------------------------------------------
  734. ; Set current time/date for file entry
  735. ; input  : ebx = file entry pointer
  736. ;-----------------------------------------------------
  737.     push  eax
  738.     call  get_time_for_file     ; update files date/time
  739.     mov   [ebx+22],ax
  740.     call  get_date_for_file
  741.     mov   [ebx+24],ax
  742.     pop   eax
  743.     ret
  744.  
  745.  
  746. makedir:
  747. ;-----------------------------------------------------
  748. ; input  : eax = directory name
  749. ;          edx = path
  750. ; output : eax = 0 - ok
  751. ;                3 - unknown FS
  752. ;                5 - file not found
  753. ;                8 - disk full
  754. ;               10 - access denied
  755. ; Note   : can only make one directory at time
  756. ;-----------------------------------------------------
  757.     cmp   [fat_type],0
  758.     jnz   make_dir_fat_ok
  759.     mov   eax,ERROR_UNKNOWN_FS
  760.     ret
  761.  
  762.   make_dir_fat_ok:
  763. ;    call  reserve_hd1
  764.  
  765.     pushad
  766.  
  767.     mov   ebx,edx
  768.     call  get_cluster_of_a_path
  769.     jnc   make_dir_found_path
  770.  
  771.   make_dir_path_not_found:
  772.     popad
  773.     call  update_disk           ; write all of cache and fat to hd
  774.     mov   [hd1_status],0
  775.     mov   eax,ERROR_FILE_NOT_FOUND
  776.     ret
  777.  
  778.   make_dir_disk_full:
  779.     popad
  780.     call  update_disk           ; write all of cache and fat to hd
  781.     mov   [hd1_status],0
  782.     mov   eax,ERROR_DISK_FULL
  783.     ret
  784.  
  785.   make_dir_already_exist:
  786.     mov   eax,[cluster]         ; directory cluster
  787.     xor   edx,edx               ; free
  788.     mov   [f_del],1
  789.     call  set_FAT
  790.     mov   [f_del],0
  791.  
  792.     popad
  793.     call  update_disk           ; write all of cache and fat to hd
  794.     mov   [hd1_status],0
  795.     mov   eax,ERROR_ACCESS_DENIED
  796.     ret
  797.  
  798.   make_dir_found_path:
  799.     cmp   eax,[ROOT_CLUSTER]
  800.     jnz   make_dir_not_root
  801.     xor   eax,eax
  802.  
  803.   make_dir_not_root:
  804.     mov   ecx,eax               ; directorys start cluster
  805.     mov   word [NewDirEntry2+26],cx ; 16 bits low of cluster
  806.     shr   ecx,16
  807.     mov   word [NewDirEntry2+20],cx ; 16 bits high of cluster (=0 fat16)
  808.  
  809.     push  eax                   ; save parent directory cluster
  810.     mov   eax,2
  811.     call  get_free_FAT
  812.     mov   [cluster],eax         ; first free cluster
  813.     pop   eax
  814.     jc    make_dir_disk_full
  815.  
  816.     push  eax
  817.     mov   eax,[cluster]         ; directory cluster
  818.     mov   edx,[fatEND]          ; end for directory
  819.     call  set_FAT
  820.     pop   eax
  821.  
  822.     mov   ebx,PUSHAD_EAX        ; dir name
  823.     push  eax
  824.     call  analyze_directory     ; check if directory already exist
  825.     pop   eax
  826.     jnc   make_dir_already_exist ; need to free allocated cluster!
  827.  
  828.     call  analyze_directory_to_write
  829.     jc    make_dir_already_exist ; need to free allocated cluster!
  830.  
  831.     mov   esi,PUSHAD_EAX        ; dir name
  832.     mov   edi,ebx               ; pointer in buffer
  833.     mov   ecx,11
  834.     cld
  835.     rep   movsb
  836.  
  837.     mov   dword [ebx+28],0      ; dir size is always 0
  838.     mov   ecx,[cluster]
  839.     mov   [ebx+26],cx           ; 16 bits low of cluster
  840.     mov   word [NewDirEntry1+26],cx
  841.     shr   ecx,16
  842.     mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
  843.     mov   word [NewDirEntry1+20],cx
  844.     mov   byte [ebx+11],0x10    ; attribute = directory
  845.  
  846.     call  set_current_time_for_entry
  847.     mov   ecx,[ebx+22]
  848.     mov   dword [NewDirEntry1+22],ecx
  849.     mov   dword [NewDirEntry2+22],ecx
  850.  
  851.     mov   ebx,buffer            ; save the directory name,length,cluster
  852.     call  hd_write
  853.  
  854.     mov   ecx,512/4
  855.     xor   eax,eax
  856.     mov   edi,buffer
  857.     cld
  858.     rep   stosd                 ; clear new directory cluster
  859.  
  860.     mov   eax,[cluster]         ; new directory cluster
  861.     sub   eax,2
  862.     mov   edx,[SECTORS_PER_CLUSTER]
  863.     imul  eax,edx
  864.     add   eax,[DATA_START]
  865.     mov   ebx,buffer
  866.     add   eax,edx               ; start from last sector
  867.  
  868.   dir_set_empty_directory:
  869.     dec   eax                   ; next sector
  870.     cmp   edx,1                 ; is first directory sector?
  871.     jnz   not_first_sector      ; no. write empty sector
  872.     mov   esi,NewDirEntry1
  873.     mov   edi,buffer
  874.     mov   ecx,64/4
  875.     cld
  876.     rep   movsd                 ; copy 2 first directory entrys "." and ".."
  877.  
  878.   not_first_sector:
  879.     call  hd_write
  880.     dec   edx
  881.     jnz   dir_set_empty_directory
  882.  
  883.     mov   ecx,-1                ; remove 1 cluster from free disk space
  884.     call  add_disk_free_space
  885.  
  886.     popad
  887.     call  update_disk           ; write all of cache and fat to hd
  888.     mov   [hd1_status],0
  889.     xor   eax,eax
  890.     ret
  891.  
  892.  
  893. removedir:
  894. ;-----------------------------------------------------
  895. ; input  : eax = file/directory name
  896. ;          edx = path
  897. ; output : eax = 0 - ok
  898. ;                3 - unknown FS
  899. ;                5 - file not found
  900. ;               10 - access denied
  901. ;-----------------------------------------------------
  902.     cmp   [fat_type],0
  903.     jnz   remove_dir_fat_ok
  904.     mov   eax,ERROR_UNKNOWN_FS
  905.     ret
  906.  
  907.   remove_dir_fat_ok:
  908. ;    call  reserve_hd1
  909.  
  910.     push  edi
  911.     mov   edi,1                 ; allow directory remove
  912.     call  file_delete
  913.     pop   edi
  914.  
  915.     call  update_disk           ; write all of cache and fat to hd
  916.     mov   [hd1_status],0
  917.     ret
  918.  
  919.  
  920. add_disk_free_space:
  921. ;-----------------------------------------------------
  922. ; input  : ecx = cluster count
  923. ; Note   : negative = remove clusters from free space
  924. ;          positive = add clusters to free space
  925. ;-----------------------------------------------------
  926.     test  ecx,ecx               ; no change
  927.     je    add_dfs_no
  928.     cmp   [fat_type],32         ; free disk space only used by fat32
  929.     jne   add_dfs_no
  930.  
  931.     push  eax ebx
  932.     mov   eax,[ADR_FSINFO]
  933.     mov   ebx,buffer
  934.     call  hd_read
  935.     cmp   dword [ebx+0x1fc],0xaa550000 ; check sector id
  936.     jne   add_not_fs
  937.  
  938.     add   [ebx+0x1e8],ecx
  939.     call  hd_write
  940.  
  941.   add_not_fs:
  942.     pop   ebx eax
  943.  
  944.   add_dfs_no:
  945.     ret
  946.  
  947.  
  948. file_append:
  949. ;-----------------------------------------------------
  950. ; input  : eax = file name
  951. ;          edx = path
  952. ;          ecx = pointer to buffer
  953. ;          ebx = bytes to write (0 = truncate file)
  954. ;          esi = start position (-1 = end of file)
  955. ; output : eax = 0 - ok
  956. ;                3 - unknown FS
  957. ;                5 - file not found
  958. ;                6 - end of file
  959. ;                8 - disk full
  960. ;                9 - fat table corrupted
  961. ;               10 - access denied
  962. ;          ebx = bytes written
  963. ;-----------------------------------------------------
  964.     cmp   [fat_type],0
  965.     jnz   append_fat_ok
  966.     mov   eax,ERROR_UNKNOWN_FS
  967.     ret
  968.  
  969.   append_fat_ok:
  970. ;    call  reserve_hd1
  971.  
  972.     pushad
  973.  
  974.     mov   ebx,edx
  975.     call  get_cluster_of_a_path
  976.     jc    append_not_found
  977.  
  978.     mov   ebx,PUSHAD_EAX        ; file name
  979.     call  analyze_directory
  980.     jc    append_not_found
  981.  
  982.     mov   [sector_tmp],eax
  983.     mov   [entry_pos],ebx
  984.  
  985.     test  byte [ebx+11],0x10    ; is it directory?
  986.     jnz   append_access         ; yes
  987.  
  988.     mov   ecx,[ebx+28]          ; file size
  989.     mov   edi,PUSHAD_ESI        ; write position
  990.     cmp   edi,-1                ; -1 = eof
  991.     jnz   append_inside_file
  992.     mov   edi,ecx               ; file size
  993.  
  994.   append_inside_file:
  995.     cmp   edi,ecx               ; start above old file size?
  996.     ja    append_eof            ; yes
  997.  
  998.     mov   [old_filesize],ecx
  999.     mov   [new_filepos],edi
  1000.  
  1001.     mov   ecx,PUSHAD_EBX        ; bytes to write
  1002.     test  ecx,ecx               ; truncate?
  1003.     jz    append_truncate       ; yes
  1004.  
  1005.     mov   [bytes2write],ecx     ; bytes to write
  1006.     mov   esi,PUSHAD_ECX        ; pointer to buffer
  1007.     mov   eax,[ebx+20-2]        ; FAT entry
  1008.     mov   ax,[ebx+26]
  1009.     and   eax,[fatMASK]
  1010.     jnz   append_find_pos       ; first cluster <> 0
  1011.  
  1012.     mov   eax,2
  1013.     call  get_free_FAT
  1014.     jc    append_disk_full
  1015.     mov   ecx,eax               ; set files first cluster
  1016.     mov   [ebx+26],cx           ; 16 bits low of cluster
  1017.     shr   ecx,16
  1018.     mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
  1019.     mov   edx,[fatEND]          ; new end for cluster chain
  1020.     call  set_FAT
  1021.  
  1022.     push  eax                   ; save first cluster
  1023.     mov   eax,[sector_tmp]
  1024.     mov   ebx,buffer
  1025.     call  hd_write              ; write new file entry back to disk
  1026.     pop   eax
  1027.  
  1028.   append_remove_free:
  1029.     mov   ecx,-1                ; remove 1 cluster from free disk space
  1030.     call  add_disk_free_space   ; Note: uses buffer
  1031.  
  1032.   append_found_cluster:
  1033.     mov   [cluster],eax
  1034.     sub   eax,2
  1035.     mov   ecx,[SECTORS_PER_CLUSTER]
  1036.     imul  eax,ecx
  1037.     add   eax,[DATA_START]
  1038.     xor   edi,edi
  1039.  
  1040.   append_new_sector:
  1041.     push  ecx
  1042.     mov   ecx,[bytes2write]     ; bytes left in buffer
  1043.     mov   ebx,512
  1044.     sub   ebx,edi               ; bytes left in sector
  1045.     cmp   ecx,ebx
  1046.     jb    append_bytes_ok
  1047.     mov   ecx,ebx
  1048.  
  1049.   append_bytes_ok:
  1050.     cmp   ecx,512               ; overwrite full sector?
  1051.     jz    append_full_sector    ; yes
  1052.     mov   ebx,buffer            ; overwrite part of sector
  1053.     call  hd_read               ; read old sector
  1054.  
  1055.   append_full_sector:
  1056.     sub   [bytes2write],ecx
  1057.     add   [new_filepos],ecx
  1058.     add   edi,buffer
  1059.     cld
  1060.     rep   movsb
  1061.     pop   ecx
  1062.  
  1063.     mov   ebx,buffer
  1064.     call  hd_write
  1065.     cmp   [bytes2write],0       ; is all done?
  1066.     jz    append_done
  1067.     xor   edi,edi
  1068.     inc   eax
  1069.     dec   ecx
  1070.     jnz   append_new_sector
  1071.  
  1072.     mov   eax,[cluster]
  1073.     call  get_FAT
  1074.     cmp   eax,2
  1075.     jb    append_fat
  1076.     cmp   eax,[LAST_CLUSTER]
  1077.     jbe   append_found_cluster
  1078.  
  1079.   append_alloc_cluster:
  1080.     mov   eax,2                 ; ToDo: use temp array to keep track
  1081.     call  get_free_FAT          ;       of last free cluster
  1082.     jc    append_disk_full
  1083.     push  eax                   ; save new cluster
  1084.     mov   edx,[fatEND]          ; new end for cluster chain
  1085.     call  set_FAT
  1086.     mov   edx,eax
  1087.     mov   eax,[cluster]
  1088.     mov   [f_del],1
  1089.     call  set_FAT               ; update previous cluster
  1090.     mov   [f_del],0
  1091.     pop   eax
  1092.     jmp   append_remove_free
  1093.  
  1094.   append_find_pos:
  1095.     call  find_filepos
  1096.     mov   [cluster],ebx
  1097.     jnc   append_new_sector
  1098.     test  edi,edi
  1099.     jz    append_alloc_cluster
  1100.  
  1101.   append_fat:
  1102.     mov   eax,ERROR_FAT_TABLE
  1103.     jmp   append_ret_code
  1104.  
  1105.   append_disk_full:
  1106.     mov   eax,ERROR_DISK_FULL
  1107.     jmp   append_ret_code
  1108.  
  1109.   append_done:
  1110.     xor   eax,eax
  1111.  
  1112.   append_ret_code:
  1113.     mov   PUSHAD_EAX,eax        ; return code
  1114.  
  1115.     mov   eax,[sector_tmp]      ; update directory entry
  1116.     mov   ebx,buffer
  1117.     call  hd_read
  1118.     mov   ebx,[entry_pos]
  1119.     mov   ecx,[new_filepos]
  1120.     cmp   ecx,[old_filesize]    ; is file pos above old size?
  1121.     jbe   append_size_ok        ; no
  1122.     mov   [ebx+28],ecx          ; new file size
  1123.  
  1124.   append_size_ok:
  1125.     call  set_current_time_for_entry
  1126.     mov   ebx,buffer
  1127.     call  hd_write              ; write new file entry back to disk
  1128.  
  1129.     sub   ecx,PUSHAD_ESI        ; start position
  1130.     mov   PUSHAD_EBX,ecx        ; bytes written
  1131.     popad
  1132.     call  update_disk           ; write all of cache and fat to hd
  1133.     mov   [hd1_status],0
  1134.     ret
  1135.  
  1136.   append_eof:
  1137.     popad
  1138.     mov   [hd1_status],0
  1139.     xor   ebx,ebx
  1140.     mov   eax,ERROR_END_OF_FILE
  1141.     ret
  1142.  
  1143.   append_not_found:
  1144.     popad
  1145.     mov   [hd1_status],0
  1146.     xor   ebx,ebx
  1147.     mov   eax,ERROR_FILE_NOT_FOUND
  1148.     ret
  1149.  
  1150.   append_access:
  1151.     popad
  1152.     mov   [hd1_status],0
  1153.     xor   ebx,ebx
  1154.     mov   eax,ERROR_ACCESS_DENIED
  1155.     ret
  1156.  
  1157.   append_truncate:
  1158.     mov   edx,[ebx+20-2]        ; FAT entry
  1159.     mov   dx,[ebx+26]
  1160.     and   edx,[fatMASK]
  1161.     mov   [ebx+28],edi          ; set new file size
  1162.     test  edi,edi               ; 0 length file?
  1163.     jnz   truncate_save_size    ; no
  1164.     mov   [ebx+20],di           ; FAT entry = 0
  1165.     mov   [ebx+26],di
  1166.  
  1167.   truncate_save_size:
  1168.     call  set_current_time_for_entry
  1169.     mov   ebx,buffer
  1170.     call  hd_write
  1171.     mov   eax,edx               ; first cluster
  1172.     test  edi,edi               ; 0 length file?
  1173.     jz    truncate_clear_chain
  1174.  
  1175.     imul  esi,[SECTORS_PER_CLUSTER],512 ; esi = cluster size in bytes
  1176.  
  1177.   truncate_new_cluster:
  1178.     cmp   eax,2                 ; incorrect fat chain?
  1179.     jb    truncate_eof          ; yes
  1180.     cmp   eax,[fatRESERVED]     ; is it end of file?
  1181.     jnb   truncate_eof          ; yes
  1182.     sub   edi,esi
  1183.     jbe   truncate_pos_found
  1184.     call  get_FAT               ; get next cluster
  1185.     jmp   truncate_new_cluster
  1186.  
  1187.   truncate_pos_found:
  1188.     mov   edx,[fatEND]          ; new end for cluster chain
  1189.     mov   [f_del],1
  1190.     call  set_FAT
  1191.     mov   [f_del],0
  1192.     mov   eax,edx               ; clear rest of chain
  1193.  
  1194.   truncate_clear_chain:
  1195.     call  clear_cluster_chain
  1196.  
  1197.   truncate_eof:
  1198.     popad
  1199.     call  update_disk           ; write all of cache and fat to hd
  1200.     mov   [hd1_status],0
  1201.     xor   ebx,ebx
  1202.     xor   eax,eax
  1203.     ret
  1204.  
  1205.  
  1206. find_filepos:
  1207. ;-----------------------------------------------------
  1208. ; input  : eax = first cluster
  1209. ;          edi = bytes to skip over (start position)
  1210. ; output : if CARRY=0 file position found
  1211. ;          if CARRY=1 end of file found
  1212. ;          eax = current file sector
  1213. ;          ebx = last cluster
  1214. ;          ecx = sector count in last cluster
  1215. ;          edi = bytes to skip over (sector position)
  1216. ;-----------------------------------------------------
  1217.     push  esi
  1218.     mov   ecx,[SECTORS_PER_CLUSTER]
  1219.     imul  esi,ecx,512           ; esi = cluster size in bytes
  1220.     mov   ebx,eax
  1221.  
  1222.   filepos_new_cluster:
  1223.     cmp   eax,2                 ; incorrect fat chain?
  1224.     jb    filepos_eof           ; yes
  1225.     cmp   eax,[fatRESERVED]     ; is it end of file?
  1226.     jnb   filepos_eof           ; yes
  1227.  
  1228.     mov   ebx,eax
  1229.     cmp   edi,esi               ; skip over full cluster?
  1230.     jb    filepos_cluster_ok    ; no
  1231.  
  1232.     sub   edi,esi
  1233.     call  get_FAT               ; get next cluster
  1234.     jmp   filepos_new_cluster
  1235.  
  1236.   filepos_cluster_ok:
  1237.     sub   eax,2
  1238.     imul  eax,ecx
  1239.     add   eax,[DATA_START]
  1240.  
  1241.   filepos_new_sector:
  1242.     cmp   edi,512               ; skip over full sector?
  1243.     jb    filepos_sector_ok     ; no
  1244.     sub   edi,512
  1245.     inc   eax
  1246.     dec   ecx
  1247.     jnz   filepos_new_sector
  1248.  
  1249.   filepos_eof:
  1250.     pop   esi
  1251.     stc
  1252.     ret
  1253.  
  1254.   filepos_sector_ok:
  1255.     pop   esi
  1256.     clc
  1257.     ret
  1258.  
  1259.  
  1260. file_write:
  1261. ;--------------------------------------------------------------------------
  1262. ;   INPUT : user-reg  register-in-this  meaning      symbol-in-this-routine
  1263. ;
  1264. ;            EAX        EDI            system call to write    /
  1265. ;            EBX        EAX   (PAR0)   pointer to file-name    PAR0
  1266. ;            EDX        ECX   (PAR1)   pointer to buffer       PAR1
  1267. ;            ECX        EBX   (PAR2)   file size               PAR2
  1268. ;            ESI        EDX   (PAR3)   pointer to path         PAR3
  1269. ;
  1270. ; output : eax = 0 - ok
  1271. ;                3 - unknown FS
  1272. ;                5 - file not found
  1273. ;                8 - disk full
  1274. ;               10 - access denied
  1275. ;--------------------------------------------------------------------------
  1276.     cmp   [fat_type],0
  1277.     jnz   fat_ok_for_writing
  1278.     mov   eax,ERROR_UNKNOWN_FS
  1279.     ret
  1280.  
  1281.   fat_ok_for_writing:
  1282. ;    call  reserve_hd1
  1283.  
  1284.     pushad
  1285.  
  1286.     xor   edi,edi               ; don't allow directory remove
  1287.     call  file_delete           ; try to delete the file first
  1288.     test  eax,eax
  1289.     jz    old_deleted           ; deleted ok
  1290.     cmp   eax,ERROR_FILE_NOT_FOUND
  1291.     jnz   exit_write_access     ; it exist but can't delete
  1292.  
  1293.   old_deleted:
  1294.     mov   ebx,PUSHAD_EDX
  1295.     call  get_cluster_of_a_path
  1296.     jnc   found_directory_for_writing
  1297.  
  1298.   exit_writing_with_error:
  1299.     popad
  1300.     call  update_disk           ; write all of cache and fat to hd
  1301.     mov   [hd1_status],0
  1302.     mov   eax,ERROR_FILE_NOT_FOUND
  1303.     ret
  1304.  
  1305.   exit_writing_disk_full_clear:
  1306.     mov   eax,[sector_tmp]
  1307.     mov   ebx,buffer
  1308.     call  hd_read               ; read directory sector
  1309.     mov   edx,[entry_pos]
  1310.     mov   byte [edx],0xe5       ; mark as deleted
  1311.     call  hd_write
  1312.     mov   eax,[edx+20-2]        ; FAT entry
  1313.     mov   ax,[edx+26]
  1314.     and   eax,[fatMASK]
  1315.     call  clear_cluster_chain
  1316.  
  1317.   exit_writing_disk_full:
  1318.     popad
  1319.     call  update_disk           ; write all of cache and fat to hd
  1320.     mov   [hd1_status],0
  1321.     mov   eax,ERROR_DISK_FULL
  1322.     ret
  1323.  
  1324.   exit_write_access:
  1325.     popad
  1326.     call  update_disk           ; write all of cache and fat to hd
  1327.     mov   [hd1_status],0
  1328.     mov   eax,ERROR_ACCESS_DENIED
  1329.     ret
  1330.  
  1331. found_directory_for_writing:
  1332.     call  analyze_directory_to_write
  1333.     jc    exit_writing_disk_full
  1334.  
  1335.     mov   [sector_tmp],eax
  1336.     mov   [entry_pos],ebx
  1337.     push  eax                   ; save directory sector
  1338.     mov   eax,2
  1339.     call  get_free_FAT
  1340.     mov   [cluster],eax         ; first free cluster
  1341.     pop   eax
  1342.     jc    exit_writing_disk_full
  1343.  
  1344.     mov   esi,PUSHAD_EAX        ; file name
  1345.     mov   edi,ebx               ; pointer in buffer
  1346.     mov   ecx,11
  1347.     cld
  1348.     rep   movsb
  1349.  
  1350.     mov   esi,PUSHAD_EBX        ; file size (bytes left)
  1351.     mov   [ebx+28],esi          ; file size
  1352.     mov   ecx,[cluster]
  1353.     mov   [ebx+26],cx           ; 16 bits low of cluster
  1354.     shr   ecx,16
  1355.     mov   [ebx+20],cx           ; 16 bits high of cluster (=0 fat16)
  1356.     mov   byte [ebx+11],0x20    ; attribute = archive
  1357.  
  1358.     call  set_current_time_for_entry
  1359.  
  1360.     mov   ebx,buffer            ; save the directory name,length,cluster
  1361.     call  hd_write
  1362.  
  1363.     imul  edi,[SECTORS_PER_CLUSTER],512 ; edi = cluster size in bytes
  1364.     xor   ecx,ecx               ; cluster count
  1365.     mov   ebx,PUSHAD_ECX        ; ebx = buffer
  1366.  
  1367. hd_new_block_write:
  1368.  
  1369.     mov   eax,[cluster]         ; eax = block
  1370.     call  set_data_cluster
  1371.  
  1372.     sub   esi,edi               ; sub wrote bytes
  1373.     jbe   file_saved_OK         ; end if all done
  1374.     add   ebx,edi               ; update buffer position
  1375.  
  1376.     inc   eax
  1377.     call  get_free_FAT          ; next free in FAT
  1378.     jc    exit_writing_disk_full_clear
  1379.  
  1380.     mov   edx,eax
  1381.     xchg  eax,[cluster]         ; get old cluster and save new cluster
  1382.     call  set_FAT               ; add it in cluster chain
  1383.     dec   ecx                   ; update cluster count
  1384.     jmp   hd_new_block_write
  1385.  
  1386. file_saved_OK:
  1387.  
  1388.     mov   edx,[fatEND]          ; new end for cluster chain
  1389.     call  set_FAT
  1390.     dec   ecx                   ; update cluster count
  1391.  
  1392.     call  add_disk_free_space   ; remove clusters from free disk space
  1393.  
  1394.     popad
  1395.     call  update_disk           ; write all of cache and fat to hd
  1396.     mov   [hd1_status],0
  1397.     xor   eax,eax
  1398.     ret
  1399.  
  1400.  
  1401. file_read:
  1402. ;--------------------------------------------------------------------------
  1403. ;   INPUT :  user-register register-in-this  meaning         symbol-in-this
  1404. ;
  1405. ;            EAX           EDI               system call to write   /
  1406. ;            EBX           EAX   (PAR0)      pointer to file-name   PAR0
  1407. ;            EDX           ECX   (PAR1)      pointer to buffer      PAR1
  1408. ;            ECX           EBX   (PAR2)   vt file blocks to read    PAR2
  1409. ;            ESI           EDX   (PAR3)      pointer to path        PAR3
  1410. ;            EDI           ESI            vt first 512 block to read
  1411. ;                          EDI               if 0 - read root
  1412. ;
  1413. ; output : eax = 0 - ok
  1414. ;                3 - unknown FS
  1415. ;                5 - file not found
  1416. ;                6 - end of file
  1417. ;                9 - fat table corrupted
  1418. ;          ebx = size of file/directory
  1419. ;--------------------------------------------------------------------------
  1420.     cmp   [fat_type],0
  1421.     jnz   fat_ok_for_reading
  1422.     xor   ebx,ebx
  1423.     mov   eax,ERROR_UNKNOWN_FS
  1424.     mov   [hd1_status], ebx
  1425.     ret
  1426.  
  1427.   fat_ok_for_reading:
  1428. ;    call  reserve_hd1
  1429.  
  1430.     pushad
  1431.  
  1432.     mov   ebx,edx
  1433.     call  get_cluster_of_a_path
  1434.     jc    file_to_read_not_found
  1435.  
  1436.     test  edi,edi               ; read rootdir
  1437.     jne   no_read_root
  1438.  
  1439.     xor   eax,eax
  1440.     call  get_dir_size          ; return rootdir size
  1441.     mov   [file_size],eax
  1442.     mov   eax,[ROOT_CLUSTER]
  1443.     jmp   file_read_start
  1444.  
  1445.   no_read_root:
  1446.     mov   ebx,PUSHAD_EAX        ; file name
  1447.     call  analyze_directory
  1448.     jc    file_to_read_not_found
  1449.  
  1450.     mov   eax,[ebx+28]          ; file size
  1451.     test  byte [ebx+11],0x10    ; is it directory?
  1452.     jz    read_set_size         ; no
  1453.  
  1454.     mov   eax,[ebx+20-2]        ; FAT entry
  1455.     mov   ax,[ebx+26]
  1456.     and   eax,[fatMASK]
  1457.     call  get_dir_size
  1458.  
  1459.   read_set_size:
  1460.     mov   [file_size],eax
  1461.  
  1462.     mov   eax,[ebx+20-2]        ; FAT entry
  1463.     mov   ax,[ebx+26]
  1464.     and   eax,[fatMASK]
  1465.  
  1466.   file_read_start:
  1467.     mov   ebx,PUSHAD_ECX        ; pointer to buffer
  1468.     mov   edx,PUSHAD_EBX        ; file blocks to read
  1469.     mov   esi,PUSHAD_ESI        ; first 512 block to read
  1470.  
  1471.   file_read_new_cluster:
  1472.     call  get_data_cluster
  1473.     jc    file_read_eof         ; end of file or cluster out of range
  1474.  
  1475.     test  edx,edx               ; is all read?
  1476.     je    file_read_OK          ; yes
  1477.  
  1478.     call  get_FAT               ; get next cluster
  1479.     cmp   eax,[fatRESERVED]     ; end of file
  1480.     jnb   file_read_eof
  1481.     cmp   eax,2                 ; incorrect fat chain
  1482.     jnb   file_read_new_cluster
  1483.  
  1484.     popad
  1485.     mov   [hd1_status],0
  1486.     mov   ebx,[file_size]
  1487.     mov   eax,ERROR_FAT_TABLE
  1488.     ret
  1489.  
  1490.   file_read_eof:
  1491.     popad
  1492.     mov   [hd1_status],0
  1493.     mov   ebx,[file_size]
  1494.     mov   eax,ERROR_END_OF_FILE
  1495.     ret
  1496.  
  1497.   file_read_OK:
  1498.     popad
  1499.     mov   [hd1_status],0
  1500.     mov   ebx,[file_size]
  1501.     xor   eax,eax
  1502.     ret
  1503.  
  1504.   file_to_read_not_found:
  1505.     popad
  1506.     mov   [hd1_status],0
  1507.     xor   ebx,ebx
  1508.     mov   eax,ERROR_FILE_NOT_FOUND
  1509.     ret
  1510.  
  1511.  
  1512. get_dir_size:
  1513. ;-----------------------------------------------------
  1514. ; input  : eax = first cluster (0=rootdir)
  1515. ; output : eax = directory size in bytes
  1516. ;-----------------------------------------------------
  1517.     push  edx
  1518.     xor   edx,edx               ; count of directory clusters
  1519.     test  eax,eax
  1520.     jnz   dir_size_next
  1521.  
  1522.     mov   eax,[ROOT_SECTORS]
  1523.     shl   eax,9                 ; fat16 rootdir size in bytes
  1524.     cmp   [fat_type],16
  1525.     je    dir_size_ret
  1526.     mov   eax,[ROOT_CLUSTER]
  1527.  
  1528.   dir_size_next:
  1529.     cmp   eax,2                 ; incorrect fat chain
  1530.     jb    dir_size_end
  1531.     cmp   eax,[fatRESERVED]     ; end of directory
  1532.     ja    dir_size_end
  1533.     call  get_FAT               ; get next cluster
  1534.     inc   edx
  1535.     jmp   dir_size_next
  1536.  
  1537.   dir_size_end:
  1538.     imul  eax,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
  1539.     imul  eax,edx
  1540.  
  1541.   dir_size_ret:
  1542.     pop   edx
  1543.     ret
  1544.  
  1545.  
  1546. file_delete:
  1547. ;-----------------------------------------------------
  1548. ; input  : eax = file/directory name
  1549. ;          edx = path
  1550. ;          edi = 1 - allow directory remove else don't remove directory
  1551. ; output : eax = 0 - ok
  1552. ;                3 - unknown FS
  1553. ;                5 - file not found
  1554. ;               10 - access denied
  1555. ;-----------------------------------------------------
  1556.     cmp   [fat_type],0
  1557.     jnz   file_del_fat_ok
  1558.     mov   eax,ERROR_UNKNOWN_FS
  1559.     ret
  1560.  
  1561.   file_del_fat_ok:
  1562.     pushad
  1563.  
  1564.     mov   ebx,edx
  1565.     call  get_cluster_of_a_path
  1566.     jc    file_to_delete_not_found
  1567.  
  1568.     mov   ebx,PUSHAD_EAX        ; file/directory name
  1569.     call  analyze_directory
  1570.     jc    file_to_delete_not_found
  1571.  
  1572.     test  byte [ebx+11],0x10    ; is it directory?
  1573.     jz    delete_notdir         ; no. it's file
  1574.     cmp   edi,1                 ; allow directory remove
  1575.     jnz   delete_no_access      ; no
  1576.  
  1577.     push  eax                   ; save directory sector
  1578.     mov   eax,[ebx+20-2]        ; first cluster of file
  1579.     mov   ax,[ebx+26]           ; 0 length files start cluster = 0
  1580.     and   eax,[fatMASK]
  1581.     xor   ebp,ebp               ; counter for directory deepnes
  1582.     call  clear_directory
  1583.     pop   eax
  1584.     jc    delete_no_access
  1585.  
  1586.     push  ebx                   ; save directory pointer in buffer
  1587.     mov   ebx,buffer
  1588.     call  hd_read               ; read directory sector
  1589.     pop   ebx
  1590.  
  1591.   delete_notdir:
  1592.     call  delete_entry_name
  1593.     mov   eax,ecx               ; first cluster of file
  1594.     call  clear_cluster_chain
  1595.     popad
  1596.     xor   eax,eax
  1597.     ret
  1598.  
  1599.   delete_no_access:
  1600.     popad
  1601.     mov   eax,ERROR_ACCESS_DENIED
  1602.     ret
  1603.  
  1604.   file_to_delete_not_found:
  1605.     popad
  1606.     mov   eax,ERROR_FILE_NOT_FOUND
  1607.     ret
  1608.  
  1609.  
  1610. clear_cluster_chain:
  1611. ;-----------------------------------------------------
  1612. ; input  : eax = first cluster
  1613. ;-----------------------------------------------------
  1614.     push  eax ecx edx
  1615.     xor   ecx,ecx               ; cluster count
  1616.     mov   [f_del],1             ; delete on
  1617.  
  1618.   clean_new_chain:
  1619.     cmp   eax,[LAST_CLUSTER]    ; end of file
  1620.     ja    delete_OK
  1621.     cmp   eax,2                 ; unfinished fat chain or zero length file
  1622.     jb    delete_OK
  1623.     cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
  1624.     jz    delete_OK
  1625.  
  1626.     xor   edx,edx
  1627.     call  set_FAT               ; clear fat entry
  1628.     inc   ecx                   ; update cluster count
  1629.     mov   eax,edx               ; old cluster
  1630.     jmp   clean_new_chain
  1631.  
  1632.   delete_OK:
  1633.     call  add_disk_free_space   ; add clusters to free disk space
  1634.     mov   [f_del],0
  1635.     pop   edx ecx eax
  1636.     ret
  1637.  
  1638.  
  1639. clear_directory:
  1640. ;-----------------------------------------------------
  1641. ; input  : eax = directory cluster
  1642. ;          ebp = directory deepnes
  1643. ; Note   : use recursive call
  1644. ;-----------------------------------------------------
  1645.     pushad
  1646.     inc   ebp
  1647.     cmp   ebp,64                ; if over 63 directory deep
  1648.     jnb   clear_error           ; something must be wrong
  1649.  
  1650.   clear_new_cluster:
  1651.     cmp   eax,[LAST_CLUSTER]
  1652.     ja    clear_end
  1653.     cmp   eax,[ROOT_CLUSTER]    ; don't remove root cluster
  1654.     jz    clear_end
  1655.     mov   esi,eax               ; esi = current directory cluster
  1656.     sub   eax,2
  1657.     jb    clear_end
  1658.     mov   ecx,[SECTORS_PER_CLUSTER]
  1659.     imul  eax,ecx
  1660.     add   eax,[DATA_START]
  1661.  
  1662.   clear_new_sector:
  1663.     mov   edi,eax               ; edi = current directory sector
  1664.     mov   ebx,deltree_buffer
  1665.     call  hd_read
  1666.     mov   edx,512/32            ; count of dir entrys per sector = 16
  1667.  
  1668.   clear_analyze:
  1669.     mov   al,[ebx+11]           ; file attribute
  1670.     and   al,0xf
  1671.     cmp   al,0xf
  1672.     je    clear_long_filename
  1673.  
  1674.     cmp   byte [ebx],'.'        ; parent or current directory
  1675.     je    clear_next_entry
  1676.     cmp   byte [ebx],0xe5       ; deleted
  1677.     je    clear_next_entry
  1678.     cmp   byte [ebx],0          ; empty
  1679.     je    clear_write_last
  1680.     ;je    clear_next_entry
  1681.  
  1682.     mov   eax,[ebx+20-2]        ; first cluster of entry
  1683.     mov   ax,[ebx+26]
  1684.     and   eax,[fatMASK]
  1685.  
  1686.     test  byte [ebx+11],0x10    ; is it directory?
  1687.     jz    clear_file            ; no
  1688.  
  1689.     push  eax ebx
  1690.     mov   eax,edi
  1691.     mov   ebx,deltree_buffer    ; save buffer over recursive call
  1692.     call  hd_write              ; write directory sector to disk
  1693.     pop   ebx eax
  1694.  
  1695.     call  clear_directory       ; recursive call !!!
  1696.     jc    clear_error           ; exit if error found
  1697.  
  1698.     push  eax ebx
  1699.     mov   eax,edi
  1700.     mov   ebx,deltree_buffer
  1701.     call  hd_read               ; read directory sector again
  1702.     pop   ebx eax
  1703.  
  1704.   clear_file:
  1705.     call  clear_cluster_chain
  1706.  
  1707.   clear_long_filename:
  1708.     mov   byte [ebx],0xe5
  1709.  
  1710.   clear_next_entry:
  1711.     add   ebx,32                ; position of next dir entry
  1712.     dec   edx
  1713.     jnz   clear_analyze
  1714.  
  1715.     mov   eax,edi
  1716.     mov   ebx,deltree_buffer
  1717.     call  hd_write              ; write directory sector to disk
  1718.  
  1719.     inc   eax                   ; next sector
  1720.     dec   ecx
  1721.     jnz   clear_new_sector
  1722.  
  1723.     mov   eax,esi
  1724.     call  get_FAT               ; get next cluster
  1725.     jmp   clear_new_cluster     ; clear it
  1726.  
  1727.   clear_write_last:
  1728.     mov   eax,edi
  1729.     mov   ebx,deltree_buffer
  1730.     call  hd_write              ; write directory sector to disk
  1731.  
  1732.   clear_end:
  1733.     popad
  1734.     clc
  1735.     ret
  1736.  
  1737.   clear_error:
  1738.     popad
  1739.     stc
  1740.     ret
  1741.  
  1742.  
  1743. delete_entry_name:
  1744. ;-----------------------------------------------------
  1745. ; input  : eax = directory sector
  1746. ;          ebx = directory pointer in buffer
  1747. ;          longname_sec = 2 previous directory sectors
  1748. ; output : ecx = first cluster
  1749. ; change : eax,ebx,edx
  1750. ;-----------------------------------------------------
  1751.     mov   byte [ebx],0xe5
  1752.     mov   ecx,[ebx+20-2]        ; first cluster of file
  1753.     mov   cx,[ebx+26]           ; 0 length files start cluster = 0
  1754.     and   ecx,[fatMASK]
  1755.  
  1756.   delete_empty:
  1757.     sub   ebx,32
  1758.     cmp   ebx,buffer
  1759.     jnb   delete_test_long
  1760.  
  1761.     mov   ebx,buffer
  1762.     call  hd_write              ; write directory sector back
  1763.     xor   eax,eax
  1764.     xchg  eax,[longname_sec2]
  1765.     xchg  eax,[longname_sec1]
  1766.     test  eax,eax               ; is there previous directory sector?
  1767.     jz    delete_name_end       ; no
  1768.  
  1769.     mov   ebx,buffer
  1770.     call  hd_read               ; read previous sector
  1771.     mov   ebx,buffer+0x1e0      ; start from last entry
  1772.  
  1773.   delete_test_long:
  1774.     mov   dh,[ebx+11]           ; file attribute
  1775.     and   dh,0xf
  1776.     cmp   dh,0xf
  1777.     jne   delete_write_buffer
  1778.  
  1779.     cmp   byte [ebx],0x40       ; end of long dir entry?
  1780.     mov   byte [ebx],0xe5
  1781.     jb    delete_empty
  1782.  
  1783.   delete_write_buffer:
  1784.     mov   ebx,buffer
  1785.     call  hd_write              ; write directory sector back
  1786.  
  1787.   delete_name_end:
  1788.     ret
  1789.  
  1790.  
  1791. rename:
  1792. ;-----------------------------------------------------------
  1793. ; input  : eax = source directory name
  1794. ;          edx = source path
  1795. ;          ebx = dest directory name
  1796. ;          edi = dest path
  1797. ; output : eax = 0 - ok
  1798. ;                3 - unknown FS
  1799. ;                5 - file not found
  1800. ;                8 - disk full
  1801. ;               10 - access denied
  1802. ;-----------------------------------------------------------
  1803.     cmp   [fat_type],0
  1804.     jnz   fat_ok_for_rename
  1805.     mov   eax,ERROR_UNKNOWN_FS
  1806.     ret
  1807.  
  1808.   fat_ok_for_rename:
  1809. ;    call  reserve_hd1
  1810.  
  1811.     pushad
  1812.  
  1813.     mov   ebx,edx               ; source path
  1814.     call  get_cluster_of_a_path
  1815.     jc    rename_entry_not_found
  1816.  
  1817.     mov   ebx,PUSHAD_EAX        ; source directory name
  1818.     call  analyze_directory
  1819.     jc    rename_entry_not_found
  1820.  
  1821.     mov   [sector_tmp],eax      ; save source sector
  1822.     mov   [entry_pos],ebx
  1823.     mov   esi,ebx
  1824.     mov   edi,dir_entry
  1825.     mov   ecx,32/4
  1826.     cld
  1827.     rep   movsd                 ; save entry
  1828.  
  1829.     mov   ebx,PUSHAD_EDI        ; dest path
  1830.     call  get_cluster_of_a_path
  1831.     jc    rename_entry_not_found
  1832.  
  1833.     mov   edx,eax               ; save dest directory cluster
  1834.     mov   ebx,PUSHAD_EBX        ; dest directory name
  1835.     push  [longname_sec1]
  1836.     push  [longname_sec2]
  1837.     call  analyze_directory     ; check if entry already exist
  1838.     pop   [longname_sec2]
  1839.     pop   [longname_sec1]
  1840.     jnc   rename_entry_already_exist
  1841.  
  1842.     mov   eax,edx
  1843.     call  analyze_directory_to_write
  1844.     jc    rename_disk_full
  1845.  
  1846.     mov   esi,dir_entry
  1847.     mov   edi,ebx
  1848.     mov   ecx,32/4
  1849.     cld
  1850.     rep   movsd                 ; copy entry
  1851.     mov   esi,PUSHAD_EBX        ; dest directory name
  1852.     mov   edi,ebx
  1853.     mov   ecx,11
  1854.     rep   movsb                 ; copy name
  1855.  
  1856.     mov   ebx,buffer            ; save the directory name,length,cluster
  1857.     call  hd_write
  1858.  
  1859.     test  byte [dir_entry+11],0x10 ; is it directory?
  1860.     jz    rename_not_dir           ; no
  1861.     mov   eax,[dir_entry+20-2]     ; FAT entry
  1862.     mov   ax,[dir_entry+26]
  1863.     and   eax,[fatMASK]
  1864.     call  change_2dot_cluster
  1865.  
  1866.   rename_not_dir:
  1867.     mov   eax,[sector_tmp]
  1868.     mov   ebx,buffer
  1869.     call  hd_read               ; read source directory sector
  1870.  
  1871.     mov   ebx,[entry_pos]
  1872.     call  delete_entry_name
  1873.  
  1874.     popad
  1875.     call  update_disk           ; write all of cache and fat to hd
  1876.     mov   [hd1_status],0
  1877.     xor   eax,eax
  1878.     ret
  1879.  
  1880.   rename_entry_not_found:
  1881.     popad
  1882.     mov   [hd1_status],0
  1883.     mov   eax,ERROR_FILE_NOT_FOUND
  1884.     ret
  1885.  
  1886.   rename_entry_already_exist:
  1887.     popad
  1888.     mov   [hd1_status],0
  1889.     mov   eax,ERROR_ACCESS_DENIED
  1890.     ret
  1891.  
  1892.   rename_disk_full:
  1893.     popad
  1894.     mov   [hd1_status],0
  1895.     mov   eax,ERROR_DISK_FULL
  1896.     ret
  1897.  
  1898.  
  1899. change_2dot_cluster:
  1900. ;-----------------------------------------------------------
  1901. ; input  : eax = directory cluster
  1902. ;          edx = value to save
  1903. ; change : eax,ebx,edx
  1904. ;-----------------------------------------------------------
  1905.     cmp   eax,[LAST_CLUSTER]
  1906.     ja    not_2dot              ; too big cluster number, something is wrong
  1907.     sub   eax,2
  1908.     jb    not_2dot
  1909.  
  1910.     imul  eax,[SECTORS_PER_CLUSTER]
  1911.     add   eax,[DATA_START]
  1912.     mov   ebx,buffer
  1913.     call  hd_read
  1914.  
  1915.     cmp   dword [ebx+32],'..  '
  1916.     jnz   not_2dot
  1917.  
  1918.     cmp   edx,[ROOT_CLUSTER]    ; is rootdir cluster?
  1919.     jne   not_2dot_root
  1920.     xor   edx,edx               ; yes. set it zero
  1921.  
  1922.   not_2dot_root:
  1923.     mov   [ebx+32+26],dx        ; 16 bits low of cluster
  1924.     shr   edx,16
  1925.     mov   [ebx+32+20],dx        ; 16 bits high of cluster (=0 fat16)
  1926.     call  hd_write
  1927.  
  1928.   not_2dot:
  1929.     ret
  1930.  
  1931.  
  1932. get_filesize:
  1933. ;-----------------------------------------------------------
  1934. ; input  : eax = file name
  1935. ;          edx = path
  1936. ;          edi = if 0 - read rootdir else normal dir/file size
  1937. ; output : eax = 0 - ok
  1938. ;                3 - unknown FS
  1939. ;                5 - file not found
  1940. ;          ebx = file size
  1941. ;-----------------------------------------------------------
  1942.     cmp   [fat_type],0
  1943.     jnz   get_filesize_fat_ok
  1944.     xor   ebx,ebx
  1945.     mov   eax,ERROR_UNKNOWN_FS
  1946.     ret
  1947.  
  1948.   get_filesize_fat_ok:
  1949. ;    call  reserve_hd1
  1950.  
  1951.     pushad
  1952.     xor   eax,eax
  1953.     test  edi,edi               ; is read rootdir?
  1954.     je    get_filesize_dirsize  ; yes
  1955.  
  1956.   get_filesize_no_root:
  1957.     mov   ebx,edx
  1958.     call  get_cluster_of_a_path
  1959.     jc    get_filesize_not_found
  1960.  
  1961.     mov   ebx,PUSHAD_EAX        ; file name
  1962.     call  analyze_directory
  1963.     jc    get_filesize_not_found
  1964.  
  1965.     mov   eax,[ebx+28]          ; file size
  1966.     test  byte [ebx+11],0x10    ; is it directory?
  1967.     jz    get_filesize_set_size ; no
  1968.  
  1969.     mov   eax,[ebx+20-2]        ; FAT entry
  1970.     mov   ax,[ebx+26]
  1971.     and   eax,[fatMASK]
  1972.  
  1973.   get_filesize_dirsize:
  1974.     call  get_dir_size
  1975.  
  1976.   get_filesize_set_size:
  1977.     mov   PUSHAD_EBX,eax
  1978.     popad
  1979.     mov   [hd1_status],0
  1980.     xor   eax,eax
  1981.     ret
  1982.  
  1983.   get_filesize_not_found:
  1984.     popad
  1985.     mov   [hd1_status],0
  1986.     xor   ebx,ebx
  1987.     mov   eax,ERROR_FILE_NOT_FOUND
  1988.     ret
  1989.  
  1990.  
  1991. get_fileattr:
  1992. ;-----------------------------------------------------------
  1993. ; input  : eax = file name
  1994. ;          edx = path
  1995. ; output : eax = 0 - ok
  1996. ;                3 - unknown FS
  1997. ;                5 - file not found
  1998. ;          ebx = file attribute
  1999. ;-----------------------------------------------------------
  2000.     cmp   [fat_type],0
  2001.     jnz   get_fileattr_fat_ok
  2002.     xor   ebx,ebx
  2003.     mov   eax,ERROR_UNKNOWN_FS
  2004.     ret
  2005.  
  2006.   get_fileattr_fat_ok:
  2007. ;    call  reserve_hd1
  2008.  
  2009.     pushad
  2010.     mov   ebx,edx
  2011.     call  get_cluster_of_a_path
  2012.     jc    get_fileattr_not_found
  2013.  
  2014.     mov   ebx,PUSHAD_EAX        ; file name
  2015.     call  analyze_directory
  2016.     jc    get_fileattr_not_found
  2017.  
  2018.     movzx eax,byte [ebx+11]     ; file attribute
  2019.     mov   PUSHAD_EBX,eax
  2020.     popad
  2021.     mov   [hd1_status],0
  2022.     xor   eax,eax
  2023.     ret
  2024.  
  2025.   get_fileattr_not_found:
  2026.     popad
  2027.     mov   [hd1_status],0
  2028.     xor   ebx,ebx
  2029.     mov   eax,ERROR_FILE_NOT_FOUND
  2030.     ret
  2031.  
  2032.  
  2033. get_filedate:
  2034. ;-----------------------------------------------------------
  2035. ; input  : eax = file name
  2036. ;          edx = path
  2037. ; output : eax = 0 - ok
  2038. ;                3 - unknown FS
  2039. ;                5 - file not found
  2040. ;          ebx = file date/time
  2041. ;                bits 31..25 = year-1980
  2042. ;                bits 24..21 = month
  2043. ;                bits 20..16 = day
  2044. ;                bits 15..11 = hour
  2045. ;                bits 10..5  = minute
  2046. ;                bits 4..0   = second/2
  2047. ;-----------------------------------------------------------
  2048.     cmp   [fat_type],0
  2049.     jnz   get_filedate_fat_ok
  2050.     xor   ebx,ebx
  2051.     mov   eax,ERROR_UNKNOWN_FS
  2052.     ret
  2053.  
  2054.   get_filedate_fat_ok:
  2055. ;    call  reserve_hd1
  2056.  
  2057.     pushad
  2058.     mov   ebx,edx
  2059.     call  get_cluster_of_a_path
  2060.     jc    get_filedate_not_found
  2061.  
  2062.     mov   ebx,PUSHAD_EAX        ; file name
  2063.     call  analyze_directory
  2064.     jc    get_filedate_not_found
  2065.  
  2066.     mov   eax,[ebx+22]          ; file date/time
  2067.     mov   PUSHAD_EBX,eax
  2068.     popad
  2069.     mov   [hd1_status],0
  2070.     xor   eax,eax
  2071.     ret
  2072.  
  2073.   get_filedate_not_found:
  2074.     popad
  2075.     mov   [hd1_status],0
  2076.     xor   ebx,ebx
  2077.     mov   eax,ERROR_FILE_NOT_FOUND
  2078.     ret
  2079.  
  2080.  
  2081. get_hd_info:
  2082. ;-----------------------------------------------------------
  2083. ; output : eax = 0 - ok
  2084. ;                3 - unknown FS
  2085. ;          edx = cluster size in bytes
  2086. ;          ebx = total clusters on disk
  2087. ;          ecx = free clusters on disk
  2088. ;-----------------------------------------------------------
  2089.     cmp   [fat_type],0
  2090.     jnz   info_fat_ok
  2091.     xor   edx,edx
  2092.     xor   ebx,ebx
  2093.     xor   ecx,ecx
  2094.     mov   eax,ERROR_UNKNOWN_FS
  2095.     ret
  2096.  
  2097.   info_fat_ok:
  2098. ;    call  reserve_hd1
  2099.  
  2100.     xor   ecx,ecx               ; count of free clusters
  2101.     mov   eax,2
  2102.     mov   ebx,[LAST_CLUSTER]
  2103.  
  2104.   info_cluster:
  2105.     push  eax
  2106.     call  get_FAT               ; get cluster info
  2107.     test  eax,eax               ; is it free?
  2108.     jnz   info_used             ; no
  2109.     inc   ecx
  2110.  
  2111.   info_used:
  2112.     pop   eax
  2113.     inc   eax
  2114.     cmp   eax,ebx               ; is above last cluster?
  2115.     jbe   info_cluster          ; no. test next cluster
  2116.  
  2117.     dec   ebx                   ; cluster count
  2118.     imul  edx,[SECTORS_PER_CLUSTER],512 ; cluster size in bytes
  2119.     mov   [hd1_status],0
  2120.     xor   eax,eax
  2121.     ret
  2122.  
  2123.  
  2124. update_disk:
  2125. ;-----------------------------------------------------------
  2126. ; write changed fat and cache to disk
  2127. ;-----------------------------------------------------------
  2128.     cmp   [fat_change],0        ; is fat changed?
  2129.     je    upd_no_change
  2130.  
  2131.     call  write_fat_sector
  2132.  
  2133.   upd_no_change:
  2134.  
  2135.     call  write_cache
  2136.     ret
  2137.  
  2138.  
  2139. ;**************************************************************************
  2140. ;
  2141. ;   0x600008  - first entry in cache list
  2142. ;
  2143. ;            +0   - lba sector
  2144. ;            +4   - state of cache sector
  2145. ;                   0 = empty
  2146. ;                   1 = used for read  ( same as in hd )
  2147. ;                   2 = used for write ( differs from hd )
  2148. ;
  2149. ;      +65536 - cache entries
  2150. ;
  2151. ;**************************************************************************
  2152.  
  2153.  
  2154. hd_read:
  2155. ;-----------------------------------------------------------
  2156. ; input  : eax = block to read
  2157. ;          ebx = destination
  2158. ;-----------------------------------------------------------
  2159.     push  ecx esi edi           ; scan cache
  2160.  
  2161.     mov   ecx,cache_max         ; entries in cache
  2162.     mov   esi,0x600000+8
  2163.     mov   edi,1
  2164.  
  2165.   hdreadcache:
  2166.  
  2167.     cmp   dword [esi+4],0       ; empty
  2168.     je    nohdcache
  2169.  
  2170.     cmp   [esi],eax             ; correct sector
  2171.     je    yeshdcache
  2172.  
  2173.   nohdcache:
  2174.  
  2175.     add   esi,8
  2176.     inc   edi
  2177.     dec   ecx
  2178.     jnz   hdreadcache
  2179.  
  2180.     call  find_empty_slot       ; ret in edi
  2181.  
  2182.     call  wait_for_hd_idle
  2183.     push  eax edx
  2184.  
  2185.     cli
  2186.     xor   eax,eax
  2187.     mov   edx,[hdbase]
  2188.     inc   edx
  2189.     out   dx,al   ; ATAFeatures ðåãèñòð "îñîáåííîñòåé"
  2190.     inc   edx
  2191.     inc   eax
  2192.     out   dx,al   ; ATASectorCount ñ÷åò÷èê ñåêòîðîâ
  2193.     inc   edx
  2194.     mov   eax,[esp+4]
  2195.     out   dx,al   ; ATASectorNumber ðåãèñòð íîìåðà ñåêòîðà
  2196.     shr   eax,8
  2197.     inc   edx
  2198.     out   dx,al   ; ATACylinder íîìåð öèëèíäðà (ìëàäøèé áàéò)
  2199.     shr   eax,8
  2200.     inc   edx
  2201.     out   dx,al   ; íîìåð öèëèíäðà (ñòàðøèé áàéò)
  2202.     shr   eax,8
  2203.     inc   edx
  2204.     and   al,1+2+4+8
  2205.     add   al,byte [hdid]
  2206.     add   al,128+64+32
  2207.     out   dx,al   ; íîìåð ãîëîâêè/íîìåð äèñêà
  2208.     inc   edx
  2209.     mov   al,20h
  2210.     out   dx,al   ; ATACommand ðåãèñòð êîìàíä
  2211.     sti
  2212.  
  2213.     call  wait_for_sector_buffer
  2214.  
  2215.     cmp   [hd_error],0
  2216.     jne   hd_read_error
  2217.  
  2218.     cli
  2219.     push  edi
  2220.     shl   edi,9
  2221.     add   edi,0x600000+65536
  2222.     mov   ecx,256
  2223.     mov   edx,[hdbase]
  2224.     cld
  2225.     rep   insw
  2226.     pop   edi
  2227.     sti
  2228.  
  2229.     pop   edx eax
  2230.  blok_read_2:
  2231.     lea   esi,[edi*8+0x600000]
  2232.     mov   [esi],eax             ; sector number
  2233.     mov   dword [esi+4],1       ; hd read - mark as same as in hd
  2234.  
  2235.   yeshdcache:
  2236.  
  2237.     mov   esi,edi
  2238.     shl   esi,9
  2239.     add   esi,0x600000+65536
  2240.     mov   edi,ebx
  2241.     mov   ecx,512/4
  2242.     cld
  2243.     rep   movsd                 ; move data
  2244. ; blok_read_2:
  2245.     pop   edi esi ecx
  2246.     ret
  2247.    
  2248.  
  2249. hd_write:
  2250. ;-----------------------------------------------------------
  2251. ; input  : eax = block
  2252. ;          ebx = pointer to memory
  2253. ;-----------------------------------------------------------
  2254.     push  ecx esi edi
  2255.  
  2256.     ; check if the cache already has the sector and overwrite it
  2257.  
  2258.     mov   ecx,cache_max
  2259.     mov   esi,0x600000+8
  2260.     mov   edi,1
  2261.  
  2262.   hdwritecache:
  2263.  
  2264.     cmp   dword [esi+4],0       ; if cache slot is empty
  2265.     je    not_in_cache_write
  2266.  
  2267.     cmp   [esi],eax             ; if the slot has the sector
  2268.     je    yes_in_cache_write
  2269.  
  2270.   not_in_cache_write:
  2271.  
  2272.     add   esi,8
  2273.     inc   edi
  2274.     dec   ecx
  2275.     jnz   hdwritecache
  2276.  
  2277.     ; sector not found in cache
  2278.     ; write the block to a new location
  2279.  
  2280.     call  find_empty_slot       ; ret in edi
  2281.  
  2282.     lea   esi,[edi*8+0x600000]
  2283.     mov   [esi],eax             ; sector number
  2284.  
  2285.   yes_in_cache_write:
  2286.  
  2287.     mov   dword [esi+4],2       ; write - differs from hd
  2288.  
  2289.     shl   edi,9
  2290.     add   edi,0x600000+65536
  2291.     mov   esi,ebx
  2292.     mov   ecx,512/4
  2293.     cld
  2294.     rep   movsd                 ; move data
  2295.  
  2296.     pop   edi esi ecx
  2297.     ret
  2298.  
  2299.  
  2300. write_cache:
  2301. ;-----------------------------------------------------------
  2302. ; write all changed sectors to disk
  2303. ;-----------------------------------------------------------
  2304.     push  eax ecx edx esi edi
  2305.  
  2306.     ; write difference ( 2 ) from cache to hd
  2307.  
  2308.     mov   ecx,cache_max
  2309.     mov   esi,0x600000+8
  2310.     mov   edi,1
  2311.  
  2312.   write_cache_more:
  2313.  
  2314.     cmp   dword [esi+4],2       ; if cache slot is not different
  2315.     jne   does_not_need_writing
  2316.  
  2317.     mov   dword [esi+4],1       ; same as in hd
  2318.     mov   eax,[esi]             ; eax = sector to write
  2319.  
  2320.     cmp   eax,[PARTITION_START]
  2321.     jb    danger
  2322.     cmp   eax,[PARTITION_END]
  2323.     ja    danger
  2324.  
  2325.     call  wait_for_hd_idle
  2326.  
  2327.     cli
  2328.     xor   eax,eax
  2329.     mov   edx,[hdbase]
  2330.     inc   edx
  2331.     out   dx,al
  2332.     inc   edx
  2333.     inc   eax
  2334.     out   dx,al
  2335.     inc   edx
  2336.     mov   eax,[esi]             ; eax = sector to write
  2337.     out   dx,al
  2338.     shr   eax,8
  2339.     inc   edx
  2340.     out   dx,al
  2341.     shr   eax,8
  2342.     inc   edx
  2343.     out   dx,al
  2344.     shr   eax,8
  2345.     inc   edx
  2346.     and   al,1+2+4+8
  2347.     add   al,byte [hdid]
  2348.     add   al,128+64+32
  2349.     out   dx,al
  2350.     inc   edx
  2351.     mov   al,30h
  2352.     out   dx,al
  2353.     sti
  2354.  
  2355.     call  wait_for_sector_buffer
  2356.  
  2357.     cmp   [hd_error],0
  2358.     jne   hd_write_error
  2359.  
  2360.     push  ecx esi
  2361.  
  2362.     cli
  2363.     mov   esi,edi
  2364.     shl   esi,9
  2365.     add   esi,0x600000+65536    ; esi = from memory position
  2366.     mov   ecx,256
  2367.     mov   edx,[hdbase]
  2368.     cld
  2369.     rep   outsw
  2370.     sti
  2371.  
  2372.     pop   esi ecx
  2373.  
  2374.   danger:
  2375.   does_not_need_writing:
  2376.  
  2377.     add   esi,8
  2378.     inc   edi
  2379.     dec   ecx
  2380.     jnz   write_cache_more
  2381.  
  2382.     pop   edi esi edx ecx eax
  2383.     ret
  2384.  
  2385.  
  2386. find_empty_slot:
  2387. ;-----------------------------------------------------------
  2388. ; find empty or read slot, flush cache if next 10% is used by write
  2389. ; output : edi = cache slot
  2390. ;-----------------------------------------------------------
  2391.     push  ecx esi
  2392.  
  2393.   search_again:
  2394.  
  2395.     mov   ecx,cache_max*10/100
  2396.     mov   edi,[cache_search_start]
  2397.  
  2398.   search_for_empty:
  2399.  
  2400.     inc   edi
  2401.     cmp   edi,cache_max
  2402.     jbe   inside_cache
  2403.     mov   edi,1
  2404.  
  2405.   inside_cache:
  2406.  
  2407.     cmp   dword [edi*8+0x600000+4],2    ; get cache slot info
  2408.     jb    found_slot                    ; it's empty or read
  2409.     dec   ecx
  2410.     jnz   search_for_empty
  2411.  
  2412.     call  write_cache                   ; no empty slots found, write all
  2413.     jmp   search_again                  ; and start again
  2414.  
  2415.   found_slot:
  2416.  
  2417.     mov   [cache_search_start],edi
  2418.  
  2419.     pop   esi ecx
  2420.     ret
  2421.  
  2422.  
  2423. save_hd_wait_timeout:
  2424.  
  2425.     push  eax
  2426.     mov   eax,[timer_ticks];[0xfdf0]
  2427.     add   eax,300               ; 3 sec timeout
  2428.     mov   [hd_wait_timeout],eax
  2429.     pop   eax
  2430.     ret
  2431.  
  2432.  
  2433. check_hd_wait_timeout:
  2434.  
  2435.     push  eax
  2436.     mov   eax,[hd_wait_timeout]
  2437.     cmp   [timer_ticks], eax ;[0xfdf0],eax
  2438.     jg    hd_timeout_error
  2439.     pop   eax
  2440.     ret
  2441.  
  2442. iglobal
  2443.   hd_timeout_str   db 'K : FS - HD timeout',13,10,0
  2444.   hd_read_str      db 'K : FS - HD read error',13,10,0
  2445.   hd_write_str     db 'K : FS - HD write error',13,10,0
  2446. endg
  2447.  
  2448. hd_timeout_error:
  2449.  
  2450.     call  clear_hd_cache
  2451.     call  clear_application_table_status
  2452.     mov   esi,hd_timeout_str
  2453.     call  sys_msg_board_str
  2454.     jmp   $
  2455.  
  2456.  
  2457. hd_read_error:
  2458.  
  2459.     call  clear_hd_cache
  2460.     call  clear_application_table_status
  2461.     mov   esi,hd_read_str
  2462.     call  sys_msg_board_str
  2463.     jmp   $
  2464.  
  2465. hd_write_error:
  2466.  
  2467.     call  clear_hd_cache
  2468.     call  clear_application_table_status
  2469.     mov   esi,hd_write_str
  2470.     call  sys_msg_board_str
  2471.     jmp   $
  2472.  
  2473.  
  2474.  
  2475.  
  2476. wait_for_hd_idle:
  2477.  
  2478.     push  eax edx
  2479.  
  2480.     call  save_hd_wait_timeout
  2481.  
  2482.     mov   edx,[hdbase]
  2483.     add   edx,0x7
  2484.  
  2485.   wfhil1:
  2486.  
  2487.     call  check_hd_wait_timeout
  2488.  
  2489.     in    al,dx
  2490.     test  al,128
  2491.     jnz   wfhil1
  2492.  
  2493.     pop   edx eax
  2494.     ret
  2495.  
  2496.  
  2497. wait_for_sector_buffer:
  2498.  
  2499.     push  eax edx
  2500.  
  2501.     mov   edx,[hdbase]
  2502.     add   edx,0x7
  2503.  
  2504.     call  save_hd_wait_timeout
  2505.  
  2506.   hdwait_sbuf:                  ; wait for sector buffer to be ready
  2507.  
  2508.     call  check_hd_wait_timeout
  2509.  
  2510.     in    al,dx
  2511.     test  al,8
  2512.     jz    hdwait_sbuf
  2513.  
  2514.     mov   [hd_error],0
  2515.  
  2516.     cmp   [hd_setup],1          ; do not mark error for setup request
  2517.     je    buf_wait_ok
  2518.  
  2519.     test  al,1                  ; previous command ended up with an error
  2520.     jz    buf_wait_ok
  2521.     mov   [hd_error],1
  2522.  
  2523.   buf_wait_ok:
  2524.  
  2525.     pop   edx eax
  2526.     ret
  2527.  
  2528.  
  2529.  
  2530. read_hd_file:
  2531. ;-----------------------------------------------------------------
  2532. ;
  2533. ; Converting old reading function for hd-application start.
  2534. ;
  2535. ; IN:
  2536. ;
  2537. ; eax - pointer to file (0 = read only first sector of drive: eg 'label')
  2538. ; ebx - file lenght
  2539. ; ecx - start 512 byte block number
  2540. ; edx - number of blocks to read
  2541. ; esi - pointer to return/work area (atleast 20 000 bytes)
  2542. ;
  2543. ; For new read function
  2544. ;
  2545. ; EAX   (PAR0)      pointer to file-name
  2546. ; ECX   (PAR1)      pointer to buffer
  2547. ; EBX   (PAR2)   vt file blocks to read
  2548. ; EDX   (PAR3)      pointer to path
  2549. ; ESI            vt first 512 block to read
  2550. ; EDI               if 0 - return root
  2551. ;--------------------------------------------------------------------------
  2552.  
  2553.     push  ecx esi edi
  2554.     mov   esi,eax
  2555.     mov   edi,startpath
  2556.     mov   ecx,250
  2557.     cld
  2558.     rep   movsb
  2559.     pop   edi esi ecx
  2560.  
  2561.     mov   eax,startpath
  2562.     mov   [eax+ebx-12],byte 0
  2563.  
  2564.     push  eax ebx ecx edx esi
  2565.  
  2566.     pop   ecx ; pointer to buffer
  2567.     add   ecx,1024
  2568.     pop   ebx ; number of blocks to read
  2569.     pop   esi ; first block to read
  2570.     dec   esi
  2571.     pop   eax ; file length
  2572.     pop   edx ; pointer to path
  2573.  
  2574.     mov   edi,12
  2575.     lea   eax,[eax+edx-12+1]
  2576.     call  file_read
  2577.  
  2578.     ret
  2579.  
  2580.