Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
425 victor 1
$Revision: 527 $
431 serge 2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
527 diamond 3
;;                                                              ;;
431 serge 4
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
5
;; Distributed under terms of the GNU General Public License    ;;
6
;;                                                              ;;
527 diamond 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
527 diamond 1447
        cmp     ebx, ecx
1448
        jb      @f
1449
        pop     ebx
1450
        push    ecx
1451
@@:
83 diamond 1452
        cmp     edi, ecx
1453
        jbe     .skip
1454
@@:
1455
        dec     edi
527 diamond 1456
        mov     al, [edi]
83 diamond 1457
        dec     ebx
1458
        mov     [ebx], al
527 diamond 1459
        mov     byte [edi], ' '
83 diamond 1460
        cmp     edi, ecx
1461
        ja      @b
1462
.skip:
1463
        mov     bh, 3
1464
        jmp     @f
1465
.firstdot:
1466
        cmp     bl, 8
1467
        jz      .space
1468
        push    edi
1469
        or      bh, 2
1470
@@:
1471
        mov     edi, ecx
1472
        mov     bl, 3
1473
        jmp     .loop
1474
.done:
1475
        test    bh, 2
1476
        jz      @f
1477
        pop     edi
1478
@@:
1479
        lea     edi, [ecx-8]
1480
        test    bh, 1
1481
        jz      @f
1482
        call    fat_next_short_name
1483
@@:
1484
        popad
1485
        ret
1486
 
1487
;----------------------------------------------------------------
1488
;
321 diamond 1489
;  fs_RamdiskRewrite - LFN variant for writing ramdisk
1490
;  fs_RamdiskCreateFolder - create folder on ramdisk
83 diamond 1491
;
321 diamond 1492
;  esi  points to file/folder name
83 diamond 1493
;  ebx  ignored (reserved)
321 diamond 1494
;  ecx  number of bytes to write, 0+ (ignored for folders)
1495
;  edx  mem location to data (ignored for folders)
83 diamond 1496
;
1497
;  ret ebx = number of written bytes
1498
;      eax = 0 ok read or other = errormsg
1499
;
1500
;--------------------------------------------------------------
1501
@@:
1502
        mov     eax, ERROR_ACCESS_DENIED
1503
        xor     ebx, ebx
1504
        ret
1505
 
321 diamond 1506
fs_RamdiskCreateFolder:
1507
        mov     al, 1           ; create folder
1508
        jmp     fs_RamdiskRewrite.common
1509
 
83 diamond 1510
fs_RamdiskRewrite:
321 diamond 1511
        xor     eax, eax        ; create file
1512
.common:
83 diamond 1513
        cmp     byte [esi], 0
1514
        jz      @b
91 diamond 1515
        pushad
521 diamond 1516
        xor     edi, edi
83 diamond 1517
        push    esi
521 diamond 1518
        test    ebp, ebp
1519
        jz      @f
1520
        mov     esi, ebp
83 diamond 1521
@@:
1522
        lodsb
1523
        test    al, al
1524
        jz      @f
1525
        cmp     al, '/'
1526
        jnz     @b
521 diamond 1527
        lea     edi, [esi-1]
91 diamond 1528
        jmp     @b
1529
@@:
83 diamond 1530
        pop     esi
521 diamond 1531
        test    edi, edi
1532
        jnz     .noroot
91 diamond 1533
        test    ebp, ebp
521 diamond 1534
        jnz     .hasebp
91 diamond 1535
        push    ramdisk_root_extend_dir
1536
        push    ramdisk_root_next_write
521 diamond 1537
        push    edi
91 diamond 1538
        push    ramdisk_root_first
1539
        push    ramdisk_root_next
1540
        jmp     .common1
521 diamond 1541
.hasebp:
1542
        mov     eax, ERROR_ACCESS_DENIED
1543
        cmp     byte [ebp], 0
1544
        jz      .ret1
1545
        push    ebp
1546
        xor     ebp, ebp
1547
        call    rd_find_lfn
1548
        pop     esi
1549
        jc      .notfound0
1550
        jmp     .common0
91 diamond 1551
.noroot:
335 diamond 1552
        mov     eax, ERROR_ACCESS_DENIED
521 diamond 1553
        cmp     byte [edi+1], 0
335 diamond 1554
        jz      .ret1
91 diamond 1555
; check existence
521 diamond 1556
        mov     byte [edi], 0
1557
        push    edi
91 diamond 1558
        call    rd_find_lfn
521 diamond 1559
        pop     esi
1560
        mov     byte [esi], '/'
