Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1159 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2008. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
1206 hidnplayr 8
$Revision: 1206 $
1159 hidnplayr 9
 
10
 
11
image_of_eax EQU esp+36
12
image_of_ebx EQU esp+24
13
 
14
; System function 70 - files with long names (LFN)
15
; diamond, 2006
16
 
17
iglobal
18
; in this table names must be in lowercase
19
rootdirs:
20
	db	2,'rd'
21
	dd	fs_OnRamdisk
22
	dd	fs_NextRamdisk
23
	db	7,'ramdisk'
24
	dd	fs_OnRamdisk
25
	dd	fs_NextRamdisk
26
	db	2,'fd'
27
	dd	fs_OnFloppy
28
	dd	fs_NextFloppy
29
	db	10,'floppydisk'
30
	dd	fs_OnFloppy
31
	dd	fs_NextFloppy
32
	db	3,'hd0'
33
	dd	fs_OnHd0
34
	dd	fs_NextHd0
35
	db	3,'hd1'
36
	dd	fs_OnHd1
37
	dd	fs_NextHd1
38
	db	3,'hd2'
39
	dd	fs_OnHd2
40
	dd	fs_NextHd2
41
	db	3,'hd3'
42
	dd	fs_OnHd3
43
	dd	fs_NextHd3
44
;**********************************************
45
	db	3,'cd0'
46
	dd	fs_OnCd0
47
	dd	fs_NextCd
48
	db	3,'cd1'
49
	dd	fs_OnCd1
50
	dd	fs_NextCd
51
	db	3,'cd2'
52
	dd	fs_OnCd2
53
	dd	fs_NextCd
54
	db	3,'cd3'
55
	dd	fs_OnCd3
56
	dd	fs_NextCd
57
;***********************************************
58
	db	0
59
 
60
 
61
virtual_root_query:
62
	dd	fs_HasRamdisk
63
	db	'rd',0
64
	dd	fs_HasFloppy
65
	db	'fd',0
66
	dd	fs_HasHd0
67
	db	'hd0',0
68
	dd	fs_HasHd1
69
	db	'hd1',0
70
	dd	fs_HasHd2
71
	db	'hd2',0
72
	dd	fs_HasHd3
73
	db	'hd3',0
74
;**********************************************
75
	dd	fs_HasCd0
76
	db	'cd0',0
77
	dd	fs_HasCd1
78
	db	'cd1',0
79
	dd	fs_HasCd2
80
	db	'cd2',0
81
	dd	fs_HasCd3
82
	db	'cd3',0
83
;**********************************************
84
	dd	0
85
 
86
fs_additional_handlers:
87
        dd      biosdisk_handler, biosdisk_enum_root
88
; add new handlers here
89
        dd      0
90
 
91
endg
92
 
93
file_system_lfn:
94
; in: eax->fileinfo block
95
; operation codes:
96
; 0 : read file
97
; 1 : read folder
98
; 2 : create/rewrite file
99
; 3 : write/append to file
100
; 4 : set end of file
101
; 5 : get file/directory attributes structure
102
; 6 : set file/directory attributes structure
103
; 7 : start application
104
; 8 : delete file
105
; 9 : create directory
106
 
107
; parse file name
108
	xchg	ebx, eax
109
	lea	esi, [ebx+20]
110
	lodsb
111
	test	al, al
112
	jnz	@f
113
	mov	esi, [esi]
114
	lodsb
115
@@:
116
	cmp	al, '/'
117
	jz	.notcurdir
118
	dec	esi
119
	mov	ebp, esi
120
	test	al, al
121
	jnz	@f
122
	xor	ebp, ebp
123
@@:
124
	mov	esi, [current_slot]
125
	mov	esi, [esi+APPDATA.cur_dir]
126
	jmp	.parse_normal
127
.notcurdir:
128
	cmp	byte [esi], 0
129
	jz	.rootdir
130
	call	process_replace_file_name
131
.parse_normal:
132
	cmp dword [ebx], 7
133
	jne @F
134
	mov edx, [ebx+4]
135
	mov ebx, [ebx+8]
136
	call fs_execute  ; esi+ebp, ebx, edx
137
	mov [image_of_eax], eax
138
	ret
139
@@:
140
	mov	edi, rootdirs-8
141
	xor	ecx, ecx
142
	push	esi
