Subversion Repositories Kolibri OS

Rev

Rev 78 | Rev 86 | 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
 
837
fat_entry_to_bdfe:
838
; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
839
; destroys eax
840
        movzx   eax, byte [edi+11]
841
        mov     [esi], eax	; attributes
842
        mov     eax, [ebp-4]
843
        mov     [esi+4], eax	; ASCII/UNICODE name
844
        movzx   eax, word [edi+14]
845
        call    fat_time_to_bdfe
846
        mov     [esi+8], eax	; creation time
847
        movzx   eax, word [edi+16]
848
        call    fat_date_to_bdfe
849
        mov     [esi+12], eax	; creation date
850
        and     dword [esi+16], 0	; last access time is not supported on FAT
851
        movzx   eax, word [edi+18]
852
        call    fat_date_to_bdfe
853
        mov     [esi+20], eax	; last access date
854
        movzx   eax, word [edi+22]
855
        call    fat_time_to_bdfe
856
        mov     [esi+24], eax	; last write time
857
        movzx   eax, word [edi+24]
858
        call    fat_date_to_bdfe
859
        mov     [esi+28], eax	; last write date
860
        mov     eax, [edi+28]
861
        mov     [esi+32], eax	; file size (low dword)
862
        xor     eax, eax
863
        mov     [esi+36], eax	; file size (high dword)
864
        push    ecx edi
865
        lea     edi, [esi+40]
866
        mov     esi, ebp
78 diamond 867
        test    byte [esi-4], 1
868
        jz      .ansi
869
        mov     ecx, 260/2
75 diamond 870
        rep     movsd
78 diamond 871
        mov     [edi-2], ax
872
@@:
75 diamond 873
        mov     esi, edi
874
        pop     edi ecx
875
        ret
78 diamond 876
.ansi:
877
        mov     ecx, 264/4
878
        rep     movsd
879
        mov     [edi-1], al
880
        jmp     @b
75 diamond 881
 
71 diamond 882
rd_find_lfn:
883
; in: esi->name
884
; out: CF=1 - file not found
885
;      else CF=0 and edi->direntry
78 diamond 886
        push    esi ebp edi
887
        sub     esp, 262*2      ; allocate space for LFN
888
        mov     ebp, esp        ; ebp points to buffer
889
        push    0               ; for fat_get_name: read ASCII name
890
        mov     edi, 0x100000+512*19    ; to root dir
71 diamond 891
.l1:
78 diamond 892
        call    fat_get_name
893
        jc      .l2
894
        call    fat_compare_name
895
        jz      .found
71 diamond 896
.l2:
78 diamond 897
        add     edi, 0x20
898
        cmp     edi, 0x100000+512*33
899
        jb      .l1
71 diamond 900
.notfound:
78 diamond 901
        add     esp, 262*2+4
902
        pop     edi ebp esi
903
        stc
904
        ret
71 diamond 905
.found:
906
; found
907
; if this is LFN entry, advance to true entry
78 diamond 908
        cmp     byte [edi+11], 0xF
909
        jnz     @f
910
        add     edi, 0x20
71 diamond 911
@@:
912
; folders are not supported
78 diamond 913
        cmp     byte [esi], 0
914
        jnz     .notfound
915
        add     esp, 262*2+4+4  ; CF=0
916
        pop     ebp esi
917
        ret
71 diamond 918
 
919
;----------------------------------------------------------------
920
;
921
;  fs_RamdiskRead - LFN variant for reading sys floppy
922
;
923
;  esi  points to filename
924
;  ebx  pointer to 64-bit number = first wanted byte, 0+
925
;       may be ebx=0 - start from first byte
926
;  ecx  number of bytes to read, 0+
927
;  edx  mem location to return data
928
;
77 diamond 929
;  ret ebx = bytes read or 0xffffffff file not found
71 diamond 930
;      eax = 0 ok read or other = errormsg
931
;
932
;--------------------------------------------------------------
933
fs_RamdiskRead:
75 diamond 934
        cmp     byte [esi], 0
935
        jnz     @f
936
        or      ebx, -1
937
        mov     eax, 10         ; access denied
938
        ret
71 diamond 939
@@:
75 diamond 940
        push    edi
941
        call    rd_find_lfn
942
        jnc     .found
943
        pop     edi
944
        or      ebx, -1
