Subversion Repositories Kolibri OS

Rev

Rev 4429 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4429 Rev 5116
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
5
;;                                                                 ;;
6
;;  FAT32.INC                                                      ;;
6
;;  FAT32.INC                                                      ;;
7
;;                                                                 ;;
7
;;                                                                 ;;
8
;;  FAT functions for KolibriOS                                    ;;
8
;;  FAT functions for KolibriOS                                    ;;
9
;;                                                                 ;;
9
;;                                                                 ;;
10
;;  Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it          ;;
10
;;  Copyright 2002 Paolo Minazzi, paolo.minazzi@inwind.it          ;;
11
;;                                                                 ;;
11
;;                                                                 ;;
12
;;  See file COPYING for details                                   ;;
12
;;  See file COPYING for details                                   ;;
13
;;  04.02.2007 LFN create folder - diamond                         ;;
13
;;  04.02.2007 LFN create folder - diamond                         ;;
14
;;  08.10.2006 LFN delete file/folder - diamond                    ;;
14
;;  08.10.2006 LFN delete file/folder - diamond                    ;;
15
;;  20.08.2006 LFN set file size (truncate/extend) - diamond       ;;
15
;;  20.08.2006 LFN set file size (truncate/extend) - diamond       ;;
16
;;  17.08.2006 LFN write/append to file - diamond                  ;;
16
;;  17.08.2006 LFN write/append to file - diamond                  ;;
17
;;  23.06.2006 LFN start application - diamond                     ;;
17
;;  23.06.2006 LFN start application - diamond                     ;;
18
;;  15.06.2006 LFN get/set file/folder info - diamond              ;;
18
;;  15.06.2006 LFN get/set file/folder info - diamond              ;;
19
;;  27.05.2006 LFN create/rewrite file - diamond                   ;;
19
;;  27.05.2006 LFN create/rewrite file - diamond                   ;;
20
;;  04.05.2006 LFN read folder - diamond                           ;;
20
;;  04.05.2006 LFN read folder - diamond                           ;;
21
;;  29.04.2006 Elimination of hangup after the                     ;;
21
;;  29.04.2006 Elimination of hangup after the                     ;;
22
;;             expiration hd_wait_timeout -  Mario79               ;;
22
;;             expiration hd_wait_timeout -  Mario79               ;;
23
;;  23.04.2006 LFN read file - diamond                             ;;
23
;;  23.04.2006 LFN read file - diamond                             ;;
24
;;  28.01.2006 find all Fat16/32 partition in all input point      ;;
24
;;  28.01.2006 find all Fat16/32 partition in all input point      ;;
25
;;             to MBR, see file part_set.inc - Mario79             ;;
25
;;             to MBR, see file part_set.inc - Mario79             ;;
26
;;  15.01.2005 get file size/attr/date, file_append - ATV          ;;
26
;;  15.01.2005 get file size/attr/date, file_append - ATV          ;;
27
;;  04.12.2004 skip volume label, file delete bug fixed - ATV      ;;
27
;;  04.12.2004 skip volume label, file delete bug fixed - ATV      ;;
28
;;  29.11.2004 get_free_FAT changed, append dir bug fixed - ATV    ;;
28
;;  29.11.2004 get_free_FAT changed, append dir bug fixed - ATV    ;;
29
;;  23.11.2004 don't allow overwrite dir with file - ATV           ;;
29
;;  23.11.2004 don't allow overwrite dir with file - ATV           ;;
30
;;  18.11.2004 get_disk_info and more error codes - ATV            ;;
30
;;  18.11.2004 get_disk_info and more error codes - ATV            ;;
31
;;  17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV      ;;
31
;;  17.11.2004 set_FAT/get_FAT and disk cache rewritten - ATV      ;;
32
;;  10.11.2004 removedir clear whole directory structure - ATV     ;;
32
;;  10.11.2004 removedir clear whole directory structure - ATV     ;;
33
;;  08.11.2004 rename - ATV                                        ;;
33
;;  08.11.2004 rename - ATV                                        ;;
34
;;  30.10.2004 file_read return also dirsize in bytes - ATV        ;;
34
;;  30.10.2004 file_read return also dirsize in bytes - ATV        ;;
35
;;  20.10.2004 Makedir/Removedir - ATV                             ;;
35
;;  20.10.2004 Makedir/Removedir - ATV                             ;;
36
;;  14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx)         ;;
36
;;  14.10.2004 Partition chain/Fat16 - ATV (thanks drh3xx)         ;;
37
;;  06.9.2004  Fix free space by Mario79 added - MH                ;;
37
;;  06.9.2004  Fix free space by Mario79 added - MH                ;;
38
;;  24.5.2004  Write back buffer for File_write -VT                ;;
38
;;  24.5.2004  Write back buffer for File_write -VT                ;;
39
;;  20.5.2004  File_read function to work with syscall 58 - VT     ;;
39
;;  20.5.2004  File_read function to work with syscall 58 - VT     ;;
40
;;  30.3.2004  Error parameters at function return - VT            ;;
40
;;  30.3.2004  Error parameters at function return - VT            ;;
41
;;  01.5.2002  Bugfix in device write - VT                         ;;
41
;;  01.5.2002  Bugfix in device write - VT                         ;;
42
;;  20.5.2002  Hd status check - VT                                ;;
42
;;  20.5.2002  Hd status check - VT                                ;;
43
;;  29.6.2002  Improved fat32 verification - VT                    ;;
43
;;  29.6.2002  Improved fat32 verification - VT                    ;;
44
;;                                                                 ;;
44
;;                                                                 ;;
45
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
45
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
46
 
46
 
47
$Revision: 4273 $
47
$Revision: 5089 $
48
 
48
 
49
 
49
 
50
cache_max equ 1919      ; max. is 1919*512+0x610000=0x6ffe00
50
cache_max equ 1919      ; max. is 1919*512+0x610000=0x6ffe00
51
 
51
 
52
PUSHAD_EAX equ [esp+28]
52
PUSHAD_EAX equ [esp+28]
53
PUSHAD_ECX equ [esp+24]
53
PUSHAD_ECX equ [esp+24]
54
PUSHAD_EDX equ [esp+20]
54
PUSHAD_EDX equ [esp+20]
55
PUSHAD_EBX equ [esp+16]
55
PUSHAD_EBX equ [esp+16]
56
PUSHAD_EBP equ [esp+8]
56
PUSHAD_EBP equ [esp+8]
57
PUSHAD_ESI equ [esp+4]
57
PUSHAD_ESI equ [esp+4]
58
PUSHAD_EDI equ [esp+0]
58
PUSHAD_EDI equ [esp+0]
59
 
59
 
60
; Internal data for every FAT partition.
60
; Internal data for every FAT partition.
61
struct FAT PARTITION
61
struct FAT PARTITION
62
fs_type              db ?
62
fs_type              db ?
63
fat16_root           db 0       ; flag for fat16 rootdir
63
fat16_root           db 0       ; flag for fat16 rootdir
64
fat_change           db 0       ; 1=fat has changed
64
fat_change           db 0       ; 1=fat has changed
65
                     db ?       ; alignment
65
                     db ?       ; alignment
66
Lock                 MUTEX ?    ; currently operations with one partition
66
Lock                 MUTEX ?    ; currently operations with one partition
67
                                ; can not be executed in parallel since the
67
                                ; can not be executed in parallel since the
68
                                ; legacy code is not ready; this mutex guards
68
                                ; legacy code is not ready; this mutex guards
69
                                ; all operations
69
                                ; all operations
70
SECTORS_PER_FAT      dd 0x1f3a
70
SECTORS_PER_FAT      dd 0x1f3a
71
NUMBER_OF_FATS       dd 0x2
71
NUMBER_OF_FATS       dd 0x2
72
SECTORS_PER_CLUSTER  dd 0x8
72
SECTORS_PER_CLUSTER  dd 0x8
73
BYTES_PER_SECTOR     dd 0x200   ; Note: if BPS <> 512 need lots of changes
73
BYTES_PER_SECTOR     dd 0x200   ; Note: if BPS <> 512 need lots of changes
74
ROOT_CLUSTER         dd 2       ; first rootdir cluster
74
ROOT_CLUSTER         dd 2       ; first rootdir cluster
75
FAT_START            dd 0       ; start of fat table
75
FAT_START            dd 0       ; start of fat table
76
ROOT_START           dd 0       ; start of rootdir (only fat16)
76
ROOT_START           dd 0       ; start of rootdir (only fat16)
77
ROOT_SECTORS         dd 0       ; count of rootdir sectors (only fat16)
77
ROOT_SECTORS         dd 0       ; count of rootdir sectors (only fat16)
78
DATA_START           dd 0       ; start of data area (=first cluster 2)
78
DATA_START           dd 0       ; start of data area (=first cluster 2)
79
LAST_CLUSTER         dd 0       ; last availabe cluster
79
LAST_CLUSTER         dd 0       ; last availabe cluster
80
ADR_FSINFO           dd 0       ; used only by fat32
80
ADR_FSINFO           dd 0       ; used only by fat32
81
 
81
 
82
fatRESERVED          dd 0x0FFFFFF6
82
fatRESERVED          dd 0x0FFFFFF6
83
fatBAD               dd 0x0FFFFFF7
83
fatBAD               dd 0x0FFFFFF7
84
fatEND               dd 0x0FFFFFF8
84
fatEND               dd 0x0FFFFFF8
85
fatMASK              dd 0x0FFFFFFF
85
fatMASK              dd 0x0FFFFFFF
86
 
86
 
87
fatStartScan         dd 2
87
fatStartScan         dd 2
88
 
88
 
89
cluster_tmp          dd 0       ; used by analyze_directory
89
cluster_tmp          dd 0       ; used by analyze_directory
90
                                ; and analyze_directory_to_write
90
                                ; and analyze_directory_to_write
91
 
91
 
92
longname_sec1        dd 0       ; used by analyze_directory to save 2 previous
92
longname_sec1        dd 0       ; used by analyze_directory to save 2 previous
93
longname_sec2        dd 0       ; directory sectors for delete long filename
93
longname_sec2        dd 0       ; directory sectors for delete long filename
94
 
94
 
95
fat_in_cache         dd -1
95
fat_in_cache         dd -1
96
 
96
 
97
; For FAT16/FAT32, this points to 512-byte buffer for the current sector of FAT.
97
; For FAT16/FAT32, this points to 512-byte buffer for the current sector of FAT.
98
; For FAT12, the entire FAT structure is read
98
; For FAT12, the entire FAT structure is read
99
; and unpacked from 12bit per cluster to word per cluster.
99
; and unpacked from 12bit per cluster to word per cluster.
100
;
100
;
101
; Note: work with unpacked copy of FAT12 means
101
; Note: work with unpacked copy of FAT12 means
102
; additional memory and additional code for packing/unpacking.
102
; additional memory and additional code for packing/unpacking.
103
; I'm not sure that the economy justifies the cost, but anyway,
103
; I'm not sure that the economy justifies the cost, but anyway,
104
; there is how work was done before my edits, and I'm just keeping the principle.
104
; there is how work was done before my edits, and I'm just keeping the principle.
105
fat_cache_ptr        dd ?
105
fat_cache_ptr        dd ?
106
fat12_unpacked_ptr   dd ?
106
fat12_unpacked_ptr   dd ?
107
buffer               rb 512
107
buffer               rb 512
108
fsinfo_buffer        rb 512
108
fsinfo_buffer        rb 512
109
ends
109
ends
110
 
110
 
111
uglobal
111
uglobal
112
align 4
112
align 4
113
partition_count      dd 0       ; partitions found by set_FAT32_variables
113
partition_count      dd 0       ; partitions found by set_FAT32_variables
114
 
114
 
115
hd_error             dd 0       ; set by wait_for_sector_buffer
115
hd_error             dd 0       ; set by wait_for_sector_buffer
116
hd_setup             dd 0
116
hd_setup             dd 0
117
hd_wait_timeout      dd 0
117
hd_wait_timeout      dd 0
118
 
118
 
119
cache_search_start   dd 0       ; used by find_empty_slot
119
cache_search_start   dd 0       ; used by find_empty_slot
120
endg
120
endg
121
 
121
 
122
uglobal
122
uglobal
123
align 4
123
align 4
124
 Sector512:                      ; label for dev_hdcd.inc
124
 Sector512:                      ; label for dev_hdcd.inc
125
  buffer:
125
  buffer:
126
                times 512 db 0
126
                times 512 db 0
127
endg
127
endg
128
 
128
 
129
iglobal
129
iglobal
130
align 4
130
align 4
131
fat_user_functions:
131
fat_user_functions:
132
        dd      fat_free
132
        dd      fat_free
133
        dd      (fat_user_functions_end - fat_user_functions - 4) / 4
133
        dd      (fat_user_functions_end - fat_user_functions - 4) / 4
134
        dd      fat_Read
134
        dd      fat_Read
135
        dd      fat_ReadFolder
135
        dd      fat_ReadFolder
136
        dd      fat_Rewrite
136
        dd      fat_Rewrite
137
        dd      fat_Write
137
        dd      fat_Write
138
        dd      fat_SetFileEnd
138
        dd      fat_SetFileEnd
139
        dd      fat_GetFileInfo
139
        dd      fat_GetFileInfo
140
        dd      fat_SetFileInfo
140
        dd      fat_SetFileInfo
141
        dd      0
141
        dd      0
142
        dd      fat_Delete
142
        dd      fat_Delete
143
        dd      fat_CreateFolder
143
        dd      fat_CreateFolder
144
fat_user_functions_end:
144
fat_user_functions_end:
145
endg
145
endg
146
 
146
 
147
; these labels are located before the main function to make
147
; these labels are located before the main function to make
148
; most of jumps to these be short
148
; most of jumps to these be short
149
fat_create_partition.free_return0:
149
fat_create_partition.free_return0:
150
        mov     eax, ebp
150
        mov     eax, ebp
151
        call    free
151
        call    free
152
        pop     ebp
152
        pop     ebp
153
fat_create_partition.return0:
153
fat_create_partition.return0:
154
        xor     eax, eax
154
        xor     eax, eax
155
        ret
155
        ret
156
fat_create_partition:
156
fat_create_partition:
-
 
157
; sector size must be 512
-
 
158
        cmp     dword [esi+DISK.MediaInfo.SectorSize], 512
-
 
159
        jnz     .return0
157
; bootsector must have been successfully read
160
; bootsector must have been successfully read
158
        cmp     dword [esp+4], 0
161
        cmp     dword [esp+4], 0
159
        jnz     .return0
162
        jnz     .return0
160
; bootsector signature must be correct
163
; bootsector signature must be correct
161
        cmp     word [ebx+0x1fe], 0xaa55
164
        cmp     word [ebx+0x1fe], 0xaa55
162
        jnz     .return0
165
        jnz     .return0
163
; sectors per cluster must be nonzero
166
; sectors per cluster must be nonzero
164
        cmp     byte [ebx+0xd], 0
167
        cmp     byte [ebx+0xd], 0
165
        jz      .return0
168
        jz      .return0
166
; bytes per sector must be 0x200
169
; bytes per sector must be 0x200
167
        cmp     word [ebx+0xb], 0x200
170
        cmp     word [ebx+0xb], 0x200
168
        jnz     .return0
171
        jnz     .return0
169
; number of fats must be nonzero
172
; number of fats must be nonzero
170
        cmp     byte [ebx+0x10], 0
173
        cmp     byte [ebx+0x10], 0
171
        jz      .return0
174
        jz      .return0
172
; The only reason to be invalid partition now is FAT12. Since the test for
175
; The only reason to be invalid partition now is FAT12. Since the test for
173
; FAT size requires knowledge of some calculated values, which are also used
176
; FAT size requires knowledge of some calculated values, which are also used
174
; in the normal operation, let's hope for the best and allocate data now; if
177
; in the normal operation, let's hope for the best and allocate data now; if
175
; it will prove wrong, just deallocate it.
178
; it will prove wrong, just deallocate it.
176
        movi    eax, sizeof.FAT
179
        movi    eax, sizeof.FAT
177
        call    malloc
180
        call    malloc
178
        test    eax, eax
181
        test    eax, eax
179
        jz      .return0
182
        jz      .return0
180
        mov     ecx, dword [ebp+PARTITION.FirstSector]
183
        mov     ecx, dword [ebp+PARTITION.FirstSector]
181
        mov     dword [eax+FAT.FirstSector], ecx
184
        mov     dword [eax+FAT.FirstSector], ecx
182
        mov     ecx, dword [ebp+PARTITION.FirstSector+4]
185
        mov     ecx, dword [ebp+PARTITION.FirstSector+4]
183
        mov     dword [eax+FAT.FirstSector+4], ecx
186
        mov     dword [eax+FAT.FirstSector+4], ecx
184
        mov     ecx, dword [ebp+PARTITION.Length]
187
        mov     ecx, dword [ebp+PARTITION.Length]
185
        mov     dword [eax+FAT.Length], ecx
188
        mov     dword [eax+FAT.Length], ecx
186
        mov     ecx, dword [ebp+PARTITION.Length+4]
189
        mov     ecx, dword [ebp+PARTITION.Length+4]
187
        mov     dword [eax+FAT.Length+4], ecx
190
        mov     dword [eax+FAT.Length+4], ecx
188
        mov     ecx, [ebp+PARTITION.Disk]
191
        mov     ecx, [ebp+PARTITION.Disk]
189
        mov     [eax+FAT.Disk], ecx
192
        mov     [eax+FAT.Disk], ecx
190
        mov     [eax+FAT.FSUserFunctions], fat_user_functions
193
        mov     [eax+FAT.FSUserFunctions], fat_user_functions
191
        or      [eax+FAT.fat_in_cache], -1
194
        or      [eax+FAT.fat_in_cache], -1
192
        mov     [eax+FAT.fat_change], 0
195
        mov     [eax+FAT.fat_change], 0
193
        push    ebp
196
        push    ebp
194
        mov     ebp, eax
197
        mov     ebp, eax
195
 
198
 
196
        lea     ecx, [ebp+FAT.Lock]
199
        lea     ecx, [ebp+FAT.Lock]
197
        call    mutex_init
200
        call    mutex_init
198
 
201
 
199
        movzx   eax, word [ebx+0xe]     ; sectors reserved
202
        movzx   eax, word [ebx+0xe]     ; sectors reserved
200
        mov     [ebp+FAT.FAT_START], eax
203
        mov     [ebp+FAT.FAT_START], eax
201
 
204
 
202
        movzx   eax, byte [ebx+0xd]     ; sectors per cluster
205
        movzx   eax, byte [ebx+0xd]     ; sectors per cluster
203
        mov     [ebp+FAT.SECTORS_PER_CLUSTER], eax
206
        mov     [ebp+FAT.SECTORS_PER_CLUSTER], eax
204
 
207
 
205
        movzx   ecx, word [ebx+0xb]     ; bytes per sector
208
        movzx   ecx, word [ebx+0xb]     ; bytes per sector
206
        mov     [ebp+FAT.BYTES_PER_SECTOR], ecx
209
        mov     [ebp+FAT.BYTES_PER_SECTOR], ecx
207
 
210
 
208
        movzx   eax, word [ebx+0x11]    ; count of rootdir entries (=0 fat32)
211
        movzx   eax, word [ebx+0x11]    ; count of rootdir entries (=0 fat32)
209
        shl     eax, 5                  ; mul 32
212
        shl     eax, 5                  ; mul 32
210
        dec     ecx
213
        dec     ecx
211
        add     eax, ecx                ; round up if not equal count
214
        add     eax, ecx                ; round up if not equal count
212
        inc     ecx                     ; bytes per sector
215
        inc     ecx                     ; bytes per sector
213
        xor     edx, edx
216
        xor     edx, edx
214
        div     ecx
217
        div     ecx
215
        mov     [ebp+FAT.ROOT_SECTORS], eax     ; count of rootdir sectors
218
        mov     [ebp+FAT.ROOT_SECTORS], eax     ; count of rootdir sectors
216
 
219
 
217
        movzx   eax, word [ebx+0x16]    ; sectors per fat <65536
220
        movzx   eax, word [ebx+0x16]    ; sectors per fat <65536
218
        test    eax, eax
221
        test    eax, eax
219
        jnz     @f
222
        jnz     @f
220
        mov     eax, [ebx+0x24]         ; sectors per fat
223
        mov     eax, [ebx+0x24]         ; sectors per fat
221
@@:
224
@@:
222
        mov     [ebp+FAT.SECTORS_PER_FAT], eax
225
        mov     [ebp+FAT.SECTORS_PER_FAT], eax
223
 
226
 
224
        movzx   eax, byte [ebx+0x10]    ; number of fats
227
        movzx   eax, byte [ebx+0x10]    ; number of fats
225
        mov     [ebp+FAT.NUMBER_OF_FATS], eax
228
        mov     [ebp+FAT.NUMBER_OF_FATS], eax
226
        mul     [ebp+FAT.SECTORS_PER_FAT]
229
        mul     [ebp+FAT.SECTORS_PER_FAT]
227
        test    edx, edx
230
        test    edx, edx
228
        jnz     .free_return0
231
        jnz     .free_return0
229
        add     eax, [ebp+FAT.FAT_START]
232
        add     eax, [ebp+FAT.FAT_START]
230
        jc      .free_return0
233
        jc      .free_return0
231
        mov     [ebp+FAT.ROOT_START], eax       ; rootdir = fat_start + fat_size * fat_count
234
        mov     [ebp+FAT.ROOT_START], eax       ; rootdir = fat_start + fat_size * fat_count
232
        add     eax, [ebp+FAT.ROOT_SECTORS]     ; rootdir sectors should be 0 on fat32
235
        add     eax, [ebp+FAT.ROOT_SECTORS]     ; rootdir sectors should be 0 on fat32
233
        jc      .free_return0
236
        jc      .free_return0
234
        mov     [ebp+FAT.DATA_START], eax       ; data area = rootdir + rootdir_size
237
        mov     [ebp+FAT.DATA_START], eax       ; data area = rootdir + rootdir_size
235
 
238
 
236
        movzx   eax, word [ebx+0x13]    ; total sector count <65536
239
        movzx   eax, word [ebx+0x13]    ; total sector count <65536
237
        test    eax, eax
240
        test    eax, eax
238
        jnz     @f
241
        jnz     @f
239
        mov     eax, [ebx+0x20]         ; total sector count
242
        mov     eax, [ebx+0x20]         ; total sector count
240
@@:
243
@@:
241
; total sector count must not exceed partition size
244
; total sector count must not exceed partition size
242
        cmp     dword [ebp+FAT.Length+4], 0
245
        cmp     dword [ebp+FAT.Length+4], 0
243
        jnz     @f
246
        jnz     @f
244
        cmp     eax, dword [ebp+FAT.Length]
247
        cmp     eax, dword [ebp+FAT.Length]
245
        ja      .free_return0
248
        ja      .free_return0
246
@@:
249
@@:
247
        mov     dword [ebp+FAT.Length], eax
250
        mov     dword [ebp+FAT.Length], eax
248
        and     dword [ebp+FAT.Length+4], 0
251
        and     dword [ebp+FAT.Length+4], 0
249
        sub     eax, [ebp+FAT.DATA_START]       ; eax = count of data sectors
252
        sub     eax, [ebp+FAT.DATA_START]       ; eax = count of data sectors
250
        jc      .free_return0
253
        jc      .free_return0
251
        xor     edx, edx
254
        xor     edx, edx
252
        div     [ebp+FAT.SECTORS_PER_CLUSTER]
255
        div     [ebp+FAT.SECTORS_PER_CLUSTER]
253
        inc     eax
256
        inc     eax
254
        mov     [ebp+FAT.LAST_CLUSTER], eax
257
        mov     [ebp+FAT.LAST_CLUSTER], eax
255
        dec     eax                     ; cluster count
258
        dec     eax                     ; cluster count
256
        jz      .free_return0
259
        jz      .free_return0
257
        mov     [ebp+FAT.fatStartScan], 2
260
        mov     [ebp+FAT.fatStartScan], 2
258
 
261
 
259
        ; limits by Microsoft Hardware White Paper v1.03
262
        ; limits by Microsoft Hardware White Paper v1.03
260
        cmp     eax, 4085               ; 0xff5
263
        cmp     eax, 4085               ; 0xff5
261
        jb      .fat12
264
        jb      .fat12
262
        cmp     eax, 65525              ; 0xfff5
265
        cmp     eax, 65525              ; 0xfff5
263
        jb      .fat16
266
        jb      .fat16
264
.fat32:
267
.fat32:
265
        mov     eax, [ebx+0x2c]         ; rootdir cluster
268
        mov     eax, [ebx+0x2c]         ; rootdir cluster
266
        mov     [ebp+FAT.ROOT_CLUSTER], eax
269
        mov     [ebp+FAT.ROOT_CLUSTER], eax
267
        movzx   eax, word [ebx+0x30]
270
        movzx   eax, word [ebx+0x30]
268
        mov     [ebp+FAT.ADR_FSINFO], eax
271
        mov     [ebp+FAT.ADR_FSINFO], eax
269
        push    ebx
272
        push    ebx
270
        add     ebx, 512
273
        add     ebx, 512
271
        call    fs_read32_sys
274
        call    fs_read32_sys
272
        test    eax, eax
275
        test    eax, eax
273
        jnz     @f
276
        jnz     @f
274
        mov     eax, [ebx+0x1ec]
277
        mov     eax, [ebx+0x1ec]
275
        cmp     eax, -1
278
        cmp     eax, -1
276
        jz      @f
279
        jz      @f
277
        mov     [ebp+FAT.fatStartScan], eax
280
        mov     [ebp+FAT.fatStartScan], eax
278
@@:
281
@@:
279
        pop     ebx
282
        pop     ebx
280
        mov     [ebp+FAT.fatRESERVED], 0x0FFFFFF6
283
        mov     [ebp+FAT.fatRESERVED], 0x0FFFFFF6
281
        mov     [ebp+FAT.fatBAD], 0x0FFFFFF7
284
        mov     [ebp+FAT.fatBAD], 0x0FFFFFF7
282
        mov     [ebp+FAT.fatEND], 0x0FFFFFF8
285
        mov     [ebp+FAT.fatEND], 0x0FFFFFF8
283
        mov     [ebp+FAT.fatMASK], 0x0FFFFFFF
286
        mov     [ebp+FAT.fatMASK], 0x0FFFFFFF
284
        mov     al, 32
287
        mov     al, 32
285
.fat_not_12_finalize:
288
.fat_not_12_finalize:
286
        mov     [ebp+FAT.fs_type], al
289
        mov     [ebp+FAT.fs_type], al
287
; For FAT16 and FAT32, allocate 512 bytes for FAT cache.
290
; For FAT16 and FAT32, allocate 512 bytes for FAT cache.
288
        mov     eax, 512
291
        mov     eax, 512
289
        call    malloc
292
        call    malloc
290
        test    eax, eax
293
        test    eax, eax
291
        jz      .free_return0
294
        jz      .free_return0
292
        mov     [ebp+FAT.fat_cache_ptr], eax
295
        mov     [ebp+FAT.fat_cache_ptr], eax
293
        mov     eax, ebp
296
        mov     eax, ebp
294
        pop     ebp
297
        pop     ebp
295
        ret
298
        ret
296
.fat16:
299
.fat16:
297
        and     [ebp+FAT.ROOT_CLUSTER], 0
300
        and     [ebp+FAT.ROOT_CLUSTER], 0
298
        mov     [ebp+FAT.fatRESERVED], 0x0000FFF6
301
        mov     [ebp+FAT.fatRESERVED], 0x0000FFF6
299
        mov     [ebp+FAT.fatBAD], 0x0000FFF7
302
        mov     [ebp+FAT.fatBAD], 0x0000FFF7
300
        mov     [ebp+FAT.fatEND], 0x0000FFF8
303
        mov     [ebp+FAT.fatEND], 0x0000FFF8
301
        mov     [ebp+FAT.fatMASK], 0x0000FFFF
304
        mov     [ebp+FAT.fatMASK], 0x0000FFFF
302
        mov     al, 16
305
        mov     al, 16
303
        jmp     .fat_not_12_finalize
306
        jmp     .fat_not_12_finalize
304
.fat12:
307
.fat12:
305
        and     [ebp+FAT.ROOT_CLUSTER], 0
308
        and     [ebp+FAT.ROOT_CLUSTER], 0
306
        mov     [ebp+FAT.fatRESERVED], 0xFF6
309
        mov     [ebp+FAT.fatRESERVED], 0xFF6
307
        mov     [ebp+FAT.fatBAD], 0xFF7
310
        mov     [ebp+FAT.fatBAD], 0xFF7
308
        mov     [ebp+FAT.fatEND], 0xFFF
311
        mov     [ebp+FAT.fatEND], 0xFFF
309
        mov     [ebp+FAT.fatMASK], 0xFFF
312
        mov     [ebp+FAT.fatMASK], 0xFFF
310
        mov     al, 12
313
        mov     al, 12
311
        mov     [ebp+FAT.fs_type], al
314
        mov     [ebp+FAT.fs_type], al
312
; For FAT12, allocate&read data for entire table:
315
; For FAT12, allocate&read data for entire table:
313
; calculate A = ALIGN_UP(NUM_CLUSTERS, 8),
316
; calculate A = ALIGN_UP(NUM_CLUSTERS, 8),
314
; calculatefatchain/restorefatchain will process A items,
317
; calculatefatchain/restorefatchain will process A items,
315
; allocate ALIGN_UP(A*3/2, 512) bytes for FAT table plus A*2 bytes for unpacked data.
318
; allocate ALIGN_UP(A*3/2, 512) bytes for FAT table plus A*2 bytes for unpacked data.
316
        mov     eax, [ebp+FAT.LAST_CLUSTER]
319
        mov     eax, [ebp+FAT.LAST_CLUSTER]
317
        and     eax, not 7
320
        and     eax, not 7
318
        add     eax, 8
321
        add     eax, 8
319
        mov     edx, eax
322
        mov     edx, eax
320
        lea     eax, [eax*3]
323
        lea     eax, [eax*3]
321
        add     eax, 512*2-1
324
        add     eax, 512*2-1
322
        shr     eax, 10
325
        shr     eax, 10
323
        shl     eax, 9
326
        shl     eax, 9
324
        lea     eax, [eax+edx*2]
327
        lea     eax, [eax+edx*2]
325
        call    malloc
328
        call    malloc
326
        test    eax, eax
329
        test    eax, eax
327
        jz      .free_return0
330
        jz      .free_return0
328
; Read ALIGN_UP(NUM_CLUSTERS*3/2, 512) bytes.
331
; Read ALIGN_UP(NUM_CLUSTERS*3/2, 512) bytes.
329
; Note that this can be less than allocated, this is ok,
332
; Note that this can be less than allocated, this is ok,
330
; overallocation simplifies calculatefatchain/restorefatchain.
333
; overallocation simplifies calculatefatchain/restorefatchain.
331
        push    ebx
334
        push    ebx
332
        mov     [ebp+FAT.fat_cache_ptr], eax
335
        mov     [ebp+FAT.fat_cache_ptr], eax
333
        mov     edx, [ebp+FAT.LAST_CLUSTER]
336
        mov     edx, [ebp+FAT.LAST_CLUSTER]
334
        lea     edx, [(edx+1)*3 + 512*2-1]
337
        lea     edx, [(edx+1)*3 + 512*2-1]
335
        shr     edx, 10
338
        shr     edx, 10
336
        xchg    eax, ebx
339
        xchg    eax, ebx
337
        xor     eax, eax
340
        xor     eax, eax
338
.read_fat:
341
.read_fat:
339
        push    eax
342
        push    eax
340
        add     eax, [ebp+FAT.FAT_START]
343
        add     eax, [ebp+FAT.FAT_START]
341
        call    fs_read32_sys
344
        call    fs_read32_sys
342
        test    eax, eax
345
        test    eax, eax
343
        pop     eax
346
        pop     eax
344
        jz      @f
347
        jz      @f
345
        dbgstr 'Failed to read FAT table'
348
        dbgstr 'Failed to read FAT table'
346
        mov     eax, [ebp+FAT.fat_cache_ptr]
349
        mov     eax, [ebp+FAT.fat_cache_ptr]