143
.scan1:
144
	pop	esi
145
	add	edi, ecx
146
	scasd
147
	scasd
148
	mov	cl, byte [edi]
149
	test	cl, cl
150
	jz	.notfound_try
151
	inc	edi
152
	push	esi
153
@@:
154
	lodsb
155
	or	al, 20h
156
	scasb
157
	loopz	@b
158
	jnz	.scan1
159
	lodsb
160
	cmp	al, '/'
161
	jz	.found1
162
	test	al, al
163
	jnz	.scan1
164
	pop	eax
165
; directory /xxx
166
.maindir:
167
	mov	esi, [edi+4]
168
.maindir_noesi:
169
	cmp	dword [ebx], 1
170
	jnz	.access_denied
171
	xor	eax, eax
172
	mov	ebp, [ebx+12]
173
	mov	edx, [ebx+16]
174
    ;    add     edx, std_application_base_address
175
	push	dword [ebx+4]	; first block
176
	mov	ebx, [ebx+8]	; flags
177
; ebx=flags, [esp]=first block, ebp=number of blocks, edx=return area, esi='Next' handler
178
	mov	edi, edx
179
	push    ecx
180
	mov	ecx, 32/4
181
	rep	stosd
182
	pop     ecx
183
	mov	byte [edx], 1	; version
184
.maindir_loop:
185
	call	esi
186
	jc	.maindir_done
187
	inc	dword [edx+8]
188
	dec	dword [esp]
189
	jns	.maindir_loop
190
	dec	ebp
191
	js	.maindir_loop
192
	inc	dword [edx+4]
193
	mov	dword [edi], 0x10	; attributes: folder
194
	mov	dword [edi+4], 1	; name type: UNICODE
195
	push	eax
196
	xor	eax, eax
197
	add	edi, 8
198
	push    ecx
199
	mov	ecx, 40/4-2
200
	rep	stosd
201
	pop     ecx
202
	pop	eax
203
	push	eax edx
204
; convert number in eax to decimal UNICODE string
205
	push	edi
206
	push    ecx
207
	push	-'0'
208
	mov	ecx, 10
209
@@:
210
	xor	edx, edx
211
	div	ecx
212
	push	edx
213
	test	eax, eax
214
	jnz	@b
215
@@:
216
	pop	eax
217
	add	al, '0'
218
	stosb
219
	test	bl, 1		; UNICODE name?
220
	jz	.ansi2
221
	mov	byte [edi], 0
222
	inc	edi
223
.ansi2:
224
	test	al, al
225
	jnz	@b
226
	mov	byte [edi-1], 0
227
	pop     ecx
228
	pop	edi
229
; UNICODE name length is 520 bytes, ANSI - 264
230
	add	edi, 520
231
	test	bl, 1
232
	jnz	@f
233
	sub	edi, 520-264
234
@@:
235
	pop	edx eax
236
	jmp	.maindir_loop
237
.maindir_done:
238
	pop	eax
239
	mov	ebx, [edx+4]
240
	xor	eax, eax
241
	dec	ebp
242
	js	@f
243
	mov	al, ERROR_END_OF_FILE
244
@@:
245
	mov	[image_of_eax], eax
246
	mov	[image_of_ebx], ebx
247
	ret
248
; directory /
249
.rootdir:
250
	cmp	dword [ebx], 1	; read folder?
251
	jz	.readroot
252
.access_denied:
253
	mov	dword [image_of_eax], 10      ; access denied
254
	ret
255
 
256
.readroot:
257
; virtual root folder - special handler
258
	mov	esi, virtual_root_query
259
	mov	ebp, [ebx+12]
260
	mov	edx, [ebx+16]
261
    ;    add     edx, std_application_base_address
262
	push	dword [ebx+4]	; first block
263
	mov	ebx, [ebx+8]	; flags
264
	xor	eax, eax
265
; eax=0, [esp]=first block, ebx=flags, ebp=number of blocks, edx=return area
266
	mov	edi, edx
267
	mov	ecx, 32/4
268
	rep	stosd
269
	mov	byte [edx], 1	; version
270
.readroot_loop:
271
	cmp	dword [esi], eax
272
	jz	.readroot_done_static
273
	call	dword [esi]
274
	add	esi, 4
275
	test	eax, eax
276
	jnz	@f
