; CPSWLD.ASM
;       KERMIT - (Celtic for "FREE")
;
;       This is the CP/M-80 implementation of the Columbia University
;       KERMIT file transfer protocol.
;
;       Version 4.0
;
;       Copyright June 1981,1982,1983,1984
;       Columbia University
;
; Originally written by Bill Catchings of the Columbia University Center for
; Computing Activities, 612 W. 115th St., New York, NY 10025.
;
; Contributions by Frank da Cruz, Daphne Tzoar, Bernie Eiben,
; Bruce Tanner, Nick Bush, Greg Small, Kimmo Laaksonen, Jeff Damens, and many
; others. 
;
;       Multi-file access subroutine.  Allows processing of multiple files
;       (i.e., *.ASM) from disk.  This routine builds the proper name in the
;       FCB each time it is called.  This command would be used in such pro-
;       grams such as modem transfer, tape save, etc. in which you want to
;       process single or multiple files.
;       Note that it will fail if more than 256 entries match the wildcard.
;
; revision history:
; edit 4: June 20, 1986, by OBSchou.  Added stuff at top and tail of routine
;       to support multiple FCBs.  If the routine get to mfn01 (Search for next)
;       then the next file found gets its fcb added to the buffer.  Once no 
;       more files have been found, the mfflg3 flag is set non-zero. 
;       The first thing to test on entry is whether a disk access
;       is needed.  Either way, the routine should return the next file name
;       in the fcb, or return with the carry flag set if there are no more
;       files to do.  Once there is a carry flag set for the return, all 
;       temporary flags are reset. Get all that?
;
; edit 3: July 27, 1984
;       support LASM: remove exclamation points, link to CP4CMD.
;
; edit 2: June 7, 1984 (CJC)
;       formatting and documentation; add module version string; redo movfcb,
;       in preparation for moving DMA buffer (later...).
;
; edit 1: May, 1984 (CJC)
;       extracted from CPMBASE.M80 version 3.9; modifications are described
;       in the accompanying .UPD file.
;
wldver:	db	'CPSWLD.ASM (4)  20-Jun-86$'

;       The FCB will be set up with the next name, ready to do normal 
;       processing (OPEN, READ, etc.) when routine is called.
;
;       Carry is set if no more names can be found
;
;       MFFLG1 is count/switch [0 for first time thru, pos for all others]
;       MFFLG2 is counted down for each successive GETNEXT file call
;       MFFLG3 is set to the last remaining FCBs buffered once Search for next
;               file fails with files in the buffer.
;
;       Technique used is to repeat SFIRST/SNEXT sequence N+1 times for each
;       successive call, till sequence fails. CP/M does NOT allow disk-handling
;       between SFIRST and SNEXT.
;       called by: send, seof, dir

mfname:	ora	a		; clear carry
	push	b		;Save registers
	push	d
	push	h
	jmp	mfnam0		; skip over the next bit (which is entered from elsewhere)

;[4] Get the FCB counter and see if we have any fcbs already.
mfnam1:	lxi	h,fcb0
	shld	xfcbptr		; reset the pointer if we are to return an FCB

mfnam0:	lda	fcbcnt
	ana	a		; if none, then we may have to get some from disk
	jz	mfn00		; see later on
	lhld	xfcbptr		; we have some, so give the next one to the user
	lxi	d,fcb		; move from (hl) to (de) for length bc
	lxi	b,12
	call	mover
	xra	a
	sta	fcbext		; clear fcb extents and such
	sta	fcbrno		; like record number
	lhld	xfcbptr		; point to next fcb
	lxi	d,fcblen
	dad	d		; yup
	shld	xfcbptr
	lda	fcbcnt
	dcr	a
	sta	fcbcnt		; decrease the number of fcbs we have
	xra	a		; clear carry
	jmp	mffix1		; and exit as if were all done

mfn00:	lda	mfflg3		; no more FCBs for the user, any more on disk?
	ana	a
	jnz	mffix2		; no, then set the carry flag to say so.
	lxi	h,fcb0		; now reset the fcb pointers and counter
	shld	xfcbptr
	xra	a
	sta	fcbcnt
