Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1 ha 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                      ;;
3
;; RAMDISK functions                                                    ;;
4
;; (C) 2004 Ville Turjanmaa, License: GPL                               ;;
5
;; Addings by M.Lisovin                                                 ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
5 halyavin 8
; calculate fat chain
1 ha 9
 
5 halyavin 10
calculatefatchain:
11
 
12
   pushad
13
 
14
   mov  esi,0x100000+512
15
   mov  edi,0x280000
16
 
17
 fcnew:
18
   mov  eax,dword [esi]
19
   mov  ebx,dword [esi+4]
20
   mov  ecx,dword [esi+8]
21
   mov  edx,ecx
22
   shr  edx,4   ;8 ok
23
   shr  dx,4    ;7 ok
24
   xor  ch,ch
25
   shld ecx,ebx,20 ;6 ok
26
   shr  cx,4     ;5 ok
27
   shld ebx,eax,12
28
   and  ebx,0x0fffffff  ;4 ok
29
   shr  bx,4    ;3 ok
30
   shl  eax,4
31
   and  eax,0x0fffffff  ;2 ok
32
   shr  ax,4  ;1 ok
33
   mov dword [edi],eax
34
   add  edi,4
35
   mov dword [edi],ebx
36
   add  edi,4
37
   mov dword [edi],ecx
38
   add  edi,4
39
   mov dword [edi],edx
40
   add  edi,4
41
   add  esi,12
42
 
43
   cmp  edi,0x280000+2856*2   ;2849 clusters
44
   jnz  fcnew
45
 
46
   popad
47
   ret
48
 
49
 
50
restorefatchain:   ; restore fat chain
51
 
52
   pushad
53
 
54
   mov  esi,0x280000
55
   mov  edi,0x100000+512
56
 
57
  fcnew2:
58
   mov  eax,dword [esi]
59
   mov  ebx,dword [esi+4]
60
   shl  ax,4
61
   shl  eax,4
62
   shl  bx,4
63
   shr  ebx,4
64
   shrd eax,ebx,8
65
   shr  ebx,8
66
   mov dword [edi],eax
67
   add  edi,4
68
   mov word [edi],bx
69
   add  edi,2
70
   add  esi,8
71
 
72
   cmp  edi,0x100000+512+4278     ;4274 bytes - all used FAT
73
   jb   fcnew2
74
 
75
   mov  esi,0x100000+512           ; duplicate fat chain
76
   mov  edi,0x100000+512+0x1200
77
   mov  ecx,1069        ;4274/4
78
   cld
79
   rep  movsd
80
 
81
   popad
82
   ret
83
 
84
 
1 ha 85
ramdisk_free_space:
86
;---------------------------------------------
87
;
88
; returns free space in edi
89
; rewr.by Mihasik
90
;---------------------------------------------
91
 
92
        push   eax ebx ecx
93
 
94
        mov  edi,0x280000 ;start of FAT
95
        xor  ax,ax    ;Free cluster=0x0000 in FAT
96
        xor  ebx,ebx  ;counter
5 halyavin 97
        mov  ecx,2849 ;2849 clusters
1 ha 98
        cld
99
    rdfs1:
100
        repne scasw
101
        jnz  rdfs2    ;if last cluster not 0
102
        inc  ebx
103
        jcxz rdfs2    ;if last cluster=0
104
        jmp  rdfs1    ;if not last
105
    rdfs2:
106
        shl  ebx,9    ;free clusters*512
107
        mov  edi,ebx
108
 
109
        pop    ecx ebx eax
110
        ret
111
 
112
 
113
expand_filename:
114
;---------------------------------------------
115
;
116
; exapand filename with '.' to 11 character
117
; eax - pointer to filename
118
;---------------------------------------------
119
 
120
        push esi edi ebx
121
 
122
        mov  edi,esp                  ; check for '.' in the name
123
        add  edi,12+8
