Subversion Repositories Kolibri OS

Rev

Rev 83 | Rev 88 | 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
 
15
   mov  esi,0x100000+512
16
   mov  edi,0x280000
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
 
41
   cmp  edi,0x280000+2856*2   ;2849 clusters
42
   jnz  fcnew
43
 
44
   popad
45
   ret
46
 
47
 
48
restorefatchain:   ; restore fat chain
49
 
50
   pushad
51
 
52
   mov  esi,0x280000
53
   mov  edi,0x100000+512
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
 
69
   cmp  edi,0x100000+512+4278     ;4274 bytes - all used FAT
70
   jb   fcnew2
71
 
72
   mov  esi,0x100000+512           ; duplicate fat chain
73
   mov  edi,0x100000+512+0x1200
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
 
91
        mov  edi,0x280000 ;start of FAT
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
105
 
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
196
        mov    edx,ecx
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
205
        mov    esi,0x100000+512*19
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
249
        add    eax,0x100000             ;image base
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:
71 diamond 263
        movzx  eax,word [edi*2+0x280000]	; 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
311
 
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
329
        add    edi,0x280000
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
 
342
 
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
 
378
        mov    edi,0x100000+512*18+512  ;Point at directory
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
410
        mov    edi,0x280000            ;pointer to first cluster
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
426
        add    ebx,0x100000
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
 
461
        mov    edi,0x100000+512*18+512  ;Point at directory
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
470
        cmp    edi,0x100000+512*33
471
        jb     rd_newsearch
472
        mov    eax,5      ;if file not found - eax=5
473
        xor    ebx,ebx
474
        dec    ebx    ;ebx=0xffffffff and zf=0
475
     rd_ff:
476
        ret
477
 
478
  rd_getfileinfo:
479
     ;get date, time, size or attributes of file
480
     ;IN: eax - pointer to file, ebx - type of function: 12-get filesize, 13-get fileattr, 14-get filedate
481
     ;ecx - filelengh 0=root
482
     ;OUT: eax=0 - Ok or 5 - file not found ebx - date/time, size or attributes
483
        test   ecx,ecx
484
        jnz    no_getfinfo_root
485
        mov    eax,5      ;if root - fnf
486
        xor    ebx,ebx
487
        dec    ebx
488
        ret
489
    no_getfinfo_root:     ;if not root
490
        sub    esp,32
491
        call   expand_filename
492
        call   rd_findfile
493
        je     fifoundi
494
        add    esp,32      ;if file not found
495
        ret
496
    fifoundi:
497
        cmp    ebx,13
498
        jne    no_rd_attr
499
        movzx ebx,byte [edi]    ;get attributes
500
        jmp    rd_getfileinfo_end
501
     no_rd_attr:
502
        cmp    ebx,14
503
        jne    no_rd_date
504
        mov    ebx,dword [edi+11] ;get date/time
505
        jmp    rd_getfileinfo_end
506
     no_rd_date:
507
        mov    ebx,dword [edi+17] ;get size
508
     rd_getfileinfo_end:
509
        xor    eax,eax
510
        add    esp,32
71 diamond 511
        ret
512
 
513
; \begin{diamond}
514
 
515
uni2ansi_str:
516
; convert UNICODE zero-terminated string to ASCII-string (codepage 866)
517
; in: esi->source, edi->buffer (may be esi=edi)
518
; destroys: eax,esi,edi
83 diamond 519
        lodsw
520
        test    ax, ax
521
        jz      .done
522
        cmp     ax, 0x80
523
        jb      .ascii
524
        cmp     ax, 0x401
525
        jz      .yo1
526
        cmp     ax, 0x451
527
        jz      .yo2
528
        cmp     ax, 0x410
529
        jb      .unk
530
        cmp     ax, 0x440
531
        jb      .rus1
532
        cmp     ax, 0x450
533
        jb      .rus2
71 diamond 534
.unk:
83 diamond 535
        mov     al, '_'
536
        jmp     .doit
71 diamond 537
.yo1:
83 diamond 538
        mov     al, 'ð'
539
        jmp     .doit
71 diamond 540
.yo2:
83 diamond 541
        mov     al, 'ñ'
542
        jmp     .doit
71 diamond 543
.rus1:
544
; 0x410-0x43F -> 0x80-0xAF
83 diamond 545
        add     al, 0x70
546
        jmp     .doit
71 diamond 547
.rus2:
75 diamond 548
; 0x440-0x44F -> 0xE0-0xEF
83 diamond 549
        add     al, 0xA0
71 diamond 550
.ascii:
551
.doit:
83 diamond 552
        stosb
553
        jmp     uni2ansi_str
71 diamond 554
.done:
83 diamond 555
        mov     byte [edi], 0
556
        ret
71 diamond 557
 
75 diamond 558
ansi2uni_char:
559
; convert ANSI character in al to UNICODE character in ax, using cp866 encoding
560
        mov     ah, 0
561
; 0x00-0x7F - trivial map
562
        cmp     al, 0x80
563
        jb      .ret
564
; 0x80-0xAF -> 0x410-0x43F
565
        cmp     al, 0xB0
566
        jae     @f
567
        add     ax, 0x410-0x80
568
.ret:
569
        ret
570
@@:
571
; 0xE0-0xEF -> 0x440-0x44F
572
        cmp     al, 0xE0
573
        jb      .unk
574
        cmp     al, 0xF0