;[4] end of this addition.  See below as well.


	mvi	c,setdma	;Init DMA addr, FCB
	lxi	d,80H
	call	bdos
	xra	a		;A = 0
	sta	fcbext		;clear extension
	lda	mfflg1		;find out if "second" call in row
	ora	a
	jnz	mfn01		;Were here before
	sta	mfflg2
	lxi	h,fcb
	lxi	d,mfreq
	lxi	b,12
	call	mover		;.from FCB to MFREQ
	mvi	c,SFIRST	;Search first
	lxi	d,fcb
	call	bdos
	jmp	mfn02		;and check results

mfn01:	dcr	a
	sta	mfflg2		;store down-counter
	lxi	h,mfreq		;SFIRST REQ name
	lxi	d,fcb
	lxi	b,12
	call	mover		;.from MFREQ to FCB
	mvi	c,sfirst	;Search first old one,we got it before
	lxi	d,fcb
	call	bdos		;no error's expected -we got that before
mfn01a:
	mvi	c,snext		;Search next
	call	bdos
mfn02:	push	psw
	lda	mfflg2		;get "repeat file counter"
	ora	a
	jz	mfn02a		;if zero, check if SNEXT had ERROR
	dcr	a		;count down
	sta	mfflg2		;store back
	pop	psw		;no error-check, we got it before
	jmp	mfn01a		;next SNEXT

mfn02a:	pop	psw
	ora	a
	jm	mffi2a		;No (more) found
	call	movfcb		;move data to fcb
	lda	mfreq		;the original disk-designator
	sta	fcb		;back into fcb
	lda	mfflg1		;get file-flag
	inr	a		;increment
	sta	mfflg1		;and store for next go-around
	mvi	a,0		;Setup FCB
	sta	fcbext		;clean up FCB for OPEN etc
	sta	fcbrno
	lhld	xfcbptr		;[4] like here 
	xchg
	lxi	h,fcb		;[4] from fcb space
	lxi	b,12
	call	mover
	lhld	xfcbptr		;[4] now lets update the pointers
	lxi	d,fcblen
	dad	d
	shld	xfcbptr		;[4] new pointer
	lda	fcbcnt		;[4] now the fcb counter
	inr	a
	sta	fcbcnt
	cpi	maxfcb		;[4] any more spare space?
	jp	mfnam1		;[4] nope, so get first fcb and return
	lxi	d,fcb		; else restore the file to serach for
	lxi	h,mfreq
	lxi	b,12		; copy the original fcb to fcb
	call	mover
	jmp	mfn01a		; and look for next match.

mffix1:	pop	h		;restore registers
	pop	d
	pop	b
	ret			;and return

mffi2a:
	sta	mfflg3		;[4] no more FCBs from disks to be had, but
	lda	fcbcnt		;[4]we have some in the buffer, havet we?
	ana	a
	jnz	mfnam1		;[4] yes, so all's ok.  Get an fcb and return,

mffix2:	xra	a
	sta	mfflg3		;[4] clear the new flag (=no more fcbs at all)
	sta	mfflg2		;[4] may as well do the others, as we're not comming again
	sta	mfflg1		;[4]
	stc			;set carry
	jmp	mffix1		;return with CARRY set

;       copy directory entry to FCB
;       called with A/ entry number in directory (0-3)
;                   directory block in DMA buffer (buff)

movfcb:	add	a
	add	a
	add	a
	add	a
	add	a		;* 32
	mov	c,a		; copy offset to bc
	mvi	b,0		; (high byte is zero)
	lxi	h,buff		; get start of disk buffer
	dad	b		; calculate start of directory entry
	lxi	d,fcb
	lxi	b,12
	call	mover
	ret

;       Data storage for MFNAME (multi-file access)
mfreq:	DS	12		;Requested name
mfflg1:	DB	0		;First time thru flag for MFNAME
mfflg2:	DB	0		;Down counter for MFNAME
mfflg3:	DB	0		;[4] Non zero if no more FCBs from disk,
				;[4] but we still have some in buffer
;
IF lasm
	LINK	CPSCMD
ENDIF;lasm