124
 
125
        mov  esi,eax
126
 
127
        mov  eax,edi
128
        mov  [eax+0],dword '    '
129
        mov  [eax+4],dword '    '
130
        mov  [eax+8],dword '    '
131
 
132
      flr1:
133
 
134
        cmp  [esi],byte '.'
135
        jne  flr2
136
        mov  edi,eax
137
        add  edi,7
138
        jmp  flr3
139
 
140
      flr2:
141
 
142
        mov  bl,[esi]
143
        mov  [edi],bl
144
 
145
      flr3:
146
 
147
        inc  esi
148
        inc  edi
149
 
150
        mov  ebx,eax
151
        add  ebx,11
152
 
153
        cmp  edi,ebx
154
        jbe  flr1
155
 
156
        pop  ebx edi esi
157
        ret
158
 
159
fileread:
160
;----------------------------------------------------------------
161
;
162
;  fileread - sys floppy
163
;
164
;  eax  points to filename 11 chars
165
;  ebx  first wanted block       ; 1+ ; if 0 then set to 1
166
;  ecx  number of blocks to read ; 1+ ; if 0 then set to 1
167
;  edx  mem location to return data
168
;  esi  length of filename 12*X 0=root
169
;
170
;  ret ebx = size or 0xffffffff file not found
171
;      eax = 0 ok read or other = errormsg
172
;
173
;--------------------------------------------------------------
174
        test   ebx,ebx ;if ebx=0 - set to 1
175
        jnz    frfl5
176
        inc    ebx
177
      frfl5:
178
        test   ecx,ecx ;if ecx=0 - set to 1
179
        jnz    frfl6
180
        inc    ecx
181
      frfl6:
182
        test   esi,esi          ; return ramdisk root
183
        jnz    fr_noroot        ;if not root
184
        cmp    ebx,14           ;14 clusters=root dir
185
        ja     oorr
186
        cmp    ecx,14
187
        ja     oorr
188
        jmp    fr_do
189
      oorr:
190
        mov    eax,5            ;out of root range (fnf)
191
        xor    ebx,ebx
192
        dec    ebx              ;0xffffffff
193
        ret
194
 
195
      fr_do:                    ;reading rootdir
196
        mov    edi,edx
197
        dec    ebx
198
        push   edx
199
        mov    edx,ecx
200
        add    edx,ebx
5 halyavin 201
        cmp    edx,15     ;ebx+ecx=14+1
1 ha 202
        pushf
203
        jbe    fr_do1
204
        sub    edx,14
205
        sub    ecx,edx
206
      fr_do1:
207
        shl    ebx,9
208
        mov    esi,0x100000+512*19
209
        add    esi,ebx
210
        shl    ecx,7
211
        cld
212
        rep    movsd
213
        popf
214
        pop    edx
5 halyavin 215
        jae    fr_do2
1 ha 216
        xor    eax,eax ; ok read
217
        xor    ebx,ebx
218
        ret
219
      fr_do2:        ;if last cluster
220
        mov    eax,6  ;end of file
221
        xor    ebx,ebx
222
        ret
223
 
224
     fr_noroot:
225
 
226
        sub    esp,32
227
        call   expand_filename
228
 
229
        dec    ebx
230
 
231
        push   eax
232
 
233
        push   eax ebx ecx edx esi edi
234
        call   rd_findfile
235
        je     fifound
236
        add    esp,32+28   ;if file not found
237
        ret
238
 
239
     fifound:
240
 
241
        mov    ebx,[edi-11+28]          ;file size
242
        mov    [esp+20],ebx
243
        mov    [esp+24],ebx
244
        add    edi,0xf
245
        movzx  eax,word [edi]
246
        mov    edi,eax                  ;edi=cluster
247
 
248
      frnew:
249
 
250
        add    eax,31                   ;bootsector+2*fat+filenames
251
        shl    eax,9                    ;*512