347
        call    free
350
        call    free
348
        pop     ebx
351
        pop     ebx
349
        jmp     .free_return0
352
        jmp     .free_return0
350
@@:
353
@@:
351
        add     ebx, 512
354
        add     ebx, 512
352
        inc     eax
355
        inc     eax
353
        cmp     eax, edx
356
        cmp     eax, edx
354
        jb      .read_fat
357
        jb      .read_fat
355
        mov     [ebp+FAT.fat12_unpacked_ptr], ebx
358
        mov     [ebp+FAT.fat12_unpacked_ptr], ebx
356
        call    calculatefatchain
359
        call    calculatefatchain
357
        pop     ebx
360
        pop     ebx
358
        mov     eax, ebp
361
        mov     eax, ebp
359
        pop     ebp
362
        pop     ebp
360
        ret
363
        ret
361
 
364
 
362
fat_free:
365
fat_free:
363
        push    eax
366
        push    eax
364
        mov     eax, [eax+FAT.fat_cache_ptr]
367
        mov     eax, [eax+FAT.fat_cache_ptr]
365
        call    free
368
        call    free
366
        pop     eax
369
        pop     eax
367
        jmp     free
370
        jmp     free
368
 
371
 
369
calculatefatchain:
372
calculatefatchain:
370
 
373
 
371
        pushad
374
        pushad
372
 
375
 
373
        mov     esi, [ebp+FAT.fat_cache_ptr]
376
        mov     esi, [ebp+FAT.fat_cache_ptr]
374
        mov     edi, [ebp+FAT.fat12_unpacked_ptr]
377
        mov     edi, [ebp+FAT.fat12_unpacked_ptr]
375
 
378
 
376
        mov     edx, [ebp+FAT.LAST_CLUSTER]
379
        mov     edx, [ebp+FAT.LAST_CLUSTER]
377
        and     edx, not 7
380
        and     edx, not 7
378
        lea     edx, [edi+(edx+8)*2]
381
        lea     edx, [edi+(edx+8)*2]
379
        push    edx
382
        push    edx
380
 
383
 
381
 fcnew:
384
 fcnew:
382
        mov     eax, dword [esi]
385
        mov     eax, dword [esi]
383
        mov     ebx, dword [esi+4]
386
        mov     ebx, dword [esi+4]
384
        mov     ecx, dword [esi+8]
387
        mov     ecx, dword [esi+8]
385
        mov     edx, ecx
388
        mov     edx, ecx
386
        shr     edx, 4;8 ok
389
        shr     edx, 4;8 ok
387
        shr     dx, 4;7 ok
390
        shr     dx, 4;7 ok
388
        xor     ch, ch
391
        xor     ch, ch
389
        shld    ecx, ebx, 20;6 ok
392
        shld    ecx, ebx, 20;6 ok
390
        shr     cx, 4;5 ok
393
        shr     cx, 4;5 ok
391
        shld    ebx, eax, 12
394
        shld    ebx, eax, 12
392
        and     ebx, 0x0fffffff;4 ok
395
        and     ebx, 0x0fffffff;4 ok
393
        shr     bx, 4;3 ok
396
        shr     bx, 4;3 ok
394
        shl     eax, 4
397
        shl     eax, 4
395
        and     eax, 0x0fffffff;2 ok
398
        and     eax, 0x0fffffff;2 ok
396
        shr     ax, 4;1 ok
399
        shr     ax, 4;1 ok
397
        mov     dword [edi], eax
400
        mov     dword [edi], eax
398
        mov     dword [edi+4], ebx
401
        mov     dword [edi+4], ebx
399
        mov     dword [edi+8], ecx
402
        mov     dword [edi+8], ecx
400
        mov     dword [edi+12], edx
403
        mov     dword [edi+12], edx
401
        add     edi, 16
404
        add     edi, 16
402
        add     esi, 12
405
        add     esi, 12
403
 
406
 
404
        cmp     edi, [esp]
407
        cmp     edi, [esp]
405
        jnz     fcnew
408
        jnz     fcnew
406
        pop     eax
409
        pop     eax
407
 
410
 
408
        popad
411
        popad
409
        ret
412
        ret
410
 
413
 
411
 
414
 
412
restorefatchain:   ; restore fat chain
415
restorefatchain:   ; restore fat chain
413
 
416
 
414
        pushad
417
        pushad
415
 
418
 
416
        mov     esi, [ebp+FAT.fat12_unpacked_ptr]
419
        mov     esi, [ebp+FAT.fat12_unpacked_ptr]
417
        mov     edi, [ebp+FAT.fat_cache_ptr]
420
        mov     edi, [ebp+FAT.fat_cache_ptr]
418
 
421
 
419
        mov     edx, [ebp+FAT.LAST_CLUSTER]
422
        mov     edx, [ebp+FAT.LAST_CLUSTER]
420
        and     edx, not 7
423
        and     edx, not 7
421
        lea     edx, [esi+(edx+8)*2]
424
        lea     edx, [esi+(edx+8)*2]
422
 
425
 
423
  fcnew2:
426
  fcnew2:
424
        mov     eax, dword [esi]
427
        mov     eax, dword [esi]
425
        mov     ebx, dword [esi+4]
428
        mov     ebx, dword [esi+4]
426
        shl     ax, 4
429
        shl     ax, 4
427
        shl     eax, 4
430
        shl     eax, 4
428
        shl     bx, 4
431
        shl     bx, 4
429
        shr     ebx, 4
432
        shr     ebx, 4
430
        shrd    eax, ebx, 8
433
        shrd    eax, ebx, 8
431
        shr     ebx, 8
434
        shr     ebx, 8
432
        mov     dword [edi], eax
435
        mov     dword [edi], eax
433
        mov     word [edi+4], bx
436
        mov     word [edi+4], bx
434
        add     edi, 6
437
        add     edi, 6
435
        add     esi, 8
438
        add     esi, 8
436
 
439
 
437
        cmp     esi, edx
440
        cmp     esi, edx
438
        jb      fcnew2
441
        jb      fcnew2
439
 
442
 
440
        mov     esi, [ebp+FAT.NUMBER_OF_FATS]
443
        mov     esi, [ebp+FAT.NUMBER_OF_FATS]
441
        mov     edx, [ebp+FAT.LAST_CLUSTER]
444
        mov     edx, [ebp+FAT.LAST_CLUSTER]
442
        lea     edx, [(edx+1)*3 + 512*2-1]
445
        lea     edx, [(edx+1)*3 + 512*2-1]
443
        shr     edx, 10
446
        shr     edx, 10
444
        push    [ebp+FAT.FAT_START]
447
        push    [ebp+FAT.FAT_START]
445
 
448
 
446
.write_fats:
449
.write_fats:
447
        xor     eax, eax
450
        xor     eax, eax
448
        mov     ebx, [ebp+FAT.fat_cache_ptr]
451
        mov     ebx, [ebp+FAT.fat_cache_ptr]
449
.loop1:
452
.loop1:
450
        push    eax
453
        push    eax
451
        add     eax, [esp+4]
454
        add     eax, [esp+4]
452
        call    fs_write32_sys
455
        call    fs_write32_sys
453
        test    eax, eax
456
        test    eax, eax
454
        pop     eax
457
        pop     eax
455
        jnz     .fail
458
        jnz     .fail
456
        add     ebx, 512
459
        add     ebx, 512
457
        inc     eax
460
        inc     eax
458
        cmp     eax, edx
461
        cmp     eax, edx
459
        jb      .loop1
462
        jb      .loop1
460
        pop     eax
463
        pop     eax
461
        add     eax, [ebp+FAT.SECTORS_PER_FAT]
464
        add     eax, [ebp+FAT.SECTORS_PER_FAT]
462
        push    eax
465
        push    eax
463
        dec     esi
466
        dec     esi
464
        jnz     .write_fats
467
        jnz     .write_fats
465
        pop     eax
468
        pop     eax
466
 
469
 
467
        popad
470
        popad
468
        ret
471
        ret
469
.fail:
472
.fail:
470
        dbgstr 'Failed to save FAT'
473
        dbgstr 'Failed to save FAT'
471
        popad
474
        popad
472
        ret
475
        ret
473
 
476
 
474
iglobal
477
iglobal
475
label fat_legal_chars byte
478
label fat_legal_chars byte
476
; 0 = not allowed
479
; 0 = not allowed
477
; 1 = allowed only in long names
480
; 1 = allowed only in long names
478
; 3 = allowed
481
; 3 = allowed
479
        times 32 db 0
482
        times 32 db 0
480
;                 ! " # $ % & ' ( ) * + , - . /
483
;                 ! " # $ % & ' ( ) * + , - . /
481
        db      1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0
484
        db      1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0
482
;               0 1 2 3 4 5 6 7 8 9 : ; < = > ?
485
;               0 1 2 3 4 5 6 7 8 9 : ; < = > ?
483
        db      3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0
486
        db      3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0
484
;               @ A B C D E F G H I J K L M N O
487
;               @ A B C D E F G H I J K L M N O
485
        db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
488
        db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
486
;               P Q R S T U V W X Y Z [ \ ] ^ _
489
;               P Q R S T U V W X Y Z [ \ ] ^ _
487
        db      3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3
490
        db      3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3
488
;               ` a b c d e f g h i j k l m n o
491
;               ` a b c d e f g h i j k l m n o
489
        db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
492
        db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
490
;               p q r s t u v w x y z { | } ~
493
;               p q r s t u v w x y z { | } ~
491
        db      3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0
494
        db      3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0
492
endg
495
endg
493
 
496
 
494
fat_name_is_legal:
497
fat_name_is_legal:
495
; in: esi->(long) name
498
; in: esi->(long) name
496
; out: CF set <=> legal
499
; out: CF set <=> legal
497
; destroys eax
500
; destroys eax
498
        push    esi
501
        push    esi
499
        xor     eax, eax
502
        xor     eax, eax
500
@@:
503
@@:
501
        lodsb
504
        lodsb
502
        test    al, al
505
        test    al, al
503
        jz      .done
506
        jz      .done
504
        cmp     al, 80h
507
        cmp     al, 80h
505
        jae     .big
508
        jae     .big
506
        test    [fat_legal_chars+eax], 1
509
        test    [fat_legal_chars+eax], 1
507
        jnz     @b
510
        jnz     @b
508
.err:
511
.err:
509
        pop     esi
512
        pop     esi
510
        clc
513
        clc
511
        ret
514
        ret
512
.big:
515
.big:
513
; 0x80-0xAF, 0xE0-0xEF
516
; 0x80-0xAF, 0xE0-0xEF
514
        cmp     al, 0xB0
517
        cmp     al, 0xB0
515
        jb      @b
518
        jb      @b
516
        cmp     al, 0xE0
519
        cmp     al, 0xE0
517
        jb      .err
520
        jb      .err
518
        cmp     al, 0xF0
521
        cmp     al, 0xF0
519
        jb      @b
522
        jb      @b
520
        jmp     .err
523
        jmp     .err
521
.done:
524
.done:
522
        sub     esi, [esp]
525
        sub     esi, [esp]
523
        cmp     esi, 257
526
        cmp     esi, 257
524
        pop     esi
527
        pop     esi
525
        ret
528
        ret
526
 
529
 
527
fat_next_short_name:
530
fat_next_short_name:
528
; in: edi->8+3 name
531
; in: edi->8+3 name
529
; out: name corrected
532
; out: name corrected
530
;      CF=1 <=> error
533
;      CF=1 <=> error
531
        pushad
534
        pushad
532
        mov     ecx, 8
535
        mov     ecx, 8
533
        mov     al, '~'
536
        mov     al, '~'
534
        std
537
        std
535
        push    edi
538
        push    edi
536
        add     edi, 7
539
        add     edi, 7
537
        repnz scasb
540
        repnz scasb
538
        pop     edi
541
        pop     edi
539
        cld
542
        cld
540
        jz      .tilde
543
        jz      .tilde
541
; tilde is not found, insert "~1" at end
544
; tilde is not found, insert "~1" at end
542
        add     edi, 6
545
        add     edi, 6
543
        cmp     word [edi], '  '
546
        cmp     word [edi], '  '
544
        jnz     .insert_tilde
547
        jnz     .insert_tilde
545
@@:
548
@@:
546
        dec     edi
549
        dec     edi
547
        cmp     byte [edi], ' '
550
        cmp     byte [edi], ' '
548
        jz      @b
551
        jz      @b
549
        inc     edi
552
        inc     edi
550
.insert_tilde:
553
.insert_tilde:
551
        mov     word [edi], '~1'
554
        mov     word [edi], '~1'
552
        popad
555
        popad
553
        clc
556
        clc
554
        ret
557
        ret
555
.tilde:
558
.tilde:
556
        push    edi
559
        push    edi
557
        add     edi, 7
560
        add     edi, 7
558
        xor     ecx, ecx
561
        xor     ecx, ecx
559
@@:
562
@@:
560
; after tilde may be only digits and trailing spaces
563
; after tilde may be only digits and trailing spaces
561
        cmp     byte [edi], '~'
564
        cmp     byte [edi], '~'
562
        jz      .break
565
        jz      .break
563
        cmp     byte [edi], ' '
566
        cmp     byte [edi], ' '
564
        jz      .space
567
        jz      .space
565
        cmp     byte [edi], '9'
568
        cmp     byte [edi], '9'
566
        jnz     .found
569
        jnz     .found
567
        dec     edi
570
        dec     edi
568
        jmp     @b
571
        jmp     @b
569
.space:
572
.space:
570
        dec     edi
573
        dec     edi
571
        inc     ecx
574
        inc     ecx
572
        jmp     @b
575
        jmp     @b
573
.found:
576
.found:
574
        inc     byte [edi]
577
        inc     byte [edi]
575
        add     dword [esp], 8
578
        add     dword [esp], 8
576
        jmp     .zerorest
579
        jmp     .zerorest
577
.break:
580
.break:
578
        jecxz   .noplace
581
        jecxz   .noplace
579
        inc     edi
582
        inc     edi
580
        mov     al, '1'
583
        mov     al, '1'
581
@@:
584
@@:
582
        xchg    al, [edi]
585
        xchg    al, [edi]
583
        inc     edi
586
        inc     edi
584
        cmp     al, ' '
587
        cmp     al, ' '
585
        mov     al, '0'
588
        mov     al, '0'
586
        jnz     @b
589
        jnz     @b
587
.succ:
590
.succ:
588
        pop     edi
591
        pop     edi
589
        popad
592
        popad
590
        clc
593
        clc
591
        ret
594
        ret
592
.noplace:
595
.noplace:
593
        dec     edi
596
        dec     edi
594
        cmp     edi, [esp]
597
        cmp     edi, [esp]
595
        jz      .err
598
        jz      .err
596
        add     dword [esp], 8
599
        add     dword [esp], 8
597
        mov     word [edi], '~1'
600
        mov     word [edi], '~1'
598
        inc     edi
601
        inc     edi
599
        inc     edi
602
        inc     edi
600
@@:
603
@@:
601
        mov     byte [edi], '0'
604
        mov     byte [edi], '0'
602
.zerorest:
605
.zerorest:
603
        inc     edi
606
        inc     edi
604
        cmp     edi, [esp]
607
        cmp     edi, [esp]
605
        jb      @b
608
        jb      @b
606
        pop     edi
609
        pop     edi
607
        popad
610
        popad
608
        ;clc    ; automatically
611
        ;clc    ; automatically
609
        ret
612
        ret
610
.err:
613
.err:
611
        pop     edi
614
        pop     edi
612
        popad
615
        popad
613
        stc
616
        stc
614
        ret
617
        ret
615
 
618
 
616
fat_gen_short_name:
619
fat_gen_short_name:
617
; in: esi->long name
620
; in: esi->long name
618
;     edi->buffer (8+3=11 chars)
621
;     edi->buffer (8+3=11 chars)
619
; out: buffer filled
622
; out: buffer filled
620
        pushad
623
        pushad
621
        mov     eax, '    '
624
        mov     eax, '    '
622
        push    edi
625
        push    edi
623
        stosd
626
        stosd
624
        stosd
627
        stosd
625
        stosd
628
        stosd
626
        pop     edi
629
        pop     edi
627
        xor     eax, eax
630
        xor     eax, eax
628
        movi    ebx, 8
631
        movi    ebx, 8
629
        lea     ecx, [edi+8]
632
        lea     ecx, [edi+8]
630
.loop:
633
.loop:
631
        lodsb
634
        lodsb
632
        test    al, al
635
        test    al, al
633
        jz      .done
636
        jz      .done
634
        call    char_toupper
637
        call    char_toupper
635
        cmp     al, ' '
638
        cmp     al, ' '
636
        jz      .space
639
        jz      .space
637
        cmp     al, 80h
640
        cmp     al, 80h
638
        ja      .big
641
        ja      .big
639
        test    [fat_legal_chars+eax], 2
642
        test    [fat_legal_chars+eax], 2
640
        jnz     .symbol
643
        jnz     .symbol
641
.inv_symbol:
644
.inv_symbol:
642
        mov     al, '_'
645
        mov     al, '_'
643
        or      bh, 1
646
        or      bh, 1
644
.symbol:
647
.symbol:
645
        cmp     al, '.'
648
        cmp     al, '.'
646
        jz      .dot
649
        jz      .dot
647
.normal_symbol:
650
.normal_symbol:
648
        dec     bl
651
        dec     bl
649
        jns     .store
652
        jns     .store
650
        mov     bl, 0
653
        mov     bl, 0
651
.space:
654
.space:
652
        or      bh, 1
655
        or      bh, 1
653
        jmp     .loop
656
        jmp     .loop
654
.store:
657
.store:
655
        stosb
658
        stosb
656
        jmp     .loop
659
        jmp     .loop
657
.big:
660
.big:
658
        cmp     al, 0xB0
661
        cmp     al, 0xB0
659
        jb      .normal_symbol
662
        jb      .normal_symbol
660
        cmp     al, 0xE0
663
        cmp     al, 0xE0
661
        jb      .inv_symbol
664
        jb      .inv_symbol
662
        cmp     al, 0xF0
665
        cmp     al, 0xF0
663
        jb      .normal_symbol
666
        jb      .normal_symbol
664
        jmp     .inv_symbol
667
        jmp     .inv_symbol
665
.dot:
668
.dot:
666
        test    bh, 2
669
        test    bh, 2
667
        jz      .firstdot
670
        jz      .firstdot
668
        pop     ebx
671
        pop     ebx
669
        add     ebx, edi
672
        add     ebx, edi
670
        sub     ebx, ecx
673
        sub     ebx, ecx
671
        push    ebx
674
        push    ebx
672
        cmp     ebx, ecx
675
        cmp     ebx, ecx
673
        jb      @f
676
        jb      @f
674
        pop     ebx
677
        pop     ebx
675
        push    ecx
678
        push    ecx
676
@@:
679
@@:
677
        cmp     edi, ecx
680
        cmp     edi, ecx
678
        jbe     .skip
681
        jbe     .skip
679
@@:
682
@@:
680
        dec     edi
683
        dec     edi
681
        mov     al, [edi]
684
        mov     al, [edi]
682
        dec     ebx
685
        dec     ebx
683
        mov     [ebx], al
686
        mov     [ebx], al
684
        mov     byte [edi], ' '
687
        mov     byte [edi], ' '
685
        cmp     edi, ecx
688
        cmp     edi, ecx
686
        ja      @b
689
        ja      @b
687
.skip:
690
.skip:
688
        mov     bh, 3
691
        mov     bh, 3
689
        jmp     @f
692
        jmp     @f
690
.firstdot:
693
.firstdot:
691
        cmp     bl, 8
694
        cmp     bl, 8
692
        jz      .space
695
        jz      .space
693
        push    edi
696
        push    edi
694
        or      bh, 2
697
        or      bh, 2
695
@@:
698
@@:
696
        mov     edi, ecx
699
        mov     edi, ecx
697
        mov     bl, 3
700
        mov     bl, 3
698
        jmp     .loop
701
        jmp     .loop
699
.done:
702
.done:
700
        test    bh, 2
703
        test    bh, 2
701
        jz      @f
704
        jz      @f
702
        pop     edi
705
        pop     edi
703
@@:
706
@@:
704
        lea     edi, [ecx-8]
707
        lea     edi, [ecx-8]
705
        test    bh, 1
708
        test    bh, 1
706
        jz      @f
709
        jz      @f
707
        call    fat_next_short_name
710
        call    fat_next_short_name
708
@@:
711
@@:
709
        popad
712
        popad
710
        ret
713
        ret
711
 
714
 
712
fat12_free_space:
715
fat12_free_space:
713
;---------------------------------------------
716
;---------------------------------------------
714
;
717
;
715
; returns free space in edi
718
; returns free space in edi
716
; rewr.by Mihasik
719
; rewr.by Mihasik
717
;---------------------------------------------
720
;---------------------------------------------
718
 
721
 
719
        push    eax ebx ecx
722
        push    eax ebx ecx
720
 
723
 
721
        mov     edi, [ebp+FAT.fat12_unpacked_ptr];start of FAT
724
        mov     edi, [ebp+FAT.fat12_unpacked_ptr];start of FAT
722
        xor     ax, ax;Free cluster=0x0000 in FAT
725
        xor     ax, ax;Free cluster=0x0000 in FAT
723
        xor     ebx, ebx;counter
726
        xor     ebx, ebx;counter
724
        mov     ecx, [ebp+FAT.LAST_CLUSTER]
727
        mov     ecx, [ebp+FAT.LAST_CLUSTER]
725
        inc     ecx
728
        inc     ecx
726
        cld
729
        cld
727
    rdfs1:
730
    rdfs1:
728
        repne scasw
731
        repne scasw
729
        jnz     rdfs2 ;if last cluster not 0
732
        jnz     rdfs2 ;if last cluster not 0
730
        inc     ebx
733
        inc     ebx
731
        test    ecx, ecx
734
        test    ecx, ecx
732
        jnz     rdfs1
735
        jnz     rdfs1
733
    rdfs2:
736
    rdfs2:
734
        shl     ebx, 9;free clusters*512
737
        shl     ebx, 9;free clusters*512
735
        mov     edi, ebx
738
        mov     edi, ebx
736
 
739
 
737
        pop     ecx ebx eax
740
        pop     ecx ebx eax
738
        ret
741
        ret
739
 
742
 
740
 
743
 
741
 
744
 
742
set_FAT:
745
set_FAT:
743
;--------------------------------
746
;--------------------------------
744
; input  : EAX = cluster
747
; input  : EAX = cluster
745
;          EDX = value to save
748
;          EDX = value to save
746
;          EBP = pointer to FAT structure
749
;          EBP = pointer to FAT structure
747
; output : EDX = old value
750
; output : EDX = old value
748
;--------------------------------
751
;--------------------------------
749
; out: CF set <=> error
752
; out: CF set <=> error
750
        push    eax ebx esi
753
        push    eax ebx esi
751
 
754
 
752
        cmp     eax, 2
755
        cmp     eax, 2
753
        jb      sfc_error
756
        jb      sfc_error
754
        cmp     eax, [ebp+FAT.LAST_CLUSTER]
757
        cmp     eax, [ebp+FAT.LAST_CLUSTER]
755
        ja      sfc_error
758
        ja      sfc_error
756
        cmp     [ebp+FAT.fs_type], 12
759
        cmp     [ebp+FAT.fs_type], 12
757
        je      set_FAT12
760
        je      set_FAT12
758
        cmp     [ebp+FAT.fs_type], 16
761
        cmp     [ebp+FAT.fs_type], 16
759
        je      sfc_1
762
        je      sfc_1
760
        add     eax, eax
763
        add     eax, eax
761
  sfc_1:
764
  sfc_1:
762
        add     eax, eax
765
        add     eax, eax
763
        mov     esi, 511
766
        mov     esi, 511
764
        and     esi, eax        ; esi = position in fat sector
767
        and     esi, eax        ; esi = position in fat sector
765
        shr     eax, 9          ; eax = fat sector
768
        shr     eax, 9          ; eax = fat sector
766
        add     eax, [ebp+FAT.FAT_START]
769
        add     eax, [ebp+FAT.FAT_START]
767
        mov     ebx, [ebp+FAT.fat_cache_ptr]
770
        mov     ebx, [ebp+FAT.fat_cache_ptr]
768
 
771
 
769
        cmp     eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
772
        cmp     eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
770
        je      sfc_in_cache    ; yes
773
        je      sfc_in_cache    ; yes
771
 
774
 
772
        cmp     [ebp+FAT.fat_change], 0; is fat changed?
775
        cmp     [ebp+FAT.fat_change], 0; is fat changed?
773
        je      sfc_no_change   ; no
776
        je      sfc_no_change   ; no
774
        call    write_fat_sector; yes. write it into disk
777
        call    write_fat_sector; yes. write it into disk
775
        jc      sfc_error
778
        jc      sfc_error
776
 
779
 
777
  sfc_no_change:
780
  sfc_no_change:
778
        mov     [ebp+FAT.fat_in_cache], eax; save fat sector
781
        mov     [ebp+FAT.fat_in_cache], eax; save fat sector
779
        call    fs_read32_sys
782
        call    fs_read32_sys
780
        test    eax, eax
783
        test    eax, eax
781
        jne     sfc_error
784
        jne     sfc_error
782
 
785
 
783
 
786
 
784
  sfc_in_cache:
787
  sfc_in_cache:
785
        cmp     [ebp+FAT.fs_type], 16
788
        cmp     [ebp+FAT.fs_type], 16
786
        jne     sfc_test32
789
        jne     sfc_test32
787
 
790
 
788
  sfc_set16:
791
  sfc_set16:
789
        xchg    [ebx+esi], dx   ; save new value and get old value
792
        xchg    [ebx+esi], dx   ; save new value and get old value
790
        jmp     sfc_write
793
        jmp     sfc_write
791
 
794
 
792
  sfc_test32:
795
  sfc_test32:
793
        mov     eax, [ebp+FAT.fatMASK]
796
        mov     eax, [ebp+FAT.fatMASK]
794
 
797
 
795
  sfc_set32:
798
  sfc_set32:
796
        and     edx, eax
799
        and     edx, eax
797
        xor     eax, -1         ; mask for high bits
800
        xor     eax, -1         ; mask for high bits
798
        and     eax, [ebx+esi]  ; get high 4 bits
801
        and     eax, [ebx+esi]  ; get high 4 bits
799
        or      eax, edx
802
        or      eax, edx
800
        mov     edx, [ebx+esi]  ; get old value
803
        mov     edx, [ebx+esi]  ; get old value
801
        mov     [ebx+esi], eax  ; save new value
804
        mov     [ebx+esi], eax  ; save new value
802
 
805
 
803
  sfc_write:
806
  sfc_write:
804
        mov     [ebp+FAT.fat_change], 1; fat has changed
807
        mov     [ebp+FAT.fat_change], 1; fat has changed
805
 
808
 
806
  sfc_nonzero:
809
  sfc_nonzero:
807
        and     edx, [ebp+FAT.fatMASK]
810
        and     edx, [ebp+FAT.fatMASK]
808
 
811
 
809
  sfc_return:
812
  sfc_return:
810
        pop     esi ebx eax
813
        pop     esi ebx eax
811
        ret
814
        ret
812
  sfc_error:
815
  sfc_error:
813
        stc
816
        stc
814
        jmp     sfc_return
817
        jmp     sfc_return
815
 
818
 
816
  set_FAT12:
819
  set_FAT12:
817
        test    edx, 0xF000
820
        test    edx, 0xF000
818
        jnz     sfc_error
821
        jnz     sfc_error
819
        mov     ebx, [ebp+FAT.fat12_unpacked_ptr]
822
        mov     ebx, [ebp+FAT.fat12_unpacked_ptr]
820
        xchg    [ebx+eax*2], dx
823
        xchg    [ebx+eax*2], dx
821
        mov     [ebp+FAT.fat_change], 1
824
        mov     [ebp+FAT.fat_change], 1
822
        pop     esi ebx eax
825
        pop     esi ebx eax
823
        clc
826
        clc
824
        ret
827
        ret
825
 
828
 
826
get_FAT:
829
get_FAT:
827
;--------------------------------
830
;--------------------------------
828
; input  : EAX = cluster
831
; input  : EAX = cluster
829
;          EBP = pointer to FAT structure
832
;          EBP = pointer to FAT structure
830
; output : EAX = next cluster
833
; output : EAX = next cluster
831
;--------------------------------
834
;--------------------------------
832
; out: CF set <=> error
835
; out: CF set <=> error
833
        push    ebx esi
836
        push    ebx esi
834
 
837
 
835
        cmp     [ebp+FAT.fs_type], 12
838
        cmp     [ebp+FAT.fs_type], 12
836
        je      get_FAT12
839
        je      get_FAT12
837
 
840
 
838
        cmp     [ebp+FAT.fs_type], 16
841
        cmp     [ebp+FAT.fs_type], 16
839
        je      gfc_1
842
        je      gfc_1
840
        add     eax, eax
843
        add     eax, eax
841
  gfc_1:
844
  gfc_1:
842
        add     eax, eax
845
        add     eax, eax
843
        mov     esi, 511
846
        mov     esi, 511
844
        and     esi, eax        ; esi = position in fat sector
847
        and     esi, eax        ; esi = position in fat sector
845
        shr     eax, 9          ; eax = fat sector
848
        shr     eax, 9          ; eax = fat sector
846
        add     eax, [ebp+FAT.FAT_START]
849
        add     eax, [ebp+FAT.FAT_START]
847
        mov     ebx, [ebp+FAT.fat_cache_ptr]
850
        mov     ebx, [ebp+FAT.fat_cache_ptr]
848
 
851
 
849
        cmp     eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
852
        cmp     eax, [ebp+FAT.fat_in_cache]; is fat sector already in memory?
850
        je      gfc_in_cache
853
        je      gfc_in_cache
851
 
854
 
852
        cmp     [ebp+FAT.fat_change], 0; is fat changed?
855
        cmp     [ebp+FAT.fat_change], 0; is fat changed?
853
        je      gfc_no_change   ; no
856
        je      gfc_no_change   ; no
854
        call    write_fat_sector; yes. write it into disk
857
        call    write_fat_sector; yes. write it into disk
855
        jc      hd_error_01
858
        jc      hd_error_01
856
 
859
 
857
  gfc_no_change:
860
  gfc_no_change:
858
        mov     [ebp+FAT.fat_in_cache], eax
861
        mov     [ebp+FAT.fat_in_cache], eax
859
        call    fs_read32_sys
862
        call    fs_read32_sys
860
        test    eax, eax
863
        test    eax, eax
861
        jne     hd_error_01
864
        jne     hd_error_01
862
 
865
 
863
  gfc_in_cache:
866
  gfc_in_cache:
864
        mov     eax, [ebx+esi]
867
        mov     eax, [ebx+esi]
865
        and     eax, [ebp+FAT.fatMASK]
868
        and     eax, [ebp+FAT.fatMASK]
866
  gfc_return:
869
  gfc_return:
867
        pop     esi ebx
870
        pop     esi ebx
868
        ret
871
        ret
869
 hd_error_01:
872
 hd_error_01:
870
        stc
873
        stc
871
        jmp     gfc_return
874
        jmp     gfc_return
872
 
875
 
873
get_FAT12:
876
get_FAT12:
874
        mov     ebx, [ebp+FAT.fat12_unpacked_ptr]
877
        mov     ebx, [ebp+FAT.fat12_unpacked_ptr]
875
        movzx   eax, word [ebx+eax*2]
878
        movzx   eax, word [ebx+eax*2]
876
        pop     esi ebx
879
        pop     esi ebx
877
        clc
880
        clc
878
        ret
881
        ret
879
 
882
 
880
 
883
 
881
get_free_FAT:
884
get_free_FAT:
882
;-----------------------------------------------------------
885
;-----------------------------------------------------------
883
; output : if CARRY=0 EAX = # first cluster found free
886
; output : if CARRY=0 EAX = # first cluster found free
884
;          if CARRY=1 disk full
887
;          if CARRY=1 disk full
885
; Note   : for more speed need to use fat_cache directly
888
; Note   : for more speed need to use fat_cache directly
886
;-----------------------------------------------------------
889
;-----------------------------------------------------------
887
        push    ecx
