; CP4CPM.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. 
;
;	This file duplicates the CP/M DIR and ERA functions so we don't have
;	to exit.
;
; revision history:
; edit 3: July 8, 1984 (CJC)
;	Merge modifications from Toad Hall: support LASM (linked by CP4TT,
;	links to CP4WLD), use prcrlf where appropriate.
;
; edit 2: June 5, 1984 (CJC)
;	documentation and formatting; delete unused code (dir13); add module
;	version string.
;
; edit 1: May, 1984 (CJC)
;	extracted from CPMBASE.M80 version 3.9; modifications are described in
;	the accompanying .UPD file.
;
cpmver:	db	'CP4CPM.ASM (3)  8-Jul-84$'	; name, edit number, date

npl	EQU	04H	;Number of names per line for dir command.

;	This is the DIR command.  Display the name and size of all files
;	matching the filespec.
;	here from: kermit
;
;	Note: This is abstracted from Keith Peterson's DIRF.ASM
;		directory print function.  Thanks again Keith.
;
;
dir:	lxi	d,fcb		;Where to put the data, if any.
	mvi	a,cmifin
	call	comnd		;Parse a full or piece of file-spec
	 jmp	dir2		;Didn't get a FULL file-spec
	jmp	dir4		;lets do it
;
;
;Make FCB all '?' to match any file
dir2:	lda	fcb
	cpi	' '		;CMIFIN leaves that as ' '
	jnz	dir2a		;he typed at least x:
	xra	a
	sta	fcb		;default drive
dir2a:	lxi	h,fcb+1
	mvi	b,11		;FN+FT count.

dir3:	mvi	m,'?'		;Store '?'s in FCB.
	inx	h
	dcr	b
	jnz	dir3
;Print signon message and drive name
dir4:	lda	fcb
	ora	a		;if not zero, get default
	jnz	dir4a
	lda	curdsk		;get default
dir4a:	adi	'A'-1		;Asciize it
	sta	dnam14		;Save it in message.
	call	prcrlf
	lxi	d,inms14	;Point to message
	call	prtstr
;
;Initialize number of names per line counter
	mvi	a,npl		;Nr. names per line.
	sta	nnams		;Init counter.
;
	call	dir26		;Get disk parameters
dir5:	call	mfname		;get some names
	jnc	dir6		;got one
	jmp	dir17		;got none - do summary

dir6:				;Check for console break
	mvi	c,consta	;Ck status of kbd.
	call	bdos
	ora	a		;Any key pressed?
	jz	dir6a		;nope, keep going
	mvi	c,conin
	call	bdos		;gobble key
	jmp	dir17		;and print summary only

;Print an entry
dir6a:	lxi	h,fcb+1		;point to Filename
	mvi	b,8		;File name length.
	call	dir11		;Type filename.
	mvi	a,'.'		;Period after FN.
	call	dir10
	mvi	b,3	 	;Get the filetype.
	call	dir11
	call	dir25		;print size
	lxi	h,nnams	 	;Point to names counter.
	dcr	m	 	;One less on this line.
	push	psw
	cnz	dir7	 	;No cr-lf needed, do fence.
	pop	psw
	cz	dir12	 	;Cr-lf needed.
	jmp	dir5

;Print space, fence character, then space
dir7:	call	dir9
	mvi	a,':'	 	;Fence character.
	call	dir10
	jmp	dir9

; dir8 - Print two spaces
; dir9 - Print one space
; dir10 - Type char in A register
dir8:	call	dir9
dir9:	mvi	a,' '
dir10:	push	b
	push	d
	push	h
	mov	e,a	 	;Char to E for CP/M.
	mvi	c,conout	;Write char to console function.
	call	bdos
	pop	h
	pop 	d
	pop	b
	ret

;Type (B) characters from memory (HL)
dir11:	mov	a,m
	ani	7FH	 	;Remove CP/M 2.x attributes.
	call	dir10
	inx	h
	dcr	b
	jnz	dir11
	ret

;CR-LF routine. HL=NNAMS upon entry
dir12:	push	b
	push	d
	push	h
	call	prcrlf		;Print CR/LF [Toad Hall]
	pop	h		;(did use call to dir10, but slooow)
	pop	d
	pop	b
	mvi	m,npl	 	;Number of names per line.
	ret

