	name	  talk
	page	  66,80
	.lfcond   ;conditional assem
	title	  TALK-dumb terminal
;
;Talk- a dumb terminal emulator
;      for the IBM-PC, illustrates
;      ROM-BIOS asynch. support.
;      copyright (c)1983 RAY DUNCAN
;      May be freely reproduced for
;      non-commercial use.
CR   EQU  0DH			     ;ASCII carriage return
LF   EQU  0AH			     ;ASCII line feed
ESC  EQU  1BH			     ;ASCII escape code
;
ECHO EQU  0			     ;flags conditional assembly 0=full duplex
;								 1=half duplex
COM_PORT EQU 0			     ;set to 0 or 1 0=comm1, 1=comm2.
;
CSEG SEGMENT PARA PUBLIC 'CODE'
;
ASSUME CS:CSEG,DS:DSEG,SS:STACK
;
TALK  PROC FAR			     ;ENTRY POINT FROM DOS
  PUSH	DS			     ;save DS:0000 on stack for return to DOS
  XOR	AX,AX			     ;make data area accessible
  PUSH	AX			     ;
  MOV	AX,SEG DSEG		     ;
  MOV	DS,AX			     ;
  CALL	COM_STAT		     ;Check that modem is on-line by checking
  TEST	AL,20H			     ;the "DATA SET READY" bit in status word.
  JNZ	TALK1			     ;if the bit is on then proceed.
  MOV	DX,OFFSET MSG1		     ;if the bit is off, print a message and
  JMP	TALK6			     ;return to DOS.
;
TALK1:				     ;let the user know the modem is on.
  MOV	AH,15			     ;use "get mode" of rom bios video driver
  INT	10H			     ;to get the number of columns, for CLEAR
  DEC	AH			     ;
  MOV	COLUMNS,AH		     ;
  CMP	AL,7			     ;make sure screen is in text mode
  JE	TALK2			     ;mode 7 ok proceed
  CMP	AL,3			     ;
  JBE	TALK2			     ;mode 0-3 is ok proceed
  MOV	DX,OFFSET MSG2		     ;all else is illegal. return and show
  JMP	TALK6			     ;message.
;
TALK2:				     ;clear screen,reverse video, cursor home.
  MOV	BH,70H			     ;
  CALL	CLEAR			     ;
  CALL	HOME			     ;
;
;******************************************************************************
;		 THIS IS THE MAIN BODY OF THE PROGRAM
;******************************************************************************
;
TALK3:	CALL PC_STAT		     ;check for keybrd buffer w/ character
  JZ	TALK4			     ;Nope!
  CALL	PC_IN			     ;read character from keyboard.
  CMP	AL,ESC			     ;is it the ESCape key?
  JE	TALK5			     ;Yes, it is, lets exit this turkey!
  IF	ECHO			     ;CONDITIONAL if echo = 0 then dont
  PUSH	AX			     ;assemble this.
  CALL	PC_OUT			     ;save character, send it to display
  POP	AX			     ;restore character.
ENDIF				     ;END CONDITIONAL
  CALL	COM_OUT 		     ;write the character to the comm port
;
TALK4:	CALL COM_STAT		     ;Check for character in the comm port
  JZ	TALK3			     ;No? loop
  CALL	COM_IN			     ;read character from comm port
  CALL	PC_OUT			     ;display it
  JMP	TALK3			     ;start from TALK3 and do it again
;
TALK5:				     ;EXIT fom talk1,
  MOV	BH,07H			     ;restore normal video
  CALL	CLEAR			     ;clear screen
  CALL	HOME			     ;set cursor upper left
  MOV	DX,OFFSET  MSG3 	     ;point to sign off message
;
TALK6:MOV AH,9			     ;call function 9 to display "GOOD BYE..."
  INT	21H			     ;do it.
RET				     ;Now return to dos
;
TALK ENDP			     ;
;
COM_STAT PROC NEAR		     ;use ROM BIOS function 3
  MOV	DX,COM_PORT		    ;to get
  MOV	AH,3			     ;comm port status
  INT	14H			     ;
  TEST	AH,098H 		     ;check error flags for time_out, break,
  JNZ	COM_ERR 		     ;or frame error. error detected, then beep
