Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
431 serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
527 diamond 2
;;                                                              ;;
2465 Serge 3
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
431 serge 4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
527 diamond 6
;; RAMDISK functions                                            ;;
7
;; (C) 2004 Ville Turjanmaa, License: GPL                       ;;
8
;; Addings by M.Lisovin                                         ;;
9
;; LFN support by diamond                                       ;;
431 serge 10
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1 ha 11
 
593 mikedld 12
$Revision: 3555 $
13
 
14
 
5 halyavin 15
; calculate fat chain
1 ha 16
 
5 halyavin 17
calculatefatchain:
18
 
3555 Serge 19
        pushad
5 halyavin 20
 
2434 Serge 21
        mov     esi, RAMDISK+512
22
        mov     edi, RAMDISK_FAT
5 halyavin 23
 
24
 fcnew:
2434 Serge 25
        mov     eax, dword [esi]
26
        mov     ebx, dword [esi+4]
27
        mov     ecx, dword [esi+8]
28
        mov     edx, ecx
29
        shr     edx, 4;8 ok
30
        shr     dx, 4;7 ok
31
        xor     ch, ch
32
        shld    ecx, ebx, 20;6 ok
33
        shr     cx, 4;5 ok
34
        shld    ebx, eax, 12
35
        and     ebx, 0x0fffffff;4 ok
36
        shr     bx, 4;3 ok
37
        shl     eax, 4
38
        and     eax, 0x0fffffff;2 ok
39
        shr     ax, 4;1 ok
40
        mov     dword [edi], eax
41
        mov     dword [edi+4], ebx
42
        mov     dword [edi+8], ecx
43
        mov     dword [edi+12], edx
44
        add     edi, 16
45
        add     esi, 12
5 halyavin 46
 
2434 Serge 47
        cmp     edi, RAMDISK_FAT+2856*2;2849 clusters
3555 Serge 48
        jnz     fcnew
5 halyavin 49
 
3555 Serge 50
        popad
51
        ret
5 halyavin 52
 
53
 
54
restorefatchain:   ; restore fat chain
55
 
3555 Serge 56
        pushad
5 halyavin 57
 
2434 Serge 58
        mov     esi, RAMDISK_FAT
59
        mov     edi, RAMDISK+512
5 halyavin 60
 
61
  fcnew2:
2434 Serge 62
        mov     eax, dword [esi]
63
        mov     ebx, dword [esi+4]
64
        shl     ax, 4
65
        shl     eax, 4
66
        shl     bx, 4
67
        shr     ebx, 4
68
        shrd    eax, ebx, 8
69
        shr     ebx, 8
70
        mov     dword [edi], eax
71
        mov     word [edi+4], bx
72
        add     edi, 6
73
        add     esi, 8
5 halyavin 74
 
2434 Serge 75
        cmp     edi, RAMDISK+512+4278;4274 bytes - all used FAT
3555 Serge 76
        jb      fcnew2
5 halyavin 77
 
2434 Serge 78
        mov     esi, RAMDISK+512  ; duplicate fat chain
79
        mov     edi, RAMDISK+512+0x1200
80
        mov     ecx, 1069;4274/4
3555 Serge 81
        cld
82
        rep movsd
5 halyavin 83
 
3555 Serge 84
        popad
85
        ret
5 halyavin 86
 
87
 
1 ha 88
ramdisk_free_space:
89
;---------------------------------------------
90
;
91
; returns free space in edi
92
; rewr.by Mihasik
93
;---------------------------------------------
94
 
3555 Serge 95
        push    eax ebx ecx
1 ha 96
 
2434 Serge 97
        mov     edi, RAMDISK_FAT;start of FAT
98
        xor     ax, ax;Free cluster=0x0000 in FAT
99
        xor     ebx, ebx;counter
100
        mov     ecx, 2849;2849 clusters
3555 Serge 101
        cld
1 ha 102
    rdfs1:
3555 Serge 103
        repne scasw
104
        jnz     rdfs2 ;if last cluster not 0
105
        inc     ebx
106
        test    ecx, ecx
107
        jnz     rdfs1
1 ha 108
    rdfs2:
2434 Serge 109
        shl     ebx, 9;free clusters*512
110
        mov     edi, ebx
247 serge 111
 
3555 Serge 112
        pop     ecx ebx eax
113
        ret
1 ha 114
 
115
 
116
expand_filename:
117
;---------------------------------------------
118
;
119
; exapand filename with '.' to 11 character
120
; eax - pointer to filename
121
;---------------------------------------------
122
 
3555 Serge 123
        push    esi edi ebx
1 ha 124
 
2434 Serge 125
        mov     edi, esp              ; check for '.' in the name
126
        add     edi, 12+8
1 ha 127
 
2434 Serge 128
        mov     esi, eax
1 ha 129
 
2434 Serge 130
        mov     eax, edi
131
        mov     [eax+0], dword '    '
132
        mov     [eax+4], dword '    '
133
        mov     [eax+8], dword '    '
1 ha 134
 
135
      flr1:
136
 
2434 Serge 137
        cmp     [esi], byte '.'
3555 Serge 138
        jne     flr2
2434 Serge 139
        mov     edi, eax
140
        add     edi, 7
3555 Serge 141
        jmp     flr3
1 ha 142
 
143
      flr2:
144
 
2434 Serge 145
        mov     bl, [esi]
146
        mov     [edi], bl
1 ha 147
 
148
      flr3:
149
 
3555 Serge 150
        inc     esi
151
        inc     edi
1 ha 152
 
2434 Serge 153
        mov     ebx, eax
154
        add     ebx, 11
1 ha 155
 
2434 Serge 156
        cmp     edi, ebx
3555 Serge 157
        jbe     flr1
1 ha 158
 
3555 Serge 159
        pop     ebx edi esi
160
        ret
1 ha 161
 
162
fileread:
163
;----------------------------------------------------------------
164
;
165
;  fileread - sys floppy
166
;
167
;  eax  points to filename 11 chars
168
;  ebx  first wanted block       ; 1+ ; if 0 then set to 1
169
;  ecx  number of blocks to read ; 1+ ; if 0 then set to 1
170
;  edx  mem location to return data
171
;  esi  length of filename 12*X 0=root
172
;
173
;  ret ebx = size or 0xffffffff file not found
174
;      eax = 0 ok read or other = errormsg
175
;
176
;--------------------------------------------------------------
2434 Serge 177
        test    ebx, ebx;if ebx=0 - set to 1
3555 Serge 178
        jnz     frfl5
179
        inc     ebx
1 ha 180
      frfl5:
2434 Serge 181
        test    ecx, ecx;if ecx=0 - set to 1
3555 Serge 182
        jnz     frfl6
183
        inc     ecx
1 ha 184
      frfl6:
2434 Serge 185
        test    esi, esi        ; return ramdisk root
3555 Serge 186
        jnz     fr_noroot       ;if not root
2434 Serge 187
        cmp     ebx, 14         ;14 clusters=root dir
3555 Serge 188
        ja      oorr
2434 Serge 189
        cmp     ecx, 14
3555 Serge 190
        ja      oorr
191
        jmp     fr_do
1 ha 192
      oorr:
2434 Serge 193
        mov     eax, 5          ;out of root range (fnf)
194
        xor     ebx, ebx
3555 Serge 195
        dec     ebx             ;0xffffffff
196
        ret
1 ha 197
 
3555 Serge 198
      fr_do:                    ;reading rootdir
2434 Serge 199
        mov     edi, edx
3555 Serge 200
        dec     ebx
201
        push    edx
2434 Serge 202
        mov     edx, ecx
203
        add     edx, ebx
204
        cmp     edx, 15   ;ebx+ecx=14+1
3555 Serge 205
        pushf
206
        jbe     fr_do1
2434 Serge 207
        sub     edx, 14
208
        sub     ecx, edx
1 ha 209
      fr_do1:
2434 Serge 210
        shl     ebx, 9
211
        mov     esi, RAMDISK+512*19
212
        add     esi, ebx
213
        shl     ecx, 7
3555 Serge 214
        cld
215
        rep movsd
216
        popf
217
        pop     edx
218
        jae     fr_do2
2434 Serge 219
        xor     eax, eax; ok read
220
        xor     ebx, ebx
3555 Serge 221
        ret
222
      fr_do2:        ;if last cluster
2434 Serge 223
        mov     eax, 6;end of file
224
        xor     ebx, ebx
3555 Serge 225
        ret
1 ha 226
 
227
     fr_noroot:
228
 
2434 Serge 229
        sub     esp, 32
3555 Serge 230
        call    expand_filename
1 ha 231
 
3555 Serge 232
        dec     ebx
1 ha 233
 
3555 Serge 234
        push    eax
1 ha 235
 
3555 Serge 236
        push    eax ebx ecx edx esi edi
237
        call    rd_findfile
238
        je      fifound
2434 Serge 239
        add     esp, 32+28 ;if file not found
3555 Serge 240
        ret
1 ha 241
 
242
     fifound:
243
 
2434 Serge 244
        mov     ebx, [edi-11+28]        ;file size
245
        mov     [esp+20], ebx
246
        mov     [esp+24], ebx
247
        add     edi, 0xf
248
        movzx   eax, word [edi]
249
        mov     edi, eax                ;edi=cluster
1 ha 250
 
251
      frnew:
252
 
2434 Serge 253
        add     eax, 31                 ;bootsector+2*fat+filenames
254
        shl     eax, 9                  ;*512
255
        add     eax, RAMDISK           ;image base
256
        mov     ebx, [esp+8]
257
        mov     ecx, 512                ;[esp+4]
1 ha 258
 
2434 Serge 259
        cmp     [esp+16], dword 0       ; wanted cluster ?
3555 Serge 260
        jne     frfl7
261
        call    memmove
2434 Serge 262
        add     [esp+8], dword 512
3555 Serge 263
        dec     dword [esp+12]          ; last wanted cluster ?
264
        je      frnoread
265
        jmp     frfl8
1 ha 266
      frfl7:
3555 Serge 267
        dec     dword [esp+16]
1 ha 268
      frfl8:
2434 Serge 269
        movzx   eax, word [edi*2+RAMDISK_FAT]      ; find next cluster from FAT
270
        mov     edi, eax
271
        cmp     edi, 4095               ;eof  - cluster
3555 Serge 272
        jz      frnoread2
1 ha 273
 
2434 Serge 274
        cmp     [esp+24], dword 512     ;eof  - size
3555 Serge 275
        jb      frnoread
2434 Serge 276
        sub     [esp+24], dword 512
1 ha 277
 
3555 Serge 278
        jmp     frnew
1 ha 279
 
280
      frnoread2:
281
 
2434 Serge 282
        cmp     [esp+16], dword 0       ; eof without read ?
3555 Serge 283
        je      frnoread
1 ha 284
 
3555 Serge 285
        pop     edi esi edx ecx
2434 Serge 286
        add     esp, 4
