;TRS-80 Model 100 -- Kaypro File Transfer Utility
;
;Transfers ASCII files to/from Model 100 at
;19200 baud.  Use setting 98N1E and Save & Load on Model 100
;Examples are:
;   In TEXT: Save to:com:98n1e
;   in BASIC: Save"com:98n1e"
;
;Requires RS-232 cable with "Null Modem Adapter"
;for computer interconnect.
;
;Written by Don Corbitt, Feb 1984
;
;Modified by Phil Wheeler, July 1984
;
;
	org	100h
boot	equ	0
bdos	equ	5
fcbl	equ	5ch
dbuff	equ	80h		; Disk i/o buffer
conin	equ	1		; Get char from console - wait
printf	equ	9		; Print buffer function (DE) until '$'
inlinf	equ	10		; Read buffer from console
openf	equ	15		; Open file,
closef	equ	16		; Close file after write
search	equ	17		; Look for file - ff if not found
readf	equ	20		; Read block from file
writef	equ	21		; Write block to file
makef	equ	22		; Make a file entry
baud	equ	0		; Port to set baud rate
uartd	equ	4		; Uart data port
uarts	equ	6		; Uart status port
bell	equ	7
cr	equ	13
lf	equ	10
nul	equ	0
eof	equ	1ah		; End of file signal
xoff	equ	19		; Stop transmission
xon	equ	17		; Start transmission

start:
	mvi	a,15		; 19200 baud
	out	baud
	mvi	b,9
	lxi	h,initcom	; String of chars to initialize uart
	mvi	c,uarts		; Set stat for 98n1e
	db	0edh,0b3h	; Otir
loop1:
	lxi	d,menu
	mvi	c,printf
	call	bdos
	mvi	c,conin
	call	bdos
	call	touppr		; Get upper case letters
	cpi	'Q'		; Return to CP/M
	rz
	cpi	'S'		; Send file to M100
	jz	send
	cpi	'R'		; Receive file from M100
	jz	receive
	jmp	loop1		; Try again
send:
	lxi	d,sndmsg	; 'Enter file to send'
	mvi	c,printf
	call	bdos
	call	gfspec		; Get the file name, and see if it exists
	jnz	sendit		; It exists, so send it
	lxi	d,nfmsg		; 'File doesn't exist'
	mvi	c,printf
	call	bdos
	jmp	loop1		; Try again
sendit:
	lxi	h,stbuff	; End of program - start of buffer
	push	h
	lxi	d,fcbl
	mvi	c,openf		; Open file and read contents
	call	bdos
sloop:	mvi	c,readf
	lxi	d,fcbl
	call	bdos
	ana	a		; Nz = EOF
	jnz	sendfil
	pop	d		; Current end of data
	lxi	h,dbuff		; Dma buffer - disk buffer
	lxi	b,80h		; Size of buffer
	db	0edh,0b0h	; Ldir (hl)->(de)
	push	d		; New end of data
	jmp	sloop

sendfil:
	call	motoff
;	in	28		; get contents of disk select port
;	ani	252		; de-select both drives
;	ori	64		; turn off motor
;	out	28		; rewrite port
;	mvi	c,closef	;close file now
;	lxi	d,fcbl		;set params
;	call	bdos
	pop	h		; Arrange stack - discard this value
	lxi	h,stbuff	; Buffer ended with EOF, OK?
sloop1:	mov	c,m		; Get first char
	inx	h
	call	rsout		; Send char
	cpi	eof
	jz	send		; End of file - send new file??
	call	rsist		; Char waiting??
	jz	sloop1
	call	rsin		; Get char
	cpi	xoff		; If xoff, then wait.....
	jnz	sloop1		; Else ignore it
sloop2:	call	rsin
	cpi	xon
	jnz	sloop2
	jmp	sloop1


;rs output status. Z if uart busy, NZ otherwise.  A modified.

rsost:
	in	uarts
	ani	4
	ret

;RS character out, character in C

rsout:				; Send byte in C to uart
	call	rsost
	jz	rsout
	mov	a,c
	out	uartd
	ret

;rs input status.  Z if no char waiting, NZ if char ready.

rsist:
	in	uarts
	ani	1		; Char waiting?
	ret

;get char from uart and return in A.

rsin:
	call	rsist
	jz	rsin		; Try again if one not waiting
	in	uartd
	ret

receive:
	lxi	d,recmsg
	mvi	c,printf
	call	bdos
	call	gfspec
	jz	rcvit		; Doesn't exist, so get it
	lxi	d,fexmsg
	mvi	c,printf
	call	bdos
	jmp	loop1