91 diamond 1561
        jnc     @f
521 diamond 1562
.notfound0:
91 diamond 1563
        mov     eax, ERROR_FILE_NOT_FOUND
1564
.ret1:
1565
        mov     [esp+28], eax
1566
        popad
83 diamond 1567
        xor     ebx, ebx
1568
        ret
1569
@@:
521 diamond 1570
        inc     esi
1571
.common0:
91 diamond 1572
        test    byte [edi+11], 0x10     ; must be directory
1573
        mov     eax, ERROR_ACCESS_DENIED
1574
        jz      .ret1
1575
        movzx   ebp, word [edi+26]      ; ebp=cluster
1576
        mov     eax, ERROR_FAT_TABLE
1577
        cmp     ebp, 2
1578
        jb      .ret1
1579
        cmp     ebp, 2849
1580
        jae     .ret1
1581
        push    ramdisk_notroot_extend_dir
1582
        push    ramdisk_notroot_next_write
1583
        push    ebp
1584
        push    ramdisk_notroot_first
1585
        push    ramdisk_notroot_next
1586
.common1:
1587
        call    fat_find_lfn
83 diamond 1588
        jc      .notfound
321 diamond 1589
; found
91 diamond 1590
        test    byte [edi+11], 10h
321 diamond 1591
        jz      .exists_file
1592
; found directory; if we are creating directory, return OK,
1593
;                  if we are creating file, say "access denied"
1594
        add     esp, 20
1595
        popad
1596
        test    al, al
1597
        mov     eax, ERROR_ACCESS_DENIED
91 diamond 1598
        jz      @f
321 diamond 1599
        mov     al, 0
1600
@@:
1601
        xor     ebx, ebx
1602
        ret
1603
.exists_file:
1604
; found file; if we are creating directory, return "access denied",
1605
;             if we are creating file, delete existing file and continue
1606
        cmp     byte [esp+20+28], 0
1607
        jz      @f
91 diamond 1608
        add     esp, 20
1609
        popad
1610
        mov     eax, ERROR_ACCESS_DENIED
1611
        xor     ebx, ebx
1612
        ret
1613
@@:
1614
; delete FAT chain
83 diamond 1615
        push    edi
1616
        xor     eax, eax
1617
        mov     dword [edi+28], eax     ; zero size
1618
        xchg    ax, word [edi+26]       ; start cluster
1619
        test    eax, eax
1620
        jz      .done1
1621
@@:
1622
        cmp     eax, 0xFF8
1623
        jae     .done1
321 diamond 1624
        lea     edi, [RAMDISK_FAT + eax*2] ; position in FAT
83 diamond 1625
        xor     eax, eax
1626
        xchg    ax, [edi]
1627
        jmp     @b
1628
.done1:
1629
        pop     edi
1630
        call    get_time_for_file
1631
        mov     [edi+22], ax
1632
        call    get_date_for_file
1633
        mov     [edi+24], ax
1634
        mov     [edi+18], ax
1635
        or      byte [edi+11], 20h      ; set 'archive' attribute
1636
        jmp     .doit
1637
.notfound:
1638
; file is not found; generate short name
1639
        call    fat_name_is_legal
1640
        jc      @f
91 diamond 1641
        add     esp, 20
1642
        popad
1643
        mov     eax, ERROR_FILE_NOT_FOUND
1644
        xor     ebx, ebx
1645
        ret
83 diamond 1646
@@:
1647
        sub     esp, 12
1648
        mov     edi, esp
1649
        call    fat_gen_short_name
1650
.test_short_name_loop:
91 diamond 1651
        push    esi edi ecx
1652
        mov     esi, edi
1653
        lea     eax, [esp+12+12+8]
1654
        mov     [eax], ebp
1655
        call    dword [eax-4]
1656
        jc      .found
83 diamond 1657
.test_short_name_entry:
91 diamond 1658
        cmp     byte [edi+11], 0xF
83 diamond 1659
        jz      .test_short_name_cont
1660
        mov     ecx, 11
1661
        push    esi edi
1662
        repz    cmpsb
1663
        pop     edi esi
1664
        jz      .short_name_found
1665
.test_short_name_cont:
91 diamond 1666
        lea     eax, [esp+12+12+8]
1667
        call    dword [eax-8]
1668
        jnc     .test_short_name_entry
83 diamond 1669
        jmp     .found
1670
.short_name_found:
91 diamond 1671
        pop     ecx edi esi
83 diamond 1672
        call    fat_next_short_name
1673
        jnc     .test_short_name_loop
1674
.disk_full:
91 diamond 1675
        add     esp, 12+20