890
        push    ecx
888
        mov     ecx, [ebp+FAT.LAST_CLUSTER]; counter for full disk
891
        mov     ecx, [ebp+FAT.LAST_CLUSTER]; counter for full disk
889
        mov     eax, [ebp+FAT.fatStartScan]
892
        mov     eax, [ebp+FAT.fatStartScan]
890
        cmp     [ebp+FAT.fs_type], 12
893
        cmp     [ebp+FAT.fs_type], 12
891
        jz      get_free_FAT12
894
        jz      get_free_FAT12
892
        dec     ecx
895
        dec     ecx
893
        cmp     eax, 2
896
        cmp     eax, 2
894
        jb      gff_reset
897
        jb      gff_reset
895
 
898
 
896
  gff_test:
899
  gff_test:
897
        cmp     eax, [ebp+FAT.LAST_CLUSTER]; if above last cluster start at cluster 2
900
        cmp     eax, [ebp+FAT.LAST_CLUSTER]; if above last cluster start at cluster 2
898
        jbe     gff_in_range
901
        jbe     gff_in_range
899
  gff_reset:
902
  gff_reset:
900
        mov     eax, 2
903
        mov     eax, 2
901
 
904
 
902
  gff_in_range:
905
  gff_in_range:
903
        push    eax
906
        push    eax
904
        call    get_FAT         ; get cluster state
907
        call    get_FAT         ; get cluster state
905
        jc      gff_not_found_1
908
        jc      gff_not_found_1
906
 
909
 
907
        test    eax, eax        ; is it free?
910
        test    eax, eax        ; is it free?
908
        pop     eax
911
        pop     eax
909
        je      gff_found       ; yes
912
        je      gff_found       ; yes
910
        inc     eax             ; next cluster
913
        inc     eax             ; next cluster
911
        dec     ecx             ; is all checked?
914
        dec     ecx             ; is all checked?
912
        jnz     gff_test        ; no
915
        jnz     gff_test        ; no
913
 
916
 
914
  gff_not_found:
917
  gff_not_found:
915
        pop     ecx             ; yes. disk is full
918
        pop     ecx             ; yes. disk is full
916
        stc
919
        stc
917
        ret
920
        ret
918
 
921
 
919
  gff_not_found_1:
922
  gff_not_found_1:
920
        pop     eax
923
        pop     eax
921
        jmp     gff_not_found
924
        jmp     gff_not_found
922
 
925
 
923
  gff_found:
926
  gff_found:
924
        lea     ecx, [eax+1]
927
        lea     ecx, [eax+1]
925
        mov     [ebp+FAT.fatStartScan], ecx
928
        mov     [ebp+FAT.fatStartScan], ecx
926
        pop     ecx
929
        pop     ecx
927
        clc
930
        clc
928
        ret
931
        ret
929
 
932
 
930
get_free_FAT12:
933
get_free_FAT12:
931
        push    edx edi
934
        push    edx edi
932
        mov     edi, [ebp+FAT.fat12_unpacked_ptr]
935
        mov     edi, [ebp+FAT.fat12_unpacked_ptr]
933
        cmp     eax, 2
936
        cmp     eax, 2
934
        jb      .reset
937
        jb      .reset
935
        cmp     eax, ecx
938
        cmp     eax, ecx
936
        jbe     @f
939
        jbe     @f
937
.reset:
940
.reset:
938
        mov     eax, 2
941
        mov     eax, 2
939
@@:
942
@@:
940
        mov     edx, eax
943
        mov     edx, eax
941
        lea     edi, [edi+eax*2]
944
        lea     edi, [edi+eax*2]
942
        sub     ecx, eax
945
        sub     ecx, eax
943
        inc     ecx
946
        inc     ecx
944
        xor     eax, eax
947
        xor     eax, eax
945
        repnz scasw
948
        repnz scasw
946
        jz      .found
949
        jz      .found
947
        cmp     edx, 2
950
        cmp     edx, 2
948
        jz      .notfound
951
        jz      .notfound
949
        mov     edi, [ebp+FAT.fat12_unpacked_ptr]
952
        mov     edi, [ebp+FAT.fat12_unpacked_ptr]
950
        lea     ecx, [edx-2]
953
        lea     ecx, [edx-2]
951
        repnz scasw
954
        repnz scasw
952
        jnz     .notfound
955
        jnz     .notfound
953
.found:
956
.found:
954
        sub     edi, [ebp+FAT.fat12_unpacked_ptr]
957
        sub     edi, [ebp+FAT.fat12_unpacked_ptr]
955
        shr     edi, 1
958
        shr     edi, 1
956
        mov     [ebp+FAT.fatStartScan], edi
959
        mov     [ebp+FAT.fatStartScan], edi
957
        lea     eax, [edi-1]
960
        lea     eax, [edi-1]
958
        pop     edi edx ecx
961
        pop     edi edx ecx
959
        ret
962
        ret
960
.notfound:
963
.notfound:
961
        pop     edi edx ecx
964
        pop     edi edx ecx
962
        stc
965
        stc
963
        ret
966
        ret
964
 
967
 
965
 
968
 
966
write_fat_sector:
969
write_fat_sector:
967
;-----------------------------------------------------------
970
;-----------------------------------------------------------
968
; write changed fat to disk
971
; write changed fat to disk
969
;-----------------------------------------------------------
972
;-----------------------------------------------------------
970
        push    eax ebx ecx
973
        push    eax ebx ecx
971
 
974
 
972
        mov     [ebp+FAT.fat_change], 0
975
        mov     [ebp+FAT.fat_change], 0
973
        mov     eax, [ebp+FAT.fat_in_cache]
976
        mov     eax, [ebp+FAT.fat_in_cache]
974
        cmp     eax, -1
977
        cmp     eax, -1
975
        jz      write_fat_not_used
978
        jz      write_fat_not_used
976
        mov     ebx, [ebp+FAT.fat_cache_ptr]
979
        mov     ebx, [ebp+FAT.fat_cache_ptr]
977
        mov     ecx, [ebp+FAT.NUMBER_OF_FATS]
980
        mov     ecx, [ebp+FAT.NUMBER_OF_FATS]
978
 
981
 
979
  write_next_fat:
982
  write_next_fat:
980
        push    eax
983
        push    eax
981
        call    fs_write32_sys
984
        call    fs_write32_sys
982
        test    eax, eax
985
        test    eax, eax
983
        pop     eax
986
        pop     eax
984
        jnz     write_fat_not_used
987
        jnz     write_fat_not_used
985
 
988
 
986
        add     eax, [ebp+FAT.SECTORS_PER_FAT]
989
        add     eax, [ebp+FAT.SECTORS_PER_FAT]
987
        dec     ecx
990
        dec     ecx
988
        jnz     write_next_fat
991
        jnz     write_next_fat
989
 
992
 
990
  write_fat_not_used:
993
  write_fat_not_used:
991
        pop     ecx ebx eax
994
        pop     ecx ebx eax
992
        ret
995
        ret
993
 
996
 
994
 
997
 
995
 
998
 
996
 
999
 
997
 
1000
 
998
bcd2bin:
1001
bcd2bin:
999
;----------------------------------
1002
;----------------------------------
1000
; input  : AL=BCD number (eg. 0x11)
1003
; input  : AL=BCD number (eg. 0x11)
1001
; output : AH=0
1004
; output : AH=0
1002
;          AL=decimal number (eg. 11)
1005
;          AL=decimal number (eg. 11)
1003
;----------------------------------
1006
;----------------------------------
1004
        xor     ah, ah
1007
        xor     ah, ah
1005
        shl     ax, 4
1008
        shl     ax, 4
1006
        shr     al, 4
1009
        shr     al, 4
1007
        aad
1010
        aad
1008
        ret
1011
        ret
1009
 
1012
 
1010
 
1013
 
1011
get_date_for_file:
1014
get_date_for_file:
1012
;-----------------------------------------------------
1015
;-----------------------------------------------------
1013
; Get date from CMOS and pack day,month,year in AX
1016
; Get date from CMOS and pack day,month,year in AX
1014
; DATE   bits  0..4   : day of month 0..31
1017
; DATE   bits  0..4   : day of month 0..31
1015
;              5..8   : month of year 1..12
1018
;              5..8   : month of year 1..12
1016
;              9..15  : count of years from 1980
1019
;              9..15  : count of years from 1980
1017
;-----------------------------------------------------
1020
;-----------------------------------------------------
1018
        mov     al, 0x7 ;day
1021
        mov     al, 0x7 ;day
1019
        out     0x70, al
1022
        out     0x70, al
1020
        in      al, 0x71
1023
        in      al, 0x71
1021
        call    bcd2bin
1024
        call    bcd2bin
1022
        ror     eax, 5
1025
        ror     eax, 5
1023
 
1026
 
1024
        mov     al, 0x8 ;month
1027
        mov     al, 0x8 ;month
1025
        out     0x70, al
1028
        out     0x70, al
1026
        in      al, 0x71
1029
        in      al, 0x71
1027
        call    bcd2bin
1030
        call    bcd2bin
1028
        ror     eax, 4
1031
        ror     eax, 4
1029
 
1032
 
1030
        mov     al, 0x9 ;year
1033
        mov     al, 0x9 ;year
1031
        out     0x70, al
1034
        out     0x70, al
1032
        in      al, 0x71
1035
        in      al, 0x71
1033
        call    bcd2bin
1036
        call    bcd2bin
1034
        add     ax, 20  ;because CMOS return only the two last
1037
        add     ax, 20  ;because CMOS return only the two last
1035
                        ;digit (eg. 2000 -> 00 , 2001 -> 01) and we
1038
                        ;digit (eg. 2000 -> 00 , 2001 -> 01) and we
1036
        rol     eax, 9  ;need the difference with 1980 (eg. 2001-1980)
1039
        rol     eax, 9  ;need the difference with 1980 (eg. 2001-1980)
1037
        ret
1040
        ret
1038
 
1041
 
1039
 
1042
 
1040
get_time_for_file:
1043
get_time_for_file:
1041
;-----------------------------------------------------
1044
;-----------------------------------------------------
1042
; Get time from CMOS and pack hour,minute,second in AX
1045
; Get time from CMOS and pack hour,minute,second in AX
1043
; TIME   bits  0..4   : second (the low bit is lost)
1046
; TIME   bits  0..4   : second (the low bit is lost)
1044
;              5..10  : minute 0..59
1047
;              5..10  : minute 0..59
1045
;              11..15 : hour 0..23
1048
;              11..15 : hour 0..23
1046
;-----------------------------------------------------
1049
;-----------------------------------------------------
1047
        mov     al, 0x0 ;second
1050
        mov     al, 0x0 ;second
1048
        out     0x70, al
1051
        out     0x70, al
1049
        in      al, 0x71
1052
        in      al, 0x71
1050
        call    bcd2bin
1053
        call    bcd2bin
1051
        ror     eax, 6
1054
        ror     eax, 6
1052
 
1055
 
1053
        mov     al, 0x2 ;minute
1056
        mov     al, 0x2 ;minute
1054
        out     0x70, al
1057
        out     0x70, al
1055
        in      al, 0x71
1058
        in      al, 0x71
1056
        call    bcd2bin
1059
        call    bcd2bin
1057
        ror     eax, 6
1060
        ror     eax, 6
1058
 
1061
 
1059
        mov     al, 0x4 ;hour
1062
        mov     al, 0x4 ;hour
1060
        out     0x70, al
1063
        out     0x70, al
1061
        in      al, 0x71
1064
        in      al, 0x71
1062
        call    bcd2bin
1065
        call    bcd2bin
1063
        rol     eax, 11
1066
        rol     eax, 11
1064
        ret
1067
        ret
1065
 
1068
 
1066
 
1069
 
1067
set_current_time_for_entry:
1070
set_current_time_for_entry:
1068
;-----------------------------------------------------
1071
;-----------------------------------------------------
1069
; Set current time/date for file entry
1072
; Set current time/date for file entry
1070
; input  : ebx = file entry pointer
1073
; input  : ebx = file entry pointer
1071
;-----------------------------------------------------
1074
;-----------------------------------------------------
1072
        push    eax
1075
        push    eax
1073
        call    get_time_for_file; update files date/time
1076
        call    get_time_for_file; update files date/time
1074
        mov     [ebx+22], ax
1077
        mov     [ebx+22], ax
1075
        call    get_date_for_file
1078
        call    get_date_for_file
1076
        mov     [ebx+24], ax
1079
        mov     [ebx+24], ax
1077
        pop     eax
1080
        pop     eax
1078
        ret
1081
        ret
1079
 
1082
 
1080
 
1083
 
1081
 
1084
 
1082
add_disk_free_space:
1085
add_disk_free_space:
1083
;-----------------------------------------------------
1086
;-----------------------------------------------------
1084
; input  : ecx = cluster count
1087
; input  : ecx = cluster count
1085
; Note   : negative = remove clusters from free space
1088
; Note   : negative = remove clusters from free space
1086
;          positive = add clusters to free space
1089
;          positive = add clusters to free space
1087
;-----------------------------------------------------
1090
;-----------------------------------------------------
1088
        test    ecx, ecx        ; no change
1091
        test    ecx, ecx        ; no change
1089
        je      add_dfs_no
1092
        je      add_dfs_no
1090
        cmp     [ebp+FAT.fs_type], 32  ; free disk space only used by fat32
1093
        cmp     [ebp+FAT.fs_type], 32  ; free disk space only used by fat32
1091
        jne     add_dfs_no
1094
        jne     add_dfs_no
1092
 
1095
 
1093
        push    eax ebx
1096
        push    eax ebx
1094
        mov     eax, [ebp+FAT.ADR_FSINFO]
1097
        mov     eax, [ebp+FAT.ADR_FSINFO]
1095
        lea     ebx, [ebp+FAT.fsinfo_buffer]
1098
        lea     ebx, [ebp+FAT.fsinfo_buffer]
1096
        call    fs_read32_sys
1099
        call    fs_read32_sys
1097
        test    eax, eax
1100
        test    eax, eax
1098
        jnz     add_not_fs
1101
        jnz     add_not_fs
1099
 
1102
 
1100
        cmp     dword [ebx+0x1fc], 0xaa550000; check sector id
1103
        cmp     dword [ebx+0x1fc], 0xaa550000; check sector id
1101
        jne     add_not_fs
1104
        jne     add_not_fs
1102
 
1105
 
1103
        add     [ebx+0x1e8], ecx
1106
        add     [ebx+0x1e8], ecx
1104
        push    [ebp+FAT.fatStartScan]
1107
        push    [ebp+FAT.fatStartScan]
1105
        pop     dword [ebx+0x1ec]
1108
        pop     dword [ebx+0x1ec]
1106
        mov     eax, [ebp+FAT.ADR_FSINFO]
1109
        mov     eax, [ebp+FAT.ADR_FSINFO]
1107
        call    fs_write32_sys
1110
        call    fs_write32_sys
1108
;    jc    add_not_fs
1111
;    jc    add_not_fs
1109
 
1112
 
1110
  add_not_fs:
1113
  add_not_fs:
1111
        pop     ebx eax
1114
        pop     ebx eax
1112
 
1115
 
1113
  add_dfs_no:
1116
  add_dfs_no:
1114
        ret
1117
        ret
1115
 
1118
 
1116
 
1119
 
1117
 
1120
 
1118
clear_cluster_chain:
1121
clear_cluster_chain:
1119
;-----------------------------------------------------
1122
;-----------------------------------------------------
1120
; input  : eax = first cluster
1123
; input  : eax = first cluster
1121
;-----------------------------------------------------
1124
;-----------------------------------------------------
1122
        push    eax ecx edx
1125
        push    eax ecx edx
1123
        xor     ecx, ecx        ; cluster count
1126
        xor     ecx, ecx        ; cluster count
1124
 
1127
 
1125
  clean_new_chain:
1128
  clean_new_chain:
1126
        cmp     eax, [ebp+FAT.LAST_CLUSTER]; end of file
1129
        cmp     eax, [ebp+FAT.LAST_CLUSTER]; end of file
1127
        ja      delete_OK
1130
        ja      delete_OK
1128
        cmp     eax, 2          ; unfinished fat chain or zero length file
1131
        cmp     eax, 2          ; unfinished fat chain or zero length file
1129
        jb      delete_OK
1132
        jb      delete_OK
1130
        cmp     eax, [ebp+FAT.ROOT_CLUSTER]; don't remove root cluster
1133
        cmp     eax, [ebp+FAT.ROOT_CLUSTER]; don't remove root cluster
1131
        jz      delete_OK
1134
        jz      delete_OK
1132
 
1135
 
1133
        xor     edx, edx
1136
        xor     edx, edx
1134
        call    set_FAT         ; clear fat entry
1137
        call    set_FAT         ; clear fat entry
1135
        jc      access_denied_01
1138
        jc      access_denied_01
1136
 
1139
 
1137
        inc     ecx             ; update cluster count
1140
        inc     ecx             ; update cluster count
1138
        mov     eax, edx        ; old cluster
1141
        mov     eax, edx        ; old cluster
1139
        jmp     clean_new_chain
1142
        jmp     clean_new_chain
1140
 
1143
 
1141
  delete_OK:
1144
  delete_OK:
1142
        call    add_disk_free_space; add clusters to free disk space
1145
        call    add_disk_free_space; add clusters to free disk space
1143
        clc
1146
        clc
1144
  access_denied_01:
1147
  access_denied_01:
1145
        pop     edx ecx eax
1148
        pop     edx ecx eax
1146
        ret
1149
        ret
1147
 
1150
 
1148
 
1151
 
1149
if 0
1152
if 0
1150
get_hd_info:
1153
get_hd_info:
1151
;-----------------------------------------------------------
1154
;-----------------------------------------------------------
1152
; output : eax = 0 - ok
1155
; output : eax = 0 - ok
1153
;                3 - unknown FS
1156
;                3 - unknown FS
1154
;               10 - access denied
1157
;               10 - access denied
1155
;          edx = cluster size in bytes
1158
;          edx = cluster size in bytes
1156
;          ebx = total clusters on disk
1159
;          ebx = total clusters on disk
1157
;          ecx = free clusters on disk
1160
;          ecx = free clusters on disk
1158
;-----------------------------------------------------------
1161
;-----------------------------------------------------------
1159
        cmp     [ebp+FAT.fs_type], 16
1162
        cmp     [ebp+FAT.fs_type], 16
1160
        jz      info_fat_ok
1163
        jz      info_fat_ok
1161
        cmp     [ebp+FAT.fs_type], 32
1164
        cmp     [ebp+FAT.fs_type], 32
1162
        jz      info_fat_ok
1165
        jz      info_fat_ok
1163
        xor     edx, edx
1166
        xor     edx, edx
1164
        xor     ebx, ebx
1167
        xor     ebx, ebx
1165
        xor     ecx, ecx
1168
        xor     ecx, ecx
1166
        mov     eax, ERROR_UNKNOWN_FS
1169
        mov     eax, ERROR_UNKNOWN_FS
1167
        ret
1170
        ret
1168
 
1171
 
1169
  info_fat_ok:
1172
  info_fat_ok:
1170
;    call  reserve_hd1
1173
;    call  reserve_hd1
1171
 
1174
 
1172
        xor     ecx, ecx        ; count of free clusters
1175
        xor     ecx, ecx        ; count of free clusters
1173
        mov     eax, 2
1176
        mov     eax, 2
1174
        mov     ebx, [ebp+FAT.LAST_CLUSTER]
1177
        mov     ebx, [ebp+FAT.LAST_CLUSTER]
1175
 
1178
 
1176
  info_cluster:
1179
  info_cluster:
1177
        push    eax
1180
        push    eax
1178
        call    get_FAT         ; get cluster info
1181
        call    get_FAT         ; get cluster info
1179
        jc      info_access_denied
1182
        jc      info_access_denied
1180
 
1183
 
1181
        test    eax, eax        ; is it free?
1184
        test    eax, eax        ; is it free?
1182
        jnz     info_used       ; no
1185
        jnz     info_used       ; no
1183
        inc     ecx
1186
        inc     ecx
1184
 
1187
 
1185
  info_used:
1188
  info_used:
1186
        pop     eax
1189
        pop     eax
1187
        inc     eax
1190
        inc     eax
1188
        cmp     eax, ebx        ; is above last cluster?
1191
        cmp     eax, ebx        ; is above last cluster?
1189
        jbe     info_cluster    ; no. test next cluster
1192
        jbe     info_cluster    ; no. test next cluster
1190
 
1193
 
1191
        dec     ebx             ; cluster count
1194
        dec     ebx             ; cluster count
1192
        imul    edx, [ebp+FAT.SECTORS_PER_CLUSTER], 512; cluster size in bytes
1195
        imul    edx, [ebp+FAT.SECTORS_PER_CLUSTER], 512; cluster size in bytes
1193
        xor     eax, eax
1196
        xor     eax, eax
1194
        ret
1197
        ret
1195
 
1198
 
1196
  info_access_denied:
1199
  info_access_denied:
1197
        add     esp, 4
1200
        add     esp, 4
1198
        xor     edx, edx
1201
        xor     edx, edx
1199
        xor     ebx, ebx
1202
        xor     ebx, ebx
1200
        xor     ecx, ecx
1203
        xor     ecx, ecx
1201
        mov     eax, ERROR_ACCESS_DENIED
1204
        mov     eax, ERROR_ACCESS_DENIED
1202
        ret
1205
        ret
1203
end if
1206
end if
1204
 
1207
 
1205
update_disk:
1208
update_disk:
1206
        cmp     [ebp+FAT.fat_change], 0 ; is fat changed?
1209
        cmp     [ebp+FAT.fat_change], 0 ; is fat changed?
1207
        je      upd_no_change
1210
        je      upd_no_change
1208
        cmp     [ebp+FAT.fs_type], 12
1211
        cmp     [ebp+FAT.fs_type], 12
1209
        jz      .fat12
1212
        jz      .fat12
1210
;-----------------------------------------------------------
1213
;-----------------------------------------------------------
1211
; write changed fat and cache to disk
1214
; write changed fat and cache to disk
1212
;-----------------------------------------------------------
1215
;-----------------------------------------------------------
1213
 
1216
 
1214
        call    write_fat_sector
1217
        call    write_fat_sector
1215
        jc      update_disk_acces_denied
1218
        jc      update_disk_acces_denied
1216
        jmp     upd_no_change
1219
        jmp     upd_no_change
1217
.fat12:
1220
.fat12:
1218
        call    restorefatchain
1221
        call    restorefatchain
1219
        mov     [ebp+FAT.fat_change], 0
1222
        mov     [ebp+FAT.fat_change], 0
1220
 
1223
 
1221
  upd_no_change:
1224
  upd_no_change:
1222
 
1225
 
1223
        push    esi
1226
        push    esi
1224
        mov     esi, [ebp+PARTITION.Disk]
1227
        mov     esi, [ebp+PARTITION.Disk]
1225
        call    disk_sync
1228
        call    disk_sync
1226
        pop     esi
1229
        pop     esi
1227
  update_disk_acces_denied:
1230
  update_disk_acces_denied:
1228
        ret
1231
        ret
1229
 
1232
 
1230
fat_lock:
1233
fat_lock:
1231
        lea     ecx, [ebp+FAT.Lock]
1234
        lea     ecx, [ebp+FAT.Lock]
1232
        jmp     mutex_lock
1235
        jmp     mutex_lock
1233
fat_unlock:
1236
fat_unlock:
1234
        lea     ecx, [ebp+FAT.Lock]
1237
        lea     ecx, [ebp+FAT.Lock]
1235
        jmp     mutex_unlock
1238
        jmp     mutex_unlock
1236
 
1239
 
1237
; \begin{diamond}
1240
; \begin{diamond}
1238
uni2ansi_str:
1241
uni2ansi_str:
1239
; convert UNICODE zero-terminated string to ASCII-string (codepage 866)
1242
; convert UNICODE zero-terminated string to ASCII-string (codepage 866)
1240
; in: esi->source, edi->buffer (may be esi=edi)
1243
; in: esi->source, edi->buffer (may be esi=edi)
1241
; destroys: eax,esi,edi
1244
; destroys: eax,esi,edi
1242
        lodsw
1245
        lodsw
1243
        test    ax, ax
1246
        test    ax, ax
1244
        jz      .done
1247
        jz      .done
1245
        cmp     ax, 0x80
1248
        cmp     ax, 0x80
1246
        jb      .ascii
1249
        jb      .ascii
1247
        cmp     ax, 0x401
1250
        cmp     ax, 0x401
1248
        jz      .yo1
1251
        jz      .yo1
1249
        cmp     ax, 0x451
1252
        cmp     ax, 0x451
1250
        jz      .yo2
1253
        jz      .yo2
1251
        cmp     ax, 0x410
1254
        cmp     ax, 0x410
1252
        jb      .unk
1255
        jb      .unk
1253
        cmp     ax, 0x440
1256
        cmp     ax, 0x440
1254
        jb      .rus1
1257
        jb      .rus1
1255
        cmp     ax, 0x450
1258
        cmp     ax, 0x450
1256
        jb      .rus2
1259
        jb      .rus2
1257
.unk:
1260
.unk:
1258
        mov     al, '_'
1261
        mov     al, '_'
1259
        jmp     .doit
1262
        jmp     .doit
1260
.yo1:
1263
.yo1:
1261
        mov     al, 0xF0 ; 'Ё'
1264
        mov     al, 0xF0 ; 'Ё'
1262
        jmp     .doit
1265
        jmp     .doit
1263
.yo2:
1266
.yo2:
1264
        mov     al, 0xF1 ; 'ё'
1267
        mov     al, 0xF1 ; 'ё'
1265
        jmp     .doit
1268
        jmp     .doit
1266
.rus1:
1269
.rus1:
1267
; 0x410-0x43F -> 0x80-0xAF
1270
; 0x410-0x43F -> 0x80-0xAF
1268
        add     al, 0x70
1271
        add     al, 0x70
1269
        jmp     .doit
1272
        jmp     .doit
1270
.rus2:
1273
.rus2:
1271
; 0x440-0x44F -> 0xE0-0xEF
1274
; 0x440-0x44F -> 0xE0-0xEF
1272
        add     al, 0xA0
1275
        add     al, 0xA0
1273
.ascii:
1276
.ascii:
1274
.doit:
1277
.doit:
1275
        stosb
1278
        stosb
1276
        jmp     uni2ansi_str
1279
        jmp     uni2ansi_str
1277
.done:
1280
.done:
1278
        mov     byte [edi], 0
1281
        mov     byte [edi], 0
1279
        ret
1282
        ret
1280
 
1283
 
1281
ansi2uni_char:
1284
ansi2uni_char:
1282
; convert ANSI character in al to UNICODE character in ax, using cp866 encoding
1285
; convert ANSI character in al to UNICODE character in ax, using cp866 encoding
1283
        mov     ah, 0
1286
        mov     ah, 0
1284
; 0x00-0x7F - trivial map
1287
; 0x00-0x7F - trivial map
1285
        cmp     al, 0x80
1288
        cmp     al, 0x80
1286
        jb      .ret
1289
        jb      .ret
1287
; 0x80-0xAF -> 0x410-0x43F
1290
; 0x80-0xAF -> 0x410-0x43F
1288
        cmp     al, 0xB0
1291
        cmp     al, 0xB0
1289
        jae     @f
1292
        jae     @f
1290
        add     ax, 0x410-0x80
1293
        add     ax, 0x410-0x80
1291
.ret:
1294
.ret:
1292
        ret
1295
        ret
1293
@@:
1296
@@:
1294
; 0xE0-0xEF -> 0x440-0x44F
1297
; 0xE0-0xEF -> 0x440-0x44F
1295
        cmp     al, 0xE0
1298
        cmp     al, 0xE0
1296
        jb      .unk
1299
        jb      .unk
1297
        cmp     al, 0xF0
1300
        cmp     al, 0xF0
1298
        jae     @f
1301
        jae     @f
1299
        add     ax, 0x440-0xE0
1302
        add     ax, 0x440-0xE0
1300
        ret
1303
        ret
1301
; 0xF0 -> 0x401
1304
; 0xF0 -> 0x401
1302
; 0xF1 -> 0x451
1305
; 0xF1 -> 0x451
1303
@@:
1306
@@:
1304
        cmp     al, 0xF0 ; 'Ё'
1307
        cmp     al, 0xF0 ; 'Ё'
1305
        jz      .yo1
1308
        jz      .yo1
1306
        cmp     al, 0xF1 ; 'ё'
1309
        cmp     al, 0xF1 ; 'ё'
1307
        jz      .yo2
1310
        jz      .yo2
1308
.unk:
1311
.unk:
1309
        mov     al, '_'         ; ah=0
1312
        mov     al, '_'         ; ah=0
1310
        ret
1313
        ret
1311
.yo1:
1314
.yo1:
1312
        mov     ax, 0x401
1315
        mov     ax, 0x401
1313
        ret
1316
        ret
1314
.yo2:
1317
.yo2:
1315
        mov     ax, 0x451
1318
        mov     ax, 0x451
1316
        ret
1319
        ret
1317
 
1320
 
1318
char_toupper:
1321
char_toupper:
1319
; convert character to uppercase, using cp866 encoding
1322
; convert character to uppercase, using cp866 encoding
1320
; in: al=symbol
1323
; in: al=symbol
1321
; out: al=converted symbol
1324
; out: al=converted symbol
1322
        cmp     al, 'a'
1325
        cmp     al, 'a'
1323
        jb      .ret
1326
        jb      .ret
1324
        cmp     al, 'z'
1327
        cmp     al, 'z'
1325
        jbe     .az
1328
        jbe     .az
1326
        cmp     al, 0xF1 ; 'ё'
1329
        cmp     al, 0xF1 ; 'ё'
1327
        jz      .yo1
1330
        jz      .yo1
1328
        cmp     al, 0xA0 ; 'а'
1331
        cmp     al, 0xA0 ; 'а'
1329
        jb      .ret
1332
        jb      .ret
1330
        cmp     al, 0xE0 ; 'р'
1333
        cmp     al, 0xE0 ; 'р'
1331
        jb      .rus1
1334
        jb      .rus1
1332
        cmp     al, 0xEF ; 'я'
1335
        cmp     al, 0xEF ; 'я'
1333
        ja      .ret
1336
        ja      .ret
1334
; 0xE0-0xEF -> 0x90-0x9F
1337
; 0xE0-0xEF -> 0x90-0x9F
1335
        sub     al, 0xE0-0x90
1338
        sub     al, 0xE0-0x90
1336
.ret:
1339
.ret:
1337
        ret
1340
        ret
1338
.rus1:
1341
.rus1:
1339
; 0xA0-0xAF -> 0x80-0x8F
1342
; 0xA0-0xAF -> 0x80-0x8F
1340
.az:
1343
.az:
1341
        and     al, not 0x20
1344
        and     al, not 0x20
1342
        ret
1345
        ret
1343
.yo1:
1346
.yo1:
1344
; 0xF1 -> 0xF0
1347
; 0xF1 -> 0xF0
1345
        dec     ax
1348
        dec     ax
1346
        ret
1349
        ret
1347
 
1350
 
1348
fat_get_name:
1351
fat_get_name:
1349
; in: edi->FAT entry
1352
; in: edi->FAT entry
1350
; out: CF=1 - no valid entry
1353
; out: CF=1 - no valid entry
1351
; else CF=0 and ebp->ASCIIZ-name
1354
; else CF=0 and ebp->ASCIIZ-name
1352
; (maximum length of filename is 255 (wide) symbols without trailing 0,
1355
; (maximum length of filename is 255 (wide) symbols without trailing 0,
1353
;  but implementation requires buffer 261 words)
1356
;  but implementation requires buffer 261 words)
1354
; destroys eax
1357
; destroys eax
1355
        cmp     byte [edi], 0
1358
        cmp     byte [edi], 0
1356
        jz      .no
1359
        jz      .no
1357
        cmp     byte [edi], 0xE5
1360
        cmp     byte [edi], 0xE5
1358
        jnz     @f
1361
        jnz     @f
1359
.no:
1362
.no:
1360
        stc
1363
        stc
1361
        ret
1364
        ret
1362
@@:
1365
@@:
1363
        cmp     byte [edi+11], 0xF