rcvit:
	lxi	d,fcbl
	mvi	c,makef
	call	bdos
	lxi	h,stbuff
rloop:	call	rsin		; Get a char
	mov	m,a		; And put in buffer
	inx	h
	cpi	eof		; If not last
	jnz	rloop		; Then get another
	lxi	h,stbuff
secloop:
	lxi	d,dbuff
	mvi	b,80h
byteloop:
	mov	a,m
	stax	d
	cpi	eof
	jz	lastone
	inx	h
	inx	d
	dcr	b
	jnz	byteloop
	call	wsect
	jmp	secloop

lastloop:
	stax	d
lastone:
	inx	d
	dcr	b
	jnz	lastloop
	call	wsect
	lxi	d,fcbl
	mvi	c,closef
	call	bdos
	jmp	receive		; End of file - get another one??
wsect:
	push	h		; Save position in buffer
	lxi	d,fcbl
	mvi	c,writef
	call	bdos
	pop	h
	ret
touppr:
	cpi	'a'
	rc
	cpi	'z'+1
	rnc
	ani	5fh
	ret

gfspec:
	lxi	h,fcbl
	mvi	b,33		; 33 bytes to erase
	xra	a
erase:	mov	m,a
	inx	h		; Next byte in fcbl
	dcr	b
	jnz	erase
	lxi	h,fcbl+1
	mvi	b,11		; File name block - default spaces
	mvi	a,32		; Space
erase1:	mov	m,a
	inx	h
	dcr	b
	jnz	erase1
	lxi	d,fbuff		; Buffer to hold file name
	push	d		; Save start of buffer
	mvi	c,inlinf	; Read line from keyboard
	call	bdos		; Get line
	pop	h		; Start of buffer (max count)
	inx	h		; Actual value returned
	mov	a,m
	ana	a		; No chars in queue??
	mov	b,a		; Count in b
	jnz	congsp		; If chars, continue get file spec
	pop	h		; Remove one level of subroutines
	jmp	loop1		; Start over with menu
congsp:
	inx	h		; First char of fspec
	inx	h		; Second char of fspec
	mov	a,m		; Get ':' if in fspec
	dcx	h		; First char of fspec
	cpi	':'
	mvi	a,0		; Zero (A) without affecting flags
	jnz	noprefix
	dcr	b
	dcr	b		; Skipping first two chars of buffer
	mov	a,m
	call	touppr
	sbi	'@'		; Get value from 1 to 17 (A to P)
	sta	fcbl		; Set drive number
	inx	h		; Point to ':'
	inx	h		; Point to first char of name
noprefix:
	lxi	d,fcbl+1	; Start of name section of fcbl
nprloop:
	mov	a,m
	call	touppr
	cpi	'.'
	jz	stext		; Start extension
	stax	d		; Put in fcbl
	inx	h
	inx	d
	dcr	b
	jnz	nprloop
exist:
	mvi	c,search
	lxi	d,fcbl
	call	bdos
	inr	a
	push	psw
	call	motoff
	pop	psw
	ret
motoff:	in	28
	ori	64
	out	28
	ret
stext:
	inx	h		; Skip '.'
	lxi	d,fcbl+9	; Start of extension
	dcr	b
	jz	exist		; Done
extloop:
	mov	a,m
	call	touppr
	stax	d
	inx	h
	inx	d
	dcr	b
	jnz	extloop
	jmp	exist


fbuff:	db	18
	ds	18


fexmsg:	db	bell,cr,lf,'File already exists',cr,lf,'$'
recmsg:	db	cr,lf,'File to recieve: $'
sndmsg:	db	cr,lf,'File to send: $'
nfmsg:	db	bell,cr,lf,'File doesn''t exist!!',cr,lf,'$'
menu:	db	cr,lf,lf
	db	'Use with COM:98N1E & Save or Load on Model 100'
	db	cr,lf,'Works with TEXT or BASIC',cr,lf,lf
	db	'Selections are:',cr,lf,lf
	db	'  [Q] Return to CP/M',cr,lf,'  [S] Send file to M100'
	db	cr,lf,'  [R] Receive file from M100',cr,lf
	db	cr,lf,'Enter your selection: $'
initcom:
	db	00h,18h,04h,44h,03h,0c1h,05h,0eah
endbuff:
	dw	0
stbuff	equ	$		; Start of free space
	end	start
—