1676
        popad
83 diamond 1677
        mov     eax, ERROR_DISK_FULL
1678
        xor     ebx, ebx
1679
        ret
1680
.found:
91 diamond 1681
        pop     ecx edi esi
83 diamond 1682
; now find space in directory
1683
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
1684
        mov     al, '~'
1685
        push    ecx edi
1686
        mov     ecx, 8
1687
        repnz   scasb
1688
        push    1
1689
        pop     eax     ; 1 entry
1690
        jnz     .notilde
1691
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
1692
        xor     eax, eax
1693
@@:
1694
        cmp     byte [esi], 0
1695
        jz      @f
1696
        inc     esi
1697
        inc     eax
1698
        jmp     @b
1699
@@:
1700
        sub     esi, eax
1701
        add     eax, 12+13
1702
        mov     ecx, 13
1703
        push    edx
1704
        cdq
1705
        div     ecx
1706
        pop     edx
1707
.notilde:
91 diamond 1708
        push    -1
1709
        push    -1
83 diamond 1710
; find  successive entries in directory
1711
        xor     ecx, ecx
91 diamond 1712
        push    eax
1713
        lea     eax, [esp+12+8+12+8]
1714
        mov     [eax], ebp
1715
        call    dword [eax-4]
1716
        pop     eax
83 diamond 1717
.scan_dir:
1718
        cmp     byte [edi], 0
1719
        jz      .free
1720
        cmp     byte [edi], 0xE5
1721
        jz      .free
1722
        xor     ecx, ecx
1723
.scan_cont:
91 diamond 1724
        push    eax
1725
        lea     eax, [esp+12+8+12+8]
1726
        call    dword [eax-8]
1727
        pop     eax
1728
        jnc     .scan_dir
1729
        push    eax
1730
        lea     eax, [esp+12+8+12+8]
1731
        call    dword [eax+8]           ; extend directory
1732
        pop     eax
1733
        jnc     .scan_dir
1734
        add     esp, 8+8+12+20
1735
        popad
1736
        mov     eax, ERROR_DISK_FULL
1737
        xor     ebx, ebx
1738
        ret
83 diamond 1739
.free:
91 diamond 1740
        test    ecx, ecx
1741
        jnz     @f
1742
        mov     [esp], edi
1743
        mov     ecx, [esp+8+8+12+8]
1744
        mov     [esp+4], ecx
1745
        xor     ecx, ecx
1746
@@:
83 diamond 1747
        inc     ecx
1748
        cmp     ecx, eax
1749
        jb      .scan_cont
1750
; found!
1751
; calculate name checksum
1752
        push    esi ecx
91 diamond 1753
        mov     esi, [esp+8+8]
83 diamond 1754
        mov     ecx, 11
1755
        xor     eax, eax
1756
@@:
1757
        ror     al, 1
1758
        add     al, [esi]
1759
        inc     esi
1760
        loop    @b
1761
        pop     ecx esi
91 diamond 1762
        pop     edi
1763
        pop     dword [esp+8+12+8]
83 diamond 1764
; edi points to last entry in free chunk
1765
        dec     ecx
1766
        jz      .nolfn
1767
        push    esi
91 diamond 1768
        push    eax
1769
        mov     al, 40h
83 diamond 1770
.writelfn:
91 diamond 1771
        or      al, cl
1772
        mov     esi, [esp+4]
1773
        push    ecx
1774
        dec     ecx
1775
        imul    ecx, 13
1776
        add     esi, ecx
83 diamond 1777
        stosb
1778
        mov     cl, 5
1779
        call    .read_symbols
1780
        mov     ax, 0xF
1781
        stosw
91 diamond 1782
        mov     al, [esp+4]
83 diamond 1783
        stosb
1784
        mov     cl, 6
1785
        call    .read_symbols
1786
        xor     eax, eax
1787
        stosw
1788
        mov     cl, 2
1789
        call    .read_symbols
91 diamond 1790
        pop     ecx
1791
        lea     eax, [esp+8+8+12+8]
1792
        call    dword [eax+4]   ; next write
1793
        xor     eax, eax
83 diamond 1794
        loop    .writelfn
91 diamond 1795
        pop     eax
83 diamond 1796
        pop     esi
1797
.nolfn:
1798
        xchg    esi, [esp]
1799
        mov     ecx, 11
1800
        rep     movsb
1801
        mov     word [edi], 20h         ; attributes
1802
        sub     edi, 11
1803
        pop     esi ecx
1804
        add     esp, 12
