Subversion Repositories Kolibri OS

Rev

Rev 6036 | Rev 6262 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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