945
        mov     eax, 5          ; file not found
946
        ret
71 diamond 947
.found:
75 diamond 948
        test    ebx, ebx
949
        jz      .l1
950
        cmp     dword [ebx+4], 0
951
        jz      @f
77 diamond 952
        xor     ebx, ebx
71 diamond 953
.reteof:
75 diamond 954
        mov     eax, 6          ; EOF
955
        pop     edi
956
        ret
71 diamond 957
@@:
75 diamond 958
        mov     ebx, [ebx]
71 diamond 959
.l1:
77 diamond 960
        push    ecx edx
961
        push    0
962
        mov     eax, [edi+28]
963
        sub     eax, ebx
964
        jb      .eof
965
        cmp     eax, ecx
966
        jae     @f
967
        mov     ecx, eax
968
        mov     byte [esp], 6           ; EOF
969
@@:
75 diamond 970
        movzx   edi, word [edi+26]	; cluster
71 diamond 971
.new:
75 diamond 972
        jecxz   .done
973
        test    edi, edi
974
        jz      .eof
975
        cmp     edi, 0xFF8
976
        jae     .eof
977
        lea     eax, [edi+31]           ; bootsector+2*fat+filenames
978
        shl     eax, 9                  ; *512
979
        add     eax, 0x100000           ; image base
71 diamond 980
; now eax points to data of cluster
75 diamond 981
        sub     ebx, 512
982
        jae     .skip
983
        lea     eax, [eax+ebx+512]
984
        neg     ebx
985
        push    ecx
986
        cmp     ecx, ebx
987
        jbe     @f
988
        mov     ecx, ebx
71 diamond 989
@@:
75 diamond 990
        mov     ebx, edx
991
        call    memmove
992
        add     edx, ecx
993
        sub     [esp], ecx
994
        pop     ecx
995
        xor     ebx, ebx
71 diamond 996
.skip:
75 diamond 997
        movzx   edi, word [edi*2+0x280000]      ; find next cluster from FAT
998
        jmp     .new
71 diamond 999
.eof:
77 diamond 1000
        mov     ebx, edx
1001
        pop     eax edx ecx
1002
        sub     ebx, edx
75 diamond 1003
        jmp     .reteof
71 diamond 1004
.done:
77 diamond 1005
        mov     ebx, edx
1006
        pop     eax edx ecx edi
1007
        sub     ebx, edx
75 diamond 1008
        ret
71 diamond 1009
 
75 diamond 1010
;----------------------------------------------------------------
1011
;
1012
;  fs_RamdiskReadFolder - LFN variant for reading sys floppy folder
1013
;
1014
;  esi  points to filename; only root is folder on ramdisk
78 diamond 1015
;  ebx  pointer to structure 32-bit number = first wanted block
1016
;                          & flags (bitfields)
1017
; flags: bit 0: 0=ANSI names, 1=UNICODE names
75 diamond 1018
;  ecx  number of blocks to read, 0+
1019
;  edx  mem location to return data
1020
;
1021
;  ret ebx = size or 0xffffffff file not found
1022
;      eax = 0 ok read or other = errormsg
1023
;
1024
;--------------------------------------------------------------
1025
fs_RamdiskReadFolder:
1026
        cmp     byte [esi], 0
1027
        jz      @f
1028
; ramdisk doesn't support folders
1029
        mov     eax, ERROR_ACCESS_DENIED
1030
        or      ebx, -1
1031
        ret
1032
@@:
1033
        push    esi edi ecx
1034
; init header
1035
        push    ecx
1036
        mov     edi, edx
1037
        mov     ecx, 32/4
1038
        xor     eax, eax
1039
        rep     stosd
1040
        mov     byte [edx], 1   ; version
1041
        pop     ecx
1042
        push    ebp
1043
        sub     esp, 262*2      ; allocate space for LFN
1044
        mov     ebp, esp
78 diamond 1045
        push    dword [ebx+4]   ; for fat_get_name: read ANSI/UNICODE name
1046
        mov     ebx, [ebx]
75 diamond 1047
; read root
1048
        mov     esi, edi        ; esi points to block of data of folder entry (BDFE)
1049
        mov     edi, 0x100000+512*19
1050
.l1:
1051
        call    fat_get_name
1052
        jc      .l2
1053
        cmp     byte [edi+11], 0xF