1366
        cmp     byte [edi+11], 0xF
1364
        jz      .longname
1367
        jz      .longname
1365
        test    byte [edi+11], 8
1368
        test    byte [edi+11], 8
1366
        jnz     .no
1369
        jnz     .no
1367
        push    ecx
1370
        push    ecx
1368
        push    edi ebp
1371
        push    edi ebp
1369
        test    byte [ebp-4], 1
1372
        test    byte [ebp-4], 1
1370
        jnz     .unicode_short
1373
        jnz     .unicode_short
1371
 
1374
 
1372
        mov     eax, [edi]
1375
        mov     eax, [edi]
1373
        mov     ecx, [edi+4]
1376
        mov     ecx, [edi+4]
1374
        mov     [ebp], eax
1377
        mov     [ebp], eax
1375
        mov     [ebp+4], ecx
1378
        mov     [ebp+4], ecx
1376
 
1379
 
1377
        mov     ecx, 8
1380
        mov     ecx, 8
1378
@@:
1381
@@:
1379
        cmp     byte [ebp+ecx-1], ' '
1382
        cmp     byte [ebp+ecx-1], ' '
1380
        loope   @b
1383
        loope   @b
1381
 
1384
 
1382
        mov     eax, [edi+8]
1385
        mov     eax, [edi+8]
1383
        cmp     al, ' '
1386
        cmp     al, ' '
1384
        je      .done
1387
        je      .done
1385
        shl     eax, 8
1388
        shl     eax, 8
1386
        mov     al, '.'
1389
        mov     al, '.'
1387
 
1390
 
1388
        lea     ebp, [ebp+ecx+1]
1391
        lea     ebp, [ebp+ecx+1]
1389
        mov     [ebp], eax
1392
        mov     [ebp], eax
1390
        mov     ecx, 3
1393
        mov     ecx, 3
1391
@@:
1394
@@:
1392
        rol     eax, 8
1395
        rol     eax, 8
1393
        cmp     al, ' '
1396
        cmp     al, ' '
1394
        jne     .done
1397
        jne     .done
1395
        loop    @b
1398
        loop    @b
1396
        dec     ebp
1399
        dec     ebp
1397
.done:
1400
.done:
1398
        and     byte [ebp+ecx+1], 0   ; CF=0
1401
        and     byte [ebp+ecx+1], 0   ; CF=0
1399
        pop     ebp edi ecx
1402
        pop     ebp edi ecx
1400
        ret
1403
        ret
1401
.unicode_short:
1404
.unicode_short:
1402
        mov     ecx, 8
1405
        mov     ecx, 8
1403
        push    ecx
1406
        push    ecx
1404
@@:
1407
@@:
1405
        mov     al, [edi]
1408
        mov     al, [edi]
1406
        inc     edi
1409
        inc     edi
1407
        call    ansi2uni_char
1410
        call    ansi2uni_char
1408
        mov     [ebp], ax
1411
        mov     [ebp], ax
1409
        inc     ebp
1412
        inc     ebp
1410
        inc     ebp
1413
        inc     ebp
1411
        loop    @b
1414
        loop    @b
1412
        pop     ecx
1415
        pop     ecx
1413
@@:
1416
@@:
1414
        cmp     word [ebp-2], ' '
1417
        cmp     word [ebp-2], ' '
1415
        jnz     @f
1418
        jnz     @f
1416
        dec     ebp
1419
        dec     ebp
1417
        dec     ebp
1420
        dec     ebp
1418
        loop    @b
1421
        loop    @b
1419
@@:
1422
@@:
1420
        mov     word [ebp], '.'
1423
        mov     word [ebp], '.'
1421
        inc     ebp
1424
        inc     ebp
1422
        inc     ebp
1425
        inc     ebp
1423
        mov     ecx, 3
1426
        mov     ecx, 3
1424
        push    ecx
1427
        push    ecx
1425
@@:
1428
@@:
1426
        mov     al, [edi]
1429
        mov     al, [edi]
1427
        inc     edi
1430
        inc     edi
1428
        call    ansi2uni_char
1431
        call    ansi2uni_char
1429
        mov     [ebp], ax
1432
        mov     [ebp], ax
1430
        inc     ebp
1433
        inc     ebp
1431
        inc     ebp
1434
        inc     ebp
1432
        loop    @b
1435
        loop    @b
1433
        pop     ecx
1436
        pop     ecx
1434
@@:
1437
@@:
1435
        cmp     word [ebp-2], ' '
1438
        cmp     word [ebp-2], ' '
1436
        jnz     @f
1439
        jnz     @f
1437
        dec     ebp
1440
        dec     ebp
1438
        dec     ebp
1441
        dec     ebp
1439
        loop    @b
1442
        loop    @b
1440
        dec     ebp
1443
        dec     ebp
1441
        dec     ebp
1444
        dec     ebp
1442
@@:
1445
@@:
1443
        and     word [ebp], 0   ; CF=0
1446
        and     word [ebp], 0   ; CF=0
1444
        pop     ebp edi ecx
1447
        pop     ebp edi ecx
1445
        ret
1448
        ret
1446
.longname:
1449
.longname:
1447
; LFN
1450
; LFN
1448
        mov     al, byte [edi]
1451
        mov     al, byte [edi]
1449
        and     eax, 0x3F
1452
        and     eax, 0x3F
1450
        dec     eax
1453
        dec     eax
1451
        cmp     al, 20
1454
        cmp     al, 20
1452
        jae     .no     ; ignore invalid entries
1455
        jae     .no     ; ignore invalid entries
1453
        mov     word [ebp+260*2], 0     ; force null-terminating for orphans
1456
        mov     word [ebp+260*2], 0     ; force null-terminating for orphans
1454
        imul    eax, 13*2
1457
        imul    eax, 13*2
1455
        add     ebp, eax
1458
        add     ebp, eax
1456
        test    byte [edi], 0x40
1459
        test    byte [edi], 0x40
1457
        jz      @f
1460
        jz      @f
1458
        mov     word [ebp+13*2], 0
1461
        mov     word [ebp+13*2], 0
1459
@@:
1462
@@:
1460
        push    eax
1463
        push    eax
1461
; now copy name from edi to ebp ...
1464
; now copy name from edi to ebp ...
1462
        mov     eax, [edi+1]
1465
        mov     eax, [edi+1]
1463
        mov     [ebp], eax      ; symbols 1,2
1466
        mov     [ebp], eax      ; symbols 1,2
1464
        mov     eax, [edi+5]
1467
        mov     eax, [edi+5]
1465
        mov     [ebp+4], eax    ; 3,4
1468
        mov     [ebp+4], eax    ; 3,4
1466
        mov     eax, [edi+9]
1469
        mov     eax, [edi+9]
1467
        mov     [ebp+8], ax     ; 5
1470
        mov     [ebp+8], ax     ; 5
1468
        mov     eax, [edi+14]
1471
        mov     eax, [edi+14]
1469
        mov     [ebp+10], eax   ; 6,7
1472
        mov     [ebp+10], eax   ; 6,7
1470
        mov     eax, [edi+18]
1473
        mov     eax, [edi+18]
1471
        mov     [ebp+14], eax   ; 8,9
1474
        mov     [ebp+14], eax   ; 8,9
1472
        mov     eax, [edi+22]
1475
        mov     eax, [edi+22]
1473
        mov     [ebp+18], eax   ; 10,11
1476
        mov     [ebp+18], eax   ; 10,11
1474
        mov     eax, [edi+28]
1477
        mov     eax, [edi+28]
1475
        mov     [ebp+22], eax   ; 12,13
1478
        mov     [ebp+22], eax   ; 12,13
1476
; ... done
1479
; ... done
1477
        pop     eax
1480
        pop     eax
1478
        sub     ebp, eax
1481
        sub     ebp, eax
1479
        test    eax, eax
1482
        test    eax, eax
1480
        jz      @f
1483
        jz      @f
1481
; if this is not first entry, more processing required
1484
; if this is not first entry, more processing required
1482
        stc
1485
        stc
1483
        ret
1486
        ret
1484
@@:
1487
@@:
1485
; if this is first entry:
1488
; if this is first entry:
1486
        test    byte [ebp-4], 1
1489
        test    byte [ebp-4], 1
1487
        jnz     .ret
1490
        jnz     .ret
1488
; buffer at ebp contains UNICODE name, convert it to ANSI
1491
; buffer at ebp contains UNICODE name, convert it to ANSI
1489
        push    esi edi
1492
        push    esi edi
1490
        mov     esi, ebp
1493
        mov     esi, ebp
1491
        mov     edi, ebp
1494
        mov     edi, ebp
1492
        call    uni2ansi_str
1495
        call    uni2ansi_str
1493
        pop     edi esi
1496
        pop     edi esi
1494
.ret:
1497
.ret:
1495
        clc
1498
        clc
1496
        ret
1499
        ret
1497
 
1500
 
1498
fat_compare_name:
1501
fat_compare_name:
1499
; compares ASCIIZ-names, case-insensitive (cp866 encoding)
1502
; compares ASCIIZ-names, case-insensitive (cp866 encoding)
1500
; in: esi->name, ebp->name
1503
; in: esi->name, ebp->name
1501
; out: if names match: ZF=1 and esi->next component of name
1504
; out: if names match: ZF=1 and esi->next component of name
1502
;      else: ZF=0, esi is not changed
1505
;      else: ZF=0, esi is not changed
1503
; destroys eax
1506
; destroys eax
1504
        push    ebp esi
1507
        push    ebp esi
1505
.loop:
1508
.loop:
1506
        mov     al, [ebp]
1509
        mov     al, [ebp]
1507
        inc     ebp
1510
        inc     ebp
1508
        call    char_toupper
1511
        call    char_toupper
1509
        push    eax
1512
        push    eax
1510
        lodsb
1513
        lodsb
1511
        call    char_toupper
1514
        call    char_toupper
1512
        cmp     al, [esp]
1515
        cmp     al, [esp]
1513
        jnz     .done
1516
        jnz     .done
1514
        pop     eax
1517
        pop     eax
1515
        test    al, al
1518
        test    al, al
1516
        jnz     .loop
1519
        jnz     .loop
1517
        dec     esi
1520
        dec     esi
1518
        pop     eax
1521
        pop     eax
1519
        pop     ebp
1522
        pop     ebp
1520
        xor     eax, eax        ; set ZF flag
1523
        xor     eax, eax        ; set ZF flag
1521
        ret
1524
        ret
1522
.done:
1525
.done:
1523
        cmp     al, '/'
1526
        cmp     al, '/'
1524
        jnz     @f
1527
        jnz     @f
1525
        cmp     byte [esp], 0
1528
        cmp     byte [esp], 0
1526
        jnz     @f
1529
        jnz     @f
1527
        mov     [esp+4], esi
1530
        mov     [esp+4], esi
1528
@@:
1531
@@:
1529
        pop     eax
1532
        pop     eax
1530
        pop     esi ebp
1533
        pop     esi ebp
1531
        ret
1534
        ret
1532
 
1535
 
1533
fat_find_lfn:
1536
fat_find_lfn:
1534
; in: esi->name
1537
; in: esi->name
1535
;     [esp+4] = next
1538
;     [esp+4] = next
1536
;     [esp+8] = first
1539
;     [esp+8] = first
1537
;     [esp+C]... - possibly parameters for first and next
1540
;     [esp+C]... - possibly parameters for first and next
1538
; out: CF=1 - file not found, eax=error code
1541
; out: CF=1 - file not found, eax=error code
1539
;      else CF=0, esi->next name component, edi->direntry
1542
;      else CF=0, esi->next name component, edi->direntry
1540
        pusha
1543
        pusha
1541
        lea     eax, [esp+0Ch+20h]
1544
        lea     eax, [esp+0Ch+20h]
1542
        call    dword [eax-4]
1545
        call    dword [eax-4]
1543
        jc      .reterr
1546
        jc      .reterr
1544
        sub     esp, 262*2      ; reserve place for LFN
1547
        sub     esp, 262*2      ; reserve place for LFN
1545
        push    0               ; for fat_get_name: read ASCII name
1548
        push    0               ; for fat_get_name: read ASCII name
1546
.l1:
1549
.l1:
1547
        lea     ebp, [esp+4]
1550
        lea     ebp, [esp+4]
1548
        call    fat_get_name
1551
        call    fat_get_name
1549
        jc      .l2
1552
        jc      .l2
1550
        call    fat_compare_name
1553
        call    fat_compare_name
1551
        jz      .found
1554
        jz      .found
1552
.l2:
1555
.l2:
1553
        mov     ebp, [esp+8+262*2+4]
1556
        mov     ebp, [esp+8+262*2+4]
1554
        lea     eax, [esp+0Ch+20h+262*2+4]
1557
        lea     eax, [esp+0Ch+20h+262*2+4]
1555
        call    dword [eax-8]
1558
        call    dword [eax-8]
1556
        jnc     .l1
1559
        jnc     .l1
1557
        add     esp, 262*2+4
1560
        add     esp, 262*2+4
1558
.reterr:
1561
.reterr:
1559
        mov     [esp+28], eax
1562
        mov     [esp+28], eax
1560
        stc
1563
        stc
1561
        popa
1564
        popa
1562
        ret
1565
        ret
1563
.found:
1566
.found:
1564
        add     esp, 262*2+4
1567
        add     esp, 262*2+4
1565
        mov     ebp, [esp+8]
1568
        mov     ebp, [esp+8]
1566
; if this is LFN entry, advance to true entry
1569
; if this is LFN entry, advance to true entry
1567
        cmp     byte [edi+11], 0xF
1570
        cmp     byte [edi+11], 0xF
1568
        jnz     @f
1571
        jnz     @f
1569
        lea     eax, [esp+0Ch+20h]
1572
        lea     eax, [esp+0Ch+20h]
1570
        call    dword [eax-8]
1573
        call    dword [eax-8]
1571
        jc      .reterr
1574
        jc      .reterr
1572
@@:
1575
@@:
1573
        add     esp, 8          ; CF=0
1576
        add     esp, 8          ; CF=0
1574
        push    esi
1577
        push    esi
1575
        push    edi
1578
        push    edi
1576
        popa
1579
        popa
1577
        ret
1580
        ret
1578
 
1581
 
1579
fat_time_to_bdfe:
1582
fat_time_to_bdfe:
1580
; in: eax=FAT time
1583
; in: eax=FAT time
1581
; out: eax=BDFE time
1584
; out: eax=BDFE time
1582
        push    ecx edx
1585
        push    ecx edx
1583
        mov     ecx, eax
1586
        mov     ecx, eax
1584
        mov     edx, eax
1587
        mov     edx, eax
1585
        shr     eax, 11
1588
        shr     eax, 11
1586
        shl     eax, 16 ; hours
1589
        shl     eax, 16 ; hours
1587
        and     edx, 0x1F
1590
        and     edx, 0x1F
1588
        add     edx, edx
1591
        add     edx, edx
1589
        mov     al, dl  ; seconds
1592
        mov     al, dl  ; seconds
1590
        shr     ecx, 5
1593
        shr     ecx, 5
1591
        and     ecx, 0x3F
1594
        and     ecx, 0x3F
1592
        mov     ah, cl  ; minutes
1595
        mov     ah, cl  ; minutes
1593
        pop     edx ecx
1596
        pop     edx ecx
1594
        ret
1597
        ret
1595
 
1598
 
1596
fat_date_to_bdfe:
1599
fat_date_to_bdfe:
1597
        push    ecx edx
1600
        push    ecx edx
1598
        mov     ecx, eax
1601
        mov     ecx, eax
1599
        mov     edx, eax
1602
        mov     edx, eax
1600
        shr     eax, 9
1603
        shr     eax, 9
1601
        add     ax, 1980
1604
        add     ax, 1980
1602
        shl     eax, 16 ; year
1605
        shl     eax, 16 ; year
1603
        and     edx, 0x1F
1606
        and     edx, 0x1F
1604
        mov     al, dl  ; day
1607
        mov     al, dl  ; day
1605
        shr     ecx, 5
1608
        shr     ecx, 5
1606
        and     ecx, 0xF
1609
        and     ecx, 0xF
1607
        mov     ah, cl  ; month
1610
        mov     ah, cl  ; month
1608
        pop     edx ecx
1611
        pop     edx ecx
1609
        ret
1612
        ret
1610
 
1613
 
1611
bdfe_to_fat_time:
1614
bdfe_to_fat_time:
1612
        push    edx
1615
        push    edx
1613
        mov     edx, eax
1616
        mov     edx, eax
1614
        shr     eax, 16
1617
        shr     eax, 16
1615
        and     dh, 0x3F
1618
        and     dh, 0x3F
1616
        shl     eax, 6
1619
        shl     eax, 6
1617
        or      al, dh
1620
        or      al, dh
1618
        shr     dl, 1
1621
        shr     dl, 1
1619
        and     dl, 0x1F
1622
        and     dl, 0x1F
1620
        shl     eax, 5
1623
        shl     eax, 5
1621
        or      al, dl
1624
        or      al, dl
1622
        pop     edx
1625
        pop     edx
1623
        ret
1626
        ret
1624
 
1627
 
1625
bdfe_to_fat_date:
1628
bdfe_to_fat_date:
1626
        push    edx
1629
        push    edx
1627
        mov     edx, eax
1630
        mov     edx, eax
1628
        shr     eax, 16
1631
        shr     eax, 16
1629
        sub     ax, 1980
1632
        sub     ax, 1980
1630
        and     dh, 0xF
1633
        and     dh, 0xF
1631
        shl     eax, 4
1634
        shl     eax, 4
1632
        or      al, dh
1635
        or      al, dh
1633
        and     dl, 0x1F
1636
        and     dl, 0x1F
1634
        shl     eax, 5
1637
        shl     eax, 5
1635
        or      al, dl
1638
        or      al, dl
1636
        pop     edx
1639
        pop     edx
1637
        ret
1640
        ret
1638
 
1641
 
1639
fat_entry_to_bdfe:
1642
fat_entry_to_bdfe:
1640
; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
1643
; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
1641
; destroys eax
1644
; destroys eax
1642
        mov     eax, [ebp-4]
1645
        mov     eax, [ebp-4]
1643
        mov     [esi+4], eax    ; ASCII/UNICODE name
1646
        mov     [esi+4], eax    ; ASCII/UNICODE name
1644
fat_entry_to_bdfe2:
1647
fat_entry_to_bdfe2:
1645
        movzx   eax, byte [edi+11]
1648
        movzx   eax, byte [edi+11]
1646
        mov     [esi], eax      ; attributes
1649
        mov     [esi], eax      ; attributes
1647
        movzx   eax, word [edi+14]
1650
        movzx   eax, word [edi+14]
1648
        call    fat_time_to_bdfe
1651
        call    fat_time_to_bdfe
1649
        mov     [esi+8], eax    ; creation time
1652
        mov     [esi+8], eax    ; creation time
1650
        movzx   eax, word [edi+16]
1653
        movzx   eax, word [edi+16]
1651
        call    fat_date_to_bdfe
1654
        call    fat_date_to_bdfe
1652
        mov     [esi+12], eax   ; creation date
1655
        mov     [esi+12], eax   ; creation date
1653
        and     dword [esi+16], 0       ; last access time is not supported on FAT
1656
        and     dword [esi+16], 0       ; last access time is not supported on FAT
1654
        movzx   eax, word [edi+18]
1657
        movzx   eax, word [edi+18]
1655
        call    fat_date_to_bdfe
1658
        call    fat_date_to_bdfe
1656
        mov     [esi+20], eax   ; last access date
1659
        mov     [esi+20], eax   ; last access date
1657
        movzx   eax, word [edi+22]
1660
        movzx   eax, word [edi+22]
1658
        call    fat_time_to_bdfe
1661
        call    fat_time_to_bdfe
1659
        mov     [esi+24], eax   ; last write time
1662
        mov     [esi+24], eax   ; last write time
1660
        movzx   eax, word [edi+24]
1663
        movzx   eax, word [edi+24]
1661
        call    fat_date_to_bdfe
1664
        call    fat_date_to_bdfe
1662
        mov     [esi+28], eax   ; last write date
1665
        mov     [esi+28], eax   ; last write date
1663
        mov     eax, [edi+28]
1666
        mov     eax, [edi+28]
1664
        mov     [esi+32], eax   ; file size (low dword)
1667
        mov     [esi+32], eax   ; file size (low dword)
1665
        xor     eax, eax
1668
        xor     eax, eax
1666
        mov     [esi+36], eax   ; file size (high dword)
1669
        mov     [esi+36], eax   ; file size (high dword)
1667
        test    ebp, ebp
1670
        test    ebp, ebp
1668
        jz      .ret
1671
        jz      .ret
1669
        push    ecx edi
1672
        push    ecx edi
1670
        lea     edi, [esi+40]
1673
        lea     edi, [esi+40]
1671
        mov     esi, ebp
1674
        mov     esi, ebp
1672
        test    byte [esi-4], 1
1675
        test    byte [esi-4], 1
1673
        jz      .ansi
1676
        jz      .ansi
1674
        mov     ecx, 260/2
1677
        mov     ecx, 260/2
1675
        rep movsd
1678
        rep movsd
1676
        mov     [edi-2], ax
1679
        mov     [edi-2], ax
1677
@@:
1680
@@:
1678
        mov     esi, edi
1681
        mov     esi, edi
1679
        pop     edi ecx
1682
        pop     edi ecx
1680
.ret:
1683
.ret:
1681
        ret
1684
        ret
1682
.ansi:
1685
.ansi:
1683
        mov     ecx, 264/4
1686
        mov     ecx, 264/4
1684
        rep movsd
1687
        rep movsd
1685
        mov     [edi-1], al
1688
        mov     [edi-1], al
1686
        jmp     @b
1689
        jmp     @b
1687
 
1690
 
1688
bdfe_to_fat_entry:
1691
bdfe_to_fat_entry:
1689
; convert BDFE at edx to FAT entry at edi
1692
; convert BDFE at edx to FAT entry at edi
1690
; destroys eax
1693
; destroys eax
1691
; attributes byte
1694
; attributes byte
1692
        test    byte [edi+11], 8        ; volume label?
1695
        test    byte [edi+11], 8        ; volume label?
1693
        jnz     @f
1696
        jnz     @f
1694
        mov     al, [edx]
1697
        mov     al, [edx]
1695
        and     al, 0x27
1698
        and     al, 0x27
1696
        and     byte [edi+11], 0x10
1699
        and     byte [edi+11], 0x10
1697
        or      byte [edi+11], al
1700
        or      byte [edi+11], al
1698
@@:
1701
@@:
1699
        mov     eax, [edx+8]
1702
        mov     eax, [edx+8]
1700
        call    bdfe_to_fat_time
1703
        call    bdfe_to_fat_time
1701
        mov     [edi+14], ax            ; creation time
1704
        mov     [edi+14], ax            ; creation time
1702
        mov     eax, [edx+12]
1705
        mov     eax, [edx+12]
1703
        call    bdfe_to_fat_date
1706
        call    bdfe_to_fat_date
1704
        mov     [edi+16], ax            ; creation date
1707
        mov     [edi+16], ax            ; creation date
1705
        mov     eax, [edx+20]
1708
        mov     eax, [edx+20]
1706
        call    bdfe_to_fat_date
1709
        call    bdfe_to_fat_date
1707
        mov     [edi+18], ax            ; last access date
1710
        mov     [edi+18], ax            ; last access date
1708
        mov     eax, [edx+24]
1711
        mov     eax, [edx+24]
1709
        call    bdfe_to_fat_time
1712
        call    bdfe_to_fat_time
1710
        mov     [edi+22], ax            ; last write time
1713
        mov     [edi+22], ax            ; last write time
1711
        mov     eax, [edx+28]
1714
        mov     eax, [edx+28]
1712
        call    bdfe_to_fat_date
1715
        call    bdfe_to_fat_date
1713
        mov     [edi+24], ax            ; last write date
1716
        mov     [edi+24], ax            ; last write date
1714
        ret
1717
        ret
1715
 
1718
 
1716
hd_find_lfn:
1719
hd_find_lfn:
1717
; in: ebp -> FAT structure
1720
; in: ebp -> FAT structure
1718
; in: esi+[esp+4] -> name
1721
; in: esi+[esp+4] -> name
1719
; out: CF=1 - file not found, eax=error code
1722
; out: CF=1 - file not found, eax=error code
1720
;      else CF=0 and edi->direntry, eax=sector
1723
;      else CF=0 and edi->direntry, eax=sector
1721
; destroys eax
1724
; destroys eax
1722
        push    esi edi
1725
        push    esi edi
1723
        push    0
1726
        push    0
1724
        push    0
1727
        push    0
1725
        push    fat1x_root_first
1728
        push    fat1x_root_first
1726
        push    fat1x_root_next
1729
        push    fat1x_root_next
1727
        mov     eax, [ebp+FAT.ROOT_CLUSTER]
1730
        mov     eax, [ebp+FAT.ROOT_CLUSTER]
1728
        cmp     [ebp+FAT.fs_type], 32
1731
        cmp     [ebp+FAT.fs_type], 32
1729
        jz      .fat32
1732
        jz      .fat32
1730
.loop:
1733
.loop:
1731
        and     [ebp+FAT.longname_sec1], 0
1734
        and     [ebp+FAT.longname_sec1], 0
1732
        and     [ebp+FAT.longname_sec2], 0
1735
        and     [ebp+FAT.longname_sec2], 0
1733
        call    fat_find_lfn
1736
        call    fat_find_lfn
1734
        jc      .notfound
1737
        jc      .notfound
1735
        cmp     byte [esi], 0
1738
        cmp     byte [esi], 0
1736
        jz      .found
1739
        jz      .found
1737
.continue:
1740
.continue:
1738
        test    byte [edi+11], 10h
1741
        test    byte [edi+11], 10h
1739
        jz      .notfound
1742
        jz      .notfound
1740
        and     dword [esp+12], 0
1743
        and     dword [esp+12], 0
1741
        mov     eax, [edi+20-2]
1744
        mov     eax, [edi+20-2]
1742
        mov     ax, [edi+26]    ; cluster
1745
        mov     ax, [edi+26]    ; cluster
1743
.fat32:
1746
.fat32:
1744
        mov     [esp+8], eax
1747
        mov     [esp+8], eax
1745
        mov     dword [esp+4], fat_notroot_first
1748
        mov     dword [esp+4], fat_notroot_first
1746
        mov     dword [esp], fat_notroot_next
1749
        mov     dword [esp], fat_notroot_next
1747
        jmp     .loop
1750
        jmp     .loop
1748
.notfound:
1751
.notfound:
1749
        add     esp, 16
1752
        add     esp, 16
1750
        pop     edi esi
1753
        pop     edi esi
1751
        stc
1754
        stc
1752
        ret     4
1755
        ret     4
1753
.found:
1756
.found:
1754
        lea     eax, [esp+4+24]
1757
        lea     eax, [esp+4+24]
1755
        cmp     dword [eax], 0
1758
        cmp     dword [eax], 0
1756
        jz      @f
1759
        jz      @f
1757
        mov     esi, [eax]
1760
        mov     esi, [eax]
1758
        and     dword [eax], 0
1761
        and     dword [eax], 0
1759
        jmp     .continue
1762
        jmp     .continue
1760
@@:
1763
@@:
1761
        lea     eax, [esp+8]
1764
        lea     eax, [esp+8]
1762
        cmp     dword [eax], 0
1765
        cmp     dword [eax], 0
1763
        jz      .root
1766
        jz      .root
1764
        call    fat_get_sector
1767
        call    fat_get_sector
1765
        jmp     .cmn
1768
        jmp     .cmn
1766
.root:
1769
.root:
1767
        mov     eax, [eax+4]
1770
        mov     eax, [eax+4]
1768
        add     eax, [ebp+FAT.ROOT_START]
1771
        add     eax, [ebp+FAT.ROOT_START]
1769
.cmn:
1772
.cmn:
1770
        add     esp, 20         ; CF=0
1773
        add     esp, 20         ; CF=0
1771
        pop     esi
1774
        pop     esi
1772
        ret     4
1775
        ret     4
1773
 
1776
 
1774
;----------------------------------------------------------------
1777
;----------------------------------------------------------------
1775
; fat_Read - FAT implementation of reading a file
1778
; fat_Read - FAT implementation of reading a file
1776
; in:  ebp = pointer to FAT structure
1779
; in:  ebp = pointer to FAT structure
1777
; in:  esi+[esp+4] = name
1780
; in:  esi+[esp+4] = name
1778
; in:  ebx = pointer to parameters from sysfunc 70
1781
; in:  ebx = pointer to parameters from sysfunc 70
1779
; out: eax, ebx = return values for sysfunc 70
1782
; out: eax, ebx = return values for sysfunc 70
1780
;----------------------------------------------------------------
1783
;----------------------------------------------------------------
1781
fat_Read:
1784
fat_Read:
1782
        call    fat_lock
1785
        call    fat_lock
1783
        push    edi
1786
        push    edi
1784
        cmp     byte [esi], 0
1787
        cmp     byte [esi], 0
1785
        jnz     @f
1788
        jnz     @f
1786
.noaccess:
1789
.noaccess:
1787
        pop     edi
1790
        pop     edi
1788
.noaccess_2:
1791
.noaccess_2:
1789
        call    fat_unlock
1792
        call    fat_unlock
1790
        or      ebx, -1
1793
        or      ebx, -1
1791
        mov     eax, ERROR_ACCESS_DENIED
1794
        mov     eax, ERROR_ACCESS_DENIED
1792
        ret
1795
        ret
1793
 
1796
 
1794
@@:
1797
@@:
1795
        stdcall hd_find_lfn, [esp+4+4]
1798
        stdcall hd_find_lfn, [esp+4+4]
1796
        jnc     .found
1799
        jnc     .found
1797
        pop     edi
1800
        pop     edi
1798
        push    eax
1801
        push    eax
1799
        call    fat_unlock
1802
        call    fat_unlock
1800
        pop     eax
1803
        pop     eax
1801
        or      ebx, -1
1804
        or      ebx, -1
1802
        ret
1805
        ret
1803
 
1806
 
1804
.found:
1807
.found:
1805
        test    byte [edi+11], 0x10; do not allow read directories
1808
        test    byte [edi+11], 0x10; do not allow read directories
1806
        jnz     .noaccess
1809
        jnz     .noaccess
1807
        cmp     dword [ebx+8], 0
1810
        cmp     dword [ebx+8], 0
1808
        jz      @f
1811
        jz      @f
1809
        xor     ebx, ebx
1812
        xor     ebx, ebx
1810
.reteof:
1813
.reteof:
1811
        call    fat_unlock
1814
        call    fat_unlock
1812
        mov     eax, ERROR_END_OF_FILE
1815
        mov     eax, ERROR_END_OF_FILE
1813
        pop     edi
1816
        pop     edi
1814
        ret
1817
        ret
1815
@@:
1818
@@:
1816
        mov     ecx, [ebx+12]   ; size
1819
        mov     ecx, [ebx+12]   ; size
1817
        mov     edx, [ebx+16]   ; pointer
1820
        mov     edx, [ebx+16]   ; pointer
1818
        mov     ebx, [ebx+4]    ; file offset
1821
        mov     ebx, [ebx+4]    ; file offset
1819
        push    edx
1822
        push    edx
1820
        push    0
1823
        push    0
1821
        mov     eax, [edi+28]
1824
        mov     eax, [edi+28]
1822
        sub     eax, ebx
1825
        sub     eax, ebx
1823
        jb      .eof
1826
        jb      .eof
1824
        cmp     eax, ecx
1827
        cmp     eax, ecx
1825
        jae     @f
1828
        jae     @f
1826
        mov     ecx, eax
1829
        mov     ecx, eax
1827
        mov     byte [esp], 6
1830
        mov     byte [esp], 6
1828
@@:
1831
@@:
1829
        mov     eax, [edi+20-2]
1832
        mov     eax, [edi+20-2]
1830
        mov     ax, [edi+26]
1833
        mov     ax, [edi+26]
1831
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
1834
; now eax=cluster, ebx=position, ecx=count, edx=buffer for data
1832
.new_cluster:
1835
.new_cluster:
1833
        jecxz   .new_sector
