Subversion Repositories Kolibri OS

Rev

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

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