Subversion Repositories Kolibri OS

Rev

Rev 848 | Details | Compare with Previous | Last modification | View Log | RSS feed

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