1805
        mov     byte [edi+13], 0        ; tenths of a second at file creation time
1806
        call    get_time_for_file
1807
        mov     [edi+14], ax            ; creation time
1808
        mov     [edi+22], ax            ; last write time
1809
        call    get_date_for_file
1810
        mov     [edi+16], ax            ; creation date
1811
        mov     [edi+24], ax            ; last write date
1812
        mov     [edi+18], ax            ; last access date
1813
        and     word [edi+20], 0        ; high word of cluster
1814
        and     word [edi+26], 0        ; low word of cluster - to be filled
1815
        and     dword [edi+28], 0       ; file size - to be filled
321 diamond 1816
        cmp     byte [esp+20+28], 0
1817
        jz      .doit
1818
; create directory
1819
        mov     byte [edi+11], 10h         ; attributes: folder
1820
        mov     ecx, 32*2
1821
        mov     edx, edi
83 diamond 1822
.doit:
91 diamond 1823
        push    edx
83 diamond 1824
        push    ecx
1825
        push    edi
1826
        add     edi, 26         ; edi points to low word of cluster
1827
        push    edi
1828
        jecxz   .done
1829
        mov     ecx, 2849
321 diamond 1830
        mov     edi, RAMDISK_FAT
83 diamond 1831
.write_loop:
1832
; allocate new cluster
1833
        xor     eax, eax
1834
        repnz   scasw
1835
        jnz     .disk_full2
1836
        dec     edi
1837
        dec     edi
465 serge 1838
 
1839
    ;    lea     eax, [edi-(RAMDISK_FAT)]
1840
 
1841
        mov eax, edi
1842
        sub eax, RAMDISK_FAT
1843
 
83 diamond 1844
        shr     eax, 1                  ; eax = cluster
1845
        mov     word [edi], 0xFFF       ; mark as last cluster
1846
        xchg    edi, [esp]
1847
        stosw
1848
        pop     edi
1849
        push    edi
1850
        inc     ecx
1851
; write data
321 diamond 1852
        cmp     byte [esp+16+20+28], 0
1853
        jnz     .writedir
83 diamond 1854
        shl     eax, 9
321 diamond 1855
        add     eax, RAMDISK+31*512
1856
.writefile:
83 diamond 1857
        mov     ebx, edx
1858
        xchg    eax, ebx
1859
        push    ecx
1860
        mov     ecx, 512
1861
        cmp     dword [esp+12], ecx
1862
        jae     @f
1863
        mov     ecx, [esp+12]
1864
@@:
1865
        call    memmove
1866
        add     edx, ecx
1867
        sub     [esp+12], ecx
1868
        pop     ecx
1869
        jnz     .write_loop
1870
.done:
1871
        mov     ebx, edx
91 diamond 1872
        pop     edi edi ecx edx
83 diamond 1873
        sub     ebx, edx
1874
        mov     [edi+28], ebx
91 diamond 1875
        add     esp, 20
131 diamond 1876
        mov     [esp+16], ebx
91 diamond 1877
        popad
83 diamond 1878
        xor     eax, eax
1879
        ret
1880
.disk_full2:
1881
        mov     ebx, edx
91 diamond 1882
        pop     edi edi ecx edx
83 diamond 1883
        sub     ebx, edx
1884
        mov     [edi+28], ebx
91 diamond 1885
        add     esp, 20
131 diamond 1886
        mov     [esp+16], ebx
91 diamond 1887
        popad
83 diamond 1888
        push    ERROR_DISK_FULL
1889
        pop     eax
1890
        ret
321 diamond 1891
.writedir:
1892
        mov     edi, eax
1893
        shl     edi, 9
1894
        add     edi, RAMDISK+31*512
1895
        mov     esi, edx
1896
        mov     ecx, 32/4
1897
        push    ecx
1898
        rep     movsd
1899
        mov     dword [edi-32], '.   '
1900
        mov     dword [edi-32+4], '    '
1901
        mov     dword [edi-32+8], '    '
1902
        mov     byte [edi-32+11], 10h
1903
        mov     word [edi-32+26], ax
1904
        mov     esi, edx
1905
        pop     ecx
1906
        rep     movsd
1907
        mov     dword [edi-32], '..  '
1908
        mov     dword [edi-32+4], '    '
1909
        mov     dword [edi-32+8], '    '
1910
        mov     byte [edi-32+11], 10h
1911
        mov     eax, [esp+16+8]
1912
        mov     word [edi-32+26], ax
437 diamond 1913
        xor     eax, eax
1914
        mov     ecx, (512-32*2)/4
1915
        rep     stosd