252
        add    eax,0x100000             ;image base
253
        mov    ebx,[esp+8]
254
        mov    ecx,512                  ;[esp+4]
255
 
256
        cmp    [esp+16],dword 0         ; wanted cluster ?
257
        jne    frfl7
258
        call   memmove
259
        add    [esp+8],dword 512
260
        dec    dword [esp+12]           ; last wanted cluster ?
261
        je     frnoread
262
        jmp    frfl8
263
      frfl7:
264
        dec    dword [esp+16]
265
      frfl8:
71 diamond 266
        movzx  eax,word [edi*2+0x280000]	; find next cluster from FAT
1 ha 267
        mov    edi,eax
268
        cmp    edi,4095                 ;eof  - cluster
269
        jz     frnoread2
270
 
271
        cmp    [esp+24],dword 512       ;eof  - size
272
        jb     frnoread
273
        sub    [esp+24],dword 512
274
 
275
        jmp    frnew
276
 
277
      frnoread2:
278
 
279
        cmp    [esp+16],dword 0         ; eof without read ?
280
        je     frnoread
281
 
282
        pop    edi esi edx ecx
283
        add    esp,4
284
        pop    ebx     ; ebx <- eax : size of file
285
        add    esp,36
286
        mov    eax,6   ; end of file
287
        ret
288
 
289
      frnoread:
290
 
291
        pop    edi esi edx ecx
292
        add    esp,4
293
        pop    ebx     ; ebx <- eax : size of file
294
        add    esp,36
295
        xor    eax,eax  ;read ok
296
        ret
297
 
298
filedelete:
299
;--------------------------------------------
300
;
301
; filedelete - sys floppy
302
; in:
303
; eax -  pointer to filename 11 chars
304
;
305
; out:
306
; eax - 0 = successful, 5 = file not found
307
;
308
;--------------------------------------------
309
 
310
        sub    esp,32
311
        call   expand_filename
312
 
313
        push   eax ebx ecx edx esi edi
314
 
315
        call   rd_findfile
316
        je     fifoundd
317
        pop    edi esi edx ecx ebx eax ;file not found
318
        add    esp,32
319
        mov    eax,5
320
        ret
321
 
322
     fifoundd:
323
 
324
        mov    [edi-11],byte 0xE5       ;mark filename deleted
325
        add    edi,0xf
326
        movzx  eax,word [edi]
327
        mov    edi,eax                  ;edi = cluster
328
 
329
      frnewd:
330
 
331
        shl    edi,1                    ;find next cluster from FAT
332
        add    edi,0x280000
333
        movzx  eax,word [edi]
334
        mov    [edi],word 0x0           ;clear fat chain cluster
335
        mov    edi,eax
336
        cmp    edi,dword 0xff8          ;last cluster ?
337
        jb     frnewd
338
 
339
        pop    edi esi edx ecx ebx eax
340
        add    esp,32
341
        xor    eax,eax       ; file found
342
        ret
343
 
344
 
345
 
346
filesave:
347
;----------------------------------------------------------
348
;
349
; filesave - sys floppy
350
;
351
; eax points to filename 11 chars
352
;
353
;        eax      ; pointer to file name
354
;        ebx      ; buffer
355
;        ecx      ; count to write in bytes
356
;        edx      ; 0 create new , 1 append
357
;
358
;-----------------------------------------------------------
359
 
360
        sub  esp,32
361
        call expand_filename
362
        test edx,edx
363
        jnz  fsdel
364
        pusha
365
        call filedelete
366
        popa
367
 
368
      fsdel:
369
 
370
        call   ramdisk_free_space
371
        cmp    ecx,edi
372
        jbe    rd_do_save
373
        add    esp,32
374
        mov    eax,8    ;disk full
375
        ret
376
 
377
      rd_do_save:
378
 
379
        push   eax ebx ecx edx esi edi
380
 