575
        jae     @f
576
        add     ax, 0x440-0xE0
577
        ret
578
; 0xF0 -> 0x401
579
; 0xF1 -> 0x451
580
@@:
581
        cmp     al, 'ð'
582
        jz      .yo1
583
        cmp     al, 'ñ'
584
        jz      .yo2
585
.unk:
586
        mov     al, '_'         ; ah=0
587
        ret
588
.yo1:
589
        mov     ax, 0x401
590
        ret
591
.yo2:
592
        mov     ax, 0x451
593
        ret
594
 
71 diamond 595
char_toupper:
596
; convert character to uppercase, using cp866 encoding
597
; in: al=symbol
598
; out: al=converted symbol
83 diamond 599
        cmp     al, 'a'
600
        jb      .ret
601
        cmp     al, 'z'
602
        jbe     .az
603
        cmp     al, ' '
604
        jb      .ret
605
        cmp     al, 'à'
606
        jb      .rus1
607
        cmp     al, 'ï'
608
        ja      .ret
71 diamond 609
; 0xE0-0xEF -> 0x90-0x9F
83 diamond 610
        sub     al, 'à'-''
71 diamond 611
.ret:
83 diamond 612
        ret
71 diamond 613
.rus1:
614
; 0xA0-0xAF -> 0x80-0x8F
615
.az:
83 diamond 616
        and     al, not 0x20
617
        ret
71 diamond 618
 
619
fat_get_name:
620
; in: edi->FAT entry
621
; out: CF=1 - no valid entry
622
; else CF=0 and ebp->ASCIIZ-name
623
; (maximum length of filename is 255 (wide) symbols without trailing 0,
624
;  but implementation requires buffer 261 words)
625
; destroys eax
83 diamond 626
        cmp     byte [edi], 0
627
        jz      .no
628
        cmp     byte [edi], 0xE5
629
        jnz     @f
71 diamond 630
.no:
83 diamond 631
        stc
632
        ret
71 diamond 633
@@:
83 diamond 634
        cmp     byte [edi+11], 0xF
635
        jz      .longname
636
        push    ecx
637
        mov     ecx, 8
638
        push    edi ebp ecx
78 diamond 639
        test    byte [ebp-4], 1
75 diamond 640
        jnz     .unicode_short
71 diamond 641
@@:
83 diamond 642
        mov     al, [edi]
643
        inc     edi
644
        mov     [ebp], al
645
        inc     ebp
646
        loop    @b
647
        pop     ecx
71 diamond 648
@@:
83 diamond 649
        cmp     byte [ebp-1], ' '
650
        jnz     @f
651
        dec     ebp
652
        loop    @b
71 diamond 653
@@:
83 diamond 654
        mov     byte [ebp], '.'
655
        inc     ebp
656
        mov     ecx, 3
657
        push    ecx
71 diamond 658
@@:
83 diamond 659
        mov     al, [edi]
660
        inc     edi
661
        mov     [ebp], al
662
        inc     ebp
663
        loop    @b
664
        pop     ecx
71 diamond 665
@@:
83 diamond 666
        cmp     byte [ebp-1], ' '
667
        jnz     @f
668
        dec     ebp
669
        loop    @b
670
        dec     ebp
71 diamond 671
@@:
83 diamond 672
        and     byte [ebp], 0	; CF=0
673
        pop     ebp edi ecx
674
        ret
75 diamond 675
.unicode_short:
676
@@:
677
        mov     al, [edi]
678
        inc     edi
679
        call    ansi2uni_char
680
        mov     [ebp], ax
681
        inc     ebp
682
        inc     ebp
683
        loop    @b
684
        pop     ecx
685
@@:
83 diamond 686
        cmp     word [ebp-2], ' '
687
        jnz     @f
688
        dec     ebp
689
        dec     ebp
690
        loop    @b
75 diamond 691
@@:
83 diamond 692
        mov     word [ebp], '.'
693
        inc     ebp
694
        inc     ebp
695
        mov     ecx, 3
696
        push    ecx
75 diamond 697
@@:
83 diamond 698
        mov     al, [edi]
699
        inc     edi
700
        call    ansi2uni_char
701
        mov     [ebp], ax
75 diamond 702
        inc     ebp
703
        inc     ebp
704
        loop    @b
705
        pop     ecx
706
@@:
83 diamond 707
        cmp     word [ebp-2], ' '
708
        jnz     @f
709
        dec     ebp
710
        dec     ebp
711
        loop    @b
712
        dec     ebp
713
        dec     ebp
75 diamond 714
@@:
83 diamond 715
        and     word [ebp], 0	; CF=0
716
        pop     ebp edi ecx
717
        ret
71 diamond 718
.longname:
719
; LFN
83 diamond 720
        mov     al, byte [edi]
721
        and     eax, 0x3F
722
        dec     eax
723
        cmp     al, 20
724
        jae     .no     ; ignore invalid entries
725
        mov     word [ebp+260*2], 0     ; force null-terminating for orphans
726
        imul    eax, 13*2
727
        add     ebp, eax
728
        test    byte [edi], 0x40
729
        jz      @f
730
        mov     word [ebp+13*2], 0
71 diamond 731
@@:
83 diamond 732
        push    eax
71 diamond 733
; now copy name from edi to ebp ...
83 diamond 734
        mov     eax, [edi+1]
735
        mov     [ebp], eax      ; symbols 1,2