3555 Serge 287
        pop     ebx    ; ebx <- eax : size of file
2434 Serge 288
        add     esp, 36
289
        mov     eax, 6 ; end of file
3555 Serge 290
        ret
1 ha 291
 
292
      frnoread:
293
 
3555 Serge 294
        pop     edi esi edx ecx
2434 Serge 295
        add     esp, 4
3555 Serge 296
        pop     ebx    ; ebx <- eax : size of file
2434 Serge 297
        add     esp, 36
298
        xor     eax, eax;read ok
3555 Serge 299
        ret
1 ha 300
 
301
 
302
 
303
   rd_findfile:
304
   ;by Mihasik
305
   ;IN: eax - pointer to filename OUT: filestring+11 in edi or notZero in flags and fnf in eax,ebx
306
 
2434 Serge 307
        mov     edi, RAMDISK+512*18+512;Point at directory
3555 Serge 308
        cld
1 ha 309
    rd_newsearch:
2434 Serge 310
        mov     esi, eax
311
        mov     ecx, 11
3555 Serge 312
        rep cmpsb
313
        je      rd_ff
2434 Serge 314
        add     cl, 21
315
        add     edi, ecx
316
        cmp     edi, RAMDISK+512*33
3555 Serge 317
        jb      rd_newsearch
2434 Serge 318
        mov     eax, 5    ;if file not found - eax=5
319
        xor     ebx, ebx
3555 Serge 320
        dec     ebx   ;ebx=0xffffffff and zf=0
1 ha 321
     rd_ff:
3555 Serge 322
        ret
1 ha 323
 
71 diamond 324
; \begin{diamond}
325
 
326
uni2ansi_str:
327
; convert UNICODE zero-terminated string to ASCII-string (codepage 866)
328
; in: esi->source, edi->buffer (may be esi=edi)
329
; destroys: eax,esi,edi
3555 Serge 330
        lodsw
331
        test    ax, ax
332
        jz      .done
333
        cmp     ax, 0x80
334
        jb      .ascii
335
        cmp     ax, 0x401
336
        jz      .yo1
337
        cmp     ax, 0x451
338
        jz      .yo2
339
        cmp     ax, 0x410
340
        jb      .unk
341
        cmp     ax, 0x440
342
        jb      .rus1
343
        cmp     ax, 0x450
344
        jb      .rus2
71 diamond 345
.unk:
3555 Serge 346
        mov     al, '_'
347
        jmp     .doit
71 diamond 348
.yo1:
3555 Serge 349
        mov     al, 0xF0 ; 'Ё'
350
        jmp     .doit
71 diamond 351
.yo2:
3555 Serge 352
        mov     al, 0xF1 ; 'ё'
353
        jmp     .doit
71 diamond 354
.rus1:
355
; 0x410-0x43F -> 0x80-0xAF
3555 Serge 356
        add     al, 0x70
357
        jmp     .doit
71 diamond 358
.rus2:
75 diamond 359
; 0x440-0x44F -> 0xE0-0xEF
3555 Serge 360
        add     al, 0xA0
71 diamond 361
.ascii:
362
.doit:
3555 Serge 363
        stosb
364
        jmp     uni2ansi_str
71 diamond 365
.done:
3555 Serge 366
        mov     byte [edi], 0
367
        ret
71 diamond 368
 
75 diamond 369
ansi2uni_char:
370
; convert ANSI character in al to UNICODE character in ax, using cp866 encoding
3555 Serge 371
        mov     ah, 0
75 diamond 372
; 0x00-0x7F - trivial map
3555 Serge 373
        cmp     al, 0x80
374
        jb      .ret
75 diamond 375
; 0x80-0xAF -> 0x410-0x43F
3555 Serge 376
        cmp     al, 0xB0
377
        jae     @f
378
        add     ax, 0x410-0x80
75 diamond 379
.ret:
3555 Serge 380
        ret
75 diamond 381
@@:
382
; 0xE0-0xEF -> 0x440-0x44F
3555 Serge 383
        cmp     al, 0xE0
384
        jb      .unk
385
        cmp     al, 0xF0
386
        jae     @f
387
        add     ax, 0x440-0xE0
388
        ret
75 diamond 389
; 0xF0 -> 0x401
390
; 0xF1 -> 0x451
391
@@:
3555 Serge 392
        cmp     al, 0xF0 ; 'Ё'
393
        jz      .yo1
394
        cmp     al, 0xF1 ; 'ё'
395
        jz      .yo2
75 diamond 396
.unk:
3555 Serge 397
        mov     al, '_'         ; ah=0
398
        ret
75 diamond 399
.yo1:
3555 Serge 400
        mov     ax, 0x401
401
        ret
75 diamond 402
.yo2:
3555 Serge 403
        mov     ax, 0x451
404
        ret
75 diamond 405
 
71 diamond 406
char_toupper:
407
; convert character to uppercase, using cp866 encoding
408
; in: al=symbol
409
; out: al=converted symbol
3555 Serge 410
        cmp     al, 'a'
411
        jb      .ret
412
        cmp     al, 'z'
413
        jbe     .az
414
        cmp     al, 0xF1 ; 'ё'
1504 diamond 415
        jz      .yo1
3555 Serge 416
        cmp     al, 0xA0 ; 'а'
417
        jb      .ret
418
        cmp     al, 0xE0 ; 'р'
419
        jb      .rus1
420
        cmp     al, 0xEF ; 'я'
421
        ja      .ret
71 diamond 422
; 0xE0-0xEF -> 0x90-0x9F
3555 Serge 423
        sub     al, 0xE0-0x90
71 diamond 424
.ret:
3555 Serge 425
        ret
71 diamond 426
.rus1:
427
; 0xA0-0xAF -> 0x80-0x8F
428
.az:
3555 Serge 429
        and     al, not 0x20
430
        ret
1504 diamond 431
.yo1:
432
; 0xF1 -> 0xF0
433
        dec     ax
434
        ret
71 diamond 435
 
436
fat_get_name:
437
; in: edi->FAT entry
438
; out: CF=1 - no valid entry
439
; else CF=0 and ebp->ASCIIZ-name
440
; (maximum length of filename is 255 (wide) symbols without trailing 0,
441
;  but implementation requires buffer 261 words)
442
; destroys eax
3555 Serge 443
        cmp     byte [edi], 0
444
        jz      .no
445
        cmp     byte [edi], 0xE5
446
        jnz     @f
71 diamond 447
.no:
3555 Serge 448
        stc
449
        ret
71 diamond 450
@@:
3555 Serge 451
        cmp     byte [edi+11], 0xF
452
        jz      .longname
453
        test    byte [edi+11], 8
454
        jnz     .no
455
        push    ecx
456
        push    edi ebp
457
        test    byte [ebp-4], 1
458
        jnz     .unicode_short
247 serge 459
 
3555 Serge 460
        mov     eax, [edi]
461
        mov     ecx, [edi+4]
462
        mov     [ebp], eax
463
        mov     [ebp+4], ecx
247 serge 464
 
3555 Serge 465
        mov     ecx, 8
71 diamond 466
@@:
3555 Serge 467
        cmp     byte [ebp+ecx-1], ' '
468
        loope   @b
247 serge 469
 
3555 Serge 470
        mov     eax, [edi+8]
471
        cmp     al, ' '
472
        je      .done
473
        shl     eax, 8
474
        mov     al, '.'
247 serge 475
 
3555 Serge 476
        lea     ebp, [ebp+ecx+1]
477
        mov     [ebp], eax
478
        mov     ecx, 3
71 diamond 479
@@:
3555 Serge 480
        rol     eax, 8
481
        cmp     al, ' '
482
        jne     .done
483
        loop    @b
484
        dec     ebp
247 serge 485
.done:
3555 Serge 486
        and     byte [ebp+ecx+1], 0   ; CF=0
487
        pop     ebp edi ecx
488
        ret
75 diamond 489
.unicode_short:
3555 Serge 490
        mov     ecx, 8
491
        push    ecx
75 diamond 492
@@:
3555 Serge 493
        mov     al, [edi]
494
        inc     edi
495
        call    ansi2uni_char
496
        mov     [ebp], ax
497
        inc     ebp
498
        inc     ebp
499
        loop    @b
500
        pop     ecx
75 diamond 501
@@:
3555 Serge 502
        cmp     word [ebp-2], ' '
503
        jnz     @f
504
        dec     ebp
505
        dec     ebp
506
        loop    @b
75 diamond 507
@@:
3555 Serge 508
        mov     word [ebp], '.'
509
        inc     ebp
510
        inc     ebp
511
        mov     ecx, 3
512
        push    ecx
75 diamond 513
@@:
3555 Serge 514
        mov     al, [edi]
515
        inc     edi
516
        call    ansi2uni_char
517
        mov     [ebp], ax
518
        inc     ebp
519
        inc     ebp
520
        loop    @b
521
        pop     ecx
75 diamond 522
@@:
3555 Serge 523
        cmp     word [ebp-2], ' '
524
        jnz     @f
525
        dec     ebp
526
        dec     ebp
527
        loop    @b
528
        dec     ebp
529
        dec     ebp
75 diamond 530
@@:
3555 Serge 531
        and     word [ebp], 0   ; CF=0
532
        pop     ebp edi ecx
533
        ret
71 diamond 534
.longname:
535
; LFN
3555 Serge 536
        mov     al, byte [edi]
537
        and     eax, 0x3F
538
        dec     eax
539
        cmp     al, 20
540
        jae     .no     ; ignore invalid entries
541
        mov     word [ebp+260*2], 0     ; force null-terminating for orphans
542
        imul    eax, 13*2
543
        add     ebp, eax
544
        test    byte [edi], 0x40
545
        jz      @f
546
        mov     word [ebp+13*2], 0
71 diamond 547
@@:
3555 Serge 548
        push    eax
71 diamond 549
; now copy name from edi to ebp ...
3555 Serge 550
        mov     eax, [edi+1]
551
        mov     [ebp], eax      ; symbols 1,2
552
        mov     eax, [edi+5]
553
        mov     [ebp+4], eax    ; 3,4
554
        mov     eax, [edi+9]
555
        mov     [ebp+8], ax     ; 5
556
        mov     eax, [edi+14]
557
        mov     [ebp+10], eax   ; 6,7
558
        mov     eax, [edi+18]
559
        mov     [ebp+14], eax   ; 8,9
560
        mov     eax, [edi+22]
561
        mov     [ebp+18], eax   ; 10,11
562
        mov     eax, [edi+28]
563
        mov     [ebp+22], eax   ; 12,13
71 diamond 564
; ... done
3555 Serge 565
        pop     eax
566
        sub     ebp, eax
567
        test    eax, eax
568
        jz      @f
71 diamond 569
; if this is not first entry, more processing required
3555 Serge 570
        stc
571
        ret
71 diamond 572
@@:
573
; if this is first entry:
3555 Serge 574
        test    byte [ebp-4], 1
575
        jnz     .ret