381
        mov    edi,0x100000+512*18+512  ;Point at directory
382
        mov    edx,224 +1
383
        ; find an empty spot for filename in the root dir
384
     l20ds:
385
        dec    edx
386
        test   edx,edx
387
        jz     frnoreadds
388
     l21ds:
389
        cmp    [edi],byte 0xE5
390
        jz     fifoundds
391
        cmp    [edi],byte 0x0
392
        jz     fifoundds
393
        add    edi,32                   ; Advance to next entry
394
        jmp    l20ds
395
     fifoundds:
396
 
397
        push   edi                      ; move the filename to root dir
398
        mov    esi,[esp+4+20]
399
        mov    ecx,11
400
        cld
401
        rep    movsb
402
        pop    edi
403
        mov    edx,edi
404
        add    edx,11+0xf               ; edx <- cluster save position
405
        mov    ebx,[esp+12]             ; save file size
406
        mov    [edi+28],ebx
407
        mov    [edi+11],byte 0x20       ; attribute
408
; Ivan Poddubny 11/12/2003:
409
call get_date_for_file   ; from FAT32.INC
410
mov [edi+24],ax          ; date
411
call get_time_for_file   ; from FAT32.INC
412
mov [edi+22],ax          ; time
413
; End
414
        mov    edi,0x280000            ;pointer to first cluster
415
        mov    ecx,2849
416
        cld
417
      frnewds:
418
        xor    ax,ax
419
        repne  scasw
420
        mov    ebx,2848
421
        sub    ebx,ecx
422
        mov    [edx],bx                 ; save next cluster pos. to prev cl.
423
        mov    edx,edi                  ; next save pos abs mem add
424
        dec    edx
425
        dec    edx
426
        call   fdc_filesave
427
        pusha                           ; move save to floppy cluster
428
        add    ebx,31
429
        shl    ebx,9
430
        add    ebx,0x100000
431
        mov    eax,[esp+32+16]
432
        mov    ecx,512
433
        call   memmove
434
        popa
435
 
436
        mov    eax,[esp+12]
437
        cmp    eax,512
48 halyavin 438
        jbe    flnsa
1 ha 439
        sub    eax,512
440
        mov    [esp+12],eax
441
        mov    eax,[esp+16]
442
        add    eax,512
443
        mov    [esp+16],eax
444
        jmp    frnewds
445
 
446
     flnsa:
447
        dec    edi
448
        dec    edi
449
        mov    [edi],word 4095          ; mark end of file - last cluster
450
 
451
      frnoreadds:
452
 
453
        pop    edi esi edx ecx ebx eax
454
        add    esp,32
455
 
19 mario79 456
;        pusha
457
;        cli
458
;        call   fdc_commitfile
459
;        sti
460
;        popa
1 ha 461
 
462
        xor    eax,eax ;ok write
463
        ret
464
 
465
   rd_findfile:
466
   ;by Mihasik
467
   ;IN: eax - pointer to filename OUT: filestring+11 in edi or notZero in flags and fnf in eax,ebx
468
 
469
        mov    edi,0x100000+512*18+512  ;Point at directory
470
        cld
471
    rd_newsearch:
472
        mov    esi,eax
473
        mov    ecx,11
474
        rep    cmpsb
475
        je     rd_ff
476
        add    cl,21
477
        add    edi,ecx
478
        cmp    edi,0x100000+512*33
479
        jb     rd_newsearch
480
        mov    eax,5      ;if file not found - eax=5
481
        xor    ebx,ebx
482
        dec    ebx    ;ebx=0xffffffff and zf=0
483
     rd_ff:
484
        ret
485
 
486
  rd_getfileinfo:
487
     ;get date, time, size or attributes of file
488
     ;IN: eax - pointer to file, ebx - type of function: 12-get filesize, 13-get fileattr, 14-get filedate
489
     ;ecx - filelengh 0=root
