Subversion Repositories Kolibri OS

Rev

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