Subversion Repositories Kolibri OS

Rev

Rev 425 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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