Subversion Repositories Kolibri OS

Rev

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