;
;
COM_STAT1:			     ;test data ready bit,
  TEST	AH,1			     ;Z flag = 0 if data waiting
RET				     ;return
;
;
COM_ERR:PUSH AX 		     ;error detected
  MOV	AL,7			     ;set 7 for beep
  CALL	PC_OUT			     ;beep it
  POP	AX			     ;return comm status
  JMP	COM_STAT1		    ;
COM_STAT ENDP			     ;
;
COM_IN PROC NEAR		     ;use ROM BIOS function 2 to get character
  MOV	DX,COM_PORT		    ;
  MOV	AH,2			     ;
  INT	14H			     ;
RET				     ;
COM_IN ENDP			     ;
;
COM_OUT PROC NEAR		     ;write the character in AL
  MOV	DX,COM_PORT		    ;to the comm port. DX destroyed
  MOV	AH,1			     ;use ROM BIOS function 1 to
  INT	14H			     ;send character
RET				     ;
COM_OUT ENDP			     ;
;
PC_STAT PROC NEAR		     ;read status of keyboard
  MOV	AL,IN_CHAR		     ;Z=0 if character waiting
  OR	AL,AL			     ;Z=1 if empty
  JNZ	PC_STAT1		     ;if character waiting just return w/status
  MOV	AH,6			     ;otherwise call DOS to determine status
  MOV  DL,0FFH			    ;
  INT	21H			     ;
  JZ	PC_STAT1		     ;jump if nothing ready
  MOV	IN_CHAR,AL		     ;got a character, save it for PC-IN
;
PC_STAT1:			     ;return with status
RET				     ;
PC_STAT ENDP			     ;
;
PC_IN PROC NEAR 		     ;
  MOV	AL,IN_CHAR		     ;
  OR	AL,AL			     ;any character waiting?
  JNZ	PC_IN1			     ;yes, return it to caller.
  CALL	PC_STAT 		     ;no, try and read a character.
  JMP	PC_IN			     ;
;
PC_IN1: XOR AH,AH		     ;clear the character waiting flag.
  MOV	IN_CHAR,AH		     ;
RET				     ;exit with the character in AL
PC_IN ENDP			     ;
;				     ;
;
PC_OUT PROC NEAR		     ;write the character in AL to the screen
  MOV	DL,AL			     ;use DOS function 6 to send the character
  MOV	AH,6			     ;because it ignores ctrl characters so
  INT	21H			     ;they can be sent to remote system
RET				     ;
PC_OUT ENDP			     ;
;
CLEAR PROC NEAR 		     ;clear display and set it to the attribute
  MOV	DL,COLUMNS		     ;in BH. AX,CX,DX may be destroyed.
  MOV	DH,24			     ;DL,DH = x,y of lower right of window
  MOV	CX,0			     ;CL,CH = x,y of upper left of window
  MOV	AX,600H 		     ;AH=6 for scroll or intialize AL=0 for #
  INT	10H			     ;to scroll. Call ROM BIOS video driver
RET				     ;
CLEAR ENDP			     ;
;
HOME PROC NEAR			     ;
  MOV	DX,0			     ;DL,DH = x,y for cursor both = 0
  MOV	BH,0			     ;BH = video page
  MOV	AH,2			     ;function 2= set cursor
  INT	10H			     ;call ROM BIOS video driver
RET				     ;
HOME ENDP			     ;
;
CSEG ENDS			     ;
;
;
DSEG SEGMENT PARA'DATA'              ;
  IN_CHAR DB 0			     ;stores kybrd input character
  COLUMNS DB 0			     ;highest # column in current display mode
;
;
  MSG1	  DB CR,LF,'Check your MODEM!'
	  DB CR,LF,'$'
  MSG2	  DB cr,lf,'Display is TEXT MODE'
	  DB CR,LF,'$'
  MSG3	  DB CR,LF,'Good Bye, Thanks for Calling!'
	  DB CR,LF,'$'
DSEG ENDS
;
;
STACK SEGMENT PARA stack 'stack'
  DB 64 DUP(?)
STACK ENDS
;
;
END TALK