1836
        jecxz   .new_sector
1834
        cmp     eax, 2
1837
        cmp     eax, 2
1835
        jb      .eof
1838
        jb      .eof
1836
        cmp     eax, [ebp+FAT.fatRESERVED]
1839
        cmp     eax, [ebp+FAT.fatRESERVED]
1837
        jae     .eof
1840
        jae     .eof
1838
        mov     [ebp+FAT.cluster_tmp], eax
1841
        mov     [ebp+FAT.cluster_tmp], eax
1839
        dec     eax
1842
        dec     eax
1840
        dec     eax
1843
        dec     eax
1841
        mov     edi, [ebp+FAT.SECTORS_PER_CLUSTER]
1844
        mov     edi, [ebp+FAT.SECTORS_PER_CLUSTER]
1842
        imul    eax, edi
1845
        imul    eax, edi
1843
        add     eax, [ebp+FAT.DATA_START]
1846
        add     eax, [ebp+FAT.DATA_START]
1844
.new_sector:
1847
.new_sector:
1845
        test    ecx, ecx
1848
        test    ecx, ecx
1846
        jz      .done
1849
        jz      .done
1847
        sub     ebx, 512
1850
        sub     ebx, 512
1848
        jae     .skip
1851
        jae     .skip
1849
        add     ebx, 512
1852
        add     ebx, 512
1850
        jnz     .force_buf
1853
        jnz     .force_buf
1851
        cmp     ecx, 512
1854
        cmp     ecx, 512
1852
        jb      .force_buf
1855
        jb      .force_buf
1853
; we may read directly to given buffer
1856
; we may read directly to given buffer
1854
        push    eax ebx
1857
        push    eax ebx
1855
        mov     ebx, edx
1858
        mov     ebx, edx
1856
        call    fs_read32_app
1859
        call    fs_read32_app
1857
        test    eax, eax
1860
        test    eax, eax
1858
        pop     ebx eax
1861
        pop     ebx eax
1859
        jne     .noaccess_1
1862
        jne     .noaccess_1
1860
        add     edx, 512
1863
        add     edx, 512
1861
        sub     ecx, 512
1864
        sub     ecx, 512
1862
        jmp     .skip
1865
        jmp     .skip
1863
.force_buf:
1866
.force_buf:
1864
; we must read sector to temporary buffer and then copy it to destination
1867
; we must read sector to temporary buffer and then copy it to destination
1865
        push    eax ebx
1868
        push    eax ebx
1866
        lea     ebx, [ebp+FAT.buffer]
1869
        lea     ebx, [ebp+FAT.buffer]
1867
        call    fs_read32_app
1870
        call    fs_read32_app
1868
        test    eax, eax
1871
        test    eax, eax
1869
        mov     eax, ebx
1872
        mov     eax, ebx
1870
        pop     ebx
1873
        pop     ebx
1871
        jne     .noaccess_3
1874
        jne     .noaccess_3
1872
        add     eax, ebx
1875
        add     eax, ebx
1873
        push    ecx
1876
        push    ecx
1874
        add     ecx, ebx
1877
        add     ecx, ebx
1875
        cmp     ecx, 512
1878
        cmp     ecx, 512
1876
        jbe     @f
1879
        jbe     @f
1877
        mov     ecx, 512
1880
        mov     ecx, 512
1878
@@:
1881
@@:
1879
        sub     ecx, ebx
1882
        sub     ecx, ebx
1880
        mov     ebx, edx
1883
        mov     ebx, edx
1881
        call    memmove
1884
        call    memmove
1882
        add     edx, ecx
1885
        add     edx, ecx
1883
        sub     [esp], ecx
1886
        sub     [esp], ecx
1884
        pop     ecx
1887
        pop     ecx
1885
        pop     eax
1888
        pop     eax
1886
        xor     ebx, ebx
1889
        xor     ebx, ebx
1887
.skip:
1890
.skip:
1888
        inc     eax
1891
        inc     eax
1889
        dec     edi
1892
        dec     edi
1890
        jnz     .new_sector
1893
        jnz     .new_sector
1891
        mov     eax, [ebp+FAT.cluster_tmp]
1894
        mov     eax, [ebp+FAT.cluster_tmp]
1892
        call    get_FAT
1895
        call    get_FAT
1893
        jc      .noaccess_1
1896
        jc      .noaccess_1
1894
 
1897
 
1895
        jmp     .new_cluster
1898
        jmp     .new_cluster
1896
.noaccess_3:
1899
.noaccess_3:
1897
        pop     eax
1900
        pop     eax
1898
.noaccess_1:
1901
.noaccess_1:
1899
        pop     eax
1902
        pop     eax
1900
        push    ERROR_DEVICE
1903
        push    ERROR_DEVICE
1901
.done:
1904
.done:
1902
        mov     ebx, edx
1905
        mov     ebx, edx
1903
        call    fat_unlock
1906
        call    fat_unlock
1904
        pop     eax edx edi
1907
        pop     eax edx edi
1905
        sub     ebx, edx
1908
        sub     ebx, edx
1906
        ret
1909
        ret
1907
.eof:
1910
.eof:
1908
        mov     ebx, edx
1911
        mov     ebx, edx
1909
        pop     eax edx
1912
        pop     eax edx
1910
        sub     ebx, edx
1913
        sub     ebx, edx
1911
        jmp     .reteof
1914
        jmp     .reteof
1912
 
1915
 
1913
;----------------------------------------------------------------
1916
;----------------------------------------------------------------
1914
; fat_ReadFolder - FAT implementation of reading a folder
1917
; fat_ReadFolder - FAT implementation of reading a folder
1915
; in:  ebp = pointer to FAT structure
1918
; in:  ebp = pointer to FAT structure
1916
; in:  esi+[esp+4] = name
1919
; in:  esi+[esp+4] = name
1917
; in:  ebx = pointer to parameters from sysfunc 70
1920
; in:  ebx = pointer to parameters from sysfunc 70
1918
; out: eax, ebx = return values for sysfunc 70
1921
; out: eax, ebx = return values for sysfunc 70
1919
;----------------------------------------------------------------
1922
;----------------------------------------------------------------
1920
fat_ReadFolder:
1923
fat_ReadFolder:
1921
        call    fat_lock
1924
        call    fat_lock
1922
        mov     eax, [ebp+FAT.ROOT_CLUSTER]
1925
        mov     eax, [ebp+FAT.ROOT_CLUSTER]
1923
        push    edi
1926
        push    edi
1924
        cmp     byte [esi], 0
1927
        cmp     byte [esi], 0
1925
        jz      .doit
1928
        jz      .doit
1926
        stdcall hd_find_lfn, [esp+4+4]
1929
        stdcall hd_find_lfn, [esp+4+4]
1927
        jnc     .found
1930
        jnc     .found
1928
        pop     edi
1931
        pop     edi
1929
        push    eax
1932
        push    eax
1930
        call    fat_unlock
1933
        call    fat_unlock
1931
        pop     eax
1934
        pop     eax
1932
        or      ebx, -1
1935
        or      ebx, -1
1933
        ret
1936
        ret
1934
.found:
1937
.found:
1935
        test    byte [edi+11], 0x10     ; do not allow read files
1938
        test    byte [edi+11], 0x10     ; do not allow read files
1936
        jnz     .found_dir
1939
        jnz     .found_dir
1937
        pop     edi
1940
        pop     edi
1938
        call    fat_unlock
1941
        call    fat_unlock
1939
        or      ebx, -1
1942
        or      ebx, -1
1940
        mov     eax, ERROR_ACCESS_DENIED
1943
        mov     eax, ERROR_ACCESS_DENIED
1941
        ret
1944
        ret
1942
.found_dir:
1945
.found_dir:
1943
        mov     eax, [edi+20-2]
1946
        mov     eax, [edi+20-2]
1944
        mov     ax, [edi+26]    ; eax=cluster
1947
        mov     ax, [edi+26]    ; eax=cluster
1945
.doit:
1948
.doit:
1946
        push    esi
1949
        push    esi
1947
        sub     esp, 262*2      ; reserve space for LFN
1950
        sub     esp, 262*2      ; reserve space for LFN
1948
        push    dword [ebx+8]   ; for fat_get_name: read ANSI/UNICODE name
1951
        push    dword [ebx+8]   ; for fat_get_name: read ANSI/UNICODE name
1949
        mov     edx, [ebx+16]   ; pointer to buffer
1952
        mov     edx, [ebx+16]   ; pointer to buffer
1950
; init header
1953
; init header
1951
        push    eax
1954
        push    eax
1952
        mov     edi, edx
1955
        mov     edi, edx
1953
        mov     ecx, 32/4
1956
        mov     ecx, 32/4
1954
        xor     eax, eax
1957
        xor     eax, eax
1955
        rep stosd
1958
        rep stosd
1956
        pop     eax
1959
        pop     eax
1957
        mov     byte [edx], 1   ; version
1960
        mov     byte [edx], 1   ; version
1958
        mov     esi, edi        ; esi points to BDFE
1961
        mov     esi, edi        ; esi points to BDFE
1959
        mov     ecx, [ebx+12]   ; number of blocks to read
1962
        mov     ecx, [ebx+12]   ; number of blocks to read
1960
        mov     ebx, [ebx+4]    ; index of the first block
1963
        mov     ebx, [ebx+4]    ; index of the first block
1961
.new_cluster:
1964
.new_cluster:
1962
        mov     [ebp+FAT.cluster_tmp], eax
1965
        mov     [ebp+FAT.cluster_tmp], eax
1963
        test    eax, eax
1966
        test    eax, eax
1964
        jnz     @f
1967
        jnz     @f
1965
        cmp     [ebp+FAT.fs_type], 32
1968
        cmp     [ebp+FAT.fs_type], 32
1966
        jz      .notfound
1969
        jz      .notfound
1967
        mov     eax, [ebp+FAT.ROOT_START]
1970
        mov     eax, [ebp+FAT.ROOT_START]
1968
        push    [ebp+FAT.ROOT_SECTORS]
1971
        push    [ebp+FAT.ROOT_SECTORS]
1969
        push    ebx
1972
        push    ebx
1970
        jmp     .new_sector
1973
        jmp     .new_sector
1971
@@:
1974
@@:
1972
        dec     eax
1975
        dec     eax
1973
        dec     eax
1976
        dec     eax
1974
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1977
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
1975
        push    [ebp+FAT.SECTORS_PER_CLUSTER]
1978
        push    [ebp+FAT.SECTORS_PER_CLUSTER]
1976
        add     eax, [ebp+FAT.DATA_START]
1979
        add     eax, [ebp+FAT.DATA_START]
1977
        push    ebx
1980
        push    ebx
1978
.new_sector:
1981
.new_sector:
1979
        lea     ebx, [ebp+FAT.buffer]
1982
        lea     ebx, [ebp+FAT.buffer]
1980
        mov     edi, ebx
1983
        mov     edi, ebx
1981
        push    eax
1984
        push    eax
1982
        call    fs_read32_sys
1985
        call    fs_read32_sys
1983
        test    eax, eax
1986
        test    eax, eax
1984
        pop     eax
1987
        pop     eax
1985
        jnz     .notfound2
1988
        jnz     .notfound2
1986
        add     ebx, 512
1989
        add     ebx, 512
1987
        push    eax
1990
        push    eax
1988
.l1:
1991
.l1:
1989
        push    ebp
1992
        push    ebp
1990
        lea     ebp, [esp+20]
1993
        lea     ebp, [esp+20]
1991
        call    fat_get_name
1994
        call    fat_get_name
1992
        pop     ebp
1995
        pop     ebp
1993
        jc      .l2
1996
        jc      .l2
1994
        cmp     byte [edi+11], 0xF
1997
        cmp     byte [edi+11], 0xF
1995
        jnz     .do_bdfe
1998
        jnz     .do_bdfe
1996
        add     edi, 0x20
1999
        add     edi, 0x20
1997
        cmp     edi, ebx
2000
        cmp     edi, ebx
1998
        jb      .do_bdfe
2001
        jb      .do_bdfe
1999
        pop     eax
2002
        pop     eax
2000
        inc     eax
2003
        inc     eax
2001
        dec     dword [esp+4]
2004
        dec     dword [esp+4]
2002
        jnz     @f
2005
        jnz     @f
2003
        mov     eax, [ebp+FAT.cluster_tmp]
2006
        mov     eax, [ebp+FAT.cluster_tmp]
2004
        test    eax, eax
2007
        test    eax, eax
2005
        jz      .done
2008
        jz      .done
2006
        call    get_FAT
2009
        call    get_FAT
2007
        jc      .notfound2
2010
        jc      .notfound2
2008
        cmp     eax, 2
2011
        cmp     eax, 2
2009
        jb      .done
2012
        jb      .done
2010
        cmp     eax, [ebp+FAT.fatRESERVED]
2013
        cmp     eax, [ebp+FAT.fatRESERVED]
2011
        jae     .done
2014
        jae     .done
2012
        push    eax
2015
        push    eax
2013
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2016
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2014
        mov     [esp+8], eax
2017
        mov     [esp+8], eax
2015
        pop     eax
2018
        pop     eax
2016
        mov     [ebp+FAT.cluster_tmp], eax
2019
        mov     [ebp+FAT.cluster_tmp], eax
2017
        dec     eax
2020
        dec     eax
2018
        dec     eax
2021
        dec     eax
2019
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2022
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2020
        add     eax, [ebp+FAT.DATA_START]
2023
        add     eax, [ebp+FAT.DATA_START]
2021
@@:
2024
@@:
2022
        lea     ebx, [ebp+FAT.buffer]
2025
        lea     ebx, [ebp+FAT.buffer]
2023
        mov     edi, ebx
2026
        mov     edi, ebx
2024
        push    eax
2027
        push    eax
2025
        call    fs_read32_sys
2028
        call    fs_read32_sys
2026
        test    eax, eax
2029
        test    eax, eax
2027
        pop     eax
2030
        pop     eax
2028
        jnz     .notfound2
2031
        jnz     .notfound2
2029
        add     ebx, 512
2032
        add     ebx, 512
2030
        push    eax
2033
        push    eax
2031
.do_bdfe:
2034
.do_bdfe:
2032
        inc     dword [edx+8]   ; new file found
2035
        inc     dword [edx+8]   ; new file found
2033
        dec     dword [esp+4]
2036
        dec     dword [esp+4]
2034
        jns     .l2
2037
        jns     .l2
2035
        dec     ecx
2038
        dec     ecx
2036
        js      .l2
2039
        js      .l2
2037
        inc     dword [edx+4]   ; new file block copied
2040
        inc     dword [edx+4]   ; new file block copied
2038
        push    ebp
2041
        push    ebp
2039
        lea     ebp, [esp+20]
2042
        lea     ebp, [esp+20]
2040
        call    fat_entry_to_bdfe
2043
        call    fat_entry_to_bdfe
2041
        pop     ebp
2044
        pop     ebp
2042
.l2:
2045
.l2:
2043
        add     edi, 0x20
2046
        add     edi, 0x20
2044
        cmp     edi, ebx
2047
        cmp     edi, ebx
2045
        jb      .l1
2048
        jb      .l1
2046
        pop     eax
2049
        pop     eax
2047
        inc     eax
2050
        inc     eax
2048
        dec     dword [esp+4]
2051
        dec     dword [esp+4]
2049
        jnz     .new_sector
2052
        jnz     .new_sector
2050
        mov     eax, [ebp+FAT.cluster_tmp]
2053
        mov     eax, [ebp+FAT.cluster_tmp]
2051
        test    eax, eax
2054
        test    eax, eax
2052
        jz      .done
2055
        jz      .done
2053
        call    get_FAT
2056
        call    get_FAT
2054
        jc      .notfound2
2057
        jc      .notfound2
2055
        cmp     eax, 2
2058
        cmp     eax, 2
2056
        jb      .done
2059
        jb      .done
2057
        cmp     eax, [ebp+FAT.fatRESERVED]
2060
        cmp     eax, [ebp+FAT.fatRESERVED]
2058
        jae     .done
2061
        jae     .done
2059
        push    eax
2062
        push    eax
2060
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2063
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2061
        mov     [esp+8], eax
2064
        mov     [esp+8], eax
2062
        pop     eax
2065
        pop     eax
2063
        pop     ebx
2066
        pop     ebx
2064
        add     esp, 4
2067
        add     esp, 4
2065
        jmp     .new_cluster
2068
        jmp     .new_cluster
2066
.notfound2:
2069
.notfound2:
2067
        add     esp, 8
2070
        add     esp, 8
2068
.notfound:
2071
.notfound:
2069
        add     esp, 262*2+4
2072
        add     esp, 262*2+4
2070
        pop     esi edi
2073
        pop     esi edi
2071
        mov     ebx, [edx+4]
2074
        mov     ebx, [edx+4]
2072
        call    fat_unlock
2075
        call    fat_unlock
2073
        mov     eax, ERROR_DEVICE
2076
        mov     eax, ERROR_DEVICE
2074
        ret
2077
        ret
2075
.done:
2078
.done:
2076
        add     esp, 262*2+4+8
2079
        add     esp, 262*2+4+8
2077
        mov     ebx, [edx+4]
2080
        mov     ebx, [edx+4]
2078
        xor     eax, eax
2081
        xor     eax, eax
2079
        dec     ecx
2082
        dec     ecx
2080
        js      @f
2083
        js      @f
2081
        mov     al, ERROR_END_OF_FILE
2084
        mov     al, ERROR_END_OF_FILE
2082
@@:
2085
@@:
2083
        push    eax
2086
        push    eax
2084
        call    fat_unlock
2087
        call    fat_unlock
2085
        pop     eax
2088
        pop     eax
2086
        pop     esi edi
2089
        pop     esi edi
2087
        ret
2090
        ret
2088
 
2091
 
2089
fat1x_root_next:
2092
fat1x_root_next:
2090
        push    ecx
2093
        push    ecx
2091
        lea     ecx, [ebp+FAT.buffer+0x200-0x20]
2094
        lea     ecx, [ebp+FAT.buffer+0x200-0x20]
2092
        cmp     edi, ecx
2095
        cmp     edi, ecx
2093
        jae     fat1x_root_next_sector
2096
        jae     fat1x_root_next_sector
2094
        pop     ecx
2097
        pop     ecx
2095
        add     edi, 0x20
2098
        add     edi, 0x20
2096
        ret     ; CF=0
2099
        ret     ; CF=0
2097
fat1x_root_next_sector:
2100
fat1x_root_next_sector:
2098
; read next sector
2101
; read next sector
2099
        push    [ebp+FAT.longname_sec2]
2102
        push    [ebp+FAT.longname_sec2]
2100
        pop     [ebp+FAT.longname_sec1]
2103
        pop     [ebp+FAT.longname_sec1]
2101
        mov     ecx, [eax+4]
2104
        mov     ecx, [eax+4]
2102
        push    ecx
2105
        push    ecx
2103
        add     ecx, [ebp+FAT.ROOT_START]
2106
        add     ecx, [ebp+FAT.ROOT_START]
2104
        mov     [ebp+FAT.longname_sec2], ecx
2107
        mov     [ebp+FAT.longname_sec2], ecx
2105
        pop     ecx
2108
        pop     ecx
2106
        inc     ecx
2109
        inc     ecx
2107
        mov     [eax+4], ecx
2110
        mov     [eax+4], ecx
2108
        cmp     ecx, [ebp+FAT.ROOT_SECTORS]
2111
        cmp     ecx, [ebp+FAT.ROOT_SECTORS]
2109
        pop     ecx
2112
        pop     ecx
2110
        jb      fat1x_root_first
2113
        jb      fat1x_root_first
2111
        mov     eax, ERROR_FILE_NOT_FOUND
2114
        mov     eax, ERROR_FILE_NOT_FOUND
2112
        stc
2115
        stc
2113
        ret
2116
        ret
2114
fat1x_root_first:
2117
fat1x_root_first:
2115
        mov     eax, [eax+4]
2118
        mov     eax, [eax+4]
2116
        add     eax, [ebp+FAT.ROOT_START]
2119
        add     eax, [ebp+FAT.ROOT_START]
2117
        push    ebx
2120
        push    ebx
2118
        lea     edi, [ebp+FAT.buffer]
2121
        lea     edi, [ebp+FAT.buffer]
2119
        mov     ebx, edi
2122
        mov     ebx, edi
2120
        call    fs_read32_sys
2123
        call    fs_read32_sys
2121
        pop     ebx
2124
        pop     ebx
2122
        test    eax, eax
2125
        test    eax, eax
2123
        jnz     .readerr
2126
        jnz     .readerr
2124
        ret     ; CF=0
2127
        ret     ; CF=0
2125
.readerr:
2128
.readerr:
2126
        mov     eax, ERROR_DEVICE
2129
        mov     eax, ERROR_DEVICE
2127
        stc
2130
        stc
2128
        ret
2131
        ret
2129
.notfound:
2132
.notfound:
2130
        mov     eax, ERROR_FILE_NOT_FOUND
2133
        mov     eax, ERROR_FILE_NOT_FOUND
2131
        stc
2134
        stc
2132
        ret
2135
        ret
2133
fat1x_root_begin_write:
2136
fat1x_root_begin_write:
2134
        push    edi eax
2137
        push    edi eax
2135
        call    fat1x_root_first
2138
        call    fat1x_root_first
2136
        pop     eax edi
2139
        pop     eax edi
2137
        ret
2140
        ret
2138
fat1x_root_end_write:
2141
fat1x_root_end_write:
2139
        pusha
2142
        pusha
2140
        mov     eax, [eax+4]
2143
        mov     eax, [eax+4]
2141
        add     eax, [ebp+FAT.ROOT_START]
2144
        add     eax, [ebp+FAT.ROOT_START]
2142
        lea     ebx, [ebp+FAT.buffer]
2145
        lea     ebx, [ebp+FAT.buffer]
2143
        call    fs_write32_sys
2146
        call    fs_write32_sys
2144
        popa
2147
        popa
2145
        ret
2148
        ret
2146
fat1x_root_next_write:
2149
fat1x_root_next_write:
2147
        push    ecx
2150
        push    ecx
2148
        lea     ecx, [ebp+FAT.buffer+0x200]
2151
        lea     ecx, [ebp+FAT.buffer+0x200]
2149
        cmp     edi, ecx
2152
        cmp     edi, ecx
2150
        jae     @f
2153
        jae     @f
2151
        pop     ecx
2154
        pop     ecx
2152
        ret
2155
        ret
2153
@@:
2156
@@:
2154
        call    fat1x_root_end_write
2157
        call    fat1x_root_end_write
2155
        jmp     fat1x_root_next_sector
2158
        jmp     fat1x_root_next_sector
2156
fat1x_root_extend_dir:
2159
fat1x_root_extend_dir:
2157
        stc
2160
        stc
2158
        ret
2161
        ret
2159
 
2162
 
2160
fat_notroot_next:
2163
fat_notroot_next:
2161
        push    ecx
2164
        push    ecx
2162
        lea     ecx, [ebp+FAT.buffer+0x200-0x20]
2165
        lea     ecx, [ebp+FAT.buffer+0x200-0x20]
2163
        cmp     edi, ecx
2166
        cmp     edi, ecx
2164
        jae     fat_notroot_next_sector
2167
        jae     fat_notroot_next_sector
2165
        pop     ecx
2168
        pop     ecx
2166
        add     edi, 0x20
2169
        add     edi, 0x20
2167
        ret     ; CF=0
2170
        ret     ; CF=0
2168
fat_notroot_next_sector:
2171
fat_notroot_next_sector:
2169
        push    [ebp+FAT.longname_sec2]
2172
        push    [ebp+FAT.longname_sec2]
2170
        pop     [ebp+FAT.longname_sec1]
2173
        pop     [ebp+FAT.longname_sec1]
2171
        push    eax
2174
        push    eax
2172
        call    fat_get_sector
2175
        call    fat_get_sector
2173
        mov     [ebp+FAT.longname_sec2], eax
2176
        mov     [ebp+FAT.longname_sec2], eax
2174
        pop     eax
2177
        pop     eax
2175
        mov     ecx, [eax+4]
2178
        mov     ecx, [eax+4]
2176
        inc     ecx
2179
        inc     ecx
2177
        cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2180
        cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2178
        jae     fat_notroot_next_cluster
2181
        jae     fat_notroot_next_cluster
2179
        mov     [eax+4], ecx
2182
        mov     [eax+4], ecx
2180
        jmp     @f
2183
        jmp     @f
2181
fat_notroot_next_cluster:
2184
fat_notroot_next_cluster:
2182
        push    eax
2185
        push    eax
2183
        mov     eax, [eax]
2186
        mov     eax, [eax]
2184
        call    get_FAT
2187
        call    get_FAT
2185
        mov     ecx, eax
2188
        mov     ecx, eax
2186
        pop     eax
2189
        pop     eax
2187
        jc      fat_notroot_first.deverr
2190
        jc      fat_notroot_first.deverr
2188
        cmp     ecx, 2
2191
        cmp     ecx, 2
2189
        jb      fat_notroot_next_err
2192
        jb      fat_notroot_next_err
2190
        cmp     ecx, [ebp+FAT.fatRESERVED]
2193
        cmp     ecx, [ebp+FAT.fatRESERVED]
2191
        jae     fat_notroot_next_err
2194
        jae     fat_notroot_next_err
2192
        mov     [eax], ecx
2195
        mov     [eax], ecx
2193
        and     dword [eax+4], 0
2196
        and     dword [eax+4], 0
2194
@@:
2197
@@:
2195
        pop     ecx
2198
        pop     ecx
2196
fat_notroot_first:
2199
fat_notroot_first:
2197
        call    fat_get_sector
2200
        call    fat_get_sector
2198
        push    ebx
2201
        push    ebx
2199
        lea     edi, [ebp+FAT.buffer]
2202
        lea     edi, [ebp+FAT.buffer]
2200
        mov     ebx, edi
2203
        mov     ebx, edi
2201
        call    fs_read32_sys
2204
        call    fs_read32_sys
2202
        pop     ebx
2205
        pop     ebx
2203
        test    eax, eax
2206
        test    eax, eax
2204
        jz      .ret ; CF=0
2207
        jz      .ret ; CF=0
2205
        push    ecx
2208
        push    ecx
2206
.deverr:
2209
.deverr:
2207
        pop     ecx
2210
        pop     ecx
2208
        mov     eax, ERROR_DEVICE
2211
        mov     eax, ERROR_DEVICE
2209
        stc
2212
        stc
2210
.ret:
2213
.ret:
2211
        ret
2214
        ret
2212
fat_notroot_next_err:
2215
fat_notroot_next_err:
2213
        pop     ecx
2216
        pop     ecx
2214
        mov     eax, ERROR_FILE_NOT_FOUND
2217
        mov     eax, ERROR_FILE_NOT_FOUND
2215
        stc
2218
        stc
2216
        ret
2219
        ret
2217
fat_notroot_begin_write:
2220
fat_notroot_begin_write:
2218
        push    eax edi
2221
        push    eax edi
2219
        call    fat_notroot_first
2222
        call    fat_notroot_first
2220
        pop     edi eax
2223
        pop     edi eax
2221
        ret
2224
        ret
2222
fat_notroot_end_write:
2225
fat_notroot_end_write:
2223
        call    fat_get_sector
2226
        call    fat_get_sector
2224
        push    ebx
2227
        push    ebx
2225
        lea     ebx, [ebp+FAT.buffer]
2228
        lea     ebx, [ebp+FAT.buffer]
2226
        call    fs_write32_sys
2229
        call    fs_write32_sys
2227
        pop     ebx
2230
        pop     ebx
2228
        ret
2231
        ret
2229
fat_notroot_next_write:
2232
fat_notroot_next_write:
2230
        push    ecx
2233
        push    ecx
2231
        lea     ecx, [ebp+FAT.buffer+0x200]
2234
        lea     ecx, [ebp+FAT.buffer+0x200]
2232
        cmp     edi, ecx
2235
        cmp     edi, ecx
2233
        jae     @f
2236
        jae     @f
2234
        pop     ecx
2237
        pop     ecx
2235
        ret
2238
        ret
2236
@@:
2239
@@:
2237
        push    eax
2240
        push    eax
2238
        call    fat_notroot_end_write
2241
        call    fat_notroot_end_write
2239
        pop     eax
2242
        pop     eax
2240
        jmp     fat_notroot_next_sector
2243
        jmp     fat_notroot_next_sector
2241
fat_notroot_extend_dir:
2244
fat_notroot_extend_dir:
2242
        push    eax
2245
        push    eax
2243
        call    get_free_FAT
2246
        call    get_free_FAT
2244
        jnc     .found
2247
        jnc     .found
2245
        pop     eax
2248
        pop     eax
2246
        ret     ; CF=1
2249
        ret     ; CF=1
2247
.found:
2250
.found:
2248
        push    edx
2251
        push    edx
2249
        mov     edx, [ebp+FAT.fatEND]
2252
        mov     edx, [ebp+FAT.fatEND]
2250
        call    set_FAT
2253
        call    set_FAT
2251
        jc      .writeerr
2254
        jc      .writeerr
2252
        mov     edx, eax
2255
        mov     edx, eax
2253
        mov     eax, [esp+4]
2256
        mov     eax, [esp+4]
2254
        mov     eax, [eax]
2257
        mov     eax, [eax]
2255
        push    edx
2258
        push    edx
2256
        call    set_FAT
2259
        call    set_FAT
2257
        pop     edx
2260
        pop     edx
2258
        jnc     @f
2261
        jnc     @f
2259
.writeerr:
2262
.writeerr:
2260
        pop     edx
2263
        pop     edx
2261
        pop     eax
2264
        pop     eax
2262
        stc
2265
        stc
2263
        ret
2266
        ret
2264
@@:
2267
@@:
2265
        push    ecx
2268
        push    ecx
2266
        or      ecx, -1
2269
        or      ecx, -1
2267
        call    add_disk_free_space
2270
        call    add_disk_free_space
2268
; zero new cluster
2271
; zero new cluster
2269
        mov     ecx, 512/4
2272
        mov     ecx, 512/4
2270
        lea     edi, [ebp+FAT.buffer]
2273
        lea     edi, [ebp+FAT.buffer]
2271
        push    edi
2274
        push    edi
2272
        xor     eax, eax
2275
        xor     eax, eax
2273
        rep stosd
2276
        rep stosd
2274
        pop     edi
2277
        pop     edi
2275
        pop     ecx
2278
        pop     ecx
2276
        mov     eax, [esp+4]
2279
        mov     eax, [esp+4]
2277
        mov     [eax], edx
2280
        mov     [eax], edx
2278
        and     dword [eax+4], 0
2281
        and     dword [eax+4], 0
2279
        pop     edx
2282
        pop     edx
2280
        mov     eax, [eax]
2283
        mov     eax, [eax]
2281
        dec     eax
2284
        dec     eax
2282
        dec     eax
2285
        dec     eax
2283
        push    ebx ecx
2286
        push    ebx ecx
2284
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2287
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2285
        imul    eax, ecx
2288
        imul    eax, ecx
2286
        add     eax, [ebp+FAT.DATA_START]
2289
        add     eax, [ebp+FAT.DATA_START]
2287
        mov     ebx, edi
2290
        mov     ebx, edi
2288
@@:
2291
@@:
2289
        push    eax
2292
        push    eax
2290
        call    fs_write32_sys
2293
        call    fs_write32_sys
2291
        pop     eax
2294
        pop     eax
2292
        inc     eax
2295
        inc     eax
2293
        loop    @b
2296
        loop    @b
2294
        pop     ecx ebx eax
2297
        pop     ecx ebx eax
2295
        clc
2298
        clc
2296
        ret
2299
        ret
2297
 
2300
 
2298
fat_get_sector:
2301
fat_get_sector:
2299
        push    ecx
2302
        push    ecx
2300
        mov     ecx, [eax]
2303
        mov     ecx, [eax]
2301
        dec     ecx
2304
        dec     ecx
2302
        dec     ecx
2305
        dec     ecx
2303
        imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2306
        imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2304
        add     ecx, [ebp+FAT.DATA_START]
2307
        add     ecx, [ebp+FAT.DATA_START]
2305
        add     ecx, [eax+4]
2308
        add     ecx, [eax+4]