736
        mov     eax, [edi+5]
737
        mov     [ebp+4], eax	; 3,4
738
        mov     eax, [edi+9]
739
        mov     [ebp+8], ax	; 5
740
        mov     eax, [edi+14]
741
        mov     [ebp+10], eax	; 6,7
742
        mov     eax, [edi+18]
743
        mov     [ebp+14], eax	; 8,9
744
        mov     eax, [edi+22]
745
        mov     [ebp+18], eax	; 10,11
746
        mov     eax, [edi+28]
747
        mov     [ebp+22], eax	; 12,13
71 diamond 748
; ... done
83 diamond 749
        pop     eax
750
        sub     ebp, eax
751
        test    eax, eax
752
        jz      @f
71 diamond 753
; if this is not first entry, more processing required
83 diamond 754
        stc
755
        ret
71 diamond 756
@@:
757
; if this is first entry:
78 diamond 758
        test    byte [ebp-4], 1
75 diamond 759
        jnz     .ret
71 diamond 760
; buffer at ebp contains UNICODE name, convert it to ANSI
83 diamond 761
        push    esi edi
762
        mov     esi, ebp
763
        mov     edi, ebp
764
        call    uni2ansi_str
765
        pop     edi esi
75 diamond 766
.ret:
83 diamond 767
        clc
768
        ret
71 diamond 769
 
770
fat_compare_name:
771
; compares ASCIIZ-names, case-insensitive (cp866 encoding)
772
; in: esi->name, ebp->name
773
; out: if names match: ZF=1 and esi->next component of name
774
;      else: ZF=0, esi is not changed
775
; destroys eax
83 diamond 776
        push    ebp esi
71 diamond 777
.loop:
83 diamond 778
        mov     al, [ebp]
779
        inc     ebp
780
        call    char_toupper
781
        push    eax
782
        lodsb
783
        call    char_toupper
784
        cmp     al, [esp]
785
        jnz     .done
786
        pop     eax
787
        test    al, al
788
        jnz     .loop
789
        dec     esi
790
        pop     eax
791
        pop     ebp
792
        xor     eax, eax	; set ZF flag
793
        ret
71 diamond 794
.done:
83 diamond 795
        cmp     al, '/'
796
        jnz     @f
797
        cmp     byte [esp], 0
798
        jnz     @f
799
        mov     [esp+4], esi
71 diamond 800
@@:
83 diamond 801
        pop     eax
802
        pop     esi ebp
803
        ret
71 diamond 804
 
75 diamond 805
fat_time_to_bdfe:
806
; in: eax=FAT time
807
; out: eax=BDFE time
83 diamond 808
        push    ecx edx
809
        mov     ecx, eax
810
        mov     edx, eax
811
        shr     eax, 11
812
        shl     eax, 16	; hours
813
        and     edx, 0x1F
814
        add     edx, edx
815
        mov     al, dl	; seconds
816
        shr     ecx, 5
817
        and     ecx, 0x3F
818
        mov     ah, cl	; minutes
819
        pop     edx ecx
820
        ret
75 diamond 821
 
822
fat_date_to_bdfe:
83 diamond 823
        push    ecx edx
824
        mov     ecx, eax
825
        mov     edx, eax
826
        shr     eax, 9
827
        add     ax, 1980
828
        shl     eax, 16	; year
829
        and     edx, 0x1F
830
        mov     al, dl	; day
831
        shr     ecx, 5
832
        and     ecx, 0xF
833
        mov     ah, cl	; month
834
        pop     edx ecx
835
        ret
75 diamond 836
 
86 diamond 837
bdfe_to_fat_time:
838
        push    edx
839
        mov     edx, eax
840
        shr     eax, 16
841
        and     dh, 0x3F
842
        shl     eax, 6
843
        or      al, dh
844
        shr     dl, 1
845
        and     dl, 0x1F
846
        shl     eax, 5
847
        or      al, dl
848
        pop     edx
849
        ret
850
 
851
bdfe_to_fat_date:
852
        push    edx
853
        mov     edx, eax
854
        shr     eax, 16
855
        sub     ax, 1980
856
        and     dh, 0xF
857
        shl     eax, 4
858
        or      al, dh
859
        and     dl, 0x1F
860
        shl     eax, 5
861
        or      al, dl
862
        pop     edx
863
        ret
864
 
75 diamond 865
fat_entry_to_bdfe:
866
; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
867
; destroys eax
86 diamond 868
        mov     eax, [ebp-4]
869
        mov     [esi+4], eax	; ASCII/UNICODE name
870
fat_entry_to_bdfe2:
75 diamond 871
        movzx   eax, byte [edi+11]
872
        mov     [esi], eax	; attributes
873
        movzx   eax, word [edi+14]
874
        call    fat_time_to_bdfe
875
        mov     [esi+8], eax	; creation time
876
        movzx   eax, word [edi+16]
877
        call    fat_date_to_bdfe
878
        mov     [esi+12], eax	; creation date
879
        and     dword [esi+16], 0	; last access time is not supported on FAT
880
        movzx   eax, word [edi+18]
881
        call    fat_date_to_bdfe
882
        mov     [esi+20], eax	; last access date
883
        movzx   eax, word [edi+22]
884
        call    fat_time_to_bdfe
885
        mov     [esi+24], eax	; last write time
886
        movzx   eax, word [edi+24]
887
        call    fat_date_to_bdfe