277
.readroot_next:
278
	or	ecx, -1
279
	xchg	esi, edi
280
	repnz	scasb
281
	xchg	esi, edi
282
	jmp	.readroot_loop
283
@@:
284
	xor	eax, eax
285
	inc	dword [edx+8]
286
	dec	dword [esp]
287
	jns	.readroot_next
288
	dec	ebp
289
	js	.readroot_next
290
	inc	dword [edx+4]
291
	mov	dword [edi], 0x10	; attributes: folder
292
	mov	dword [edi+4], ebx	; name type: UNICODE
293
	add	edi, 8
294
	mov	ecx, 40/4-2
295
	rep	stosd
296
	push	edi
297
@@:
298
	lodsb
299
	stosb
300
	test	bl, 1
301
	jz	.ansi
302
	mov	byte [edi], 0
303
	inc	edi
304
.ansi:
305
	test	eax, eax
306
	jnz	@b
307
	pop	edi
308
	add	edi, 520
309
	test	bl, 1
310
	jnz	.readroot_loop
311
	sub	edi, 520-264
312
	jmp	.readroot_loop
313
.readroot_done_static:
314
        mov     esi, fs_additional_handlers-8
315
        sub     esp, 16
316
.readroot_ah_loop:
317
        add     esi, 8
318
        cmp     dword [esi], 0
319
        jz      .readroot_done
320
        xor     eax, eax
321
.readroot_ah_loop2:
322
        push    edi
323
        lea     edi, [esp+4]
324
        call    dword [esi+4]
325
        pop     edi
326
        test    eax, eax
327
        jz      .readroot_ah_loop
328
        inc     dword [edx+8]
329
        dec     dword [esp+16]
330
        jns     .readroot_ah_loop2
331
        dec     ebp
332
        js      .readroot_ah_loop2
333
        push    eax
334
        xor     eax, eax
335
        inc     dword [edx+4]
336
        mov     dword [edi], 0x10       ; attributes: folder
337
        mov     dword [edi+4], ebx
338
        add     edi, 8
339
        mov     ecx, 40/4-2
340
        rep     stosd
341
        push    esi edi
342
        lea     esi, [esp+12]
343
@@:
344
        lodsb
345
        stosb
346
        test    bl, 1
347
        jz      .ansi3
348
        mov     byte [edi], 0
349
        inc     edi
350
.ansi3:
351
        test    al, al
352
        jnz     @b
353
        pop     edi esi eax
354
        add     edi, 520
355
        test    bl, 1
356
        jnz     .readroot_ah_loop2
357
        sub     edi, 520-264
358
        jmp     .readroot_ah_loop2
359
.readroot_done:
360
        add     esp, 16
361
	pop	eax
362
	mov	ebx, [edx+4]
363
	xor	eax, eax
364
	dec	ebp
365
	js	@f
366
	mov	al, ERROR_END_OF_FILE
367
@@:
368
	mov	[image_of_eax], eax
369
	mov	[image_of_ebx], ebx
370
	ret
371
.notfound_try:
372
        mov     edi, fs_additional_handlers
373
@@:
374
        cmp     dword [edi], 0
375
        jz      @f
376
        call    dword [edi]
377
        scasd
378
        scasd
379
        jmp     @b
380
.notfound:
381
	mov	dword [image_of_eax], ERROR_FILE_NOT_FOUND
382
	and	dword [image_of_ebx], 0
383
	ret
384
 
385
.notfounda:
386
        cmp     edi, esp
387
        jnz     .notfound
388
        add     esp, 8
389
        jmp     .notfound
390
 
391
.found1:
392
	pop	eax
393
	cmp	byte [esi], 0
394
	jz	.maindir
395
.found2:
396
; read partition number
397
	xor	ecx, ecx
398
	xor	eax, eax
399
@@:
400
	lodsb
401
	cmp	al, '/'
402
	jz	.done1
403
	test	al, al
404
	jz	.done1
405
	sub	al, '0'
406
	cmp	al, 9
407
	ja	.notfounda
408
	lea	ecx, [ecx*5]
409
	lea	ecx, [ecx*2+eax]
410
	jmp	@b
411
.done1:
412
	jecxz	.notfounda
413
	test	al, al
414
	jnz	@f
415
	dec	esi
416
@@:
417
	cmp	byte [esi], 0