1054
        jnz     @f
1055
        add     edi, 0x20
1056
@@:
1057
        inc     dword [edx+8]   ; new file found
1058
        dec     ebx
1059
        jns     .l2
1060
        dec     ecx
1061
        js      .l2
1062
        inc     dword [edx+4]  ; new file block copied
1063
        call    fat_entry_to_bdfe
1064
.l2:
1065
        add     edi, 0x20
1066
        cmp     edi, 0x100000+512*33
1067
        jb      .l1
1068
        add     esp, 262*2+4
1069
        pop     ebp
77 diamond 1070
        mov     ebx, [edx+4]
75 diamond 1071
        xor     eax, eax
1072
        dec     ecx
1073
        js      @f
1074
        mov     al, ERROR_END_OF_FILE
1075
@@:
1076
        pop     ecx edi esi
1077
        ret
1078
 
83 diamond 1079
iglobal
1080
label fat_legal_chars byte
1081
; 0 = not allowed
1082
; 1 = allowed only in long names
1083
; 3 = allowed
1084
        times 32 db 0
1085
;                 ! " # $ % & ' ( ) * + , - . /
1086
        db      1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0
1087
;               0 1 2 3 4 5 6 7 8 9 : ; < = > ?
1088
        db      3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0
1089
;               @ A B C D E F G H I J K L M N O
1090
        db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
1091
;               P Q R S T U V W X Y Z [ \ ] ^ _
1092
        db      3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3