888
        mov     [esi+28], eax	; last write date
889
        mov     eax, [edi+28]
890
        mov     [esi+32], eax	; file size (low dword)
891
        xor     eax, eax
892
        mov     [esi+36], eax	; file size (high dword)
86 diamond 893
        test    ebp, ebp
894
        jz      .ret
75 diamond 895
        push    ecx edi
896
        lea     edi, [esi+40]
897
        mov     esi, ebp
78 diamond 898
        test    byte [esi-4], 1
899
        jz      .ansi
900
        mov     ecx, 260/2
75 diamond 901
        rep     movsd
78 diamond 902
        mov     [edi-2], ax
903
@@:
75 diamond 904
        mov     esi, edi
905
        pop     edi ecx
86 diamond 906
.ret:
75 diamond 907
        ret
78 diamond 908
.ansi:
909
        mov     ecx, 264/4
910
        rep     movsd
911
        mov     [edi-1], al
912
        jmp     @b
75 diamond 913
 
86 diamond 914
bdfe_to_fat_entry:
915
; convert BDFE at edx to FAT entry at edi
916
; destroys eax
917
; attributes byte
918
        test    byte [edi+11], 8        ; volume label?
919
        jnz     @f
920
        mov     al, [edx]
921
        and     al, 0x27
922
        and     byte [edi+11], 0x10
923
        or      byte [edi+11], al
924
@@:
925
        mov     eax, [edx+8]
926
        call    bdfe_to_fat_time
927
        mov     [edi+14], ax            ; creation time
928
        mov     eax, [edx+12]
929
        call    bdfe_to_fat_date
930
        mov     [edi+16], ax            ; creation date
931
        mov     eax, [edx+20]
932
        call    bdfe_to_fat_date
933
        mov     [edi+18], ax            ; last access date
934
        mov     eax, [edx+24]
935
        call    bdfe_to_fat_time
936
        mov     [edi+22], ax            ; last write time
937
        mov     eax, [edx+28]
938
        call    bdfe_to_fat_date
939
        mov     [edi+24], ax            ; last write date
940
        ret
941
 
942
ramdisk_root_first:
943
        mov     edi, 0x100000+512*19
944
        clc
945
        ret
946
ramdisk_root_next:
947
        add     edi, 0x20
948
        cmp     edi, 0x100000+512*33
949
        cmc
950
        ret
951
 
71 diamond 952
rd_find_lfn:
953
; in: esi->name
954
; out: CF=1 - file not found
955
;      else CF=0 and edi->direntry
86 diamond 956
        push    esi edi
957
        push    ramdisk_root_first
958
        push    ramdisk_root_next
959
        call    fat_find_lfn
960
        jc      .notfound
961
        cmp     byte [esi], 0
962
        jnz     .notfound
963
        add     esp, 12
964
        pop     esi
965
        ret     ; CF=0
71 diamond 966
.notfound:
86 diamond 967
        add     esp, 8
968
        pop     edi esi
78 diamond 969
        stc
970
        ret
71 diamond 971
 
972
;----------------------------------------------------------------
973
;
974
;  fs_RamdiskRead - LFN variant for reading sys floppy
975
;
976
;  esi  points to filename
977
;  ebx  pointer to 64-bit number = first wanted byte, 0+
978
;       may be ebx=0 - start from first byte
979
;  ecx  number of bytes to read, 0+
980
;  edx  mem location to return data
981
;
77 diamond 982
;  ret ebx = bytes read or 0xffffffff file not found
71 diamond 983
;      eax = 0 ok read or other = errormsg
984
;
985
;--------------------------------------------------------------
986
fs_RamdiskRead:
75 diamond 987
        cmp     byte [esi], 0
988
        jnz     @f
989
        or      ebx, -1
990
        mov     eax, 10         ; access denied
991
        ret
71 diamond 992
@@:
75 diamond 993
        push    edi
994
        call    rd_find_lfn
995
        jnc     .found
996
        pop     edi
997
        or      ebx, -1
998
        mov     eax, 5          ; file not found
999
        ret
71 diamond 1000
.found:
75 diamond 1001
        test    ebx, ebx
1002
        jz      .l1
1003
        cmp     dword [ebx+4], 0
1004
        jz      @f
77 diamond 1005
        xor     ebx, ebx
71 diamond 1006
.reteof:
75 diamond 1007
        mov     eax, 6          ; EOF
1008
        pop     edi
1009
        ret
71 diamond 1010
@@:
75 diamond 1011
        mov     ebx, [ebx]
71 diamond 1012
.l1:
77 diamond 1013
        push    ecx edx
1014
        push    0
1015
        mov     eax, [edi+28]
1016
        sub     eax, ebx
1017
        jb      .eof
1018
        cmp     eax, ecx
1019
        jae     @f
1020
        mov     ecx, eax
1021
        mov     byte [esp], 6           ; EOF
1022
@@:
75 diamond 1023
        movzx   edi, word [edi+26]	; cluster
71 diamond 1024
.new:
75 diamond 1025
        jecxz   .done
1026
        test    edi, edi
1027
        jz      .eof
1028
        cmp     edi, 0xFF8
1029
        jae     .eof
1030
        lea     eax, [edi+31]           ; bootsector+2*fat+filenames
1031
        shl     eax, 9                  ; *512
1032
        add     eax, 0x100000           ; image base
71 diamond 1033
; now eax points to data of cluster
75 diamond 1034
        sub     ebx, 512
