Subversion Repositories Kolibri OS

Rev

Rev 593 | Rev 1021 | 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
;;                                                              ;;
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: 766 $
13
 
14
 
5 halyavin 15
; calculate fat chain
1 ha 16
 
5 halyavin 17
calculatefatchain:
18
 
19
   pushad
20
 
766 Rus 21
   mov	esi,RAMDISK+512
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
59
   mov	edi,RAMDISK+512
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
 
766 Rus 75
   cmp	edi,RAMDISK+512+4278	 ;4274 bytes - all used FAT
76
   jb	fcnew2
5 halyavin 77
 
766 Rus 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
 
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
211
	mov    esi,RAMDISK+512*19
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
255
	add    eax,RAMDISK	       ;image base
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
 
766 Rus 307
	mov    edi,RAMDISK+512*18+512  ;Point at directory
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
316
	cmp    edi,RAMDISK+512*33
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:
766 Rus 753
	mov	edi, RAMDISK+512*19
754
	clc
755
	ret
86 diamond 756
ramdisk_root_next:
766 Rus 757
	add	edi, 0x20
758
	cmp	edi, RAMDISK+512*33
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
796
	lea	edi, [eax+(31 shl 9)+RAMDISK]
797
	clc
798
	ret
91 diamond 799
.err2:
766 Rus 800
	pop	ecx
91 diamond 801
.err:
766 Rus 802
	stc
803
	ret
91 diamond 804
ramdisk_notroot_next_write:
766 Rus 805
	test	edi, 0x1FF
806
	jz	ramdisk_notroot_next_sector
91 diamond 807
ramdisk_root_next_write:
766 Rus 808
	ret
91 diamond 809
 
810
ramdisk_notroot_extend_dir:
766 Rus 811
	pusha
812
	xor	eax, eax
813
	mov	edi, RAMDISK_FAT
814
	mov	ecx, 2849
815
	repnz	scasw
816
	jnz	.notfound
817
	mov	word [edi-2], 0xFFF
818
	sub	edi, RAMDISK_FAT
819
	shr	edi, 1
820
	dec	edi
821
	mov	eax, [esp+28]
822
	mov	ecx, [eax]
823
	mov	[RAMDISK_FAT+ecx*2], di
824
	mov	[eax], edi
825
	shl	edi, 9
826
	add	edi, (31 shl 9)+RAMDISK
827
	mov	[esp], edi
828
	xor	eax, eax
829
	mov	ecx, 128
830
	rep	stosd
831
	popa
832
	clc
833
	ret
91 diamond 834
.notfound:
766 Rus 835
	popa
836
	stc
837
	ret
91 diamond 838
 
71 diamond 839
rd_find_lfn:
521 diamond 840
; in: esi+ebp -> name
71 diamond 841
; out: CF=1 - file not found
842
;      else CF=0 and edi->direntry
766 Rus 843
	push	esi edi
844
	push	0
845
	push	ramdisk_root_first
846
	push	ramdisk_root_next
91 diamond 847
.loop:
766 Rus 848
	call	fat_find_lfn
849
	jc	.notfound
850
	cmp	byte [esi], 0
851
	jz	.found
521 diamond 852
.continue:
766 Rus 853
	test	byte [edi+11], 10h
854
	jz	.notfound
855
	movzx	eax, word [edi+26]
856
	mov	[esp+8], eax
857
	mov	dword [esp+4], ramdisk_notroot_first
858
	mov	dword [esp], ramdisk_notroot_next
859
	jmp	.loop
91 diamond 860
.notfound:
766 Rus 861
	add	esp, 12
862
	pop	edi esi
863
	stc
864
	ret
91 diamond 865
.found:
766 Rus 866
	test	ebp, ebp
867
	jz	@f
868
	mov	esi, ebp
869
	xor	ebp, ebp
870
	jmp	.continue
521 diamond 871
@@:
766 Rus 872
	mov	eax, [esp+8]
873
	add	esp, 16 	; CF=0
874
	pop	esi
875
	ret
71 diamond 876
 
877
;----------------------------------------------------------------
878
;
879
;  fs_RamdiskRead - LFN variant for reading sys floppy
880
;
881
;  esi  points to filename
882
;  ebx  pointer to 64-bit number = first wanted byte, 0+
883
;       may be ebx=0 - start from first byte
884
;  ecx  number of bytes to read, 0+
885
;  edx  mem location to return data
886
;
77 diamond 887
;  ret ebx = bytes read or 0xffffffff file not found
71 diamond 888
;      eax = 0 ok read or other = errormsg
889
;
890
;--------------------------------------------------------------
891
fs_RamdiskRead:
766 Rus 892
	cmp	byte [esi], 0
893
	jnz	@f
894
	or	ebx, -1
895
	mov	eax, 10 	; access denied
896
	ret
71 diamond 897
@@:
766 Rus 898
	push	edi
899
	call	rd_find_lfn
900
	jnc	.found
901
	pop	edi
902
	or	ebx, -1
903
	mov	eax, 5		; file not found
904
	ret
71 diamond 905
.found:
766 Rus 906
	test	ebx, ebx
907
	jz	.l1
908
	cmp	dword [ebx+4], 0
909
	jz	@f
910
	xor	ebx, ebx
71 diamond 911
.reteof:
766 Rus 912
	mov	eax, 6		; EOF
913
	pop	edi
914
	ret
71 diamond 915
@@:
766 Rus 916
	mov	ebx, [ebx]
71 diamond 917
.l1:
766 Rus 918
	push	ecx edx
919
	push	0
920
	mov	eax, [edi+28]
921
	sub	eax, ebx
922
	jb	.eof
923
	cmp	eax, ecx
924
	jae	@f
925
	mov	ecx, eax
926
	mov	byte [esp], 6		; EOF
77 diamond 927
@@:
766 Rus 928
	movzx	edi, word [edi+26]	; cluster
71 diamond 929
.new:
766 Rus 930
	jecxz	.done
931
	test	edi, edi
932
	jz	.eof
933
	cmp	edi, 0xFF8
934
	jae	.eof
935
	lea	eax, [edi+31]		; bootsector+2*fat+filenames
936
	shl	eax, 9			; *512
937
	add	eax, RAMDISK	       ; image base
71 diamond 938
; now eax points to data of cluster
766 Rus 939
	sub	ebx, 512
940
	jae	.skip
941
	lea	eax, [eax+ebx+512]
942
	neg	ebx
943
	push	ecx
944
	cmp	ecx, ebx
945
	jbe	@f
946
	mov	ecx, ebx
71 diamond 947
@@:
766 Rus 948
	mov	ebx, edx
949
	call	memmove
950
	add	edx, ecx
951
	sub	[esp], ecx
952
	pop	ecx
953
	xor	ebx, ebx
71 diamond 954
.skip:
766 Rus 955
	movzx	edi, word [edi*2+RAMDISK_FAT]	   ; find next cluster from FAT
956
	jmp	.new
71 diamond 957
.eof:
766 Rus 958
	mov	ebx, edx
959
	pop	eax edx ecx
960
	sub	ebx, edx
