Subversion Repositories Kolibri OS

Rev

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

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