1035
        jae     .skip
1036
        lea     eax, [eax+ebx+512]
1037
        neg     ebx
1038
        push    ecx
1039
        cmp     ecx, ebx
1040
        jbe     @f
1041
        mov     ecx, ebx
71 diamond 1042
@@:
75 diamond 1043
        mov     ebx, edx
1044
        call    memmove
1045
        add     edx, ecx
1046
        sub     [esp], ecx
1047
        pop     ecx
1048
        xor     ebx, ebx
71 diamond 1049
.skip:
75 diamond 1050
        movzx   edi, word [edi*2+0x280000]      ; find next cluster from FAT
1051
        jmp     .new
71 diamond 1052
.eof:
77 diamond 1053
        mov     ebx, edx
1054
        pop     eax edx ecx
1055
        sub     ebx, edx
75 diamond 1056
        jmp     .reteof
71 diamond 1057
.done:
77 diamond 1058
        mov     ebx, edx
1059
        pop     eax edx ecx edi
1060
        sub     ebx, edx
75 diamond 1061
        ret
71 diamond 1062
 
75 diamond 1063
;----------------------------------------------------------------
1064
;
1065
;  fs_RamdiskReadFolder - LFN variant for reading sys floppy folder
1066
;
1067
;  esi  points to filename; only root is folder on ramdisk
78 diamond 1068
;  ebx  pointer to structure 32-bit number = first wanted block
1069
;                          & flags (bitfields)
1070
; flags: bit 0: 0=ANSI names, 1=UNICODE names
75 diamond 1071
;  ecx  number of blocks to read, 0+
1072
;  edx  mem location to return data
1073
;
1074
;  ret ebx = size or 0xffffffff file not found
1075
;      eax = 0 ok read or other = errormsg
1076
;
1077
;--------------------------------------------------------------
1078
fs_RamdiskReadFolder:
1079
        cmp     byte [esi], 0
1080
        jz      @f
1081
; ramdisk doesn't support folders
1082
        mov     eax, ERROR_ACCESS_DENIED
1083
        or      ebx, -1
1084
        ret
1085
@@:
1086
        push    esi edi ecx
1087
; init header
1088
        push    ecx
1089
        mov     edi, edx
1090
        mov     ecx, 32/4
1091
        xor     eax, eax
1092
        rep     stosd
1093
        mov     byte [edx], 1   ; version
1094
        pop     ecx
1095
        push    ebp
1096
        sub     esp, 262*2      ; allocate space for LFN
1097
        mov     ebp, esp
78 diamond 1098
        push    dword [ebx+4]   ; for fat_get_name: read ANSI/UNICODE name
1099
        mov     ebx, [ebx]
75 diamond 1100
; read root
1101
        mov     esi, edi        ; esi points to block of data of folder entry (BDFE)
1102
        mov     edi, 0x100000+512*19
1103
.l1:
1104
        call    fat_get_name
1105
        jc      .l2
1106
        cmp     byte [edi+11], 0xF
1107
        jnz     @f
1108
        add     edi, 0x20
1109
@@:
1110
        inc     dword [edx+8]   ; new file found
1111
        dec     ebx
1112
        jns     .l2
1113
        dec     ecx
1114
        js      .l2
1115
        inc     dword [edx+4]  ; new file block copied
1116
        call    fat_entry_to_bdfe
1117
.l2:
1118
        add     edi, 0x20
1119
        cmp     edi, 0x100000+512*33
1120
        jb      .l1
1121
        add     esp, 262*2+4
1122
        pop     ebp
77 diamond 1123
        mov     ebx, [edx+4]
75 diamond 1124
        xor     eax, eax
1125
        dec     ecx
1126
        js      @f
1127
        mov     al, ERROR_END_OF_FILE
1128
@@:
1129
        pop     ecx edi esi
1130
        ret
1131
 
83 diamond 1132
iglobal
1133
label fat_legal_chars byte
1134
; 0 = not allowed
1135
; 1 = allowed only in long names
1136
; 3 = allowed
1137
        times 32 db 0
1138
;                 ! " # $ % & ' ( ) * + , - . /
1139
        db      1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0
1140
;               0 1 2 3 4 5 6 7 8 9 : ; < = > ?
1141
        db      3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0
1142
;               @ A B C D E F G H I J K L M N O
1143
        db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
1144
;               P Q R S T U V W X Y Z [ \ ] ^ _
1145
        db      3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3