;Exit - All done, return via jmp (as for all main commands)
dir16:	call	prcrlf
	lda	curdsk
	dcr	a		;relative to 0
	mov	e,a
	mvi	c,logdsk
	call	bdos		;back to "logged in" disk
	jmp	kermit	 	;...and return to kermit.

;
;Determines free space remaining
;
dir17:	xra	a
	sta	mfflg1		;clean up MFNAME
	sta	mfflg2
	lda	fcb		; get drive number from FCB
	ora	a
	jz	dir18		; default?
	dcr	a		; no, make requested drive current drive.
	mov	e,a
	mvi	c,logdsk
	call	bdos
dir18:	call	sysspc		; get space available for current drive
	push	h
	lxi	d,inms15	;"Drive "
	call	prtstr
	lda	fcb		;If no drive, get
	ora	a		;logged in drive
	jnz	dir24
	mvi	c,rddrv
	call	bdos
	inr	a
dir24:	adi	'A'-1
	sta	inms16
	lxi 	d,inms16	;"x has "
	call 	prtstr
	pop	h		;Get number of bytes available
	call	nout
	lxi	d,inms17	;"K bytes free"
	call	prtstr
	jmp	dir16		;all done

;Compute the size of the file

dir25:	mvi	c,cflsz		;get file-size
	lxi	d,fcb
	call	bdos
	lda	fcbrno		;shift least sign. part
	lxi	b,0		;init bc
	mov	l,a
	ani	7
	jz	dir250		;even K
	lxi	b,1		;save for later
dir250:	push	b		;save 0 or 1 to add to size
	mvi	b,3		;shift 3 bits
dir25a:	xra	a		;clear sign
	lda	fcbrno+1	;get most sig byte
	rar			;shift right
	sta	fcbrno+1	;put back
	lda	fcbrno		;get least sig part
	rar
	sta	fcbrno
	dcr	b		;loop 3 times
	jnz	dir25a
	mov	l,a		;size in HL
	lda	fcbrno+1
	mov	h,a
	pop	b		;get 0 or 1
	dad	b		;round up to KB used
	lda	bmask		;get (sectors/block)-1
	rrc
	rrc			;get (K/block)-1
	rrc
	ani	1FH
	mov	c,a
	dad	b		;add (K/block)-1 to size to round up
	cma			;make a mask
	ana	l		;truncate after rounding up
	mov	l,a
	push	h
	lxi	b,-10		;subtract 10
	dad	b
	jc	dir25d		;>= 10
	call	dir8		; print a leading space
	jmp	dir25e

dir25d:	pop	h		;get size again
	push	h
	lxi	b,-100		;subtract 100
	dad	b
	jc	dir25e		;>= 100
	call	dir9		; print another leading space
dir25e:	call	dir9		;a space
	pop	h		;get size back
	call	nout		;..go print it
	mvi	a,'k'		;..and follow with K size
	call	dir10
	ret

dir26:	mvi	c,gtdpar 	;current DISK PARAMETER BLOCK
	call	bdos
	inx	h
	inx	h
	mov	a,m		;Get Block Shift Factor
	sta	bshiftf
	inx	h		;Bump to Block Mask
	mov	a,m		;get it
	sta	bmask
	inx	h
	inx	h
	mov	e,m		;Get Max Block number
	inx	h
	mov	d,m
	xchg
	shld	bmax		;Put it away
	ret
;
;	ERA command - erase a CP/M file
;	here from: kermit

era:	mvi	a,cmifi		;Parse a file-spec
	lxi	d,fcb		;into FCB
	call	comnd
	 jmp	kermit		;bad parse
	lxi	d,fcb
	mvi	c,sfirst	;check if valid
	call	bdos
	inr	a		;0 if FILE not found
	jnz	era1		;found at least one
	lxi	d,erms15	;"unable to find file"
	call	prtstr
	jmp	kermit

era1:	lxi	d,fcb
	mvi	c,delf
	call	bdos
	lxi	d,inms18	;" File(s) erased"
	call	prtstr
	jmp	kermit

IF lasm
	LINK	CP4WLD
ENDIF;lasm  [Toad Hall]