2306
        mov     eax, ecx
2309
        mov     eax, ecx
2307
        pop     ecx
2310
        pop     ecx
2308
        ret
2311
        ret
2309
 
2312
 
2310
fshrad:
2313
fshrad:
2311
        call    fat_unlock
2314
        call    fat_unlock
2312
        mov     eax, ERROR_ACCESS_DENIED
2315
        mov     eax, ERROR_ACCESS_DENIED
2313
        xor     ebx, ebx
2316
        xor     ebx, ebx
2314
        ret
2317
        ret
2315
 
2318
 
2316
;----------------------------------------------------------------
2319
;----------------------------------------------------------------
2317
; fat_CreateFolder - FAT implementation of creating a folder
2320
; fat_CreateFolder - FAT implementation of creating a folder
2318
; in:  ebp = pointer to FAT structure
2321
; in:  ebp = pointer to FAT structure
2319
; in:  esi+[esp+4] = name
2322
; in:  esi+[esp+4] = name
2320
; in:  ebx = pointer to parameters from sysfunc 70
2323
; in:  ebx = pointer to parameters from sysfunc 70
2321
; out: eax, ebx = return values for sysfunc 70
2324
; out: eax, ebx = return values for sysfunc 70
2322
;----------------------------------------------------------------
2325
;----------------------------------------------------------------
2323
fat_CreateFolder:
2326
fat_CreateFolder:
2324
        push    1
2327
        push    1
2325
        jmp     fat_Rewrite.common
2328
        jmp     fat_Rewrite.common
2326
 
2329
 
2327
;----------------------------------------------------------------
2330
;----------------------------------------------------------------
2328
; fat_Rewrite - FAT implementation of creating a new file
2331
; fat_Rewrite - FAT implementation of creating a new file
2329
; in:  ebp = pointer to FAT structure
2332
; in:  ebp = pointer to FAT structure
2330
; in:  esi+[esp+4] = name
2333
; in:  esi+[esp+4] = name
2331
; in:  ebx = pointer to parameters from sysfunc 70
2334
; in:  ebx = pointer to parameters from sysfunc 70
2332
; out: eax, ebx = return values for sysfunc 70
2335
; out: eax, ebx = return values for sysfunc 70
2333
;----------------------------------------------------------------
2336
;----------------------------------------------------------------
2334
fat_Rewrite:
2337
fat_Rewrite:
2335
        push    0
2338
        push    0
2336
.common:
2339
.common:
2337
        call    fat_lock
2340
        call    fat_lock
2338
        pop     eax
2341
        pop     eax
2339
        cmp     byte [esi], 0
2342
        cmp     byte [esi], 0
2340
        jz      fshrad
2343
        jz      fshrad
2341
        mov     ecx, [ebx+12]
2344
        mov     ecx, [ebx+12]
2342
        mov     edx, [ebx+16]
2345
        mov     edx, [ebx+16]
2343
        pushad
2346
        pushad
2344
        xor     edi, edi
2347
        xor     edi, edi
2345
        mov     edx, [esp+4+20h]
2348
        mov     edx, [esp+4+20h]
2346
        push    esi
2349
        push    esi
2347
        test    edx, edx
2350
        test    edx, edx
2348
        jz      @f
2351
        jz      @f
2349
        mov     esi, edx
2352
        mov     esi, edx
2350
@@:
2353
@@:
2351
        lodsb
2354
        lodsb
2352
        test    al, al
2355
        test    al, al
2353
        jz      @f
2356
        jz      @f
2354
        cmp     al, '/'
2357
        cmp     al, '/'
2355
        jnz     @b
2358
        jnz     @b
2356
        lea     edi, [esi-1]
2359
        lea     edi, [esi-1]
2357
        jmp     @b
2360
        jmp     @b
2358
@@:
2361
@@:
2359
        pop     esi
2362
        pop     esi
2360
        test    edi, edi
2363
        test    edi, edi
2361
        jnz     .noroot
2364
        jnz     .noroot
2362
        test    edx, edx
2365
        test    edx, edx
2363
        jnz     .hasebp
2366
        jnz     .hasebp
2364
        mov     edx, [ebp+FAT.ROOT_CLUSTER]
2367
        mov     edx, [ebp+FAT.ROOT_CLUSTER]
2365
        cmp     [ebp+FAT.fs_type], 32
2368
        cmp     [ebp+FAT.fs_type], 32
2366
        jz      .pushnotroot
2369
        jz      .pushnotroot
2367
        xor     edx, edx
2370
        xor     edx, edx
2368
        push    edx
2371
        push    edx
2369
        push    fat1x_root_extend_dir
2372
        push    fat1x_root_extend_dir
2370
        push    fat1x_root_end_write
2373
        push    fat1x_root_end_write
2371
        push    fat1x_root_next_write
2374
        push    fat1x_root_next_write
2372
        push    fat1x_root_begin_write
2375
        push    fat1x_root_begin_write
2373
        push    edx
2376
        push    edx
2374
        push    edx
2377
        push    edx
2375
        push    fat1x_root_first
2378
        push    fat1x_root_first
2376
        push    fat1x_root_next
2379
        push    fat1x_root_next
2377
        jmp     .common1
2380
        jmp     .common1
2378
.hasebp:
2381
.hasebp:
2379
        mov     eax, ERROR_ACCESS_DENIED
2382
        mov     eax, ERROR_ACCESS_DENIED
2380
        cmp     byte [edx], 0
2383
        cmp     byte [edx], 0
2381
        jz      .ret1
2384
        jz      .ret1
2382
        stdcall hd_find_lfn, 0
2385
        stdcall hd_find_lfn, 0
2383
        mov     esi, [esp+4+20h]
2386
        mov     esi, [esp+4+20h]
2384
        jc      .ret1
2387
        jc      .ret1
2385
        jmp     .common0
2388
        jmp     .common0
2386
.noroot:
2389
.noroot:
2387
        mov     eax, ERROR_ACCESS_DENIED
2390
        mov     eax, ERROR_ACCESS_DENIED
2388
        cmp     byte [edi+1], 0
2391
        cmp     byte [edi+1], 0
2389
        jz      .ret1
2392
        jz      .ret1
2390
; check existence
2393
; check existence
2391
        mov     byte [edi], 0
2394
        mov     byte [edi], 0
2392
        push    edi
2395
        push    edi
2393
        stdcall hd_find_lfn, [esp+4+24h]
2396
        stdcall hd_find_lfn, [esp+4+24h]
2394
        pop     esi
2397
        pop     esi
2395
        mov     byte [esi], '/'
2398
        mov     byte [esi], '/'
2396
        jnc     @f
2399
        jnc     @f
2397
.notfound0:
2400
.notfound0:
2398
        mov     eax, ERROR_FILE_NOT_FOUND
2401
        mov     eax, ERROR_FILE_NOT_FOUND
2399
.ret1:
2402
.ret1:
2400
        mov     [esp+28], eax
2403
        mov     [esp+28], eax
2401
        call    fat_unlock
2404
        call    fat_unlock
2402
        popad
2405
        popad
2403
        xor     ebx, ebx
2406
        xor     ebx, ebx
2404
        ret
2407
        ret
2405
@@:
2408
@@:
2406
        inc     esi
2409
        inc     esi
2407
.common0:
2410
.common0:
2408
        test    byte [edi+11], 0x10     ; must be directory
2411
        test    byte [edi+11], 0x10     ; must be directory
2409
        mov     eax, ERROR_ACCESS_DENIED
2412
        mov     eax, ERROR_ACCESS_DENIED
2410
        jz      .ret1
2413
        jz      .ret1
2411
        mov     edx, [edi+20-2]
2414
        mov     edx, [edi+20-2]
2412
        mov     dx, [edi+26]            ; ebp=cluster
2415
        mov     dx, [edi+26]            ; ebp=cluster
2413
        mov     eax, ERROR_FAT_TABLE
2416
        mov     eax, ERROR_FAT_TABLE
2414
        cmp     edx, 2
2417
        cmp     edx, 2
2415
        jb      .ret1
2418
        jb      .ret1
2416
.pushnotroot:
2419
.pushnotroot:
2417
        push    edx
2420
        push    edx
2418
        push    fat_notroot_extend_dir
2421
        push    fat_notroot_extend_dir
2419
        push    fat_notroot_end_write
2422
        push    fat_notroot_end_write
2420
        push    fat_notroot_next_write
2423
        push    fat_notroot_next_write
2421
        push    fat_notroot_begin_write
2424
        push    fat_notroot_begin_write
2422
        push    0
2425
        push    0
2423
        push    edx
2426
        push    edx
2424
        push    fat_notroot_first
2427
        push    fat_notroot_first
2425
        push    fat_notroot_next
2428
        push    fat_notroot_next
2426
.common1:
2429
.common1:
2427
        call    fat_find_lfn
2430
        call    fat_find_lfn
2428
        jc      .notfound
2431
        jc      .notfound
2429
; found
2432
; found
2430
        test    byte [edi+11], 10h
2433
        test    byte [edi+11], 10h
2431
        jz      .exists_file
2434
        jz      .exists_file
2432
; found directory; if we are creating directory, return OK,
2435
; found directory; if we are creating directory, return OK,
2433
;                  if we are creating file, say "access denied"
2436
;                  if we are creating file, say "access denied"
2434
        add     esp, 36
2437
        add     esp, 36
2435
        call    fat_unlock
2438
        call    fat_unlock
2436
        popad
2439
        popad
2437
        test    al, al
2440
        test    al, al
2438
        mov     eax, ERROR_ACCESS_DENIED
2441
        mov     eax, ERROR_ACCESS_DENIED
2439
        jz      @f
2442
        jz      @f
2440
        mov     al, 0
2443
        mov     al, 0
2441
@@:
2444
@@:
2442
        xor     ebx, ebx
2445
        xor     ebx, ebx
2443
        ret
2446
        ret
2444
.exists_file:
2447
.exists_file:
2445
; found file; if we are creating directory, return "access denied",
2448
; found file; if we are creating directory, return "access denied",
2446
;             if we are creating file, delete existing file and continue
2449
;             if we are creating file, delete existing file and continue
2447
        cmp     byte [esp+36+28], 0
2450
        cmp     byte [esp+36+28], 0
2448
        jz      @f
2451
        jz      @f
2449
        add     esp, 36
2452
        add     esp, 36
2450
        call    fat_unlock
2453
        call    fat_unlock
2451
        popad
2454
        popad
2452
        mov     eax, ERROR_ACCESS_DENIED
2455
        mov     eax, ERROR_ACCESS_DENIED
2453
        xor     ebx, ebx
2456
        xor     ebx, ebx
2454
        ret
2457
        ret
2455
@@:
2458
@@:
2456
; delete FAT chain
2459
; delete FAT chain
2457
        push    edi
2460
        push    edi
2458
        xor     eax, eax
2461
        xor     eax, eax
2459
        mov     dword [edi+28], eax     ; zero size
2462
        mov     dword [edi+28], eax     ; zero size
2460
        xor     ecx, ecx
2463
        xor     ecx, ecx
2461
        mov     eax, [edi+20-2]
2464
        mov     eax, [edi+20-2]
2462
        mov     ax, [edi+26]
2465
        mov     ax, [edi+26]
2463
        mov     word [edi+20], cx
2466
        mov     word [edi+20], cx
2464
        mov     word [edi+26], cx
2467
        mov     word [edi+26], cx
2465
        test    eax, eax
2468
        test    eax, eax
2466
        jz      .done1
2469
        jz      .done1
2467
@@:
2470
@@:
2468
        cmp     eax, [ebp+FAT.fatRESERVED]
2471
        cmp     eax, [ebp+FAT.fatRESERVED]
2469
        jae     .done1
2472
        jae     .done1
2470
        push    edx
2473
        push    edx
2471
        xor     edx, edx
2474
        xor     edx, edx
2472
        call    set_FAT
2475
        call    set_FAT
2473
        mov     eax, edx
2476
        mov     eax, edx
2474
        pop     edx
2477
        pop     edx
2475
        jc      .done1
2478
        jc      .done1
2476
        inc     ecx
2479
        inc     ecx
2477
        jmp     @b
2480
        jmp     @b
2478
.done1:
2481
.done1:
2479
        pop     edi
2482
        pop     edi
2480
        call    get_time_for_file
2483
        call    get_time_for_file
2481
        mov     [edi+22], ax
2484
        mov     [edi+22], ax
2482
        call    get_date_for_file
2485
        call    get_date_for_file
2483
        mov     [edi+24], ax
2486
        mov     [edi+24], ax
2484
        mov     [edi+18], ax
2487
        mov     [edi+18], ax
2485
        or      byte [edi+11], 20h      ; set 'archive' attribute
2488
        or      byte [edi+11], 20h      ; set 'archive' attribute
2486
        jmp     .doit
2489
        jmp     .doit
2487
.notfound:
2490
.notfound:
2488
; file is not found; generate short name
2491
; file is not found; generate short name
2489
        call    fat_name_is_legal
2492
        call    fat_name_is_legal
2490
        jc      @f
2493
        jc      @f
2491
        add     esp, 36
2494
        add     esp, 36
2492
        call    fat_unlock
2495
        call    fat_unlock
2493
        popad
2496
        popad
2494
        mov     eax, ERROR_FILE_NOT_FOUND
2497
        mov     eax, ERROR_FILE_NOT_FOUND
2495
        xor     ebx, ebx
2498
        xor     ebx, ebx
2496
        ret
2499
        ret
2497
@@:
2500
@@:
2498
        sub     esp, 12
2501
        sub     esp, 12
2499
        mov     edi, esp
2502
        mov     edi, esp
2500
        call    fat_gen_short_name
2503
        call    fat_gen_short_name
2501
.test_short_name_loop:
2504
.test_short_name_loop:
2502
        push    esi edi ecx
2505
        push    esi edi ecx
2503
        mov     esi, edi
2506
        mov     esi, edi
2504
        lea     eax, [esp+12+12+8]
2507
        lea     eax, [esp+12+12+8]
2505
        mov     edx, [eax+24]
2508
        mov     edx, [eax+24]
2506
        mov     [eax], edx
2509
        mov     [eax], edx
2507
        and     dword [eax+4], 0
2510
        and     dword [eax+4], 0
2508
        call    dword [eax-4]
2511
        call    dword [eax-4]
2509
        jc      .found
2512
        jc      .found
2510
.test_short_name_entry:
2513
.test_short_name_entry:
2511
        cmp     byte [edi+11], 0xF
2514
        cmp     byte [edi+11], 0xF
2512
        jz      .test_short_name_cont
2515
        jz      .test_short_name_cont
2513
        mov     ecx, 11
2516
        mov     ecx, 11
2514
        push    esi edi
2517
        push    esi edi
2515
        repz cmpsb
2518
        repz cmpsb
2516
        pop     edi esi
2519
        pop     edi esi
2517
        jz      .short_name_found
2520
        jz      .short_name_found
2518
.test_short_name_cont:
2521
.test_short_name_cont:
2519
        lea     eax, [esp+12+12+8]
2522
        lea     eax, [esp+12+12+8]
2520
        call    dword [eax-8]
2523
        call    dword [eax-8]
2521
        jnc     .test_short_name_entry
2524
        jnc     .test_short_name_entry
2522
        jmp     .found
2525
        jmp     .found
2523
.short_name_found:
2526
.short_name_found:
2524
        pop     ecx edi esi
2527
        pop     ecx edi esi
2525
        call    fat_next_short_name
2528
        call    fat_next_short_name
2526
        jnc     .test_short_name_loop
2529
        jnc     .test_short_name_loop
2527
.disk_full:
2530
.disk_full:
2528
        add     esp, 12+36
2531
        add     esp, 12+36
2529
        call    fat_unlock
2532
        call    fat_unlock
2530
        popa
2533
        popa
2531
        mov     eax, ERROR_DISK_FULL
2534
        mov     eax, ERROR_DISK_FULL
2532
        xor     ebx, ebx
2535
        xor     ebx, ebx
2533
        ret
2536
        ret
2534
.found:
2537
.found:
2535
        pop     ecx edi esi
2538
        pop     ecx edi esi
2536
; now find space in directory
2539
; now find space in directory
2537
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
2540
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
2538
        mov     al, '~'
2541
        mov     al, '~'
2539
        push    ecx edi
2542
        push    ecx edi
2540
        mov     ecx, 8
2543
        mov     ecx, 8
2541
        repnz scasb
2544
        repnz scasb
2542
        movi    eax, 1     ; 1 entry
2545
        movi    eax, 1     ; 1 entry
2543
        jnz     .notilde
2546
        jnz     .notilde
2544
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
2547
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
2545
        xor     eax, eax
2548
        xor     eax, eax
2546
@@:
2549
@@:
2547
        cmp     byte [esi], 0
2550
        cmp     byte [esi], 0
2548
        jz      @f
2551
        jz      @f
2549
        inc     esi
2552
        inc     esi
2550
        inc     eax
2553
        inc     eax
2551
        jmp     @b
2554
        jmp     @b
2552
@@:
2555
@@:
2553
        sub     esi, eax
2556
        sub     esi, eax
2554
        add     eax, 12+13
2557
        add     eax, 12+13
2555
        mov     ecx, 13
2558
        mov     ecx, 13
2556
        push    edx
2559
        push    edx
2557
        cdq
2560
        cdq
2558
        div     ecx
2561
        div     ecx
2559
        pop     edx
2562
        pop     edx
2560
.notilde:
2563
.notilde:
2561
        push    -1
2564
        push    -1
2562
        push    -1
2565
        push    -1
2563
        push    -1
2566
        push    -1
2564
; find  successive entries in directory
2567
; find  successive entries in directory
2565
        xor     ecx, ecx
2568
        xor     ecx, ecx
2566
        push    eax
2569
        push    eax
2567
        lea     eax, [esp+16+8+12+8]
2570
        lea     eax, [esp+16+8+12+8]
2568
        mov     edx, [eax+24]
2571
        mov     edx, [eax+24]
2569
        mov     [eax], edx
2572
        mov     [eax], edx
2570
        and     dword [eax+4], 0
2573
        and     dword [eax+4], 0
2571
        call    dword [eax-4]
2574
        call    dword [eax-4]
2572
        pop     eax
2575
        pop     eax
2573
        jnc     .scan_dir
2576
        jnc     .scan_dir
2574
.fsfrfe3:
2577
.fsfrfe3:
2575
        add     esp, 12+8+12+36
2578
        add     esp, 12+8+12+36
2576
        call    fat_unlock
2579
        call    fat_unlock
2577
        popad
2580
        popad
2578
        mov     eax, ERROR_DEVICE
2581
        mov     eax, ERROR_DEVICE
2579
        xor     ebx, ebx
2582
        xor     ebx, ebx
2580
        ret
2583
        ret
2581
.scan_dir:
2584
.scan_dir:
2582
        cmp     byte [edi], 0
2585
        cmp     byte [edi], 0
2583
        jz      .free
2586
        jz      .free
2584
        cmp     byte [edi], 0xE5
2587
        cmp     byte [edi], 0xE5
2585
        jz      .free
2588
        jz      .free
2586
        xor     ecx, ecx
2589
        xor     ecx, ecx
2587
.scan_cont:
2590
.scan_cont:
2588
        push    eax
2591
        push    eax
2589
        lea     eax, [esp+16+8+12+8]
2592
        lea     eax, [esp+16+8+12+8]
2590
        call    dword [eax-8]
2593
        call    dword [eax-8]
2591
        mov     edx, eax
2594
        mov     edx, eax
2592
        pop     eax
2595
        pop     eax
2593
        jnc     .scan_dir
2596
        jnc     .scan_dir
2594
        cmp     edx, ERROR_DEVICE
2597
        cmp     edx, ERROR_DEVICE
2595
        jz      .fsfrfe3
2598
        jz      .fsfrfe3
2596
        push    eax
2599
        push    eax
2597
        lea     eax, [esp+16+8+12+8]
2600
        lea     eax, [esp+16+8+12+8]
2598
        call    dword [eax+20]          ; extend directory
2601
        call    dword [eax+20]          ; extend directory
2599
        pop     eax
2602
        pop     eax
2600
        jnc     .scan_dir
2603
        jnc     .scan_dir
2601
        add     esp, 12+8+12+36
2604
        add     esp, 12+8+12+36
2602
        call    fat_unlock
2605
        call    fat_unlock
2603
        popad
2606
        popad
2604
        mov     eax, ERROR_DISK_FULL
2607
        mov     eax, ERROR_DISK_FULL
2605
        xor     ebx, ebx
2608
        xor     ebx, ebx
2606
        ret
2609
        ret
2607
.free:
2610
.free:
2608
        test    ecx, ecx
2611
        test    ecx, ecx
2609
        jnz     @f
2612
        jnz     @f
2610
        mov     [esp], edi
2613
        mov     [esp], edi
2611
        mov     ecx, [esp+12+8+12+8]
2614
        mov     ecx, [esp+12+8+12+8]
2612
        mov     [esp+4], ecx
2615
        mov     [esp+4], ecx
2613
        mov     ecx, [esp+12+8+12+12]
2616
        mov     ecx, [esp+12+8+12+12]
2614
        mov     [esp+8], ecx
2617
        mov     [esp+8], ecx
2615
        xor     ecx, ecx
2618
        xor     ecx, ecx
2616
@@:
2619
@@:
2617
        inc     ecx
2620
        inc     ecx
2618
        cmp     ecx, eax
2621
        cmp     ecx, eax
2619
        jb      .scan_cont
2622
        jb      .scan_cont
2620
; found!
2623
; found!
2621
        push    esi ecx
2624
        push    esi ecx
2622
; If creating a directory, allocate one data cluster now and fail immediately
2625
; If creating a directory, allocate one data cluster now and fail immediately
2623
; if this is impossible. This prevents from creating an invalid directory entry
2626
; if this is impossible. This prevents from creating an invalid directory entry
2624
; on a full disk.
2627
; on a full disk.
2625
; yup, the argument is quite non-intuitive... but what should I do if
2628
; yup, the argument is quite non-intuitive... but what should I do if
2626
; the entire function uses such arguments? BTW, it refers to al from pushad,
2629
; the entire function uses such arguments? BTW, it refers to al from pushad,
2627
; which in turn is filled with 0 in fat_Rewrite and 1 in fat_CreateFolder.
2630
; which in turn is filled with 0 in fat_Rewrite and 1 in fat_CreateFolder.
2628
        cmp     byte [esp+8+12+8+12+36+28], 0
2631
        cmp     byte [esp+8+12+8+12+36+28], 0
2629
        jz      .no.preallocate.folder.data
2632
        jz      .no.preallocate.folder.data
2630
        call    get_free_FAT
2633
        call    get_free_FAT
2631
        jnc     @f
2634
        jnc     @f
2632
        add     esp, 8+12+8
2635
        add     esp, 8+12+8
2633
        jmp     .disk_full
2636
        jmp     .disk_full
2634
@@:
2637
@@:
2635
        mov     [esp+8+12+8+12+36+20], eax ; store the cluster somewhere
2638
        mov     [esp+8+12+8+12+36+20], eax ; store the cluster somewhere
2636
.no.preallocate.folder.data:
2639
.no.preallocate.folder.data:
2637
; calculate name checksum
2640
; calculate name checksum
2638
        mov     esi, [esp+8+12]
2641
        mov     esi, [esp+8+12]
2639
        mov     ecx, 11
2642
        mov     ecx, 11
2640
        xor     eax, eax
2643
        xor     eax, eax
2641
@@:
2644
@@:
2642
        ror     al, 1
2645
        ror     al, 1
2643
        add     al, [esi]
2646
        add     al, [esi]
2644
        inc     esi
2647
        inc     esi
2645
        loop    @b
2648
        loop    @b
2646
        pop     ecx esi
2649
        pop     ecx esi
2647
        pop     edi
2650
        pop     edi
2648
        pop     dword [esp+8+12+12]
2651
        pop     dword [esp+8+12+12]
2649
        pop     dword [esp+8+12+12]
2652
        pop     dword [esp+8+12+12]
2650
; edi points to first entry in free chunk
2653
; edi points to first entry in free chunk
2651
        dec     ecx
2654
        dec     ecx
2652
        jz      .nolfn
2655
        jz      .nolfn
2653
        push    esi
2656
        push    esi
2654
        push    eax
2657
        push    eax
2655
        lea     eax, [esp+8+8+12+8]
2658
        lea     eax, [esp+8+8+12+8]
2656
        call    dword [eax+8]         ; begin write
2659
        call    dword [eax+8]         ; begin write
2657
        mov     al, 40h
2660
        mov     al, 40h
2658
.writelfn:
2661
.writelfn:
2659
        or      al, cl
2662
        or      al, cl
2660
        mov     esi, [esp+4]
2663
        mov     esi, [esp+4]
2661
        push    ecx
2664
        push    ecx
2662
        dec     ecx
2665
        dec     ecx
2663
        imul    ecx, 13
2666
        imul    ecx, 13
2664
        add     esi, ecx
2667
        add     esi, ecx
2665
        stosb
2668
        stosb
2666
        mov     cl, 5
2669
        mov     cl, 5
2667
        call    fat_read_symbols
2670
        call    fat_read_symbols
2668
        mov     ax, 0xF
2671
        mov     ax, 0xF
2669
        stosw
2672
        stosw
2670
        mov     al, [esp+4]
2673
        mov     al, [esp+4]
2671
        stosb
2674
        stosb
2672
        mov     cl, 6
2675
        mov     cl, 6
2673
        call    fat_read_symbols
2676
        call    fat_read_symbols
2674
        xor     eax, eax
2677
        xor     eax, eax
2675
        stosw
2678
        stosw
2676
        mov     cl, 2
2679
        mov     cl, 2
2677
        call    fat_read_symbols
2680
        call    fat_read_symbols
2678
        pop     ecx
2681
        pop     ecx
2679
        lea     eax, [esp+8+8+12+8]
2682
        lea     eax, [esp+8+8+12+8]
2680
        call    dword [eax+12]         ; next write
2683
        call    dword [eax+12]         ; next write
2681
        xor     eax, eax
2684
        xor     eax, eax
2682
        loop    .writelfn
2685
        loop    .writelfn
2683
        pop     eax
2686
        pop     eax
2684
        pop     esi
2687
        pop     esi
2685
;        lea     eax, [esp+8+12+8]
2688
;        lea     eax, [esp+8+12+8]
2686
;        call    dword [eax+16]          ; end write
2689
;        call    dword [eax+16]          ; end write
2687
.nolfn:
2690
.nolfn:
2688
        xchg    esi, [esp]
2691
        xchg    esi, [esp]
2689
        mov     ecx, 11
2692
        mov     ecx, 11
2690
        rep movsb
2693
        rep movsb
2691
        mov     word [edi], 20h         ; attributes
2694
        mov     word [edi], 20h         ; attributes
2692
        sub     edi, 11
2695
        sub     edi, 11
2693
        pop     esi ecx
2696
        pop     esi ecx
2694
        add     esp, 12
2697
        add     esp, 12
2695
        mov     byte [edi+13], 0        ; tenths of a second at file creation time
2698
        mov     byte [edi+13], 0        ; tenths of a second at file creation time
2696
        call    get_time_for_file
2699
        call    get_time_for_file
2697
        mov     [edi+14], ax            ; creation time
2700
        mov     [edi+14], ax            ; creation time
2698
        mov     [edi+22], ax            ; last write time
2701
        mov     [edi+22], ax            ; last write time
2699
        call    get_date_for_file
2702
        call    get_date_for_file
2700
        mov     [edi+16], ax            ; creation date
2703
        mov     [edi+16], ax            ; creation date
2701
        mov     [edi+24], ax            ; last write date
2704
        mov     [edi+24], ax            ; last write date
2702
        mov     [edi+18], ax            ; last access date
2705
        mov     [edi+18], ax            ; last access date
2703
        xor     ecx, ecx
2706
        xor     ecx, ecx
2704
        mov     word [edi+20], cx       ; high word of cluster
2707
        mov     word [edi+20], cx       ; high word of cluster
2705
        mov     word [edi+26], cx       ; low word of cluster - to be filled
2708
        mov     word [edi+26], cx       ; low word of cluster - to be filled
2706
        mov     dword [edi+28], ecx     ; file size - to be filled
2709
        mov     dword [edi+28], ecx     ; file size - to be filled
2707
        cmp     byte [esp+36+28], cl
2710
        cmp     byte [esp+36+28], cl
2708
        jz      .doit
2711
        jz      .doit
2709
; create directory
2712
; create directory
2710
        mov     byte [edi+11], 10h      ; attributes: folder
2713
        mov     byte [edi+11], 10h      ; attributes: folder
2711
        mov     esi, edi
2714
        mov     esi, edi
2712
        lea     eax, [esp+8]
2715
        lea     eax, [esp+8]
2713
        call    dword [eax+16]  ; flush directory
2716
        call    dword [eax+16]  ; flush directory
2714
        mov     eax, [esp+36+20] ; extract saved cluster
2717
        mov     eax, [esp+36+20] ; extract saved cluster
2715
        mov     [esp+36+20], edi ; this is needed for calculating arg of add_disk_free_space!
2718
        mov     [esp+36+20], edi ; this is needed for calculating arg of add_disk_free_space!
2716
        push    ecx
2719
        push    ecx
2717
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2720
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2718
        shl     ecx, 9
2721
        shl     ecx, 9
2719
        push    ecx
2722
        push    ecx
2720
        push    edi
2723
        push    edi
2721
        jmp     .doit2
2724
        jmp     .doit2
2722
.doit:
2725
.doit:
2723
        mov     esi, [esp+36+20]
2726
        mov     esi, [esp+36+20]
2724
        lea     eax, [esp+8]
2727
        lea     eax, [esp+8]
2725
        call    dword [eax+16]  ; flush directory
2728
        call    dword [eax+16]  ; flush directory
2726
        push    ecx
2729
        push    ecx
2727
        mov     ecx, [esp+4+36+24]
2730
        mov     ecx, [esp+4+36+24]
2728
        push    ecx
2731
        push    ecx
2729
        push    edi
2732
        push    edi
2730
        test    ecx, ecx
2733
        test    ecx, ecx
2731
        jz      .done
2734
        jz      .done
2732
        call    get_free_FAT
2735
        call    get_free_FAT
2733
        jc      .diskfull
2736
        jc      .diskfull
2734
.doit2:
2737
.doit2:
2735
        push    eax
2738
        push    eax
2736
        mov     [edi+26], ax
2739
        mov     [edi+26], ax
2737
        shr     eax, 16
2740
        shr     eax, 16
2738
        mov     [edi+20], ax
2741
        mov     [edi+20], ax
2739
        lea     eax, [esp+16+8]
2742
        lea     eax, [esp+16+8]
2740
        call    dword [eax+16]  ; flush directory
2743
        call    dword [eax+16]  ; flush directory
2741
        pop     eax
2744
        pop     eax
2742
        push    edx
2745
        push    edx
2743
        mov     edx, [ebp+FAT.fatEND]
2746
        mov     edx, [ebp+FAT.fatEND]
2744
        call    set_FAT
2747
        call    set_FAT
2745
        pop     edx
2748
        pop     edx
2746
.write_cluster:
2749
.write_cluster:
2747
        push    eax
2750
        push    eax
2748
        dec     eax
2751
        dec     eax
2749
        dec     eax
2752
        dec     eax
2750
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2753
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
2751
        add     eax, [ebp+FAT.DATA_START]
2754
        add     eax, [ebp+FAT.DATA_START]
2752
        push    [ebp+FAT.SECTORS_PER_CLUSTER]
2755
        push    [ebp+FAT.SECTORS_PER_CLUSTER]
2753
; write data
2756
; write data
2754
.write_sector:
2757
.write_sector:
2755
        cmp     byte [esp+20+36+28], 0
2758
        cmp     byte [esp+20+36+28], 0
2756
        jnz     .writedir
2759
        jnz     .writedir
2757
        mov     ecx, 512
2760
        mov     ecx, 512
2758
        cmp     dword [esp+12], ecx
2761
        cmp     dword [esp+12], ecx
2759
        jb      .writeshort
2762
        jb      .writeshort
2760
; we can write directly from given buffer
2763
; we can write directly from given buffer
2761
        mov     ebx, esi
