Subversion Repositories Kolibri OS

Rev

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

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