71 diamond 576
; buffer at ebp contains UNICODE name, convert it to ANSI
3555 Serge 577
        push    esi edi
578
        mov     esi, ebp
579
        mov     edi, ebp
580
        call    uni2ansi_str
581
        pop     edi esi
75 diamond 582
.ret:
3555 Serge 583
        clc
584
        ret
71 diamond 585
 
586
fat_compare_name:
587
; compares ASCIIZ-names, case-insensitive (cp866 encoding)
588
; in: esi->name, ebp->name
589
; out: if names match: ZF=1 and esi->next component of name
590
;      else: ZF=0, esi is not changed
591
; destroys eax
3555 Serge 592
        push    ebp esi
71 diamond 593
.loop:
3555 Serge 594
        mov     al, [ebp]
595
        inc     ebp
596
        call    char_toupper
597
        push    eax
598
        lodsb
599
        call    char_toupper
600
        cmp     al, [esp]
601
        jnz     .done
602
        pop     eax
603
        test    al, al
604
        jnz     .loop
605
        dec     esi
606
        pop     eax
607
        pop     ebp
608
        xor     eax, eax        ; set ZF flag
609
        ret
71 diamond 610
.done:
3555 Serge 611
        cmp     al, '/'
612
        jnz     @f
613
        cmp     byte [esp], 0
614
        jnz     @f
615
        mov     [esp+4], esi
71 diamond 616
@@:
3555 Serge 617
        pop     eax
618
        pop     esi ebp
619
        ret
71 diamond 620
 
75 diamond 621
fat_time_to_bdfe:
622
; in: eax=FAT time
623
; out: eax=BDFE time
3555 Serge 624
        push    ecx edx
625
        mov     ecx, eax
626
        mov     edx, eax
627
        shr     eax, 11
628
        shl     eax, 16 ; hours
629
        and     edx, 0x1F
630
        add     edx, edx
631
        mov     al, dl  ; seconds
632
        shr     ecx, 5
633
        and     ecx, 0x3F
634
        mov     ah, cl  ; minutes
635
        pop     edx ecx
636
        ret
75 diamond 637
 
638
fat_date_to_bdfe:
3555 Serge 639
        push    ecx edx
640
        mov     ecx, eax
641
        mov     edx, eax
642
        shr     eax, 9
643
        add     ax, 1980
644
        shl     eax, 16 ; year
645
        and     edx, 0x1F
646
        mov     al, dl  ; day
647
        shr     ecx, 5
648
        and     ecx, 0xF
649
        mov     ah, cl  ; month
650
        pop     edx ecx
651
        ret
75 diamond 652
 
86 diamond 653
bdfe_to_fat_time:
3555 Serge 654
        push    edx
655
        mov     edx, eax
656
        shr     eax, 16
657
        and     dh, 0x3F
658
        shl     eax, 6
659
        or      al, dh
660
        shr     dl, 1
661
        and     dl, 0x1F
662
        shl     eax, 5
663
        or      al, dl
664
        pop     edx
665
        ret
86 diamond 666
 
667
bdfe_to_fat_date:
3555 Serge 668
        push    edx
669
        mov     edx, eax
670
        shr     eax, 16
671
        sub     ax, 1980
672
        and     dh, 0xF
673
        shl     eax, 4
674
        or      al, dh
675
        and     dl, 0x1F
676
        shl     eax, 5
677
        or      al, dl
678
        pop     edx
679
        ret
86 diamond 680
 
75 diamond 681
fat_entry_to_bdfe:
682
; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
683
; destroys eax
3555 Serge 684
        mov     eax, [ebp-4]
685
        mov     [esi+4], eax    ; ASCII/UNICODE name
86 diamond 686
fat_entry_to_bdfe2:
3555 Serge 687
        movzx   eax, byte [edi+11]
688
        mov     [esi], eax      ; attributes
689
        movzx   eax, word [edi+14]
690
        call    fat_time_to_bdfe
691
        mov     [esi+8], eax    ; creation time
692
        movzx   eax, word [edi+16]
693
        call    fat_date_to_bdfe
694
        mov     [esi+12], eax   ; creation date
695
        and     dword [esi+16], 0       ; last access time is not supported on FAT
696
        movzx   eax, word [edi+18]
697
        call    fat_date_to_bdfe
698
        mov     [esi+20], eax   ; last access date
699
        movzx   eax, word [edi+22]
700
        call    fat_time_to_bdfe
701
        mov     [esi+24], eax   ; last write time
702
        movzx   eax, word [edi+24]
703
        call    fat_date_to_bdfe
704
        mov     [esi+28], eax   ; last write date
705
        mov     eax, [edi+28]
706
        mov     [esi+32], eax   ; file size (low dword)
707
        xor     eax, eax
708
        mov     [esi+36], eax   ; file size (high dword)
709
        test    ebp, ebp
710
        jz      .ret
711
        push    ecx edi
712
        lea     edi, [esi+40]
713
        mov     esi, ebp
714
        test    byte [esi-4], 1
715
        jz      .ansi
716
        mov     ecx, 260/2
717
        rep movsd
718
        mov     [edi-2], ax
78 diamond 719
@@:
3555 Serge 720
        mov     esi, edi
721
        pop     edi ecx
86 diamond 722
.ret:
3555 Serge 723
        ret
78 diamond 724
.ansi:
3555 Serge 725
        mov     ecx, 264/4
726
        rep movsd
727
        mov     [edi-1], al
728
        jmp     @b
75 diamond 729
 
86 diamond 730
bdfe_to_fat_entry:
731
; convert BDFE at edx to FAT entry at edi
732
; destroys eax
733
; attributes byte
3555 Serge 734
        test    byte [edi+11], 8        ; volume label?
735
        jnz     @f
736
        mov     al, [edx]
737
        and     al, 0x27
738
        and     byte [edi+11], 0x10
739
        or      byte [edi+11], al
86 diamond 740
@@:
3555 Serge 741
        mov     eax, [edx+8]
742
        call    bdfe_to_fat_time
743
        mov     [edi+14], ax            ; creation time
744
        mov     eax, [edx+12]
745
        call    bdfe_to_fat_date
746
        mov     [edi+16], ax            ; creation date
747
        mov     eax, [edx+20]
748
        call    bdfe_to_fat_date
749
        mov     [edi+18], ax            ; last access date
750
        mov     eax, [edx+24]
751
        call    bdfe_to_fat_time
752
        mov     [edi+22], ax            ; last write time
753
        mov     eax, [edx+28]
754
        call    bdfe_to_fat_date
755
        mov     [edi+24], ax            ; last write date
756
        ret
86 diamond 757
 
758
ramdisk_root_first:
3555 Serge 759
        mov     edi, RAMDISK+512*19
760
        clc
761
        ret
86 diamond 762
ramdisk_root_next:
3555 Serge 763
        add     edi, 0x20
764
        cmp     edi, RAMDISK+512*33
765
        cmc
766
        ret
86 diamond 767
 
91 diamond 768
ramdisk_root_extend_dir:
3555 Serge 769
        stc
770
        ret
91 diamond 771
 
171 diamond 772
uglobal
773
; this is for delete support
3555 Serge 774
rd_prev_sector          dd      ?
775
rd_prev_prev_sector     dd      ?
171 diamond 776
endg
777
 
91 diamond 778
ramdisk_notroot_next:
3555 Serge 779
        add     edi, 0x20
780
        test    edi, 0x1FF
781
        jz      ramdisk_notroot_next_sector
782
        ret     ; CF=0
91 diamond 783
ramdisk_notroot_next_sector:
3555 Serge 784
        push    ecx
785
        mov     ecx, [eax]
786
        push    [rd_prev_sector]
787
        pop     [rd_prev_prev_sector]
788
        mov     [rd_prev_sector], ecx
789
        mov     ecx, [ecx*2+RAMDISK_FAT]
790
        and     ecx, 0xFFF
791
        cmp     ecx, 2849
792
        jae     ramdisk_notroot_first.err2
793
        mov     [eax], ecx
794
        pop     ecx
91 diamond 795
ramdisk_notroot_first:
3555 Serge 796
        mov     eax, [eax]
797
        cmp     eax, 2
798
        jb      .err
799
        cmp     eax, 2849
800
        jae     .err
801
        shl     eax, 9
802
        lea     edi, [eax+(31 shl 9)+RAMDISK]
803
        clc
804
        ret
91 diamond 805
.err2:
3555 Serge 806
        pop     ecx
91 diamond 807
.err:
3555 Serge 808
        stc
809
        ret
91 diamond 810
ramdisk_notroot_next_write:
3555 Serge 811
        test    edi, 0x1FF
812
        jz      ramdisk_notroot_next_sector
91 diamond 813
ramdisk_root_next_write:
3555 Serge 814
        ret
91 diamond 815
 
816
ramdisk_notroot_extend_dir:
3555 Serge 817
        pusha
818
        xor     eax, eax
819
        mov     edi, RAMDISK_FAT
820
        mov     ecx, 2849
821
        repnz scasw
822
        jnz     .notfound
823
        mov     word [edi-2], 0xFFF
824
        sub     edi, RAMDISK_FAT
825
        shr     edi, 1
826
        dec     edi
827
        mov     eax, [esp+28]
828
        mov     ecx, [eax]
829
        mov     [RAMDISK_FAT+ecx*2], di
830
        mov     [eax], edi
831
        shl     edi, 9
832
        add     edi, (31 shl 9)+RAMDISK
833
        mov     [esp], edi
834
        xor     eax, eax
835
        mov     ecx, 128
836
        rep stosd
837
        popa
838
        clc
839
        ret
91 diamond 840
.notfound:
3555 Serge 841
        popa
842
        stc
843
        ret
91 diamond 844
 
71 diamond 845
rd_find_lfn:
521 diamond 846
; in: esi+ebp -> name
71 diamond 847
; out: CF=1 - file not found
848
;      else CF=0 and edi->direntry
3555 Serge 849
        push    esi edi
850
        push    0
851
        push    ramdisk_root_first
852
        push    ramdisk_root_next
91 diamond 853
.loop:
3555 Serge 854
        call    fat_find_lfn
855
        jc      .notfound
856
        cmp     byte [esi], 0
857
        jz      .found
521 diamond 858
.continue:
3555 Serge 859
        test    byte [edi+11], 10h
860
        jz      .notfound
861
        movzx   eax, word [edi+26]
862
        mov     [esp+8], eax
863
        mov     dword [esp+4], ramdisk_notroot_first
864
        mov     dword [esp], ramdisk_notroot_next
865
        test    eax, eax
866
        jnz     .loop
867
        mov     dword [esp+4], ramdisk_root_first
868
        mov     dword [esp], ramdisk_notroot_next
869
        jmp     .loop
91 diamond 870
.notfound:
3555 Serge 871
        add     esp, 12
872
        pop     edi esi
873
        stc
874
        ret
91 diamond 875
.found:
3555 Serge 876
        test    ebp, ebp
877
        jz      @f