961
	jmp	.reteof
71 diamond 962
.done:
766 Rus 963
	mov	ebx, edx
964
	pop	eax edx ecx edi
965
	sub	ebx, edx
966
	ret
71 diamond 967
 
75 diamond 968
;----------------------------------------------------------------
969
;
970
;  fs_RamdiskReadFolder - LFN variant for reading sys floppy folder
971
;
972
;  esi  points to filename; only root is folder on ramdisk
78 diamond 973
;  ebx  pointer to structure 32-bit number = first wanted block
974
;                          & flags (bitfields)
975
; flags: bit 0: 0=ANSI names, 1=UNICODE names
75 diamond 976
;  ecx  number of blocks to read, 0+
977
;  edx  mem location to return data
978
;
979
;  ret ebx = size or 0xffffffff file not found
980
;      eax = 0 ok read or other = errormsg
981
;
982
;--------------------------------------------------------------
983
fs_RamdiskReadFolder:
766 Rus 984
	push	edi
985
	cmp	byte [esi], 0
986
	jz	.root
987
	call	rd_find_lfn
988
	jnc	.found
989
	pop	edi
990
	or	ebx, -1
991
	mov	eax, ERROR_FILE_NOT_FOUND
992
	ret
91 diamond 993
.found:
766 Rus 994
	test	byte [edi+11], 0x10
995
	jnz	.found_dir
996
	pop	edi
997
	or	ebx, -1
998
	mov	eax, ERROR_ACCESS_DENIED
999
	ret
91 diamond 1000
.found_dir:
766 Rus 1001
	movzx	eax, word [edi+26]
1002
	add	eax, 31
1003
	push	0
1004
	jmp	.doit
91 diamond 1005
.root:
766 Rus 1006
	mov	eax, 19
1007
	push	14
91 diamond 1008
.doit:
766 Rus 1009
	push	esi ecx ebp
1010
	sub	esp, 262*2	; reserve space for LFN
1011
	mov	ebp, esp
1012
	push	dword [ebx+4]	; for fat_get_name: read ANSI/UNICODE names
1013
	mov	ebx, [ebx]
75 diamond 1014
; init header
766 Rus 1015
	push	eax ecx
1016
	mov	edi, edx
1017
	mov	ecx, 32/4
1018
	xor	eax, eax
1019
	rep	stosd
1020
	mov	byte [edx], 1	; version
1021
	pop	ecx eax
1022
	mov	esi, edi	; esi points to block of data of folder entry (BDFE)
91 diamond 1023
.main_loop:
766 Rus 1024
	mov	edi, eax
1025
	shl	edi, 9
1026
	add	edi, RAMDISK
1027
	push	eax
75 diamond 1028
.l1:
766 Rus 1029
	call	fat_get_name
1030
	jc	.l2
1031
	cmp	byte [edi+11], 0xF
1032
	jnz	.do_bdfe
1033
	add	edi, 0x20
1034
	test	edi, 0x1FF
1035
	jnz	.do_bdfe
1036
	pop	eax
1037
	inc	eax
1038
	dec	byte [esp+262*2+16]
1039
	jz	.done
1040
	jns	@f
91 diamond 1041
; read next sector from FAT
766 Rus 1042
	mov	eax, [(eax-31-1)*2+RAMDISK_FAT]
1043
	and	eax, 0xFFF
1044
	cmp	eax, 0xFF8
1045
	jae	.done
1046
	add	eax, 31
1047
	mov	byte [esp+262*2+16], 0
75 diamond 1048
@@:
766 Rus 1049
	mov	edi, eax
1050
	shl	edi, 9
1051
	add	edi, RAMDISK
1052
	push	eax
91 diamond 1053
.do_bdfe:
766 Rus 1054
	inc	dword [edx+8]	; new file found
1055
	dec	ebx
1056
	jns	.l2
1057
	dec	ecx
1058
	js	.l2
1059
	inc	dword [edx+4]  ; new file block copied
1060
	call	fat_entry_to_bdfe
75 diamond 1061
.l2:
766 Rus 1062
	add	edi, 0x20
1063
	test	edi, 0x1FF
1064
	jnz	.l1
1065
	pop	eax
1066
	inc	eax
1067
	dec	byte [esp+262*2+16]
1068
	jz	.done
1069
	jns	@f
91 diamond 1070
; read next sector from FAT
766 Rus 1071
	mov	eax, [(eax-31-1)*2+RAMDISK_FAT]
1072
	and	eax, 0xFFF
1073
	cmp	eax, 0xFF8
1074
	jae	.done
1075
	add	eax, 31
1076
	mov	byte [esp+262*2+16], 0
91 diamond 1077
@@:
766 Rus 1078
	jmp	.main_loop
91 diamond 1079
.done:
766 Rus 1080
	add	esp, 262*2+4
1081
	pop	ebp
1082
	mov	ebx, [edx+4]
1083
	xor	eax, eax
1084
	dec	ecx
1085
	js	@f
1086
	mov	al, ERROR_END_OF_FILE
75 diamond 1087
@@:
766 Rus 1088
	pop	ecx esi edi edi
1089
	ret
75 diamond 1090
 
83 diamond 1091
iglobal
1092
label fat_legal_chars byte
1093
; 0 = not allowed
1094
; 1 = allowed only in long names
1095
; 3 = allowed
766 Rus 1096
	times 32 db 0
83 diamond 1097
;                 ! " # $ % & ' ( ) * + , - . /
766 Rus 1098
	db	1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0
83 diamond 1099
;               0 1 2 3 4 5 6 7 8 9 : ; < = > ?
766 Rus 1100
	db	3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0
83 diamond 1101
;               @ A B C D E F G H I J K L M N O
766 Rus 1102
	db	3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
83 diamond 1103
;               P Q R S T U V W X Y Z [ \ ] ^ _
766 Rus 1104
	db	3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3