418
	jnz	@f
419
	test	ebp, ebp
420
	jz	@f
421
	mov	esi, ebp
422
	xor	ebp, ebp
423
@@:
424
; now [edi] contains handler address, ecx - partition number,
425
; esi points to ASCIIZ string - rest of name
426
	jmp	dword [edi]
427
 
428
; handlers for devices
429
; in: ecx = 0 => query virtual directory /xxx
430
; in: ecx = partition number
431
;     esi -> relative (for device) name
432
;     ebx -> fileinfo
433
;     ebp = 0 or pointer to rest of name from folder addressed by esi
434
; out: [image_of_eax]=image of eax, [image_of_ebx]=image of ebx
435
 
436
fs_OnRamdisk:
437
	cmp	ecx, 1
438
	jnz	file_system_lfn.notfound
439
	mov	eax, [ebx]
440
	cmp	eax, fs_NumRamdiskServices
441
	jae	.not_impl
442
	mov	ecx, [ebx+12]
443
	mov	edx, [ebx+16]
444
   ;     add     edx, std_application_base_address
445
	add	ebx, 4
446
	call	dword [fs_RamdiskServices + eax*4]
447
	mov	[image_of_eax], eax
448
	mov	[image_of_ebx], ebx
449
	ret
450
.not_impl:
451
	mov	dword [image_of_eax], 2       ; not implemented
452
	ret
453
 
454
fs_NotImplemented:
455
	mov	eax, 2
456
	ret
457
 
458
fs_RamdiskServices:
459
	dd	fs_RamdiskRead
460
	dd	fs_RamdiskReadFolder
461
	dd	fs_RamdiskRewrite
462
	dd	fs_RamdiskWrite
463
	dd	fs_RamdiskSetFileEnd
464
	dd	fs_RamdiskGetFileInfo
465
	dd	fs_RamdiskSetFileInfo
466
	dd	0
467
	dd	fs_RamdiskDelete
468
	dd	fs_RamdiskCreateFolder
469
fs_NumRamdiskServices = ($ - fs_RamdiskServices)/4
470
 
471
fs_OnFloppy:
472
	cmp	ecx, 2
473
	ja	file_system_lfn.notfound
474
	mov	eax, [ebx]
475
	cmp	eax, fs_NumFloppyServices
476
	jae	fs_OnRamdisk.not_impl
477
	call	reserve_flp
478
	mov	[flp_number], cl
479
	mov	ecx, [ebx+12]
480
	mov	edx, [ebx+16]
481
   ;     add     edx, std_application_base_address
482
	add	ebx, 4
483
	call	dword [fs_FloppyServices + eax*4]
484
	and	[flp_status], 0
485
	mov	[image_of_eax], eax
486
	mov	[image_of_ebx], ebx
487
	ret
488
 
489
fs_FloppyServices:
490
	dd	fs_FloppyRead
491
	dd	fs_FloppyReadFolder
492
	dd	fs_FloppyRewrite
493
	dd	fs_FloppyWrite
494
	dd	fs_FloppySetFileEnd
495
	dd	fs_FloppyGetFileInfo
496
	dd	fs_FloppySetFileInfo
497
	dd	0
498
	dd	fs_FloppyDelete
499
	dd	fs_FloppyCreateFolder
500
fs_NumFloppyServices = ($ - fs_FloppyServices)/4
501
 
502
fs_OnHd0:
503
	call	reserve_hd1
504
	mov	[hdbase], 0x1F0
505
	mov	[hdid], 0
506
	push	1
507
	jmp	fs_OnHd
508
fs_OnHd1:
509
	call	reserve_hd1
510
	mov	[hdbase], 0x1F0
511
	mov	[hdid], 0x10
512
	push	2
513
	jmp	fs_OnHd
514
fs_OnHd2:
515
	call	reserve_hd1
516
	mov	[hdbase], 0x170
517
	mov	[hdid], 0
518
	push	3
519
	jmp	fs_OnHd
520
fs_OnHd3:
521
	call	reserve_hd1
522
	mov	[hdbase], 0x170
523
	mov	[hdid], 0x10
524
	push	4
525
fs_OnHd:
526
	call	reserve_hd_channel
527
	pop	eax
528
	mov	[hdpos], eax
529
	cmp	ecx, 0x100
530
	jae	fs_OnHdAndBd.nf