321 diamond 1916
        pop     edi edi ecx edx
1917
        add     esp, 20
1918
        popad
1919
        xor     eax, eax
1920
        xor     ebx, ebx
1921
        ret
83 diamond 1922
 
1923
.read_symbol:
1924
        or      ax, -1
1925
        test    esi, esi
1926
        jz      .retFFFF
1927
        lodsb
1928
        test    al, al
1929
        jnz     ansi2uni_char
1930
        xor     eax, eax
1931
        xor     esi, esi
1932
.retFFFF:
1933
        ret
1934
 
1935
.read_symbols:
1936
        call    .read_symbol
1937
        stosw
1938
        loop    .read_symbols
1939
        ret
1940
 
131 diamond 1941
;----------------------------------------------------------------
1942
;
1943
;  fs_RamdiskWrite - LFN variant for writing to sys floppy
1944
;
1945
;  esi  points to filename
1946
;  ebx  pointer to 64-bit number = first wanted byte, 0+
1947
;       may be ebx=0 - start from first byte
1948
;  ecx  number of bytes to write, 0+
1949
;  edx  mem location to data
1950
;
1951
;  ret ebx = bytes written (maybe 0)
1952
;      eax = 0 ok write or other = errormsg
1953
;
1954
;--------------------------------------------------------------
1955
@@:
1956
        push    ERROR_ACCESS_DENIED
1957
fs_RamdiskWrite.ret0:
1958
        pop     eax
1959
        xor     ebx, ebx
1960
        ret
1961
 
1962
fs_RamdiskWrite:
1963
        cmp     byte [esi], 0
1964
        jz      @b
1965
        pushad
1966
        call    rd_find_lfn
1967
        jnc     .found
1968
        popad
1969
        push    ERROR_FILE_NOT_FOUND
1970
        jmp     .ret0
1971
.found:
1972
; must not be directory
1973
        test    byte [edi+11], 10h
1974
        jz      @f
1975
        popad
1976
        push    ERROR_ACCESS_DENIED
1977
        jmp     .ret0
1978
@@:
1979
; FAT does not support files larger than 4GB
1980
        test    ebx, ebx
1981
        jz      .l1
1982
        cmp     dword [ebx+4], 0
1983
        jz      @f
1984
.eof:
1985
        popad
1986
        push    ERROR_END_OF_FILE
1987
        jmp     .ret0
1988
@@:
1989
        mov     ebx, [ebx]
1990
.l1:
1991
; now edi points to direntry, ebx=start byte to write,
1992
; ecx=number of bytes to write, edx=data pointer
133 diamond 1993
        call    fat_update_datetime
131 diamond 1994
 
1995
; extend file if needed
1996
        add     ecx, ebx
1997
        jc      .eof    ; FAT does not support files larger than 4GB
1998
        push    0       ; return value=0
1999
        cmp     ecx, [edi+28]
2000
        jbe     .length_ok
2001
        cmp     ecx, ebx
2002
        jz      .length_ok
2003
        call    ramdisk_extend_file
2004
        jnc     .length_ok
2005
; ramdisk_extend_file can return two error codes: FAT table error or disk full.
2006
; First case is fatal error, in second case we may write some data
2007
        mov     [esp], eax
2008
        cmp     al, ERROR_DISK_FULL
2009
        jz      .disk_full
2010
        pop     eax
2011
        mov     [esp+28], eax
2012
        popad
2013
        xor     ebx, ebx
2014
        ret
2015
.disk_full:
2016
; correct number of bytes to write
2017
        mov     ecx, [edi+28]
2018
        cmp     ecx, ebx
2019
        ja      .length_ok
2020
.ret:
2021
        pop     eax
2022
        mov     [esp+28], eax   ; eax=return value
2023
        sub     edx, [esp+20]
2024
        mov     [esp+16], edx   ; ebx=number of written bytes
2025
        popad
2026
        ret
2027
.length_ok:
2028
; now ebx=start pos, ecx=end pos, both lie inside file
2029
        sub     ecx, ebx
2030
        jz      .ret
2031
        movzx   edi, word [edi+26]      ; starting cluster
2032
.write_loop:
2033
        sub     ebx, 0x200
2034
        jae     .next_cluster
2035
        push    ecx
2036
        neg     ebx
2037
        cmp     ecx, ebx
2038
        jbe     @f
2039
        mov     ecx, ebx
2040
@@:
2041
        mov     eax, edi
2042
        shl     eax, 9
381 serge 2043
        add     eax, RAMDISK+31*512+0x200
131 diamond 2044
        sub     eax, ebx