1093
;               ` a b c d e f g h i j k l m n o
1094
        db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
1095
;               p q r s t u v w x y z { | } ~
1096
        db      3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0
1097
endg
1098
 
1099
fat_name_is_legal:
1100
; in: esi->(long) name
1101
; out: CF set <=> legal
1102
; destroys eax
1103
        push    esi
1104
        xor     eax, eax
1105
@@:
1106
        lodsb
1107
        test    al, al
1108
        jz      .done
1109
        cmp     al, 80h
1110
        jae     .big
1111
        test    [fat_legal_chars+eax], 1
1112
        jnz     @b
1113
.err:
1114
        pop     esi
1115
        clc
1116
        ret
1117
.big:
1118
; 0x80-0xAF, 0xE0-0xEF
1119
        cmp     al, 0xB0
1120
        jb      @b
1121
        cmp     al, 0xE0
1122
        jb      .err
1123
        cmp     al, 0xF0
1124
        jb      @b
1125
        jmp     .err
1126
.done:
1127
        sub     esi, [esp]
1128
        cmp     esi, 257
1129
        pop     esi
1130
        ret
1131
 
1132
fat_next_short_name:
1133
; in: edi->8+3 name
1134
; out: name corrected
1135
;      CF=1 <=> error
1136
        pushad
1137
        mov     ecx, 8
1138
        mov     al, '~'
1139
        std
1140
        push    edi
1141
        add     edi, 7
1142
        repnz   scasb
1143
        pop     edi
1144
        cld
1145
        jz      .tilde
1146
; tilde is not found, insert "~1" at end
1147
        add     edi, 6
1148
        cmp     word [edi], '  '
1149
        jnz     .insert_tilde
1150
@@:     dec     edi
1151
        cmp     byte [edi], ' '
1152
        jz      @b
1153
        inc     edi
1154
.insert_tilde:
1155
        mov     word [edi], '~1'
1156
        popad
1157
;       clc     ; CF already cleared
1158
        ret
1159
.tilde:
1160
        push    edi
1161
        add     edi, 7
1162
        xor     ecx, ecx
1163
@@:
1164
; after tilde may be only digits and trailing spaces
1165
        cmp     byte [edi], '~'
1166
        jz      .break
1167
        cmp     byte [edi], ' '
1168
        jz      .space
1169
        cmp     byte [edi], '9'
1170
        jnz     .found
1171
        dec     edi
1172
        jmp     @b
1173
.space:
1174
        dec     edi
1175
        inc     ecx
1176
        jmp     @b
1177
.found:
1178
        inc     byte [edi]
1179
.succ:
1180
        pop     edi
1181
        popad
1182
        clc
1183
        ret
1184
.break:
1185
        jecxz   .noplace
1186
        inc     edi
1187
        mov     al, '1'
1188
@@:
1189
        xchg    al, [edi]
1190
        inc     edi
1191
        cmp     al, ' '
1192
        mov     al, '0'
1193
        jnz     @b
1194
        jmp     .succ
1195
.noplace:
1196
        dec     edi
1197
        cmp     edi, [esp]
1198
        jz      .err
1199
        add     dword [esp], 8
1200
        mov     word [edi], '~1'
1201
        inc     edi
1202
        inc     edi
1203
@@:
1204
        mov     byte [edi], '0'
1205
        inc     edi
1206
        cmp     edi, [esp]
1207
        jb      @b
1208
        pop     edi
1209
        popad
1210
        ;clc    ; automatically
1211
        ret
1212
.err:
1213
        pop     edi
1214
        popad
1215
        stc
1216
        ret
1217
 
1218
fat_gen_short_name:
1219
; in: esi->long name
1220
;     edi->buffer (8+3=11 chars)
1221
; out: buffer filled
1222
        pushad
1223
        mov     eax, '    '
1224
        push    edi
1225
        stosd
1226
        stosd
1227
        stosd
1228
        pop     edi
1229
        xor     eax, eax
1230
        push    8
1231
        pop     ebx
1232
        lea     ecx, [edi+8]
1233
.loop:
1234
        lodsb
1235
        test    al, al
1236
        jz      .done
1237
        call    char_toupper
1238
        cmp     al, ' '
1239
        jz      .space
1240
        cmp     al, 80h
1241
        ja      .big
1242
        test    [fat_legal_chars+eax], 2
1243
        jnz     .symbol
1244
.inv_symbol:
1245
        mov     al, '_'
1246
        or      bh, 1
1247
.symbol:
1248
        cmp     al, '.'
1249
        jz      .dot
1250
.normal_symbol:
1251
        dec     bl
1252
        jns     .store
1253
        mov     bl, 0
1254
.space:
1255
        or      bh, 1
1256
        jmp     .loop
1257
.store:
1258
        stosb
1259
        jmp     .loop
1260
.big:
1261
        cmp     al, 0xB0
1262
        jb      .normal_symbol
1263
        cmp     al, 0xE0
1264
        jb      .inv_symbol
1265
        cmp     al, 0xF0
1266
        jb      .normal_symbol
1267
        jmp     .inv_symbol
1268
.dot:
1269
        test    bh, 2
1270
        jz      .firstdot
1271
        pop     ebx
1272
        add     ebx, edi
1273
        sub     ebx, ecx
1274
        push    ebx
1275
        cmp     edi, ecx
1276
        jbe     .skip
1277
@@:
1278
        dec     edi
1279
        mov     al, ' '
1280
        xchg    al, [edi]
1281
        dec     ebx
1282
        mov     [ebx], al
1283
        cmp     edi, ecx
1284
        ja      @b
1285
.skip:
1286
        mov     bh, 3
1287
        jmp     @f
1288
.firstdot:
1289
        cmp     bl, 8
1290
        jz      .space
1291
        push    edi
1292
        or      bh, 2
1293
@@:
1294
        mov     edi, ecx
1295
        mov     bl, 3
1296
        jmp     .loop
1297
.done:
1298
        test    bh, 2
1299
        jz      @f
1300
        pop     edi
1301
@@:
1302
        lea     edi, [ecx-8]
1303
        test    bh, 1
1304
        jz      @f
1305
        call    fat_next_short_name
1306
@@:
1307
        popad
1308
        ret
1309
 
1310
;----------------------------------------------------------------
1311
;
1312
;  fs_RamdiskRewrite - LFN variant for writing sys floppy
1313
;
1314
;  esi  points to filename
1315
;  ebx  ignored (reserved)
1316
;  ecx  number of bytes to write, 0+
1317
;  edx  mem location to data
1318
;
1319
;  ret ebx = number of written bytes
1320
;      eax = 0 ok read or other = errormsg
1321
;
1322
;--------------------------------------------------------------
1323
@@:
1324
        mov     eax, ERROR_ACCESS_DENIED
1325
        xor     ebx, ebx
1326
        ret
1327
 
1328
fs_RamdiskRewrite:
1329
        cmp     byte [esi], 0
1330
        jz      @b
1331
; ramdisk doesn't support folders
1332
        push    esi
1333
@@:
1334
        lodsb
1335
        test    al, al
1336
        jz      @f
1337
        cmp     al, '/'
1338
        jnz     @b
1339
        pop     esi
1340
.err5:
1341
        mov     eax, 5  ; file not found
1342
        xor     ebx, ebx
1343
        ret
1344
@@:
1345
        pop     esi
1346
; check existence
1347
        push    edi
1348
        call    rd_find_lfn
1349
        jc      .notfound
1350
; found, delete FAT chain
1351
        push    edi
1352
        xor     eax, eax
1353
        mov     dword [edi+28], eax     ; zero size
1354
        xchg    ax, word [edi+26]       ; start cluster
1355
        test    eax, eax
1356
        jz      .done1
1357
@@:
1358
        cmp     eax, 0xFF8
1359
        jae     .done1
1360
        lea     edi, [0x280000 + eax*2] ; position in FAT
1361
        xor     eax, eax
1362
        xchg    ax, [edi]
1363
        jmp     @b
1364
.done1:
1365
        pop     edi
1366
        call    get_time_for_file
1367
        mov     [edi+22], ax
1368
        call    get_date_for_file
1369
        mov     [edi+24], ax
1370
        mov     [edi+18], ax
1371
        or      byte [edi+11], 20h      ; set 'archive' attribute
1372
        jmp     .doit
1373
.notfound:
1374
; file is not found; generate short name
1375
        call    fat_name_is_legal
1376
        jc      @f
1377
        pop     edi
1378
        jmp     .err5
1379
@@:
1380
        sub     esp, 12
1381
        mov     edi, esp
1382
        call    fat_gen_short_name
1383
.test_short_name_loop:
1384
        push    esi ecx
1385
        mov     esi, 0x100000+512*19
1386
.test_short_name_entry:
1387
        cmp     byte [esi+11], 0xF
1388
        jz      .test_short_name_cont
1389
        mov     ecx, 11
1390
        push    esi edi
1391
        repz    cmpsb
1392
        pop     edi esi
1393
        jz      .short_name_found
1394
.test_short_name_cont:
1395
        add     esi, 20h
1396
        cmp     esi, 0x100000+512*33
1397
        jb      .test_short_name_entry
1398
        pop     ecx esi
1399
        jmp     .found
1400
.short_name_found:
1401
        call    fat_next_short_name
1402
        pop     ecx esi
1403
        jnc     .test_short_name_loop
1404
.disk_full:
1405
        add     esp, 12
1406
        pop     edi
1407
        mov     eax, ERROR_DISK_FULL
1408
        xor     ebx, ebx
1409
        ret
1410
.found:
1411
; now find space in directory
1412
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
1413
        mov     al, '~'
1414
        push    ecx edi
1415
        mov     ecx, 8
1416
        repnz   scasb
1417
        push    1
1418
        pop     eax     ; 1 entry
1419
        jnz     .notilde
1420
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
1421
        xor     eax, eax
1422
@@:
1423
        cmp     byte [esi], 0
1424
        jz      @f
1425
        inc     esi
1426
        inc     eax
1427
        jmp     @b
1428
@@:
1429
        sub     esi, eax
1430
        add     eax, 12+13
1431
        mov     ecx, 13
1432
        push    edx
1433
        cdq
1434
        div     ecx
1435
        pop     edx
1436
.notilde:
1437
; find  successive entries in directory
1438
        xor     ecx, ecx
1439
        mov     edi, 0x100000+512*19
1440
.scan_dir:
1441
        cmp     byte [edi], 0
1442
        jz      .free
1443
        cmp     byte [edi], 0xE5
1444
        jz      .free
1445
        xor     ecx, ecx
1446
.scan_cont:
1447
        add     edi, 0x20
1448
        cmp     edi, 0x100000+512*33
1449
        jb      .scan_dir
1450
        pop     edi ecx
1451
        jmp     .disk_full
1452
.free:
1453
        inc     ecx
1454
        cmp     ecx, eax
1455
        jb      .scan_cont
1456
; found!
1457
; calculate name checksum
1458
        push    esi ecx
1459
        mov     esi, [esp+8]
1460
        mov     ecx, 11
1461
        xor     eax, eax
1462
@@:
1463
        ror     al, 1
1464
        add     al, [esi]
1465
        inc     esi
1466
        loop    @b
1467
        pop     ecx esi
1468
; edi points to last entry in free chunk
1469
        dec     ecx
1470
        jz      .nolfn
1471
        push    esi
1472
        push    edi
1473
.writelfn:
1474
        sub     edi, 20h
1475
        push    ecx eax
1476
        mov     eax, [esp+8]
1477
        sub     eax, edi
1478
        shr     eax, 5
1479
        cmp     ecx, 1
1480
        jnz     @f
1481
        or      al, 40h
1482
@@:
1483
        stosb
1484
        mov     cl, 5
1485
        call    .read_symbols
1486
        mov     ax, 0xF
1487
        stosw
1488
        pop     eax
1489
        stosb
1490
        push    eax
1491
        mov     cl, 6
1492
        call    .read_symbols
1493
        xor     eax, eax
1494
        stosw
1495
        mov     cl, 2
1496
        call    .read_symbols
1497
        pop     eax ecx
1498
        sub     edi, 0x20
1499
        loop    .writelfn
1500
        pop     edi
1501
        pop     esi
1502
.nolfn:
1503
        xchg    esi, [esp]
1504
        mov     ecx, 11
1505
        rep     movsb
1506
        mov     word [edi], 20h         ; attributes
1507
        sub     edi, 11
1508
        pop     esi ecx
1509
        add     esp, 12
1510
        mov     byte [edi+13], 0        ; tenths of a second at file creation time
1511
        call    get_time_for_file
1512
        mov     [edi+14], ax            ; creation time
1513
        mov     [edi+22], ax            ; last write time
1514
        call    get_date_for_file
1515
        mov     [edi+16], ax            ; creation date
1516
        mov     [edi+24], ax            ; last write date
1517
        mov     [edi+18], ax            ; last access date
1518
        and     word [edi+20], 0        ; high word of cluster
1519
        and     word [edi+26], 0        ; low word of cluster - to be filled
1520
        and     dword [edi+28], 0       ; file size - to be filled
1521
.doit:
1522
        push    ecx edx
1523
        push    ecx
1524
        push    edi
1525
        add     edi, 26         ; edi points to low word of cluster
1526
        push    edi
1527
        jecxz   .done
1528
        mov     ecx, 2849
1529
        mov     edi, 0x280000
1530
.write_loop:
1531
; allocate new cluster
1532
        xor     eax, eax
1533
        repnz   scasw
1534
        jnz     .disk_full2
1535
        dec     edi
1536
        dec     edi
1537
        lea     eax, [edi-0x280000]
1538
        shr     eax, 1                  ; eax = cluster
1539
        mov     word [edi], 0xFFF       ; mark as last cluster
1540
        xchg    edi, [esp]
1541
        stosw
1542
        pop     edi
1543
        push    edi
1544
        inc     ecx
1545
; write data
1546
        shl     eax, 9
1547
        add     eax, 0x100000+31*512
1548
        mov     ebx, edx
1549
        xchg    eax, ebx
1550
        push    ecx
1551
        mov     ecx, 512
1552
        cmp     dword [esp+12], ecx
1553
        jae     @f
1554
        mov     ecx, [esp+12]
1555
@@:
1556
        call    memmove
1557
        add     edx, ecx
1558
        sub     [esp+12], ecx
1559
        pop     ecx
1560
        jnz     .write_loop
1561
.done:
1562
        mov     ebx, edx
1563
        pop     edi edi ecx edx ecx
1564
        sub     ebx, edx
1565
        mov     [edi+28], ebx
1566
        pop     edi
1567
        xor     eax, eax
1568
        ret
1569
.disk_full2:
1570
        mov     ebx, edx
1571
        pop     edi edi ecx edx ecx
1572
        sub     ebx, edx
1573
        mov     [edi+28], ebx
1574
        pop     edi
1575
        push    ERROR_DISK_FULL
1576
        pop     eax
1577
        ret
1578
 
1579
.read_symbol:
1580
        or      ax, -1
1581
        test    esi, esi
1582
        jz      .retFFFF
1583
        lodsb
1584
        test    al, al
1585
        jnz     ansi2uni_char
1586
        xor     eax, eax
1587
        xor     esi, esi
1588
.retFFFF:
1589
        ret
1590
 
1591
.read_symbols:
1592
        call    .read_symbol
1593
        stosw
1594
        loop    .read_symbols
1595
        ret
1596
 
78 diamond 1597
; \end{diamond}