531
	cmp	cl, [DRIVE_DATA+1+eax]
532
fs_OnHdAndBd:
533
	jbe	@f
534
.nf:
535
	call	free_hd_channel
536
	and	[hd1_status], 0
537
	mov	dword [image_of_eax], 5       ; not found
538
	ret
539
@@:
540
	mov	[fat32part], ecx
541
	push	ebx esi
542
	call	choice_necessity_partition_1
543
	pop	esi ebx
544
	mov	ecx, [ebx+12]
545
	mov	edx, [ebx+16]
546
    ;    add     edx, std_application_base_address
547
	mov	eax, [ebx]
548
	cmp	eax, fs_NumHdServices
549
	jae	.not_impl
550
	add	ebx, 4
551
	call	dword [fs_HdServices + eax*4]
552
	call	free_hd_channel
553
	and	[hd1_status], 0
554
	mov	[image_of_eax], eax
555
	mov	[image_of_ebx], ebx
556
	ret
557
.not_impl:
558
	call	free_hd_channel
559
	and	[hd1_status], 0
560
	mov	dword [image_of_eax], 2       ; not implemented
561
	ret
562
 
563
fs_HdServices:
564
	dd	fs_HdRead
565
	dd	fs_HdReadFolder
566
	dd	fs_HdRewrite
567
	dd	fs_HdWrite
568
	dd	fs_HdSetFileEnd
569
	dd	fs_HdGetFileInfo
570
	dd	fs_HdSetFileInfo
571
	dd	0
572
	dd	fs_HdDelete
573
	dd	fs_HdCreateFolder
574
fs_NumHdServices = ($ - fs_HdServices)/4
575
 
576
;*******************************************************
577
fs_OnCd0:
578
	call	reserve_cd
579
	mov  [ChannelNumber],1
580
	mov  [DiskNumber],0
581
	push	6
582
	push	1
583
	jmp	fs_OnCd
584
fs_OnCd1:
585
	call	reserve_cd
586
	mov  [ChannelNumber],1
587
	mov  [DiskNumber],1
588
	push	4
589
	push	2
590
	jmp	fs_OnCd
591
fs_OnCd2:
592
	call	reserve_cd
593
	mov  [ChannelNumber],2
594
	mov  [DiskNumber],0
595
	push	2
596
	push	3
597
	jmp	fs_OnCd
598
fs_OnCd3:
599
	call	reserve_cd
600
	mov  [ChannelNumber],2
601
	mov  [DiskNumber],1
602
	push	0
603
	push	4
604
fs_OnCd:
605
	call	reserve_cd_channel
606
	pop	eax
607
	mov	[cdpos], eax
608
	pop	eax
609
	cmp	ecx, 0x100
610
	jae	.nf
611
	push	ecx ebx
612
	mov	cl,al
613
	mov	bl,[DRIVE_DATA+1]
614
	shr	bl,cl
615
	test	bl,2
616
	pop	ebx ecx
617
 
618
	jnz	@f
619
.nf:
620
	call	free_cd_channel
621
	and    [cd_status], 0
622
	mov	dword [image_of_eax], 5       ; not found
623
	ret
624
@@:
625
	mov	ecx, [ebx+12]
626
	mov	edx, [ebx+16]
627
    ;    add     edx, std_application_base_address
628
	mov	eax, [ebx]
629
	cmp	eax,fs_NumCdServices
630
	jae	 .not_impl
631
	add	ebx, 4
632
	call	dword [fs_CdServices + eax*4]
633
	call	free_cd_channel
634
	and	[cd_status], 0
635
	mov	[image_of_eax], eax
636
	mov	[image_of_ebx], ebx
637
	ret
638
.not_impl:
639
	call	free_cd_channel
640
	and	[cd_status], 0
641
	mov	dword [image_of_eax], 2       ; not implemented
642
	ret
643
 
644
fs_CdServices:
645
	dd	fs_CdRead
646
	dd	fs_CdReadFolder
647
	dd	fs_NotImplemented
648
	dd	fs_NotImplemented
649
	dd	fs_NotImplemented
650
	dd	fs_CdGetFileInfo
651
	dd	fs_NotImplemented
652
	dd	0
653
	dd	fs_NotImplemented
654
	dd	fs_NotImplemented