2045
        mov     ebx, eax
2046
        mov     eax, edx
2047
        call    memmove
2048
        xor     ebx, ebx
2049
        add     edx, ecx
2050
        sub     [esp], ecx
2051
        pop     ecx
2052
        jz      .ret
2053
.next_cluster:
381 serge 2054
        movzx   edi, word [edi*2+RAMDISK_FAT]
131 diamond 2055
        jmp     .write_loop
2056
 
2057
ramdisk_extend_file.zero_size:
2058
        xor     eax, eax
2059
        jmp     ramdisk_extend_file.start_extend
2060
 
2061
; extends file on ramdisk to given size, new data area is filled by 0
2062
; in: edi->direntry, ecx=new size
133 diamond 2063
; out: CF=0 => OK, eax=0
131 diamond 2064
;      CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL)
2065
ramdisk_extend_file:
2066
        push    ecx
2067
; find the last cluster of file
2068
        movzx   eax, word [edi+26]      ; first cluster
2069
        mov     ecx, [edi+28]
2070
        jecxz   .zero_size
2071
@@:
2072
        sub     ecx, 0x200
2073
        jbe     @f
381 serge 2074
        mov     eax, [eax*2+RAMDISK_FAT]
131 diamond 2075
        and     eax, 0xFFF
2076
        jz      .fat_err
2077
        cmp     eax, 0xFF8
2078
        jb      @b
2079
.fat_err:
2080
        pop     ecx
2081
        push    ERROR_FAT_TABLE
2082
        pop     eax
2083
        stc
2084
        ret
2085
@@:
2086
        push    eax
381 serge 2087
        mov     eax, [eax*2+RAMDISK_FAT]
131 diamond 2088
        and     eax, 0xFFF
2089
        cmp     eax, 0xFF8
2090
        pop     eax
2091
        jb      .fat_err
2092
; set length to full number of sectors and make sure that last sector is zero-padded
2093
        sub     [edi+28], ecx
2094
        push    eax edi
2095
        mov     edi, eax
2096
        shl     edi, 9
381 serge 2097
        lea     edi, [edi+RAMDISK+31*512+0x200+ecx]
131 diamond 2098
        neg     ecx
2099
        xor     eax, eax
2100
        rep     stosb
2101
        pop     edi eax
2102
.start_extend:
2103
        pop     ecx
2104
; now do extend
2105
        push    edx esi
381 serge 2106
        mov     esi, RAMDISK_FAT+2*2       ; start scan from cluster 2
131 diamond 2107
        mov     edx, 2847               ; number of clusters to scan
2108
.extend_loop:
2109
        cmp     [edi+28], ecx
2110
        jae     .extend_done
2111
; add new sector
2112
        push    ecx
2113
        mov     ecx, edx
2114
        push    edi
2115
        mov     edi, esi
2116
        jecxz   .disk_full
2117
        push    eax
2118
        xor     eax, eax
2119
        repnz   scasw
2120
        pop     eax
2121
        jnz     .disk_full
2122
        mov     word [edi-2], 0xFFF
2123
        mov     esi, edi
2124
        mov     edx, ecx
381 serge 2125
        sub     edi, RAMDISK_FAT
131 diamond 2126
        shr     edi, 1
2127
        dec     edi     ; now edi=new cluster
2128
        test    eax, eax
2129
        jz      .first_cluster
381 serge 2130
        mov     [RAMDISK_FAT+eax*2], di
131 diamond 2131
        jmp     @f
2132
.first_cluster:
2133
        pop     eax     ; eax->direntry
2134
        push    eax
2135
        mov     [eax+26], di
2136
@@:
2137
        push    edi
2138
        shl     edi, 9
381 serge 2139
        add     edi, RAMDISK+31*512
131 diamond 2140
        xor     eax, eax
2141
        mov     ecx, 512/4
2142
        rep     stosd
2143
        pop     eax     ; eax=new cluster
2144
        pop     edi     ; edi->direntry
2145
        pop     ecx     ; ecx=required size
2146
        add     dword [edi+28], 0x200
2147
        jmp     .extend_loop
2148
.extend_done:
2149
        mov     [edi+28], ecx
2150
        pop     esi edx
133 diamond 2151
        xor     eax, eax        ; CF=0
131 diamond 2152
        ret
2153
.disk_full:
2154
        pop     edi ecx
2155
        pop     esi edx
2156
        stc
2157
        push    ERROR_DISK_FULL
2158
        pop     eax
2159
        ret
2160
 
133 diamond 2161
fat_update_datetime:
2162
        call    get_time_for_file
