Subversion Repositories Kolibri OS

Rev

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

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