655
fs_NumCdServices = ($ - fs_CdServices)/4
656
 
657
;*******************************************************
658
 
659
fs_HasRamdisk:
660
	mov	al, 1	; we always have ramdisk
661
	ret
662
 
663
fs_HasFloppy:
664
	cmp	byte [DRIVE_DATA], 0
665
	setnz	al
666
	ret
667
 
668
fs_HasHd0:
669
	mov	al, [DRIVE_DATA+1]
670
	and	al, 11000000b
671
	cmp	al, 01000000b
672
	setz	al
673
	ret
674
fs_HasHd1:
675
	mov	al, [DRIVE_DATA+1]
676
	and	al, 00110000b
677
	cmp	al, 00010000b
678
	setz	al
679
	ret
680
fs_HasHd2:
681
	mov	al, [DRIVE_DATA+1]
682
	and	al, 00001100b
683
	cmp	al, 00000100b
684
	setz	al
685
	ret
686
fs_HasHd3:
687
	mov	al, [DRIVE_DATA+1]
688
	and	al, 00000011b
689
	cmp	al, 00000001b
690
	setz	al
691
	ret
692
 
693
;*******************************************************
694
fs_HasCd0:
695
	mov	al, [DRIVE_DATA+1]
696
	and	al, 11000000b
697
	cmp	al, 10000000b
698
	setz	al
699
	ret
700
fs_HasCd1:
701
	mov	al, [DRIVE_DATA+1]
702
	and	al, 00110000b
703
	cmp	al, 00100000b
704
	setz	al
705
	ret
706
fs_HasCd2:
707
	mov	al, [DRIVE_DATA+1]
708
	and	al, 00001100b
709
	cmp	al, 00001000b
710
	setz	al
711
	ret
712
fs_HasCd3:
713
	mov	al, [DRIVE_DATA+1]
714
	and	al, 00000011b
715
	cmp	al, 00000010b
716
	setz	al
717
	ret
718
;*******************************************************
719
 
720
; fs_NextXXX functions:
721
; in: eax = partition number, from which start to scan
722
; out: CF=1 => no more partitions
723
;      CF=0 => eax=next partition number
724
 
725
fs_NextRamdisk:
726
; we always have /rd/1
727
	test	eax, eax
728
	stc
729
	jnz	@f
730
	mov	al, 1
731
	clc
732
@@:
733
	ret
734
 
735
fs_NextFloppy:
736
; we have /fd/1 iff (([DRIVE_DATA] and 0xF0) != 0) and /fd/2 iff (([DRIVE_DATA] and 0x0F) != 0)
737
	test	byte [DRIVE_DATA], 0xF0
738
	jz	.no1
739
	test	eax, eax
740
	jnz	.no1
741
	inc	eax
742
	ret	; CF cleared
743
.no1:
744
	test	byte [DRIVE_DATA], 0x0F
745
	jz	.no2
746
	cmp	al, 2
747
	jae	.no2
748
	mov	al, 2
749
	clc
750
	ret
751
.no2:
752
	stc
753
	ret
754
 
755
; on hdx, we have partitions from 1 to [0x40002+x]
756
fs_NextHd0:
757
	push	0
758
	jmp	fs_NextHd
759
fs_NextHd1:
760
	push	1
761
	jmp	fs_NextHd
762
fs_NextHd2:
763
	push	2
764
	jmp	fs_NextHd
765
fs_NextHd3:
766
	push	3
767
fs_NextHd:
768
	pop	ecx
769
	movzx	ecx, byte [DRIVE_DATA+2+ecx]
770
	cmp	eax, ecx
771
	jae	fs_NextFloppy.no2
772
	inc	eax
773
	clc
774
	ret
775
 
776
;*******************************************************
777
fs_NextCd:
778
; we always have /cdX/1
779
	test	eax, eax
780
	stc
781
	jnz	@f
782
	mov	al, 1
783
	clc
784
@@:
785
	ret
786
;*******************************************************
787
 
788
; Additional FS handlers.
789
; This handler gets the control each time when fn 70 is called
790
; with unknown item of root subdirectory.
791
; in: esi -> name
792
;     ebp = 0 or rest of name relative to esi
793
; out: if the handler processes path, he must not return in file_system_lfn,
794
;      but instead pop return address and return directly to the caller
795
;      otherwise simply return
796
 