490
     ;OUT: eax=0 - Ok or 5 - file not found ebx - date/time, size or attributes
491
        test   ecx,ecx
492
        jnz    no_getfinfo_root
493
        mov    eax,5      ;if root - fnf
494
        xor    ebx,ebx
495
        dec    ebx
496
        ret
497
    no_getfinfo_root:     ;if not root
498
        sub    esp,32
499
        call   expand_filename
500
        call   rd_findfile
501
        je     fifoundi
502
        add    esp,32      ;if file not found
503
        ret
504
    fifoundi:
505
        cmp    ebx,13
506
        jne    no_rd_attr
507
        movzx ebx,byte [edi]    ;get attributes
508
        jmp    rd_getfileinfo_end
509
     no_rd_attr:
510
        cmp    ebx,14
511
        jne    no_rd_date
512
        mov    ebx,dword [edi+11] ;get date/time
513
        jmp    rd_getfileinfo_end
514
     no_rd_date:
515
        mov    ebx,dword [edi+17] ;get size
516
     rd_getfileinfo_end:
517
        xor    eax,eax
518
        add    esp,32
71 diamond 519
        ret
520
 
521
; \begin{diamond}
522
 
523
uni2ansi_str:
524
; convert UNICODE zero-terminated string to ASCII-string (codepage 866)
525
; in: esi->source, edi->buffer (may be esi=edi)
526
; destroys: eax,esi,edi
527
	lodsw
528
	test	ax, ax
529
	jz	.done
530
	cmp	ax, 0x80
531
	jb	.ascii
532
	cmp	ax, 0x401
533
	jz	.yo1
534
	cmp	ax, 0x451
535
	jz	.yo2
536
	cmp	ax, 0x410
537
	jb	.unk
538
	cmp	ax, 0x440
539
	jb	.rus1
540
	cmp	ax, 0x450
541
	jb	.rus2
542
.unk:
543
	mov	al, '_'
544
	jmp	.doit
545
.yo1:
546
	mov	al, ''
547
	jmp	.doit
548
.yo2:
549
	mov	al, ''
550
	jmp	.doit
551
.rus1:
552
; 0x410-0x43F -> 0x80-0xAF
553
	add	al, 0x70
554
	jmp	.doit
555
.rus2:
556
; 0x440-0x450 -> 0xE0-0xEF
557
	add	al, 0xA0
558
.ascii:
559
.doit:
560
	stosb
561
	jmp	uni2ansi_str
562
.done:
563
	mov	byte [edi], 0
564
	ret
565
 
566
char_toupper:
567
; convert character to uppercase, using cp866 encoding
568
; in: al=symbol
569
; out: al=converted symbol
570
	cmp	al, 'a'
571
	jb	.ret
572
	cmp	al, 'z'
573
	jbe	.az
574
	cmp	al, ''
575
	jb	.ret
576
	cmp	al, ''
577
	jb	.rus1
578
	cmp	al, ''
579
	ja	.ret
580
; 0xE0-0xEF -> 0x90-0x9F
581
	sub	al, ''-''
582
.ret:
583
	ret
584
.rus1:
585
; 0xA0-0xAF -> 0x80-0x8F
586
.az:
587
	and	al, not 0x20
588
	ret
589
 
590
fat_get_name:
591
; in: edi->FAT entry
592
; out: CF=1 - no valid entry
593
; else CF=0 and ebp->ASCIIZ-name
594
; (maximum length of filename is 255 (wide) symbols without trailing 0,
595
;  but implementation requires buffer 261 words)
596
; destroys eax
597
	cmp	byte [edi], 0
598
	jz	.no
599
	cmp	byte [edi], 0xE5
600
	jnz	@f
601
.no:
602
	stc
603
	ret
604
@@:
605
	cmp	byte [edi+11], 0xF
606
	jz	.longname
607
	push	ecx
608
	mov	ecx, 8