2764
        mov     ebx, esi
2762
        add     esi, ecx
2765
        add     esi, ecx
2763
        jmp     .writecommon
2766
        jmp     .writecommon
2764
.writeshort:
2767
.writeshort:
2765
        mov     ecx, [esp+12]
2768
        mov     ecx, [esp+12]
2766
        push    ecx
2769
        push    ecx
2767
        lea     edi, [ebp+FAT.buffer]
2770
        lea     edi, [ebp+FAT.buffer]
2768
        mov     ebx, edi
2771
        mov     ebx, edi
2769
        rep movsb
2772
        rep movsb
2770
.writedircont:
2773
.writedircont:
2771
        lea     ecx, [ebp+FAT.buffer+0x200]
2774
        lea     ecx, [ebp+FAT.buffer+0x200]
2772
        sub     ecx, edi
2775
        sub     ecx, edi
2773
        push    eax
2776
        push    eax
2774
        xor     eax, eax
2777
        xor     eax, eax
2775
        rep stosb
2778
        rep stosb
2776
        pop     eax
2779
        pop     eax
2777
        pop     ecx
2780
        pop     ecx
2778
.writecommon:
2781
.writecommon:
2779
        push    eax
2782
        push    eax
2780
        call    fs_write32_app
2783
        call    fs_write32_app
2781
        test    eax, eax
2784
        test    eax, eax
2782
        pop     eax
2785
        pop     eax
2783
        jnz     .writeerr
2786
        jnz     .writeerr
2784
        inc     eax
2787
        inc     eax
2785
        sub     dword [esp+12], ecx
2788
        sub     dword [esp+12], ecx
2786
        jz      .writedone
2789
        jz      .writedone
2787
        dec     dword [esp]
2790
        dec     dword [esp]
2788
        jnz     .write_sector
2791
        jnz     .write_sector
2789
        pop     eax
2792
        pop     eax
2790
; allocate new cluster
2793
; allocate new cluster
2791
        pop     eax
2794
        pop     eax
2792
        mov     ecx, eax
2795
        mov     ecx, eax
2793
        call    get_free_FAT
2796
        call    get_free_FAT
2794
        jc      .diskfull
2797
        jc      .diskfull
2795
        push    edx
2798
        push    edx
2796
        mov     edx, [ebp+FAT.fatEND]
2799
        mov     edx, [ebp+FAT.fatEND]
2797
        call    set_FAT
2800
        call    set_FAT
2798
        xchg    eax, ecx
2801
        xchg    eax, ecx
2799
        mov     edx, ecx
2802
        mov     edx, ecx
2800
        call    set_FAT
2803
        call    set_FAT
2801
        pop     edx
2804
        pop     edx
2802
        xchg    eax, ecx
2805
        xchg    eax, ecx
2803
        jmp     .write_cluster
2806
        jmp     .write_cluster
2804
.diskfull:
2807
.diskfull:
2805
        mov     eax, ERROR_DISK_FULL
2808
        mov     eax, ERROR_DISK_FULL
2806
        jmp     .ret
2809
        jmp     .ret
2807
.writeerr:
2810
.writeerr:
2808
        pop     eax eax
2811
        pop     eax eax
2809
        sub     esi, ecx
2812
        sub     esi, ecx
2810
        mov     eax, ERROR_DEVICE
2813
        mov     eax, ERROR_DEVICE
2811
        jmp     .ret
2814
        jmp     .ret
2812
.writedone:
2815
.writedone:
2813
        pop     eax eax
2816
        pop     eax eax
2814
.done:
2817
.done:
2815
        xor     eax, eax
2818
        xor     eax, eax
2816
.ret:
2819
.ret:
2817
        pop     edi ecx
2820
        pop     edi ecx
2818
        sub     esi, [esp+4+36+20]
2821
        sub     esi, [esp+4+36+20]
2819
        mov     [esp+4+36+28], eax
2822
        mov     [esp+4+36+28], eax
2820
        mov     [esp+4+36+16], esi
2823
        mov     [esp+4+36+16], esi
2821
        lea     eax, [esp+12]
2824
        lea     eax, [esp+12]
2822
        call    dword [eax+8]
2825
        call    dword [eax+8]
2823
        mov     [edi+28], esi
2826
        mov     [edi+28], esi
2824
        call    dword [eax+16]
2827
        call    dword [eax+16]
2825
        mov     [esp+36+16], ebx
2828
        mov     [esp+36+16], ebx
2826
        lea     eax, [esi+511]
2829
        lea     eax, [esi+511]
2827
        shr     eax, 9
2830
        shr     eax, 9
2828
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2831
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2829
        lea     eax, [eax+ecx-1]
2832
        lea     eax, [eax+ecx-1]
2830
        xor     edx, edx
2833
        xor     edx, edx
2831
        div     ecx
2834
        div     ecx
2832
        pop     ecx
2835
        pop     ecx
2833
        sub     ecx, eax
2836
        sub     ecx, eax
2834
        call    add_disk_free_space
2837
        call    add_disk_free_space
2835
        add     esp, 36
2838
        add     esp, 36
2836
        call    update_disk
2839
        call    update_disk
2837
        call    fat_unlock
2840
        call    fat_unlock
2838
        popad
2841
        popad
2839
        ret
2842
        ret
2840
.writedir:
2843
.writedir:
2841
        push    512
2844
        push    512
2842
        lea     edi, [ebp+FAT.buffer]
2845
        lea     edi, [ebp+FAT.buffer]
2843
        mov     ebx, edi
2846
        mov     ebx, edi
2844
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2847
        mov     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
2845
        shl     ecx, 9
2848
        shl     ecx, 9
2846
        cmp     ecx, [esp+16]
2849
        cmp     ecx, [esp+16]
2847
        jnz     .writedircont
2850
        jnz     .writedircont
2848
        dec     dword [esp+20]
2851
        dec     dword [esp+20]
2849
        push    esi
2852
        push    esi
2850
        mov     ecx, 32/4
2853
        mov     ecx, 32/4
2851
        rep movsd
2854
        rep movsd
2852
        pop     esi
2855
        pop     esi
2853
        mov     dword [edi-32], '.   '
2856
        mov     dword [edi-32], '.   '
2854
        mov     dword [edi-32+4], '    '
2857
        mov     dword [edi-32+4], '    '
2855
        mov     dword [edi-32+8], '    '
2858
        mov     dword [edi-32+8], '    '
2856
        mov     byte [edi-32+11], 10h
2859
        mov     byte [edi-32+11], 10h
2857
        push    esi
2860
        push    esi
2858
        mov     ecx, 32/4
2861
        mov     ecx, 32/4
2859
        rep movsd
2862
        rep movsd
2860
        pop     esi
2863
        pop     esi
2861
        mov     dword [edi-32], '..  '
2864
        mov     dword [edi-32], '..  '
2862
        mov     dword [edi-32+4], '    '
2865
        mov     dword [edi-32+4], '    '
2863
        mov     dword [edi-32+8], '    '
2866
        mov     dword [edi-32+8], '    '
2864
        mov     byte [edi-32+11], 10h
2867
        mov     byte [edi-32+11], 10h
2865
        mov     ecx, [esp+20+36]
2868
        mov     ecx, [esp+20+36]
2866
        cmp     ecx, [ebp+FAT.ROOT_CLUSTER]
2869
        cmp     ecx, [ebp+FAT.ROOT_CLUSTER]
2867
        jnz     @f
2870
        jnz     @f
2868
        xor     ecx, ecx
2871
        xor     ecx, ecx
2869
@@:
2872
@@:
2870
        mov     word [edi-32+26], cx
2873
        mov     word [edi-32+26], cx
2871
        shr     ecx, 16
2874
        shr     ecx, 16
2872
        mov     [edi-32+20], cx
2875
        mov     [edi-32+20], cx
2873
        jmp     .writedircont
2876
        jmp     .writedircont
2874
 
2877
 
2875
fat_read_symbol:
2878
fat_read_symbol:
2876
        or      ax, -1
2879
        or      ax, -1
2877
        test    esi, esi
2880
        test    esi, esi
2878
        jz      .retFFFF
2881
        jz      .retFFFF
2879
        lodsb
2882
        lodsb
2880
        test    al, al
2883
        test    al, al
2881
        jnz     ansi2uni_char
2884
        jnz     ansi2uni_char
2882
        xor     eax, eax
2885
        xor     eax, eax
2883
        xor     esi, esi
2886
        xor     esi, esi
2884
.retFFFF:
2887
.retFFFF:
2885
        ret
2888
        ret
2886
 
2889
 
2887
fat_read_symbols:
2890
fat_read_symbols:
2888
        call    fat_read_symbol
2891
        call    fat_read_symbol
2889
        stosw
2892
        stosw
2890
        loop    fat_read_symbols
2893
        loop    fat_read_symbols
2891
        ret
2894
        ret
2892
 
2895
 
2893
 
2896
 
2894
fat_Write.access_denied:
2897
fat_Write.access_denied:
2895
        push    ERROR_ACCESS_DENIED
2898
        push    ERROR_ACCESS_DENIED
2896
fat_Write.ret0:
2899
fat_Write.ret0:
2897
        pop     eax
2900
        pop     eax
2898
        xor     ebx, ebx
2901
        xor     ebx, ebx
2899
        ret
2902
        ret
2900
 
2903
 
2901
fat_Write.ret11:
2904
fat_Write.ret11:
2902
        push    ERROR_DEVICE
2905
        push    ERROR_DEVICE
2903
        jmp     fat_Write.ret0
2906
        jmp     fat_Write.ret0
2904
 
2907
 
2905
;----------------------------------------------------------------
2908
;----------------------------------------------------------------
2906
; fat_Write - FAT implementation of writing to file
2909
; fat_Write - FAT implementation of writing to file
2907
; in:  ebp = pointer to FAT structure
2910
; in:  ebp = pointer to FAT structure
2908
; in:  esi+[esp+4] = name
2911
; in:  esi+[esp+4] = name
2909
; in:  ebx = pointer to parameters from sysfunc 70
2912
; in:  ebx = pointer to parameters from sysfunc 70
2910
; out: eax, ebx = return values for sysfunc 70
2913
; out: eax, ebx = return values for sysfunc 70
2911
;----------------------------------------------------------------
2914
;----------------------------------------------------------------
2912
fat_Write:
2915
fat_Write:
2913
        cmp     byte [esi], 0
2916
        cmp     byte [esi], 0
2914
        jz      .access_denied
2917
        jz      .access_denied
2915
        call    fat_lock
2918
        call    fat_lock
2916
        push    edi
2919
        push    edi
2917
        stdcall hd_find_lfn, [esp+4+4]
2920
        stdcall hd_find_lfn, [esp+4+4]
2918
        jnc     .found
2921
        jnc     .found
2919
        pop     edi
2922
        pop     edi
2920
        push    eax
2923
        push    eax
2921
        call    fat_unlock
2924
        call    fat_unlock
2922
        jmp     .ret0
2925
        jmp     .ret0
2923
.found:
2926
.found:
2924
; FAT does not support files larger than 4GB
2927
; FAT does not support files larger than 4GB
2925
        cmp     dword [ebx+8], 0
2928
        cmp     dword [ebx+8], 0
2926
        jz      @f
2929
        jz      @f
2927
.eof:
2930
.eof:
2928
        pop     edi
2931
        pop     edi
2929
        push    ERROR_END_OF_FILE
2932
        push    ERROR_END_OF_FILE
2930
        call    fat_unlock
2933
        call    fat_unlock
2931
        jmp     .ret0
2934
        jmp     .ret0
2932
@@:
2935
@@:
2933
        mov     ecx, [ebx+12]
2936
        mov     ecx, [ebx+12]
2934
        mov     edx, [ebx+16]
2937
        mov     edx, [ebx+16]
2935
        mov     ebx, [ebx+4]
2938
        mov     ebx, [ebx+4]
2936
; now edi points to direntry, ebx=start byte to write,
2939
; now edi points to direntry, ebx=start byte to write,
2937
; ecx=number of bytes to write, edx=data pointer
2940
; ecx=number of bytes to write, edx=data pointer
2938
 
2941
 
2939
; extend file if needed
2942
; extend file if needed
2940
        add     ecx, ebx
2943
        add     ecx, ebx
2941
        jc      .eof    ; FAT does not support files larger than 4GB
2944
        jc      .eof    ; FAT does not support files larger than 4GB
2942
        push    edx
2945
        push    edx
2943
        push    eax     ; save directory sector
2946
        push    eax     ; save directory sector
2944
        push    0       ; return value=0
2947
        push    0       ; return value=0
2945
 
2948
 
2946
        call    get_time_for_file
2949
        call    get_time_for_file
2947
        mov     [edi+22], ax            ; last write time
2950
        mov     [edi+22], ax            ; last write time
2948
        call    get_date_for_file
2951
        call    get_date_for_file
2949
        mov     [edi+24], ax            ; last write date
2952
        mov     [edi+24], ax            ; last write date
2950
        mov     [edi+18], ax            ; last access date
2953
        mov     [edi+18], ax            ; last access date
2951
 
2954
 
2952
        push    dword [edi+28]          ; save current file size
2955
        push    dword [edi+28]          ; save current file size
2953
        cmp     ecx, [edi+28]
2956
        cmp     ecx, [edi+28]
2954
        jbe     .length_ok
2957
        jbe     .length_ok
2955
        cmp     ecx, ebx
2958
        cmp     ecx, ebx
2956
        jz      .length_ok
2959
        jz      .length_ok
2957
        call    hd_extend_file
2960
        call    hd_extend_file
2958
        jnc     .length_ok
2961
        jnc     .length_ok
2959
        mov     [esp+4], eax
2962
        mov     [esp+4], eax
2960
; hd_extend_file can return three error codes: FAT table error, device error or disk full.
2963
; hd_extend_file can return three error codes: FAT table error, device error or disk full.
2961
; First two cases are fatal errors, in third case we may write some data
2964
; First two cases are fatal errors, in third case we may write some data
2962
        cmp     al, ERROR_DISK_FULL
2965
        cmp     al, ERROR_DISK_FULL
2963
        jz      .disk_full
2966
        jz      .disk_full
2964
        call    fat_unlock
2967
        call    fat_unlock
2965
        pop     eax
2968
        pop     eax
2966
        pop     eax
2969
        pop     eax
2967
        pop     ecx
2970
        pop     ecx
2968
        pop     edx
2971
        pop     edx
2969
        pop     edi
2972
        pop     edi
2970
        xor     ebx, ebx
2973
        xor     ebx, ebx
2971
        ret
2974
        ret
2972
.disk_full:
2975
.disk_full:
2973
; correct number of bytes to write
2976
; correct number of bytes to write
2974
        mov     ecx, [edi+28]
2977
        mov     ecx, [edi+28]
2975
        cmp     ecx, ebx
2978
        cmp     ecx, ebx
2976
        ja      .length_ok
2979
        ja      .length_ok
2977
        push    0
2980
        push    0
2978
.ret:
2981
.ret:
2979
        pop     eax
2982
        pop     eax
2980
        sub     edx, [esp+12]
2983
        sub     edx, [esp+12]
2981
        mov     ebx, edx        ; ebx=number of written bytes
2984
        mov     ebx, edx        ; ebx=number of written bytes
2982
        call    update_disk
2985
        call    update_disk
2983
        test    eax, eax
2986
        test    eax, eax
2984
        jz      @f
2987
        jz      @f
2985
        mov     byte [esp+4], ERROR_DEVICE
2988
        mov     byte [esp+4], ERROR_DEVICE
2986
@@:
2989
@@:
2987
        call    fat_unlock
2990
        call    fat_unlock
2988
        pop     eax
2991
        pop     eax
2989
        pop     eax
2992
        pop     eax
2990
        pop     ecx
2993
        pop     ecx
2991
        pop     edx
2994
        pop     edx
2992
        pop     edi
2995
        pop     edi
2993
        ret
2996
        ret
2994
.length_ok:
2997
.length_ok:
2995
        mov     esi, [edi+28]
2998
        mov     esi, [edi+28]
2996
        mov     eax, [edi+20-2]
2999
        mov     eax, [edi+20-2]
2997
        mov     ax, [edi+26]
3000
        mov     ax, [edi+26]
2998
        mov     edi, eax        ; edi=current cluster
3001
        mov     edi, eax        ; edi=current cluster
2999
        push    0               ; current sector in cluster
3002
        push    0               ; current sector in cluster
3000
; save directory
3003
; save directory
3001
        mov     eax, [esp+12]
3004
        mov     eax, [esp+12]
3002
        push    ebx
3005
        push    ebx
3003
        lea     ebx, [ebp+FAT.buffer]
3006
        lea     ebx, [ebp+FAT.buffer]
3004
        call    fs_write32_sys
3007
        call    fs_write32_sys
3005
        pop     ebx
3008
        pop     ebx
3006
        test    eax, eax
3009
        test    eax, eax
3007
        jz      @f
3010
        jz      @f
3008
.device_err:
3011
.device_err:
3009
        mov     byte [esp+8], ERROR_DEVICE
3012
        mov     byte [esp+8], ERROR_DEVICE
3010
        jmp     .ret
3013
        jmp     .ret
3011
.fat_err:
3014
.fat_err:
3012
        mov     byte [esp+8], ERROR_FAT_TABLE
3015
        mov     byte [esp+8], ERROR_FAT_TABLE
3013
        jmp     .ret
3016
        jmp     .ret
3014
@@:
3017
@@:
3015
 
3018
 
3016
; now ebx=start pos, ecx=end pos, both lie inside file
3019
; now ebx=start pos, ecx=end pos, both lie inside file
3017
        sub     ecx, ebx
3020
        sub     ecx, ebx
3018
        jz      .ret
3021
        jz      .ret
3019
.write_loop:
3022
.write_loop:
3020
; skip unmodified sectors
3023
; skip unmodified sectors
3021
        cmp     dword [esp+4], 0x200
3024
        cmp     dword [esp+4], 0x200
3022
        jb      .modify
3025
        jb      .modify
3023
        sub     ebx, 0x200
3026
        sub     ebx, 0x200
3024
        jae     .skip
3027
        jae     .skip
3025
        add     ebx, 0x200
3028
        add     ebx, 0x200
3026
.modify:
3029
.modify:
3027
; get length of data in current sector
3030
; get length of data in current sector
3028
        push    ecx
3031
        push    ecx
3029
        sub     ebx, 0x200
3032
        sub     ebx, 0x200
3030
        jb      .hasdata
3033
        jb      .hasdata
3031
        neg     ebx
3034
        neg     ebx
3032
        xor     ecx, ecx
3035
        xor     ecx, ecx
3033
        jmp     @f
3036
        jmp     @f
3034
.hasdata:
3037
.hasdata:
3035
        neg     ebx
3038
        neg     ebx
3036
        cmp     ecx, ebx
3039
        cmp     ecx, ebx
3037
        jbe     @f
3040
        jbe     @f
3038
        mov     ecx, ebx
3041
        mov     ecx, ebx
3039
@@:
3042
@@:
3040
; get current sector number
3043
; get current sector number
3041
        mov     eax, edi
3044
        mov     eax, edi
3042
        dec     eax
3045
        dec     eax
3043
        dec     eax
3046
        dec     eax
3044
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3047
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3045
        add     eax, [ebp+FAT.DATA_START]
3048
        add     eax, [ebp+FAT.DATA_START]
3046
        add     eax, [esp+4]
3049
        add     eax, [esp+4]
3047
; load sector if needed
3050
; load sector if needed
3048
        cmp     dword [esp+8], 0        ; we don't need to read uninitialized data
3051
        cmp     dword [esp+8], 0        ; we don't need to read uninitialized data
3049
        jz      .noread
3052
        jz      .noread
3050
        cmp     ecx, 0x200      ; we don't need to read sector if it is fully rewritten
3053
        cmp     ecx, 0x200      ; we don't need to read sector if it is fully rewritten
3051
        jz      .noread
3054
        jz      .noread
3052
        cmp     ecx, esi        ; (same for the last sector)
3055
        cmp     ecx, esi        ; (same for the last sector)
3053
        jz      .noread
3056
        jz      .noread
3054
        push    eax ebx
3057
        push    eax ebx
3055
        lea     ebx, [ebp+FAT.buffer]
3058
        lea     ebx, [ebp+FAT.buffer]
3056
        call    fs_read32_app
3059
        call    fs_read32_app
3057
        test    eax, eax
3060
        test    eax, eax
3058
        pop     ebx eax
3061
        pop     ebx eax
3059
        jz      @f
3062
        jz      @f
3060
.device_err2:
3063
.device_err2:
3061
        pop     ecx
3064
        pop     ecx
3062
        jmp     .device_err
3065
        jmp     .device_err
3063
@@:
3066
@@:
3064
.noread:
3067
.noread:
3065
; zero uninitialized data if file was extended (because hd_extend_file does not this)
3068
; zero uninitialized data if file was extended (because hd_extend_file does not this)
3066
        push    eax ecx edi
3069
        push    eax ecx edi
3067
        xor     eax, eax
3070
        xor     eax, eax
3068
        mov     ecx, 0x200
3071
        mov     ecx, 0x200
3069
        sub     ecx, [esp+8+12]
3072
        sub     ecx, [esp+8+12]
3070
        jbe     @f
3073
        jbe     @f
3071
        lea     edi, [ebp+FAT.buffer]
3074
        lea     edi, [ebp+FAT.buffer]
3072
        add     edi, [esp+8+12]
3075
        add     edi, [esp+8+12]
3073
        rep stosb
3076
        rep stosb
3074
@@:
3077
@@:
3075
; zero uninitialized data in the last sector
3078
; zero uninitialized data in the last sector
3076
        mov     ecx, 0x200
3079
        mov     ecx, 0x200
3077
        sub     ecx, esi
3080
        sub     ecx, esi
3078
        jbe     @f
3081
        jbe     @f
3079
        lea     edi, [ebp+FAT.buffer+esi]
3082
        lea     edi, [ebp+FAT.buffer+esi]
3080
        rep stosb
3083
        rep stosb
3081
@@:
3084
@@:
3082
        pop     edi ecx
3085
        pop     edi ecx
3083
; copy new data
3086
; copy new data
3084
        mov     eax, edx
3087
        mov     eax, edx
3085
        neg     ebx
3088
        neg     ebx
3086
        jecxz   @f
3089
        jecxz   @f
3087
        lea     ebx, [ebp+FAT.buffer+0x200+ebx]
3090
        lea     ebx, [ebp+FAT.buffer+0x200+ebx]
3088
        call    memmove
3091
        call    memmove
3089
        xor     ebx, ebx
3092
        xor     ebx, ebx
3090
@@:
3093
@@:
3091
        pop     eax
3094
        pop     eax
3092
; save sector
3095
; save sector
3093
        push    ebx
3096
        push    ebx
3094
        lea     ebx, [ebp+FAT.buffer]
3097
        lea     ebx, [ebp+FAT.buffer]
3095
        call    fs_write32_app
3098
        call    fs_write32_app
3096
        pop     ebx
3099
        pop     ebx
3097
        test    eax, eax
3100
        test    eax, eax
3098
        jnz     .device_err2
3101
        jnz     .device_err2
3099
        add     edx, ecx
3102
        add     edx, ecx
3100
        sub     [esp], ecx
3103
        sub     [esp], ecx
3101
        pop     ecx
3104
        pop     ecx
3102
        jz      .ret
3105
        jz      .ret
3103
.skip:
3106
.skip:
3104
; next sector
3107
; next sector
3105
        pop     eax
3108
        pop     eax
3106
        inc     eax
3109
        inc     eax
3107
        push    eax
3110
        push    eax
3108
        cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3111
        cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3109
        jb      @f
3112
        jb      @f
3110
        and     dword [esp], 0
3113
        and     dword [esp], 0
3111
        mov     eax, edi
3114
        mov     eax, edi
3112
        call    get_FAT
3115
        call    get_FAT
3113
        mov     edi, eax
3116
        mov     edi, eax
3114
        jc      .device_err
3117
        jc      .device_err
3115
        cmp     edi, 2
3118
        cmp     edi, 2
3116
        jb      .fat_err
3119
        jb      .fat_err
3117
        cmp     edi, [ebp+FAT.fatRESERVED]
3120
        cmp     edi, [ebp+FAT.fatRESERVED]
3118
        jae     .fat_err
3121
        jae     .fat_err
3119
@@:
3122
@@:
3120
        sub     esi, 0x200
3123
        sub     esi, 0x200
3121
        jae     @f
3124
        jae     @f
3122
        xor     esi, esi
3125
        xor     esi, esi
3123
@@:
3126
@@:
3124
        sub     dword [esp+4], 0x200
3127
        sub     dword [esp+4], 0x200
3125
        jae     @f
3128
        jae     @f
3126
        and     dword [esp+4], 0
3129
        and     dword [esp+4], 0
3127
@@:
3130
@@:
3128
        jmp     .write_loop
3131
        jmp     .write_loop
3129
 
3132
 
3130
hd_extend_file.zero_size:
3133
hd_extend_file.zero_size:
3131
        xor     eax, eax
3134
        xor     eax, eax
3132
        jmp     hd_extend_file.start_extend
3135
        jmp     hd_extend_file.start_extend
3133
 
3136
 
3134
; extends file on hd to given size (new data area is undefined)
3137
; extends file on hd to given size (new data area is undefined)
3135
; in: edi->direntry, ecx=new size
3138
; in: edi->direntry, ecx=new size
3136
; out: CF=0 => OK, eax=0
3139
; out: CF=0 => OK, eax=0
3137
;      CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL or ERROR_DEVICE)
3140
;      CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL or ERROR_DEVICE)
3138
hd_extend_file:
3141
hd_extend_file:
3139
        push    esi
3142
        push    esi
3140
        mov     esi, [ebp+FAT.SECTORS_PER_CLUSTER]
3143
        mov     esi, [ebp+FAT.SECTORS_PER_CLUSTER]
3141
        imul    esi, [ebp+FAT.BYTES_PER_SECTOR]
3144
        imul    esi, [ebp+FAT.BYTES_PER_SECTOR]
3142
        push    ecx
3145
        push    ecx
3143
; find the last cluster of file
3146
; find the last cluster of file
3144
        mov     eax, [edi+20-2]
3147
        mov     eax, [edi+20-2]
3145
        mov     ax, [edi+26]
3148
        mov     ax, [edi+26]
3146
        mov     ecx, [edi+28]
3149
        mov     ecx, [edi+28]
3147
        jecxz   .zero_size
3150
        jecxz   .zero_size
3148
.last_loop:
3151
.last_loop:
3149
        sub     ecx, esi
3152
        sub     ecx, esi
3150
        jbe     .last_found
3153
        jbe     .last_found
3151
        call    get_FAT
3154
        call    get_FAT
3152
        jnc     @f
3155
        jnc     @f
3153
.device_err:
3156
.device_err:
3154
        pop     ecx
3157
        pop     ecx
3155
.device_err2:
3158
.device_err2:
3156
        pop     esi
3159
        pop     esi
3157
        push    ERROR_DEVICE
3160
        push    ERROR_DEVICE
3158
.ret_err:
3161
.ret_err:
3159
        pop     eax
3162
        pop     eax
3160
        stc
3163
        stc
3161
        ret
3164
        ret
3162
@@:
3165
@@:
3163
        cmp     eax, 2
3166
        cmp     eax, 2
3164
        jb      .fat_err
3167
        jb      .fat_err
3165
        cmp     eax, [ebp+FAT.fatRESERVED]
3168
        cmp     eax, [ebp+FAT.fatRESERVED]
3166
        jb      .last_loop
3169
        jb      .last_loop
3167
.fat_err:
3170
.fat_err:
3168
        pop     ecx esi
3171
        pop     ecx esi
3169
        push    ERROR_FAT_TABLE
3172
        push    ERROR_FAT_TABLE
3170
        jmp     .ret_err
3173
        jmp     .ret_err
3171
.last_found:
3174
.last_found:
3172
        push    eax
3175
        push    eax
3173
        call    get_FAT
3176
        call    get_FAT
3174
        jnc     @f
3177
        jnc     @f
3175
        pop     eax
3178
        pop     eax
3176
        jmp     .device_err
3179
        jmp     .device_err
3177
@@:
3180
@@:
3178
        cmp     eax, [ebp+FAT.fatRESERVED]
3181
        cmp     eax, [ebp+FAT.fatRESERVED]
3179
        pop     eax
3182
        pop     eax
3180
        jb      .fat_err
3183
        jb      .fat_err
3181
; set length to full number of clusters
3184
; set length to full number of clusters
3182
        sub     [edi+28], ecx
3185
        sub     [edi+28], ecx
3183
.start_extend:
3186
.start_extend:
3184
        pop     ecx
3187
        pop     ecx
3185
; now do extend
3188
; now do extend
3186
        push    edx
3189
        push    edx
3187
        mov     edx, 2          ; start scan from cluster 2
3190
        mov     edx, 2          ; start scan from cluster 2
3188
.extend_loop:
3191
.extend_loop:
3189
        cmp     [edi+28], ecx
3192
        cmp     [edi+28], ecx
3190
        jae     .extend_done
3193
        jae     .extend_done
3191
; add new cluster
3194
; add new cluster
3192
        push    eax
3195
        push    eax
3193
        call    get_free_FAT
3196
        call    get_free_FAT
3194
        jc      .disk_full
3197
        jc      .disk_full
3195
        mov     edx, [ebp+FAT.fatEND]
3198
        mov     edx, [ebp+FAT.fatEND]
3196
        call    set_FAT
3199
        call    set_FAT
3197
        mov     edx, eax
3200
        mov     edx, eax
3198
        pop     eax
3201
        pop     eax
3199
        test    eax, eax
3202
        test    eax, eax
3200
        jz      .first_cluster
3203
        jz      .first_cluster
3201
        push    edx
3204
        push    edx
3202
        call    set_FAT
3205
        call    set_FAT
3203
        pop     edx
3206
        pop     edx
3204
        jmp     @f
3207
        jmp     @f
3205
.first_cluster:
3208
.first_cluster:
3206
        ror     edx, 16
3209
        ror     edx, 16
3207
        mov     [edi+20], dx
3210
        mov     [edi+20], dx
3208
        ror     edx, 16
3211
        ror     edx, 16
3209
        mov     [edi+26], dx
3212
        mov     [edi+26], dx
3210
@@:
3213
@@:
3211
        push    ecx
3214
        push    ecx
3212
        mov     ecx, -1
3215
        mov     ecx, -1
3213
        call    add_disk_free_space
3216
        call    add_disk_free_space
3214
        pop     ecx
3217
        pop     ecx
3215
        mov     eax, edx
3218
        mov     eax, edx
3216
        add     [edi+28], esi
3219
        add     [edi+28], esi
3217
        jmp     .extend_loop
3220
        jmp     .extend_loop
3218
.extend_done:
3221
.extend_done:
3219
        mov     [edi+28], ecx
3222
        mov     [edi+28], ecx
3220
        pop     edx esi
3223
        pop     edx esi
3221
        xor     eax, eax        ; CF=0
3224
        xor     eax, eax        ; CF=0
3222
        ret
3225
        ret
3223
.device_err3:
3226
.device_err3:
3224
        pop     edx
3227
        pop     edx
3225
        jmp     .device_err2
3228
        jmp     .device_err2
3226
.disk_full:
3229
.disk_full:
3227
        pop     eax edx esi
3230
        pop     eax edx esi
3228
        movi    eax, ERROR_DISK_FULL
3231
        movi    eax, ERROR_DISK_FULL
3229
        stc
3232
        stc
3230
        ret
3233
        ret
3231
 
3234
 
3232
fat_update_datetime:
3235
fat_update_datetime:
3233
        call    get_time_for_file
3236
        call    get_time_for_file
3234
        mov     [edi+22], ax            ; last write time
3237
        mov     [edi+22], ax            ; last write time
3235
        call    get_date_for_file
3238
        call    get_date_for_file
3236
        mov     [edi+24], ax            ; last write date
3239
        mov     [edi+24], ax            ; last write date
3237
        mov     [edi+18], ax            ; last access date
3240
        mov     [edi+18], ax            ; last access date
3238
        ret
3241
        ret
3239
 
3242
 