83 diamond 1105
;               ` a b c d e f g h i j k l m n o
766 Rus 1106
	db	3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
83 diamond 1107
;               p q r s t u v w x y z { | } ~
766 Rus 1108
	db	3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0
83 diamond 1109
endg
1110
 
1111
fat_name_is_legal:
1112
; in: esi->(long) name
1113
; out: CF set <=> legal
1114
; destroys eax
766 Rus 1115
	push	esi
1116
	xor	eax, eax
83 diamond 1117
@@:
766 Rus 1118
	lodsb
1119
	test	al, al
1120
	jz	.done
1121
	cmp	al, 80h
1122
	jae	.big
1123
	test	[fat_legal_chars+eax], 1
1124
	jnz	@b
83 diamond 1125
.err:
766 Rus 1126
	pop	esi
1127
	clc
1128
	ret
83 diamond 1129
.big:
1130
; 0x80-0xAF, 0xE0-0xEF
766 Rus 1131
	cmp	al, 0xB0
1132
	jb	@b
1133
	cmp	al, 0xE0
1134
	jb	.err
1135
	cmp	al, 0xF0
1136
	jb	@b
1137
	jmp	.err
83 diamond 1138
.done:
766 Rus 1139
	sub	esi, [esp]
1140
	cmp	esi, 257
1141
	pop	esi
1142
	ret
83 diamond 1143
 
1144
fat_next_short_name:
1145
; in: edi->8+3 name
1146
; out: name corrected
1147
;      CF=1 <=> error
766 Rus 1148
	pushad
1149
	mov	ecx, 8
1150
	mov	al, '~'
1151
	std
1152
	push	edi
1153
	add	edi, 7
1154
	repnz	scasb
1155
	pop	edi
1156
	cld
1157
	jz	.tilde
83 diamond 1158
; tilde is not found, insert "~1" at end
766 Rus 1159
	add	edi, 6
1160
	cmp	word [edi], '  '
1161
	jnz	.insert_tilde
1162
@@:	dec	edi
1163
	cmp	byte [edi], ' '
1164
	jz	@b
1165
	inc	edi
83 diamond 1166
.insert_tilde:
766 Rus 1167
	mov	word [edi], '~1'
1168
	popad
1169
	clc
1170
	ret
83 diamond 1171
.tilde:
766 Rus 1172
	push	edi
1173
	add	edi, 7
1174
	xor	ecx, ecx
83 diamond 1175
@@:
1176
; after tilde may be only digits and trailing spaces
766 Rus 1177
	cmp	byte [edi], '~'
1178
	jz	.break
1179
	cmp	byte [edi], ' '
1180
	jz	.space
1181
	cmp	byte [edi], '9'
1182
	jnz	.found
1183
	dec	edi
1184
	jmp	@b
83 diamond 1185
.space:
766 Rus 1186
	dec	edi
1187
	inc	ecx
1188
	jmp	@b
83 diamond 1189
.found:
766 Rus 1190
	inc	byte [edi]
1191
	add	dword [esp], 8
1192
	jmp	.zerorest
83 diamond 1193
.break:
766 Rus 1194
	jecxz	.noplace
1195
	inc	edi
1196
	mov	al, '1'
83 diamond 1197
@@:
766 Rus 1198
	xchg	al, [edi]
1199
	inc	edi
1200
	cmp	al, ' '
1201
	mov	al, '0'
1202
	jnz	@b
466 diamond 1203
.succ:
766 Rus 1204
	pop	edi
1205
	popad
1206
	clc
1207
	ret
83 diamond 1208
.noplace:
766 Rus 1209
	dec	edi
1210
	cmp	edi, [esp]
1211
	jz	.err
1212
	add	dword [esp], 8
1213
	mov	word [edi], '~1'
1214
	inc	edi
1215
	inc	edi
83 diamond 1216
@@:
766 Rus 1217
	mov	byte [edi], '0'
466 diamond 1218
.zerorest:
766 Rus 1219
	inc	edi
1220
	cmp	edi, [esp]
1221
	jb	@b
1222
	pop	edi
1223
	popad
1224
	;clc    ; automatically
1225
	ret
83 diamond 1226
.err:
766 Rus 1227
	pop	edi
1228
	popad
1229
	stc
1230
	ret
83 diamond 1231
 
1232
fat_gen_short_name:
1233
; in: esi->long name
1234
;     edi->buffer (8+3=11 chars)
1235
; out: buffer filled
766 Rus 1236
	pushad
1237
	mov	eax, '    '
1238
	push	edi
1239
	stosd
1240
	stosd
1241
	stosd
1242
	pop	edi
1243
	xor	eax, eax
1244
	push	8
1245
	pop	ebx
1246
	lea	ecx, [edi+8]
83 diamond 1247
.loop:
766 Rus 1248
	lodsb
1249
	test	al, al
1250
	jz	.done
1251
	call	char_toupper
1252
	cmp	al, ' '
1253
	jz	.space
1254
	cmp	al, 80h
1255
	ja	.big
1256
	test	[fat_legal_chars+eax], 2
1257
	jnz	.symbol
83 diamond 1258
.inv_symbol:
766 Rus 1259
	mov	al, '_'
1260
	or	bh, 1
83 diamond 1261
.symbol:
766 Rus 1262
	cmp	al, '.'
1263
	jz	.dot
83 diamond 1264
.normal_symbol:
766 Rus 1265
	dec	bl
1266
	jns	.store
1267
	mov	bl, 0
83 diamond 1268
.space:
766 Rus 1269
	or	bh, 1
1270
	jmp	.loop
83 diamond 1271
.store:
766 Rus 1272
	stosb
1273
	jmp	.loop
83 diamond 1274
.big:
766 Rus 1275
	cmp	al, 0xB0
1276
	jb	.normal_symbol
1277
	cmp	al, 0xE0
1278
	jb	.inv_symbol
1279
	cmp	al, 0xF0
1280
	jb	.normal_symbol
1281
	jmp	.inv_symbol
83 diamond 1282
.dot:
766 Rus 1283
	test	bh, 2
1284
	jz	.firstdot
1285
	pop	ebx
1286
	add	ebx, edi
1287
	sub	ebx, ecx
1288
	push	ebx
1289
	cmp	ebx, ecx
1290
	jb	@f
1291
	pop	ebx
1292
	push	ecx
527 diamond 1293
@@:
766 Rus 1294
	cmp	edi, ecx
1295
	jbe	.skip
83 diamond 1296
@@:
766 Rus 1297
	dec	edi
1298
	mov	al, [edi]
1299
	dec	ebx
1300
	mov	[ebx], al
1301
	mov	byte [edi], ' '
1302
	cmp	edi, ecx
1303
	ja	@b
83 diamond 1304
.skip:
766 Rus 1305
	mov	bh, 3
1306
	jmp	@f
83 diamond 1307
.firstdot:
766 Rus 1308
	cmp	bl, 8
1309
	jz	.space
1310
	push	edi
1311
	or	bh, 2
83 diamond 1312
@@:
766 Rus 1313
	mov	edi, ecx
1314
	mov	bl, 3
1315
	jmp	.loop
83 diamond 1316
.done:
766 Rus 1317
	test	bh, 2
1318
	jz	@f
1319
	pop	edi
83 diamond 1320
@@:
766 Rus 1321
	lea	edi, [ecx-8]
1322
	test	bh, 1
1323
	jz	@f
1324
	call	fat_next_short_name
83 diamond 1325
@@:
766 Rus 1326
	popad
1327
	ret
83 diamond 1328
 
1329
;----------------------------------------------------------------
1330
;
321 diamond 1331
;  fs_RamdiskRewrite - LFN variant for writing ramdisk
1332
;  fs_RamdiskCreateFolder - create folder on ramdisk
83 diamond 1333
;
321 diamond 1334
;  esi  points to file/folder name
83 diamond 1335
;  ebx  ignored (reserved)
321 diamond 1336
;  ecx  number of bytes to write, 0+ (ignored for folders)
1337
;  edx  mem location to data (ignored for folders)
83 diamond 1338
;
1339
;  ret ebx = number of written bytes
1340
;      eax = 0 ok read or other = errormsg
1341
;
1342
;--------------------------------------------------------------
1343
@@:
766 Rus 1344
	mov	eax, ERROR_ACCESS_DENIED
1345
	xor	ebx, ebx
1346
	ret
83 diamond 1347
 
321 diamond 1348
fs_RamdiskCreateFolder:
766 Rus 1349
	mov	al, 1		; create folder
1350
	jmp	fs_RamdiskRewrite.common
321 diamond 1351
 
83 diamond 1352
fs_RamdiskRewrite:
766 Rus 1353
	xor	eax, eax	; create file
321 diamond 1354
.common:
766 Rus 1355
	cmp	byte [esi], 0
1356
	jz	@b
1357
	pushad
1358
	xor	edi, edi
1359
	push	esi
1360
	test	ebp, ebp
1361
	jz	@f
1362
	mov	esi, ebp
83 diamond 1363
@@:
766 Rus 1364
	lodsb
1365
	test	al, al
1366
	jz	@f
1367
	cmp	al, '/'
1368
	jnz	@b
1369
	lea	edi, [esi-1]
1370
	jmp	@b
91 diamond 1371
@@:
766 Rus 1372
	pop	esi
1373
	test	edi, edi
1374
	jnz	.noroot
1375
	test	ebp, ebp
1376
	jnz	.hasebp
1377
	push	ramdisk_root_extend_dir
1378
	push	ramdisk_root_next_write
1379
	push	edi
1380
	push	ramdisk_root_first
1381
	push	ramdisk_root_next
1382
	jmp	.common1
521 diamond 1383
.hasebp:
766 Rus 1384
	mov	eax, ERROR_ACCESS_DENIED
1385
	cmp	byte [ebp], 0
1386
	jz	.ret1
1387
	push	ebp
1388
	xor	ebp, ebp
1389
	call	rd_find_lfn
1390
	pop	esi
1391
	jc	.notfound0
1392
	jmp	.common0
91 diamond 1393
.noroot:
766 Rus 1394
	mov	eax, ERROR_ACCESS_DENIED
1395
	cmp	byte [edi+1], 0
1396
	jz	.ret1
91 diamond 1397
; check existence
766 Rus 1398
	mov	byte [edi], 0
1399
	push	edi
1400
	call	rd_find_lfn
1401
	pop	esi
1402
	mov	byte [esi], '/'
1403
	jnc	@f
521 diamond 1404
.notfound0:
766 Rus 1405
	mov	eax, ERROR_FILE_NOT_FOUND
91 diamond 1406
.ret1:
766 Rus 1407
	mov	[esp+28], eax
1408
	popad
1409
	xor	ebx, ebx
1410
	ret
83 diamond 1411
@@:
766 Rus 1412
	inc	esi
521 diamond 1413
.common0:
766 Rus 1414
	test	byte [edi+11], 0x10	; must be directory
1415
	mov	eax, ERROR_ACCESS_DENIED
1416
	jz	.ret1
1417
	movzx	ebp, word [edi+26]	; ebp=cluster
1418
	mov	eax, ERROR_FAT_TABLE
1419
	cmp	ebp, 2
1420
	jb	.ret1
1421
	cmp	ebp, 2849
1422
	jae	.ret1
1423
	push	ramdisk_notroot_extend_dir
1424
	push	ramdisk_notroot_next_write
1425
	push	ebp
1426
	push	ramdisk_notroot_first
1427
	push	ramdisk_notroot_next
91 diamond 1428
.common1:
766 Rus 1429
	call	fat_find_lfn
1430
	jc	.notfound
321 diamond 1431
; found
766 Rus 1432
	test	byte [edi+11], 10h
1433
	jz	.exists_file
321 diamond 1434
; found directory; if we are creating directory, return OK,
1435
;                  if we are creating file, say "access denied"
766 Rus 1436
	add	esp, 20
1437
	popad
1438
	test	al, al
1439
	mov	eax, ERROR_ACCESS_DENIED
1440
	jz	@f
1441
	mov	al, 0
321 diamond 1442
@@:
766 Rus 1443
	xor	ebx, ebx
1444
	ret
321 diamond 1445
.exists_file:
1446
; found file; if we are creating directory, return "access denied",
1447
;             if we are creating file, delete existing file and continue
766 Rus 1448
	cmp	byte [esp+20+28], 0
1449
	jz	@f
1450
	add	esp, 20
1451
	popad
1452
	mov	eax, ERROR_ACCESS_DENIED
1453
	xor	ebx, ebx
1454
	ret
91 diamond 1455
@@:
1456
; delete FAT chain
766 Rus 1457
	push	edi
1458
	xor	eax, eax
1459
	mov	dword [edi+28], eax	; zero size
1460
	xchg	ax, word [edi+26]	; start cluster
1461
	test	eax, eax
1462
	jz	.done1
83 diamond 1463
@@:
766 Rus 1464
	cmp	eax, 0xFF8
1465
	jae	.done1
1466
	lea	edi, [RAMDISK_FAT + eax*2] ; position in FAT
1467
	xor	eax, eax
1468
	xchg	ax, [edi]
1469
	jmp	@b
83 diamond 1470
.done1:
766 Rus 1471
	pop	edi
1472
	call	get_time_for_file
1473
	mov	[edi+22], ax
1474
	call	get_date_for_file
1475
	mov	[edi+24], ax
1476
	mov	[edi+18], ax
1477
	or	byte [edi+11], 20h	; set 'archive' attribute
1478
	jmp	.doit
83 diamond 1479
.notfound:
1480
; file is not found; generate short name
766 Rus 1481
	call	fat_name_is_legal
1482
	jc	@f
1483
	add	esp, 20
1484
	popad
1485
	mov	eax, ERROR_FILE_NOT_FOUND
1486
	xor	ebx, ebx
1487
	ret
83 diamond 1488
@@:
766 Rus 1489
	sub	esp, 12
1490
	mov	edi, esp
1491
	call	fat_gen_short_name
83 diamond 1492
.test_short_name_loop:
766 Rus 1493
	push	esi edi ecx
1494
	mov	esi, edi
1495
	lea	eax, [esp+12+12+8]
1496
	mov	[eax], ebp
1497
	call	dword [eax-4]
1498
	jc	.found
83 diamond 1499
.test_short_name_entry:
766 Rus 1500
	cmp	byte [edi+11], 0xF
1501
	jz	.test_short_name_cont
1502
	mov	ecx, 11
1503
	push	esi edi
1504
	repz	cmpsb
1505
	pop	edi esi
1506
	jz	.short_name_found
83 diamond 1507
.test_short_name_cont:
766 Rus 1508
	lea	eax, [esp+12+12+8]
1509
	call	dword [eax-8]
1510
	jnc	.test_short_name_entry
1511
	jmp	.found
83 diamond 1512
.short_name_found:
766 Rus 1513
	pop	ecx edi esi
1514
	call	fat_next_short_name
1515
	jnc	.test_short_name_loop
83 diamond 1516
.disk_full:
766 Rus 1517
	add	esp, 12+20
1518
	popad
1519
	mov	eax, ERROR_DISK_FULL
1520
	xor	ebx, ebx
1521
	ret
83 diamond 1522
.found:
766 Rus 1523
	pop	ecx edi esi
83 diamond 1524
; now find space in directory
1525
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
766 Rus 1526
	mov	al, '~'
1527
	push	ecx edi
1528
	mov	ecx, 8
1529
	repnz	scasb
1530
	push	1
1531
	pop	eax	; 1 entry
1532
	jnz	.notilde
83 diamond 1533
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
766 Rus 1534
	xor	eax, eax
83 diamond 1535
@@:
766 Rus 1536
	cmp	byte [esi], 0
1537
	jz	@f
1538
	inc	esi
1539
	inc	eax
1540
	jmp	@b
83 diamond 1541
@@:
766 Rus 1542
	sub	esi, eax
1543
	add	eax, 12+13
1544
	mov	ecx, 13
1545
	push	edx
1546
	cdq
1547
	div	ecx
1548
	pop	edx
83 diamond 1549
.notilde:
766 Rus 1550
	push	-1
1551
	push	-1
83 diamond 1552
; find  successive entries in directory
766 Rus 1553
	xor	ecx, ecx
1554
	push	eax
1555
	lea	eax, [esp+12+8+12+8]
1556
	mov	[eax], ebp
1557
	call	dword [eax-4]
1558
	pop	eax
83 diamond 1559
.scan_dir:
766 Rus 1560
	cmp	byte [edi], 0
1561
	jz	.free
1562
	cmp	byte [edi], 0xE5
1563
	jz	.free
1564
	xor	ecx, ecx
83 diamond 1565
.scan_cont:
766 Rus 1566
	push	eax
1567
	lea	eax, [esp+12+8+12+8]
1568
	call	dword [eax-8]
1569
	pop	eax
1570
	jnc	.scan_dir
1571
	push	eax
1572
	lea	eax, [esp+12+8+12+8]
1573
	call	dword [eax+8]		; extend directory
1574
	pop	eax
1575
	jnc	.scan_dir
1576
	add	esp, 8+8+12+20
1577
	popad
1578
	mov	eax, ERROR_DISK_FULL
1579
	xor	ebx, ebx
1580
	ret
83 diamond 1581
.free:
766 Rus 1582
	test	ecx, ecx
1583
	jnz	@f
1584
	mov	[esp], edi
1585
	mov	ecx, [esp+8+8+12+8]
1586
	mov	[esp+4], ecx
1587
	xor	ecx, ecx
91 diamond 1588
@@:
766 Rus 1589
	inc	ecx
1590
	cmp	ecx, eax
1591
	jb	.scan_cont
83 diamond 1592
; found!
1593
; calculate name checksum
766 Rus 1594
	push	esi ecx
1595
	mov	esi, [esp+8+8]
1596
	mov	ecx, 11
1597
	xor	eax, eax
83 diamond 1598
@@:
766 Rus 1599
	ror	al, 1
1600
	add	al, [esi]
1601
	inc	esi
1602
	loop	@b
1603
	pop	ecx esi
1604
	pop	edi
1605
	pop	dword [esp+8+12+8]
83 diamond 1606
; edi points to last entry in free chunk
766 Rus 1607
	dec	ecx
1608
	jz	.nolfn
1609
	push	esi
1610
	push	eax
1611
	mov	al, 40h
83 diamond 1612
.writelfn:
766 Rus 1613
	or	al, cl
1614
	mov	esi, [esp+4]
1615
	push	ecx
1616
	dec	ecx
1617
	imul	ecx, 13
1618
	add	esi, ecx
1619
	stosb
1620
	mov	cl, 5
1621
	call	.read_symbols
1622
	mov	ax, 0xF
1623
	stosw
1624
	mov	al, [esp+4]
1625
	stosb
1626
	mov	cl, 6
1627
	call	.read_symbols
1628
	xor	eax, eax
1629
	stosw
1630
	mov	cl, 2
1631
	call	.read_symbols
1632
	pop	ecx
1633
	lea	eax, [esp+8+8+12+8]
1634
	call	dword [eax+4]	; next write
1635
	xor	eax, eax
1636
	loop	.writelfn
1637
	pop	eax
1638
	pop	esi
83 diamond 1639
.nolfn:
766 Rus 1640
	xchg	esi, [esp]
1641
	mov	ecx, 11
1642
	rep	movsb
1643
	mov	word [edi], 20h 	; attributes
1644
	sub	edi, 11
1645
	pop	esi ecx
1646
	add	esp, 12
1647
	mov	byte [edi+13], 0	; tenths of a second at file creation time
1648
	call	get_time_for_file
1649
	mov	[edi+14], ax		; creation time
1650
	mov	[edi+22], ax		; last write time
1651
	call	get_date_for_file
1652
	mov	[edi+16], ax		; creation date
1653
	mov	[edi+24], ax		; last write date
1654
	mov	[edi+18], ax		; last access date
1655
	and	word [edi+20], 0	; high word of cluster
1656
	and	word [edi+26], 0	; low word of cluster - to be filled
1657
	and	dword [edi+28], 0	; file size - to be filled
1658
	cmp	byte [esp+20+28], 0
1659
	jz	.doit
321 diamond 1660
; create directory
766 Rus 1661
	mov	byte [edi+11], 10h	   ; attributes: folder
1662
	mov	ecx, 32*2
1663
	mov	edx, edi
83 diamond 1664
.doit:
766 Rus 1665
	push	edx
1666
	push	ecx
1667
	push	edi
1668
	add	edi, 26 	; edi points to low word of cluster
1669
	push	edi
1670
	jecxz	.done
1671
	mov	ecx, 2849
1672
	mov	edi, RAMDISK_FAT
83 diamond 1673
.write_loop:
1674
; allocate new cluster
766 Rus 1675
	xor	eax, eax
1676
	repnz	scasw
1677
	jnz	.disk_full2
1678
	dec	edi
1679
	dec	edi
465 serge 1680
 
1681
    ;    lea     eax, [edi-(RAMDISK_FAT)]
1682
 
766 Rus 1683
	mov eax, edi
1684
	sub eax, RAMDISK_FAT
465 serge 1685
 
766 Rus 1686
	shr	eax, 1			; eax = cluster
1687
	mov	word [edi], 0xFFF	; mark as last cluster
1688
	xchg	edi, [esp]
1689
	stosw
1690
	pop	edi
1691
	push	edi
1692
	inc	ecx
83 diamond 1693
; write data
766 Rus 1694
	cmp	byte [esp+16+20+28], 0
1695
	jnz	.writedir
1696
	shl	eax, 9
1697
	add	eax, RAMDISK+31*512
321 diamond 1698
.writefile:
766 Rus 1699
	mov	ebx, edx
1700
	xchg	eax, ebx
1701
	push	ecx
1702
	mov	ecx, 512
1703
	cmp	dword [esp+12], ecx
1704
	jae	@f
1705
	mov	ecx, [esp+12]
83 diamond 1706
@@:
766 Rus 1707
	call	memmove
1708
	add	edx, ecx
1709
	sub	[esp+12], ecx
1710
	pop	ecx
1711
	jnz	.write_loop
83 diamond 1712
.done:
766 Rus 1713
	mov	ebx, edx
1714
	pop	edi edi ecx edx
1715
	sub	ebx, edx
1716
	mov	[edi+28], ebx
1717
	add	esp, 20
1718
	mov	[esp+16], ebx
1719
	popad
1720
	xor	eax, eax
1721
	ret
83 diamond 1722
.disk_full2:
766 Rus 1723
	mov	ebx, edx
1724
	pop	edi edi ecx edx
1725
	sub	ebx, edx
1726
	mov	[edi+28], ebx
1727
	add	esp, 20
1728
	mov	[esp+16], ebx
1729
	popad
1730
	push	ERROR_DISK_FULL
1731
	pop	eax
1732
	ret
321 diamond 1733
.writedir:
766 Rus 1734
	mov	edi, eax
1735
	shl	edi, 9
1736
	add	edi, RAMDISK+31*512
1737
	mov	esi, edx
1738
	mov	ecx, 32/4
1739
	push	ecx
1740
	rep	movsd
1741
	mov	dword [edi-32], '.   '
1742
	mov	dword [edi-32+4], '    '
1743
	mov	dword [edi-32+8], '    '
1744
	mov	byte [edi-32+11], 10h
1745
	mov	word [edi-32+26], ax
1746
	mov	esi, edx
1747
	pop	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	eax, [esp+16+8]
1754
	mov	word [edi-32+26], ax
1755
	xor	eax, eax
1756
	mov	ecx, (512-32*2)/4
1757
	rep	stosd
1758
	pop	edi edi ecx edx
1759
	add	esp, 20
1760
	popad
1761
	xor	eax, eax
1762
	xor	ebx, ebx
1763
	ret
83 diamond 1764
 
1765
.read_symbol:
766 Rus 1766
	or	ax, -1
1767
	test	esi, esi
1768
	jz	.retFFFF
1769
	lodsb
1770
	test	al, al
1771
	jnz	ansi2uni_char
1772
	xor	eax, eax
1773
	xor	esi, esi
83 diamond 1774
.retFFFF:
766 Rus 1775
	ret
83 diamond 1776
 
1777
.read_symbols:
766 Rus 1778
	call	.read_symbol
1779
	stosw
1780
	loop	.read_symbols
1781
	ret
83 diamond 1782
 
131 diamond 1783
;----------------------------------------------------------------
1784
;
1785
;  fs_RamdiskWrite - LFN variant for writing to sys floppy
1786
;
1787
;  esi  points to filename
1788
;  ebx  pointer to 64-bit number = first wanted byte, 0+
1789
;       may be ebx=0 - start from first byte
1790
;  ecx  number of bytes to write, 0+
1791
;  edx  mem location to data
1792
;
1793
;  ret ebx = bytes written (maybe 0)
1794
;      eax = 0 ok write or other = errormsg
1795
;
1796
;--------------------------------------------------------------
1797
@@:
766 Rus 1798
	push	ERROR_ACCESS_DENIED
131 diamond 1799
fs_RamdiskWrite.ret0:
766 Rus 1800
	pop	eax
1801
	xor	ebx, ebx
1802
	ret
131 diamond 1803
 
1804
fs_RamdiskWrite:
766 Rus 1805
	cmp	byte [esi], 0
1806
	jz	@b
1807
	pushad
1808
	call	rd_find_lfn
1809
	jnc	.found
1810
	popad
1811
	push	ERROR_FILE_NOT_FOUND
1812
	jmp	.ret0
131 diamond 1813
.found:
1814
; must not be directory
766 Rus 1815
	test	byte [edi+11], 10h
1816
	jz	@f
1817
	popad
1818
	push	ERROR_ACCESS_DENIED
1819
	jmp	.ret0
131 diamond 1820
@@:
1821
; FAT does not support files larger than 4GB
766 Rus 1822
	test	ebx, ebx
1823
	jz	.l1
1824
	cmp	dword [ebx+4], 0
1825
	jz	@f
131 diamond 1826
.eof:
766 Rus 1827
	popad
1828
	push	ERROR_END_OF_FILE
1829
	jmp	.ret0
131 diamond 1830
@@:
766 Rus 1831
	mov	ebx, [ebx]
131 diamond 1832
.l1:
1833
; now edi points to direntry, ebx=start byte to write,
1834
; ecx=number of bytes to write, edx=data pointer
766 Rus 1835
	call	fat_update_datetime
131 diamond 1836
 
1837
; extend file if needed
766 Rus 1838
	add	ecx, ebx
1839
	jc	.eof	; FAT does not support files larger than 4GB
1840
	push	0	; return value=0
1841
	cmp	ecx, [edi+28]
1842
	jbe	.length_ok
1843
	cmp	ecx, ebx
1844
	jz	.length_ok
1845
	call	ramdisk_extend_file
1846
	jnc	.length_ok
131 diamond 1847
; ramdisk_extend_file can return two error codes: FAT table error or disk full.
1848
; First case is fatal error, in second case we may write some data
766 Rus 1849
	mov	[esp], eax
1850
	cmp	al, ERROR_DISK_FULL
1851
	jz	.disk_full
1852
	pop	eax
1853
	mov	[esp+28], eax
1854
	popad
1855
	xor	ebx, ebx
1856
	ret
131 diamond 1857
.disk_full:
1858
; correct number of bytes to write
766 Rus 1859
	mov	ecx, [edi+28]
1860
	cmp	ecx, ebx
1861
	ja	.length_ok
131 diamond 1862
.ret:
766 Rus 1863
	pop	eax
1864
	mov	[esp+28], eax	; eax=return value
1865
	sub	edx, [esp+20]
1866
	mov	[esp+16], edx	; ebx=number of written bytes
1867
	popad
1868
	ret
131 diamond 1869
.length_ok:
1870
; now ebx=start pos, ecx=end pos, both lie inside file
766 Rus 1871
	sub	ecx, ebx
1872
	jz	.ret
1873
	movzx	edi, word [edi+26]	; starting cluster
131 diamond 1874
.write_loop:
766 Rus 1875
	sub	ebx, 0x200
1876
	jae	.next_cluster
1877
	push	ecx
1878
	neg	ebx
1879
	cmp	ecx, ebx
1880
	jbe	@f
1881
	mov	ecx, ebx
131 diamond 1882
@@:
766 Rus 1883
	mov	eax, edi
1884
	shl	eax, 9
1885
	add	eax, RAMDISK+31*512+0x200
1886
	sub	eax, ebx
1887
	mov	ebx, eax
1888
	mov	eax, edx
1889
	call	memmove
1890
	xor	ebx, ebx
1891
	add	edx, ecx
1892
	sub	[esp], ecx
1893
	pop	ecx
1894
	jz	.ret
131 diamond 1895
.next_cluster:
766 Rus 1896
	movzx	edi, word [edi*2+RAMDISK_FAT]
1897
	jmp	.write_loop
131 diamond 1898
 
1899
ramdisk_extend_file.zero_size:
766 Rus 1900
	xor	eax, eax
1901
	jmp	ramdisk_extend_file.start_extend
131 diamond 1902
 
1903
; extends file on ramdisk to given size, new data area is filled by 0
1904
; in: edi->direntry, ecx=new size
133 diamond 1905
; out: CF=0 => OK, eax=0
131 diamond 1906
;      CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL)
1907
ramdisk_extend_file:
766 Rus 1908
	push	ecx
131 diamond 1909
; find the last cluster of file
766 Rus 1910
	movzx	eax, word [edi+26]	; first cluster
1911
	mov	ecx, [edi+28]
1912
	jecxz	.zero_size
131 diamond 1913
@@:
766 Rus 1914
	sub	ecx, 0x200
1915
	jbe	@f
1916
	mov	eax, [eax*2+RAMDISK_FAT]
1917
	and	eax, 0xFFF
1918
	jz	.fat_err
1919
	cmp	eax, 0xFF8
1920
	jb	@b
131 diamond 1921
.fat_err:
766 Rus 1922
	pop	ecx
1923
	push	ERROR_FAT_TABLE
1924
	pop	eax
1925
	stc
1926
	ret
131 diamond 1927
@@:
766 Rus 1928
	push	eax
1929
	mov	eax, [eax*2+RAMDISK_FAT]
1930
	and	eax, 0xFFF
1931
	cmp	eax, 0xFF8
1932
	pop	eax
1933
	jb	.fat_err
131 diamond 1934
; set length to full number of sectors and make sure that last sector is zero-padded
766 Rus 1935
	sub	[edi+28], ecx
1936
	push	eax edi
1937
	mov	edi, eax
1938
	shl	edi, 9
1939
	lea	edi, [edi+RAMDISK+31*512+0x200+ecx]
1940
	neg	ecx
1941
	xor	eax, eax
1942
	rep	stosb
1943
	pop	edi eax
131 diamond 1944
.start_extend:
766 Rus 1945
	pop	ecx
131 diamond 1946
; now do extend
766 Rus 1947
	push	edx esi
1948
	mov	esi, RAMDISK_FAT+2*2	   ; start scan from cluster 2
1949
	mov	edx, 2847		; number of clusters to scan
131 diamond 1950
.extend_loop:
766 Rus 1951
	cmp	[edi+28], ecx
1952
	jae	.extend_done
131 diamond 1953
; add new sector
766 Rus 1954
	push	ecx
1955
	mov	ecx, edx
1956
	push	edi
1957
	mov	edi, esi
1958
	jecxz	.disk_full
1959
	push	eax
1960
	xor	eax, eax
1961
	repnz	scasw
1962
	pop	eax
1963
	jnz	.disk_full
1964
	mov	word [edi-2], 0xFFF
1965
	mov	esi, edi
1966
	mov	edx, ecx
1967
	sub	edi, RAMDISK_FAT
1968
	shr	edi, 1
1969
	dec	edi	; now edi=new cluster
1970
	test	eax, eax
1971
	jz	.first_cluster
1972
	mov	[RAMDISK_FAT+eax*2], di
1973
	jmp	@f
131 diamond 1974
.first_cluster:
766 Rus 1975
	pop	eax	; eax->direntry
1976
	push	eax
1977
	mov	[eax+26], di
131 diamond 1978
@@:
766 Rus 1979
	push	edi
1980
	shl	edi, 9
1981
	add	edi, RAMDISK+31*512
1982
	xor	eax, eax
1983
	mov	ecx, 512/4
1984
	rep	stosd
1985
	pop	eax	; eax=new cluster
1986
	pop	edi	; edi->direntry
1987
	pop	ecx	; ecx=required size
1988
	add	dword [edi+28], 0x200
1989
	jmp	.extend_loop
131 diamond 1990
.extend_done:
766 Rus 1991
	mov	[edi+28], ecx
1992
	pop	esi edx
1993
	xor	eax, eax	; CF=0
1994
	ret
131 diamond 1995
.disk_full:
766 Rus 1996
	pop	edi ecx
1997
	pop	esi edx
1998
	stc
1999
	push	ERROR_DISK_FULL
2000
	pop	eax
2001
	ret
131 diamond 2002
 
133 diamond 2003
fat_update_datetime:
766 Rus 2004
	call	get_time_for_file
2005
	mov	[edi+22], ax		; last write time
2006
	call	get_date_for_file
2007
	mov	[edi+24], ax		; last write date
2008
	mov	[edi+18], ax		; last access date
2009
	ret
133 diamond 2010
 
2011
;----------------------------------------------------------------
2012
;
2013
;  fs_RamdiskSetFileEnd - set end of file on ramdisk
2014
;
2015
;  esi  points to filename
2016
;  ebx  points to 64-bit number = new file size
2017
;  ecx  ignored (reserved)
2018
;  edx  ignored (reserved)
2019
;
2020
;  ret eax = 0 ok or other = errormsg
2021
;
2022
;--------------------------------------------------------------
2023
fs_RamdiskSetFileEnd:
766 Rus 2024
	cmp	byte [esi], 0
2025
	jnz	@f
133 diamond 2026
.access_denied:
766 Rus 2027
	push	ERROR_ACCESS_DENIED
2028
	jmp	.ret
133 diamond 2029
@@:
766 Rus 2030
	push	edi
2031
	call	rd_find_lfn
2032
	jnc	@f
2033
	pop	edi
2034
	push	ERROR_FILE_NOT_FOUND
133 diamond 2035
.ret:
766 Rus 2036
	pop	eax
2037
	ret
133 diamond 2038
@@:
2039
; must not be directory
766 Rus 2040
	test	byte [edi+11], 10h
2041
	jz	@f
2042
	pop	edi
2043
	jmp	.access_denied
133 diamond 2044
@@:
2045
; file size must not exceed 4Gb
766 Rus 2046
	cmp	dword [ebx+4], 0
2047
	jz	@f
2048
	pop	edi
2049
	push	ERROR_END_OF_FILE
2050
	jmp	.ret
133 diamond 2051
@@:
2052
; set file modification date/time to current
766 Rus 2053
	call	fat_update_datetime
2054
	mov	eax, [ebx]
2055
	cmp	eax, [edi+28]
2056
	jb	.truncate
2057
	ja	.expand
2058
	pop	edi
2059
	xor	eax, eax
2060
	ret
133 diamond 2061
.expand:
766 Rus 2062
	push	ecx
2063
	mov	ecx, eax
2064
	call	ramdisk_extend_file
2065
	pop	ecx
2066
	pop	edi
2067
	ret
133 diamond 2068
.truncate:
766 Rus 2069
	mov	[edi+28], eax
2070
	push	ecx
2071
	movzx	ecx, word [edi+26]
2072
	test	eax, eax
2073
	jz	.zero_size
133 diamond 2074
; find new last sector
2075
@@:
766 Rus 2076
	sub	eax, 0x200
2077
	jbe	@f
2078
	movzx	ecx, word [RAMDISK_FAT+ecx*2]
2079
	jmp	@b
133 diamond 2080
@@:
2081
; zero data at the end of last sector
766 Rus 2082
	push	ecx
2083
	mov	edi, ecx
2084
	shl	edi, 9
2085
	lea	edi, [edi+RAMDISK+31*512+eax+0x200]
2086
	mov	ecx, eax
2087
	neg	ecx
2088
	xor	eax, eax
2089
	rep	stosb
2090
	pop	ecx
133 diamond 2091
; terminate FAT chain
766 Rus 2092
	lea	ecx, [RAMDISK_FAT+ecx+ecx]
2093
	push	dword [ecx]
2094
	mov	word [ecx], 0xFFF
2095
	pop	ecx
2096
	and	ecx, 0xFFF
2097
	jmp	.delete
133 diamond 2098
.zero_size:
766 Rus 2099
	and	word [edi+26], 0
133 diamond 2100
.delete:
2101
; delete FAT chain starting with ecx
2102
; mark all clusters as free
766 Rus 2103
	cmp	ecx, 0xFF8
2104
	jae	.deleted
2105
	lea	ecx, [RAMDISK_FAT+ecx+ecx]
2106
	push	dword [ecx]
2107
	and	word [ecx], 0
2108
	pop	ecx
2109
	and	ecx, 0xFFF
2110
	jmp	.delete
133 diamond 2111
.deleted:
766 Rus 2112
	pop	ecx
2113
	pop	edi
2114
	xor	eax, eax
2115
	ret
133 diamond 2116
 
86 diamond 2117
fs_RamdiskGetFileInfo:
766 Rus 2118
	cmp	byte [esi], 0
2119
	jnz	@f
2120
	mov	eax, 2	; unsupported
2121
	ret
86 diamond 2122
@@:
766 Rus 2123
	push	edi
2124
	call	rd_find_lfn
86 diamond 2125
fs_GetFileInfo_finish:
766 Rus 2126
	jnc	@f
2127
	pop	edi
2128
	mov	eax, ERROR_FILE_NOT_FOUND
2129
	ret
86 diamond 2130
@@:
766 Rus 2131
	push	esi ebp
2132
	xor	ebp, ebp
2133
	mov	esi, edx
2134
	and	dword [esi+4], 0
2135
	call	fat_entry_to_bdfe2
2136
	pop	ebp esi
2137
	pop	edi
2138
	xor	eax, eax
2139
	ret
86 diamond 2140
 
2141
fs_RamdiskSetFileInfo:
766 Rus 2142
	cmp	byte [esi], 0
2143
	jnz	@f
2144
	mov	eax, 2	; unsupported
2145
	ret
86 diamond 2146
@@:
766 Rus 2147
	push	edi
2148
	call	rd_find_lfn
2149
	jnc	@f
2150
	pop	edi
2151
	mov	eax, ERROR_FILE_NOT_FOUND
2152
	ret
86 diamond 2153
@@:
766 Rus 2154
	call	bdfe_to_fat_entry
2155
	pop	edi
2156
	xor	eax, eax
2157
	ret
86 diamond 2158
 
91 diamond 2159
;----------------------------------------------------------------
2160
;
171 diamond 2161
;  fs_RamdiskDelete - delete file or empty folder from ramdisk
2162
;
2163
;  esi  points to filename
2164
;
2165
;  ret  eax = 0 ok or other = errormsg
2166
;
2167
;--------------------------------------------------------------
2168
fs_RamdiskDelete:
766 Rus 2169
	cmp	byte [esi], 0
2170
	jnz	@f
171 diamond 2171
; cannot delete root!
2172
.access_denied:
766 Rus 2173
	push	ERROR_ACCESS_DENIED
171 diamond 2174
.pop_ret:
766 Rus 2175
	pop	eax
2176
	ret
171 diamond 2177
@@:
766 Rus 2178
	and	[rd_prev_sector], 0
2179
	and	[rd_prev_prev_sector], 0
2180
	push	edi
2181
	call	rd_find_lfn
2182
	jnc	.found
2183
	pop	edi
2184
	push	ERROR_FILE_NOT_FOUND
2185
	jmp	.pop_ret
171 diamond 2186
.found:
766 Rus 2187
	cmp	dword [edi], '.   '
2188
	jz	.access_denied2
2189
	cmp	dword [edi], '..  '
2190
	jz	.access_denied2
2191
	test	byte [edi+11], 10h
2192
	jz	.dodel
171 diamond 2193
; we can delete only empty folders!
766 Rus 2194
	movzx	eax, word [edi+26]
2195
	push	ebx
2196
	mov	ebx, eax
2197
	shl	ebx, 9
2198
	add	ebx, RAMDISK + 31*0x200 + 2*0x20
171 diamond 2199
.checkempty:
766 Rus 2200
	cmp	byte [ebx], 0
2201
	jz	.empty
2202
	cmp	byte [ebx], 0xE5
2203
	jnz	.notempty
2204
	add	ebx, 0x20
2205
	test	ebx, 0x1FF
2206
	jnz	.checkempty
2207
	movzx	eax, word [RAMDISK_FAT + eax*2]
2208
	test	eax, eax
2209
	jz	.empty
2210
	mov	ebx, eax
2211
	shl	ebx, 9
2212
	add	ebx, RAMDISK + 31*0x200
2213
	jmp	.checkempty
171 diamond 2214
.notempty:
766 Rus 2215
	pop	ebx
171 diamond 2216
.access_denied2:
766 Rus 2217
	pop	edi
2218
	jmp	.access_denied
171 diamond 2219
.empty:
766 Rus 2220
	pop	ebx
171 diamond 2221
.dodel:
766 Rus 2222
	movzx	eax, word [edi+26]
171 diamond 2223
; delete folder entry
766 Rus 2224
	mov	byte [edi], 0xE5
171 diamond 2225
; delete LFN (if present)
2226
.lfndel:
766 Rus 2227
	test	edi, 0x1FF
2228
	jnz	@f
2229
	cmp	[rd_prev_sector], 0
2230
	jz	@f
2231
	cmp	[rd_prev_sector], -1
2232
	jz	.lfndone
2233
	mov	edi, [rd_prev_sector]
2234
	push	[rd_prev_prev_sector]
2235
	pop	[rd_prev_sector]
2236
	or	[rd_prev_prev_sector], -1
2237
	shl	edi, 9
2238
	add	edi, RAMDISK + 31*0x200 + 0x200
171 diamond 2239
@@:
766 Rus 2240
	sub	edi, 0x20
2241
	cmp	byte [edi], 0xE5
2242
	jz	.lfndone
2243
	cmp	byte [edi+11], 0xF
2244
	jnz	.lfndone
2245
	mov	byte [edi], 0xE5
2246
	jmp	.lfndel
171 diamond 2247
.lfndone:
2248
; delete FAT chain
766 Rus 2249
	test	eax, eax
2250
	jz	.done
2251
	lea	eax, [RAMDISK_FAT + eax*2]
2252
	push	dword [eax]
2253
	and	word [eax], 0
2254
	pop	eax
2255
	and	eax, 0xFFF
2256
	jmp	.lfndone
171 diamond 2257
.done:
766 Rus 2258
	pop	edi
2259
	xor	eax, eax
2260
	ret
171 diamond 2261
 
78 diamond 2262
; \end{diamond}