Subversion Repositories Kolibri OS

Rev

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

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