; TX1.MAC
; contains a C-callable function: 

;	int tx1(fname)
;	char *fname;

; which transmits the file given by the (unambiguous) file name fname
; over the console to be received by RX.
; It returns a non-zero value (TRUE) if the file was successfully
; transmitted, and zero (FALSE) if the file could not be opened or an
; error occurred during file transfer.

; For transfer protocol, see comments in RX.MAC.

; If the file name is empty (i.e., has zero length), 
; end of transmission (EOT) is signalled and TX1 returns TRUE.

; Note: TX1 expects the File Control Block (FCB) be already set up
; 	by a previous call to either getffn() or getnfn() in GFN.MAC
;	and be accessable for the linker as public variable FCB.

; Parameter passing complies with ECO-C conventions (see pp.63
; of the ECO-C manual).

; This is the one-file version of TXF.MAC.

; 14 Feb 1988	A.Herrmann
; 09 Mar 1988	changed to initial ready-signal;
;		conditional assembly for use within TERM


MSG	EQU	1		;Output message = yes


BDOS	EQU	5
DMAADR	EQU	080H
DMASIZ	EQU	128

WBOOT	EQU	0

CONSTA	EQU	6		;console status port
CONDAT	EQU	4		;console data port

TEMPTY	EQU	2		;transmit buffer empty bit
RAVAIL	EQU	0		;receive char available bit

ACK	EQU	0FH		;Acknowledge
EOT	EQU	7FH		;End Of Transmission

TRUE	EQU	1
FALSE	EQU	0


	.Z80

	EXTRN	FCB		;File Control Block

	INCLUDE B:FNCENT.LIB	;macro for parameter handling

TX1::
	FNCENT 2		;2 bytes for input parameter	
	LD HL,2+4		;get input parameter
	ADD HL,SP
	LD E,(HL)
	INC HL
	LD D,(HL)		;DE = pointer to name string
	CALL TXFILE
	JP NZ,TFEXIT

ERREXT:
	LD HL,FALSE		;return FALSE if error on attempt to open file 
	JP $RTNI##		; or during transfer

TFEXIT:
	LD HL,TRUE
	JP $RTNI##		;return upon successful completion

;--------------------------------------------------------------------------

TXFILE:
	PUSH DE
	CALL WAITAK		;Wait for ready-signal
	POP DE
	LD A,(DE)		;DE -> File name string
	OR A
	JP NZ,TXFIL1
	LD A,EOT		;Empty file name: Signal end of transmission
	CALL SENDCH
	JP TXOKAY
TXFIL1:
	LD DE,FCB
	LD C,15
	CALL BDOS		;open file with FCB
	CP 0FFH
	JP NZ,TXFIL2
	LD A,EOT		;File not found: Signal end of transmission
	CALL SENDCH
	JP TXERR

TXFIL2:
	CALL TXNAME
	CALL WAITAK		;wait for ACK
	CALL TXSIZE
	CALL WAITAK
	CALL TXDATA

	LD DE,FCB
	LD C,16
	CALL BDOS		;close file

	CALL WAITAK		;Wait for final acknowledgement

	IF MSG
	LD DE,ACKMSG
	LD C,9
	CALL BDOS
	ENDIF

TXOKAY:	LD A,TRUE
	OR A
	RET			;Return with Z = 0

TXERR:	LD A,FALSE
	OR A
	RET			;Return with Z = 1

	IF MSG
ACKMSG:	DB ' acknowledged'
	DB '$'
	ENDIF

;--------------------------------------------------------------------------

TXNAME:				;transmit the file name
	LD HL,FCB
	INC HL			;WITHOUT the disk number
	LD B,8
	CALL TXSTR
	PUSH HL
	LD A,'.'
	CALL SENDCH
	POP HL
	LD B,3
	CALL TXSTR
	LD A,EOT		;end file name with EOT
	CALL SENDCH
	RET

TXSTR:				;transmit B chars
	LD A,(HL)		;starting at HL
	INC HL			;skipping the Blanks
	CP ' '
	JR Z,TXSTR1
	PUSH HL
	PUSH BC
	CALL SENDCH
	POP BC
	POP HL
TXSTR1:	DJNZ TXSTR
	RET


TXSIZE:				;transmit the number of 128-byte records
	LD DE,FCB
	PUSH DE
	LD C,35
	CALL BDOS		;get file size
	POP DE
	LD HL,33		;random rec size in FCB
	ADD HL,DE
	LD A,(HL)
	PUSH HL
	CALL SENDCH		;low byte first
	POP HL
	INC HL
	LD A,(HL)
	CALL SENDCH		;high byte
	RET


TXDATA:				;transmit file data
	LD DE,DMAADR
	LD C,26
	CALL BDOS		;set DMA address

TXDAT1:	LD DE,FCB
	LD C,20
	CALL BDOS		;read next sequential record
	OR A
	JP NZ,TXDONE

	LD HL,DMAADR
	LD B,DMASIZ
TXDAT2:	LD A,(HL)
	INC HL
	PUSH HL
	PUSH BC
	CALL SENDCH
	POP BC
	POP HL
	DJNZ TXDAT2
	CALL WAITAK
	JP TXDAT1
TXDONE:	RET

	
SENDCH:				;send char in A via console port
	PUSH AF
SENDC1:	IN A,(CONSTA)
	BIT TEMPTY,A
	JR NZ,SENDC2		;Wait until transmit buffer empty
	CALL CHKKEY		; or abort upon Ctrl/C from keyboard
	JR SENDC1
SENDC2:	POP AF
	OUT (CONDAT),A
	RET

WAITAK::			;wait for ACK from console port
	IN A,(CONSTA)
	BIT RAVAIL,A
	JR NZ,WAITA1		;Wait until character available
	CALL CHKKEY		; or abort upon Ctrl/C from keyboard
	JR WAITAK
WAITA1:	IN A,(CONDAT)
	CP ACK
	JR NZ,WAITAK		;Try again if not ACK

	IF MSG
	PUSH AF
	LD E,'.'
	LD C,6
	CALL BDOS		;Display '.' on screen
	POP AF
	ENDIF

	RET

CHKKEY:				;check if Ctrl/C from keyboard
	LD C,6
	LD E,0FFH
	CALL BDOS
	CP 03
	JP Z,WBOOT		;Warmboot
	RET

	END