878
        mov     esi, ebp
879
        xor     ebp, ebp
880
        jmp     .continue
521 diamond 881
@@:
3555 Serge 882
        mov     eax, [esp+8]
883
        add     esp, 16         ; CF=0
884
        pop     esi
885
        ret
71 diamond 886
 
887
;----------------------------------------------------------------
888
;
889
;  fs_RamdiskRead - LFN variant for reading sys floppy
890
;
891
;  esi  points to filename
892
;  ebx  pointer to 64-bit number = first wanted byte, 0+
893
;       may be ebx=0 - start from first byte
894
;  ecx  number of bytes to read, 0+
895
;  edx  mem location to return data
896
;
77 diamond 897
;  ret ebx = bytes read or 0xffffffff file not found
71 diamond 898
;      eax = 0 ok read or other = errormsg
899
;
900
;--------------------------------------------------------------
901
fs_RamdiskRead:
3555 Serge 902
        cmp     byte [esi], 0
903
        jnz     @f
904
        or      ebx, -1
905
        mov     eax, 10         ; access denied
906
        ret
71 diamond 907
@@:
3555 Serge 908
        push    edi
909
        call    rd_find_lfn
910
        jnc     .found
911
        pop     edi
912
        or      ebx, -1
913
        mov     eax, 5          ; file not found
914
        ret
71 diamond 915
.found:
3555 Serge 916
        test    ebx, ebx
917
        jz      .l1
918
        cmp     dword [ebx+4], 0
919
        jz      @f
920
        xor     ebx, ebx
71 diamond 921
.reteof:
3555 Serge 922
        mov     eax, 6          ; EOF
923
        pop     edi
924
        ret
71 diamond 925
@@:
3555 Serge 926
        mov     ebx, [ebx]
71 diamond 927
.l1:
3555 Serge 928
        push    ecx edx
929
        push    0
930
        mov     eax, [edi+28]
931
        sub     eax, ebx
932
        jb      .eof
933
        cmp     eax, ecx
934
        jae     @f
935
        mov     ecx, eax
936
        mov     byte [esp], 6           ; EOF
77 diamond 937
@@:
3555 Serge 938
        movzx   edi, word [edi+26]      ; cluster
71 diamond 939
.new:
3555 Serge 940
        jecxz   .done
941
        test    edi, edi
942
        jz      .eof
943
        cmp     edi, 0xFF8
944
        jae     .eof
945
        lea     eax, [edi+31]           ; bootsector+2*fat+filenames
946
        shl     eax, 9                  ; *512
947
        add     eax, RAMDISK           ; image base
71 diamond 948
; now eax points to data of cluster
3555 Serge 949
        sub     ebx, 512
950
        jae     .skip
951
        lea     eax, [eax+ebx+512]
952
        neg     ebx
953
        push    ecx
954
        cmp     ecx, ebx
955
        jbe     @f
956
        mov     ecx, ebx
71 diamond 957
@@:
3555 Serge 958
        mov     ebx, edx
959
        call    memmove
960
        add     edx, ecx
961
        sub     [esp], ecx
962
        pop     ecx
963
        xor     ebx, ebx
71 diamond 964
.skip:
3555 Serge 965
        movzx   edi, word [edi*2+RAMDISK_FAT]      ; find next cluster from FAT
966
        jmp     .new
71 diamond 967
.eof:
3555 Serge 968
        mov     ebx, edx
969
        pop     eax edx ecx
970
        sub     ebx, edx
971
        jmp     .reteof
71 diamond 972
.done:
3555 Serge 973
        mov     ebx, edx
974
        pop     eax edx ecx edi
975
        sub     ebx, edx
976
        ret
71 diamond 977
 
75 diamond 978
;----------------------------------------------------------------
979
;
980
;  fs_RamdiskReadFolder - LFN variant for reading sys floppy folder
981
;
982
;  esi  points to filename; only root is folder on ramdisk
78 diamond 983
;  ebx  pointer to structure 32-bit number = first wanted block
984
;                          & flags (bitfields)
985
; flags: bit 0: 0=ANSI names, 1=UNICODE names
75 diamond 986
;  ecx  number of blocks to read, 0+
987
;  edx  mem location to return data
988
;
989
;  ret ebx = size or 0xffffffff file not found
990
;      eax = 0 ok read or other = errormsg
991
;
992
;--------------------------------------------------------------
993
fs_RamdiskReadFolder:
3555 Serge 994
        push    edi
995
        cmp     byte [esi], 0
996
        jz      .root
997
        call    rd_find_lfn
998
        jnc     .found
999
        pop     edi
1000
        or      ebx, -1
1001
        mov     eax, ERROR_FILE_NOT_FOUND
1002
        ret
91 diamond 1003
.found:
3555 Serge 1004
        test    byte [edi+11], 0x10
1005
        jnz     .found_dir
1006
        pop     edi
1007
        or      ebx, -1
1008
        mov     eax, ERROR_ACCESS_DENIED
1009
        ret
91 diamond 1010
.found_dir:
3555 Serge 1011
        movzx   eax, word [edi+26]
1012
        add     eax, 31
1013
        push    0
1014
        jmp     .doit
91 diamond 1015
.root:
3555 Serge 1016
        mov     eax, 19
1017
        push    14
91 diamond 1018
.doit:
3555 Serge 1019
        push    esi ecx ebp
1020
        sub     esp, 262*2      ; reserve space for LFN
1021
        mov     ebp, esp
1022
        push    dword [ebx+4]   ; for fat_get_name: read ANSI/UNICODE names
1023
        mov     ebx, [ebx]
75 diamond 1024
; init header
3555 Serge 1025
        push    eax ecx
1026
        mov     edi, edx
1027
        mov     ecx, 32/4
1028
        xor     eax, eax
1029
        rep stosd
1030
        mov     byte [edx], 1   ; version
1031
        pop     ecx eax
1032
        mov     esi, edi        ; esi points to block of data of folder entry (BDFE)
91 diamond 1033
.main_loop:
3555 Serge 1034
        mov     edi, eax
1035
        shl     edi, 9
1036
        add     edi, RAMDISK
1037
        push    eax
75 diamond 1038
.l1:
3555 Serge 1039
        call    fat_get_name
1040
        jc      .l2
1041
        cmp     byte [edi+11], 0xF
1042
        jnz     .do_bdfe
1043
        add     edi, 0x20
1044
        test    edi, 0x1FF
1045
        jnz     .do_bdfe
1046
        pop     eax
1047
        inc     eax
1048
        dec     byte [esp+262*2+16]
1049
        jz      .done
1050
        jns     @f
91 diamond 1051
; read next sector from FAT
3555 Serge 1052
        mov     eax, [(eax-31-1)*2+RAMDISK_FAT]
1053
        and     eax, 0xFFF
1054
        cmp     eax, 0xFF8
1055
        jae     .done
1056
        add     eax, 31
1057
        mov     byte [esp+262*2+16], 0
75 diamond 1058
@@:
3555 Serge 1059
        mov     edi, eax
1060
        shl     edi, 9
1061
        add     edi, RAMDISK
1062
        push    eax
91 diamond 1063
.do_bdfe:
3555 Serge 1064
        inc     dword [edx+8]   ; new file found
1065
        dec     ebx
1066
        jns     .l2
1067
        dec     ecx
1068
        js      .l2
1069
        inc     dword [edx+4]  ; new file block copied
1070
        call    fat_entry_to_bdfe
75 diamond 1071
.l2:
3555 Serge 1072
        add     edi, 0x20
1073
        test    edi, 0x1FF
1074
        jnz     .l1
1075
        pop     eax
1076
        inc     eax
1077
        dec     byte [esp+262*2+16]
1078
        jz      .done
1079
        jns     @f
91 diamond 1080
; read next sector from FAT
3555 Serge 1081
        mov     eax, [(eax-31-1)*2+RAMDISK_FAT]
1082
        and     eax, 0xFFF
1083
        cmp     eax, 0xFF8
1084
        jae     .done
1085
        add     eax, 31
1086
        mov     byte [esp+262*2+16], 0
91 diamond 1087
@@:
3555 Serge 1088
        jmp     .main_loop
91 diamond 1089
.done:
3555 Serge 1090
        add     esp, 262*2+4
1091
        pop     ebp
1092
        mov     ebx, [edx+4]
1093
        xor     eax, eax
1094
        dec     ecx
1095
        js      @f
1096
        mov     al, ERROR_END_OF_FILE
75 diamond 1097
@@:
3555 Serge 1098
        pop     ecx esi edi edi
1099
        ret
75 diamond 1100
 
83 diamond 1101
iglobal
1102
label fat_legal_chars byte
1103
; 0 = not allowed
1104
; 1 = allowed only in long names
1105
; 3 = allowed
3555 Serge 1106
        times 32 db 0
83 diamond 1107
;                 ! " # $ % & ' ( ) * + , - . /
3555 Serge 1108
        db      1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0
83 diamond 1109
;               0 1 2 3 4 5 6 7 8 9 : ; < = > ?
3555 Serge 1110
        db      3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0
83 diamond 1111
;               @ A B C D E F G H I J K L M N O
3555 Serge 1112
        db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
83 diamond 1113
;               P Q R S T U V W X Y Z [ \ ] ^ _
3555 Serge 1114
        db      3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3