2163
        mov     [edi+22], ax            ; last write time
2164
        call    get_date_for_file
2165
        mov     [edi+24], ax            ; last write date
2166
        mov     [edi+18], ax            ; last access date
2167
        ret
2168
 
2169
;----------------------------------------------------------------
2170
;
2171
;  fs_RamdiskSetFileEnd - set end of file on ramdisk
2172
;
2173
;  esi  points to filename
2174
;  ebx  points to 64-bit number = new file size
2175
;  ecx  ignored (reserved)
2176
;  edx  ignored (reserved)
2177
;
2178
;  ret eax = 0 ok or other = errormsg
2179
;
2180
;--------------------------------------------------------------
2181
fs_RamdiskSetFileEnd:
2182
        cmp     byte [esi], 0
2183
        jnz     @f
2184
.access_denied:
2185
        push    ERROR_ACCESS_DENIED
2186
        jmp     .ret
2187
@@:
2188
        push    edi
2189
        call    rd_find_lfn
2190
        jnc     @f
2191
        pop     edi
2192
        push    ERROR_FILE_NOT_FOUND
2193
.ret:
2194
        pop     eax
2195
        ret
2196
@@:
2197
; must not be directory
2198
        test    byte [edi+11], 10h
2199
        jz      @f
2200
        pop     edi
2201
        jmp     .access_denied
2202
@@:
2203
; file size must not exceed 4Gb
2204
        cmp     dword [ebx+4], 0
2205
        jz      @f
2206
        pop     edi
2207
        push    ERROR_END_OF_FILE
2208
        jmp     .ret
2209
@@:
2210
; set file modification date/time to current
2211
        call    fat_update_datetime
2212
        mov     eax, [ebx]
2213
        cmp     eax, [edi+28]
2214
        jb      .truncate
2215
        ja      .expand
2216
        pop     edi
2217
        xor     eax, eax
2218
        ret
2219
.expand:
2220
        push    ecx
2221
        mov     ecx, eax
2222
        call    ramdisk_extend_file
2223
        pop     ecx
2224
        pop     edi
2225
        ret
2226
.truncate:
2227
        mov     [edi+28], eax
2228
        push    ecx
2229
        movzx   ecx, word [edi+26]
2230
        test    eax, eax
2231
        jz      .zero_size
2232
; find new last sector
2233
@@:
2234
        sub     eax, 0x200
2235
        jbe     @f
381 serge 2236
        movzx   ecx, word [RAMDISK_FAT+ecx*2]
133 diamond 2237
        jmp     @b
2238
@@:
2239
; zero data at the end of last sector
2240
        push    ecx
2241
        mov     edi, ecx
2242
        shl     edi, 9
381 serge 2243
        lea     edi, [edi+RAMDISK+31*512+eax+0x200]
133 diamond 2244
        mov     ecx, eax
2245
        neg     ecx
2246
        xor     eax, eax
2247
        rep     stosb
2248
        pop     ecx
2249
; terminate FAT chain
381 serge 2250
        lea     ecx, [RAMDISK_FAT+ecx+ecx]
133 diamond 2251
        push    dword [ecx]
2252
        mov     word [ecx], 0xFFF
2253
        pop     ecx
2254
        and     ecx, 0xFFF
2255
        jmp     .delete
2256
.zero_size:
2257
        and     word [edi+26], 0
2258
.delete:
2259
; delete FAT chain starting with ecx
2260
; mark all clusters as free
2261
        cmp     ecx, 0xFF8
2262
        jae     .deleted
381 serge 2263
        lea     ecx, [RAMDISK_FAT+ecx+ecx]
133 diamond 2264
        push    dword [ecx]
2265
        and     word [ecx], 0
2266
        pop     ecx
2267
        and     ecx, 0xFFF
2268
        jmp     .delete
2269
.deleted:
2270
        pop     ecx
2271
        pop     edi
2272
        xor     eax, eax
2273
        ret
2274
 
86 diamond 2275
fs_RamdiskGetFileInfo:
2276
        cmp     byte [esi], 0
2277
        jnz     @f
2278
        mov     eax, 2  ; unsupported
2279
        ret
2280
@@:
2281
        push    edi
2282
        call    rd_find_lfn
2283
fs_GetFileInfo_finish:
2284
        jnc     @f
2285
        pop     edi
2286
        mov     eax, ERROR_FILE_NOT_FOUND
2287
        ret
2288
@@:
2289
        push    esi ebp
2290
        xor     ebp, ebp
2291
        mov     esi, edx
2292
        and     dword [esi+4], 0