3240
 
3243
 
3241
;----------------------------------------------------------------
3244
;----------------------------------------------------------------
3242
; fat_SetFileEnd - FAT implementation of setting end-of-file
3245
; fat_SetFileEnd - FAT implementation of setting end-of-file
3243
; in:  ebp = pointer to FAT structure
3246
; in:  ebp = pointer to FAT structure
3244
; in:  esi+[esp+4] = name
3247
; in:  esi+[esp+4] = name
3245
; in:  ebx = pointer to parameters from sysfunc 70
3248
; in:  ebx = pointer to parameters from sysfunc 70
3246
; out: eax, ebx = return values for sysfunc 70
3249
; out: eax, ebx = return values for sysfunc 70
3247
;----------------------------------------------------------------
3250
;----------------------------------------------------------------
3248
fat_SetFileEnd:
3251
fat_SetFileEnd:
3249
        call    fat_lock
3252
        call    fat_lock
3250
        push    edi
3253
        push    edi
3251
        cmp     byte [esi], 0
3254
        cmp     byte [esi], 0
3252
        jnz     @f
3255
        jnz     @f
3253
.access_denied:
3256
.access_denied:
3254
        push    ERROR_ACCESS_DENIED
3257
        push    ERROR_ACCESS_DENIED
3255
.ret:
3258
.ret:
3256
        call    fat_unlock
3259
        call    fat_unlock
3257
        pop     eax
3260
        pop     eax
3258
        pop     edi
3261
        pop     edi
3259
        ret
3262
        ret
3260
@@:
3263
@@:
3261
        stdcall hd_find_lfn, [esp+4+4]
3264
        stdcall hd_find_lfn, [esp+4+4]
3262
        jnc     @f
3265
        jnc     @f
3263
.reteax:
3266
.reteax:
3264
        push    eax
3267
        push    eax
3265
        jmp     .ret
3268
        jmp     .ret
3266
@@:
3269
@@:
3267
; must not be directory
3270
; must not be directory
3268
        test    byte [edi+11], 10h
3271
        test    byte [edi+11], 10h
3269
        jnz     .access_denied
3272
        jnz     .access_denied
3270
; file size must not exceed 4 Gb
3273
; file size must not exceed 4 Gb
3271
        cmp     dword [ebx+8], 0
3274
        cmp     dword [ebx+8], 0
3272
        jz      @f
3275
        jz      @f
3273
        push    ERROR_END_OF_FILE
3276
        push    ERROR_END_OF_FILE
3274
        jmp     .ret
3277
        jmp     .ret
3275
@@:
3278
@@:
3276
        push    eax     ; save directory sector
3279
        push    eax     ; save directory sector
3277
; set file modification date/time to current
3280
; set file modification date/time to current
3278
        call    fat_update_datetime
3281
        call    fat_update_datetime
3279
        mov     eax, [ebx+4]
3282
        mov     eax, [ebx+4]
3280
        cmp     eax, [edi+28]
3283
        cmp     eax, [edi+28]
3281
        jb      .truncate
3284
        jb      .truncate
3282
        ja      .expand
3285
        ja      .expand
3283
        pop     eax
3286
        pop     eax
3284
        lea     ebx, [ebp+FAT.buffer]
3287
        lea     ebx, [ebp+FAT.buffer]
3285
        call    fs_write32_sys
3288
        call    fs_write32_sys
3286
        test    eax, eax
3289
        test    eax, eax
3287
        jz      @f
3290
        jz      @f
3288
        push    ERROR_DEVICE
3291
        push    ERROR_DEVICE
3289
        jmp     .ret
3292
        jmp     .ret
3290
@@:
3293
@@:
3291
        push    0
3294
        push    0
3292
        jmp     .ret
3295
        jmp     .ret
3293
.expand:
3296
.expand:
3294
        push    ebx ebp ecx
3297
        push    ebx ebp ecx
3295
        push    dword [edi+28]  ; save old size
3298
        push    dword [edi+28]  ; save old size
3296
        mov     ecx, eax
3299
        mov     ecx, eax
3297
        call    hd_extend_file
3300
        call    hd_extend_file
3298
        push    eax             ; return code
3301
        push    eax             ; return code
3299
        jnc     .expand_ok
3302
        jnc     .expand_ok
3300
        cmp     al, ERROR_DISK_FULL
3303
        cmp     al, ERROR_DISK_FULL
3301
        jz      .disk_full
3304
        jz      .disk_full
3302
.pop_ret:
3305
.pop_ret:
3303
        call    update_disk
3306
        call    update_disk
3304
        pop     eax ecx ecx ebp ebx ecx
3307
        pop     eax ecx ecx ebp ebx ecx
3305
        jmp     .reteax
3308
        jmp     .reteax
3306
.expand_ok:
3309
.expand_ok:
3307
.disk_full:
3310
.disk_full:
3308
; save directory
3311
; save directory
3309
        mov     eax, [edi+28]
3312
        mov     eax, [edi+28]
3310
        xchg    eax, [esp+20]
3313
        xchg    eax, [esp+20]
3311
        lea     ebx, [ebp+FAT.buffer]
3314
        lea     ebx, [ebp+FAT.buffer]
3312
        call    fs_write32_sys
3315
        call    fs_write32_sys
3313
        test    eax, eax
3316
        test    eax, eax
3314
        mov     eax, [edi+20-2]
3317
        mov     eax, [edi+20-2]
3315
        mov     ax, [edi+26]
3318
        mov     ax, [edi+26]
3316
        mov     edi, eax
3319
        mov     edi, eax
3317
        jz      @f
3320
        jz      @f
3318
.pop_ret11:
3321
.pop_ret11:
3319
        mov     byte [esp], ERROR_DEVICE
3322
        mov     byte [esp], ERROR_DEVICE
3320
        jmp     .pop_ret
3323
        jmp     .pop_ret
3321
@@:
3324
@@:
3322
        test    edi, edi
3325
        test    edi, edi
3323
        jz      .pop_ret
3326
        jz      .pop_ret
3324
; now zero new data
3327
; now zero new data
3325
        push    0
3328
        push    0
3326
; edi=current cluster, [esp]=sector in cluster
3329
; edi=current cluster, [esp]=sector in cluster
3327
; [esp+24]=new size, [esp+8]=old size, [esp+4]=return code
3330
; [esp+24]=new size, [esp+8]=old size, [esp+4]=return code
3328
.zero_loop:
3331
.zero_loop:
3329
        cmp     edi, 2
3332
        cmp     edi, 2
3330
        jb      .error_fat
3333
        jb      .error_fat
3331
        cmp     edi, [ebp+FAT.fatRESERVED]
3334
        cmp     edi, [ebp+FAT.fatRESERVED]
3332
        jae     .error_fat
3335
        jae     .error_fat
3333
        sub     dword [esp+8], 0x200
3336
        sub     dword [esp+8], 0x200
3334
        jae     .next_cluster
3337
        jae     .next_cluster
3335
        lea     eax, [edi-2]
3338
        lea     eax, [edi-2]
3336
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3339
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3337
        add     eax, [ebp+FAT.DATA_START]
3340
        add     eax, [ebp+FAT.DATA_START]
3338
        add     eax, [esp]
3341
        add     eax, [esp]
3339
        cmp     dword [esp+8], -0x200
3342
        cmp     dword [esp+8], -0x200
3340
        jz      .noread
3343
        jz      .noread
3341
        push    eax
3344
        push    eax
3342
        lea     ebx, [ebp+FAT.buffer]
3345
        lea     ebx, [ebp+FAT.buffer]
3343
        call    fs_read32_app
3346
        call    fs_read32_app
3344
        test    eax, eax
3347
        test    eax, eax
3345
        pop     eax
3348
        pop     eax
3346
        jnz     .err_next
3349
        jnz     .err_next
3347
.noread:
3350
.noread:
3348
        mov     ecx, [esp+8]
3351
        mov     ecx, [esp+8]
3349
        neg     ecx
3352
        neg     ecx
3350
        push    edi
3353
        push    edi
3351
        lea     edi, [ebp+FAT.buffer+0x200]
3354
        lea     edi, [ebp+FAT.buffer+0x200]
3352
        add     edi, [esp+12]
3355
        add     edi, [esp+12]
3353
        push    eax
3356
        push    eax
3354
        xor     eax, eax
3357
        xor     eax, eax
3355
        mov     [esp+16], eax
3358
        mov     [esp+16], eax
3356
        rep stosb
3359
        rep stosb
3357
        pop     eax
3360
        pop     eax
3358
        pop     edi
3361
        pop     edi
3359
        call    fs_write32_app
3362
        call    fs_write32_app
3360
        test    eax, eax
3363
        test    eax, eax
3361
        jz      .next_cluster
3364
        jz      .next_cluster
3362
.err_next:
3365
.err_next:
3363
        mov     byte [esp+4], ERROR_DEVICE
3366
        mov     byte [esp+4], ERROR_DEVICE
3364
.next_cluster:
3367
.next_cluster:
3365
        pop     eax
3368
        pop     eax
3366
        sub     dword [esp+20], 0x200
3369
        sub     dword [esp+20], 0x200
3367
        jbe     .pop_ret
3370
        jbe     .pop_ret
3368
        inc     eax
3371
        inc     eax
3369
        push    eax
3372
        push    eax
3370
        cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3373
        cmp     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3371
        jb      .zero_loop
3374
        jb      .zero_loop
3372
        and     dword [esp], 0
3375
        and     dword [esp], 0
3373
        mov     eax, edi
3376
        mov     eax, edi
3374
        call    get_FAT
3377
        call    get_FAT
3375
        mov     edi, eax
3378
        mov     edi, eax
3376
        jnc     .zero_loop
3379
        jnc     .zero_loop
3377
        pop     eax
3380
        pop     eax
3378
        jmp     .pop_ret11
3381
        jmp     .pop_ret11
3379
.truncate:
3382
.truncate:
3380
        mov     [edi+28], eax
3383
        mov     [edi+28], eax
3381
        push    ecx
3384
        push    ecx
3382
        mov     ecx, [edi+20-2]
3385
        mov     ecx, [edi+20-2]
3383
        mov     cx, [edi+26]
3386
        mov     cx, [edi+26]
3384
        push    eax
3387
        push    eax
3385
        test    eax, eax
3388
        test    eax, eax
3386
        jz      .zero_size
3389
        jz      .zero_size
3387
; find new last cluster
3390
; find new last cluster
3388
@@:
3391
@@:
3389
        cmp     ecx, 2
3392
        cmp     ecx, 2
3390
        jb      .error_fat2
3393
        jb      .error_fat2
3391
        cmp     ecx, [ebp+FAT.fatRESERVED]
3394
        cmp     ecx, [ebp+FAT.fatRESERVED]
3392
        jae     .error_fat2
3395
        jae     .error_fat2
3393
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3396
        mov     eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3394
        shl     eax, 9
3397
        shl     eax, 9
3395
        sub     [esp], eax
3398
        sub     [esp], eax
3396
        jbe     @f
3399
        jbe     @f
3397
        mov     eax, ecx
3400
        mov     eax, ecx
3398
        call    get_FAT
3401
        call    get_FAT
3399
        mov     ecx, eax
3402
        mov     ecx, eax
3400
        jnc     @b
3403
        jnc     @b
3401
.device_err3:
3404
.device_err3:
3402
        pop     eax ecx eax edi
3405
        pop     eax ecx eax edi
3403
        call    update_disk
3406
        call    update_disk
3404
        call    fat_unlock
3407
        call    fat_unlock
3405
        movi    eax, ERROR_DEVICE
3408
        movi    eax, ERROR_DEVICE
3406
        ret
3409
        ret
3407
@@:
3410
@@:
3408
; we will zero data at the end of last sector - remember it
3411
; we will zero data at the end of last sector - remember it
3409
        push    ecx
3412
        push    ecx
3410
; terminate FAT chain
3413
; terminate FAT chain
3411
        push    edx
3414
        push    edx
3412
        mov     eax, ecx
3415
        mov     eax, ecx
3413
        mov     edx, [ebp+FAT.fatEND]
3416
        mov     edx, [ebp+FAT.fatEND]
3414
        call    set_FAT
3417
        call    set_FAT
3415
        mov     eax, edx
3418
        mov     eax, edx
3416
        pop     edx
3419
        pop     edx
3417
        jnc     @f
3420
        jnc     @f
3418
.device_err4:
3421
.device_err4:
3419
        pop     ecx
3422
        pop     ecx
3420
        jmp     .device_err3
3423
        jmp     .device_err3
3421
.zero_size:
3424
.zero_size:
3422
        and     word [edi+20], 0
3425
        and     word [edi+20], 0
3423
        and     word [edi+26], 0
3426
        and     word [edi+26], 0
3424
        push    0
3427
        push    0
3425
        mov     eax, ecx
3428
        mov     eax, ecx
3426
@@:
3429
@@:
3427
; delete FAT chain
3430
; delete FAT chain
3428
        call    clear_cluster_chain
3431
        call    clear_cluster_chain
3429
        jc      .device_err4
3432
        jc      .device_err4
3430
; save directory
3433
; save directory
3431
        mov     eax, [esp+12]
3434
        mov     eax, [esp+12]
3432
        push    ebx
3435
        push    ebx
3433
        lea     ebx, [ebp+FAT.buffer]
3436
        lea     ebx, [ebp+FAT.buffer]
3434
        call    fs_write32_sys
3437
        call    fs_write32_sys
3435
        pop     ebx
3438
        pop     ebx
3436
        test    eax, eax
3439
        test    eax, eax
3437
        jnz     .device_err4
3440
        jnz     .device_err4
3438
; zero last sector, ignore errors
3441
; zero last sector, ignore errors
3439
        pop     ecx
3442
        pop     ecx
3440
        pop     eax
3443
        pop     eax
3441
        dec     ecx
3444
        dec     ecx
3442
        imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
3445
        imul    ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
3443
        add     ecx, [ebp+FAT.DATA_START]
3446
        add     ecx, [ebp+FAT.DATA_START]
3444
        push    eax
3447
        push    eax
3445
        sar     eax, 9
3448
        sar     eax, 9
3446
        add     ecx, eax
3449
        add     ecx, eax
3447
        pop     eax
3450
        pop     eax
3448
        and     eax, 0x1FF
3451
        and     eax, 0x1FF
3449
        jz      .truncate_done
3452
        jz      .truncate_done
3450
        push    ebx eax
3453
        push    ebx eax
3451
        mov     eax, ecx
3454
        mov     eax, ecx
3452
        lea     ebx, [ebp+FAT.buffer]
3455
        lea     ebx, [ebp+FAT.buffer]
3453
        call    fs_read32_app
3456
        call    fs_read32_app
3454
        pop     eax
3457
        pop     eax
3455
        lea     edi, [ebp+FAT.buffer+eax]
3458
        lea     edi, [ebp+FAT.buffer+eax]
3456
        push    ecx
3459
        push    ecx
3457
        mov     ecx, 0x200
3460
        mov     ecx, 0x200
3458
        sub     ecx, eax
3461
        sub     ecx, eax
3459
        xor     eax, eax
3462
        xor     eax, eax
3460
        rep stosb
3463
        rep stosb
3461
        pop     eax
3464
        pop     eax
3462
        call    fs_write32_app
3465
        call    fs_write32_app
3463
        pop     ebx
3466
        pop     ebx
3464
.truncate_done:
3467
.truncate_done:
3465
        pop     ecx eax edi
3468
        pop     ecx eax edi
3466
        call    update_disk
3469
        call    update_disk
3467
        call    fat_unlock
3470
        call    fat_unlock
3468
        xor     eax, eax
3471
        xor     eax, eax
3469
        ret
3472
        ret
3470
.error_fat:
3473
.error_fat:
3471
        pop     eax
3474
        pop     eax
3472
        mov     byte [esp], ERROR_FAT_TABLE
3475
        mov     byte [esp], ERROR_FAT_TABLE
3473
        jmp     .pop_ret
3476
        jmp     .pop_ret
3474
.error_fat2:
3477
.error_fat2:
3475
        pop     eax ecx eax edi
3478
        pop     eax ecx eax edi
3476
        call    update_disk
3479
        call    update_disk
3477
        call    fat_unlock
3480
        call    fat_unlock
3478
        movi    eax, ERROR_FAT_TABLE
3481
        movi    eax, ERROR_FAT_TABLE
3479
        ret
3482
        ret
3480
 
3483
 
3481
;----------------------------------------------------------------
3484
;----------------------------------------------------------------
3482
; fat_GetFileInfo - FAT implementation of getting file info
3485
; fat_GetFileInfo - FAT implementation of getting file info
3483
; in:  ebp = pointer to FAT structure
3486
; in:  ebp = pointer to FAT structure
3484
; in:  esi+[esp+4] = name
3487
; in:  esi+[esp+4] = name
3485
; in:  ebx = pointer to parameters from sysfunc 70
3488
; in:  ebx = pointer to parameters from sysfunc 70
3486
; out: eax, ebx = return values for sysfunc 70
3489
; out: eax, ebx = return values for sysfunc 70
3487
;----------------------------------------------------------------
3490
;----------------------------------------------------------------
3488
fat_GetFileInfo:
3491
fat_GetFileInfo:
3489
        cmp     byte [esi], 0
3492
        cmp     byte [esi], 0
3490
        jnz     @f
3493
        jnz     @f
3491
        mov     eax, 2
3494
        mov     eax, 2
3492
        ret
3495
        ret
3493
@@:
3496
@@:
3494
        push    edi
3497
        push    edi
3495
        call    fat_lock
3498
        call    fat_lock
3496
        stdcall hd_find_lfn, [esp+4+4]
3499
        stdcall hd_find_lfn, [esp+4+4]
3497
        jc      .error
3500
        jc      .error
3498
        push    ebp
3501
        push    ebp
3499
        xor     ebp, ebp
3502
        xor     ebp, ebp
3500
        mov     esi, [ebx+16]
3503
        mov     esi, [ebx+16]
3501
        mov     dword [esi+4], ebp
3504
        mov     dword [esi+4], ebp
3502
        call    fat_entry_to_bdfe2
3505
        call    fat_entry_to_bdfe2
3503
        pop     ebp
3506
        pop     ebp
3504
        call    fat_unlock
3507
        call    fat_unlock
3505
        xor     eax, eax
3508
        xor     eax, eax
3506
        pop     edi
3509
        pop     edi
3507
        ret
3510
        ret
3508
.error:
3511
.error:
3509
        push    eax
3512
        push    eax
3510
        call    fat_unlock
3513
        call    fat_unlock
3511
        pop     eax
3514
        pop     eax
3512
        pop     edi
3515
        pop     edi
3513
        ret
3516
        ret
3514
 
3517
 
3515
;----------------------------------------------------------------
3518
;----------------------------------------------------------------
3516
; fat_SetFileInfo - FAT implementation of setting file info
3519
; fat_SetFileInfo - FAT implementation of setting file info
3517
; in:  ebp = pointer to FAT structure
3520
; in:  ebp = pointer to FAT structure
3518
; in:  esi+[esp+4] = name
3521
; in:  esi+[esp+4] = name
3519
; in:  ebx = pointer to parameters from sysfunc 70
3522
; in:  ebx = pointer to parameters from sysfunc 70
3520
; out: eax, ebx = return values for sysfunc 70
3523
; out: eax, ebx = return values for sysfunc 70
3521
;----------------------------------------------------------------
3524
;----------------------------------------------------------------
3522
fat_SetFileInfo:
3525
fat_SetFileInfo:
3523
        cmp     byte [esi], 0
3526
        cmp     byte [esi], 0
3524
        jnz     @f
3527
        jnz     @f
3525
        mov     eax, 2
3528
        mov     eax, 2
3526
        ret
3529
        ret
3527
@@:
3530
@@:
3528
        push    edi
3531
        push    edi
3529
        call    fat_lock
3532
        call    fat_lock
3530
        stdcall hd_find_lfn, [esp+4+4]
3533
        stdcall hd_find_lfn, [esp+4+4]
3531
        jc      .error
3534
        jc      .error
3532
        push    eax
3535
        push    eax
3533
        mov     edx, [ebx+16]
3536
        mov     edx, [ebx+16]
3534
        call    bdfe_to_fat_entry
3537
        call    bdfe_to_fat_entry
3535
        pop     eax
3538
        pop     eax
3536
        lea     ebx, [ebp+FAT.buffer]
3539
        lea     ebx, [ebp+FAT.buffer]
3537
        call    fs_write32_sys
3540
        call    fs_write32_sys
3538
        call    update_disk
3541
        call    update_disk
3539
        call    fat_unlock
3542
        call    fat_unlock
3540
        pop     edi
3543
        pop     edi
3541
        xor     eax, eax
3544
        xor     eax, eax
3542
        ret
3545
        ret
3543
.error:
3546
.error:
3544
        push    eax
3547
        push    eax
3545
        call    fat_unlock
3548
        call    fat_unlock
3546
        pop     eax
3549
        pop     eax
3547
        pop     edi
3550
        pop     edi
3548
        ret
3551
        ret
3549
 
3552
 
3550
;----------------------------------------------------------------
3553
;----------------------------------------------------------------
3551
; fat_Delete - FAT implementation of deleting a file/folder
3554
; fat_Delete - FAT implementation of deleting a file/folder
3552
; in:  ebp = pointer to FAT structure
3555
; in:  ebp = pointer to FAT structure
3553
; in:  esi+[esp+4] = name
3556
; in:  esi+[esp+4] = name
3554
; in:  ebx = pointer to parameters from sysfunc 70
3557
; in:  ebx = pointer to parameters from sysfunc 70
3555
; out: eax, ebx = return values for sysfunc 70
3558
; out: eax, ebx = return values for sysfunc 70
3556
;----------------------------------------------------------------
3559
;----------------------------------------------------------------
3557
fat_Delete:
3560
fat_Delete:
3558
        call    fat_lock
3561
        call    fat_lock
3559
        cmp     byte [esi], 0
3562
        cmp     byte [esi], 0
3560
        jnz     @f
3563
        jnz     @f
3561
; cannot delete root!
3564
; cannot delete root!
3562
.access_denied:
3565
.access_denied:
3563
        push    ERROR_ACCESS_DENIED
3566
        push    ERROR_ACCESS_DENIED
3564
.pop_ret:
3567
.pop_ret:
3565
        call    fat_unlock
3568
        call    fat_unlock
3566
        pop     eax
3569
        pop     eax
3567
        xor     ebx, ebx
3570
        xor     ebx, ebx
3568
        ret
3571
        ret
3569
@@:
3572
@@:
3570
        and     [ebp+FAT.longname_sec1], 0
3573
        and     [ebp+FAT.longname_sec1], 0
3571
        and     [ebp+FAT.longname_sec2], 0
3574
        and     [ebp+FAT.longname_sec2], 0
3572
        push    edi
3575
        push    edi
3573
        stdcall hd_find_lfn, [esp+4+4]
3576
        stdcall hd_find_lfn, [esp+4+4]
3574
        jnc     .found
3577
        jnc     .found
3575
        pop     edi
3578
        pop     edi
3576
        push    ERROR_FILE_NOT_FOUND
3579
        push    ERROR_FILE_NOT_FOUND
3577
        jmp     .pop_ret
3580
        jmp     .pop_ret
3578
.found:
3581
.found:
3579
        cmp     dword [edi], '.   '
3582
        cmp     dword [edi], '.   '
3580
        jz      .access_denied2
3583
        jz      .access_denied2
3581
        cmp     dword [edi], '..  '
3584
        cmp     dword [edi], '..  '
3582
        jz      .access_denied2
3585
        jz      .access_denied2
3583
        test    byte [edi+11], 10h
3586
        test    byte [edi+11], 10h
3584
        jz      .dodel
3587
        jz      .dodel
3585
; we can delete only empty folders!
3588
; we can delete only empty folders!
3586
        pushad
3589
        pushad
3587
        mov     esi, [edi+20-2]
3590
        mov     esi, [edi+20-2]
3588
        mov     si, [edi+26]
3591
        mov     si, [edi+26]
3589
        xor     ecx, ecx
3592
        xor     ecx, ecx
3590
        lea     eax, [esi-2]
3593
        lea     eax, [esi-2]
3591
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3594
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3592
        add     eax, [ebp+FAT.DATA_START]
3595
        add     eax, [ebp+FAT.DATA_START]
3593
        lea     ebx, [ebp+FAT.buffer]
3596
        lea     ebx, [ebp+FAT.buffer]
3594
        call    fs_read32_sys
3597
        call    fs_read32_sys
3595
        test    eax, eax
3598
        test    eax, eax
3596
        jnz     .err1
3599
        jnz     .err1
3597
        lea     eax, [ebx+0x200]
3600
        lea     eax, [ebx+0x200]
3598
        add     ebx, 2*0x20
3601
        add     ebx, 2*0x20
3599
.checkempty:
3602
.checkempty:
3600
        cmp     byte [ebx], 0
3603
        cmp     byte [ebx], 0
3601
        jz      .empty
3604
        jz      .empty
3602
        cmp     byte [ebx], 0xE5
3605
        cmp     byte [ebx], 0xE5
3603
        jnz     .notempty
3606
        jnz     .notempty
3604
        add     ebx, 0x20
3607
        add     ebx, 0x20
3605
        cmp     ebx, eax
3608
        cmp     ebx, eax
3606
        jb      .checkempty
3609
        jb      .checkempty
3607
        inc     ecx
3610
        inc     ecx
3608
        cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
3611
        cmp     ecx, [ebp+FAT.SECTORS_PER_CLUSTER]
3609
        jb      @f
3612
        jb      @f
3610
        mov     eax, esi
3613
        mov     eax, esi
3611
        call    get_FAT
3614
        call    get_FAT
3612
        jc      .err1
3615
        jc      .err1
3613
        cmp     eax, 2
3616
        cmp     eax, 2
3614
        jb      .error_fat
3617
        jb      .error_fat
3615
        cmp     eax, [ebp+FAT.fatRESERVED]
3618
        cmp     eax, [ebp+FAT.fatRESERVED]
3616
        jae     .empty
3619
        jae     .empty
3617
        mov     esi, eax
3620
        mov     esi, eax
3618
        xor     ecx, ecx
3621
        xor     ecx, ecx
3619
@@:
3622
@@:
3620
        lea     eax, [esi-2]
3623
        lea     eax, [esi-2]
3621
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3624
        imul    eax, [ebp+FAT.SECTORS_PER_CLUSTER]
3622
        add     eax, [ebp+FAT.DATA_START]
3625
        add     eax, [ebp+FAT.DATA_START]
3623
        add     eax, ecx
3626
        add     eax, ecx
3624
        lea     ebx, [ebp+FAT.buffer]
3627
        lea     ebx, [ebp+FAT.buffer]
3625
        call    fs_read32_sys
3628
        call    fs_read32_sys
3626
        test    eax, eax
3629
        test    eax, eax
3627
        lea     eax, [ebx+0x200]
3630
        lea     eax, [ebx+0x200]
3628
        jz      .checkempty
3631
        jz      .checkempty
3629
.err1:
3632
.err1:
3630
        popad
3633
        popad
3631
.err2:
3634
.err2:
3632
        pop     edi
3635
        pop     edi
3633
        call    fat_unlock
3636
        call    fat_unlock
3634
        movi    eax, ERROR_DEVICE
3637
        movi    eax, ERROR_DEVICE
3635
        ret
3638
        ret
3636
.error_fat:
3639
.error_fat:
3637
        popad
3640
        popad
3638
        pop     edi
3641
        pop     edi
3639
        call    fat_unlock
3642
        call    fat_unlock
3640
        movi    eax, ERROR_FAT_TABLE
3643
        movi    eax, ERROR_FAT_TABLE
3641
        ret
3644
        ret
3642
.notempty:
3645
.notempty:
3643
        popad
3646
        popad
3644
.access_denied2:
3647
.access_denied2:
3645
        pop     edi
3648
        pop     edi
3646
        call    fat_unlock
3649
        call    fat_unlock
3647
        movi    eax, ERROR_ACCESS_DENIED
3650
        movi    eax, ERROR_ACCESS_DENIED
3648
        ret
3651
        ret
3649
.empty:
3652
.empty:
3650
        popad
3653
        popad
3651
        push    eax ebx
3654
        push    eax ebx
3652
        lea     ebx, [ebp+FAT.buffer]
3655
        lea     ebx, [ebp+FAT.buffer]
3653
        call    fs_read32_sys
3656
        call    fs_read32_sys
3654
        test    eax, eax
3657
        test    eax, eax
3655
        pop     ebx eax
3658
        pop     ebx eax
3656
        jnz     .err2
3659
        jnz     .err2
3657
.dodel:
3660
.dodel:
3658
        push    eax
3661
        push    eax
3659
        mov     eax, [edi+20-2]
3662
        mov     eax, [edi+20-2]
3660
        mov     ax, [edi+26]
3663
        mov     ax, [edi+26]
3661
        xchg    eax, [esp]
3664
        xchg    eax, [esp]
3662
; delete folder entry
3665
; delete folder entry
3663
        mov     byte [edi], 0xE5
3666
        mov     byte [edi], 0xE5
3664
; delete LFN (if present)
3667
; delete LFN (if present)
3665
.lfndel:
3668
.lfndel:
3666
        lea     edx, [ebp+FAT.buffer]
3669
        lea     edx, [ebp+FAT.buffer]
3667
        cmp     edi, edx
3670
        cmp     edi, edx
3668
        ja      @f
3671
        ja      @f
3669
        cmp     [ebp+FAT.longname_sec2], 0
3672
        cmp     [ebp+FAT.longname_sec2], 0
3670
        jz      .lfndone
3673
        jz      .lfndone
3671
        push    [ebp+FAT.longname_sec2]
3674
        push    [ebp+FAT.longname_sec2]
3672
        push    [ebp+FAT.longname_sec1]
3675
        push    [ebp+FAT.longname_sec1]
3673
        pop     [ebp+FAT.longname_sec2]
3676
        pop     [ebp+FAT.longname_sec2]
3674
        and     [ebp+FAT.longname_sec1], 0
3677
        and     [ebp+FAT.longname_sec1], 0
3675
        push    ebx
3678
        push    ebx
3676
        mov     ebx, edx
3679
        mov     ebx, edx
3677
        call    fs_write32_sys
3680
        call    fs_write32_sys
3678
        mov     eax, [esp+4]
3681
        mov     eax, [esp+4]
3679
        call    fs_read32_sys
3682
        call    fs_read32_sys
3680
        pop     ebx
3683
        pop     ebx
3681
        pop     eax
3684
        pop     eax
3682
        lea     edi, [ebp+FAT.buffer+0x200]
3685
        lea     edi, [ebp+FAT.buffer+0x200]
3683
@@:
3686
@@:
3684
        sub     edi, 0x20
3687
        sub     edi, 0x20
3685
        cmp     byte [edi], 0xE5
3688
        cmp     byte [edi], 0xE5
3686
        jz      .lfndone
3689
        jz      .lfndone
3687
        cmp     byte [edi+11], 0xF
3690
        cmp     byte [edi+11], 0xF
3688
        jnz     .lfndone
3691
        jnz     .lfndone
3689
        mov     byte [edi], 0xE5
3692
        mov     byte [edi], 0xE5
3690
        jmp     .lfndel
3693
        jmp     .lfndel
3691
.lfndone:
3694
.lfndone:
3692
        push    ebx
3695
        push    ebx
3693
        lea     ebx, [ebp+FAT.buffer]
3696
        lea     ebx, [ebp+FAT.buffer]
3694
        call    fs_write32_sys
3697
        call    fs_write32_sys
3695
        pop     ebx
3698
        pop     ebx
3696
; delete FAT chain
3699
; delete FAT chain
3697
        pop     eax
3700
        pop     eax
3698
        call    clear_cluster_chain
3701
        call    clear_cluster_chain
3699
        call    update_disk
3702
        call    update_disk
3700
        call    fat_unlock
3703
        call    fat_unlock
3701
        pop     edi
3704
        pop     edi
3702
        xor     eax, eax
3705
        xor     eax, eax
3703
        ret
3706
        ret
3704
 
3707
 
3705
; \end{diamond}
3708
; \end{diamond}
3706
>
3709
>
3707
>
3710
>