609
	push	edi ebp ecx
610
@@:
611
	mov	al, [edi]
612
	inc	edi
613
	mov	[ebp], al
614
	inc	ebp
615
	loop	@b
616
	pop	ecx
617
@@:
618
	cmp	byte [ebp-1], ' '
619
	jnz	@f
620
	dec	ebp
621
	loop	@b
622
@@:
623
	mov	byte [ebp], '.'
624
	inc	ebp
625
	mov	ecx, 3
626
	push	ecx
627
@@:
628
	mov	al, [edi]
629
	inc	edi
630
	mov	[ebp], al
631
	inc	ebp
632
	loop	@b
633
	pop	ecx
634
@@:
635
	cmp	byte [ebp-1], ' '
636
	jnz	@f
637
	dec	ebp
638
	loop	@b
639
	dec	ebp
640
@@:
641
	and	byte [ebp], 0	; CF=0
642
	pop	ebp edi ecx
643
	ret
644
.longname:
645
; LFN
646
	mov	al, byte [edi]
647
	and	eax, 0x3F
648
	dec	eax
649
	cmp	al, 20
650
	jae	.no	; ignore invalid entries
651
	mov	word [ebp+260*2], 0	; force null-terminating for orphans
652
	imul	eax, 13*2
653
	add	ebp, eax
654
	test	byte [edi], 0x40
655
	jz	@f
656
	mov	word [ebp+13*2], 0
657
@@:
658
	push	eax
659
; now copy name from edi to ebp ...
660
	mov	eax, [edi+1]
661
	mov	[ebp], eax	; symbols 1,2
662
	mov	eax, [edi+5]
663
	mov	[ebp+4], eax	; 3,4
664
	mov	eax, [edi+9]
665
	mov	[ebp+8], ax	; 5
666
	mov	eax, [edi+14]
667
	mov	[ebp+10], eax	; 6,7
668
	mov	eax, [edi+18]
669
	mov	[ebp+14], eax	; 8,9
670
	mov	eax, [edi+22]
671
	mov	[ebp+18], eax	; 10,11
672
	mov	eax, [edi+28]
673
	mov	[ebp+22], eax	; 12,13
674
; ... done
675
	pop	eax
676
	sub	ebp, eax
677
	test	eax, eax
678
	jz	@f
679
; if this is not first entry, more processing required
680
	stc
681
	ret
682
@@:
683
; if this is first entry:
684
; buffer at ebp contains UNICODE name, convert it to ANSI
685
	push	esi edi
686
	mov	esi, ebp
687
	mov	edi, ebp
688
	call	uni2ansi_str
689
	pop	edi esi
690
	clc
691
	ret
692
 
693
fat_compare_name:
694
; compares ASCIIZ-names, case-insensitive (cp866 encoding)
695
; in: esi->name, ebp->name
696
; out: if names match: ZF=1 and esi->next component of name
697
;      else: ZF=0, esi is not changed
698
; destroys eax
699
	push	ebp esi
700
.loop:
701
	mov	al, [ebp]
702
	inc	ebp
703
	call	char_toupper
704
	push	eax
705
	lodsb
706
	call	char_toupper
707
	cmp	al, [esp]
708
	jnz	.done
709
	pop	eax
710
	test	al, al
711
	jnz	.loop
712
	dec	esi
713
	pop	eax
714
	pop	ebp
715
	xor	eax, eax	; set ZF flag
716
	ret
717
.done:
718
	cmp	al, '/'
719
	jnz	@f
720
	cmp	byte [esp], 0
721
	jnz	@f
722
	mov	[esp+4], esi
723
@@:
724
	pop	eax
725
	pop	esi ebp
726
	ret
727
 
728
rd_find_lfn:
729
; in: esi->name
730
; out: CF=1 - file not found
731
;      else CF=0 and edi->direntry
732
	push	esi ebp edi
