Subversion Repositories Kolibri OS

Rev

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

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