Subversion Repositories Kolibri OS

Rev

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

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