Subversion Repositories Kolibri OS

Rev

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