1146
;               ` a b c d e f g h i j k l m n o
1147
        db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
1148
;               p q r s t u v w x y z { | } ~
1149
        db      3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0
1150
endg
1151
 
1152
fat_name_is_legal:
1153
; in: esi->(long) name
1154
; out: CF set <=> legal
1155
; destroys eax
1156
        push    esi
1157
        xor     eax, eax
1158
@@:
1159
        lodsb
1160
        test    al, al
1161
        jz      .done
1162
        cmp     al, 80h
1163
        jae     .big
1164
        test    [fat_legal_chars+eax], 1
1165
        jnz     @b
1166
.err:
1167
        pop     esi
1168
        clc
1169
        ret
1170
.big:
1171
; 0x80-0xAF, 0xE0-0xEF
1172
        cmp     al, 0xB0
1173
        jb      @b
1174
        cmp     al, 0xE0
1175
        jb      .err
1176
        cmp     al, 0xF0
1177
        jb      @b
1178
        jmp     .err
1179
.done:
1180
        sub     esi, [esp]
1181
        cmp     esi, 257
1182
        pop     esi
1183
        ret
1184
 
1185
fat_next_short_name:
1186
; in: edi->8+3 name
1187
; out: name corrected
1188
;      CF=1 <=> error
1189
        pushad
1190
        mov     ecx, 8
1191
        mov     al, '~'
1192
        std
1193
        push    edi
1194
        add     edi, 7
1195
        repnz   scasb
1196
        pop     edi
1197
        cld
1198
        jz      .tilde
1199
; tilde is not found, insert "~1" at end
1200
        add     edi, 6
1201
        cmp     word [edi], '  '
1202
        jnz     .insert_tilde
1203
@@:     dec     edi
1204
        cmp     byte [edi], ' '
1205
        jz      @b
1206
        inc     edi
1207
.insert_tilde:
1208
        mov     word [edi], '~1'
1209
        popad
1210
;       clc     ; CF already cleared
1211
        ret
1212
.tilde:
1213
        push    edi
1214
        add     edi, 7
1215
        xor     ecx, ecx
1216
@@:
1217
; after tilde may be only digits and trailing spaces
1218
        cmp     byte [edi], '~'
1219
        jz      .break
1220
        cmp     byte [edi], ' '
1221
        jz      .space
1222
        cmp     byte [edi], '9'
1223
        jnz     .found
1224
        dec     edi
1225
        jmp     @b
1226
.space:
1227
        dec     edi
1228
        inc     ecx
1229
        jmp     @b
1230
.found:
1231
        inc     byte [edi]
1232
.succ:
1233
        pop     edi
1234
        popad
1235
        clc
1236
        ret
1237
.break:
1238
        jecxz   .noplace
1239
        inc     edi
1240
        mov     al, '1'
1241
@@:
1242
        xchg    al, [edi]
1243
        inc     edi
1244
        cmp     al, ' '
1245
        mov     al, '0'
1246
        jnz     @b
1247
        jmp     .succ
1248
.noplace:
1249
        dec     edi
1250
        cmp     edi, [esp]
1251
        jz      .err
1252
        add     dword [esp], 8
1253
        mov     word [edi], '~1'
1254
        inc     edi
1255
        inc     edi
1256
@@:
1257
        mov     byte [edi], '0'
1258
        inc     edi
1259
        cmp     edi, [esp]
1260
        jb      @b
1261
        pop     edi
1262
        popad
1263
        ;clc    ; automatically
1264
        ret
1265
.err:
1266
        pop     edi
1267
        popad
1268
        stc
1269
        ret
1270
 
1271
fat_gen_short_name:
1272
; in: esi->long name
1273
;     edi->buffer (8+3=11 chars)
1274
; out: buffer filled
1275
        pushad
1276
        mov     eax, '    '
1277
        push    edi
1278
        stosd
1279
        stosd
1280
        stosd
1281
        pop     edi
1282
        xor     eax, eax
1283
        push    8
1284
        pop     ebx
1285
        lea     ecx, [edi+8]
1286
.loop:
1287
        lodsb
1288
        test    al, al
1289
        jz      .done
1290
        call    char_toupper
1291
        cmp     al, ' '
1292
        jz      .space
1293
        cmp     al, 80h
1294
        ja      .big
1295
        test    [fat_legal_chars+eax], 2
1296
        jnz     .symbol
1297
.inv_symbol:
1298
        mov     al, '_'
1299
        or      bh, 1
1300
.symbol:
1301
        cmp     al, '.'
1302
        jz      .dot
1303
.normal_symbol:
1304
        dec     bl
1305
        jns     .store
1306
        mov     bl, 0
1307
.space:
1308
        or      bh, 1
1309
        jmp     .loop
1310
.store:
1311
        stosb
1312
        jmp     .loop
1313
.big:
1314
        cmp     al, 0xB0
1315
        jb      .normal_symbol
1316
        cmp     al, 0xE0
1317
        jb      .inv_symbol
1318
        cmp     al, 0xF0
1319
        jb      .normal_symbol
1320
        jmp     .inv_symbol
1321
.dot:
1322
        test    bh, 2
1323
        jz      .firstdot
1324
        pop     ebx
1325
        add     ebx, edi
1326
        sub     ebx, ecx
1327
        push    ebx
1328
        cmp     edi, ecx
1329
        jbe     .skip
1330
@@:
1331
        dec     edi
1332
        mov     al, ' '
1333
        xchg    al, [edi]
1334
        dec     ebx
1335
        mov     [ebx], al
1336
        cmp     edi, ecx
1337
        ja      @b
1338
.skip:
1339
        mov     bh, 3
1340
        jmp     @f
1341
.firstdot:
1342
        cmp     bl, 8
1343
        jz      .space
1344
        push    edi
1345
        or      bh, 2
1346
@@:
1347
        mov     edi, ecx
1348
        mov     bl, 3
1349
        jmp     .loop
1350
.done:
1351
        test    bh, 2
1352
        jz      @f
1353
        pop     edi
1354
@@:
1355
        lea     edi, [ecx-8]
1356
        test    bh, 1
1357
        jz      @f
1358
        call    fat_next_short_name
1359
@@:
1360
        popad
1361
        ret
1362
 
1363
;----------------------------------------------------------------
1364
;
1365
;  fs_RamdiskRewrite - LFN variant for writing sys floppy
1366
;
1367
;  esi  points to filename
1368
;  ebx  ignored (reserved)
1369
;  ecx  number of bytes to write, 0+
1370
;  edx  mem location to data
1371
;
1372
;  ret ebx = number of written bytes
1373
;      eax = 0 ok read or other = errormsg
1374
;
1375
;--------------------------------------------------------------
1376
@@:
1377
        mov     eax, ERROR_ACCESS_DENIED
1378
        xor     ebx, ebx
1379
        ret
1380
 
1381
fs_RamdiskRewrite:
1382
        cmp     byte [esi], 0
1383
        jz      @b
1384
; ramdisk doesn't support folders
1385
        push    esi
1386
@@:
1387
        lodsb
1388
        test    al, al
1389
        jz      @f
1390
        cmp     al, '/'
1391
        jnz     @b
1392
        pop     esi
1393
.err5:
1394
        mov     eax, 5  ; file not found
1395
        xor     ebx, ebx
1396
        ret
1397
@@:
1398
        pop     esi
1399
; check existence
1400
        push    edi
1401
        call    rd_find_lfn
1402
        jc      .notfound
1403
; found, delete FAT chain
1404
        push    edi
1405
        xor     eax, eax
1406
        mov     dword [edi+28], eax     ; zero size
1407
        xchg    ax, word [edi+26]       ; start cluster
1408
        test    eax, eax
1409
        jz      .done1
1410
@@:
1411
        cmp     eax, 0xFF8
1412
        jae     .done1
1413
        lea     edi, [0x280000 + eax*2] ; position in FAT
1414
        xor     eax, eax
1415
        xchg    ax, [edi]
1416
        jmp     @b
1417
.done1:
1418
        pop     edi
1419
        call    get_time_for_file
1420
        mov     [edi+22], ax
1421
        call    get_date_for_file
1422
        mov     [edi+24], ax
1423
        mov     [edi+18], ax
1424
        or      byte [edi+11], 20h      ; set 'archive' attribute
1425
        jmp     .doit
1426
.notfound:
1427
; file is not found; generate short name
1428
        call    fat_name_is_legal
1429
        jc      @f
1430
        pop     edi
1431
        jmp     .err5
1432
@@:
1433
        sub     esp, 12
1434
        mov     edi, esp
1435
        call    fat_gen_short_name
1436
.test_short_name_loop:
1437
        push    esi ecx
1438
        mov     esi, 0x100000+512*19
1439
.test_short_name_entry:
1440
        cmp     byte [esi+11], 0xF
1441
        jz      .test_short_name_cont
1442
        mov     ecx, 11
1443
        push    esi edi
1444
        repz    cmpsb
1445
        pop     edi esi
1446
        jz      .short_name_found
1447
.test_short_name_cont:
1448
        add     esi, 20h
1449
        cmp     esi, 0x100000+512*33
1450
        jb      .test_short_name_entry
1451
        pop     ecx esi
1452
        jmp     .found
1453
.short_name_found:
1454
        call    fat_next_short_name
1455
        pop     ecx esi
1456
        jnc     .test_short_name_loop
1457
.disk_full:
1458
        add     esp, 12
1459
        pop     edi
1460
        mov     eax, ERROR_DISK_FULL
1461
        xor     ebx, ebx
1462
        ret
1463
.found:
1464
; now find space in directory
1465
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
1466
        mov     al, '~'
1467
        push    ecx edi
1468
        mov     ecx, 8
1469
        repnz   scasb
1470
        push    1
1471
        pop     eax     ; 1 entry
1472
        jnz     .notilde
1473
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
1474
        xor     eax, eax
1475
@@:
1476
        cmp     byte [esi], 0
1477
        jz      @f
1478
        inc     esi
1479
        inc     eax
1480
        jmp     @b
1481
@@:
1482
        sub     esi, eax
1483
        add     eax, 12+13
1484
        mov     ecx, 13
1485
        push    edx
1486
        cdq
1487
        div     ecx
1488
        pop     edx
1489
.notilde:
1490
; find  successive entries in directory
1491
        xor     ecx, ecx
1492
        mov     edi, 0x100000+512*19
1493
.scan_dir:
1494
        cmp     byte [edi], 0
1495
        jz      .free
1496
        cmp     byte [edi], 0xE5
1497
        jz      .free
1498
        xor     ecx, ecx
1499
.scan_cont:
1500
        add     edi, 0x20
1501
        cmp     edi, 0x100000+512*33
1502
        jb      .scan_dir
1503
        pop     edi ecx
1504
        jmp     .disk_full
1505
.free:
1506
        inc     ecx
1507
        cmp     ecx, eax
1508
        jb      .scan_cont
1509
; found!
1510
; calculate name checksum
1511
        push    esi ecx
1512
        mov     esi, [esp+8]
1513
        mov     ecx, 11
1514
        xor     eax, eax
1515
@@:
1516
        ror     al, 1
1517
        add     al, [esi]
1518
        inc     esi
1519
        loop    @b
1520
        pop     ecx esi
1521
; edi points to last entry in free chunk
1522
        dec     ecx
1523
        jz      .nolfn
1524
        push    esi
1525
        push    edi
1526
.writelfn:
1527
        sub     edi, 20h
1528
        push    ecx eax
1529
        mov     eax, [esp+8]
1530
        sub     eax, edi
1531
        shr     eax, 5
1532
        cmp     ecx, 1
1533
        jnz     @f
1534
        or      al, 40h
1535
@@:
1536
        stosb
1537
        mov     cl, 5
1538
        call    .read_symbols
1539
        mov     ax, 0xF
1540
        stosw
1541
        pop     eax
1542
        stosb
1543
        push    eax
1544
        mov     cl, 6
1545
        call    .read_symbols
1546
        xor     eax, eax
1547
        stosw
1548
        mov     cl, 2
1549
        call    .read_symbols
1550
        pop     eax ecx
1551
        sub     edi, 0x20
1552
        loop    .writelfn
1553
        pop     edi
1554
        pop     esi
1555
.nolfn:
1556
        xchg    esi, [esp]
1557
        mov     ecx, 11
1558
        rep     movsb
1559
        mov     word [edi], 20h         ; attributes
1560
        sub     edi, 11
1561
        pop     esi ecx
1562
        add     esp, 12
1563
        mov     byte [edi+13], 0        ; tenths of a second at file creation time
1564
        call    get_time_for_file
1565
        mov     [edi+14], ax            ; creation time
1566
        mov     [edi+22], ax            ; last write time
1567
        call    get_date_for_file
1568
        mov     [edi+16], ax            ; creation date
1569
        mov     [edi+24], ax            ; last write date
1570
        mov     [edi+18], ax            ; last access date
1571
        and     word [edi+20], 0        ; high word of cluster
1572
        and     word [edi+26], 0        ; low word of cluster - to be filled
1573
        and     dword [edi+28], 0       ; file size - to be filled
1574
.doit:
1575
        push    ecx edx
1576
        push    ecx
1577
        push    edi
1578
        add     edi, 26         ; edi points to low word of cluster
1579
        push    edi
1580
        jecxz   .done
1581
        mov     ecx, 2849
1582
        mov     edi, 0x280000
1583
.write_loop:
1584
; allocate new cluster
1585
        xor     eax, eax
1586
        repnz   scasw
1587
        jnz     .disk_full2
1588
        dec     edi
1589
        dec     edi
1590
        lea     eax, [edi-0x280000]
1591
        shr     eax, 1                  ; eax = cluster
1592
        mov     word [edi], 0xFFF       ; mark as last cluster
1593
        xchg    edi, [esp]
1594
        stosw
1595
        pop     edi
1596
        push    edi
1597
        inc     ecx
1598
; write data
1599
        shl     eax, 9
1600
        add     eax, 0x100000+31*512
1601
        mov     ebx, edx
1602
        xchg    eax, ebx
1603
        push    ecx
1604
        mov     ecx, 512
1605
        cmp     dword [esp+12], ecx
1606
        jae     @f
1607
        mov     ecx, [esp+12]
1608
@@:
1609
        call    memmove
1610
        add     edx, ecx
1611
        sub     [esp+12], ecx
1612
        pop     ecx
1613
        jnz     .write_loop
1614
.done:
1615
        mov     ebx, edx
1616
        pop     edi edi ecx edx ecx
1617
        sub     ebx, edx
1618
        mov     [edi+28], ebx
1619
        pop     edi
1620
        xor     eax, eax
1621
        ret
1622
.disk_full2:
1623
        mov     ebx, edx
1624
        pop     edi edi ecx edx ecx
1625
        sub     ebx, edx
1626
        mov     [edi+28], ebx
1627
        pop     edi
1628
        push    ERROR_DISK_FULL
1629
        pop     eax
1630
        ret
1631
 
1632
.read_symbol:
1633
        or      ax, -1
1634
        test    esi, esi
1635
        jz      .retFFFF
1636
        lodsb
1637
        test    al, al
1638
        jnz     ansi2uni_char
1639
        xor     eax, eax
1640
        xor     esi, esi
1641
.retFFFF:
1642
        ret
1643
 
1644
.read_symbols:
1645
        call    .read_symbol
1646
        stosw
1647
        loop    .read_symbols
1648
        ret
1649
 
86 diamond 1650
fs_RamdiskGetFileInfo:
1651
        cmp     byte [esi], 0
1652
        jnz     @f
1653
        mov     eax, 2  ; unsupported
1654
        ret
1655
@@:
1656
        push    edi
1657
        call    rd_find_lfn
1658
fs_GetFileInfo_finish:
1659
        jnc     @f
1660
        pop     edi
1661
        mov     eax, ERROR_FILE_NOT_FOUND
1662
        ret
1663
@@:
1664
        push    esi ebp
1665
        xor     ebp, ebp
1666
        mov     esi, edx
1667
        and     dword [esi+4], 0
1668
        call    fat_entry_to_bdfe2
1669
        pop     ebp esi
1670
        pop     edi
1671
        xor     eax, eax
1672
        ret
1673
 
1674
fs_RamdiskSetFileInfo:
1675
        cmp     byte [esi], 0
1676
        jnz     @f
1677
        mov     eax, 2  ; unsupported
1678
        ret
1679
@@:
1680
        push    edi
1681
        call    rd_find_lfn
1682
        jnc     @f
1683
        pop     edi
1684
        mov     eax, ERROR_FILE_NOT_FOUND
1685
        ret
1686
@@:
1687
        call    bdfe_to_fat_entry
1688
        pop     edi
1689
        xor     eax, eax
1690
        ret
1691
 
78 diamond 1692
; \end{diamond}