797
; here we test for /bd/... - BIOS disks
798
biosdisk_handler:
799
        cmp     [NumBiosDisks], 0
800
        jz      .ret
801
        mov     al, [esi]
802
        or      al, 20h
803
        cmp     al, 'b'
804
        jnz     .ret
805
        mov     al, [esi+1]
806
        or      al, 20h
807
        cmp     al, 'd'
808
        jnz     .ret
809
        push    esi
810
        inc     esi
811
        inc     esi
812
        cmp     byte [esi], '0'
813
        jb      .ret2
814
        cmp     byte [esi], '9'
815
        ja      .ret2
816
        xor     edx, edx
817
@@:
818
        lodsb
819
        test    al, al
820
        jz      .ok
821
        cmp     al, '/'
822
        jz      .ok
823
        sub     al, '0'
824
        cmp     al, 9
825
        ja      .ret2
826
        lea     edx, [edx*5]
827
        lea     edx, [edx*2+eax]
828
        jmp     @b
829
.ret2:
830
        pop     esi
831
.ret:
832
        ret
833
.ok:
834
        cmp     al, '/'
835
        jz      @f
836
        dec     esi
837
@@:
838
        add     dl, 80h
839
        xor     ecx, ecx
840
@@:
841
        cmp     dl, [BiosDisksData+ecx*4]
842
        jz      .ok2
843
        inc     ecx
844
        cmp     ecx, [NumBiosDisks]
845
        jb      @b
846
        jmp     .ret2
847
.ok2:
848
        add     esp, 8
849
        test    al, al
850
        jnz     @f
851
        mov     esi, fs_BdNext
852
        jmp     file_system_lfn.maindir_noesi
853
@@:
854
        push    ecx
855
        push    fs_OnBd
856
        mov     edi, esp
857
        jmp     file_system_lfn.found2
858
 
859
fs_BdNext:
860
        cmp     eax, [BiosDiskPartitions+ecx*4]
861
	inc	eax
862
	cmc
863
	ret
864
 
865
fs_OnBd:
866
        pop     edx edx
867
; edx = disk number, ecx = partition number
868
; esi+ebp = name
869
	call	reserve_hd1
870
	add     edx, 0x80
871
	mov     [hdpos], edx
872
	cmp     ecx, [BiosDiskPartitions+(edx-0x80)*4]
873
	jmp     fs_OnHdAndBd
874
 
875
; This handler is called when virtual root is enumerated
876
; and must return all items which can be handled by this.
877
; It is called several times, first time with eax=0
878
; in: eax = 0 for first call, previously returned value for subsequent calls
879
; out: eax = 0 => no more items
880
;      eax != 0 => buffer pointed to by edi contains name of item
881
 
882
; here we enumerate existing BIOS disks /bd
883
biosdisk_enum_root:
884
        cmp     eax, [NumBiosDisks]
885
        jae     .end
886
        push    eax
887
        movzx   eax, byte [BiosDisksData+eax*4]
888
        sub     al, 80h
889
        push    eax
890
        mov     al, 'b'
891
        stosb
892
        mov     al, 'd'
893
        stosb
894
        pop     eax
895
        cmp     al, 10
896
        jae     .big
897
        add     al, '0'
898
        stosb
899
        mov     byte [edi], 0
900
        pop     eax
901
        inc     eax
902
        ret
903
.end:
904
        xor     eax, eax
905
        ret
906
.big:
907
        push    ecx
908
        push    -'0'
909
        mov     ecx, 10
910
@@:
911
        xor     edx, edx
912
        div     ecx
913
        push    edx
914
        test    eax, eax
915
        jnz     @b
916
        xchg    eax, edx
917
@@:
918
        pop     eax
919
        add     al, '0'
920
        stosb
921
        jnz     @b
922
        pop     ecx
923
        pop     eax
924
        inc     eax
925
        ret
926
 
927
process_replace_file_name:
928
	mov	ebp, [full_file_name_table]
929
	mov	edi, [full_file_name_table.size]
930
	dec	edi
931
	shl	edi, 7
932
	add	edi, ebp
933
.loop:
934
	cmp	edi, ebp
935
	jb	.notfound
936
	push	esi edi
937
@@:
938
	cmp	byte [edi], 0
939
	jz	.dest_done
940
	lodsb
941
	test	al, al