2293
        call    fat_entry_to_bdfe2
2294
        pop     ebp esi
2295
        pop     edi
2296
        xor     eax, eax
2297
        ret
2298
 
2299
fs_RamdiskSetFileInfo:
2300
        cmp     byte [esi], 0
2301
        jnz     @f
2302
        mov     eax, 2  ; unsupported
2303
        ret
2304
@@:
2305
        push    edi
2306
        call    rd_find_lfn
2307
        jnc     @f
2308
        pop     edi
2309
        mov     eax, ERROR_FILE_NOT_FOUND
2310
        ret
2311
@@:
2312
        call    bdfe_to_fat_entry
2313
        pop     edi
2314
        xor     eax, eax
2315
        ret
2316
 
91 diamond 2317
;----------------------------------------------------------------
2318
;
171 diamond 2319
;  fs_RamdiskDelete - delete file or empty folder from ramdisk
2320
;
2321
;  esi  points to filename
2322
;
2323
;  ret  eax = 0 ok or other = errormsg
2324
;
2325
;--------------------------------------------------------------
2326
fs_RamdiskDelete:
2327
        cmp     byte [esi], 0
2328
        jnz     @f
2329
; cannot delete root!
2330
.access_denied:
2331
        push    ERROR_ACCESS_DENIED
2332
.pop_ret:
2333
        pop     eax
2334
        ret
2335
@@:
2336
        and     [rd_prev_sector], 0
2337
        and     [rd_prev_prev_sector], 0
2338
        push    edi
2339
        call    rd_find_lfn
2340
        jnc     .found
2341
        pop     edi
2342
        push    ERROR_FILE_NOT_FOUND
2343
        jmp     .pop_ret
2344
.found:
2345
        cmp     dword [edi], '.   '
2346
        jz      .access_denied2
2347
        cmp     dword [edi], '..  '
2348
        jz      .access_denied2
2349
        test    byte [edi+11], 10h
2350
        jz      .dodel
2351
; we can delete only empty folders!
2352
        movzx   eax, word [edi+26]
2353
        push    ebx
2354
        mov     ebx, eax
2355
        shl     ebx, 9
2356
        add     ebx, RAMDISK + 31*0x200 + 2*0x20
2357
.checkempty:
2358
        cmp     byte [ebx], 0
2359
        jz      .empty
2360
        cmp     byte [ebx], 0xE5
2361
        jnz     .notempty
2362
        add     ebx, 0x20
2363
        test    ebx, 0x1FF
2364
        jnz     .checkempty
2365
        movzx   eax, word [RAMDISK_FAT + eax*2]
2366
        test    eax, eax
2367
        jz      .empty
2368
        mov     ebx, eax
2369
        shl     ebx, 9
2370
        add     ebx, RAMDISK + 31*0x200
2371
        jmp     .checkempty
2372
.notempty:
2373
        pop     ebx
2374
.access_denied2:
2375
        pop     edi
2376
        jmp     .access_denied
2377
.empty:
2378
        pop     ebx
2379
.dodel:
2380
        movzx   eax, word [edi+26]
2381
; delete folder entry
2382
        mov     byte [edi], 0xE5
2383
; delete LFN (if present)
2384
.lfndel:
2385
        test    edi, 0x1FF
2386
        jnz     @f
2387
        cmp     [rd_prev_sector], 0
2388
        jz      @f
2389
        cmp     [rd_prev_sector], -1
2390
        jz      .lfndone
2391
        mov     edi, [rd_prev_sector]
2392
        push    [rd_prev_prev_sector]
2393
        pop     [rd_prev_sector]
2394
        or      [rd_prev_prev_sector], -1
2395
        shl     edi, 9
2396
        add     edi, RAMDISK + 31*0x200 + 0x200
2397
@@:
2398
        sub     edi, 0x20
2399
        cmp     byte [edi], 0xE5
2400
        jz      .lfndone
2401
        cmp     byte [edi+11], 0xF
2402
        jnz     .lfndone
2403
        mov     byte [edi], 0xE5
2404
        jmp     .lfndel
2405
.lfndone:
2406
; delete FAT chain
2407
        test    eax, eax
2408
        jz      .done
2409
        lea     eax, [RAMDISK_FAT + eax*2]
2410
        push    dword [eax]
2411
        and     word [eax], 0
2412
        pop     eax
2413
        and     eax, 0xFFF
2414
        jmp     .lfndone
2415
.done:
2416
        pop     edi
2417
        xor     eax, eax
2418
        ret
2419
 
78 diamond 2420
; \end{diamond}