83 diamond 1115
;               ` a b c d e f g h i j k l m n o
3555 Serge 1116
        db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
83 diamond 1117
;               p q r s t u v w x y z { | } ~
3555 Serge 1118
        db      3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0
83 diamond 1119
endg
1120
 
1121
fat_name_is_legal:
1122
; in: esi->(long) name
1123
; out: CF set <=> legal
1124
; destroys eax
3555 Serge 1125
        push    esi
1126
        xor     eax, eax
83 diamond 1127
@@:
3555 Serge 1128
        lodsb
1129
        test    al, al
1130
        jz      .done
1131
        cmp     al, 80h
1132
        jae     .big
1133
        test    [fat_legal_chars+eax], 1
1134
        jnz     @b
83 diamond 1135
.err:
3555 Serge 1136
        pop     esi
1137
        clc
1138
        ret
83 diamond 1139
.big:
1140
; 0x80-0xAF, 0xE0-0xEF
3555 Serge 1141
        cmp     al, 0xB0
1142
        jb      @b
1143
        cmp     al, 0xE0
1144
        jb      .err
1145
        cmp     al, 0xF0
1146
        jb      @b
1147
        jmp     .err
83 diamond 1148
.done:
3555 Serge 1149
        sub     esi, [esp]
1150
        cmp     esi, 257
1151
        pop     esi
1152
        ret
83 diamond 1153
 
1154
fat_next_short_name:
1155
; in: edi->8+3 name
1156
; out: name corrected
1157
;      CF=1 <=> error
3555 Serge 1158
        pushad
1159
        mov     ecx, 8
1160
        mov     al, '~'
1161
        std
1162
        push    edi
1163
        add     edi, 7
1164
        repnz scasb
1165
        pop     edi
1166
        cld
1167
        jz      .tilde
83 diamond 1168
; tilde is not found, insert "~1" at end
3555 Serge 1169
        add     edi, 6
1170
        cmp     word [edi], '  '
1171
        jnz     .insert_tilde
2434 Serge 1172
@@:
1173
        dec     edi
3555 Serge 1174
        cmp     byte [edi], ' '
1175
        jz      @b
1176
        inc     edi
83 diamond 1177
.insert_tilde:
3555 Serge 1178
        mov     word [edi], '~1'
1179
        popad
1180
        clc
1181
        ret
83 diamond 1182
.tilde:
3555 Serge 1183
        push    edi
1184
        add     edi, 7
1185
        xor     ecx, ecx
83 diamond 1186
@@:
1187
; after tilde may be only digits and trailing spaces
3555 Serge 1188
        cmp     byte [edi], '~'
1189
        jz      .break
1190
        cmp     byte [edi], ' '
1191
        jz      .space
1192
        cmp     byte [edi], '9'
1193
        jnz     .found
1194
        dec     edi
1195
        jmp     @b
83 diamond 1196
.space:
3555 Serge 1197
        dec     edi
1198
        inc     ecx
1199
        jmp     @b
83 diamond 1200
.found:
3555 Serge 1201
        inc     byte [edi]
1202
        add     dword [esp], 8
1203
        jmp     .zerorest
83 diamond 1204
.break:
3555 Serge 1205
        jecxz   .noplace
1206
        inc     edi
1207
        mov     al, '1'
83 diamond 1208
@@:
3555 Serge 1209
        xchg    al, [edi]
1210
        inc     edi
1211
        cmp     al, ' '
1212
        mov     al, '0'
1213
        jnz     @b
466 diamond 1214
.succ:
3555 Serge 1215
        pop     edi
1216
        popad
1217
        clc
1218
        ret
83 diamond 1219
.noplace:
3555 Serge 1220
        dec     edi
1221
        cmp     edi, [esp]
1222
        jz      .err
1223
        add     dword [esp], 8
1224
        mov     word [edi], '~1'
1225
        inc     edi
1226
        inc     edi
83 diamond 1227
@@:
3555 Serge 1228
        mov     byte [edi], '0'
466 diamond 1229
.zerorest:
3555 Serge 1230
        inc     edi
1231
        cmp     edi, [esp]
1232
        jb      @b
1233
        pop     edi
1234
        popad
1235
        ;clc    ; automatically
1236
        ret
83 diamond 1237
.err:
3555 Serge 1238
        pop     edi
1239
        popad
1240
        stc
1241
        ret
83 diamond 1242
 
1243
fat_gen_short_name:
1244
; in: esi->long name
1245
;     edi->buffer (8+3=11 chars)
1246
; out: buffer filled
3555 Serge 1247
        pushad
1248
        mov     eax, '    '
1249
        push    edi
1250
        stosd
1251
        stosd
1252
        stosd
1253
        pop     edi
1254
        xor     eax, eax
1255
        push    8
1256
        pop     ebx
1257
        lea     ecx, [edi+8]
83 diamond 1258
.loop:
3555 Serge 1259
        lodsb
1260
        test    al, al
1261
        jz      .done
1262
        call    char_toupper
1263
        cmp     al, ' '
1264
        jz      .space
1265
        cmp     al, 80h
1266
        ja      .big
1267
        test    [fat_legal_chars+eax], 2
1268
        jnz     .symbol
83 diamond 1269
.inv_symbol:
3555 Serge 1270
        mov     al, '_'
1271
        or      bh, 1
83 diamond 1272
.symbol:
3555 Serge 1273
        cmp     al, '.'
1274
        jz      .dot
83 diamond 1275
.normal_symbol:
3555 Serge 1276
        dec     bl
1277
        jns     .store
1278
        mov     bl, 0
83 diamond 1279
.space:
3555 Serge 1280
        or      bh, 1
1281
        jmp     .loop
83 diamond 1282
.store:
3555 Serge 1283
        stosb
1284
        jmp     .loop
83 diamond 1285
.big:
3555 Serge 1286
        cmp     al, 0xB0
1287
        jb      .normal_symbol
1288
        cmp     al, 0xE0
1289
        jb      .inv_symbol
1290
        cmp     al, 0xF0
1291
        jb      .normal_symbol
1292
        jmp     .inv_symbol
83 diamond 1293
.dot:
3555 Serge 1294
        test    bh, 2
1295
        jz      .firstdot
1296
        pop     ebx
1297
        add     ebx, edi
1298
        sub     ebx, ecx
1299
        push    ebx
1300
        cmp     ebx, ecx
1301
        jb      @f
1302
        pop     ebx
1303
        push    ecx
527 diamond 1304
@@:
3555 Serge 1305
        cmp     edi, ecx
1306
        jbe     .skip
83 diamond 1307
@@:
3555 Serge 1308
        dec     edi
1309
        mov     al, [edi]
1310
        dec     ebx
1311
        mov     [ebx], al
1312
        mov     byte [edi], ' '
1313
        cmp     edi, ecx
1314
        ja      @b
83 diamond 1315
.skip:
3555 Serge 1316
        mov     bh, 3
1317
        jmp     @f
83 diamond 1318
.firstdot:
3555 Serge 1319
        cmp     bl, 8
1320
        jz      .space
1321
        push    edi
1322
        or      bh, 2
83 diamond 1323
@@:
3555 Serge 1324
        mov     edi, ecx
1325
        mov     bl, 3
1326
        jmp     .loop
83 diamond 1327
.done:
3555 Serge 1328
        test    bh, 2
1329
        jz      @f
1330
        pop     edi
83 diamond 1331
@@:
3555 Serge 1332
        lea     edi, [ecx-8]
1333
        test    bh, 1
1334
        jz      @f
1335
        call    fat_next_short_name
83 diamond 1336
@@:
3555 Serge 1337
        popad
1338
        ret
83 diamond 1339
 
1340
;----------------------------------------------------------------
1341
;
321 diamond 1342
;  fs_RamdiskRewrite - LFN variant for writing ramdisk
1343
;  fs_RamdiskCreateFolder - create folder on ramdisk
83 diamond 1344
;
321 diamond 1345
;  esi  points to file/folder name
83 diamond 1346
;  ebx  ignored (reserved)
321 diamond 1347
;  ecx  number of bytes to write, 0+ (ignored for folders)
1348
;  edx  mem location to data (ignored for folders)
83 diamond 1349
;
1350
;  ret ebx = number of written bytes
1351
;      eax = 0 ok read or other = errormsg
1352
;
1353
;--------------------------------------------------------------
1354
@@:
3555 Serge 1355
        mov     eax, ERROR_ACCESS_DENIED
1356
        xor     ebx, ebx
1357
        ret
83 diamond 1358
 
321 diamond 1359
fs_RamdiskCreateFolder:
3555 Serge 1360
        mov     al, 1           ; create folder
1361
        jmp     fs_RamdiskRewrite.common
321 diamond 1362
 
83 diamond 1363
fs_RamdiskRewrite:
3555 Serge 1364
        xor     eax, eax        ; create file
321 diamond 1365
.common:
3555 Serge 1366
        cmp     byte [esi], 0
1367
        jz      @b
1368
        pushad
1369
        xor     edi, edi
1370
        push    esi
1371
        test    ebp, ebp
1372
        jz      @f
1373
        mov     esi, ebp
83 diamond 1374
@@:
3555 Serge 1375
        lodsb
1376
        test    al, al
1377
        jz      @f
1378
        cmp     al, '/'
1379
        jnz     @b
1380
        lea     edi, [esi-1]
1381
        jmp     @b
91 diamond 1382
@@:
3555 Serge 1383
        pop     esi
1384
        test    edi, edi
1385
        jnz     .noroot
1386
        test    ebp, ebp
1387
        jnz     .hasebp
1388
        push    ramdisk_root_extend_dir
1389
        push    ramdisk_root_next_write
1390
        push    edi
1391
        push    ramdisk_root_first
1392
        push    ramdisk_root_next
1393
        jmp     .common1
521 diamond 1394
.hasebp:
3555 Serge 1395
        mov     eax, ERROR_ACCESS_DENIED
1396
        cmp     byte [ebp], 0
1397
        jz      .ret1
1398
        push    ebp
1399
        xor     ebp, ebp
1400
        call    rd_find_lfn
1401
        pop     esi
1402
        jc      .notfound0
1403
        jmp     .common0
91 diamond 1404
.noroot:
3555 Serge 1405
        mov     eax, ERROR_ACCESS_DENIED
1406
        cmp     byte [edi+1], 0
1407
        jz      .ret1
91 diamond 1408
; check existence
3555 Serge 1409
        mov     byte [edi], 0
1410
        push    edi
1411
        call    rd_find_lfn
1412
        pop     esi
1413
        mov     byte [esi], '/'
1414
        jnc     @f
521 diamond 1415
.notfound0:
3555 Serge 1416
        mov     eax, ERROR_FILE_NOT_FOUND
91 diamond 1417
.ret1:
3555 Serge 1418
        mov     [esp+28], eax
1419
        popad
1420
        xor     ebx, ebx
1421
        ret
83 diamond 1422
@@:
3555 Serge 1423
        inc     esi
521 diamond 1424
.common0:
3555 Serge 1425
        test    byte [edi+11], 0x10     ; must be directory
1426
        mov     eax, ERROR_ACCESS_DENIED
1427
        jz      .ret1
1428
        movzx   ebp, word [edi+26]      ; ebp=cluster
1429
        mov     eax, ERROR_FAT_TABLE
1430
        cmp     ebp, 2
1431
        jb      .ret1
1432
        cmp     ebp, 2849
1433
        jae     .ret1
1434
        push    ramdisk_notroot_extend_dir
1435
        push    ramdisk_notroot_next_write
1436
        push    ebp
1437
        push    ramdisk_notroot_first
1438
        push    ramdisk_notroot_next
91 diamond 1439
.common1:
3555 Serge 1440
        call    fat_find_lfn
1441
        jc      .notfound
321 diamond 1442
; found
3555 Serge 1443
        test    byte [edi+11], 10h
1444
        jz      .exists_file
321 diamond 1445
; found directory; if we are creating directory, return OK,
1446
;                  if we are creating file, say "access denied"
3555 Serge 1447
        add     esp, 20
1448
        popad
1449
        test    al, al
1450
        mov     eax, ERROR_ACCESS_DENIED
1451
        jz      @f
1452
        mov     al, 0
321 diamond 1453
@@:
3555 Serge 1454
        xor     ebx, ebx
1455
        ret
321 diamond 1456
.exists_file:
1457
; found file; if we are creating directory, return "access denied",
1458
;             if we are creating file, delete existing file and continue
3555 Serge 1459
        cmp     byte [esp+20+28], 0
1460
        jz      @f
1461
        add     esp, 20
1462
        popad
1463
        mov     eax, ERROR_ACCESS_DENIED
1464
        xor     ebx, ebx
1465
        ret
91 diamond 1466
@@:
1467
; delete FAT chain
3555 Serge 1468
        push    edi
1469
        xor     eax, eax
1470
        mov     dword [edi+28], eax     ; zero size
1471
        xchg    ax, word [edi+26]       ; start cluster
1472
        test    eax, eax
1473
        jz      .done1
83 diamond 1474
@@:
3555 Serge 1475
        cmp     eax, 0xFF8
1476
        jae     .done1
1477
        lea     edi, [RAMDISK_FAT + eax*2] ; position in FAT
1478
        xor     eax, eax
1479
        xchg    ax, [edi]
1480
        jmp     @b
83 diamond 1481
.done1:
3555 Serge 1482
        pop     edi
1483
        call    get_time_for_file
1484
        mov     [edi+22], ax
1485
        call    get_date_for_file
1486
        mov     [edi+24], ax
1487
        mov     [edi+18], ax
1488
        or      byte [edi+11], 20h      ; set 'archive' attribute
1489
        jmp     .doit
83 diamond 1490
.notfound:
1491
; file is not found; generate short name
3555 Serge 1492
        call    fat_name_is_legal
1493
        jc      @f
1494
        add     esp, 20
1495
        popad
1496
        mov     eax, ERROR_FILE_NOT_FOUND
1497
        xor     ebx, ebx
1498
        ret
83 diamond 1499
@@:
3555 Serge 1500
        sub     esp, 12
1501
        mov     edi, esp
1502
        call    fat_gen_short_name
83 diamond 1503
.test_short_name_loop:
3555 Serge 1504
        push    esi edi ecx
1505
        mov     esi, edi
1506
        lea     eax, [esp+12+12+8]
1507
        mov     [eax], ebp
1508
        call    dword [eax-4]
1509
        jc      .found
83 diamond 1510
.test_short_name_entry:
3555 Serge 1511
        cmp     byte [edi+11], 0xF
1512
        jz      .test_short_name_cont
1513
        mov     ecx, 11
1514
        push    esi edi
1515
        repz cmpsb
1516
        pop     edi esi
1517
        jz      .short_name_found
83 diamond 1518
.test_short_name_cont:
3555 Serge 1519
        lea     eax, [esp+12+12+8]
1520
        call    dword [eax-8]
1521
        jnc     .test_short_name_entry
1522
        jmp     .found
83 diamond 1523
.short_name_found:
3555 Serge 1524
        pop     ecx edi esi
1525
        call    fat_next_short_name
1526
        jnc     .test_short_name_loop
83 diamond 1527
.disk_full:
3555 Serge 1528
        add     esp, 12+20
1529
        popad
1530
        mov     eax, ERROR_DISK_FULL
1531
        xor     ebx, ebx
1532
        ret
83 diamond 1533
.found:
3555 Serge 1534
        pop     ecx edi esi
83 diamond 1535
; now find space in directory
1536
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
3555 Serge 1537
        mov     al, '~'
1538
        push    ecx edi
1539
        mov     ecx, 8
1540
        repnz scasb
1541
        push    1
1542
        pop     eax     ; 1 entry
1543
        jnz     .notilde
83 diamond 1544
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
3555 Serge 1545
        xor     eax, eax
83 diamond 1546
@@:
3555 Serge 1547
        cmp     byte [esi], 0
1548
        jz      @f
1549
        inc     esi
1550
        inc     eax
1551
        jmp     @b
83 diamond 1552
@@:
3555 Serge 1553
        sub     esi, eax
1554
        add     eax, 12+13
1555
        mov     ecx, 13
1556
        push    edx
1557
        cdq
1558
        div     ecx
1559
        pop     edx
83 diamond 1560
.notilde:
3555 Serge 1561
        push    -1
1562
        push    -1
83 diamond 1563
; find  successive entries in directory
3555 Serge 1564
        xor     ecx, ecx
1565
        push    eax
1566
        lea     eax, [esp+12+8+12+8]
1567
        mov     [eax], ebp
1568
        call    dword [eax-4]
1569
        pop     eax
83 diamond 1570
.scan_dir:
3555 Serge 1571
        cmp     byte [edi], 0
1572
        jz      .free
1573
        cmp     byte [edi], 0xE5
1574
        jz      .free
1575
        xor     ecx, ecx
83 diamond 1576
.scan_cont:
3555 Serge 1577
        push    eax
1578
        lea     eax, [esp+12+8+12+8]
1579
        call    dword [eax-8]
1580
        pop     eax
1581
        jnc     .scan_dir
1582
        push    eax
1583
        lea     eax, [esp+12+8+12+8]
1584
        call    dword [eax+8]           ; extend directory
1585
        pop     eax
1586
        jnc     .scan_dir
1587
        add     esp, 8+8+12+20
1588
        popad
1589
        mov     eax, ERROR_DISK_FULL
1590
        xor     ebx, ebx
1591
        ret
83 diamond 1592
.free:
3555 Serge 1593
        test    ecx, ecx
1594
        jnz     @f
1595
        mov     [esp], edi
1596
        mov     ecx, [esp+8+8+12+8]
1597
        mov     [esp+4], ecx
1598
        xor     ecx, ecx
91 diamond 1599
@@:
3555 Serge 1600
        inc     ecx
1601
        cmp     ecx, eax
1602
        jb      .scan_cont
83 diamond 1603
; found!
3555 Serge 1604
; If creating a directory, allocate one data cluster now and fail immediately
1605
; if this is impossible. This prevents from creating an invalid directory entry
1606
; on a full disk.
1607
; yup, the argument is quite non-intuitive... but what should I do if
1608
; the entire function uses such arguments? BTW, it refers to al from pushad,
1609
; which in turn is filled with 0 in fs_RamdiskRewrite and 1 in fs_RamdiskCreateFolder.
1610
        push    esi ecx
1611
        cmp     byte [esp+24+12+20+28], 0
1612
        jz      .no.preallocate.folder.data
1613
        mov     ecx, 2849
1614
        mov     edi, RAMDISK_FAT
1615
        xor     eax, eax
1616
        repnz scasw
1617
        jz      @f
1618
        add     esp, 24
1619
        jmp     .disk_full
1620
@@:
1621
        mov     [esp+24+12+20+20], edi  ; store the cluster somewhere
1622
.no.preallocate.folder.data:
83 diamond 1623
; calculate name checksum
3555 Serge 1624
        mov     esi, [esp+8+8]
1625
        mov     ecx, 11
1626
        xor     eax, eax
83 diamond 1627
@@:
3555 Serge 1628
        ror     al, 1
1629
        add     al, [esi]
1630
        inc     esi
1631
        loop    @b
1632
        pop     ecx esi
1633
        pop     edi
1634
        pop     dword [esp+8+12+8]
83 diamond 1635
; edi points to last entry in free chunk
3555 Serge 1636
        dec     ecx
1637
        jz      .nolfn
1638
        push    esi
1639
        push    eax
1640
        mov     al, 40h
83 diamond 1641
.writelfn:
3555 Serge 1642
        or      al, cl
1643
        mov     esi, [esp+4]
1644
        push    ecx
1645
        dec     ecx
1646
        imul    ecx, 13
1647
        add     esi, ecx
1648
        stosb
1649
        mov     cl, 5
1650
        call    .read_symbols
1651
        mov     ax, 0xF
1652
        stosw
1653
        mov     al, [esp+4]
1654
        stosb
1655
        mov     cl, 6
1656
        call    .read_symbols
1657
        xor     eax, eax
1658
        stosw
1659
        mov     cl, 2
1660
        call    .read_symbols
1661
        pop     ecx
1662
        lea     eax, [esp+8+8+12+8]
1663
        call    dword [eax+4]   ; next write
1664
        xor     eax, eax
1665
        loop    .writelfn
1666
        pop     eax
1667
        pop     esi
83 diamond 1668
.nolfn:
3555 Serge 1669
        xchg    esi, [esp]
1670
        mov     ecx, 11
1671
        rep movsb
1672
        mov     word [edi], 20h         ; attributes
1673
        sub     edi, 11
1674
        pop     esi ecx
1675
        add     esp, 12
1676
        mov     byte [edi+13], 0        ; tenths of a second at file creation time
1677
        call    get_time_for_file
1678
        mov     [edi+14], ax            ; creation time
1679
        mov     [edi+22], ax            ; last write time
1680
        call    get_date_for_file
1681
        mov     [edi+16], ax            ; creation date
1682
        mov     [edi+24], ax            ; last write date
1683
        mov     [edi+18], ax            ; last access date
1684
        and     word [edi+20], 0        ; high word of cluster
1685
        and     word [edi+26], 0        ; low word of cluster - to be filled
1686
        and     dword [edi+28], 0       ; file size - to be filled
1687
        cmp     byte [esp+20+28], 0
1688
        jz      .doit
321 diamond 1689
; create directory
3555 Serge 1690
        mov     byte [edi+11], 10h         ; attributes: folder
1691
        mov     ecx, 32*2
1692
        mov     edx, edi
1693
        push    edx
1694
        push    ecx
1695
        push    edi
1696
        add     edi, 26         ; edi points to low word of cluster
1697
        push    edi
1698
        mov     edi, [esp+16+20+20]
1699
        jmp     .doit2
83 diamond 1700
.doit:
3555 Serge 1701
        push    edx
1702
        push    ecx
1703
        push    edi
1704
        add     edi, 26         ; edi points to low word of cluster
1705
        push    edi
1706
        jecxz   .done
1707
        mov     ecx, 2849
1708
        mov     edi, RAMDISK_FAT
83 diamond 1709
.write_loop:
1710
; allocate new cluster
3555 Serge 1711
        xor     eax, eax
1712
        repnz scasw
1713
        jnz     .disk_full2
1714
.doit2:
1715
        dec     edi
1716
        dec     edi
465 serge 1717
 
1718
    ;    lea     eax, [edi-(RAMDISK_FAT)]
1719
 
3555 Serge 1720
        mov     eax, edi
1721
        sub     eax, RAMDISK_FAT
465 serge 1722
 
3555 Serge 1723
        shr     eax, 1                  ; eax = cluster
1724
        mov     word [edi], 0xFFF       ; mark as last cluster
1725
        xchg    edi, [esp]
1726
        stosw
1727
        pop     edi
1728
        push    edi
1729
        inc     ecx
83 diamond 1730
; write data
3555 Serge 1731
        cmp     byte [esp+16+20+28], 0
1732
        jnz     .writedir
1733
        shl     eax, 9
1734
        add     eax, RAMDISK+31*512
321 diamond 1735
.writefile:
3555 Serge 1736
        mov     ebx, edx
1737
        xchg    eax, ebx
1738
        push    ecx
1739
        mov     ecx, 512
1740
        cmp     dword [esp+12], ecx
1741
        jae     @f
1742
        mov     ecx, [esp+12]
83 diamond 1743
@@:
3555 Serge 1744
        call    memmove
1745
        add     edx, ecx
1746
        sub     [esp+12], ecx
1747
        pop     ecx
1748
        jnz     .write_loop
83 diamond 1749
.done:
3555 Serge 1750
        mov     ebx, edx
1751
        pop     edi edi ecx edx
1752
        sub     ebx, edx
1753
        mov     [edi+28], ebx
1754
        add     esp, 20
1755
        mov     [esp+16], ebx
1756
        popad
1757
        xor     eax, eax
1758
        ret
83 diamond 1759
.disk_full2:
3555 Serge 1760
        mov     ebx, edx
1761
        pop     edi edi ecx edx
1762
        sub     ebx, edx
1763
        mov     [edi+28], ebx
1764
        add     esp, 20
1765
        mov     [esp+16], ebx
1766
        popad
1767
        push    ERROR_DISK_FULL
1768
        pop     eax
1769
        ret
321 diamond 1770
.writedir:
3555 Serge 1771
        mov     edi, eax
1772
        shl     edi, 9
1773
        add     edi, RAMDISK+31*512
1774
        mov     esi, edx
1775
        mov     ecx, 32/4
1776
        push    ecx
1777
        rep movsd
1778
        mov     dword [edi-32], '.   '
1779
        mov     dword [edi-32+4], '    '
1780
        mov     dword [edi-32+8], '    '
1781
        mov     byte [edi-32+11], 10h
1782
        mov     word [edi-32+26], ax
1783
        mov     esi, edx
1784
        pop     ecx
1785
        rep movsd
1786
        mov     dword [edi-32], '..  '
1787
        mov     dword [edi-32+4], '    '
1788
        mov     dword [edi-32+8], '    '
1789
        mov     byte [edi-32+11], 10h
1790
        mov     eax, [esp+16+8]
1791
        mov     word [edi-32+26], ax
1792
        xor     eax, eax
1793
        mov     ecx, (512-32*2)/4
1794
        rep stosd
1795
        pop     edi edi ecx edx
1796
        add     esp, 20
1797
        popad
1798
        xor     eax, eax
1799
        xor     ebx, ebx
1800
        ret
83 diamond 1801
 
1802
.read_symbol:
3555 Serge 1803
        or      ax, -1
1804
        test    esi, esi
1805
        jz      .retFFFF
1806
        lodsb
1807
        test    al, al
1808
        jnz     ansi2uni_char
1809
        xor     eax, eax
1810
        xor     esi, esi
83 diamond 1811
.retFFFF:
3555 Serge 1812
        ret
83 diamond 1813
 
1814
.read_symbols:
3555 Serge 1815
        call    .read_symbol
1816
        stosw
1817
        loop    .read_symbols
1818
        ret
83 diamond 1819
 
131 diamond 1820
;----------------------------------------------------------------
1821
;
1822
;  fs_RamdiskWrite - LFN variant for writing to sys floppy
1823
;
1824
;  esi  points to filename
1825
;  ebx  pointer to 64-bit number = first wanted byte, 0+
1826
;       may be ebx=0 - start from first byte
1827
;  ecx  number of bytes to write, 0+
1828
;  edx  mem location to data
1829
;
1830
;  ret ebx = bytes written (maybe 0)
1831
;      eax = 0 ok write or other = errormsg
1832
;
1833
;--------------------------------------------------------------
1834
@@:
3555 Serge 1835
        push    ERROR_ACCESS_DENIED
131 diamond 1836
fs_RamdiskWrite.ret0:
3555 Serge 1837
        pop     eax
1838
        xor     ebx, ebx
1839
        ret
131 diamond 1840
 
1841
fs_RamdiskWrite:
3555 Serge 1842
        cmp     byte [esi], 0
1843
        jz      @b
1844
        pushad
1845
        call    rd_find_lfn
1846
        jnc     .found
1847
        popad
1848
        push    ERROR_FILE_NOT_FOUND
1849
        jmp     .ret0
131 diamond 1850
.found:
1851
; must not be directory
3555 Serge 1852
        test    byte [edi+11], 10h
1853
        jz      @f
1854
        popad
1855
        push    ERROR_ACCESS_DENIED
1856
        jmp     .ret0
131 diamond 1857
@@:
1858
; FAT does not support files larger than 4GB
3555 Serge 1859
        test    ebx, ebx
1860
        jz      .l1
1861
        cmp     dword [ebx+4], 0
1862
        jz      @f
131 diamond 1863
.eof:
3555 Serge 1864
        popad
1865
        push    ERROR_END_OF_FILE
1866
        jmp     .ret0
131 diamond 1867
@@:
3555 Serge 1868
        mov     ebx, [ebx]
131 diamond 1869
.l1:
1870
; now edi points to direntry, ebx=start byte to write,
1871
; ecx=number of bytes to write, edx=data pointer
3555 Serge 1872
        call    fat_update_datetime
131 diamond 1873
 
1874
; extend file if needed
3555 Serge 1875
        add     ecx, ebx
1876
        jc      .eof    ; FAT does not support files larger than 4GB
1877
        push    0       ; return value=0
1878
        cmp     ecx, [edi+28]
1879
        jbe     .length_ok
1880
        cmp     ecx, ebx
1881
        jz      .length_ok
1882
        call    ramdisk_extend_file
1883
        jnc     .length_ok
131 diamond 1884
; ramdisk_extend_file can return two error codes: FAT table error or disk full.
1885
; First case is fatal error, in second case we may write some data
3555 Serge 1886
        mov     [esp], eax
1887
        cmp     al, ERROR_DISK_FULL
1888
        jz      .disk_full
1889
        pop     eax
1890
        mov     [esp+28], eax
1891
        popad
1892
        xor     ebx, ebx
1893
        ret
131 diamond 1894
.disk_full:
1895
; correct number of bytes to write
3555 Serge 1896
        mov     ecx, [edi+28]
1897
        cmp     ecx, ebx
1898
        ja      .length_ok
131 diamond 1899
.ret:
3555 Serge 1900
        pop     eax
1901
        mov     [esp+28], eax   ; eax=return value
1902
        sub     edx, [esp+20]
1903
        mov     [esp+16], edx   ; ebx=number of written bytes
1904
        popad
1905
        ret
131 diamond 1906
.length_ok:
1907
; now ebx=start pos, ecx=end pos, both lie inside file
3555 Serge 1908
        sub     ecx, ebx
1909
        jz      .ret
1910
        movzx   edi, word [edi+26]      ; starting cluster
131 diamond 1911
.write_loop:
3555 Serge 1912
        sub     ebx, 0x200
1913
        jae     .next_cluster
1914
        push    ecx
1915
        neg     ebx
1916
        cmp     ecx, ebx
1917
        jbe     @f
1918
        mov     ecx, ebx
131 diamond 1919
@@:
3555 Serge 1920
        mov     eax, edi
1921
        shl     eax, 9
1922
        add     eax, RAMDISK+31*512+0x200
1923
        sub     eax, ebx
1924
        mov     ebx, eax
1925
        mov     eax, edx
1926
        call    memmove
1927
        xor     ebx, ebx
1928
        add     edx, ecx
1929
        sub     [esp], ecx
1930
        pop     ecx
1931
        jz      .ret
131 diamond 1932
.next_cluster:
3555 Serge 1933
        movzx   edi, word [edi*2+RAMDISK_FAT]
1934
        jmp     .write_loop
131 diamond 1935
 
1936
ramdisk_extend_file.zero_size:
3555 Serge 1937
        xor     eax, eax
1938
        jmp     ramdisk_extend_file.start_extend
131 diamond 1939
 
1940
; extends file on ramdisk to given size, new data area is filled by 0
1941
; in: edi->direntry, ecx=new size
133 diamond 1942
; out: CF=0 => OK, eax=0
131 diamond 1943
;      CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL)
1944
ramdisk_extend_file:
3555 Serge 1945
        push    ecx
131 diamond 1946
; find the last cluster of file
3555 Serge 1947
        movzx   eax, word [edi+26]      ; first cluster
1948
        mov     ecx, [edi+28]
1949
        jecxz   .zero_size
131 diamond 1950
@@:
3555 Serge 1951
        sub     ecx, 0x200
1952
        jbe     @f
1953
        mov     eax, [eax*2+RAMDISK_FAT]
1954
        and     eax, 0xFFF
1955
        jz      .fat_err
1956
        cmp     eax, 0xFF8
1957
        jb      @b
131 diamond 1958
.fat_err:
3555 Serge 1959
        pop     ecx
1960
        push    ERROR_FAT_TABLE
1961
        pop     eax
1962
        stc
1963
        ret
131 diamond 1964
@@:
3555 Serge 1965
        push    eax
1966
        mov     eax, [eax*2+RAMDISK_FAT]
1967
        and     eax, 0xFFF
1968
        cmp     eax, 0xFF8
1969
        pop     eax
1970
        jb      .fat_err
131 diamond 1971
; set length to full number of sectors and make sure that last sector is zero-padded
3555 Serge 1972
        sub     [edi+28], ecx
1973
        push    eax edi
1974
        mov     edi, eax
1975
        shl     edi, 9
1976
        lea     edi, [edi+RAMDISK+31*512+0x200+ecx]
1977
        neg     ecx
1978
        xor     eax, eax
1979
        rep stosb
1980
        pop     edi eax
131 diamond 1981
.start_extend:
3555 Serge 1982
        pop     ecx
131 diamond 1983
; now do extend
3555 Serge 1984
        push    edx esi
1985
        mov     esi, RAMDISK_FAT+2*2       ; start scan from cluster 2
1986
        mov     edx, 2847               ; number of clusters to scan
131 diamond 1987
.extend_loop:
3555 Serge 1988
        cmp     [edi+28], ecx
1989
        jae     .extend_done
131 diamond 1990
; add new sector
3555 Serge 1991
        push    ecx
1992
        mov     ecx, edx
1993
        push    edi
1994
        mov     edi, esi
1995
        jecxz   .disk_full
1996
        push    eax
1997
        xor     eax, eax
1998
        repnz scasw
1999
        pop     eax
2000
        jnz     .disk_full
2001
        mov     word [edi-2], 0xFFF
2002
        mov     esi, edi
2003
        mov     edx, ecx
2004
        sub     edi, RAMDISK_FAT
2005
        shr     edi, 1
2006
        dec     edi     ; now edi=new cluster
2007
        test    eax, eax
2008
        jz      .first_cluster
2009
        mov     [RAMDISK_FAT+eax*2], di
2010
        jmp     @f
131 diamond 2011
.first_cluster:
3555 Serge 2012
        pop     eax     ; eax->direntry
2013
        push    eax
2014
        mov     [eax+26], di
131 diamond 2015
@@:
3555 Serge 2016
        push    edi
2017
        shl     edi, 9
2018
        add     edi, RAMDISK+31*512
2019
        xor     eax, eax
2020
        mov     ecx, 512/4
2021
        rep stosd
2022
        pop     eax     ; eax=new cluster
2023
        pop     edi     ; edi->direntry
2024
        pop     ecx     ; ecx=required size
2025
        add     dword [edi+28], 0x200
2026
        jmp     .extend_loop
131 diamond 2027
.extend_done:
3555 Serge 2028
        mov     [edi+28], ecx
2029
        pop     esi edx
2030
        xor     eax, eax        ; CF=0
2031
        ret
131 diamond 2032
.disk_full:
3555 Serge 2033
        pop     edi ecx
2034
        pop     esi edx
2035
        stc
2036
        push    ERROR_DISK_FULL
2037
        pop     eax
2038
        ret
131 diamond 2039
 
133 diamond 2040
fat_update_datetime:
3555 Serge 2041
        call    get_time_for_file
2042
        mov     [edi+22], ax            ; last write time
2043
        call    get_date_for_file
2044
        mov     [edi+24], ax            ; last write date
2045
        mov     [edi+18], ax            ; last access date
2046
        ret
133 diamond 2047
 
2048
;----------------------------------------------------------------
2049
;
2050
;  fs_RamdiskSetFileEnd - set end of file on ramdisk
2051
;
2052
;  esi  points to filename
2053
;  ebx  points to 64-bit number = new file size
2054
;  ecx  ignored (reserved)
2055
;  edx  ignored (reserved)
2056
;
2057
;  ret eax = 0 ok or other = errormsg
2058
;
2059
;--------------------------------------------------------------
2060
fs_RamdiskSetFileEnd:
3555 Serge 2061
        cmp     byte [esi], 0
2062
        jnz     @f
133 diamond 2063
.access_denied:
3555 Serge 2064
        push    ERROR_ACCESS_DENIED
2065
        jmp     .ret
133 diamond 2066
@@:
3555 Serge 2067
        push    edi
2068
        call    rd_find_lfn
2069
        jnc     @f
2070
        pop     edi
2071
        push    ERROR_FILE_NOT_FOUND
133 diamond 2072
.ret:
3555 Serge 2073
        pop     eax
2074
        ret
133 diamond 2075
@@:
2076
; must not be directory
3555 Serge 2077
        test    byte [edi+11], 10h
2078
        jz      @f
2079
        pop     edi
2080
        jmp     .access_denied
133 diamond 2081
@@:
2082
; file size must not exceed 4Gb
3555 Serge 2083
        cmp     dword [ebx+4], 0
2084
        jz      @f
2085
        pop     edi
2086
        push    ERROR_END_OF_FILE
2087
        jmp     .ret
133 diamond 2088
@@:
2089
; set file modification date/time to current
3555 Serge 2090
        call    fat_update_datetime
2091
        mov     eax, [ebx]
2092
        cmp     eax, [edi+28]
2093
        jb      .truncate
2094
        ja      .expand
2095
        pop     edi
2096
        xor     eax, eax
2097
        ret
133 diamond 2098
.expand:
3555 Serge 2099
        push    ecx
2100
        mov     ecx, eax
2101
        call    ramdisk_extend_file
2102
        pop     ecx
2103
        pop     edi
2104
        ret
133 diamond 2105
.truncate:
3555 Serge 2106
        mov     [edi+28], eax
2107
        push    ecx
2108
        movzx   ecx, word [edi+26]
2109
        test    eax, eax
2110
        jz      .zero_size
133 diamond 2111
; find new last sector
2112
@@:
3555 Serge 2113
        sub     eax, 0x200
2114
        jbe     @f
2115
        movzx   ecx, word [RAMDISK_FAT+ecx*2]
2116
        jmp     @b
133 diamond 2117
@@:
2118
; zero data at the end of last sector
3555 Serge 2119
        push    ecx
2120
        mov     edi, ecx
2121
        shl     edi, 9
2122
        lea     edi, [edi+RAMDISK+31*512+eax+0x200]
2123
        mov     ecx, eax
2124
        neg     ecx
2125
        xor     eax, eax
2126
        rep stosb
2127
        pop     ecx
133 diamond 2128
; terminate FAT chain
3555 Serge 2129
        lea     ecx, [RAMDISK_FAT+ecx+ecx]
2130
        push    dword [ecx]
2131
        mov     word [ecx], 0xFFF
2132
        pop     ecx
2133
        and     ecx, 0xFFF
2134
        jmp     .delete
133 diamond 2135
.zero_size:
3555 Serge 2136
        and     word [edi+26], 0
133 diamond 2137
.delete:
2138
; delete FAT chain starting with ecx
2139
; mark all clusters as free
3555 Serge 2140
        cmp     ecx, 0xFF8
2141
        jae     .deleted
2142
        lea     ecx, [RAMDISK_FAT+ecx+ecx]
2143
        push    dword [ecx]
2144
        and     word [ecx], 0
2145
        pop     ecx
2146
        and     ecx, 0xFFF
2147
        jmp     .delete
133 diamond 2148
.deleted:
3555 Serge 2149
        pop     ecx
2150
        pop     edi
2151
        xor     eax, eax
2152
        ret
133 diamond 2153
 
86 diamond 2154
fs_RamdiskGetFileInfo:
3555 Serge 2155
        cmp     byte [esi], 0
2156
        jnz     @f
2157
        mov     eax, 2  ; unsupported
2158
        ret
86 diamond 2159
@@:
3555 Serge 2160
        push    edi
2161
        call    rd_find_lfn
86 diamond 2162
fs_GetFileInfo_finish:
3555 Serge 2163
        jnc     @f
2164
        pop     edi
2165
        mov     eax, ERROR_FILE_NOT_FOUND
2166
        ret
86 diamond 2167
@@:
3555 Serge 2168
        push    esi ebp
2169
        xor     ebp, ebp
2170
        mov     esi, edx
2171
        and     dword [esi+4], 0
2172
        call    fat_entry_to_bdfe2
2173
        pop     ebp esi
2174
        pop     edi
2175
        xor     eax, eax
2176
        ret
86 diamond 2177
 
2178
fs_RamdiskSetFileInfo:
3555 Serge 2179
        cmp     byte [esi], 0
2180
        jnz     @f
2181
        mov     eax, 2  ; unsupported
2182
        ret
86 diamond 2183
@@:
3555 Serge 2184
        push    edi
2185
        call    rd_find_lfn
2186
        jnc     @f
2187
        pop     edi
2188
        mov     eax, ERROR_FILE_NOT_FOUND
2189
        ret
86 diamond 2190
@@:
3555 Serge 2191
        call    bdfe_to_fat_entry
2192
        pop     edi
2193
        xor     eax, eax
2194
        ret
86 diamond 2195
 
91 diamond 2196
;----------------------------------------------------------------
2197
;
171 diamond 2198
;  fs_RamdiskDelete - delete file or empty folder from ramdisk
2199
;
2200
;  esi  points to filename
2201
;
2202
;  ret  eax = 0 ok or other = errormsg
2203
;
2204
;--------------------------------------------------------------
2205
fs_RamdiskDelete:
3555 Serge 2206
        cmp     byte [esi], 0
2207
        jnz     @f
171 diamond 2208
; cannot delete root!
2209
.access_denied:
3555 Serge 2210
        push    ERROR_ACCESS_DENIED
171 diamond 2211
.pop_ret:
3555 Serge 2212
        pop     eax
2213
        ret
171 diamond 2214
@@:
3555 Serge 2215
        and     [rd_prev_sector], 0
2216
        and     [rd_prev_prev_sector], 0
2217
        push    edi
2218
        call    rd_find_lfn
2219
        jnc     .found
2220
        pop     edi
2221
        push    ERROR_FILE_NOT_FOUND
2222
        jmp     .pop_ret
171 diamond 2223
.found:
3555 Serge 2224
        cmp     dword [edi], '.   '
2225
        jz      .access_denied2
2226
        cmp     dword [edi], '..  '
2227
        jz      .access_denied2
2228
        test    byte [edi+11], 10h
2229
        jz      .dodel
171 diamond 2230
; we can delete only empty folders!
3555 Serge 2231
        movzx   eax, word [edi+26]
2232
        push    ebx
2233
        mov     ebx, eax
2234
        shl     ebx, 9
2235
        add     ebx, RAMDISK + 31*0x200 + 2*0x20
171 diamond 2236
.checkempty:
3555 Serge 2237
        cmp     byte [ebx], 0
2238
        jz      .empty
2239
        cmp     byte [ebx], 0xE5
2240
        jnz     .notempty
2241
        add     ebx, 0x20
2242
        test    ebx, 0x1FF
2243
        jnz     .checkempty
2244
        movzx   eax, word [RAMDISK_FAT + eax*2]
2245
        test    eax, eax
2246
        jz      .empty
2247
        mov     ebx, eax
2248
        shl     ebx, 9
2249
        add     ebx, RAMDISK + 31*0x200
2250
        jmp     .checkempty
171 diamond 2251
.notempty:
3555 Serge 2252
        pop     ebx
171 diamond 2253
.access_denied2:
3555 Serge 2254
        pop     edi
2255
        jmp     .access_denied
171 diamond 2256
.empty:
3555 Serge 2257
        pop     ebx
171 diamond 2258
.dodel:
3555 Serge 2259
        movzx   eax, word [edi+26]
171 diamond 2260
; delete folder entry
3555 Serge 2261
        mov     byte [edi], 0xE5
171 diamond 2262
; delete LFN (if present)
2263
.lfndel:
3555 Serge 2264
        test    edi, 0x1FF
2265
        jnz     @f
2266
        cmp     [rd_prev_sector], 0
2267
        jz      @f
2268
        cmp     [rd_prev_sector], -1
2269
        jz      .lfndone
2270
        mov     edi, [rd_prev_sector]
2271
        push    [rd_prev_prev_sector]
2272
        pop     [rd_prev_sector]
2273
        or      [rd_prev_prev_sector], -1
2274
        shl     edi, 9
2275
        add     edi, RAMDISK + 31*0x200 + 0x200
171 diamond 2276
@@:
3555 Serge 2277
        sub     edi, 0x20
2278
        cmp     byte [edi], 0xE5
2279
        jz      .lfndone
2280
        cmp     byte [edi+11], 0xF
2281
        jnz     .lfndone
2282
        mov     byte [edi], 0xE5
2283
        jmp     .lfndel
171 diamond 2284
.lfndone:
2285
; delete FAT chain
3500 Serge 2286
        cmp     eax, 2
2287
        jb      .done
2288
        cmp     eax, 0xFF8
2289
        jae     .done
3555 Serge 2290
        lea     eax, [RAMDISK_FAT + eax*2]
2291
        push    dword [eax]
2292
        and     word [eax], 0
2293
        pop     eax
2294
        and     eax, 0xFFF
2295
        jmp     .lfndone
171 diamond 2296
.done:
3555 Serge 2297
        pop     edi
2298
        xor     eax, eax
2299
        ret
171 diamond 2300
 
78 diamond 2301
; \end{diamond}