Subversion Repositories Kolibri OS

Rev

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

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