733
	sub	esp, 262*2	; allocate space for LFN
734
	mov	ebp, esp	; ebp points to buffer
735
	mov	edi, 0x100000+512*19	; to root dir
736
.l1:
737
	call	fat_get_name
738
	jc	.l2
739
	call	fat_compare_name
740
	jz	.found
741
.l2:
742
	add	edi, 0x20
743
	cmp	edi, 0x100000+512*33
744
	jb	.l1
745
.notfound:
746
	add	esp, 262*2
747
	pop	edi ebp esi
748
	stc
749
	ret
750
.found:
751
; found
752
; if this is LFN entry, advance to true entry
753
	cmp	byte [edi+11], 0xF
754
	jnz	@f
755
	add	edi, 0x20
756
@@:
757
; folders are not supported
758
	cmp	byte [esi], 0
759
	jnz	.notfound
760
	add	esp, 262*2+4	; CF=0
761
	pop	ebp esi
762
	ret
763
 
764
;----------------------------------------------------------------
765
;
766
;  fs_RamdiskRead - LFN variant for reading sys floppy
767
;
768
;  esi  points to filename
769
;  ebx  pointer to 64-bit number = first wanted byte, 0+
770
;       may be ebx=0 - start from first byte
771
;  ecx  number of bytes to read, 0+
772
;  edx  mem location to return data
773
;
774
;  ret ebx = size or 0xffffffff file not found
775
;      eax = 0 ok read or other = errormsg
776
;
777
;--------------------------------------------------------------
778
fs_RamdiskRead:
779
	cmp	byte [esi], 0
780
	jnz	@f
781
	or	ebx, -1
782
	mov	eax, 10		; access denied
783
	ret
784
@@:
785
	push	edi
786
	call	rd_find_lfn
787
	jnc	.found
788
	pop	edi
789
	or	ebx, -1
790
	mov	eax, 5		; file not found
791
	ret
792
.found:
793
	test	ebx, ebx
794
	jz	.l1
795
	cmp	dword [ebx+4], 0
796
	jz	@f
797
	mov	ebx, [edi+28]
798
.reteof:
799
	mov	eax, 6		; EOF
800
	pop	edi
801
	ret
802
@@:
803
	mov	ebx, [ebx]
804
.l1:
805
	push	dword [edi+28]		; file size
806
	push	dword [edi+28]
807
	movzx	edi, word [edi+26]	; cluster
808
	push	ecx edx
809
.new:
810
	jecxz	.done
811
	test	edi, edi
812
	jz	.eof
813
	cmp	edi, 0xFF8
814
	jae	.eof
815
	lea	eax, [edi+31]		; bootsector+2*fat+filenames
816
	shl	eax, 9			; *512
817
	add	eax, 0x100000		; image base
818
; now eax points to data of cluster
819
	sub	ebx, 512
820
	jae	.skip
821
	lea	eax, [eax+ebx+512]
822
	neg	ebx
823
	push	ecx
824
	cmp	ecx, ebx
825
	jbe	@f
826
	mov	ecx, ebx
827
@@:
828
	cmp	ecx, [esp+12]
829
	jbe	@f
830
	mov	ecx, [esp+12]
831
@@:
832
	mov	ebx, edx
833
	call	memmove
834
	add	edx, ecx
835
	sub	[esp], ecx
836
	sub	[esp+12], ecx
837
	pop	ecx
838
	xor	ebx, ebx
839
	cmp	[esp+8], ebx
840
	jnz	.skip
841
	jecxz	.done
842
	jmp	.eof
843
.skip:
844
	movzx	edi, word [edi*2+0x280000]	; find next cluster from FAT
845
	jmp	.new
846
.eof:
847
	pop	edx ecx ebx ebx
848
	jmp	.reteof
849
.done:
850
	pop	edx ecx ebx ebx edi
851
	xor	eax, eax
852
	ret
853
 
854
; \end{diamond}