942
	jz	.cont
943
	or	al, 20h
944
	scasb
945
	jz	@b
946
	jmp	.cont
947
.dest_done:
948
	cmp	byte [esi], 0
949
	jz	.found
950
	cmp	byte [esi], '/'
951
	jnz	.cont
952
	inc	esi
953
	jmp	.found
954
.cont:
955
	pop	edi esi
956
	sub	edi, 128
957
	jmp	.loop
958
.found:
959
	pop	edi eax
960
	mov	ebp, esi
961
	cmp	byte [esi], 0
962
	lea	esi, [edi+64]
963
	jnz	.ret
964
.notfound:
965
	xor	ebp, ebp
966
.ret:
967
	ret
968
 
969
sys_current_directory:
970
	mov	esi, [current_slot]
971
	mov	esi, [esi+APPDATA.cur_dir]
972
	mov	edx, esi
973
	dec	eax
974
	jz	.set
975
	dec	eax
976
	jz	.get
977
	ret
978
.get:
979
; sysfunction 30.2: [for app] eax=30,ebx=2,ecx->buffer,edx=len
980
; for our code: ebx->buffer,ecx=len
981
@@:
982
	lodsb
983
	test	al, al
984
	jnz	@b
985
	sub	esi, edx
986
	inc	esi
987
	mov	[esp+36], esi
988
	cmp	ecx, esi
989
	jbe	@f
990
	mov	ecx, esi
991
@@:
992
	cmp	ecx, 1
993
	jbe	.ret
994
	mov	esi, edx
995
	mov	edi, ebx
996
	mov	al, '/'
997
	stosb
998
	dec	ecx
999
	dec	ecx
1000
	rep	movsb
1001
	mov	byte [edi], 0
1002
.ret:
1003
	ret
1004
.set:
1005
; sysfunction 30.1: [for app] eax=30,ebx=1,ecx->string
1006
; for our code: ebx->string to set
1007
@@:
1008
	inc	esi
1009
	cmp	byte [esi-1], 0
1010
	jnz	@b
1011
	dec	esi
1012
	cmp	byte [ebx], '/'
1013
	jz	.set_absolute
1014
; string gives relative path
1015
.relative:
1016
	cmp	byte [ebx], 0
1017
	jz	.set_ok
1018
	cmp	word [ebx], '.'
1019
	jz	.set_ok
1020
	cmp	word [ebx], './'
1021
	jnz	@f
1022
	add	ebx, 2
1023
	jmp	.relative
1024
@@:
1025
	cmp	word [ebx], '..'
1026
	jnz	.doset_relative
1027
	cmp	byte [ebx+2], 0
1028
	jz	@f
1029
	cmp	byte [ebx+2], '/'
1030
	jnz	.doset_relative
1031
@@:
1032
	dec	esi
1033
	cmp	byte [esi], '/'
1034
	jnz	@b
1035
	mov	byte [esi], 0
1036
	add	ebx, 3
1037
	jmp	.relative
1038
.doset_relative:
1039
	add	edx, 0x1000
1040
	mov	byte [esi], '/'
1041
	inc	esi
1042
	cmp	esi, edx
1043
	jae	.overflow_esi
1044
@@:
1045
	mov	al, [ebx]
1046
	inc	ebx
1047
	mov	[esi], al
1048
	inc	esi
1049
	test	al, al
1050
	jz	.set_ok
1051
	cmp	esi, edx
1052
	jb	@b
1053
.overflow_esi:
1054
	mov	byte [esi-1], 0 	; force null-terminated string
1055
.set_ok:
1056
	ret
1057
.set_absolute:
1058
	lea	esi, [ebx+1]
1059
	call	process_replace_file_name
1060
	mov	edi, edx
1061
	add	edx, 0x1000
1062
.set_copy:
1063
	lodsb
1064
	stosb
1065
	test	al, al
1066
	jz	.set_part2
1067
.set_copy_cont:
1068
	cmp	edi, edx
1069
	jb	.set_copy
1070
.overflow_edi:
1071
	mov	byte [edi-1], 0
1072
	ret
1073
.set_part2:
1074
	mov	esi, ebp
1075
	xor	ebp, ebp
1076
	test	esi, esi
1077
	jz	.set_ok
1078
	mov	byte [edi-1], '/'
1079
	jmp	.set_copy_cont