	TITLE	'MDM705 (02/27/83)  --  CP/M MODEM PROGRAM'
;
; THIS PROGRAM  ORIGINATED  IN 1977.  WRITTEN  BY WARD CHRISTENSEN, IT
; HAS SINCE UNDERGONE  EXTENSIVE REVISIONS.  SO MANY PEOPLE HAVE ADDED
; USEFUL FEATURES IT WOULD  BE DIFFICULT TO LIST THEM ALL.  OTHER VER-
; SIONS OF THE  ORIGINAL PROGRAM  HAVE BEEN MADE, THIS ONE CATERING TO
; THOSE USING THE 'PMMI' AUTO-DIALING S-100 MODEM.  THOSE HAVING OTHER
; MODEMS CAN READILY USE IT, LOSING ONLY THE AUTO-DIALING FEATURE.  BE
; CAREFUL TO SET THE PORTS AND OTHER OPTIONS CORRECTLY.  OVERLAYS HAVE
; BEEN MADE ALLOWING RAPID ADAPTATION TO COMPUTERS NOT USING THE S-100
; BUS.  IT CONFORMS READILY TO NORMAL UARTS AND OTHER I/O DEVICES SUCH
; AS THE 2661, 8250, 8251, ETC.
;
;   NOTE:  If upgrading this program, please add modest comments that
;	   describe the changes and the date they were made.  Then send
;	   to TCBBS in Dearborn (313) 846-6127.
;
;   GENERAL INTEREST:  When transferring files modem-to-modem, the batch
;   mode is extremely useful.  It not only speeds things up, but there
;   is no timeout at the receiving end while the other person prepares
;   to send.  With normal single program transfer, the receiving end
;   switches to checksum in one minute and times out completely in 100
;   seconds.  This offers ample opportunity to transfer programs between
;   individuals.  Remember the batch mode can be used for single files
;   or with wildcards.  Many outstanding optional features have been
;   added by various people throughout its development.  Our thanks to
;   all those who have - and will - contribute.
;					- Irv Hoff, W6FFC
;
;***********************************************************************
;
; 830326:0825
;	    Delay between dialled numbers increased from 2 to 8 units
;  MDM705P  for use with old 416-48x-xxxx exchange that gets lost if
;           one dials too fast.
;	    Various magic numbers in Break and Dialler routines replaced
;	    with appropriate equates (mods NOT marked).
;           Option PAR added for the PMMI-only section to toggle the
;	    terminal mode between 8 bits no parity (default) and 7 bits
;           even parity as required by dear old primitive IBM front end.
;					- Greg Louis
;
; 02/27/83  'V' mode corrected.  When CTL-B is used to change Baudrate
;	    on-the-fly, the Baudrate remains the same when going to-from
;  MDM705   the "T" mode now.  (Previously it would often ignore CTL-B
;	    entirely if the "T" mode had been selected with no Baudrate
;	    included, leading to notices regarding "flakey operation".)
;	    Thanks to Frank Gaude'.  Deleted some superfluous coding.
;	    Fixed quiet mode timing for suitable use with "BYE", etc.
;					- Irv Hoff
;
; 02/13/83  1. 'D' option (if PMMI) auto-disconnects the phone line at
;		  the end of a transfer if included in command.  (Pre-
;		  viously said "Press return to disconnect").
;  MDM704   2. Added an 'X' option that auto-disconnects at the end of
;		  a transfer and jumps to 'BYEBYE' which reboots back to
;		  CP/M.  Does a cold boot if CLDBOOT has been entered.
;	    3. Fixed the "quiet mode" so that only those messages which
;		  can interfere with the BYE protocol are suppressed.
;					- R. L. Plouffe	
;
; 02/07/83  Reworked the "quiet" mode (used in conjunction with "BYE" on
;           some occasions for batch mode, etc.)  Protection added for
;  MDM703   quiet mode to insure returning to command prompt after file
;           transfer even if "T" was inadvertently selected.  Added nor-
;	    mal method of changing user area as well as with LOG.  Other
;	    modest changes.  Thanks to Frank Gaude' for suggestions and
;	    testing.			- Irv Hoff
;
; 01/27/83  Rstores original drive and user area when returning to CP/M.
;	    Reorganized the PMMI dialing section, fixing several long-
;  MDM702   standing bugs in the auto-redialing system.  Also can now
;	    (finally) auto-redial off the menu command line, including
;	    ringback numbers.  Number of dialing attempts now displayed.
;	    Added triple protection against inadvertently erasing all
;	    files on a disk with improper use of "*" or "?" wildcards.
;	    Batch mode rejected except when using "S" or "R".  If send-
;	    ing a file in "T" mode (via CTL-T), line feeds are displayed
;	    but not sent.  Line delays are triggered from CR characters.
;					- Irv Hoff
;
; 01/10/83  Added some of the features in the current COMM 7.13 version.
;	    It is now simple to abort while in send or receive.  Clock
;  MDM701   speeds up to 25.5 MHz may be used, in 0.1 MHz increments.
;	    Several glitches fixed.  Particular thanks to Frank Gaude'
;	    for permission to adapt some of his routines, plus his help
;	    and continued interest.	- Irv Hoff
;
; 01/01/83  First version.  This is similar to MODEM 7.98 but with the
;	    macro library now integral in the program.  It assembles via
;  MDM700   ASM or MAC as well as with other popular assemblers.   Those
;	    contributing heavily to recent development leading to MODEM
;	    7.98 were Bruce Ratoff, Paul Kelley, Frank Gaude', Mark Pul-
;	    ver, Bob Plouffe and myself.  Many others have made large
;	    contributions in previous years.  MDM700 was selected as a
;	    name to commence a new series of version numbers.  This also
;	    can readily be placed on data bank systems that limit file
;	    names to a total of 6 characters.
;					- Irv Hoff
;
;***********************************************************************
;
;
TRUE		EQU	0FFH
FALSE		EQU	0
;
;
DBUFSIZ:	EQU	16	;buffer size for file transfer in Kbytes
;
ERRCRC:		EQU	6	;number of times to try CRC mode..
				;..before switching to CHECKSUM
;
; PMMI EQUATES  (The first 8 lines are also of particular interest to
; non-PMMI users.)
;
PORT:		EQU	0C0H	;*PMMI base address (0C0H is typical)
;
MODCTLP:	EQU	PORT	;modem control port
MODDATP:	EQU	PORT+1	;*modem data port
BAUDRP:		EQU	PORT+2	;modem baud rate port
MODCTL2:	EQU	PORT+3	;modem 2nd control port
MODRCVB:	EQU	02H	;modem receive bit (DAV)
MODRCVR:	EQU	02H	;modem receive ready
MODSNDB:	EQU	01H	;modem send bit (transmit buffer empty)
MODSNDR:	EQU	01H	;modem send ready bit
;
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
NOPARMSK:	EQU	10H	;mask to reset to no parity
EVPARMSK:	EQU	20H	;mask to set even parity
ODPARMSK:	EQU	0CFH	;mask to set odd parity
BRKMSK:		EQU	0FBH	;mask to set break
ERRCDMSK:	EQU	38H	;mask to block all bits but error codes
FRMER:		EQU	20H     ;mask for framing error
ORUNER:		EQU	10H	;mask for overrun error
PARER:		EQU	08H	;mask for parity error
;
ANSWMOD:	EQU	1EH	;answer mode
ORIGMOD:	EQU	1DH	;originate mode
ORIG7E		EQU	29H	;orig mode, 7 bits, even parity
BDNMCH:		EQU	75H	;bad name match
LIBLEN:		EQU	34	;length of each phone library entry
RUB:		EQU	7FH	;rub
WAITCTS:	EQU	100	;number of seconds (x5) to wait for the
				;computer to answer after PMMI auto-dial
				;100=20 sec, 150=30 sec, 255=51 sec.
				;any number 0-255 acceptable
CRC:		EQU	'C'	;requests 'CRC' instead of 'CKSUM'
ESC:		EQU	'['-40H	;^[ = escape
SOH:		EQU	'A'-40H	;^A = start of header
EOT:		EQU	'D'-40H	;^D = end of text
ACK:		EQU	'F'-40H	;^F = acknowledge
OKNMCH:		EQU	'F'-40H	;^F = ok name match
BELL:		EQU	'G'-40H	;^G = bell character
BKSP:		EQU	'H'-40H	;^H = backspace
LF:		EQU	'J'-40H	;^J = linefeed
CR:		EQU	'M'-40H	;^M = carriage return
XON:		EQU	'Q'-40H	;^Q = XON character
XOFF:		EQU	'S'-40H	;^S = XOFF character
NAK:		EQU	'U'-40H	;^U = not acknowledge
CAN:		EQU	'X'-40H	;^X = cancel send or receive
EOFCHAR:	EQU	'Z'-40H	;^Z = end of file
;
BOTTRAM		SET	LAST+100H AND 0FF00H
;
;
		ORG	0100H
;
;
		JMP	START	;skip the data area below
;
; THESE ROUTINES AND EQUATES ARE AT THE BEGINNING OF THE PROGRAM SO
; THEY CAN BE PATCHED BY A MONITOR OR OVERLAY FILE WITHOUT RE-ASSEMBLING
; THE PROGRAM.
;
PMMIBYTE:	DB	TRUE	;*true=PMMI modem, false=non-PMMI modem
;
CLOCK:		DB	40	;*clock speed x10, up to 25.5 mhz.
				;2 MHz=20, 3.68 MH=37, 4 MHz=40, etc.
MSPEED:		DB	1	;*sets display time for sending a file
				;0=110  1=300  2=450  3=600  4=710
				;5=1200 6=2400 7=4800 8=9600
BYTDLY:		DB	5	;default time to send character in
				;terminal mode file transfer (0-9)
				;0=0 delay, 1=10 ms, 5=50 ms, 9=90 ms
CRDLY:		DB	5	;end-of-line delay after CRLF in terminal
				;mode file transfer for slow BBS systems
				;0=0 delay, 1=100 ms, 5=500 ms, 9=900 ms
NOOFCOL:	DB	5	;number of directory columns
SETUPTST:	DB	FALSE	;true=non-PMMI setup routine
SCRNTEST:	DB	TRUE	;*true=if home cursor and clear screen
				;routine at CLRSCRN
BAKUPBYTE:	DB	FALSE	;true=make .BAK file
CKSUMDFLT:	DB	FALSE	;true=default to Checksum checking
				;*false=default to CRC checking
TOGGLECRC:	DB	TRUE	;true=allow toggling of Checksum to CRC
CONVBKSP:	DB	FALSE	;true=convert backspace to rub
TOGGLEBK:	DB	TRUE	;true=allow toggling of bksp to rub
ADDLF:		DB	FALSE	;true=add LF after CR
TOGGLELF:	DB	TRUE	;true=allow toggling of LF after CR
TRANLOGON:	DB	FALSE	;true=allow transmission of logon
				;write logon sequence at location LOGON
SAVCCP:		DB	TRUE	;true=do not overwrite CCP
LOCONEXTCHR:	DB	FALSE	;true=local cmd if EXTCHR precedes
				;false=not local cmd if EXTCHR precedes
TOGGLELOC:	DB	TRUE	;true=allow toggling of LOCONEXTCHR
LSTTST:		DB	TRUE	;*true=allow toggling of printer on/off
				;in terminal mode. Set to false if your
				;printer can't keep up with the modem
XOFFTST:	DB	FALSE	;true=allow testing of XOFF from remote
				;while sending a file in terminal mode
XONWAIT:	DB	FALSE	;true=wait for XON aftersending CR while
				;transmitting a file in terminal mode	
TOGXOFF:	DB	TRUE	;true=allow toggling of XOFF testing
EXITCHR:	DB	'E'-40H	;^E = Exit without disconnect
LOGCHR:		DB	'O'-40H	;^O = Send logon
LSTCHR:		DB	'P'-40H	;^P = Toggle printer
UNSAVECHR:	DB	'R'-40H	;^R = Close input text buffer
TRANCHR:	DB	'T'-40H ;^T = Transmit file to remote
SAVECHR:	DB	'Y'-40H	;^Y = Open input text buffer
EXTCHR:		DB	'^'-40H	;^^ = Send next character
;
;
; Equates used only by PMMI routines grouped together here.
;
PULSERATE:	DB	250	;125 for 20pps, 250 for 10pps on PMMI
				;not used if PMMI FALSE
CLDBOOT:	DW	00000H	;warm reboot address - put your own
				;address for a cold reboot if preferred
BRKCHR:		DB	'@'-40H	;^@ = Transmit "BREAK" with PMMI
CHGBAUD:	DB	'B'-40H	;^B = Used with PMMI in terminal
				; mode to change baud rate on fly
DISCCHR:	DB	'D'-40H	;^D = PMMI Disconnect
;
;
IN$MODCTLP:	IN	MODCTLP ! RET	;in modem control port
		DB	0,0,0,0,0,0,0	;spares if needed for non-PMMI
OUT$MODDATP:	OUT	MODDATP ! RET	;out modem data port
		DB	0,0,0,0,0,0,0	;spares if needed for non-PMMI
IN$MODDATP:	IN	MODDATP ! RET	;in modem data port
		DB	0,0,0,0,0,0,0	;spares if needed for non-PMMI
ANI$MODSNDB:	ANI	MODSNDB ! RET	;bit to test for send ready
CPI$MODSNDR:	CPI	MODSNDR ! RET	;value of send bit when ready
ANI$MODRCVB:	ANI	MODRCVB ! RET	;bit to test for receive ready
CPI$MODRCVR:	CPI	MODRCVR ! RET	;value of receive bit when ready
;
;
; THE FOLLOWING ARE TYPICALLY USED ONLY BY PMMI
;
IN$BAUDRP:	IN	BAUDRP   ! RET	;in baudrate port
OUT$BAUDRP:	OUT	BAUDRP   ! RET	;out baudrate port
OUT$MODCTL2:	OUT	MODCTL2  ! RET	;out modem control port #2
OUT$MODCTLP:	OUT	MODCTLP		;out modem control port
		STA	UARTCTLB ! RET	;and store control byte
;
LOGONPTR:	DW	LOGON
JMP$INITMOD:	JMP	INITMOD
JMP$SETUPR:	JMP	SETUPR
;
; MOD(BGL) FOR PARITY SWITCH DURING CONVERSATIONAL TRANSMISSION
PARTY:		DB	ORIGMOD
PARTOG:		DB	ORIGMOD+ORIG7E
;
; Clear sequences are for Televideo, Lear Siegler, etc.  Change to match
; your terminal.  (Heath uses ESC 4AH for clear to end of screen, ESC 45H
; to clear screen.  Lear Siegler and others use ESC 79H for clear to end
; of screen and ESC 3AH to clear screen.)  Room allowed for four bytes.
; (Last zero needed for stopping the string display.  Any extra 0's just
; act as NOP's.)
;
CLREOS:		CALL	ILPRT
		DB	'O'-40H,0,0,0,0
		RET
;.....
;
;
CLRSCRN:	CALL	ILPRT
		DB	'L'-40H,0,0,0,0
		RET
;.....
;
;
; NEXT FIVE LINES SHOULD NOT BE CHANGED BY USER OVERLAY
;
JMP$ILPRT:	JMP	ILPRT
JMP$INLNCOMP:	JMP	INLNCOMP
JMP$INBUF:	JMP	INBUF
JMP$SYSVER:	JMP	SYSVER
JMP$DIAL:	JMP	DIAL
JMP$DISCONNT:	JMP	DISCONNT
;
;	
; Send version number and date
;
SYSVER:	  LDA	PMMIBYTE	;USING THE PMMI S-100 MODEM?
	  ORA	A
	  JZ	SYSVER1		;GO IF NOT
	  CALL	ILPRT
	  DB	'Version for PMMI S-100 modem starting at port: ',0
	  LDA	IN$MODCTLP+1
	  CALL	HEXO		;PUT IN PMMI CONTROL PORT NUMBER
	  CALL	ILPRT
	  DB	'H',CR,LF,0
	  RET
;.....
;
;
SYSVER1:  CALL	ILPRT		;IF NOT USING THE PMMI S-100 BOARD
	  DB	'Version for Non-PMMI modem',CR,LF,0
	  RET
;.....
;
;
; INSERT YOUR LOGON HERE.  CAN BE ANY LENGTH DESIRED.  MUST END WITH 0.
;
LOGON:	  DB	0
;
;
; INSERT YOUR INITIALIZATION ROUTINE HERE IF NEEDED.  CAN REPLACE THE
; FOLLOWING SECTION WHICH IS PRESENTLY USED FOR THE PMMI BOARD.
;
INITMOD:
;
;
; SETS THE BAUD RATE FOR THE PMMI BOARD (IF ONE IS SPECIFIED)
;
SETBAUD:  LDA	PMMIBYTE
	  ORA	A
	  RZ			;IF NOT PMMI S-100 BOARD, IGNORE REST
;
	  LDA	ANSWFLG		;IF 'O' OR 'A' NOT REQUESTED AND
	  ORA	A		;   BAUDRATE NOT SPECIFIED, RETURNS
	  JZ	FIXBAUD		;   WITH CURRENT MODE AND RATE
	  LDA	ORIGFLG		;IF OPTION REQUESTED, A BLANK FORCES 300
	  ORA	A		;   BAUD AS DOES A NULL FROM NEWBAUD
	  RNZ			;NO CHANGE IF NEITHER 'O' OR 'A' SHOWN
;
FIXBAUD:  CALL	GETBAUD
	  MOV	B,A		;SAVE THE BAUD RATE VALUE
	  CALL	OUT$BAUDRP	;SET THE PMMI BOARD TO THAT BAUDRATE
	  CALL	CHGMSPD		;GET THE 'MSPEED' VALUE
	  MOV	A,C		;IT COMES BACK IN THE 'C' REG.
	  STA	MSPEED		;SET THE CORRECT 'MSPEED'
	  MOV	A,B		;GET THE BAUD RATE VALUE BACK
	  CPI	52
	  MVI	A,5FH		;DTR (FILTER FOR OVER 300 BAUD)
	  JC	GT300		;YES, GREATER THAN
	  MVI	A,7FH		;DTR (FILTER FOR 300 AND LESS BAUD)
;
GT300:	  CALL	OUT$MODCTL2
	  STA	MODCTLB		;SAVE MODEM CONTROL BYTE
	  LDA	UARTFLG		;UART CONROL BYTE FOR 'A' OR 'O'
	  ORA	A
; MOD(BGL)***
	  LDA	PARTY		;GET ORIGINATE MODE
	  JZ	OFFHOOK		;EXIT IF 'O' SET
	  MVI	A,ANSWMOD
;
OFFHOOK:  LXI	H,7500
;
OFFDLY:   DCR	L
	  JNZ	OFFDLY
	  DCR	H
	  JNZ	OFFDLY
	  CALL	OUT$MODCTLP
	  RET
;.....
;
;
;-----------------------------------------------------------------------
;
; Phone number library table for PMMI auto-dialing.  Each number must be
; as long as "LIBLEN" (EQU at start of program).  Some areas require ex-
; tra characters such as:   1-313-846-7127.  Room is left for those.
;
;		'----5---10---15---20---25---30--34'
NUMBLIB:  DB	'A=Amrad...............703-734-1387'	;'A'
	  DB	'B=                                '	;'B'
	  DB	'C=CBBS Pasadena.......213-799-1632'	;'C'
	  DB	'D=PMMI................703-379-0303'	;'D'
	  DB	'E=Edward Huang........415-595-0541'	;'E'
	  DB	'F=                                '	;'F'
	  DB	'G=Gasnet NASA.........301-344-9156'	;'G'
	  DB	'H=Dave Hardy..........313-846-6127'	;'H'
	  DB	'I=Wayne Hammerly......301-953-3753'	;'I'
	  DB	'J=RBBS Pasadena.......213-356-1034'	;'J'
	  DB	'K=Bob Kuhman..........408-732-2433'	;'K'
	  DB	'L=Program Store.......202-337-4694'	;'L'
	  DB	'M=Dick Mead...........213-799-1632'	;'M'
	  DB	'N=Mtn/View PICONET....415-965-4097'	;'N'
	  DB	'O=Bob Plouffe.........703-524-2549'	;'O'
	  DB	'P=Keith Petersen.....313-759-6569R'	;'P'
	  DB	'Q=Bruce Ratoff........201-272-1874'	;'Q'
	  DB	'R=Mark Pulver.........312-789-0499'	;'R'
	  DB	'S=Paul Traina.........408-867-1243'	;'S'
	  DB	'T=TCBBS, Dearborn.....313-846-7127'	;'T'
	  DB	'U=                                '	;'U'
	  DB	'V=                                '	;'V'
	  DB	'W=Ward Christensen....312-545-8086'	;'W'
	  DB	'X=                                '	;'X'
	  DB	'Y=                                '	;'Y'
	  DB	'Z=                                '	;'Z'
	  DB	0					;end
;		'----5---10---15---20---25---30--34'
;.....
;
;
;***********************************************************************
;
; P - R - O - G - R - A - M    S - T - A - R - T - S    H - E - R - E
;
;***********************************************************************
;
;
START:	  POP	H		;GET THE STACK RETURN TO CCP
	  SHLD	EXIT1+1		;ENABLES RETURN TO CCP
	  LXI	SP,STACK	;START LOCAL STACK
	  CALL	ILPRT
	  DB	CR,LF,'MDM705 - 02/27/83',CR,LF,0
	  CALL	INITADR		;INITIALIZE ADDRESSES
	  CALL	JMP$SYSVER	;GIVE CONFIGURATION MESSAGE
	  CALL	GETUSER		;GET CURRENT USER NUMBER
	  STA	OLDUSER
	  MVI	A,TRUE		;0FFH
	  STA	NFILFLG		;RESET THE NO FILE FLAG TO SHOW NO FILE
	  CMA			;0
	  STA	ORIGMOD		;SET INITIALLY FOR ORIGINATE MODE
	  STA	SAVEFLG
	  LDA	FCB+1		;IS THERE A COMMAND TAIL?
	  STA	OPTION
	  CPI	' '
	  JNZ	START0		;IF YES, DIGEST IT
	  SUB	A
	  STA	EXITFLG		;ELSE SAY WE WANT MENU
	  JMP	START1
;
START0:	  LXI	H,80H		;SIMULATE COMMAND LINE INPUT FROM MENU
	  MOV	B,M		;SAVE CHAR COUNT
;
STARTA:	  INX	H
	  MOV	A,M		;SKIP OVER LEADING SPACES IN COMMAND TAIL
	  CPI	' '
	  JNZ	STARTB
	  DCR	B
	  JMP	STARTA
;
STARTB:	  MOV	A,B
	  STA	CMDBUF+1	;STORE COMMAND CHAR COUNT - LGNG SPACES
	  INR	B		;MOVE 1 EXTRA BYTE (SHOULD BE A NULL)
	  LXI	D,CMDBUF+2
	  CALL	MOVE
	  CALL	SETFCB		;DIGEST COMMAND LINE AND OPTIONS
;
START1:	  LDA	UARTFLG
	  ORA	A
	  MVI	A,ANSWMOD
	  STA	UARTCTLB
	  JNZ	RESTART
;MOD(BGL)***
	  LDA	PARTY
	  STA	UARTCTLB
;
RESTART:  LXI	SP,STACK	;MAKE SURE WE HAVE A CLEAN STACK
	  LXI	D,CMDBUF+1	;MAY BE USEFUL WHERE WE ARE GOING
	  LDA	OPTION		;GET MAIN OPTION
	  MOV	B,A		;SAVE IT
	  LDA	PMMIBYTE	;PMMI?
	  ORA	A		;SET FLAGS
	  MOV	A,B		;GET OPTION BACK
	  JZ	S1		;NOT PMMI
	  CPI	'C'		;CALL (DIAL) FUNCTION?
	  JZ	JMP$DIAL	;YES, GO TO IT
	  CPI	'D'		;DISCONNECT?
	  JZ	DISCON1		;YES, DISCONNECT & GO MENU
;
S1:	  CPI	' '		;NO OPTION SPEC'D?
	  JZ	MENU		;TRUE, GO MENU
	  CPI	'H'		;MENU ASKED FOR?
	  JZ	MENU2		;YES, GO MENU2
	  CALL	JMP$INITMOD
	  CALL	MOVEFCB
	  CALL	IN$MODDATP 	;GOBBLE UP GARBAGE..
	  CALL	IN$MODDATP 	;..CHARACTERS ON LINE
	  XRA	A
	  STA	ECHOFLG		;RESET ECHO FLAG
	  STA	LOCFLG		;RESET LOCAL FLAG
	  LDA	OPTION		;PROCESS MAIN OPTION
	  CPI	'E'		;ECHO MODE?
	  JNZ	NOECH		;JUMP IF NOT
	  MVI	A,TRUE		;SET ECHO TO TRUE
	  STA	ECHOFLG
	  JMP	DSKSAVE
;
NOECH:	  CPI	'L'		;LOCAL ECHO MODE
	  JNZ	NOLOC
	  MVI	A,TRUE
	  STA	LOCFLG
	  JMP	DSKSAVE
;
NOLOC:	  CPI	'T'		;TERMINAL MODE?
	  JZ	DSKSAVE		;YES
	  CPI	'S'		;SEND A FILE?
	  JZ	SENDFIL		;YES
	  CPI	'R'		;RECEIVE A FILE?
	  JZ	RCVFIL		;YES
	  CALL	NTVLDMSG	;SAY NOT A VALID OPTION
	  JMP	MENU		;NO VALID OPTION SPEC'D, GO MENU
;
;
; Revised terminal routine allowing memory save.  First checks for bad
; options, to prevent wiping out the disk with accidental memory save.
;
DSKSAVE:  LDA	BATCHFLG	;BATCH FLAG SET?
	  ORA	A
	  JNZ	DSKSAVE1
	  XRA	A
	  STA	BATCHFLG
	  JMP	NOTVLD		;IF YES, ERROR FOR "E", "L" OR "T"
;
DSKSAVE1: LDA	FCB+1		;FIRST CHARACTER OF FILENAME (IF ANY)
	  CPI	' '		;FILE SPECIFIED?
	  JNZ	GOODNM		;YES, GOOD NAME
	  MVI	A,TRUE		;0FFH
	  STA	NFILFLG
	  CMA
	  STA	SAVEFLG
	  JMP	TERM
;...
;
;
GOODNM:	  CALL	ERASFIL
	  CALL	MOVE2
	  LXI	D,FCB3
	  MVI	C,MAKE
	  CALL	BDOS
	  LXI	D,FCB3
	  MVI	C,OPEN
	  CALL	BDOS
	  LXI	H,BOTTRAM
	  SHLD	HLSAVE
	  XRA	A
	  STA	NFILFLG		;SHOW NOW SAVING TO MEMORY FOR DISK FILE
	  STA	LISTMOR		;STOP ANY BUFFERED PRINTER OUTPUT
;
TERM:	  LDA	UARTFLG
	  STA	ORIGSAV
	  ORA	A
	  MVI	A,ANSWMOD
	  JNZ	TERM1
;MOD(BGL)***
	  LDA	PARTY		;GET DEFAULT PARITY
;
TERM1:	  STA	UARTCTLB
;
TERM2:	  LDA	LISTMOR		;ANY BUFFERED PRINTER OUTPUT?
	  ORA	A
	  CNZ	GOLIST		;GO IF SO
	  CALL	STAT		;KEYPRESS?
	  JZ	TERML		;NO, CHECK LINE
	  CALL	KEYIN		;GET CHAR FROM KBD
	  CPI	' '
	  JNC	NOTOG		;GO IF NOT CONTROL CHARACTER
	  MOV	B,A		;SAVE
 	  CPI	BKSP		;TEST FOR BACKSPACE
	  JNZ	NOBKSP
	  LDA	CONVBKSP	;CONVERT BACKSPACE TO RUB?
	  ORA	A
	  JZ	NOBKSP		;GO IF NO CONVERSION
	  MVI	A,RUB
	  JMP	NOTOG
;...
;
;
NOBKSP:	  LDA	EXACFLG
	  ORA	A		;EXACT?
	  MVI	A,0
	  STA	EXACFLG		;CLR FOR NEXT TIME
	  JZ	NTEXAFLG	;GO OF EXAFLG FALSE
	  LDA	LOCONEXTCHR
	  ORA	A		;SHOULD WE SEND ON EXAFLG?
	  MOV	A,B
	  JZ	NOTOG		;YES, IF LOCONEXTCHR FALSE
	  LDA	EXTCHR		;WE WANT TO SEND EXTCHR IN ANY CASE
	  CMP	B
	  MOV	A,B
	  JZ	NOTOG		;SEND IF EXTCHR
	  JMP	LOCCHK		;OTHERWISE DO LOCAL STUFF
;...
;
;
NTEXAFLG: LDA	EXTCHR		;TREAT NEXT CHARACTER IN SPECIAL WAY?
	  CMP	B
	  JZ	EXTFLG		;YES, SET EXAFLG FOR NEXT CHAR
	  LDA	LOCONEXTCHR
	  ORA	A		;SHOULD WE SEND IF NOT EXAFLG
	  MOV	A,B
	  JNZ	NOTOG		;YES, IF LOCONEXTCHR TRUE
;
LOCCHK:	  LDA	EXITCHR		;RETURN TO MENU?
	  CMP	B
	  JZ	EXITMEN		;YES, RETURN TO MENU
	  LDA	TRANCHR		;OUTPUT TEXT FILE TO REMOTE?
	  CMP	B
	  CZ	TRANSFER	;SEND-A-FILE (BLIND SEND)
	  JZ	TERM2		;LOOP
	  LDA	TRANLOGON
	  ORA	A
	  JZ	SKPLOGON
	  LDA	LOGCHR		;SEND LOGON?
	  CMP	B
	  JZ	SENDLOG
;
SKPLOGON: LDA	LSTTST		;GOING TO USE THE EXTERNAL PRINTER?
	  ORA	A
	  JZ	NOLST		;IF NOT, SKIP THIS AREA
	  LDA	LSTCHR		;GET THE PRINTER CONTROL-CHARACTER
	  CMP	B		;DID WE JUST ASK FOR PRINTER CONTROL?
	  JNZ	NOLST		;IF NOT, EXIT
	  LDA	LISTFLG		;OTHERWISE RESET THE PRINTER TOGGLE
	  CMA
	  STA	LISTFLG		;AND STORE
	  CALL	CRLF		
	  CALL	CRLF
	  CALL	LSTMSG		;TELL IF PRINTER IS ON OR OFF NOW
	  CALL	CRLF
	  JMP	TERML		;BACK TO THE TERMINAL MODE AGAIN
;.....
;
;
NOLST:	  LDA	PMMIBYTE	;USING A PMMI BOARD?
	  ORA	A
	  JZ	S2		;IF NOT, SKIP THE NEXT FEW LINES
	  LDA	DISCCHR		;PMMI DISCONNECT?
	  CMP	B
	  JZ	DISCON1		;YES, DISCONNECT & RETURN TO MENU
	  LDA	BRKCHR		;PMMI BREAK?
	  CMP	B
	  JZ	BREAK
	  LDA	CHGBAUD		;PMMI CHANGE BAUD?
	  CMP	B
	  PUSH	PSW
	  PUSH	H
	  CZ	NEWBAUD
  	  POP	H
	  POP	PSW
	  JZ	TERML
;...
;
;
S2:	  LDA	UNSAVECHR	;CLOSE INPUT BUFFER?
	  CMP	B
	  JZ	S2A		;IF YES, DISABLE COPY
	  LDA	SAVECHR		;OPEN INPUT BUFFER?
	  CMP	B
	  MOV	A,B		;RESTORE CHARACTER TYPED
	  JNZ	NOTOG
	  LDA	NFILFLG		;DO NOT ALLOW SAVE IF..
	  CPI	TRUE		;..THIS FLAG IS SET.
	  JZ	TERML
	  MVI	A,TRUE		;0FFH -- ALLOW COPY INTO FILE
	  JMP	S2B
;
S2A:	  MVI	A,FALSE		;0 -- STOP COPY INTO FILE
;
S2B:	  STA	SAVEFLG
	  CALL	BUFMSG
	  JMP	TERML
;.....
;
;	
;***********************************************************************
;
; SEND A CP/M FILE
;
;***********************************************************************
;
;
SENDFIL:  MVI	A,TRUE		;ALWAYS FORCE CHECKSUM MODE..
	  STA	CRCFLAG		;..INITIALLY ON SEND
;
SENDFIL1: CALL	PARITY		;SET PARITY IF REQUESTED
	  LDA	BATCHFLG	;CHECK IF MULTIPLE FILE..
	  ORA	A		;..MODE IS SET.
	  JNZ	SENDC1
	  MVI	A,TRUE		;INDICATE SEND FOR BATCH MODE
	  STA	SENDFLG
	  LDA	FSTFLG		;IF FIRST TIME THRU..
	  ORA	A		;..SCAN THE COMMAND LINE..
	  CNZ	TNMBUF		;..FOR MULTIPLE NAMES.
	  CALL	SENDFN		;SENDS FILE NAME TO RECEIVER
	  JNC	SENDC2		;CARRY SET MEANS NO MORE FILES.
	  MVI	A,'B'		;STOP BATCH..
	  STA	BATCHFLG  	;..MODE OPTION.
	  MVI	A,EOT		;FINAL XFER END
	  CALL	SEND
	  JMP	DONE
;.....
;
;
SENDC1:	  LDA	FCB+1
	  CPI	' '
	  JZ	BLKFILE
;
SENDC2:	  CALL	CNREC		;GET NUMBER OF RECORDS
	  CALL	OPENFIL
	  MVI	E,100
	  CALL	WAITNAK
;
SENDLP:	  CALL	CKABORT		;WANT TO TERMINATE WHLE SENDING FILE?
	  CALL	RDRECD
	  JC	SENDEOF
	  CALL	INCRRNO
	  MVI	A,1
	  STA	ERRCT
;
SENDRPT:  CALL	CKABORT		;WANT TO TERMINATE WHILE SENDING FILE?
	  CALL	SENDHDR
	  CALL	SENDREC
	  LDA	CRCFLAG
	  ORA	A
	  CZ	SENDCRC
	  CNZ	SENDCKS
	  CALL	GETACK
	  JC	SENDRPT
	  JMP	SENDLP
;.....
;
;
SENDEOF:  MVI	A,EOT
	  CALL	SEND
	  CALL	GETACK
	  JC	SENDEOF
	  JMP	DONE
;.....
;
;
;***********************************************************************
;
; RECEIVE A FILE
;
;***********************************************************************
;
;
RCVFIL:	  LDA	CKSUMDFLT	;GET MODE REQUESTED BY OPERATOR
	  STA	CRCFLAG		;STORE IT
;
RCVFIL1:  CALL	PARITY		;SET PARITY IF REQUESTED
	  LDA	BATCHFLG	;USING BATCH TRANSFER?
	  ORA	A
	  JNZ	RCVC1		;IF NOT, EXIT
	  MVI	A,FALSE		;FLAG WHERE TO RETURN..
	  STA	SENDFLG		;..FOR NEXT FILE TRANS.
	  CALL	GETFN		;GET THE FILE NAME.
	  JNC	RCVC2		;CARRY SET MEANS NO MORE FILES.
	  MVI	A,'B'		;STOP BATCH..
	  STA	BATCHFLG	;..MODE OPTION.
	  JMP	DONE
;...
;
;
RCVC1:	  LDA	FCB+1		;MAKE SURE FILE IS NAMED
	  CPI	' '
	  JZ	BLKFILE
	  JMP	RCVC3
;...
;
;
RCVC2:	  CALL	CKCPM2
	  CALL	CKBAKUP
;
RCVC3:	  CALL	ERASFIL
	  CALL	MAKEFIL
	  LDA	BATCHFLG	;USING BATCH TRANSFER?
	  ORA	A
	  JZ	RCVC4		;IF YES, DO NOT PRINT MESSAGE
	  CALL	ILPRT
	  DB	'File open, ready to receive',0
;
RCVC4:    LDA	CRCFLAG		;USING CRC MODE?
	  PUSH	PSW		;SAVE THE FLAG'S VALUE
	  ORA	A
	  JZ	RCVC5		;IF YES, EXIT
	  CALL	ILPRT		;OTHERWISE IN CHECKSUM MODE
	  DB	CR,LF,'CHECKSUM in effect',CR,LF,0
	  JMP	RCVC6
;...
;
;
RCVC5:	  CALL	ILPRT
	  DB	CR,LF,'CRC in effect',CR,LF,0
	  LDA	QFLG		;IN QUIET MODE NOW?
	  ORA	A
	  CZ	CRLF		;AN EXTRA CRLF FOR QUIET MODE
	  
;
RCVC6:	  POP	PSW		;GET THE FLAG'S VALUE BACK
	  ORA	A		;IN CRC MODE?
	  MVI	A,CRC
	  JZ	RCVC7		;IF YES, EXIT
	  MVI	A,NAK		;NAK FOR CHECKSUM MODE
;
RCVC7:	  CALL	SEND		;NOW SEND THE 'CRC' (OR 'NAK')
;
RCVLP:	  CALL	RCVRECD
	  JC	RCVEOT
	  CALL	WRRECD
	  CALL	INCRRNO
	  CALL	SENDACK
	  JMP	RCVLP
;.....
;
;
RCVEOT:	  CALL	WRBLOCK
	  CALL	SENDACK
	  CALL	CLOSFIL
	  JMP	DONE
;.....
;
;
;***********************************************************************
;
; FILE TRANSFER ROUTINE - CALLED WITH CONTROL-T FROM TERMINAL ROUTINE.
; TRANSFER MAY BE CANCELLED WHILE SENDING BY USING CONTROL-X.
;
;***********************************************************************
;
TRANSFER: PUSH	H
	  PUSH	D
	  PUSH	B
	  PUSH	PSW
	  LXI	H,FCB4
	  CALL	INITFCB		;INITIALIZES FCBS POINTED..
	  LXI	H,FCB+16	;..TO BY HL REG.
	  CALL	INITFCB
;
;
; GET NAME OF FILE TO SEND IN "T" (TERMINAL) MODE
;
GET:	  CALL	ILPRT
	  DB	CR,LF,'File name to send?   (RET to quit): ',0
	  LXI	D,CMDBUF
	  CALL	INBUF
	  LDA	CMDBUF+2	;WAS FILE ENTERED?
	  CPI	' '
	  JZ	TRANSL2
	  LXI	D,CMDBUF
	  LXI	H,FCB4
	  CALL	CMDLINE
	  LXI	D,FCB4
	  MVI	C,OPEN
	  CALL	BDOS
	  CPI	0FFH		;RETURN WITH 0FFH MEANS
	  JZ	TRANSL1		;FILE DOES NOT EXIST
;
;
; CHOICE OF NORMAL SPEED OR DELAYS BETWEEN CHARACTERS / LINES
;
	  CALL	ILPRT
	  DB	'Want to include time delays? (Y/N): ',0
	  CALL	KBDCHR
	  CPI	'N'		;IF 'N' SEND NORMAL SPEED
	  JZ	GET1
	  XRA	A		;OTHERWISE USE CHARACTER / LINE DELAYS
;
GET1:	  STA	DLYFLG		;STORE THE DECISION
	  CALL	CRLF	
	  LXI	D,80H
	  MVI	C,SETDMA
	  CALL	BDOS
;
;
; GET 128-BYTE RECORD
;
READMR:	  LXI	D,FCB4
	  MVI	C,READ
	  CALL	BDOS
	  CPI	1		;END OF FILE
	  JZ	RETURNS
	  CPI	2		;BAD READ
	  JZ	RETURNU
;
	  CALL	SEND80C		;SEND ONE 128-CHAR RECORD
;
	  CPI	EOFCHAR		;END OF FILE - OMIT IF OBJECT..
	  JZ	RETURNS		;..CODE IS TO BE SENT.
	  CPI	CAN		;CANCELLATION?
	  JNZ	READMR
;
TRANCAN:  CALL	ILPRT
	  DB	CR,LF,LF,'++ Transfer cancelled ++',CR,LF,BELL,0
;
RETURN:	  POP	PSW
	  POP	B
	  POP	D
	  POP	H
	  RET
;.....
;
;
RETURNS:  CALL	ILPRT
	  DB	CR,LF,'[Transfer completed]',CR,LF,BELL,0
	  JMP	RETURN
;.....
;
;
RETURNU:  CALL	ILPRT
	  DB	CR,LF,'++ File transfer unsuccessful ++',CR,LF,BELL,0
	  JMP	RETURN
;.....
;
;
TRANSL1:  CALL	ILPRT
	  DB	CR,LF,'++ No file with that name ++',CR,LF,0
;
TRANSL2:  CALL	ILPRT
	  DB	CR,LF,'"R" - return to modem',CR,LF
	  DB	'"A" - re-enter a name: ',BELL,0
	  CALL	KBDCHR
	  CPI	CR
	  JZ	TRANSL2
	  CALL	CRLF
	  CPI	'A'
	  JZ	GET		;GET A FILE NAME AND START OVER
	  CPI	'R'
	  JNZ	TRANSL2
	  JMP	RETURN		;IF AN 'R', ALL DONE
;.....
;
;
; SEND ONE 128-BYTE RCORD
;
SEND80C:  MVI	B,80H
	  LXI	H,80H
;
SENDCH1:  PUSH	D
	  CALL	SPEED		;0-90 MS. DELAY BETWEEN CHARACTERS
	  POP	D
	  MOV	A,M
	  CPI	LF		;LF CHAR?
	  JZ	SKIP22
	  CALL	MODOUT		;SEND THE CHARACTER TO MODEM
	  CPI	EOFCHAR
	  RZ
	  CALL	STAT		;TEST TO SEE IF
	  ORA	A		;CANCELLATION REQUESTED
	  JZ	SKIP12
	  CALL	KEYIN
	  CPI	CAN
	  RZ
;
SKIP12:	  INX	H
	  DCR	B
	  JNZ	SENDCH1
	  RET
;...
;
;
SKIP22:	  CALL	TYPE		;SHOW LF ON CRT, DO NOT SEND TO MODEM
	  JMP	SKIP12		;GET NEXT CHAR
;...
;
;
; Send the character to the output
;
MODOUT:	  PUSH	PSW
;
MODOUTL:  LDA	XOFFTST
	  ORA	A
	  CNZ	TXOFF	
	  CALL	SENDRDY
	  JNZ	MODOUTL
	  POP	PSW
	  CALL	OUT$MODDATP	;SEND CHARACTER TO MODEM
	  CALL	TYPE		;SEND CHARACTER TO CRT
	  CPI	CR		;WAS IT AN END OF LINE?
	  RNZ			;IF YES, GIVE A HEFTY DELAY
;
;
; Delay to allow slow BBS systems (most use BASIC) to enter the line.
; Choice of 0-9 for about 100 ms. each, maximum of 900 ms.
;
MODOUTN:  LDA	XONWAIT		;WAIT FOR XON AFTER CR ?
	  ORA	A
	  JNZ	WAITXON		;IF YES, HANDLE SEPARATELY
	  MVI	D,10
;
MODOUTT:  PUSH	D
	  CALL	SPEED1		;10 MS DELAY
	  POP	D
	  DCR	D
	  JNZ	MODOUTT		;10 LOOPS FOR 100 MS.
	  RET
;.....
;
;
; Add from 0 to 90 ms. delay between characters for slow (most use
; BASIC) bulletin board systems.  Also used to add 0-900 ms. delay
; between lines.
;
SPEED:	  LDA	BYTDLY		;GET DELAY BETWEEN CHARACTERS (0-9)
	  JMP	SPEED1+3	;1=10 MS, 5=50 MS, 9=90 MS, ETC.
;
SPEED1:	  LDA	CRDLY		;GET DELAY AFTER CRLF (0-9)
	  ORA	A		;100 MS, 5=500 MS, 9=900 MS, ETC.
	  RZ			;IF NO DELAY NEEDED, RETURN
	  MOV	C,A		;STORE NUMBER REQUESTED IN C-REG.
	  LDA	DLYFLG		;WANT ANY DELAYS THIS FILE?
	  ORA	A
	  RNZ			;IF NOT, SKIP THIS SECTION
;
SPEED2:	  CALL	SPEED3		;OUTER LOOP
	  DCR	C
	  JNZ	SPEED2
	  RET			;DONE WHENEVER THE C-REG. IS ZERO
;...
;
;
SPEED3:	  PUSH	H
	  LXI	H,14		;10 MILLISECONDS
	  LDA	XOFFTST
	  ORA	A
	  JZ	SPEED4
;
	  LXI	H,10		;7 MILLISECONDS  FOR XOFF TESTING
	  LDA	ECHOFLG
	  ORA	A
	  JZ	SPEED4
;
	  LDA	LOCFLG		;7 MILLISECONDS (SAME AS ECHOFLG)
	  ORA	A
	  JZ	SPEED4
;
	  LXI	H,75		;5 MILLISECONDS FOR REMOTE ECHO
;
SPEED4:	  CALL	FIXCNT		;MULTIPLY DELAY BY CLOCK SPEED
	  PUSH	H
	  POP	D		;GET THE HL-COUNT INTO DE PAIR
	  POP	H		;PUT STACK BACK TO NORMAL
;	
SPEED5:	  DCX	D		;INNER LOOP
	  LDA	XOFFTST
	  ORA	A
	  CNZ	TXOFF
	  MOV	A,E
	  ORA	D
	  JNZ	SPEED5
	  RET
;...
;
;
TXOFF:	  CALL	RCVREADY
	  RNZ
	  CALL	IN$MODDATP
	  ANI	7FH
	  CPI	XOFF
	  CZ	WAITXON
	  RET
;.....
;
;
WAITXON:  CALL	RCVREADY
	  JNZ	WAITXON
	  CALL	IN$MODDATP
	  ANI	7FH
	  CPI	XON
	  RZ
;
WTXON2:	  CALL	STAT		;TEST TO SEE IF REQUESTING CANCELLATION
	  ORA	A
	  JZ	WAITXON
	  CALL	KEYIN		;CAN ABORT IF THE X-ON NEVER COMES
	  CPI	CAN
	  JNZ	WAITXON
	  RZ
;.....
;
;
;***********************************************************************
;
; SUBROUTINES 
;
;***********************************************************************
;
SENDFN:	  CALL	ILPRT
	  DB	'Awaiting name NAK',CR,LF,0
	  MVI	E,100
	  CALL	WAITNLP
	  MVI	A,ACK		;GOT NAK, SEND ACK
	  CALL	SEND
	  LXI	H,FILECT
	  DCR	M
	  JM	NOMRNM
	  LHLD	NBSAVE		;GET FILE NAME..
	  LXI	D,FCB		;..IN FCB
	  MVI	B,12
	  CALL	MOVE
	  SHLD	NBSAVE
	  CALL	SENDNM		;SEND IT
	  ORA	A		;CLEAR CARRY
	  RET
;.....
;
;
NOMRNM:	  MVI	A,EOT
	  CALL	SEND
	  STC
	  RET
;.....
;
;
SENDNM:	  PUSH	H
;
SENDNM1:  MVI	D,11		;COUNT CHARS IN NAME
	  MVI	C,0		;INIT CHECKSUM
	  MOV	A,C
	  STA	FTYCNT		;INITIATE FILE TYPE COUNT
	  LXI	H,FCB+1		;ADDRESS NAME
;
NAMLPS:	  LDA	QFLG		;IN QUIET MODE NOW?
	  ORA	A
	  JNZ	SKPMON		;IF NOT, EXIT
	  LDA	NSEEFLG		;SET FLAG FOR NO SEND TO MODEM
;
SKPMON:   MOV	A,M		;SEND NAME
	  ANI	7FH		;STRIP HIGH ORDER BIT SO CP/M 2..
	  CALL	SEND		;..WON'T SEND R/O FILE DESIGNATION.
	  MVI	A,TRUE
	  STA	NSEEFLG
	  LDA	QFLG
	  ORA	A
	  MOV	A,M
	  CNZ	FTYTST		;TYPE CHARACTER ETC.
;
ACKLP:	  PUSH	B		;SAVE CKSUM
	  MVI	B,1		;WAIT FOR RECEIVER..
	  CALL	RECV		;..TO ACKNOWLEDGE..
	  POP	B		;..GETTING LETTER.
	  JC	SCKSER
	  CPI	ACK
	  JNZ	ACKLP
	  INX	H		;NEXT CHAR
	  DCR	D
	  JNZ	NAMLPS
	  MVI	A,EOFCHAR	;TELL RECEIVER END OF NAME
	  CALL	SEND
	  LDA	QFLG
	  ORA	A
	  CNZ	CRLF
	  MOV	D,C		;SAVE CHECKSUM
	  MVI	B,1
	  CALL	RECV		;GET CHECKSUM..
	  CMP	D		;..FROM RECEIVER.
	  JZ	NAMEOK
;
SCKSER:	  MVI	A,BDNMCH	;BAD NAME-TELL RECEIVER
	  CALL	SEND
	  CALL	ILPRT
	  DB	CR,LF,'++ CHECKSUM error ++',CR,LF,0
	  MVI	E,100	;DO HANDSHAKING OVER
	  CALL	WAITNLP		;DON'T PRINT "AWAITING NAK" MSG
	  MVI	A,ACK
	  CALL	SEND
	  JMP	SENDNM1
;.....
;
;
NAMEOK:	  MVI	A,OKNMCH	;GOOD NAME-TELL RECEIVER
	  CALL	SEND
	  POP	H
	  RET	
;.....
;
;
GETFN:	  LXI	H,FCB
	  CALL	INITFCB+2	;DOES NOT INITIALIZE DRIVE
	  CALL	ILPRT
	  DB	'Awaiting FILENAME',CR,LF,0
;
GNAMELP:  CALL	HSNAK
	  JC	GNAMELP
	  CALL	GETNM		;GET THE NAME
	  CPI	EOT		;IF EOT, THEN NO MORE FILES
	  JZ	NOMRNMG
	  ORA	A		;CLEAR CARRY
	  RET
;.....
;
;
NOMRNMG:  STC
	  RET
;.....
;
;
GETNM:	  PUSH	H
;
GETNM1:	  MVI	C,0		;INIT CHECKSUM
	  MOV	A,C
	  STA	FTYCNT		;INITIATE COUNT FOR FILE TYPE
	  LXI	H,FCB+1
;
NAMELPG:  MVI	B,5		;WAIT AWHILE FOR FILE NAME
	  CALL	RECV		;GET CHAR
	  JNC	GETNM2
	  CALL	ILPRT
	  DB	CR,LF,'Time out receiving FILENAME',CR,LF,0
	  JMP	GCKSER
;.....
;
;
GETNM2:	  CPI	EOT		;IF EOT, THEN NO MORE FILES
	  JZ	GNRET
	  CPI	EOFCHAR		;GOT END OF NAME
	  JZ	ENDNAME
	  MOV	M,A		;PUT NAME IN FCB
	  CALL	FTYTST
	  PUSH	B		;SAVE CKSUM
	  MVI	A,ACK		;ACK GETTING LETTERS
	  CALL	SEND
	  POP	B
	  INX	H		;GET NEXT CHAR
	  MOV	A,L		;DON'T LET NOISE...
	  CPI	7FH		;..CAUSE OVERFLOW..
	  JZ	GCKSER		;..INTO PROGRAM AREA.
	  JMP	NAMELPG
;.....
;
;
FTYTST:	  LDA	FTYCNT
	  INR	A
	  STA	FTYCNT
	  CPI	9		;ARE WE AT THE FILE TYPE?
	  JZ	SPCTST		;GO IF SO
;
ENDSPT:	  MOV	A,M
	  CPI	' '		;TEST FOR SPACE
	  CNZ	TYPE		;TYPE IF NOT
	  RET
;.....
;
;
SPCTST:	  MOV	A,M
	  CPI	' '		;TEST FOR SPACE IN FIRST FILE TYPE BYTE
	  RZ			;DON'T OUTPUT PERIOD IF SPACE
	  MVI	A,'.'	
	  CALL	TYPE
	  JMP	ENDSPT		;OUTPUT FIRST FILE TYPE BYTE
;.....
;
;
ENDNAME:  LDA	QFLG
	  ORA	A
	  CNZ	CRLF
	  MOV	A,C		;SEND CHECKSUM
	  CALL	SEND
	  MVI	B,1
	  CALL	RECV		;CHECKSUM GOOD?
	  CPI	OKNMCH		;YES IF OKNMCH SENT..
	  JZ	GNRET		;..ELSE DO OVER.
;
GCKSER:	  LXI	H,FCB		;CLEAR FCB (EXCEPT DRIVE)..
	  CALL	INITFCB+2	;..SINCE IT MIGHT BE DAMAGED..
	  CALL	ILPRT
	  DB	CR,LF,'++ CHECKSUM error ++',CR,LF,0
;
GCKSER1:  CALL	HSNAK		;DO HANDSHAKING OVER
	  JC	GCKSER1
	  JMP	GETNM1
;...
;
;
GNRET:	  POP	H
	  RET
;.....
;
;
HSNAK:	  MVI	A,NAK		;SEND NAK UNTIL..
	  CALL	SEND		;..RECEIVING ACK.
	  CALL	CKABORT		;DON'T GET HUNG UP HERE
	  MVI	B,2		;WAIT 2 SECONDS..
	  CALL	RECV		;..IN RECEIVE.
	  CPI	ACK		;IF ACK,RETURN WITH..
	  RZ			;..CARRY CLEAR.
	  STC
	  RET
;.....
;
;
TNMBUF:	  MVI	A,FALSE		;CALL FROM SENDFIL ONLY ONCE.
	  STA	FSTFLG
	  STA	FILECT
	  CALL	SCAN
	  LXI	H,NAMEBUF
	  SHLD	NBSAVE		;SAVE ADDR OF 1ST NAME
;
TNLP1:	  CALL	TRTOBUF
	  LXI	H,FCB
	  LXI	D,FCBBUF
	  CALL	CMDLINE		;PARSE NAME TO CP/M FORMAT
;
TNLP2:	  CALL	MFNAME		;SEARCH FOR NAMES (* FORMAT)
	  JC	NEXTNM
	  LDA	FCB+10		;IF CP/M 2 $SYS FILE..
	  ANI	80H		;..DON'T SEND
	  JNZ	TNLP2
	  LHLD	NBSAVE		;GET NAME
	  LXI	D,FCB		;MOVE IT TO FCB
	  XCHG
	  MVI	B,12
	  CALL	MOVE
	  XCHG
	  SHLD	NBSAVE		;ADDR OF NEXT NAME
	  LXI	H,FILECT	;COUNT FILES FOUND
	  INR	M
	  JMP	TNLP2
;.....
;
;
NEXTNM:	  LXI	H,NAMECT	;COUNT NAMES FOUND
	  DCR	M
	  JNZ	TNLP1
	  LXI	H,NAMEBUF	;SAVE START OF BUFFER
	  SHLD	NBSAVE
	  LDA	FILECT
	  CPI	64+1		;NO MORE THAN 64 TRANSFERS
	  RC
	  MVI	A,64		;ONLY X'FER FIRST 64
	  STA	FILECT
	  RET
;.....
;
;
BUFMSG:	  CALL	ILPRT
	  DB	CR,LF,'** Memory buffer ',0
	  LDA	SAVEFLG
	  ORA	A
	  JZ	BUFMSG2
	  CALL	ILPRT
	  DB	'open **',CR,LF,':',BELL,0
	  RET
;.....
;
;
BUFMSG2:  CALL	ILPRT
	  DB	'closed **',CR,LF,BELL,0
	  RET
;.....
;
;
EXITMEN:  CALL	CRLF
	  CALL	CLREOS		;CLEAR LINE TO CLEAN UP ANY MESS
	  JMP	MENU0
;.....
;
;
SENDRDY:  CALL	IN$MODCTLP
	  CALL	ANI$MODSNDB
	  JMP	CPI$MODSNDR
;.....
;
;
SENDLF:	  CALL	SENDRDY
	  JNZ	NOLFYET		;GO IF NOT READY FOR OUTPUT YET
	  MVI	A,LF
	  JMP	NOTOG		;SEND LF
;.....
;
;
NOLFYET:  CALL	EXITTEST
	  JNC	EXITMEN		;GO IF SO, SO DON'T GET HUNG UP
	  JMP	SENDLF		;ELSE KEEP TRYING TO SEND LF
;.....
;
;
SENDLOG:  PUSH	H
	  LHLD	LOGONPTR	;HL POINTS TO START OF LOGON MESSAGE
;
LOGLP:	  CALL	SENDRDY
	  JNZ	NOSENLOG	;GO IF NOT READY
	  MOV	A,M		;GET LOGON BYTE
	  INX	H
	  CPI	0		;IS IT THE END?
	  JZ	ENDLOG		;GO IF SO
	  CALL	OUT$MODDATP
	  JMP	LOGLP
;...
;
;
NOSENLOG: CALL	EXITTEST	;TEST SO DON'T GET HUNG UP
	  JNC	EXITLOG		;GO IF OPERATOR WANTS EXIT
	  JMP	LOGLP
;...
;
;
ENDLOG:	  POP	H
	  JMP	TERML
;.....
;
;
EXITLOG:  POP	H
	  JMP	EXITMEN
;.....
;
;
EXITTEST: CALL	STAT		;KEYPRESS?
	  JZ	NOKEY
	  CALL	KEYIN	
	  MOV	B,A
	  LDA	EXITCHR		;SEE IF OPERATOR WANTS EXIT
	  CMP	B
	  JNZ	NOKEY		;GO IF WRONG KEY		
	  STC
	  CMC			;RESET FOR EXIT
	  RET
;.....
;
;
NOKEY:	  STC			;SET FOR NO KEY OR WRONG KEY
	  RET
;.....
;
;
EXTFLG:	MVI	A,TRUE
	STA	EXACFLG
	JMP	TERML
;.....
;
;
RCVREADY: CALL	IN$MODCTLP
	  CALL	ANI$MODRCVB
	  JMP	CPI$MODRCVR
;.....
;
;
LSTMSG:	  LDA	LISTFLG		;SEE IF PRINTER SHOULD BE ON OR OFF
	  ORA	A
	  JZ	LSTMSG2
	  CALL	ILPRT
	  DB	'Printer is on',CR,LF,0
	  RET
;.....
;
;

LSTMSG2:  CALL	ILPRT
	  DB	'Printer is off',CR,LF,0
	  RET
;.....
;
;
NOTOG:	  CALL	OUT$MODDATP
	  MOV	B,A
	  LDA	LOCFLG
	  ORA	A
	  JNZ	LTYPE
	  LDA	ECHOFLG
	  ORA	A
	  JZ	CHKCR
;
LTYPE:	  MOV	A,B
	  CALL	TYPE
	  CALL	CHKSAVE		;TO STORE LOCAL IF BUFFER OPEN
	  CALL	CHKPRNT
;
CHKCR:	  MVI	A,CR
	  CMP	B
	  JNZ	TERML
	  LDA	ADDLF
	  ORA	A
	  JZ	TERML
	  JMP	SENDLF
;.....
;
;
;
TERML:	  CALL	RCVREADY	;TEST FOR RECEIVED CHARACTER
	  JNZ	TERM2
	  CALL	IN$MODDATP
	  ANI	7FH		;STRIP PARITY
	  JZ	TERM2		
;
GIVLF:	  CALL	TYPE
	  MOV	B,A
	  CALL	CHKSAVE
	  CALL	CHKPRNT
	  LDA	ECHOFLG
	  ORA	A
	  JZ	NOECHO
	  MOV	A,B
	  CALL	OUT$MODDATP
;
NOECHO:	  MVI	A,CR
	  CMP	B
	  JNZ	TERM2
	  LDA	ADDLF
	  JZ	TERM2
	  LDA	ECHOFLG
	  ORA	A
	  JNZ	SENDLF
	  MVI	A,LF
	  JMP	GIVLF
;
CHKSAVE:  LDA	SAVEFLG
	  ORA	A
	  RZ
	  MOV	M,B
	  INX	H
	  SHLD	HLSAVE		;MENU COMMAND DESTROYS HL-REG..
	  MVI	A,LF
	  CMP	B
	  JNZ	NOCOLON		;..TYPE ":" AFTER EACH LINE FEED..
	  MVI	A,':'		;..WHEN MEMORY SAVE ACTIVE.
	  CALL	TYPE
;
NOCOLON:  CALL	GETMAX
	  CMP	H
	  PUSH	B
	  CZ	INTDSKSV
	  POP	B
	  RET
;.....
;
;
GETMAX:	  LDA	SAVCCP
	  ORA	A
	  LDA	7
	  JZ	SUB1
	  SBI	8		;..PAGE BELOW CCP ..
;				;..ORA BDOS HAS BEEN..
SUB1:	  DCR	A		;..REACHED AND DISKSAVE IS NEEDED
	  RET
;.....
;
;
CHKPRNT:  LDA	LISTFLG		;OUT TO PRINTER?
	  ORA	A
	  RZ			;RETURN IF NOT
	  LDA	NFILFLG		;IS BUFFER USED FOR FILE?
	  ORA	A		;IF YES DON'T BUFFER PRINTER, HOWEVER..
	  CALL	GETMAX		;..CHARACTERS WILL BE LOST IF PRINTER
	  LHLD	HLSAVE1		;..SLOWER THAN MODEM	
	  CMP	H		;ARE WE THERE?
	  JNZ	NOTMAX		;GO IF NOT
	  LXI	H,BOTTRAM	;FLUSH BUFFER
	  SHLD	HLSAVE1
	  SHLD	HLSAVE2
;
NOTMAX:	  MOV	M,B		;SAVE CHARACTER IN BUFFER
	  INX	H		;INCREMENT END OF BUFFER
	  SHLD	HLSAVE1
	  MVI	A,TRUE		;SET FLAG FOR PRINTER OUTPUT
	  STA	LISTMOR
	  RET
;.....
;
;
NOBUFF:	  CALL	LSTSTAT	
	  ORA	A
	  RZ			;RETURN IF PRINTER NOT READY
	  MOV	C,B		;ELSE PRINT CHARACTER
	  JMP	LISTER
;
GOLIST:	  CALL	LSTSTAT
	  ORA	A
	  RZ			;RETURN IF PRINTER NOT READY
	  LHLD	HLSAVE2		;GET LOCATION OF NEXT CHARACTER TO PRINT
	  MOV	C,M		;GET CHARACTER
	  INX	H		;INCREMENT POINTER
	  SHLD	HLSAVE2
	  CALL	CMPBUFF		;CHECK FOR END OF BUFFER
	  JMP	LISTER		;PRINT
;
;
; ROUTINE CHECKS FOR END OF BUFFER, RESETS BUFFER IF SO AND STOPS THE
; PRINTER OUTPUT
;
CMPBUFF:  LHLD	HLSAVE2
	  XCHG
	  LHLD	HLSAVE1
	  MOV	A,L
	  SUB	E
	  MOV	L,A
	  MOV	A,H
	  SBB	D
	  ORA	L
	  RNZ
	  LXI	H,BOTTRAM
	  SHLD	HLSAVE1
	  SHLD	HLSAVE2
	  XRA	A
	  STA	LISTMOR
	  RET
;.....
;
;
INTDSKSV: MVI	A,XOFF		;SEND A CTL-S TO STOP..
	  CALL	OUT$MODDATP	;..REMOTE COMPUTER OUTPUT.
	  MVI	D,0		;D IS THE BUFFER COUNT
	  CALL	INMODEM		;GET LAST BYTES SENT..
	  STA	LASTBYT1	;..AFTER CTL-S.
	  CALL	INMODEM		;ADD MORE CALLS TO INMODEM..
	  STA	LASTBYT2	;..AND STA LASTBYT# IF YOU ARE..
	  PUSH	D
	  CALL	NUMREC1		;GET NUMBER OF RECORDS TO PUT ON DISK
	  CALL	WRTDSK		;WRITE THE RECORDS
	  POP	D
	  LXI	H,BOTTRAM
	  INR	D
	  DCR	D		;TEST BUFFER COUNT FOR ZERO
	  JZ	CTLQ
	  LDA	LASTBYT1	;GET THE LAST BYTES THAT WERE..
	  MOV	M,A		;..SAVED AND PUT THEM IN..
	  INX	H		;..BOTTRAM.
	  CALL	TYPE
	  DCR	D
	  JZ	CTLQ
	  LDA	LASTBYT2
	  MOV	M,A
	  INX	H
	  CALL	TYPE
;
CTLQ:	  MVI	A,XON		;SEND START CHARACTER..
	  JMP	OUT$MODDATP	;..TO REMOTE COMPUTER.
;.....
;
;
BREAK:	  PUSH	D		;SAVE IT
	  LXI	D,0		;ZERO IT
	  LDA	MODCTLB		;GET THE LAST MODEM CONTROL BYTE
	  ANI	BRKMSK		;SET THE TRANSMIT BREAK BIT LOW
	  CALL	OUT$MODCTL2 	;SEND IT TO THE MODEM
	  PUSH	H
	  LXI	H,48		;100 MS. BREAK
	  CALL	FIXCNT
	  PUSH	H
	  POP	B
	  POP	H
;
BRK1:	  CALL	TIMERL
	  JZ	BRK2		;IF TIME IS UP RESET BREAK
	  CPI	0		;CHECK FOR NULLS
	  JZ	BRK1		;DON'T PROCESS THEM
	  ANI	7FH		;STRIP PARITY
	  CALL	TYPE
	  PUSH	PSW
	  LDA	SAVEFLG
	  CPI	FALSE
	  JZ	NOSAVEB
	  POP	PSW
	  MOV	M,A
	  INX	H
	  SHLD	HLSAVE		;MENU COMMAND DESTROYS HL-REG..
;				;..GET	HL WHEN ENTERING VIA 'NOL' CMD.
COLONB:   CPI	LF
	  JNZ	BRK1		;..TYPE ":" AFTER EACH LINE FEED..
	  MVI	A,':'		;..WHEN MEMORY SAVE ACTIVE.
	  CALL	TYPE
	  JMP	BRK1
;...
;
;
NOSAVEB:  POP	PSW		;RESTORE IT
	  JMP	BRK1
;...
;
;
BRK2:	  LDA	MODCTLB		;GET MODEM CONTROL BYTE
	  CALL	OUT$MODCTL2
	  POP	D
	  LHLD	HLSAVE		;LAST ADDRESS WRITTEN IF DATA BEING SAVED
	  LDA	SAVCCP
	  ORA	A
	  JZ	SUB2
	  LDA	7		;CHECK TO SEE IF..
	  SBI	8		;..PAGE BELOW CCP ..
	  JMP	SUB2A
;...
;
;
SUB2:	  LDA	7
;
SUB2A:	  DCR	A		;..OR BDOS HAS BEEN ..
	  CMP	H		;..REACHED AND DISKSAVE IS NEEDED.
	  JNZ	TERM2		;NO PROBLEM - GO BACK TO NORMAL ROUTINE
	  CALL	ILPRT
	  DB	CR,LF,'Memory-save buffer full',CR,LF,BELL,0
	  JMP	TERM2
;.....
;
;
; THIS SUBROUTINE WILL LOOP UNTIL THE MODEM RECEIVES A CHARACTER OR 100
; MILLISECONDS.  IF A CHARACTER IS RECEIVED, A FLAG IS SET TO STORE THE
; CHARACTER.  A MAXIMUM OF TWO CHARACTERS ARE STORED, BUT MORE MAY BE
; STORED IF DESIRED (SEE COMMENT IN "INTDSKSV" ABOVE).
;
INMODEM:  PUSH	H
	  LXI	H,48		;100 MILLISECONDS
	  CALL	FIXCNT
	  PUSH	H
	  POP	B
	  POP	H
;
TIMERL:	  CALL	RCVREADY
	  JZ	GETBYTE
	  DCX	B
	  MOV	A,B
	  ORA	C
	  JNZ	TIMERL
	  RET
;.....
;
;
GETBYTE:
	  CALL	IN$MODDATP
	  INR	D
	  RET
;.....
;
;
NUMRECS:
	  MVI	M,EOFCHAR
	  INX	H
	  LXI	D,127
	  DAD	D
;
NUMREC1:  LXI	D,-(BOTTRAM)
	  DAD	D
	  MOV	A,L		;DIVIDE HL BY 128..
	  ORA	A
	  RAL			;..TO GET THE..
	  MOV	L,H		;..NUMBER OF RECORDS
	  MVI	H,0
	  PUSH	PSW
	  DAD	H
	  POP	PSW
	  MVI	A,0
	  ADC	L
	  MOV	L,A		;RETURNS WITH NUMBER OF..
	  RET			;..128 BYTE RECORDS IN HL.
;.....
;
;
; WRITE TO DISK BUT FIRST CHECK TO SEE IF ANYTHING TO WRITE.  IF NOT,
; CLOSE THE EMPTY FILE.
;
WRTDSK:	  LXI	D,BOTTRAM	;GET FIRST CHARACTER
	  LDAX	D		;GET THE CHARACTER AT START OF BUFFER
	  CPI	EOFCHAR		;END OF FILE CHARACTER?
	  JZ	NOWRITE		;DO NOT WRITE IF NO DATA TO STORE
	  MOV	A,H		;MAKE SURE THERE IS SOMETHING TO STORE
	  ORA	L
	  JZ	NOWRITE		;DO NOT WRITE IF NO DATA TO STORE
;
NEXTWRT:  MVI	C,SETDMA
	  CALL	BDOSRT
	  PUSH	D
	  LXI	D,FCB3
	  MVI	C,WRITE
	  CALL	BDOSRT
	  POP	D
	  XCHG
	  PUSH	D
	  LXI	D,128
	  DAD	D
	  POP	D
	  XCHG
	  DCX	H
	  MOV	A,H
	  ORA	L
	  JNZ	NEXTWRT
	  RET
;.....
;
;
; IF NO DATA TO STORE ON DISK, CLOSE THE EMPTY FILE AND ERASE IT
;
NOWRITE:  CALL  CLOSFIL		;CLOSE THE EMPTY FILE
	  CALL	NOASK		;ERASE THE EMPTY FILE
	  CALL	ILPRT
	  DB	'++ Nothing to save, erasing the file ++'
	  DB    CR,LF,BELL,0
	  JMP	DONETCA		;RESET ANY FLAGS, RETURN TO MENU
;.....
;
;
CLOSE3:	  LXI	D,FCB3
	  MVI	C,CLOSE
	  JMP	BDOS
;.....
;
;
BDOSRT:	  PUSH	B
	  PUSH	D
	  PUSH	H
	  PUSH	PSW
	  CALL	BDOS
	  POP	PSW
	  POP	H
	  POP	D
	  POP	B
	  RET
;
MOVE2:	  LXI	H,FCB3
	  CALL	INITFCB
	  LXI	H,FCB
	  LXI	D,FCB3
	  MVI	B,12
	  JMP	MOVE
;.....
;
;
INITFCB:  MVI	M,0		;ENTRY AT +2 WILL LEAVE DRIVE NO. INTACT
	  INX	H		;WILL INITIALIZE AN FCB..
	  MVI	B,11		;..POINTED TO BY HL-REG. FILLS 1ST POS
;
LOOP10:	  MVI	M,' '		;..WITH 0, NEXT 11 WITH..
	  INX	H		;..WITH BLANKS, AND LAST..
	  DCR	B		;..21 WITH NULLS.
	  JNZ	LOOP10
	  MVI	B,21
;
LOOP11:	  MVI	M,0
	  INX	H
	  DCR	B
	  JNZ	LOOP11
	  RET
;.....
;
;
; SCANS CMDBUF COUNTING NAMES AND PUTTING DELIMITER (SPACE) AFTER LAST
; NAME
;
SCAN:	  PUSH	H
	  LXI	H,NAMECT
	  MVI	M,0
	  LXI	H,CMDBUF+1	;FIND END OF CMD LINE..
	  MOV	C,M		;..AND PUT SPACE THERE.
	  MVI	B,0
	  LXI	H,CMDBUF+2
	  DAD	B
	  MVI	M,' '
	  LXI	H,CMDBUF+1
	  MOV	B,M
	  INR	B
	  INR	B
;
SCANLP1:  INX	H
	  DCR	B
	  JZ	DNSCAN
	  MOV	A,M
	  CPI	' '
	  JNZ	SCANLP1
;
SCANLP2:  INX	H		;EAT EXTRA SPACES
	  DCR	B
	  JZ	DNSCAN
	  MOV	A,M
	  CPI	' '
	  JZ	SCANLP2
	  SHLD	BGNMS		;SAVE START OF NAMES IN CMDBUF
	  INR	B
	  DCX	H
;
SCANLP3:  INX	H
	  DCR	B
	  JZ	DNSCAN
	  MOV	A,M
	  CPI	' '
	  JNZ	SCANLP3
	  LDA	NAMECT		;COUNTS NAMES
	  INR	A
	  STA	NAMECT
;
SCANLP4:  INX	H		;EAT SPACES
	  DCR	B
	  JZ	DNSCAN
	  MOV	A,M
	  CPI	' '
	  JZ	SCANLP4
	  JMP	SCANLP3
;.....
;
;
DNSCAN:	  MVI	M,' '		;SPACE AFTER LAST CHAR
	  POP	H
	  RET
;.....
;
;
; PLACES NEXT NAME IN BUFFER SO 'CMDLINE' MAY PARSE IT
;
TRTOBUF:  LHLD	BGNMS
	  MVI	B,0
	  LXI	D,FCBBUF+2
;
TBLP:	  MOV	A,M
	  CPI	' '
	  JZ	TRBFEND
	  STAX	D
	  INX	H
	  INX	D
	  INR	B		;COUNT CHARS IN NAME
	  JMP	TBLP
;.....
;
;
TRBFEND:  INX	H
	  MOV	A,M		;EAT EXTRA SPACES
	  CPI	' '
	  JZ	TRBFEND
	  SHLD	BGNMS
	  LXI	H,FCBBUF+1	;PUT # CHARS BEFORE NAME
	  MOV	M,B
	  RET
;.....
;
;
; IN CP/M V.2, IF FILE IS R/O OR SYS, IT IS CHANGED TO 'BAK'.
;
CKCPM2:	  MVI	C,CPMVER	;BDOS 12 -- VERSION NUMBER -- CP/M 2.2?
	  CALL	BDOS
	  ORA	A	
	  RZ
	  MVI	C,SETDMA
	  LXI	D,80H
	  CALL	BDOS
	  MVI	C,SRCHF
	  LXI	D,FCB
	  CALL	BDOS
	  CPI	0FFH
	  RZ
;
	  ADD	A
	  ADD	A
	  ADD	A
	  ADD	A		;..32 TO FIND..
	  ADD	A		;..NAME IN DMA.
	  LXI	H,80H
	  ADD	L
	  MOV	L,A		;'HL' POINTS TO DIRECTORY NAME
	  LXI	D,9
	  DAD	D		;POINT TO R/O ATTRIBUTE BYTE
	  MOV	A,M
	  ANI	80H		;TEST MOST SIGNIFICANT BYTE
	  JNZ	MKCHG		;IF SET, MAKE CHANGE
	  INX	H		;CHECK SYSTEM ATTRIBUTE BYTE
	  MOV	A,M
	  ANI	80H
	  RZ			;NOT $SYS OR $R/O ATTRIBUTE
	  DCX	H
;
MKCHG:	  LXI	D,-8
	  DAD	D		;POINT HL TO FILENAME + 1
	  LXI	D,FCB+1		;MOVE DIRECTORY NAME TO FCB..
	  MVI	B,11		;..WITHOUT CHANGING DRIVE.
	  CALL	MOVE
	  LXI	H,FCB+9		;R/O ATTRIBUTE
	  MOV	A,M
	  ANI	7FH		;STRIP R/O ATTRIBUTE
	  MOV	M,A
	  INX	H		;SYSTEM ATTRIBUTE
	  MOV	A,M
	  ANI	7FH
	  MOV	M,A
	  LXI	D,FCB
	  MVI	C,30		;SET NEW ATTRIBUTES IN DIRECTORY
	  CALL	BDOS
;
;
; CALLED BY CKBAKUP BELOW, RETURN DONE HERE THROUGH BDOS JUMP
;
PLANCHG:  LXI	H,FCB		;CHANGE NAME TO TYPE "BAK"
	  LXI	D,FCB2
	  MVI	B,9		;MOVE DRIVE AND NAME (NOT TYPE)
	  CALL	MOVE
	  LXI	H,75H		;START OF TYPE IN FCB2
	  MVI	M,'B'
	  INX	H
	  MVI	M,'A'
	  INX	H
	  MVI	M,'K'
	  LXI	D,FCB2
	  MVI	C,ERASE		;ERASE ANY PREV BACKUPS
	  CALL	BDOS
	  LXI	H,FCB2		;FCB2 DR FIELD SHOULD..
	  MVI	M,0		;..0 FOR RENAME.
	  LXI	D,FCB
	  MVI	C,23		;RENAME
	  JMP	BDOS
;.....
;
;
CKBAKUP:  LDA	BAKUPBYTE
	  ORA	A
	  RZ
	  MVI	C,SRCHF
	  LXI	D,FCB
	  CALL	BDOS
	  INR	A
	  RZ			;FILE NOT FOUND
	  JMP	PLANCHG		;IN "CKCPM2" - RET DONE THERE
;.....
;
;
;***********************************************************************
;
; RECEIVE A RECORD FROM SENDING STATION
;
;***********************************************************************
;
;
RCVRECD:  MVI	A,1
	  STA	ERRCT
	  XRA	A
	  STA	ONERR
;
RCVRPT:	  XRA	A		;ZERO ACCUM
	  STA	ERRCDE		;CLEAR RECEIVE ERROR CODE
	  
	  CALL	CKABORT		;WANT TO STOP RECEIVING FILE?
	  LDA	QFLG
	  ORA	A
	  JZ	RCVSQ
	  CALL	ILPRT
	  DB	CR,'Awaiting # ',0
	  PUSH	H		;SAVE IT
	  LHLD	RECDNO		;GET RECORD NUMBER
	  INX	H		;BUMP IT
	  CALL	DECOUT		;PRINT RECORD NUMBER IN DECIMAL
	  CALL	ILPRT
	  DB	' (', 0
	  CALL	DHXOUT		;16-BIT HEX CONVERSION AND OUTPUT
	  CALL	ILPRT
	  DB	'H) ',0
	  MOV	A,L		;ONLY LOW BYTE USED BY PROGRAM
	  POP	H		;RESTORE IT
;
;
; If CRC is in effect, there is a 10-second timeout to the first SOH.
; It then tries several more times to let the sender know the system is
; capable of receiving a CRC check.  At the end of that time a NAK is
; sent which tells the sender to use CHECKSUM checking instead of CRC.
; This allows automatic compatability with systems implementing CRC -
; (Cyclic Redundancy Checking).
;
; During this time incoming CRC and NAK characters are ignored as these
; may be the ones we are sending at each timeout, coming back from the
; full duplex system.
;
RCVSQ:	  MVI	B,10-1		;10-SECOND WAIT FOR 'SOH' OR 'EOT' CHAR.
	  CALL	RECV		;..(EXTRA 1 SECOND FROM RCVSERR)
	  JC	RCVSTOT		;SEND TIMEOUT MSG IF NO CHAR. IN 10 SEC.
	  CALL	RCVERR		;SEE IF IT WAS AN I/O ERROR
	  CPI	SOH		;GET A START OF HEADER?
	  JZ	RCVSOH
	  ORA	A
	  JZ	RCVSQ
	  CPI	CRC		;IGNORE OUR OWN 'CRC' CHAR. IF ANY
	  JZ	RCVSQ		;DO NOT COUNT THIS AS A TIMEOUT
	  CPI	NAK		;IGNORE OUR OWN 'NAK' CHAR. IF ANY
	  JZ	RCVSQ		;DO NOT COUNT THIS AS A TIMEOUT
	  CPI	EOT
	  STC
	  RZ
;
	  MOV	B,A
	  LDA	BATCHFLG	;USING BATCH MODE NOW?
	  ORA	A
	  JNZ	RCVSQ1		;IF NOT, EXIT
	  LDA	ONERR		;THIS THE FIRST ERROR THIS TRANSFER?
	  ORA	A
	  JNZ	RCVSQ1		;IF NOT, HANDLE NORMALLY^
	  STA	ERRCT		;RESET THE ERROR COUT TO EXCLUDE THIS
	  CMA			;IF YES, IGNORE THIS ERROR
	  STA	ONERR		;SET THE FLAG
	  JMP	RCVSERR	
;
RCVSQ1:   CALL	RCVQERR		;SEE IF QUIET MODE
;
RCVSQ2:	  MOV	A,B
	  CALL	CRLF
	  CALL	HEXO
	  CALL	ILPRT
	  DB	'H received not SOH - ',0
;
RCVPRN:	  CALL	SHOWERR		;DISPLAY ERROR COUNT
;
RCVSERR:  MVI	B,1		;1 SECOND WAIT AFTER ANY CHAR. IS SENT..
	  CALL	RECV		;..TO INSURE SENDER IS WAITING TO COPY
	  JNC	RCVSERR 	;IF STILL SENDING, IGNORE ALL CHARS.
	  CALL	CKABORT		;WANT TO STOP RECEIVING NOW?
	  LDA	CRCFLAG		;GET 'CRC' FLAG
	  ORA	A		;'CRC' IN EFFECT?
	  MVI	A,NAK		;PUT 'NAK' IN ACCUM
	  JNZ	RCVSER1		;NO, SEND THE 'NAK'
	  LDA	FIRSTME 	;GET FIRST TIME SWITCH
	  ORA	A		;HAS FIRST SOH BEEN RECEIVED?
	  MVI	A,NAK
	  JZ	RCVSER1		;YES, THEN SEND 'NAK'
	  MVI	A,CRC		;TELL SENDER 'CRC' IS IN EFFECT
;
RCVSER1:  CALL	SEND		;SEND THE 'NAK' OR 'CRC' REQUEST
	  LDA	ERRCT		;INCREMENT THE  ERROR COUNT
	  INR	A
	  STA	ERRCT
	  CPI	10+1		;IF 10 ALREADY, ABORT
	  JC	RCVRPT		;IF LESS THAN 10, KEEP GOING
	  JMP	ABORT
;.....
;
;
RCVQERR:  LDA	QFLG		;SEE IF QUIET MODE NOW
	  ORA	A
	  RNZ			;IF NOT, PROCEED NORMALLY
	  POP	H		;RESET STACK FOR 'CALL'
	  JMP	RCVSERR
;.....
;
;
RCVSABT:  LXI	SP,STACK	;RESET THE STACK JUST IN CASE
	  CALL	CLOSFIL		;CLOSE THE PARTIAL FILE
	  CALL	NOASK		;DELETE PARTIAL FILE
	  CALL	ILPRT
	  DB	CR,LF,LF
	  DB	'++ RECEIVED FILE CANCELLED ++',CR,LF,BELL
	  DB	'++ UNFINISHED FILE DELETED ++',CR,LF,0
	  JMP	DONETCA
;.....
;
;
; TIMEOUT ROUTINE EACH 10 SECONDS OF NO 'SOH' (START-OF-HEADER)
;
RCVSTOT:  MVI	A,TRUE
	  STA	ONERR
	  LDA	QFLG
	  ORA	A
	  JZ	RCVSTOT1
	  CALL	ILPRT
	  DB	CR,LF,'++ Timeout ',0
	  CALL	SHOWERR		;DISPLAY THE CURRENT ERROR COUNT
;
;
; ROUTINE WILL SWITCH FROM CRC TO CHECKSUM IF ERCNT REACHES ERRCRC AND
; CURRENTLY IN CRC MODE.
;
RCVSTOT1: LDA	ERRCT		;GET THE ERROR COUNT
	  CPI	ERRCRC		;SEE IF LESS THAN CRC-ERROR TRY LIMIT
	  JC	RCVSTOT2	;IF YES, KEEP TRYING
	  LDA	FIRSTME		;OTHERWISE SEE IF WE ALREADY GOT A SOH
	  ORA	A
	  JZ	RCVSTOT2	;IF YES, DON'T SWITCH TO CHECKSUM
	  LDA	CRCFLAG		;IF NOT, SEE IF ALREADY IN CHECKSUM
	  ORA	A
	  JNZ	RCVSTOT2
	  MVI	A,TRUE		;SHOW IN CHECKSUM NOW
	  STA	CRCFLAG		;CHANGE FROM CRC TO CHECKSUM
	  STA	CKSUMDFLT	;OPTION FLAG NOW SHOWS CHECKSUM...
	  CALL	ILPRT		;...FOR FUTURE FILES
	  DB	'++ Switching to CHECKSUM mode ++',CR,LF,BELL,0
;
RCVSTOT2: JMP	RCVSERR		;INCREMENT ERROR COUNT
;.....
;
;
; GET THE ERROR COUNT AND DISPLAY ON CRT
;
SHOWERR:  PUSH	H		;SAVE THE CURRENT ADDRESS
	  LHLD	ERRCT		;GET THE CURRENT ERROR NUMBER
	  MVI	H,0		;ONLY A 8-BIT NUMBER, NOW IN 'L' REG.
	  CALL	DECOUT		;DISPLAY THE ERROR IN DECIMAL
	  POP	H		;RESTORE THE CURRENT ADDRESS
	  CALL	ILPRT
	  DB	' ++',CR,LF,0	;FINISH THE ERROR MESSAGE
	  RET
;.....
;
;
;---->	RCVERR:
;
; Checks for framing, overrun, and parity errors.  Parity errors cannot
; be detected unless the parity option has been selected.
;    1. Error code (ERRCDE) was set in RECV routine.
;    2. ERRCDE=0 for no errors, ERRCDE<>0 for errors.
;    3. If there is an error, routine returns with carry flag set.
;
RCVERR:	  PUSH	PSW		;SAVE CHARACTER RECEIVED
	  LDA	ERRCDE		;CHECK FOR ANY RECEIVE ERROR
	  ORA	A
	  JNZ	RCVDERR		;IF AN ERROR GO SHOW WHICH ERROR IT IS
	  POP	PSW		;IF NO ERROR, GET RECEIVED CHAR. BACK
	  RET
;...
;
;
;----> RCVDERR:  Checks for a receive error and displays an appropriate
;                error message.  Then goes to RCVSERR to purge the line
;                and send a NAK.
;
RCVDERR:  STA	ONERR
	  POP	PSW		;CLEAR STACK OF "PUSH PSW" IN 'RCVERR'
	  POP	PSW		;CLEAR STACK OF "CALL  RCVERR"
	  CALL	RCVQERR		;SEE IF QUIET MODE
	  LDA	ERRCDE		;GET RECEIVE ERR CODE
	  ANI	FRMER		;WAS THERE A FRAMING ERROR?
	  JZ	RCVDERR1	;NO, GO CHECK FOR OVERRUN
	  CALL	ILPRT
	  DB	CR,LF,'++ Framing error ',0
	  JMP	RCVPRN		;PRINT # OF ERROR
;
RCVDERR1: LDA	ERRCDE		;GET RECEIVE ERR CODE
	  ANI	ORUNER		;WAS THERE AN OVERRUN
	  JZ	RCVDERR2	;NO, GO CHECK FOR PARITY ERROR
	  CALL	ILPRT
	  DB	CR,LF,'++ Overrun error ',0
	  JMP	RCVPRN		;PRINT # OF ERROR
;
RCVDERR2: LDA	ERRCDE		;GET RECEIVE ERR CODE
	  ANI	PARER		;WAS THERE A PARITY ERROR?
	  JZ	RCVRPT		;NO, GO PURGE LINE
	  CALL	ILPRT
	  DB	CR,LF,'++ Parity error ',0
	  JMP	RCVPRN		;PRINT # OF ERROR
;.....
;
;
; GOT SOH - GET BLOCK #, BLOCK # COMPLEMENTED
;
RCVSOH:	  XRA	A		;ZERO ACCUM
	  STA	FIRSTME 	;INDICATE FIRST SOH RECV'D
	  MVI	B,1		;1-SECOND DELAY
	  CALL	RECV		;GET RECORD
	  JC	RCVSTOT 	;GOT TIMEOUT
	  CALL	RCVERR		;CHECK FOR RECEIVE ERROR
	  MOV	D,A
	  MVI	B,1
	  CALL	RECV
	  JC	RCVSTOT
	  CALL	RCVERR		;CHECK FOR RECEIVE ERROR
	  CMA
	  CMP	D
	  JZ	RCVDATA
	  CALL	RCVQERR
	  CALL	ILPRT
	  DB	CR,LF,'++  Bad sector # in header',0
	  JMP	RCVPRN
;.....
;
;
RCVDATA:  MOV	A,D
	  STA	RCVRNO
	  MVI	A,1
	  STA	DATAFLG
	  MVI	C,0
	  CALL	CLRCRC		;CLEAR CRC COUNTER
	  LXI	H,80H
;
RCVCHR:	  MVI	B,1
	  CALL	RECV
	  JC	RCVSTOT
	  CALL	RCVERR		;CHECK FOR RECEIVE ERROR
	  MOV	M,A
	  INR	L
	  JNZ	RCVCHR
	  XRA	A 
	  STA	DATAFLG
	  LDA	CRCFLAG		;IN 'CRC' MODE?
	  ORA	A
	  JZ	RCVCRC		;IF YES, EXIT
	  MOV	D,C
	  MVI	B,1
	  CALL	RECV
	  JC	RCVSTOT
	  CALL	RCVERR		;CHECK FOR RECEIVE ERROR
	  CMP	D
	  JNZ	RCVCERR
;
CHKSNUM:  LDA	RCVRNO
	  MOV	B,A
	  LDA	RECDNO
	  CMP	B
	  JZ	RECVACK
	  INR	A
	  CMP	B
	  JNZ	ABORT
	  RET
;.....
;
;
RCVCRC:   MVI	E,2		;NUMBER OF CRC BYTES
;
RCVCRC1:  MVI	B,1
	  CALL	RECV
	  JC	RCVSTOT
	  CALL	RCVERR		;SEE IF ANY RECEIVE ERRORS
	  DCR	E
	  JNZ	RCVCRC1
	  CALL	CHKCRC		;CHECK 'CRC' BYTES OF RECEIVED MESSAGE
	  ORA	A
	  JZ	CHKSNUM		;IF OK, EXIT
	  CALL	RCVQERR		;SEE IF QUIET MODE
	  CALL	ILPRT		;IF NOT, SHOW ERROR MESSAGE
	  DB	CR,LF,'++ CRC error ',0
	  JMP	RCVPRN		;SHOW ERROR NUMBER
;.....
;
;
RCVCERR:  CALL	RCVQERR		;SEE IF QUIET MODE
	  CALL	ILPRT		;IF NOT, SHOW ERROR MESSAGE
	  DB	CR,LF,'++ CHECKSUM error ++ ',0
	  JMP	RCVPRN		;SHOW ERROR NUMBER
;.....  
;
;
RECVACK:  CALL	SENDACK
	  JMP	RCVRECD
;.....
;
;
SENDACK:  MVI	A,ACK
	  CALL	SEND
	  RET
;.....
;
;
SENDHDR:  LDA	QFLG
	  ORA   A
	  JZ	SENDHNM
  	  CALL	ILPRT
	  DB	CR,'Sending # ',0
	  PUSH	H		;STORE CURRENT ADDRESS
	  LHLD	RECDNO		;GET RECORD NUMBER
	  CALL	DECOUT		;PRINT IT IN DECIMAL
	  CALL	ILPRT
	  DB	' (',0
	  CALL	DHXOUT		;16 BIT HEX CONVERSION & OUTPUT
	  CALL	ILPRT
	  DB	'H) ',0
	  POP	H		;RESTORE CURRENT ADDRESS
;
SENDHNM:  MVI	A,SOH		;SEND 'SOH' CHARACTER TO THE OUTPUT
	  CALL	SEND
	  LDA	RECDNO		;SEND RECORD NUMBER TO THE OUTPUT
	  CALL	SEND
	  LDA	RECDNO
	  CMA			;COMPLEMENT THE RECORD NUMBER
	  JMP	SEND		;SEND THIS VALUE TO THE OUTPUT
;.....
;
;
SENDREC:  MVI	A,1
	  STA	DATAFLG
	  MVI	C,0
	  CALL	CLRCRC
	  LXI	H,80H
;
SENDC:	  MOV	A,M
	  CALL	SEND
	  INR	L
	  JNZ	SENDC
	  XRA	A
	  STA	DATAFLG
	  RET
;.....
;
;
SENDCKS:  MOV	A,C
	  JMP	SEND
;.....
;
;
SENDCRC:  CALL	FINCRC
	  MOV	A,D
	  CALL	SEND
	  MOV	A,E
	  CALL	SEND
	  XRA	A
	  RET
;.....
;
;
GETACK:	  MVI	B,10		;10-SECONDS MAXIMUM WAIT TIME
	  CALL	RECVDG
	  JC	GETATOT
	  CPI	ACK
	  RZ			;ALL DONE IF 'ACK' CHARACTER RECEIVED
	  MOV	B,A		;OTHERWISE SHOW WHAT THE CHARACTER WAS
	  LDA	QFLG
	  ORA	A
	  JZ	ACKERR
	  MOV	A,B
	  CALL	CRLF
	  CPI	NAK		;IS IT A NAK?
	  JZ	GETACK1		;SHOW 'NAK' IN THAT CASE
	  CALL	HEXO
	  CALL	ILPRT
	  DB	'H',0
	  JMP	GETACK2
;
GETACK1:  CALL	ILPRT
	  DB	'NAK',0	
;
GETACK2:  CALL	ILPRT		;PRINT THE ERROR MESSAGE
	  DB	' received not ACK - ',0
	  CALL	SHOWERR		;SHOW THE ERROR NUMBER
;
ACKERR:	  LDA	ERRCT		;INCREMENT THE ERROR COUNT
	  INR	A
	  STA	ERRCT
	  CPI	10+1		;SEE IF AT THE LIMIT OF 10 ERRORS YET	
	  RC			;IF NOT, RETURN
	  CALL	ERXIT
	  DB	CR,LF,'++ SEND-FILE CANCELLED ++','$'
;.....
;
;
; TIME-OUT MESSAGE ON ACK
;
GETATOT:  CALL	ILPRT
	  DB	CR,LF,'TIMEOUT on ACK',CR,LF,0
	  JMP	ACKERR
;.....
;
;
CKABORT:  LDA	QFLG
	  ORA	A
	  RZ
	  CALL	STAT
	  RZ
	  CALL	KEYIN
	  CPI	CAN
	  RNZ
;
;
; ABORTS SEND OR RECEIVE ROUTINES AND RETURNS TO COMMAND LINE
;
ABORT:	  LXI	SP,STACK
;
ABORTL:	  MVI	B,1		;1-SECOND DELAY TO CLEAR INPUT
	  CALL	RECV
	  JNC	ABORTL
	  MVI	A,CAN		;SHOW YOU ARE CANCELLING
	  CALL	SEND
;
ABORTW:	  MVI	B,1		;1-SECOND DELAY TO CLEAR INPUT
	  CALL	RECV
	  JNC	ABORTW
	  MVI	A,' '
	  CALL	SEND
	  MVI	A,'B'   	;TURN MULTI-FILE MODE..
	  STA	BATCHFLG  	;..OFF SO ROUTINE ENDS.
	  MVI	A,TRUE
	  STA	ABORTFLG	;SHOWS AN ABORT WAS MADE
	  STA	NFILFLG		;STOP COPY INTO CRT
	  LDA	OPTION		;RECEIVING A FILE NOW?
	  CPI	'R'
	  JZ	RCVSABT		;IF YES, CANCEL THE UNFINISHED FILE
	  CALL	ILPRT
 	  DB	CR,LF,LF,'++ FILE CANCELLED ++',CR,LF,BELL,0
	  JMP	DONETCA
;.....
;
;
INCRRNO:  PUSH	H
	  LHLD	RECDNO		;GET RECORD NUMBER
	  INX	H		;BUMP IT
	  SHLD	RECDNO		;STORE IT
	  MOV	A,L
	  POP	H
	  RET
;.....
;
;
; First check for any wild cards and disallow, just to be safe.  Do not
; want a group of files being accidently erased.
;
ERASFIL:  LXI	H,FCB		;FILE NAME IS STORED HERE
	  MVI	B,11		;MAXIMUM OF 11 CHARS FOR FILENAME.EXT
;
ERASFIL1: INX	H		;NEXT LOCATION IN FILE NAME
	  MOV	A,M		;GET THE CHAR.
	  CPI	'?'		;CHECK FOR ANY WILD CARD CHARS.
	  JZ	ERRORW		;ERROR IF ONE IS FOUND
	  DCR	B		;NUMBER OF TRIES LEFT
	  JNZ	ERASFIL1	;IF NOT ZERO, KEEP CHECKING
	  LDA	BATCHFLG	;DON'T ASK FOR ERASE..
	  ORA	A		;..IN MULTI-FILE MODE,..
	  JZ	NOASK		;..JUST DO IT.
	  LXI	D,FCB
	  MVI	C,SRCHF
	  CALL	BDOS
	  INR	A
	  RZ			;FILE ERASED OK, RETURN
	  CALL	ILPRT		;OTHERWISE MAKE SURE IT'S OK
	  DB	'File exists - erase?  (Y/N): ',BELL,0
	  CALL	KBDCHR
	  CPI	'Y'
	  JNZ	MENU		;IF NOT A 'Y' DO NOT ERASE
	  CALL	CRLF		;OTHERWISE ERASE THE FILE
;
NOASK:	  LXI	D,FCB
	  MVI	C,ERASE
	  JMP	BDOS
;.....
;
;
ERRORW:   POP	H		;RESTORE STACK FROM "CALL ERASFIL"
	  CALL	ILPRT
	  DB	'++ NO WILDCARDS ALLOWED FOR TEXT FILES ++'
	  DB	CR,LF,BELL,0
	  JMP	MENU
;.....
;
;
BLKFILE:  CALL	ILPRT		;ROUTINE IF NO FILE IS NAMED FOR
;				;"SEND" OR "RECEIVE"
	  DB	'++ NO FILE SPECIFIED ++',CR,LF,BELL,0
	  JMP	MENU
;.....
;
;
MAKEFIL:  LXI	D,FCB
	  MVI	C,MAKE
	  CALL	BDOS
	  INR	A
	  RNZ
	  CALL	ERXIT
	  DB	'++ ERROR -- Can''t open file ++',CR,LF
	  DB	'++ Directory is likely full ++','$'
;
CNREC:	  MVI	C,FILSIZ	;COMPUTE FILE SIZE FUNCTION IN CP/M 2.x
	  LXI	D,FCB		;POINT TO FILE CONTROL BLOCK
	  CALL	BDOS
	  LHLD	FCB+33		;GET RECORD COUNT
	  SHLD	RCNT		;STORE IT
	  LXI	H,0		;ZERO 'HL'
	  SHLD	FCB+33		;RESET RANDOM RECORD IN FCB
	  RET
;
;.....
;
;
OPENFIL:  XRA	A
	  STA	FCBEXT
	  LXI	D,FCB
	  MVI	C,OPEN
	  CALL	BDOS
	  INR	A
	  JNZ	SENDTIME	;SEND TRANSFER TIME, # OF RECORDS, ETC.
	  CALL	ERXIT		;FILE DID NOT OPEN
	  DB	'++ FILE NOT FOUND ++','$'
;
;.....
;
;

CLOSFIL:  LXI	D,FCB
	  MVI	C,CLOSE
	  CALL	BDOS
	  INR	A
	  RNZ
	  CALL	ERXIT
	  DB	CR,LF,'++ UNABLE TO CLOSE FILE ++','$'
;.....
;
;
; UPDATE RECORD READ
;
RDRECD:	  LDA	RECINBF
	  DCR	A
	  STA	RECINBF
	  JM	RDBLOCK
	  LHLD	RECPTR
	  LXI	D,80H
	  CALL	MOVE128
	  SHLD	RECPTR
	  RET
;.....
;
;
; BUFFER EMPTY SO READ IN ANOTHER BLOCK (UP TO 16K OR 128 RECORDS)
;
RDBLOCK:  LDA	EOFLG
	  CPI	1
	  STC
	  RZ
	  MVI	C,0
	  LXI	D,DBUF
;
RDRECLP:  PUSH	B
	  PUSH	D
	  MVI	C,SETDMA
	  CALL	BDOS
	  LXI	D,FCB
	  MVI	C,READ
	  CALL	BDOS
	  POP	D
	  POP	B
	  ORA	A
	  JZ	RDRECOK
	  DCR	A
	  JZ	REOF
	  CALL	ERXIT
	  DB	'++ FILE READ ERROR ++','$'
;
RDRECOK:  LXI	H,80H
	  DAD	D
	  XCHG
	  INR	C
	  MOV	A,C
	  CPI	DBUFSIZ*8	;BUFFER SIZE IN 128 BYTE RECORDS
	  JZ	RDBFULL
	  JMP	RDRECLP
;...
;
;
REOF:	  MVI	A,1
	  STA	EOFLG
	  MOV	A,C
;
;
; BUFFER FULL OR RECEIVED EOF
;
RDBFULL:  STA	RECINBF
	  LXI	H,DBUF
	  SHLD	RECPTR
	  LXI	D,80H
	  MVI	C,SETDMA
	  CALL	BDOS
	  JMP	RDRECD
;.....
;
;
; WRITE A RECORD
;
WRRECD:	  LHLD	RECPTR
	  XCHG
	  LXI	H,80H
	  CALL	MOVE128
	  XCHG
	  SHLD	RECPTR
	  LDA	RECINBF
	  INR	A
	  STA	RECINBF
	  CPI	DBUFSIZ*8 	;BUFFER SIZE IN 128 BYTE RECORDS
	  RNZ
;
;
; WRITE A 16K BLOCK TO DISK (128 RECORDS)
;
WRBLOCK:  LDA	RECINBF
	  ORA	A
	  RZ
	  MOV	C,A
	  LXI	D,DBUF
;
DKWRLP:	  PUSH	H
	  PUSH	D
	  PUSH	B
	  MVI	C,SETDMA
	  CALL	BDOS
	  LXI	D,FCB
	  MVI	C,WRITE
	  CALL	BDOS
	  POP	B
	  POP	D
	  POP	H
	  ORA	A
	  JNZ	WRERR
	  LXI	H,80H
	  DAD	D
	  XCHG
	  DCR	C
	  JNZ	DKWRLP
	  XRA	A
	  STA	RECINBF
	  LXI	H,DBUF
	  SHLD	RECPTR
	  RET
;.....
;
;
; ERROR WHILE WRITING A RECORD, SHOW WHY IT IS ABORTING
;
WRERR:	  MVI	C,CAN
	  CALL	SEND
	  CALL	ERXIT
	  DB	CR,LF,'++ FILE WRITE ERROR ++','$'
;.....
;
;
;----> RECV: Receive a character
;
; Timeout time is in B, in seconds.  Entry via 'RECVDG' deletes garbage
; characters on the line.  For example, having just sent a sector,
; calling RECVDG will delete any line noise induced characters LONG
; before the ACK/NAK would be received.
;
RECVDG:	  CALL	IN$MODDATP
	  CALL	IN$MODDATP
;
RECV:	  PUSH	D		;SAVE ANY CURRENT VALUES
	  MOV	A,B		;MULTIPLY 'B' BY 4 FOR EXTRA DELAY
	  RAL
	  RAL
	  MOV	B,A
;
MSEC:	  CALL	CKABORT		;WANT TO INTENTIONALLY ABORT?
	  PUSH	H
	  LXI	H,175		;MASTER DELAY FACTOR
	  CALL	FIXCNT
	  PUSH	H		;SAVE THE DELAY VALUE NOW IN 'HL'
	  POP	D		;GET IT BACK, BUT IN 'DE'
	  POP	H		;RESTORE THE STACK TO NORMAL
;
MWTI:	  CALL	RCVREADY	;INPUT HAVE A CHARACTER READY?
	  JZ	MCHAR		;IF YES, EXIT
	  DCR	E
	  JNZ	MWTI
	  DCR	D
	  JNZ	MWTI
	  DCR	B		;NUMBER OF SECONDS WANTED
	  JNZ	MSEC		;IF NOT ZERO, DO 1-SECOND LOOP AGAIN
	  POP	D		;RESTORE ORIGINAL VALUES
	  STC			;NO CHARACTER SO SET CARRY BIT
	  RET
;.....
;
;
MCHAR:	  LDA	PMMIBYTE	;USING A PMMI MODEM?
	  ORA	A
	  JZ	MCHAR1		;IF NOT, SKIP THE FOLLOWING LINES
	  CALL	IN$MODCTLP  	;GET ERROR-STATUS BYTE
	  ANI	ERRCDMSK    	;MASK OUT ALL EXCEPT ERROR BITS (3-5)
	  STA	ERRCDE      	;SAVE THE ERROR CODE
;
MCHAR1:	  CALL	IN$MODDATP
	  POP	D		;RESTORE ORIGINAL VALUES
	  PUSH	PSW
	  CALL	UPDCRC		;CALCULATE CRC
	  ADD	C	
	  MOV	C,A
	  LDA	RSEEFLG
	  ORA	A
	  JZ	MONIN
	  LDA	VSEEFLG
	  ORA	A
	  JNZ	NOMONIN
	  LDA	DATAFLG
	  ORA	A
	  JZ	NOMONIN
;
MONIN:	  POP	PSW
	  PUSH	PSW
	  CALL	SHOW
;
NOMONIN:  POP	PSW
	  ORA	A
	  RET
;.....
;
;
; SEND A CHARACTER TO THE MODEM
;
SEND:	  PUSH	PSW
	  LDA	NSEEFLG
	  ORA	A
	  JZ	MONOUT
	  LDA	SSEEFLG
	  ORA	A
	  JZ	MONOUT
	  LDA	VSEEFLG
	  ORA	A
	  JNZ	NOMONOT
	  LDA	DATAFLG
	  ORA	A
	  JZ	NOMONOT
;
MONOUT:	  POP	PSW
	  PUSH	PSW
	  CALL	SHOW
;
NOMONOT:  POP	PSW
	  PUSH	PSW
	  CALL	UPDCRC		;CALCULATE CRC
	  ADD	C
	  MOV	C,A
	  LDA	NSEEFLG		;NOT SENDING TO MODEM?
	  ORA	A
	  JZ	SENDW1		;IF YES, EXIT
;
SENDW:	  CALL	SENDRDY
	  JNZ	SENDW
	  POP	PSW
	  JMP	OUT$MODDATP
;
SENDW1:	  POP	PSW		;RESTORE STACK
	  RET
;.....
;
;
; WAITS FOR THE FIRST CHARACTER RECEIVED WHILE WAITING TO SEND A FILE.
; IF A CHARACTER IS NOT RECEIVED IN ONE SECOND, IT LOOPS AGAIN UNTIL A
; CHAR IS RECEIVED OR IT TIMES OUT.  THE COUNT IS SET FOR 100 SECONDS
; BEFORE TIMEOUT.  THIS GIVES ENOUGH THE RECEIVING STATION AMPLE TIME
; TO NAME A FILE, ETC.
;
WAITNAK:  CALL	ILPRT
	  DB	'Awaiting CRC request',CR,LF,0
;
WAITNLP:  CALL	CKABORT
	  MVI	B,1
	  CALL	RECV
	  CPI	CAN		;WANT TO QUIT?
	  JZ	ABORT
	  CPI	CRC		;CRC REQUEST?
	  JZ	WAITCRC		;YES, GO SET CRC FLAG
	  CPI	NAK
	  RZ
	  DCR	E
	  JNZ	WAITNLP
	  JMP	ABORT
;...
;
;
WAITCRC:  CALL	ILPRTQ
	  DB	'CRC request received',CR,LF,0
	  XRA	A
	  STA	CRCFLAG		;MAKE SURE IN 'CRC' MODE THEN
	  RET
;.....
;
;
;--->PARITY: Routine to setup PMMI for odd/even parity.
;
PARITY:	  LDA	PMMIBYTE	;IS MODEM A PMMI?
	  ORA	A		;SET FLAGS
	  RZ			;NO, RETURN
;MOD(BGL)***
	  LDA	PARTY		;CURRENTLY 8/NONE?
	  CPI	ORIGMOD		;IF NOT, IGNORE
	  RNZ
	  LDA	OPARITY		;GET ODD PARITY REQUEST BYTE
	  ORA	A		;SET FLAGS
	  JNZ	EVENPAR		;IF NOT ODD SEE IF IT IS EVEN
	  LDA	UARTCTLB	;GET UART/MODEM CONTROL BYTE
	  ANI	ODPARMSK
	  JMP	PARITY1
;...
;
;
EVENPAR:  LDA	EPARITY 	;GET EVEN PARITY REQUEST BYTE
	  ORA	A         	;SET FLAGS
	  RNZ               	;IF EVEN PARITY NOT SPECIFIED RETURN
	  LDA	UARTCTLB  	;GET UART/MODEM CONTROL BYTE
	  ANI	ODPARMSK  	;SET FOR PARITY
	  ORI	EVPARMSK  	;NOW SET FOR EVEN PARITY
;
PARITY1:  JMP	OUT$MODCTLP	;SEND TO PMMI -
;				;WHEN OUT$MODCTLP DOES RET IT
;.....				;WILL GO BACK TO CALLING ROUTINE
;
;
NOPARIT:  LDA	PMMIBYTE
	  ORA	A
	  RZ
	  LDA	UARTCTLB	;GET UART/MODEM CONTROL BYTE
	  ORI	NOPARMSK	;RESET PARITY BIT ON PMMI
	  JMP	OUT$MODCTLP
;.....
;
;MOD(BGL)***
TOGLPAR:  LXI	H,PARTOG
	  MOV	A,M
	  DCX	H
	  SUB	M
	  MOV	M,A
	  STA	UARTCTLB
	  CALL	OUT$MODCTLP
	  JMP	XPRT
;.....
;
;
INITADR:  LHLD	1		;BIOS WARM REBOOT JUMP VECTOR
	  LXI	D,3
	  DAD	D
	  SHLD	VSTAT+1		;BIOS CONSOLE STATUS JUMP VECTOR
	  DAD	D
	  SHLD	VKEYIN+1	;BIOS CONSOLE KEYBOARD JUMP VECTOR
	  DAD	D
	  SHLD	VTYPE+1		;BIOS CONSOLE CRT JUMP VECTOR
	  DAD	D
	  SHLD	VLIST+1		;BIOS LIST DEVICE JUMP VECTOR
	  LXI	D,30
	  DAD	D
	  SHLD	VLSTAT+1	;BIOS LIST DEVICE STATUS JUMP VECTOR
	  LDA	PMMIBYTE
	  ORA	A
	  RZ			;SKIP THE REST IF NOT PMMI
	  LDA	IN$MODCTLP+1
	  STA	OUT$MODCTLP+1
	  INR	A
	  STA	OUT$MODDATP+1
	  STA	IN$MODDATP+1
	  INR	A
	  STA	IN$BAUDRP+1
	  STA	OUT$BAUDRP+1
	  INR	A
	  STA	OUT$MODCTL2+1
	  RET
;.....
;
;
; CHECK OPTIONS, PUT 0 IN APPROPRIATE PLACES IN OPTION TABLE IF OPTION
; SELECTED
;
PROCOPT:  LXI	D,FCB+1
 	  LDAX	D
	  STA	OPTION
;
OPTLP:	  INX	D
	  LDAX	D
	  CPI	' '
	  JZ	ENDOPT
	  LXI	H,OPTBL
	  MVI	B,OPTBE-OPTBL
;
OPTCK:	  CMP	M
	  JNZ	OPTNO
	  CPI	'O'
	  JNZ	OPTCK1
	  XRA	A
	  STA	UARTFLG
	  JMP	OPTCK2
;...
;
;
OPTCK1:	  CPI	'A'
	  JNZ	OPTCK2
	  MVI	A,TRUE
	  STA	UARTFLG
;
OPTCK2:	  MVI	M,0
	  JMP	OPTLP
;...
;
;
OPTNO:	  INX	H
	  DCR	B
	  JNZ	OPTCK
	  CALL	NTVLDMSG
	  POP	PSW		;PRESERVE STACK
	  JMP	MENU
;
ENDOPT:	  LDA	VSEEFLG
	  ORA	A
	  RNZ
	  STA	QFLG		;QUITE MODE FOR DATA ITEMS
	  RET
;.....
;
;
DONE: 	  LDA	BATCHFLG	;IN BATCH MODE?
	  ORA	A
	  JNZ	DONETC		;EXIT IF NOT
	  LDA	QFLG
	  ORA	A
	  JZ	NMSTRNS
	  MVI	B,12		;ZERO OUT FTRNMSG
	  LXI	H,FTRNMSG
	  MVI	A,0
;
ZEROLP:	  MOV	M,A
	  INX	H
	  DCR	B
	  JNZ	ZEROLP
	  MVI	B,12		;PUT FILE NAME IN FTRNMSG
	  LXI	H,FCB+1		
	  LXI	D,FTRNMSG
;
LOADMSG:  MVI	A,4		;START OF FILE TYPE?
	  CMP	B
	  JZ	PERIOD		;PUT IN PERIOD IF SO
	  MOV	A,M	
	  CPI	' '		;DON'T PUT IN SPACE
	  JZ	SKPSP	
	  STAX	D		;STORE IN FTRNMSG
	  INX	D
;
SKPSP:	  INX	H
	  DCR	B
	  MOV	A,B
	  ORA	A		;END OF FILE NAME?
	  JZ	FTRNMSG0	;DISPLAY FILE NAME
	  JMP	LOADMSG		;LOOP FOR ANOTHER CHARACTER
;.....
;
;
PERIOD:	  MOV	A,M
	  CPI	' '		;IS FILE TYPE EMPTY?
	  JZ	FTRNMSG0	;GO IF SO
	  MVI	A,'.'		;ELSE PUT PERIOD IN MESSAGE
	  STAX	D
	  INX	D
	  DCR	B
	  JMP	LOADMSG
;.....
;
;
FTRNMSG0: CALL	ILPRT
	  DB	CR,LF
;
FTRNMSG:  DS	12
	  DB	0
	  CALL	ILPRT
	  DB	' Transferred',CR,LF,LF,BELL,0
;
NMSTRNS:  LDA	FCB		;SAVE DRIVE NO.
	  STA	DISKNO
	  LXI	H,FCB		;BLANK OUT FILE CONTROL BLOCKS
	  CALL	INITFCB
	  LDA	DISKNO		;PUT DRIVE NUMBER BACK
	  STA	FCB
	  LXI	H,RESTSN	;RESTORE RECORD NUMBERS..
	  LXI	D,RECDNOB	;..FOR NEW FILE TRANSFER.
	  MVI	B,RECDNOE-RECDNOB ;ROUTINE ALSO DONE IN MENU.
	  CALL	MOVE
	  CALL	IN$MODDATP
	  CALL	IN$MODDATP
	  LDA	SENDFLG		;GOES TO EITHER SEND OR..
	  ORA	A		;..RECEIVE FILE, DEPENDING..
	  JNZ	SENDFIL1	;..UPON WHICH ROUTINE SET..
	  JMP	RCVFIL1		;..THE FLAG IN MULTI-FILE MODE.
;.....
;
;
DONETC:	  CALL	CKABORT		;SLIGHT DELAY FOR NEXT MESSAGE
	  CALL	ILPRT
	  DB	CR,LF,'[Transfer Completed]',CR,LF,BELL,0
;
DONETCA:  LDA	XITFLG		;SPECIAL 'X' FLAG SET?
	  ORA	A
	  JZ	BYEBYE		;IF YES, DISCONNECT AND REBOOT
	  LDA	DISCFLG		;NORMAL 'D' FLAG SET?
	  ORA	A
	  JZ	DONETCC		;IF YES, DISCONNECT, GET NEXT COMMAND
;
DONETCB:  CALL	NOPARIT		;RESET TO NO PARITY
	  MVI	A,CRC
	  STA	CRCFLAG		;TURNS OFF CRC OPTION
	  MVI	A,TRUE
	  STA	FIRSTME		;SET FIRST-TIME FLAG
	  STA	FSTFLG		;RESET MULTIFILE TRANS
	  STA	NFILFLG		;..USED IN TERMINAL ROUTINE.
	  CMA
	  STA	SAVEFLG		;STOP MEMORY SAVE IN TERM ROUTINE.
	  STA	LISTMOR		;STOP ANY BUFFERED OUTPUT TO PRINTER
	  LXI	H,BOTTRAM	;RESET PRINTER BUFFER POINTERS
	  SHLD	HLSAVE1
	  SHLD	HLSAVE2	
	  LXI	H,QFLG		;IN QUIET MODE?
	  MOV	A,M
	  ORA	A
	  MVI	M,'Q'		;RESET THE FLAG TO NORMAL
	  JZ	MENU		;IF YES, GO BACK TO COMMAND LINE
	  LDA	ABORTFLG	;COME HERE FROM A TIMEOUT?
	  ORA	A
	  JNZ	MENU		;IF YES, GO TO COMMANDE MODE
	  LDA	TERMFLG		;SEE IF RETURN TO..
	  ORA	A		;..TERMINAL MODE..
	  JNZ	MENU		;..AFTER X'FER.
	  CALL	CRLF
	  JMP	TERM
;.....
;
;
DONETCC:  CALL	ILPRT
	  DB	CR,LF,'<< DISCONNECTED >>',CR,LF,0
	  CALL	JMP$DISCONNT	;HANG-UP THE PMMI
	  JMP	MENU		;BACK TO COMMAND LINE
;.....
;
;
MOVEFCB:  LXI	H,FCB+16
	  LXI	D,FCB
	  MVI	B,16
	  CALL	MOVE
	  XRA	A
	  STA	FCBSNO
	  STA	FCBEXT
	  RET
;.....
;
;
SHOW:	  CPI	LF
	  JZ	CTYPE
	  CPI	CR
	  JZ	CTYPE
	  CPI	9
	  JZ	CTYPE
	  CPI	' '
	  JC	SHOWHEX
	  CPI	7FH
	  JC	CTYPE
;
SHOWHEX:  PUSH	PSW
	  MVI	A,'('
	  CALL	CTYPE
	  POP	PSW
	  CALL	HEXO
	  MVI	A,')'
	  JMP	CTYPE
;.....
;
;
CTYPE:	  PUSH	B
	  PUSH	D
	  PUSH	H
	  MOV	E,A
	  MVI	C,WRCON
	  CALL	BDOS
	  POP	H
	  POP	D
	  POP	B
	  RET
;.....
;
;
CRLF:	  PUSH	PSW
	  MVI	A,CR
	  CALL	TYPE
	  MVI	A,LF
	  CALL	TYPE
	  POP	PSW
	  RET
;.....
;
;
STAT:	  PUSH	B
	  PUSH	D
	  PUSH	H
;
VSTAT:	  CALL	$-$		;BIOS CONSTAT ADDRESS, FILLED IN..
	  POP	H		;..BY INITADR ROUTINE
	  POP	D
	  POP	B
	  ORA	A
	  RET
;.....
;
;
KEYIN:	  PUSH	B
	  PUSH	D
	  PUSH	H
;
VKEYIN:	  CALL	$-$		;BIOS CONIN ADDRESS, FILLED IN..
	  POP	H		;..BY INITADR ROUTINE
	  POP	D
	  POP	B
	  RET
;.....
;
;
LISTER:	  PUSH	B
	  PUSH	D
	  PUSH	H
;
VLIST:	  CALL	$-$		;BIOS LIST OUT ADDRESS, FILLED IN..
	  POP	H		;..BY INITADR ROUTINE
	  POP	D
	  POP	B
	  RET
;.....
;
;
LSTSTAT:  PUSH	B
	  PUSH  D
	  PUSH	H
;
VLSTAT:	  CALL	$-$		;BIOS LIST DEVICE STATUS ADDRESS,..
	  POP	H		;..FILLED IN BY INITADR ROUTINE
	  POP	D
	  POP	B
	  RET
;.....
;
;
TYPE:	  PUSH	PSW
	  PUSH	B
	  PUSH	D
	  PUSH	H
	  MOV	C,A
;
VTYPE:	  CALL	$-$		;BIOS CONOUT ADDRESS, FILLED IN..
	  POP	H		;..BY INITADR ROUTINE
	  POP	D
	  POP	B
	  POP	PSW
	  RET
;.....
;
; GET A CHARACTER FROM THE KEYBOARD, CONVERT TO UPPER CASE IF NEEDED,
; AND SHOW ON CRT
;
KBDCHR:	  CALL	KEYIN		;GET A KEYBOARD CHARACTER
	  CALL	UCASE		;CONVERT TO UPPER CASE IF NEEDED
	  CALL	TYPE		;SHOW ON CRT
	  RET
;.....
;
;
UCASE:	  CPI	61H		;CHANGES LOWER CASE CHARACTER..
	  RC			;..IN A-REG TO UPPER CASE.
	  CPI	7AH+1		;SEE IF MORE THAN SMALL 'Z'
	  RNC
	  ANI	5FH
	  RET
;.....
;
;
DECOUT:	  PUSH	PSW
	  PUSH	B
	  PUSH	D
	  PUSH	H
	  LXI	B,-10
	  LXI	D,-1
;
DECOU2:	  DAD	B
	  INX	D
	  JC	DECOU2
	  LXI	B,10
	  DAD	B
	  XCHG
	  MOV	A,H
	  ORA	L
	  CNZ	DECOUT
	  MOV	A,E
	  ADI	'0'
	  CALL	CTYPE
	  POP	H
	  POP	D
	  POP	B
	  POP	PSW
	  RET
;.....
;
;
;---->	DHXOUT: - DOUBLE PRECISION HEX OUTPUT ROUTINE.
;
DHXOUT:	  PUSH	H
	  PUSH	PSW
	  MOV	A,H		;GET MS BYTE
	  CALL	HEXO		;OUTPUT HIGH ORDER BYTE
	  MOV	A,L		;GET LS BYTE
	  CALL	HEXO		;OUTPUT LOW ORDER BYTE
	  POP	PSW
	  POP	H
	  RET
;.....
;
;
; PRINTS A HEX VALUE IN 'A' ON THE CRT
;
HEXO:	  PUSH	PSW
	  RAR
	  RAR
	  RAR
	  RAR
	  CALL	NIBBL
	  POP	PSW
;
NIBBL:	  ANI	0FH
	  CPI	10
	  JC	ISNUM
	  ADI	7
;
ISNUM:	  ADI	'0'		;ADD IN ASCII BIAS
	  JMP	CTYPE
;.....
;
;
; DISPLAYS THE CONTROL-CHARACTERS SHOWN IN THE MENU
;
SHFTYPE:  PUSH	PSW
	  CALL	ILPRT
	  DB	'CTL-',0
	  POP	PSW
	  ADI	40H		;CONVERT BINARY TO ASCII CHARS.
	  CALL	TYPE		;SHOW ON THE CRT
	  JMP	ILPRT
;.....
;
;
; WRITE A STRING OF CHARACTERS
;
ILPRT:	  XTHL
;
ILPRT1:	  MOV	A,M		;GET THE CHARACTER
	  ORA	A		;SEE IF A "0" FOR END OF STRING
	  JZ	ILPRT2		;IF YES, ALL DONE
	  CALL  CTYPE		;SHOW ON CRT
	  INX	H		;GET THE NEXT LOCATION IN THE STRING	
	  JMP	ILPRT1
;
ILPRT2:	  XTHL			;RESTORE THE ADDRESS
	  RET
;.....
;
;
; WRITE A STRING OF CHARACTERS UNLESS IN QUIET MODE
;
ILPRTQ:	  XTHL
;
ILPRTQ1:  MOV	A,M		;GET THE CHARACTER
	  ORA	A		;SEE IF A "0" FOR END OF STRING
	  JZ	ILPRTQ2		;IF YES, ALL DONE
	  LDA	QFLG
	  ORA	A
	  MOV	A,M
	  CNZ	CTYPE		;SHOW ON CRT IF NOT IN QUITE MODE
	  INX	H		;GET THE NEXT LOCATION IN THE STRING	
	  JMP	ILPRTQ1
;
ILPRTQ2:  XTHL			;RESTORE THE ADDRESS
	  RET
;.....
;
;
PRTMSG:	  MVI	C,PRINT		;PRINT THE STRING
	  JMP	BDOS
;.....
;
;
; DISPLAYS ERROR STATEMENT THEN RETURNS TO COMMAND MODE
;
ERXIT:	  POP	D
	  CALL	PRTMSG
	  MVI	A,BELL
	  CALL	TYPE
	  CALL	CRLF
	  MVI	A,TRUE
	  STA	ABORTFLG	;SHOWS AN UNINTENTIONAL ABORT
	  LDA	BATCHFLG	;IN BATCH MODE?
	  ORA	A
	  JNZ	DONETCB		;IF NOT, EXIT
	  JMP	ABORT		;ABORT OTHER COMPUTER
;.....
;
;
; EXITS DIRECTLY TO CP/M, WITH NO REBOOT UNLESS YOU ALLOW POSSIBLE
; OVERWRITING OF CCP.
;
EXIT:	  LDA	OLDUSER		;GET ORIGINAL USER NUMBER BACK
	  MOV	E,A
	  CALL	SETUSER
	  LXI	D,80H		;RESTORE ORIGINAL BUFFER AREA
	  MVI	C,SETDMA
	  CALL	BDOS
	  LDA	SAVCCP		;WAS CCP LEFT INTACT?
	  ORA	A
	  JZ	0000H		;IF NOT, WARM REBOOT JUST IN CASE
;
EXIT1:	  JMP	$-$		;OVERWRITTEN WITH CCP RETURN BY "START"
;.....
;
;
MOVE128:  MVI	B,128
;
MOVE:	  MOV	A,M
	  STAX	D
	  INX	H
	  INX	D
	  DCR	B
	  JNZ	MOVE
	  RET
;.....
;
;
; INITIALIZES CP/M FILE CONTROL BLOCKS AT 5CH AND 6CH
;
SETFCB:	  LXI	D,CMDBUF
	  LXI	H,FCB
	  CALL	CMDLINE
	  CALL	PROCOPT
	  LDA	FCB+1		;CHECK ON THE PRIMARY OPTION
	  CPI	'E'		;RETURN IF ECHO OPTION
	  RZ
	  CPI	'H'		;RETURN IF HELP OPTION
	  RZ
	  CPI	'L'		;RETURN IF LOCAL ECHO OPTION
	  RZ
	  MOV	B,A
	  LDA	PMMIBYTE
	  ORA	A
	  MOV	A,B
	  JZ	S4
	  CPI	'C'
	  RZ
;
S4:	  CPI	'T'
	  JZ	TERMSEL
	  CPI	'S'
	  JZ	CKFILE
	  CPI	'R'
	  JNZ	BDOPT
	  LDA	BATCHFLG	;IF MULT FILE MODE, THEN..
	  ORA	A		;..RECV OPT DOES NOT NEED..
	  RZ			;..NAME.
	  JMP	CKFILE
;.....
;
;
BDOPT:	  CALL	ILPRT
	  DB	CR,LF,'++ Bad Option ++',CR,LF,LF,0
	  JMP	REENT
;.....
;
;
CKFILE:   LDA	FCB+17		;IF OPTION THAT NEEDS FILE NAME,..
	  CPI	' '		;..THEN CHECK TO SEE IF NAME..
	  RNZ			;..EXISTS. IF NOT..
;
REENT:	  CALL	ILPRT		;..DO EVERYTHING OVER.
	  DB	'++ Enter primary option plus file name ++'
	  DB	CR,LF,BELL,0
	  POP	H		;RESET STACK FROM 'CALL SETFCB'
	  JMP	MENU		;ABORT TO COMMAND LINE
;.....
;
;
TERMSEL:  LDA	FCB+17
	  CPI	' '
	  JNZ	SAVAGN
	  MVI	A,FALSE
	  STA	SAVEFLG
	  MVI	A,TRUE
	  STA	NFILFLG
	  RET
;.....
;
;
SAVAGN:	  MVI	A,FALSE
	  STA	NFILFLG
	  RET
;.....
;
;	
; CHANGE BAUDRATE ON-THE-FLY WITH CTL-B (WHILE IN TERMINAL MODE)
;
NEWBAUD:  LDA	PMMIBYTE
	  ORA	A
	  RZ
	  CALL	ILPRT
	  DB	CR,LF,'Enter new Baudrate: ',0
	  LXI	H,FCB+9
	  MVI	M,0		;DEFAULTS TO 300 BAUD IF NO ANSWER TYPED
;
NEWBAUD1: CALL	KEYIN		;GET THE BAUD RATE
	  CPI	CR		;CARRIAGE RET FINISHES BAUD RATE ENTRY
	  JNZ	CONNEWB		;GOES TO THE ESTABLISHED ROUTINE	
	  CALL	CRLF		;PROGRAM IS DONE THERE.
	  JMP	FIXBAUD		;GO CHANGE THE BAUD RATE
;.....
;
;
CONNEWB:  CPI	'0'		;NUMERALS ARE 0-9
	  JC	NEWBAUD1
	  CPI	'9'+1
	  JNC	NEWBAUD1	;IF NOT A NUMERAL, IGNORE, ASK AGAIN
	  MOV	M,A		;STORE ANSWER STARTING AT FCB+9
	  CALL	TYPE		;SHOW THE NUMERAL ON THE CRT
	  INX	H		;NEXT STORAGE LOCATION IN FCB
	  JMP	NEWBAUD1	;GET THE NEXT NUMERAL
;.....
;
;
; ADJUSTS LOOP COUNTERS FOR THE SELECTED CLOCK SPEED
;
FIXCNT:	  LDA	CLOCK		;GET THE USER'S CLOCK SPEED
	  PUSH	D
	  PUSH	H
	  POP	D
;
CNTMUL:	  DAD	D
	  DCR	A
	  JNZ	CNTMUL
	  POP	D		;RETURN WITH ANSWER IN 'HL'
	  RET
;.....
;
;  
;=======================================================================
;
; LOADS A COMMAND LINE ADDRESSED BY DE REGISTERS (MAX # CHARACTERS IN
; LINE IN DE, NUMBER OF CHARS IN LINE IN DE+1, LINE STARTS IN DE+2) INTO
; FCB ADDRESSED BY HL REGISTERS.  THE FCB SHOULD BE AT LEAST 33 BYTES IN
; LENGTH.  THE COMMAND LINE BUFFER MUST HAVE A MAXIMUM LENGTH  AT LEAST
; ONE MORE THAN THE GREATEST NUMBER OF CHARACTERS THAT WILL BE NEEDED.

CMDLINE:  PUSH	PSW
	  PUSH	B
	  PUSH	D
	  PUSH	H
	  CALL	INITIAL		;FILLS FCBS WITH BLANKS AND NULLS
	  XCHG			;GET START OF COMMAND LINE IN HL.
	  INX	H		;ADDRESS # BYTES IN CMD LINE.
	  MOV	E,M		;LOAD DE PAIR WITH # BYTES.
	  MVI	D,0
	  INX	H
	  DAD	D		;POINT TO BYTE AFTER LAST CHAR..
	  MVI	M,CR		;..IN CMD LINE AND STORE DELIMITER.
	  POP	H		;RESTORE HL AND DE.
	  POP	D
	  PUSH	D
	  PUSH	H
	  INX	D		;ADDRESS START OF COMMAND.
	  INX	D
	  CALL	DRIVE
;
NAME1:	  MVI	C,8		;TRANSFER FIRST FILENAME TO FCB.
	  CALL	TRANS
	  CPI	CR
	  JZ	DONEL
	  CPI	' '		;IF SPACE, THEN START OF..
	  JZ	NAME2		;..SECOND FILENAME.
;
TYPE1:	  POP	H		;FILETYPE MUST BE AFTER..
	  PUSH	H		;..EIGHTH BYTE OF NAME.
	  LXI	B,9
	  DAD	B
	  MVI	C,3		;TRANSFER TYPE OF FIRST FILE
	  CALL	TRANS
	  CPI	CR
	  JZ	DONEL
;
NAME2:	  LDAX	D		;EAT MULTIPLE SPACES..
	  CPI	' '		;..BETWEEN NAMES.
	  JNZ	NAME2C
	  INX	D
	  JMP	NAME2
;
NAME2C:	  POP	H		;SECOND NAME STARTS IN 16TH BYTE.
	  PUSH	H		;POINT HL TO THIS BYTE.
	  LXI	B,16
	  DAD	B
	  CALL	DRIVE
	  MVI	C,8
	  CALL	TRANS
	  CPI	CR
	  JZ	DONEL
;
TYPE2:	  POP	H		;SECOND TYPE STARTS IN 25TH BYTE.
	  PUSH	H
	  LXI	B,25
	  DAD	B
	  MVI	C,3
	  CALL	TRANS
;
DONEL:	  POP	H
	  PUSH	H
	  INX	H		;POINT TO 1ST CHAR OF 1ST NAME IN FCB..
	  CALL	SCANL		;CHECK FOR * (AMBIGUOUS NAMES).
	  POP	H
	  PUSH	H
	  LXI	B,17		;..TO 1ST CHAR OF SECOND NAME IN FCB.
	  DAD	B
	  CALL	SCANL
	  POP	H
	  POP	D
	  POP	B
	  POP	PSW
	  RET
;.....
;
;
; SUBROUTINES FOR CMDLINE SECTION
;
INITIAL:  PUSH	H	;INITIALIZES FCB WITH 1 NULL (FOR FIRST DRIVE)..
	  PUSH	B	;..11 BLANKS, 4 NULLS, 1 NULL (FOR 2ND DRIVE)..
	  MVI	M,0	;..11 BLANKS, AND 4 NULLS.
	  INX	H
	  MVI	B,11
	  MVI	A,' '
	  CALL	INITFILL
	  MVI	B,5
	  XRA	A
	  CALL	INITFILL
	  MVI	B,11
	  MVI	A,' '
	  CALL	INITFILL
	  MVI	B,4
	  XRA	A
	  CALL	INITFILL
	  POP	B
	  POP	H
	  RET
;.....
;
;
INITFILL: MOV	M,A
	  INX	H
	  DCR	B
	  JNZ	INITFILL
	  RET
;.....
;
;
DRIVE:	  INX	D		;CHECK 2ND BYTE OF FILENAME.  IF IT..
	  LDAX	D		;..IS A ":", THEN DRIVE WAS SPECIFIED..
	  DCX	D
	  CPI	':'
	  JNZ	DEFDR		;..ELSE ZERO FOR DEFAULT DRIVE ..
	  LDAX	D		;..('INIT' PUT ZERO)
	  ANI	5FH
	  SUI	40H		;CALCULATE DRIVE (A=1, B=2,...)..
	  MOV	M,A		;..AND PLACE IT IN FCB.
	  INX	D		;ADDRESS FIRST BYTE OF..
	  INX	D		;..IN CMD LINE,..
;
DEFDR:	  INX	H		;..AND NAME FIELD IN FCB.
	  RET
;.....
;
;
TRANS:	  LDAX	D		;TRANSFER FROM CMD LINE TO FCB..
	  INX	D		;..UP TO NUMBER OF CHARS SPECIFIED..
	  CPI	CR		;..BY C-REG. KEEP SCANNING FIELD..
	  RZ			;..WITHOUT TRANSFER UNTIL A DELIMITING..
;
	  CPI	'.'		;..FIELD CHAR SUCH AS '.', BLANK, OR..
	  RZ			;..C/R (FOR END OF CMD LINE).
	  CPI	' '
	  RZ
	  DCR	C
	  JM	TRANS		;ONCE C-REG IS LESS THAN ZERO, KEEP..
	  MOV	M,A		;..READING CMD LINE BUT DO NOT..
	  INX	H		;..TRANSFER TO FCB.
	  JMP	TRANS
;...
;
;
SCANL:	  MVI	B,8		;SCAN FILE NAME ADDRESSED BY HL.
;
TSTNAM:	  MOV	A,M
	  CPI	'*'		;IF '*' FOUND, FILL IN REST OF FIELD..
	  JZ	FILL1		;..WITH '?' FOR AMBIGUOUS NAME.
	  INX	H
	  DCR	B
	  JNZ	TSTNAM
	  JMP	TSTTYP
;...
;
;
FILL1:	  CALL	FILL
;
TSTTYP:	  MVI	B,3		;SCAN AND FILL TYPE FIELD FOR NAME..
;
TSTTYPL:  MOV	A,M		;..SPECIFIED ABOVE.
	  CPI	'*'
	  JZ	FILL2
;
	  INX	H
	  DCR	B
	  JNZ	TSTTYPL
	  RET
;.....
;
;
FILL2:	  CALL	FILL
	  RET
;.....
;
;
FILL:	  MVI	M,'?'		;ROUTINE TRANSFERS '?'.
	  INX	H
	  DCR	B
	  JNZ	FILL
	  RET

;=======================================================================
;
; LISTS DIRECTORY AND GIVES FREE SPACE REMAINING ON THE REQUESTED DRIVE.
;
;
; Disk system reset - currently bypassed, if you wish this feature, put
;	  JMP DIRLIST2 instead of JMP DIRLIST3 in the eighth line.  The
;	  current disk (plus the A: drive) will then reset each DIR re-
;	  quest.  You can also reset the disk with the LOG command when
;	  when inserting a different one.  This saves a reset each time
;	  DIR might be requested.
;
DIRLIST:  MVI	C,CURDSK	;CURRENT DEFAULT DISK, 25.
	  CALL	BDOS
	  PUSH	PSW		;SAVE DEFAULT DISK LETTER
	  ADI	41H		;MAKE IT ASCII AND..
	  STA	DRNAME		;..STORE HERE AND..
	  STA	DEFDRV		;..HERE.
;
DIRLIST1: JMP	DIRLIST3
;
DIRLIST2: MVI	C,RESET		;13 RESET DISK SYSTEM (RESETDK)
	  CALL	BDOS
;
DIRLIST3: POP	PSW		;GET DEFAULT LETTER BACK AND..
	  MOV	E,A		;..PUT FOR SELECT.
	  MVI	C,SELDSK	;SELECT DISK AGAIN AS DEFAULT (SELDK)
	  CALL	BDOS
;
;
; Directory list routine
;
	  LXI	D,CMDBUF	;PUT COMMAND LINE IN FCB..
	  LXI	H,FCB		;..ADDRESSED BY HL-REG..
	  CALL	CMDLINE		;..AND THEN...
	  LXI	H,FCB4
	  CALL	INITFCB
	  LDA	FCB2		;GET DRIVE NUMBER
	  STA	FCB4
	  LDA	FCB2+1
	  CPI	' '		;IF A SPACE (BLANK) GET ALL NAMES
	  PUSH	PSW
	  CZ	QSTMARK
	  POP	PSW
	  CNZ	MOVNAME		;ELSE MOVE NAME INTO FCB
	  CALL	DRIVEL
	  LXI	D,80H
	  MVI	C,SETDMA
	  CALL	BDOS
	  LDA	NOOFCOL		;NUMBER OF COLUMNS INTO REG-A
	  STA	NAMECT		;CRLF AFTER "NOOFCOL" NUMBER OF COLUMNS
	  LXI	D,FCB4
	  MVI	C,SRCHF		;DO FIRST SEARCH
  	  CALL	BDOS
	  INR	A		;FFH --> 0 IF NO FILE(S) FOUND
	  JNZ	DIRLOOP
	  CALL	ILPRT
	  DB	'++ FILE NOT FOUND ++',0
	  JMP	STORAGE		;STILL SHOW STORAGE ON DEFAULT DRIVE
;
DIRLOOP:  CALL	GETADD
	  INX	H		;POINT TO FIRST LETTER OF FILENAME
	  LXI	D,PRTNAME
	  LXI	B,8
	  CALL	MOVER
	  INX	D
	  LXI	B,3
	  CALL	MOVER
	  CALL	ILPRT
;
PRTNAME:  DB	'        ','.','   ',0   ; 8 SPACES, PERIOD, 3 SPACES
;
NEXTSR:	  LXI	D,FCB4
	  MVI	C,SRCHN		;DO NEXT SEARCH
	  CALL	BDOS
	  INR	A		;IF 0FFH --> 0 THEN..
	  JZ	STORAGE		;..DIRECTORY-READ FINISHED.
	  PUSH	PSW
	  PUSH	D
	  PUSH	H
	  LDA	NAMECT
	  DCR	A
	  STA	NAMECT		;NAME COUNT UPDATED
	  ORA	A
	  CZ	CRLF		;TERMINATE LINE OF FILE NAMES
	  JNZ	FENCE
	  LDA	NOOFCOL		;RESTART COLUMNS-PER-LINE COUNT
	  STA	NAMECT
	  JMP	NOFENCE		;FENCE NOT NEEDED
;
FENCE:	  CALL	ILPRT
	  DB	' : ',0		;FENCE IF NOT AT END OF LINE OR..
;				;..LAST FILENAME
NOFENCE:  POP	H
	  POP	D
	  POP	PSW
	  JMP	DIRLOOP
;.....
;
;
; DETERMINE STORAGE REMAINING ON DEFAULT DRIVE
;
STORAGE:  CALL	CRLF
	  MVI	C,DSKPAR	;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
	  MVI	C,DSKALL	;ADDRESS OF CP/M ALLOCATION VECTOR
	  CALL	BDOS
	  XCHG			;GET ITS LENGTH
	  LHLD	BMAX
	  INX	H
	  LXI	B,0		;INITIALIZE BLOCK COUNT TO ZERO
;
GSPBYT:	  PUSH	D		;SAVE ALLOCATION ADDRESS
	  LDAX	D
	  MVI	E,8		;SET TO PROCESS 8 BLOCKS
;
GSPLUP:	  RAL			;TEST BIT
	  JC	NOTFRE
	  INX	B
;
NOTFRE:	  MOV	D,A		;SAVE BITS
	  DCX	H
	  MOV	A,L
	  ORA	H
	  JZ	ENDALC		;QUIT IF OUT OF BLOCKS
	  MOV	A,D		;RESTORE BITS
	  DCR	E		;COUNT DOWN 8 BITS
	  JNZ	GSPLUP		;DO ANOTHER BIT
	  POP	D		;BUMP TO NEXT COUNT..
	  INX	D		;..OF ALLOCATION VECTOR.
	  JMP	GSPBYT		;PROCESS IT
;
ENDALC:	  POP	D		;CLEAR ALLOC VECTOR POINTER FROM STACK
	  MOV	L,C		;COPY BLOCK TO HL
	  MOV	H,B
	  LDA	BSHIFTF		;GET BLOCK SHIFT FACTOR
	  SUI	3		;CONVERT FROM RECORDS TO THOUSANDS (K)
	  JZ	PRTFREE		;SKIP SHIFTS IF 1K BLOCKS
;
FREKLP:	  DAD	H		;MULTIPLY BLOCKS BY K PER BLOCK
	  DCR	A
	  JNZ	FREKLP
;
PRTFREE:  CALL 	DECOUT		;(# OF FREE K BYTES IN HL)
	  LXI	D,FREEMSG
	  CALL	PRTMSG
	  CALL	GETUSER		;GET USER NUMBER
	  MVI	H,0
	  MOV	L,A
	  CALL	DECOUT		;PRINT USER NUMBER
	  LXI	D,DEFUSR
	  JMP	PRTMSG
;.....
;
;
; SUBROUTINES FOR DIRLIST SECTION
;
QSTMARK:  MVI	A,'?'		;IF BLANK IN FCB, PUT IN 11 ?'S.
	  MVI	B,11
	  LXI	H,FCB4+1
;
QSTLP:	  MOV	M,A
	  INX	H
	  DCR	B
	  JNZ	QSTLP
	  RET
;.....
;
;
MOVNAME:  LXI	H,FCB2+1
	  LXI	D,FCB4+1
	  LXI	B,11
	  CALL	MOVER
	  RET
;.....
;
;
GETADD:	  DCR	A		;UN-DO THE INR ABOVE
	  ADD	A		;TIMES 32
	  ADD	A
	  ADD	A
	  ADD	A
	  ADD	A
	  ADI	80H		;ADD DMA (CMDBUF) OFFSET
	  MOV	L,A
	  MVI	H,0
	  RET
;.....
;
;
DRIVEL:	  LDA	FCB4		;IF NO DRIVE, USE
	  ORA	A		;DEFAULT DRIVE IN DRNAME.
	  JZ	PRNTHD
	  ADI	40H		;MAKE 1=A, 2=B, ETC., AND..
	  STA	DRNAME		;..OVERWRITE DEFAULT STORED BELOW.
;
PRNTHD:	  CALL	ILPRT
	  DB	'Drive '
;
DRNAME:	  DB	' ',CR,LF,0
	  RET
;.....
;
;
; INITIALIZED STORAGE
;
FREEMSG:  DB 	'k Bytes free on default drive '
DEFDRV:	  DB	' $'
DEFUSR:	  DB	':',CR,LF,'$'
;
;
; UNINITIALIZED STORAGE
;
BMAX:	  DS	2		;HIGHEST BLOCK NUMBER ON DRIVE
BMASK:	  DS	1		;REC/BLK - 1
BSHIFTF:  DS	1		;NUMBER OF SHIFTS TO MULTIPLY BY REC/BLK
;.....
;
;
;=======================================================================
;
; DUPLICATES 'READ BUFFER' ROUTINE SAME AS CP/M FUNCTION 10, BUT DOES
; NOT USE CTL-C (REASON FOR THE ROUTINE).  DOES ALLOW CONTROLS U, R, E
; AND H (BACKSPACE).  OUTPUTS BELL IF THE INPUT IS GREATER THAN THE
; BUFFER.
;
INBUF:	  PUSH	PSW
	  PUSH	H
	  PUSH	B 
	  PUSH	D		;DE REGISTERS MUST BE PUSHED LAST
;
INBUFA:	  CALL	CLEARBUF	;CLEAR THE BUFFER AREA
	  POP	D		;GET ADDRESS OF BUFFER ON RETRIES
	  PUSH	D		;RESTORE STACK
	  XRA	A
	  INX	D		;ADDRESS COUNT FIELD
	  STAX	D		;INITIALIZE WITH A ZERO IN COUNT BYTE
	  INX	D
	  XCHG			;ADDRESS FIRST BUFFER BYTE WITH HL
;
INBUFB:	  CALL	KEYIN		;(WAITS FOR CHAR)
	  CALL	UCASE		;..DITTO.
	  CPI	CR		;IS IT <RETURN> (ENTER COMMAND)?
	  JZ	INBUFR		;IF SO, THEN RETURN.
	  CPI	7FH		;IS IT A DELETE?
	  JZ	DELETE
	  CPI	8		;CTR-H BACKSPACES..
	  JZ	DELETE		;..OVER DELETED CHAR.
	  CPI	'U'-40H		;IS IT A CTL-U?
	  JZ	INBUFO		;OUTPUT #, CR, LF, AND START OVER
	  CPI	'R'-40H		;CTL-R RETYPES LINE
	  JZ	RETYPE
	  CPI	'E'-40H		;CTL-E OUTPUTS A CRLF
	  JZ	PCRLF
	  CPI	' '		;NO CONTROL CHARACTERS OTHER..
	  JC	INBUFB		;..THAN ABOVE ALLOWED.
	  MOV	B,A		;SAVE INPUTTED CHARACTER
	  XCHG			;SAVE HL IN DE
	  POP	H		;GET ADDRESS OF BUFFER IN HL
	  PUSH	H		;RESTORE STACK
	  INX	H		;ADDRESS COUNT BYTE
	  INR	M		;INCREASE COUNT BYTE
	  DCX	H		;ADDRESS MAXIMUM
	  MOV	A,M		;PUT MAXIMUM IN A
	  INX	H		;ADDRESS COUNT
	  CMP	M		;COMPARE COUNT TO MAXIMUM
	  JC	ALERTL		;IF MAXIMUM, RING BELL AND WAIT FOR CR.
	  XCHG			;RESTORE BUFFER POINTER TO HL
	  MOV	M,B		;PUT INPUTTED CHARACTER IN BUFFER
	  MOV	A,B		;OUTPUT IT
	  CALL	TYPE
	  INX	H		;BUMP POINTER
	  JMP	INBUFB		;GET NEXT CHARACTER
;...
;
;
DELETE:	  XCHG			;SAVE BUFFER POINTER IN DE
	  POP	H		;ADDRESS BEGINNING OF BUFFER
	  PUSH	H		;RESTORE STACK
	  INX	H		;ADDRESS COUNT FIELD
	  MOV	B,A		;SAVE DELETE CHAR, 7FH OR 08H.
	  MOV	A,M
	  SUI	1		;DECREASE COUNT
	  MOV	M,A
	  JC	NODEL		;DON'T DELETE PAST BEGINING OF BUFFER
	  XCHG			;RESTORE BUFFER POINTER TO HL
	  DCX	H		;POINT TO LAST BYTE INPUTTED
	  MOV	A,B		;GET BACK 7FH OR 08H
	  MOV	B,M		;GET CHARACTER BEING DELETED
	  MVI	M,' '		;RESTORE BLANK
	  CPI	8
	  JZ	BKSPC
	  CPI	7FH
	  JZ	BKSPC0
	  JMP	INBUFB		;GET NEXT CHARACTER
;.....
;
;
NODEL:	  INR	M		;DON'T LEAVE COUNT NEGATIVE
	  XCHG			;RESTORE POINTER TO HL
	  JMP	INBUFB
;.....
;
;
BKSPC0:	  MVI	A,08H
;
BKSPC:	  CALL	TYPE		;TRUE ERASE IF 08H
	  MVI	A,' '
	  CALL	TYPE
	  MVI	A,8
	  CALL	TYPE
	  JMP	INBUFB
;.....
;
;
INBUFO:	  MVI	A,'#'		;ANNOUNCES THE LINE HAS BEEN REMOVED
	  CALL	TYPE
	  CALL	CRLF
	  JMP	INBUFA
;.....
;
;
RETYPE:	  POP	D
	  PUSH	D
	  INX	D		;POINT TO CURRENT NUMBER..
	  LDAX	D		;..OF CHARACTERS.
	  MOV	B,A
	  MVI	A,'#'
	  CALL	TYPE
	  CALL	CRLF
	  MOV	A,B		;TEST IF ZERO INPUT
	  ORA	A
	  JZ	INBUFB
;...
;
;
CTLRLP:	  INX	D
	  LDAX	D
	  CALL	TYPE
	  DCR	B
	  JNZ	CTLRLP
	  JMP	INBUFB
;.....
;
;	
ALERTL:	  MVI	A,BELL		;ALARM FOR FULL BUFFER
	  CALL	TYPE
	  DCR	M
	  XCHG
	  JMP	INBUFB
;.....
;
;
PCRLF:	  CALL	CRLF
	  JMP	INBUFB
;.....
;
;
INBUFR:	  CALL	CRLF		;1ST NEW LINE AFTER A COMMAND CHARACTER
	  POP	D
	  POP	B
	  POP	H
	  POP	PSW
	  RET
;.....
;
;
CLEARBUF: POP	D		;ACCOUNTS FOR CALL
	  POP	H		;ADDRESS BUFFER IN HL
	  PUSH	H		;RESTORE..
	  PUSH	D		;..STACK
	  MOV	B,M		;SAVE MAXIMUM IN B
	  INX	H		;POINT TO FIRST..
	  INX	H		;..BUFFER BYTE.
	  MVI	A,' '
;
CLEARL:	  MOV	M,A
	  INX	H
	  DCR	B
	  JNZ	CLEARL
	  RET
;.....
;
;
;=======================================================================
;
; IN-LINE COMPARE.  COMPARES STRING ADDRESSED BY DE-REG TO STRING AFTER
; CALL (ENDS WITH ZERO).  RETURN WITH CARRY SET MEANS STRINGS NOT THE
; SAME.  ALL REGISTERS EXCEPT A-REG ARE UNAFFECTED.
;
INLNCOMP: XTHL			;POINT HL TO 1ST CHAR.
	  PUSH	D
;
ILCOMPL:  MOV	A,M		;HL POINTS TO IN-LINE STRING.
	  ORA	A		;END OF STRING IF ZERO.
	  JZ	SAME
	  LDAX	D
	  CMP	M
	  JNZ	NOTSAME
	  INX	H
	  INX	D
	  JMP	ILCOMPL
;...
;
;
NOTSAME:  XRA	A		;IF NOT SAME, FINISH THRU..
;
NSLP:	  INX	H		;..STRING SO RETURN WILL..
	  CMP	M		;..GO TO INSTRUCTION AFTER..
	  JNZ	NSLP		;..STRING AND NOT REMAINDER OF STRING.
	  STC
;
SAME:	  POP	D
	  INX	H		;AVOIDS A NOP INSTRUCTION..
	  XTHL			;..WHEN RETURNING.
	  RET
;.....
;
;
;=======================================================================
;
; MULTI-FILE ACCESS SUBROUTINE.  ALLOWS PROCESSING OF MULTIPLE FILES
; (I.E., *.ASM) FROM DISK.  BUILDS THE CORRECT NAME IN THE FCB EACH TIME
; IT IS CALLED.  THE COMMAND IS USED IN PROGRAMS TO PROCESS SINGLE OR 
; MULTIPLE FILES.  THE FCB IS 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 ARE FOUND.
                
MFNAME:	  PUSH	B
	  PUSH	D
	  PUSH	H
	  MVI	C,SETDMA
	  LXI	D,80H
	  CALL	BDOS
	  POP	H
	  POP	D
	  POP	B
	  XRA	A
	  STA	FCBEXT
	  LDA	MFFLG1
	  ORA	A
	  JNZ	MFNAME1
	  MVI	A,1
	  STA	MFFLG1
	  LXI	H,FCB
	  LXI	D,MFNAME5
	  LXI	B,12
	  CALL	MOVER
	  LDA	FCB
	  STA	MFNAME6		;SAVE DISK IN CURR FCB
 	  LXI	H,MFNAME5
	  LXI	D,FCB
	  LXI	B,12
 	  CALL	MOVER
 	  PUSH	B
	  PUSH	D
	  PUSH	H
	  MVI	C,SRCHF
	  LXI	D,FCB
	  CALL	BDOS
	  POP	H
	  POP	D
	  POP	B
	  JMP	MFNAME2
;...
;
;
MFNAME1:  LXI	H,MFNAME6
	  LXI	D,FCB
	  LXI	B,12
	  CALL	MOVER
	  PUSH	B
	  PUSH	D
	  PUSH	H
	  MVI	C,SRCHF
	  LXI	D,FCB
	  CALL	BDOS
	  POP	H
	  POP	D
	  POP	B
	  LXI	H,MFNAME5
	  LXI	D,FCB
	  LXI	B,12
	  CALL	MOVER
	  PUSH	B
	  PUSH	D
	  PUSH	H
	  MVI	C,SRCHN
	  LXI	D,FCB
	  CALL	BDOS
	  POP	H
	  POP	D
	  POP	B
;
MFNAME2:  INR	A
	  STC
	  JNZ	MFNAME3
	  STA	MFFLG1
	  RET
;.....
;
; 	
MFNAME3:  DCR	A
	  ANI	3
	  ADD	A
	  ADD	A
	  ADD	A
	  ADD	A
	  ADD	A
	  ADI	81H
	  MOV	L,A
	  MVI	H,0
	  PUSH	H		;SAVE NAME POINTER
	  LXI	D,MFNAME6+1
	  LXI	B,11
	  CALL	MOVER
	  POP	H
	  LXI	D,FCB+1
	  LXI	B,11
	  CALL	MOVER
	  XRA	A
	  STA	FCBEXT
	  STA	FCBRNO
	  RET
;.....
;
;
MOVER:	  MVI	A,2
	  INR	A
	  JPE	MFNAME4
	  DB	0EDH,0B0H	;Z-80 'LDIR' INSTUCTION
	  RET
;.....
;
;	
MFNAME4:  MOV	A,M		;USED IF AN 8080 CPU IS ACTIVE
	  STAX	D
	  INX	H
	  INX	D
	  DCX	B
	  MOV	A,B
	  ORA	C
	  JNZ	MFNAME4
	  RET
;.....
;
;
;=======================================================================
;
; SHOWS BAUD RATES SET FOR 'TIME TO SEND' FILE TRANSFER.
;
PRTBAUD:  LXI	H,BAUDSPD
	  MVI	D,0
	  LDA	MSPEED		;GET BAUD RATE CODE
	  MOV	E,A		;X1
	  ADD	A		;X2
	  ADD	A		;X4
	  ADD	E		;X5
	  MOV	E,A
	  DAD	D		;POINT TO CORRECT RATE
	  XCHG
	  MVI	C,PRINT
	  CALL	BDOS
	  CALL	ILPRT
	  DB	' baud',CR,LF,0
	  RET
;.....
;
;
BAUDSPD	  DB	'110$',0,'300$',0,'450$',0,'600$',0,'710$',0
	  DB	'1200$','2400$','4800$','9600$'
;.....
;
;
;=======================================================================
;
; SHOWS THE TIME TO TRANSFER A FILE AT VARIOUS BAUD RATES.  (110-9600)
;
SENDTIME: CALL	ILPRT	        ;PRINT FOLLOWING MESSAGE:
	  DB	'File open: ',0
	  LHLD	RCNT		;GET RECORD COUNT.
	  CALL	DECOUT		;PRINT DECIMAL NUMBER OF RECORDS
	  CALL	ILPRT
	  DB	' (',0
	  CALL	DHXOUT		;NOW PRINT SIZE IN HEX.
	  CALL	ILPRT
	  DB	'H) records',CR,LF
	  DB	'Send time: ',0
	  LDA	MSPEED		;GET THE SPEED INDICATOR
	  MVI	D,0
	  MOV	E,A		;SET UP FOR TABLE ACCESS
	  LXI	H,BTABLE	;POINT TO BAUD FACTOR TABLE
	  DAD	D		;INDEX TO PROPER FACTOR
	  DAD	D		;FACTOR IN DE
	  MOV	E,M
	  INX	H
	  MOV	D,M
	  LHLD	RCNT		;GET # OF RECORDS
	  CALL	DVHLDE		;DIVIDE 'HL' BY VALUE IN DE (RECORDS/MIN)
	  PUSH	H
	  MOV	L,C
	  MOV	H,B
	  CALL	DECOUT		;PRINT THE MINUTES PORTION
	  CALL	ILPRT
	  DB	' mins, ',0
	  LXI	H,RECDBL	;POINT TO DIVISORS FOR SECONDS
	  LXI	D,0		;   CALCULATION
	  LDA	MSPEED		;GET INDEX FOR BAUD RATE
	  MOV	E,A
	  DAD	D		;INDEX INTO TABLE
	  MOV	A,M		;GET MULTIPLIER
	  POP	H		;GET REMAINDER
	  CALL	MULHLA		;MULTIPLY THE 'HL' X 'A'
	  CALL	SHFTHL
	  CALL	SHFTHL
	  CALL	SHFTHL
	  CALL	SHFTHL	
	  MVI	H,0
	  CALL	DECOUT		;PRINT THE SECONDS PORTION
	  CALL	ILPRT
	  DB	' secs at ',0
	  CALL	PRTBAUD
	  CALL	ILPRT
          DB	'To cancel: use CTL-X',CR,LF,0
	  RET
;.....
;
;
BTABLE:	DW	5,13,19,25,29,48,96,192,384,0	;RECORDS/MIN FOR..
RECDBL:	DB	192,74,51,38,33,20,11,5,3,0	;..110-9600 BAUD
;
;	
;---->  DVHLDE: DIVIDES 'HL' BY VALUE IN 'DE',
;	UPON EXIT: 'BC'=QUOTIENT,'L'=REMAINDER
;
DVHLDE:	  PUSH	D		; SAVE DIVISOR
	  MOV	A,E
	  CMA			; NEGATE DIVISOR
	  MOV	E,A
	  MOV	A,D
	  CMA
	  MOV	D,A
	  INX	D		; DE IS NOW TWOS COMPLEMENTED
	  LXI	B,0		; INIT QUOTIENT
;
DIVL1:	  DAD	D		; SUBTRACT DIVISOR FROM DIVIDEND
	  INX	B		; BUMP QUOTIENT
	  JC	DIVL1		; LOOP TILL SIGN CHANGES
	  DCX	B		; ADJUST QUOTIENT
	  POP	D		; RETRIEVE DIVISOR
	  DAD	D		; ADJUST REMAINDER
	  RET
;.....
;
;
;---->  MULHLA:  MULTIPLY THE VALUE IN 'HL' BY THE VALUE IN 'A'
;		 RETURN WITH ANSWER IN 'HL'
;
MULHLA:	  XCHG			; MULTIPLICAND TO DE
	  LXI	H,0		; INIT PRODUCT
	  INR	A		; ADJUST MULTIPLIER FOR ZERO TEST
;
MULLP:	  DCR	A
	  RZ
;
	  DAD	D
	  JMP	MULLP
;.....
;
;
;  SHIFT 'HL' REGISTER PAIR ONE BIT TO THE RIGHT
;
SHFTHL:	  MOV	A,L
	  RAR
	  MOV	L,A
	  ORA	A		;CLEAR THE CARRY
	  MOV	A,H
	  RAR
	  MOV	H,A
	  RNC
	  MVI	A,80H
	  ORA	L
	  MOV	L,A
	  RET
;.....
;
;
;=======================================================================
;
;		PMMI BAUD RATE INITIALZATION
;
;=======================================================================
;
GETBAUD:  LDA	FCB+9		;GET 1ST DIGIT OF REQUESTED BAUDRATE
	  CPI	' '		;IF A SPACE RETURN WITH 300 BAUD
	  MVI	A,52
	  RZ
	  LDA	FCB+9
	  ORA	A		;IF A NULL RETURN WITH 300 BAUD
	  MVI	A,52
	  RZ
	  LXI	D,FCB+9
	  LXI	H,0
;
DECLP:	  LDAX	D
	  INX	D
	  CPI	' '
	  JZ	DECLP
	  CPI	'0'		;NUMERALS ARE 0-9
	  JC	BADRATE
	  CPI	'9'+1
	  JNC	BADRATE
	  SUI	'0'
	  MOV	B,H
	  MOV	C,L
	  DAD	H
	  DAD	H
	  DAD	B
	  DAD	H
	  ADD	L
	  MOV	L,A
	  JNZ	DIGNC
	  INR	H
;
DIGNC:	  MOV	A,E
	  CPI	FCB+12
	  JNZ	DECLP
	  MOV	A,H
	  CMA
	  MOV	D,A
 	  MOV	A,L
	  CMA
	  MOV	E,A
	  INX	D
	  LXI	H,15625		;250000/16
	  LXI	B,-1
;
DIVLP:	  INX	B
	  DAD	D
	  JC 	DIVLP
	  MOV	A,B
	  ORA	A
	  MOV	A,C
	  RZ
;
BADRATE:  CALL	ERXIT
	  DB	'++ INVALID BAUDRATE ++$'
;...
;
;
CHGMSPD:  MVI	C,0		;CHANGES PMMI MSPEED FOR 110-1200 BAUD
	  CPI	100		;<300 BAUD
	  RNC
	  INR	C		;C=1 FOR 300 BAUD
	  CPI	40		;<450 BAUD
	  RNC
	  INR	C		;C=2 FOR 450 BAUD
	  CPI	30		;<600 BAUD
	  RNC
	  INR	C		;C=3 FOR 600 BAUD
	  CPI	24		;<710 BAUD
	  RNC
	  INR	C		;C=4 FOR 710 BAUD
	  RET
;.....
;
;
; The non-PMMI setup routines can go here.  The following is a starting
; point.  Several hundreds of bytes are available.
;
SETUPR:	  RET
;.....
;
;
;=======================================================================
;
;	PMMI DIALING ROUTINES
;
;=======================================================================
;
; Dialing routines taken (and greatly modified) from PMMI manual.
;
; Modem control command words
;
CLEAR:	  EQU	3FH		;IDLE MODE
MAKEM:	  EQU	1		;TELE LINE MAKE (OFF HOOK)
BRKM:	  EQU	0		;TELE LINE ON HOOK (BREAK DURING DIALING)
DTMSK:	  EQU	1		;DIAL TONE MASK
RBLMT:	  EQU	35		;7 SECONDS TO WAIT TIL NO-RING-HEARD MSG
RBWAIT:	  EQU	50		;5 SECOND DELAY BEFORE REDIALING NUMBER
TMPUL:	  EQU	80H		;TIMER PULSES MASK BIT
TRATE:	  EQU	250		;VALUE FOR 0.1 SECOND
;.....
;
; Dialing routine
;
DIAL:	  LDA	PMMIBYTE	;USING A PMMI MODEM?
	  ORA	A
	  RZ			;IF NOT, SKIP AUTO-DIALING ROUTINE
;
	  XRA	A
	  STA	CRFLAG		;ZERO THE CONTINUOUS DIAL FLAG
	  STA	RINGBKFL	;ZERO THE RINGBACK FLAG
	  LXI	H,0
	  SHLD	DIALCT		;ZERO THE DIAL COUNT
	  LXI	H,CMDBUF+1	;POINT TO THE NUMBER OF CHARACTERS IN..
	  MOV	A,M		;..THE BUFFER, THEN GET THE NUMBER
	  CPI	3+1		;ANYTHING TYPED AFTER "CAL"?
	  JC	DIAL1		;IF NOT, GO THROUGH LIBRARY ROUTINE
;
;
; If there were only 3 characters, then "CAL<RET>" was typed -- the user
; obviously expecting to get a phone number (or letter) from the library
; file.  If 4 or more, a number (or letter) was typed in from the menu
; command line, so move the characters down 4 to compensate.  Needed for
; auto-redialing of menu command line entries.
;
	  MOV	C,A		;PUT INTO THE 'C' REG.
	  MVI	B,0		;WILL MOVE ORIGINAL NUMBER DOWN 4
	  SUI	4		;ELIMINATE THE "CAL " PORTION
	  MOV	M,A		;STORE NEW COUNT AT CMDBUF+1
	  INX	H		;CMDBUF+2 (FIRST CHAR. OF STRING)
	  XCHG			;'DE' NOW HAS CMDBUF+2
	  LXI	H,CMDBUF+6	;POINT TO NUMBER (OR LETTER) TO DIAL
	  CALL	MOVER		;MOVE THE GROUP DOWN 4 PLACES
	  JMP	DIAL4		;CHECK IF LIBRARY NUMBER, THEN DIAL
;...
;
;
; Comes here if no phone number was manually entered after "CAL" and if
; no phone library letter was entered.  Displays the phone number library
; then asks for an entry.
;
DIAL1:	  MVI	C,13		;NUMBER OF LINES TO MOVE
	  LXI	H,NUMBLIB	;START OF PHONE NUMBER LIBRARY
	  LXI	D,DBUF		;BUFFER ADDRESS TO STORE THEM TEMPORARILY
	  CALL	NEWLINE		;START WITH CRLF
	  STAX	D		;+LF
	  INX	D		;AND BUMP IT
;
DIAL2:	  MVI	B,LIBLEN	;NUMBER OF BYTES TO MOVE
	  CALL	MOVE		;MOVE TO BUFFER
	  CALL	SPACES		;2 ENTRIES + 3 SPACES = 71 CHARACTERS
	  MVI	B,LIBLEN
	  CALL	MOVE
	  CALL	NEWLINE
	  DCR	C		;ONE LESS LINE TO PRINT
	  JNZ	DIAL2		;IF NOT ZERO, PRINT ANOTHER
;
DIAL3:	  MVI	A,'$'		;BDOS PRINT ROUTINE TERMINATE CHARACTER
	  STAX	D		;STORE IN BUFFER
	  CALL	CLRTST
	  MVI	C,PRINT
	  LXI	D,DBUF		;PRINT THE LIBRARY ON THE CRT
	  CALL	BDOS
	  CALL	ILPRT		;ASK WHICH ONE IS WANTED
	  DB	CR,LF,'Enter number or library letter - <CR> '
	  DB	'when finished,',CR,LF
	  DB	'CTL-X cancels while dialing: ',0
	  LXI	D,CMDBUF
	  CALL	INBUF
;
; You now have either a library letter or a manually entered phone num-
; ber.  These either came from the menu command line or from the library
; command line.  Next we see if a letter, if so, get the corresponding
; line with phone number from the library.  If a number we ignore the
; library look-up.  (Ringback numbers must end with letter 'R'.)
;
DIAL4:	  LXI	H,CMDBUF+1	;NUBER OF CHARACTERS IN BUFFER
	  MOV	A,M
	  ORA	A		;NULL MEAND <CR> WAS TYPED
	  JZ	DIALEXIT	;ABORT DIALING, RETURN TO MENU
	  INX	H		;FIRST TYPED CHAR OF NUMBER TO DIAL
	  CALL	DIALBGN		;DISCONNECT, RECONNECT, WAIT FOR TONE
	  JC	DIALEXIT	;IF NO DIALTONE, PONDER NEXT MOVE
	  MVI	B,'A'		;FIRST LETTER OF ALPHABET
	  MVI	E,0		;COUNTS NUMBER OF LETTERS TO MATCH
	  MVI	C,26		;NUMBER OF LETTERS IN ALPHABET
	  MOV	A,M		;GET CHAR BUFFER
;
DIAL5:	  CMP	B		;NUMBER FROM TABLE?
	  JZ	DIAL6
	  INR	B		;MAKE NEXT LETTER (A-Z)
	  INR	E		;COUNT UP
	  DCR	C		;COUNT DOWN
	  JZ	DIAL9		;WAS NOT A-Z SO EXIT
	  JMP	DIAL5		;LOOP
;
;
; Now have a match between the requested letter and one in the library
; 'E' holds the decimal equivalent (1-26) of the letter (A-Z).
;
DIAL6:	  LXI	H,NUMBLIB	;PHONE NUMBER LIBRARY
	  LXI	B,LIBLEN	;LENGTH OF LIBRARY ENTRY
	  MOV	A,E		;NUMBER OF TIMES TO LIBRARY LENGTH TO HL
	  ORA	A		;SET FLAGS
	  JZ	DIAL8
;
DIAL7:	  MOV	A,M		;GET FIRST CHAR OF SELECTED LIB ENTRY
	  ORA	A		;SET FLAGS
	  JZ	DIALBAD		;SEND BAD LIBRARY MSG AND ABORT
	  DAD	B		;INCREMENT 'HL' BY LIBRARY LENGTH
	  DCR	E		;COUNTDOWN
	  JNZ	DIAL7		;NOT THERE YET, LOOP
;
;
; Now have the line in the phone number library matching the requested
; letter so store that line starting at 'CMDBUF+1'
;
DIAL8:	  MVI	B,LIBLEN	;NUMBER OF CHARACTERS TO GET FROM TABLE
	  LXI	D,CMDBUF+1	;POINT TO BUFFER
	  XCHG			;'HL' POINTS TO CMDBUF+1
	  MOV	M,B		;LENGTH OF EACH TABLE ENTRY
	  XCHG			;RESTORE THE REGISTERS
	  INX	D		;POINT TO FIRST CHAR POSITION IN BUFFER
	  CALL	MOVE		;MOVE THE TABLE ENTRY TO THE BUFFER
;
;
; Now have the full line including phone number in 'CMDBUF' area.
;
DIAL9:	  LXI	H,CMDBUF+1
	  MOV	E,M		;NUMBER OF CHARS IN BUFF
	  INX	H		;POINT TO 1ST CHAR. TO DIAL
;
DIAL10:	  MOV	A,M		;GET FIRST NUMBER FROM THE BUFFER
	  ORA	A		;SET FLAGS
	  JZ	DIALBAD		;BUM NUMBER IF A NULL
;
;
; Dial a digit, check keyboard for abort
;
	  CALL	DIALA		;SHOW THE STRING, DIAL THE NUMBER
;
	  CALL	STAT		;KEYPRESS?
	  ORA	A		;SET FLAGS
	  CNZ	KEYIN		;YES, GO GET IT
	  CPI	CAN		;CTL-X?
	  JZ	DIALEXIT	;YES, ABORT
	  INX	H		;BUMP POINTER
	  PUSH	D		;SAVE DE
	  PUSH	H		;SAVE HL
	  MVI	B,1		;WAIT 0.1 SECOND (ONE TIMER INTERVAL)
	  CALL	TIMER
	  POP	H		;RESTORE HL
	  POP	D		;RESTORE DE	
	  DCR	E		;ONE LESS CHARACTER TO GO
	  JNZ	DIAL10		;IF NOT DONE, LOOP
;
;
; Show the number of dial attempts
;
	  CALL	ILPRT
	  DB	'  try #',0
	  LHLD	DIALCT		;INCREMENT THE DIAL COUNT
	  INX	H
	  SHLD	DIALCT
	  CALL	DECOUT		;SHOW NUMBER OF ATTEMPTS SO FAR
;
;
; Dialing is all done
;
	  CALL	CRLF
	  MVI	A,07FH		;TURN ON 'DTR'
	  CALL	OUT$MODCTL2	;TIMER RATE?
	  MVI	B,1		;0.1 SECOND PER INTERVAL
	  CALL	TIMER		;WAIT FOR MODEM TO TURN ON 'DTR'
;MOD(BGL)***
	  LDA	PARTY		;DEFAULT PARITY SET, NORMALLY
				;..1 STOP BIT, NO PARITY, 8 DATA
				;..BITS, NO DISCON. AFTER 17 SEC
	  CALL	OUT$MODCTLP
	  MVI	D,4		;CLEAR TO SEND MASK
	  MVI	C,WAITCTS	;WAIT TIME FOR CTS..
	  CALL	WAIT		;..(30 SECONDS, CAN SET 'WAITCTS' FOR
;                               ;..UP TO 51 SECONDS FOR EUROPEAN USE)
;
; If connection made, go get options for starting communications
;
	  JNC	CONMADE		;CONNECTION MADE
;
;
; Connection not made, see if a redial is desired
;
	  CALL	DISCONNT	;HANG-UP SO WE CAN REDIAL IF DESIRED
;
DIALAGN:  LDA	CRFLAG		;CONTINUOUS REDIAL FLAG
	  ORA	A
	  JNZ	DIALAGN1	;IF ALREADY SET, GO DIAL AGAIN
	  CALL	ILPRT		;IF NOT, SEE IF SHOULD REDIAL AGAIN
	  DB	CR,LF,'No answer after time-out.  Redial? '
	  DB	'(Y/N/C): ',BELL,0
	  CALL	KBDCHR
	  CALL	CRLF		;NEW LINE
	  CPI	'N'		;REDIAL?
	  JZ	MENU		;NO, GO MENU
	  CPI	'Y'		;REDIAL?
	  JZ	DIALAGN1	;YES, REDIAL
	  CPI	'C'		;CONTINUOUS REDIAL?
	  JNZ	DIALAGN		;INVALID RESPONSE, ASK AGAIN
	  MVI	A,TRUE		;SET TRUE
	  STA	CRFLAG		;CONTINUOUS REDIAL FLAG
;
DIALAGN1: MVI	B,RBWAIT	;5 SECONDS WAIT FOR PMMI RESET (OR BUSY)
	  CALL	TIMER		;OR BUSY TONE MAY BE SENSED AS DIALTONE
	  LDA	RINGBKFL	;RINGBACK FLAG SET?
	  ORA	A
	  JZ	DIAL4		;IF NOT, GO REDIAL A NORMAL NUMBER
	  STA	CMDBUF+1	;RESTORE ORIGINAL VALUE INCLUDING THE 'R'
	  JMP	DIAL4		;REDIAL ENTRY POINT
;.....
;
;
; Connection has been made
;
CONMADE:  CALL	ILPRT
	  DB	CR,LF,'Connection established - Select options: '
	  DB	BELL,0
;
CONMAD1:  CALL	STAT		;KEYPRESS?
	  ORA	A		;SET FLAGS
	  JNZ	GETCMD		;KEY PRESSED, GO GET OPTIONS
	  MVI	A,BELL
	  CALL	TYPE		;RING BELL
	  LXI	B,2000H
;
CONMAD2:  DCR	C
	  JNZ	CONMAD2		;KILL SOME TIME FOR TERMINAL..
	  DCR	B		;..PROCESS THE BELL
	  JNZ	CONMAD2
	  JMP	CONMAD1		;LOOP UNTIL CONNECTED
;.....
;
;
; Automatic dialing routine, prints the number being dialed
;
DIALA:	  CALL	TYPE		;PRINT WHATEVER CHARACTER, DASHES, ETC.
	  CPI	'R'		;COULD IT BE A RINGBACK CHARACTER?
	  JNZ	DIALA1		;IF NOT, PROBABLY A NUMBER SO EXIT
	  PUSH	PSW		;SAVE ACCUMULATOR & FLAGS
	  MOV	A,E		;GET THE CHARACTER COUNT.  IS THIS "R"..
	  CPI	1		;..THE LAST CHARACTER IN THE STRING?
	  JZ	RINGBK		;YES, MUST BE RINGBACK CHAR, DO RINGBACK
	  POP	PSW		;EVERYTHING BACK AS IT WAS
;
DIALA1:   CPI	'0'		;DIGITS ARE 0-9
	  RC			;EXIT LESS THAN ASCII '0'
	  CPI	'9'+1
	  RNC			;EXIT IF MORE THAN ASCII '9'
	  SUI	'0'		;STRIP ASCII -- COULD ALSO DO 'ANI 0FH'
	  JNZ	DIALA2
	  MVI	A,10		;CONVERT ZERO TO 10 PULSES
;
DIALA2:	  MOV	C,A
	  LDA	PULSERATE	;CONTAINS VALUE FOR DIAL SPEED
	  CALL	OUT$BAUDRP
;
DIALA3:	  CALL	IN$BAUDRP
	  ANI	TMPUL
	  JNZ	DIALA3
;
DIALA4:	  CALL	IN$BAUDRP
	  ANI	TMPUL
	  JZ	DIALA4
;
DIALA5:	  MVI	A,MAKEM
	  CALL	OUT$MODCTLP
;
DIALA6:	  CALL	IN$BAUDRP
	  ANI	TMPUL
	  JNZ	DIALA6
	  MVI	A,BRKM
	  CALL	OUT$MODCTLP
;
DIALA7:	  CALL	IN$BAUDRP
	  ANI	TMPUL
	  JZ	DIALA7
	  DCR	C
	  JNZ	DIALA5
	  MVI	A,MAKEM
	  CALL	OUT$MODCTLP
;MOD(BGL)***
	  MVI	B,8		;0.1 SECOND PER TIMER INTERVAL
	  JMP	TIMER		;RETURN TO CALLER
;.....
;
;
; Print bad library number message and abort if a null is encountered.
;
DIALBAD:  CALL	ILPRT
	  DB	CR,LF,'++ Bad library number called ++',CR,LF,0
;
DIALEXIT: CALL	DISCONNT	;ABORT ROUTINE
	  CALL	CRLF
	  JMP	MENU
;.....
;
;
; Disconnect from the line, reconnect and wait for the dialtone.
;
DIALBGN:  CALL	DISCONNT
	  CALL	ILPRT
	  DB	CR,LF,'Waiting for dial tone',CR,LF,0
	  MVI	A,MAKEM		;MAKE MAKE (OFF-HOOK)
	  CALL	OUT$MODCTLP	;DO IT
	  MVI	D,DTMSK		;DIAL TONE MASK
	  MVI	C,50		;WAITS UP TO 10 SEC. FOR DIAL TONE
	  CALL	WAIT		;WAIT FOR DIAL TONE
;
;
; Wait subroutine will return with carry set if unable to get dialtone.
; If carry is not set, the dialtone was received.
;
	  RNC			;IF DIAL TONE WITHIN 10 SECONDS
	  CALL	ILPRT		;ELSE, MESSAGE AND RETURN WITH CARRY SET
	  DB	CR,LF,'++ NO DIAL TONE ++',CR,LF,0
	  CALL	DISCONNT
	  STC			;SET THE CARRY BIT (NO DIALTONE)
	  RET
;.....
;
;
DISCONNT: XRA	A		;0
	  CALL	OUT$MODCTL2 	;CLEAR DAV, ESD, ETC
	  CALL	OUT$MODCTLP 	;HANG-UP
	  PUSH	B
	  MVI	B,8		;WAIT FOR PMMI TO DISCONNECT (0.8 SEC)
	  CALL	TIMER		;0.1 SECOND PER TIMER INTERVAL
	  POP	B
	  RET
;.....
;
;
HANGUP:   MVI	A,CLEAR
	  CALL	OUT$MODCTL2
	  MVI	A,0
	  CALL	OUT$MODCTLP
	  RET
;.....
;
;
; Handles the special ringback numbers.  Dials, lets it ring only once,
; hangs up and then redials.
;
RINGBK:	  POP	PSW		;TO GET IT OFF THE STACK
	  LDA	CMDBUF+1	;GET THE NUMBER OF CHARS. IN THE BUFFER
	  STA	RINGBKFL	;STORE ORIGINAL NUMBER INCLUDING THE 'R'
	  SUI	1		;SUBTRACT 1 TO AVOID THE RINGBACK CHAR
	  STA	CMDBUF+1	;STORE THE NEW VALUE
	  MVI	D,DTMSK		;LOAD TONE DETECT MASK
	  MVI	C,RBLMT		;WAITS UP TO 7 SECONDS FOR A RING
	  CALL	WAIT
	  JC	RBTIME		;JUMP IF NO RING DETECTED
	  MVI	B,25		;GOT A RING, WAIT 2.5 SEC
	  CALL	TIMER
	  CALL	IN$BAUDRP	;IS TONE STILL PRESENT?
	  ANA	D
	  JZ	DIALAGN		;YES, MUST BE BUSY
;.....
;
;
; Hang up, redial and listen for dial tone
;
RNGBK1:	  CALL	HANGUP		;HANG UP THE PHONE
	  MVI	B,RBWAIT	;WAIT 5 SECONDS BEFORE REDIALING..
	  CALL	TIMER		;..FOR LINE TO CLEAR, ETC.
	  CALL	DIALBGN		;DISCONNECT, RECONNECT, WAIT FOR TONE
	  JNC	DIAL9		;GO REDIAL NUMBER
	  JMP	DIALAGN		;NO DIAL TONE HEARD
;.....
;
;
RBTIME:	  CALL	CRLF
	  JMP	RNGBK1		;HANGUP, REDIAL, & LISTEN FOR CARRIER
;.....
;
;
; PMMI timer routine.  Waits 0.1 seconds for each unit in 'B' reg.
;
TIMER:	  MVI	A,TRATE    	;TRATE 250, VALUE FOR .1 SEC INTERVAL
	  CALL	OUT$BAUDRP 	;'B' CONTAINS NUMBER OF .1 SEC INTERVALS
;
TIMER1:   CALL	IN$BAUDRP  	;TO COUNT
	  ANI	TMPUL
	  JZ	TIMER1      	;WAIT FOR TIMER TO GO HIGH
;
TIMER2:	  CALL	IN$BAUDRP
	  ANI	TMPUL
	  JNZ	TIMER2      	;WAIT FOR TIMER TO GO LOW
	  DCR	B
	  JNZ	TIMER1
	  RET
;.....
;
;
; Time-out routine.  Must be called with mask in 'D' reg. for input at
; relative port 2 and number of seconds (times 10) in 'C' reg.
;
WAIT:	  MVI	B,2	
	  CALL	TIMER		;WAIT FOR TIMER TO GO HIGH THEN LOW
	  CALL	IN$BAUDRP	;PMMIADDR+2 (MODEM STATUS PORT)
	  ANA	D		;(CTS or DIALTONE MASK)
	  RZ			;ACTIVE LOW, SO RETURN ON 0
	  PUSH	B		;SAVE..
	  PUSH	D		;..ACTIVE REG'S
	  CALL	STAT		;KEYPRESS?
	  ORA	A		;SET FLAGS
	  CNZ	KEYIN		;YES, GET CHAR
	  CPI	CAN		;CTL-X TO INTENTIONALLY ABORT?
	  JZ	WAIT1		;YES, DISCONNECT, JMP TO MENU
	  POP	D		;RESTORE..
	  POP	B		;..REGS
	  DCR	C		;COUNT-DOWN
	  JNZ	WAIT
	  STC			;SET CARRY TO INDICATE MASK NOT SET
	  RET
;.....
;
;
WAIT1:	  POP	D		;RESET..
	  POP	B		;..STACK
	  JMP	DISCON1		;DISCONNECT
;.....
;
;
;		(END OF PMMI DIALING ROUTINE)
;
;=======================================================================
;***********************************************************************
;*								       *
;*   CRCSUBS (Cyclic Redundancy Code Subroutines) version 1.20 8080    *
;*   Mnemonics							       *
;*								       *
;*     These subroutines will compute and check a true 16-bit Cyclic   *
;*   Redundancy Code for a message of arbitrary length.		       *
;*								       *
;*     The use of this scheme will guarantee detection of all single   *
;*   and double bit errors, all errors with an odd number of error     *
;*   bits, all burst errors of length 16 or less, 99.997% of all 17-   *
;*   bit error bursts and 99.998% of all possible longer error bursts. *
;*   (Ref: Computer Networks, Andrew S. Tanenbaum, Prentiss-Hall 1981) *
;*								       *
;*	This program may be freely reproduced for non-profit use.      *
;*	Copyrighted 1981, Carpenter Associates, Bloomfield Hills, MI   *
;*								       *
;***********************************************************************
;
;
;	ENTRY	CLRCRC,UPDCRC,FINCRC,CHKCRC
;
CLRCRC:	  PUSH	H		;RESET CRC ACCUMULATOR FOR A NEW MESSAGE
	  LXI	H,0
	  SHLD	CRCVAL
	  POP	H
	  RET
;.....
;
;
UPDCRC:	  PUSH	PSW		;UPDATE CRC ACCUMULATOR USING BYTE IN 'A'
	  PUSH	B
	  PUSH	H
	  MVI	B,8
	  MOV	C,A
	  LHLD	CRCVAL
;
UPDLOOP:  MOV	A,C
	  RLC
	  MOV	C,A
	  MOV	A,L
	  RAL
	  MOV	L,A
	  MOV	A,H
	  RAL
	  MOV	H,A
	  JNC	SKIPIT
	  MOV	A,H		;THE GENERATOR IS X^16 + X^12 + X^5 + 1
	  XRI	10H		;  AS RECOMMENDED BY CCITT.
	  MOV	H,A		;  AN ALTERNATE GENERATOR WHICH IS OFTEN
	  MOV	A,L		;  USED IN SYNCHRONQOUS TRANSMISSION
	  XRI	21H		;  PROTOCOLS IS X^16 + X^15 + X^2 + 1.
	  MOV	L,A		;  THIS MAY BE USED BY SUBSTITUTING
;
SKIPIT:	  DCR	B		;  XOR 80H FOR XOR 10H, AND XOR 05H FOR
	  JNZ	UPDLOOP		;  21H IN THE ADJACENT CODE.
	  SHLD	CRCVAL
	  POP	H
	  POP	B
	  POP	PSW
	  RET
;.....
;
;
FINCRC:	  PUSH	PSW		;FINISH CRC CALCULATIONS FOR OUTPUT MSG
	  XRA	A
	  CALL	UPDCRC
	  CALL	UPDCRC
	  PUSH	H
	  LHLD	CRCVAL
	  MOV	D,H
	  MOV	E,L
	  POP	H
	  POP	PSW
	  RET
;.....
;
;
CHKCRC:	  PUSH	H		;CHECK CRC BYTES OF RECEIVED MESSAGE
	  LHLD	CRCVAL
	  MOV	A,H
	  ORA	L
	  POP	H
	  RZ
	  MVI	A,0FFH
	  RET
;.....
;
;
;***********************************************************************
;
;                             MENU
;
;***********************************************************************
;
;
MENU0:	  LDA	NFILFLG
	  ORA	A
	  JNZ	MENU		;GO IF NO FILE ACTIVE
	  CALL	ILPRT		;ELSE PRINT MESSAGE
	  DB	CR,LF
	  DB	'** There may be text in the memory buffer.  It will **'
	  DB	CR,LF
	  DB	'** be lost unless the NOL or WRT commands are used. **'
	  DB	CR,LF,BELL,0
	  JMP	MENU1
;
MENU:	  XRA	A
	  STA	ABORTFLG	;NULL THE FLAG
	  LDA	EXITFLG
	  ORA	A
	  JNZ	EXIT		;IF SET, EXIT
;
MENU1:	  LXI	H,RESTSN	;RESTORE RECORD NUMBERS..
	  LXI	D,RECDNOB 	;..FOR NEW FILE TRANSFER.
	  MVI	B,RECDNOE-RECDNOB
	  CALL	MOVE
	  LXI	H,RESTROPT	;RESTORE OPTION TABLE
	  LXI	D,OPTBL
	  MVI	B,OPTBE-OPTBL
	  CALL	MOVE
	  XRA	A
	  STA	MFFLG1		;RESET MFACCESS ROUTINE..
	  CMA			;..AND MULTI TRANS IN CASE..
	  STA	FSTFLG		;..OF ABORT.
	  JMP	XPRT
;.....
;
;
; *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *
;
;			 THE COMMAND MENU
;
; *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *
;
MENU2:	  CALL	CLRTST
	  CALL	ILPRT
	  DB	'                  Single Letter Commands',CR,LF,LF
	  DB	' ?  - Display current settings',CR,LF
	  DB	' H  - Display this information',CR,LF
	  DB	' E  - Terminal mode with echo',CR,LF
	  DB	' L  - Terminal mode with local echo',CR,LF
	  DB	' T  - Terminal mode',CR,LF
	  DB	'         For copying text to disk use T (or E or L) '
	  DB	'FILENAME.TYP',CR,LF
	  DB	'         Start or Stop toggles described on subsequent '
	  DB	'screen.',CR,LF,LF
	  DB	' R  - Receive CP/M file using Christensen Protocol'
	  DB	CR,LF
	  DB	' S  - Send CP/M file using Christensen Protocol',CR,LF 
	  DB	'         Command: R (or S) FILENAME.TYP',CR,LF,LF
	  DB	'         R and S can use the following subcommands:'
	  DB	CR,LF
	  DB	'            B  - Bulk transfer using wildcards '
	  DB	'(e.g., *.*)',CR,LF
	  DB	'            Q  - Quiet mode (no messages to console)'
	  DB	CR,LF
	  DB	'            T  - Return to terminal mode after '
	  DB	'transfer',CR,LF
	  DB	'            V  - View bytes transferred on console'
	  DB	CR,LF,LF
	  DB	'      The single letter commands may also be used on '
	  DB	'the',CR,LF
	  DB	'      command line when the program is initially '
	  DB	'executed.',CR,LF,LF,0
;
	  CALL	NXTSCRN
;
	  LDA	PMMIBYTE
	  ORA	A
	  JZ	THREELTR	;IF NOT PMMI, SKIP THIS SPECIAL PAGE
	  CALL	ILPRT
	  DB	'            Additional Subcommands for PMMI Modem'
	  DB	CR,LF,LF
	  DB	'  Modem control:',CR,LF
	  DB	'    A - Answer tone for send or receive',CR,LF
	  DB	'    O - Originate tone for send or receive',CR,LF
	  DB	'    D - Disconnect from the phone line',CR,LF
	  DB	'    X - Disconnect, then reboot to CP/M',CR,LF,LF
	  DB	'  Parity option:',CR,LF
	  DB	'    1 - Set and check for odd parity',CR,LF
	  DB	'    0 - Set and check for even parity',CR,LF
	  DB	'           Both ends must be capable of these options'
	  DB	CR,LF
	  DB	'           which are available only in R and S modes.'
	  DB	CR,LF
	  DB	'           The parity checking will be part of the'
	  DB	CR,LF
	  DB	'           file transfer protocol.',CR,LF,LF
	  DB	'  Speed Options:',CR,LF
	  DB	'        After entering your primary and secondary '
	  DB	'options,',CR,LF
	  DB	'        you can set the modem speed by placing a '
	  DB	' "." after',CR,LF
	  DB	'        the options followed by the speed e.g., '
	  DB	'300, 1200.',CR,LF,LF
	  DB	'        EXAMPLE:  SBOT.600 will set the modem for '
 	  DB	'600 baud',CR,LF,LF,0
;
	  CALL	NXTSCRN
;
THREELTR: CALL	ILPRT
	  DB	'                Three Letter Commands',CR,LF
	  DB	'CPM - Exit from this program to CP/M',CR,LF
	  DB	'DIR - List directory and space free (may specify '
	  DB	'drive)',CR,LF
	  DB	'ERA - Erase file (may specify drive)',CR,LF
	  DB	'LOG - Change default drive/user no. (specify '
	  DB	'drive/user)',CR,LF
	  DB	'      and reset disks.  e.g. LOG A0: or LOG B:  '
	  DB	'(user # unchanged)',CR,LF
	  DB	'SPD - Set speed of file output in terminal mode'
	  DB	CR,LF,0
;
	  CALL	SORPTST
	  JNZ	NOTIME
	  CALL	ILPRT
	  DB	'TIM - Select Baud rate for "time-to-send" msg.',CR,LF,0
;
NOTIME:	  LDA	TOGGLECRC
	  ORA	A
	  JZ	NOTOGCRC
	  CALL	ILPRT
	  DB	'TCC - Toggle CRC/Checksum mode on receive',CR,LF,0
;
NOTOGCRC: LDA	TOGGLEBK
	  ORA	A
	  JZ	NOTOGBK
	  CALL	ILPRT
	  DB	'TBR - Toggle backspace to rubout conversion',CR,LF,0
;
NOTOGBK:  LDA	TOGGLELOC
	  ORA	A
	  JZ	NOTOGLOC
	  CALL	ILPRT
	  DB	'TLC - Toggle  1) local command immediate',CR,LF
	  DB	'              2) local command after ',0
	  LDA	EXTCHR
	  CALL	SHFTYPE
	  DB	CR,LF,0
;
NOTOGLOC: LDA	TOGGLELF
	  ORA	A
	  JZ	NOTOGLF
	  CALL	ILPRT
	  DB	'TLF - Toggle send linefeed after carriage return '
 	  DB	'in "T" mode',CR,LF,0
;
NOTOGLF:  LDA	TOGXOFF
	  ORA	A
	  JZ	NOTOGXOF
	  CALL	ILPRT
	  DB	'TXO - Toggle XOFF testing in terminal mode '
	  DB	'file output',CR,LF,0
;
NOTOGXOF: LDA	PMMIBYTE
	  ORA	A
	  JNZ	NONUM
	  CALL	ILPRT
	  DB	'NUM - List remote systems',CR,LF,0
	  LDA	SETUPTST
	  ORA	A
	  JZ	NOPMMI
	  CALL	ILPRT
	  DB	'SET - Set communication ports',CR,LF,0
;
NONUM:	  CALL	ILPRT
	  DB	'PAR - Toggle 8 bits no par/7 bits even par',CR,LF
	  DB	'BYE - Disconnect, then reboot to CP/M',CR,LF
	  DB	'CAL - Dial number',CR,LF
	  DB	'DSC - Disconnect from the phone line',CR,LF,0
;
NOPMMI:	  CALL	ILPRT
	  DB	CR,LF,'          The following are terminal text '
	  DB	'buffer commands:',CR,LF,0
;
SKIPLF:	  CALL	ILPRT
	
	  DB	'DEL - Delete memory buffer and file',CR,LF
	  DB	'NOL - Return to terminal mode - no loss of data '
	  DB	'in buffer',CR,LF
	  DB	'WRT - Write memory buffer to disk file',CR,LF,LF,0
	  CALL	NXTSCRN
;
	  CALL	ILPRT
	  DB	'      Local Commands while in Terminal Mode'
	  DB	CR,LF,LF,0
	  LDA	EXITCHR
	  CALL	SHFTYPE
	  DB	'  - Exit to command mode',CR,LF,0
;
	  LDA     PMMIBYTE
	  ORA     A
	  JZ      S5A
;
	  LDA	DISCCHR
	  CALL	SHFTYPE
	  DB	'  - Disconnect from the phone line',CR,LF,0
	  LDA	BRKCHR
	  CALL	SHFTYPE
	  DB	'  - Send break',CR,LF,0
	  LDA	CHGBAUD
	  CALL	SHFTYPE
	  DB	'  - Change baud rate',CR,LF,0
;
S5A:	  LDA	TRANLOGON
	  ORA	A
	  JZ	NOTRNLOG
	  LDA	LOGCHR
	  CALL	SHFTYPE
	  DB	'  - Send log-on message',CR,LF,0
;
NOTRNLOG: LDA	LSTTST
	  ORA	A
	  JZ	NOLST2
	  LDA	LSTCHR
	  CALL	SHFTYPE
	  DB	'  - Toggle printer',CR,LF,0
;
NOLST2:   MVI	A,LF
	  CALL	TYPE
	  LDA	SAVECHR
	  CALL	SHFTYPE
	  DB	'  - Start copy into buffer',CR,LF,0
	  LDA	UNSAVECHR
  	  CALL	SHFTYPE
	  DB	'  - Stop copy into buffer',CR,LF,LF
	  DB	'             Start & Stop may be toggled as often as '
 	  DB	'desired.',CR,LF
	  DB	'             A ":" at start of line indicates buffer '
	  DB	'is copying.',CR,LF
	  DB	'             XOFF automatically used to stop input '
	  DB	'when writing',CR,LF
	  DB	'                full buffer to disk, XON sent to '
	  DB	'resume.',CR,LF,LF,0
	  LDA	TRANCHR
	  CALL	SHFTYPE
	  DB	'  - Transfer ASCII file to remote',CR,LF,LF,0
	  LDA	LOCONEXTCHR
	  ORA	A
	  LDA	EXTCHR
	  JNZ	REMDFLT
	  CALL	SHFTYPE
	  DB	'  - Send local control character to remote'
	  DB	CR,LF,LF,0
	  JMP	XPRT
;
REMDFLT:  CALL	SHFTYPE
	  DB	'  - Next character will be used for local control'
	  DB	CR,LF,0
;
XPRT:	  CALL	CRLF		;TURN UP A BLANK LINE TO LOOK NICE
	  LDA	NFILFLG		;HAVE A FILE OPEN FOR TEXT MODE COPY?
	  ORA	A
	  JNZ	XPRT1		;IF NOT, EXIT
	  CALL	GETSPC		;OTHERWISE SHOW REMAINING SPACE 
	  CALL	ILPRT
	  DB	' Bytes of buffer free',CR,LF,0
;
XPRT1:	  MVI	C,CURDSK	;CURRENT DISK FUNCTION
	  CALL	BDOS
	  ADI	'A'		;MAKE ASCII
	  CALL	TYPE
;
	  CALL	GETUSER		;GET CURRENT USER NUMBER
	  ORA	A
	  JZ	XPRT2		;SKIP IF USER 0
	  MVI	H,0
	  MOV	L,A
	  CALL	DECOUT		;SHOW USER CURRENT USER AREA
;
XPRT2:	  MVI	A,'>'
	  CALL	TYPE
	  MVI	A,' '
	  CALL	TYPE
	  CALL	ILPRT
	  DB	'COMMAND (H for Help): ',0
;
GETCMD:	  LXI	D,CMDBUF	;ENTER COMMAND
	  CALL	INBUF
	  LDA	CMDBUF+3
	  CPI	':'		;SEE IF REQUEST FOR NEW DRIVER/USER
	  JZ	SETDRV
	  LXI	D,CMDBUF+2	;POINT TO COMMAND
	  CALL	INLNCOMP
	  DB	'CPM',0
	  JNC	EXIT
	  CALL	CRLF		;(1ST CR,LF AT "INBUFR")
	  CALL	INLNCOMP
	  DB	'LOG',0
	  JNC	LOGNEW
	  CALL	INLNCOMP
	  DB	'DIR',0
	  JNC	DIR
	  CALL	INLNCOMP
	  DB	'ERA',0
	  JNC	ERASEF
	  CALL	INLNCOMP
	  DB	'?',0
	  JNC	CURPAR
	  CALL	INLNCOMP
	  DB	'SPD',0
	  JNC	SETSPD
	  CALL	INLNCOMP
	  DB	'TIM',0
	  JNC	SETTIM
	  CALL	INLNCOMP
	  DB	'TCC',0
	  JNC	TOGCRC
	  CALL	INLNCOMP
	  DB	'TBR',0
	  JNC	TOGBKSP
	  CALL	INLNCOMP
	  DB	'TLC',0
	  JNC	TOGLOC
	  CALL	INLNCOMP
	  DB	'TLF',0
	  JNC	TOGLF
	  CALL	INLNCOMP
	  DB	'TXO',0
	  JNC	TOGTXOFF
	  LDA	PMMIBYTE 
	  ORA	A
	  JNZ	NONUM2
	  CALL	INLNCOMP
	  DB	'NUM',0
	  JNC	NUMPRN
;
NONUM2:	  LDA	SETUPTST
	  ORA	A
	  JZ	NOSETUP
	  CALL	INLNCOMP
	  DB	'SET',0
	  JNC	SETUPENT
;
NOSETUP: CALL	INLNCOMP
	  DB	'NOL',0
	  JC	NXTOPT1		;CARRY SET = NO MATCH
	  LDA	NFILFLG
	  ORA	A
	  JNZ	NOFILOPN	;GO TELL OPERATOR IF NO FILE OPEN
	  LDA	ORIGSAV
	  STA	ORIGFLG
	  CALL	BUFMSG
	  LHLD	HLSAVE		;RETURN TO TERMINAL..
	  JMP	TERM		;..MODE WITH SAVE OPTION..
;.....				;..IF PREVIOUSLY ENABLED.
;
;
NXTOPT1:  CALL	INLNCOMP
	  DB	'WRT',0
	  JNC	WRTFIL
	  CALL	INLNCOMP
	  DB	'DEL',0
	  JNC	NEWFILE
	  CALL	INLNCOMP
	  DB	'BYE',0
	  JNC	BYEBYE
	  LDA	PMMIBYTE
	  ORA	A
	  JZ	S6
;MOD(BGL)***
	  CALL	INLNCOMP
	  DB	'PAR',0
	  JNC	TOGLPAR
	  CALL	INLNCOMP	;'DE' SET FROM 1ST INLNCOMP CALL
	  DB	'DSC',0
	  JNC	DISCON1
	  CALL	INLNCOMP
	  DB	'CAL',0
	  JC	S6
	  MVI	A,' '		;FOOL THE SYSTEM
	  STA	CMDBUF+4	;..CMDBUF SO THAT IT..
	  JMP	DOOPT		;..LOOKS AT OPTION FOR DIAL
;
S6:	  PUSH	H
	  LDA	CMDBUF+2
	  LXI	H,COMPLIST
	  CALL	COMPARE		;COMPARES LIST POINTED TO BY HL..
	  POP	H		;..TO CHAR IN A-REG.
	  JC	NOTVLD		;CARRY SET = NO MATCH
;
DOOPT:	  PUSH	H		;LOAD ORIGINAL FCB WITH TRANSFER..
	  CALL	SETFCB		;..CMDS AND GO TO BEGINNING OF..
	  POP	H		;..PROGRAM. WILL FOLLOW SAME LOGIC..
	  JMP	RESTART		;..AS IF PROGRAM WERE CALLED WITH..
;.....				;..CP/M COMMAND LINE.
;
;
NOTVLD:	  CALL	NTVLDMSG
	  JMP	XPRT
;
;
NTVLDMSG: CALL	ILPRT
	  DB	'++ Invalid command ++',CR,LF,BELL,0
	  RET
;.....
;
;
BYEBYE:	  CALL	ILPRT
	  DB	'<< Goodbye...back to CP/M >>',CR,LF,0
	  XRA	A
	  CALL	OUT$MODCTLP
	  CALL	OUT$MODCTL2
	  LDA	OLDUSER		;GET ORIGINAL USER NUMBER
	  MVI	E,A
	  CALL	SETUSER
	  LHLD	CLDBOOT
	  PCHL			;DO A COLD REBOOT, DONE
;.....
;
;
DIR:	  MVI	C,CURDSK
	  CALL	BDOS
	  STA	DISKSAV
	  CALL	DIRLIST
	  LDA	DISKSAV
 	  MOV	E,A
	  MVI	C,SELDSK
	  CALL	BDOS
	  JMP	XPRT
;.....
;
;
DISCON1:  CALL	JMP$DISCONNT
	  CALL	ILPRT
	  DB	CR,LF,'<< Disconnected >>',CR,LF,BELL,0
	  JMP	EXITMEN
;.....

;
ERASEF:	  LXI	D,CMDBUF	;PUT CMD LINE INTO FCB AT 'HL'
	  LXI	H,FCB
	  CALL	CMDLINE
	  CALL	MOVEFCB		;MOVE FCB+16 TO FCB
	  LDA	FCB+1
	  CPI	' '
	  JZ	NOTVLD		;GO IF NO FILE SPECIFIED
	  LXI	D,FCB
	  MVI	C,SRCHF
	  CALL	BDOS
	  INR	A		;0 IF FILE NOT FOUND
	  JNZ	ERAFILE 	;OK, GO ERASE
	  CALL	ILPRT
	  DB	'++ File not found ++',CR,LF,BELL,0
	  JMP	XPRT
;.....
;
;
ERAFILE:  LXI	D,FCB
	  MVI	C,ERASE
	  CALL	BDOS
	  CALL	ILPRT
	  DB	'File erased',CR,LF,0
	  JMP	XPRT
;.....
;
;
LOGNEW:	  LDA	NFILFLG
	  ORA	A
	  JZ	NORESET
	  LDA	CMDBUF+6	;ANY DISK DRIVE SPECIFIED?
	  CPI	' '
	  JNZ	LOGNEW1		;IF NOT A BLANK, EXIT
	  CALL	GETDISK		;IF NOT, USE CURRENT DRIVE
	  ADI	'A'		;TO COMPENSATE FOR NEXT LINE
;
LOGNEW1:  SUI	'A'
	  CPI	15+1		;FOR DRIVES 0-15
	  JNC	NOTVLD		;IF MORE THAN 15, DISPLAY ERROR MESSAGE
	  STA	DISKSAV		;STORE REQUESTED DRIVE
	  CALL	GETUSER		;PICK UP CURRENT USER NUMBER
	  MOV	B,A		;SAVE IT
	  LDA	CMDBUF+7	;GET NEW USER NUMBER
	  CALL	CHRCHK		;CHECK THE CHAR.
	  CALL	FINDUSER
	  LDA	CMDBUF+8	;GET 2ND DIGIT
	  CALL	CHRCHK		;CHECK THE CHAR.
	  CALL	FINDUSER+2
;
LOGNEW2:  CALL	SAVEUSER	
	  MVI	C,RESET
	  CALL	BDOS
	  LDA	DISKSAV
	  MOV	E,A
	  MVI	C,SELDSK
	  CALL	BDOS
	  LDA	SAVUSR
	  MOV	E,A
	  CALL	SETUSER	
	  JMP	XPRT
;.....
;
;
CHRCHK:	  CPI	' '
	  JZ	CHRCHK1
	  CPI	':'		;IN CASE OF A: OR A1: OR A11:  (ETC.)
	  RNZ
;
CHRCHK1:  POP	PSW		;RESET THE 'CALL' ON THE STACK
	  JMP	LOGNEW2
;.....
;
;
FINDUSER: MVI	B,0		;ZERO THE 'B' REG. FOR 1ST TIME THROUGH
	  CALL	NUMCHK		;IF NEITHER, SEE IF A VALID NUMBER
	  MOV	C,A		;SAVE
	  MOV	A,B		;GET SAVE FIRST DIGIT
	  ADD	A		;X2
	  ADD	A		;X4
	  ADD	A		;X8
	  ADD	B		;X9
	  ADD	B		;X10
	  ADD	C
	  MOV	B,A		;SAVE
	  RET
;.....
;
;
SAVEUSER: MOV	A,B
	  CPI	15+1		;USER NUMBERS ARE 0-15
	  JNC	NOTVLD
	  STA	SAVUSR
	  RET
;.....
;	
;
NUMGET:	  LXI	D,CMDBUF
	  CALL	INBUF
	  LDA	CMDBUF+2	;GET NUMBER
	  CPI	' '
	  RZ
;
NUMCHK:	  SUI	'0'		;REMOVE ASCII BIAS
	  CPI	9+1
	  RC			;OK IF 9 OR LESS
	  POP	H		;REMOVE 1ST CALL FROM THE STACK
	  POP	H		;REMOVE 2ND CALL FROM THE STACK	
	  JMP	NOTVLD
;
GETUSER:  MVI	E,0FFH		;GET CURRENT USER
;
SETUSER:  MVI	C,USER		;SET UP BDOS CALL
	  JMP	BDOS
;.....
;
;
GETDISK:  MVI	C,CURDSK	;GET CURRENT DRIVE
	  JMP	BDOS
;.....
;
;
NORESET:  CALL	ILPRT
	  DB	'++      Terminal mode file open      ++',CR,LF
	  DB	'++ Use WRT or DEL before LOG command ++',CR,LF
	  DB	CR,LF,BELL,0
	  XRA	A
	  JMP	XPRT
;.....
;
;
SETSPD:	  CALL	ILPRT
	  DB	'Delay between chars. (0-9): ',0
;
NOKEYS:	  CALL	STAT
	  JZ	NOKEYS
	  CALL	KEYIN
	  CALL	TYPE
	  CALL	SAVEA
	  SUI	'0'
	  CPI	10
	  JNC	NOTVLD
	  STA	BYTDLY
;
	  CALL	ILPRT
	  DB	'Delay at end of line (0-9): ',0
;
NOKEYS1:  CALL	STAT
	  JZ	NOKEYS1
	  CALL	KEYIN
	  CALL	TYPE
	  CALL	SAVEA
	  SUI	'0'
	  CPI	10
	  JNC	NOTVLD
	  STA	CRDLY
;
SPDMSG:	  CALL	ILPRT
	  DB	CR,LF,'Char. delay (terminal file mode) is:  ',0
	  LDA	BYTDLY
	  MOV	B,A
	  MOV	A,B
	  PUSH	H
	  MOV	L,A
	  MVI	H,0
	  CALL	DECOUT
	  POP	H
	  CALL	ILPRT
	  DB	'0 ms. per character',CR,LF
	  DB	'Line  delay (terminal file mode) is: ',0
	  LDA	CRDLY
	  MOV	B,A
	  PUSH	H
	  MOV	L,A
	  MVI	H,0
	  CALL	DECOUT
	  POP	H
	  CALL	ILPRT
	  DB	'00 ms. per character',CR,LF,0
	  JMP	XPRT
;......
;
;
SAVEA:	  PUSH	PSW
	  CALL	ILPRT
	  DB	CR,LF,0
	  POP	PSW
	  RET
;.....
;
;
SETDRV:	  LDA	CMDBUF+2	;GET THE DISK DRIVE
	  SUI	'A'		;CONVERT TO BINARY VALUE
	  CPI	15+1		;FOR DRIVES 0-15
	  JNC	NOTVLD
	  MOV	E,A
	  MVI	C,SELDSK	;SELECT REQUESTED DRIVE
	  CALL	BDOS
	  LDA	CMDBUF+5	;GET USER NUMBER, IF ANY
	  CPI	' '		;KEEP CURRENT USER AREA?
	  JZ	XPRT
	  SUI	'0'		;CONVERT TO BINARY VALUE
	  CPI	1		;IF A '1', COULD BE UNITS OR TENS
	  JNZ	SETDRV1		;IF NOT, NUMBERS STOP AT 15 SO EXIT
	  LDA	CMDBUF+6	;CHECK FOR A 2ND DIGIT
	  CPI	'0'
	  JC	SETDRV2		;IF LESS, NOT A VALID NUMBER, IGNORE
	  SUI	'0'-10		;LEAVE THE '10' IN AS TWO DIGITS USED
;
SETDRV1:  CPI	15+1		;USER AREAS ARE 0-15
	  JNC	NOTVLD
	  MOV	E,A
	  CALL	SETUSER
	  JMP	XPRT		;BACK TO WORK
;
SETDRV2:  MVI	A,1
	  JMP	SETDRV1
;.....
;
;
SETTIM:   CALL	SORPTST
	  JNZ	NOTVLD
	  CALL	ILPRT
	  DB	'Use 0-8 to give baud rate for ''S'' mode '
	  DB	'time-to-send message,',CR,LF
	  DB	'where 0=110, 1=300, 2=450, 3=600, 4=710, 5=1200, '
	  DB	'6=2400, ',CR,LF,'7=4800 AND 8=9600 Baud.'
	  DB	CR,LF,LF,'Enter value: ',0
	  CALL	NUMGET
	  CPI	8+1		;ONLY LOOKING FOR 1-8 ANSWERS
	  JNC	NOTVLD
	  STA	MSPEED
	  CALL	SETTIM2
	  JMP	XPRT
;.....
;
;
SETTIM2:  CALL	SORPTST
	  JNZ	SETTIM3
	  CALL	ILPRT
	  DB	'Rate for the S mode time-to-send message is set to ',0
	  JMP	SETTIM4
;...
;
;
SETTIM3:  CALL	ILPRT
	  DB	'Modem speed is ',0
;
SETTIM4:  JMP	PRTBAUD
;.....
;
;
SORPTST:  LDA	SETUPTST
	  MOV	B,A
	  LDA	PMMIBYTE
	  ORA	B
	  RET
;.....
;
;
TOGCRC:	  LDA	TOGGLECRC
	  ORA	A
	  JZ	NOTVLD
	  LDA	CKSUMDFLT
	  CMA
	  STA	CKSUMDFLT
	  CALL	TOGCRC1
	  JMP	XPRT
;.....
;
;
TOGCRC1:  ORA	A
	  JNZ	CHEKMSG
	  CALL	ILPRT
	  DB	'CRC mode set',CR,LF,0
	  RET
;.....
;
;
CHEKMSG:  CALL	ILPRT
	  DB	'CHECKSUM mode set',CR,LF,0
	  RET
;.....
;
;
TOGBKSP:  LDA	TOGGLEBK
	  ORA	A
	  JZ	NOTVLD
	  LDA	CONVBKSP
	  CMA
	  STA	CONVBKSP
	  CALL	TOGBKSP2
	  JMP	XPRT
;.....
;
;
TOGBKSP2: LDA	CONVBKSP
	  ORA	A
	  JZ	NORUBMSG
	  CALL	ILPRT
	  DB	'Backspace is rub',CR,LF,0
	  RET
;.....
;
;
NORUBMSG: CALL	ILPRT
	  DB	'Backspace is backspace',CR,LF,0
	  RET
;.....
;
;
TOGLOC:	  LDA	TOGGLELOC
	  ORA	A
	  JZ	NOTVLD
	  LDA	LOCONEXTCHR
	  CMA
	  STA	LOCONEXTCHR
	  CALL	TOGLOC2
	  JMP	XPRT
;.....
;
;
TOGLOC2:  CALL	ILPRT
	  DB	'Use ',0
	  LDA	LOCONEXTCHR
	  ORA	A
	  LDA	EXTCHR
	  JZ	LOCMSG
	  CALL	SHFTYPE
	  DB	' before local command',CR,LF,0
	  RET
;.....
;
;
LOCMSG:   CALL	SHFTYPE
	  DB	' to send local command to remote',CR,LF,0
	  RET
;.....
;
;
TOGLF:	  LDA	TOGGLELF
	  ORA	A
	  JZ	NOTVLD
	  LDA	ADDLF
	  CMA
	  STA	ADDLF
	  CALL	TOGLF2
	  JMP	XPRT
;.....
;
;
TOGLF2:	  CALL	ILPRT
	  DB	'Linefeed ',0
	  LDA	ADDLF
	  ORA	A
	  JNZ	LFMSG
	  CALL	ILPRT
	  DB	'NOT ',0
;
LFMSG:	  CALL	ILPRT
	  DB	'sent after <CR>',CR,LF,0
	  RET
;.....
;
;
TOGTXOFF: LDA	TOGXOFF
	  ORA	A
	  JZ	NOTVLD
	  CALL	ILPRT
	  DB	'Use XOFF testing? (Y/N): ',0
	  CALL	GETANS
	  JC	NOCHG3
	  STA	XOFFTST
;
NOCHG3:	  CALL	XOFFMSG
	  CALL	ILPRT
	  DB	CR,LF,'Use XON waiting after <CR> (Y/N): ',0
	  CALL	GETANS
	  JC	NOCHG4
	  STA	XONWAIT
;
NOCHG4:	  CALL	XONMSG
	  LDA	XONWAIT
	  ORA	A
	  JZ	XPRT
	  CMA
	  STA	XOFFTST		;DON'T ALLOW BOTH
	  CALL	ILPRT
	  DB	'Therefore ',0
	  CALL	XOFFMSG
	  JMP	XPRT
;.....
;
;
GETANS:   LXI	D,CMDBUF
	  CALL	INBUF
	  LDA	CMDBUF+2 	;GET ANSWER
	  CPI	' '
	  CMC
	  RZ
	  MOV	B,A
	  CPI	'N'
	  MVI	A,FALSE
	  RZ
	  MOV	A,B
	  CPI	'Y'
	  MVI	A,TRUE
	  RZ
	  POP	PSW		;PRESERVE STACK
	  JMP	NOTVLD
;.....
;
;
XOFFMSG:  CALL	ILPRT
	  DB	'XOFF testing ',0
	  LDA	XOFFTST
	  ORA	A
	  JNZ	XOTSTON
	  CALL	ILPRT
	  DB	'NOT ',0
;
XOTSTON:  CALL	ILPRT
	  DB	'used',0
;
XONMSG3:  CALL	ILPRT
	  DB	' in terminal mode file output',CR,LF,0
	  RET
;.....
;
;
XONMSG:	  CALL	ILPRT
	  DB	'XON ',0
	  LDA	XONWAIT
	  ORA	A
	  JNZ	XONMSG2
	  CALL	ILPRT
	  DB	'NOT ',0
;
XONMSG2:  CALL	ILPRT
	  DB	'automatically tested after <CR>',0
	  JMP	XONMSG3
;...
;
;
SETUPENT: LDA	SETUPTST
	  ORA	A
	  JZ	NOTVLD
	  LXI	D,CMDBUF+1
	  CALL	JMP$SETUPR
	  JMP	XPRT
;.....
;
;
NEWFILE:  LDA	NFILFLG
	  ORA	A
	  JNZ	NOFILOPN	
	  LDA	FCB3+1		;CHECK THAT FILE WAS REQUESTED
	  CPI	' '
	  JZ	NOFILOPN	;IF NO FILE, DON'T ERASE
	  LXI	D,FCB3
	  MVI	C,ERASE
	  CALL	BDOSRT
	  MVI	A,TRUE		;DO NOT ALLOW TERMINAL..
	  STA	NFILFLG		;..SAVE SINCE NO FILE..
	  CMA			;..SPECIFIED.
	  STA	SAVEFLG
	  LXI	H,FCB3
	  CALL	INITFCB
	  LXI	H,BOTTRAM
	  SHLD	HLSAVE
	  JMP	XPRT
;.....
;
;
WRTFIL:
	  LDA	NFILFLG
	  CPI	TRUE
	  JZ	NOFILOPN
	  LDA	FCB3+1		;CHECK THAT FILE WAS REQUESTED
	  CPI	' '
	  JZ	NOFILOPN
	  LHLD	HLSAVE		;START OF MEMORY BUFFER
	  CALL	NUMRECS		;DISK WRITE ROUTINE AS USED IN
	  CALL	WRTDSK		;   THE 'INTDSKSV' ROUTINE
	  CALL	CLOSE3
	  MVI	A,TRUE
	  STA	NFILFLG		;SHOW NO FILE OPEN NOW
	  CMA
	  STA	SAVEFLG
	  LXI	H,FCB3
	  CALL	INITFCB		;BLANK OUT FCB TO WRITTEN FILE
	  LXI	H,BOTTRAM	;   CAN'T BE ERASED
	  SHLD	HLSAVE		;RESET TO BUFFER START FOR NEXT TIME
	  JMP	XPRT
;.....
;
;
NOFILOPN: CALL	ILPRT
	  DB	'++ No File Open ++',CR,LF,BELL,0
	  JMP	XPRT
;.....
;
;
;THIS ROUTINE DISPLAYS THE PHONE NUMBERS IN THE LIBRARY
;
NUMPRN:	  PUSH	H
	  CALL	CLRTST
	  CALL	ILPRT
	  DB	'           Library of Phone Numbers of Remote Systems'
	  DB	0
	  MVI	C,13		;NUMBER OF LINES TO MOVE
	  LXI	H,NUMBLIB	;ADDRESS OF SOURCE MEMORY
	  LXI	D,DBUF		;ADDRESS OF TARGET MEMORY
	  CALL	NEWLINE		;START WITH CRLF
	  STAX	D		;+LF
	  INX	D		;AND BUMP IT
;
NUMPRN1:  INX	H		;SKIP PMMI DIALING LETTER
	  INX	H		;AND EQUAL SIGN
	  MVI	B,LIBLEN-2	;NUMBER OF BYTES TO MOVE
	  CALL	MOVE		;MOVE TO BUFFER
	  CALL	SPACES		;2 ENTRIES + 3 SPACES = 63 CHARACTERS
	  INX	H
	  INX	H
	  MVI	B,LIBLEN-2
	  CALL	MOVE
	  CALL	NEWLINE
	  DCR	C		;NUMBER OF LINES TO PRINT
	  JZ	NUMPRN2
	  JMP	NUMPRN1
;.....
;
;
NEWLINE:  MVI	A,CR		;PUTS CR-LF AT MEMORY POINTED BY 'DE'
	  STAX	D		;STORE IT
	  MVI	A,LF		;LF
	  INX	D		;BUMP POINTER
	  STAX	D		;STORE LF
	  INX	D		;BUMP POINTER
	  RET
;.....
;
;
SPACES:	  MVI	A,' '		;SPACE
	  STAX	D
	  INX	D		;1
	  STAX	D
	  INX	D		;2
	  STAX	D
	  INX	D		;3
	  RET
;.....
;
;
NUMPRN2:  MVI	A,'$'
	  STAX	D
	  MVI	C,PRINT
	  LXI	D,DBUF		;POINT TO TABLE OF NUMBERS TO PRINT
	  CALL	BDOS
	  CALL	CRLF
	  CALL	CRLF
	  POP	H
	  JMP	XPRT
;......
;
;
COMPARE:  MOV	B,M		;COMPARES A-REG WITH LIST..
;
COMPLP:	  INX	H		;..ADDRESSED BY HL. FIRST ELEMENT..
	  CMP	M		;..OF LIST MUST BE NUMBER OF ELEMENTS..
	  JZ	VALID		;..BEING COMPARED. RETURNS WITH..
	  DCR	B		;..CARRY SET IF A-REG DOES NOT..
	  JNZ	COMPLP		;.. CONTAIN AN ELEMENT IN LIST.
	  STC
;
VALID:	  RET
;.....
;
;
NXTSCRN:  CALL  ILPRT
	  DB	'HIT any KEY to CONTINUE',0
;
NOKEY1:	  CALL	STAT		;GET KEYBOARD STATUS
	  JZ	NOKEY1		;KEEP LOOPING UNTIL KEYPRESS
	  CALL	KEYIN		;GOBBLE UP KEYPRESS
	  CPI	'C'-40H		;CONTROL-C TO ABORT?
	  JNZ	CLRTST
	  POP	H		;CLEAR STACK OF RETURN ADDRESS
	  CALL	CRLF		;TURN UP A BLANK LINE
	  JMP	XPRT
;.....
;
;
CLRTST:	  LDA	SCRNTEST
	  ORA	A
	  JNZ	CLRSCRN
;.....
;
;
LOTSALF:  MVI	A,CR
	  CALL	TYPE
	  MVI	B,12
	  MVI	A,LF
;
LFLOOP:	  CALL	TYPE
	  DCR	B
	  JNZ	LFLOOP
	  RET
;.....
;
;
CURPAR:	  CALL	CLRTST
	  CALL	ILPRT
	  DB	'                Current Settings',CR,LF,LF,0
	  LDA	CKSUMDFLT	;SEE IF SET FOR 'CRC' OR 'CHECKSUM'
	  CALL	TOGCRC1
	  LDA	LSTTST
	  ORA	A
	  JZ	NOLST3
	  CALL	LSTMSG
;
NOLST3:	  CALL	SETTIM2
	  CALL	TOGBKSP2
	  CALL	TOGLF2
	  CALL	TOGLOC2
	  CALL	ILPRT
	  DB	'Terminal mode file buffer is ',0
	  LDA	NFILFLG
	  ORA	A
	  JZ	ACTIVE
	  CALL	ILPRT
	  DB	'in',0
;
ACTIVE:	  CALL	ILPRT
	  DB	'active',CR,LF,'Unused portion of buffer is ',0
	  CALL	GETSPC
	  CALL	ILPRT
	  DB	' bytes',CR,LF,0
	  CALL	XOFFMSG
	  CALL	XONMSG
	  CALL	SPDMSG
	  CALL	CRLF
	  CALL	CRLF
	  CALL	CRLF
	  JMP	XPRT
;.....
;
;
GETSPC:	  CALL	GETMAX
	  MOV	B,A
	  LHLD	HLSAVE
	  STC
	  CMC
	  MVI	A,0
	  SBB	L
	  MOV	L,A
	  MOV	A,B
	  SBB	H
	  MOV	H,A
	  CALL	DECOUT
	  RET
;.....
;
;
COMPLIST: DB	 6, 'S', 'R', 'T', 'E', 'H', 'L'
;.....
;
;
;***********************************************************************
;
;       D - A - T - A    A - R - E - A
;
;***********************************************************************
;
;
; OPTION TABLE
;
OPTBL:	  EQU	$
ANSWFLG:  DB	'A'
BATCHFLG: DB	'B'	;SET TO 'B' BY MENU. DOES NOT ALLOW MULTI-FILE
DISCFLG:  DB	'D'
LOCCHFLG: DB	'L'
ORIGFLG:  DB	'O'
QFLG:	  DB	'Q'
RSEEFLG:  DB	'R'
SSEEFLG:  DB	'S'
TERMFLG:  DB	'T'
VSEEFLG:  DB	'V'
XITFLG:	  DB	'X'		
EPARITY:  DB	'0'	;EVEN PARITY SUB-OPTION (ONLY IN S OR R MODE)
OPARITY:  DB	'1'	;ODD PARITY SUB-OPTION  (ONLY IN S OR R MODE)
OPTBE:	  EQU	$	;..TRANSFER WHEN PROGRAM INITIALLY CALLED.
;
;
; The following must be in the same order as the table above:
;
RESTROPT: DB	'A','B','D','L','O','Q','R','S','T','V','X','0','1'
;
;
; THE NEXT 13 BYTES EQUAL THE NUMBER OF BYTES BETWEEN RECDNOB AND
; RECDNOE
;
RESTSN:   DB	0,0,0,0,0,0
	  DW	DBUF
	  DB	0,0,0,0,0
;
RECDNOB   EQU	$	;START OF TABLE MARKER
RCVRNO:   DB	0	;\
RECDNO:   DB	0,0	; \
ERRCT:    DB	0	;  \
ERRCDE:   DB	0	;   \
EOFLG:    DB	0	;    \	13 BYTES BETWEEN TABLE MARKERS
RECPTR:   DW	DBUF	;    /
RECINBF:  DB	0	;   /
MAXEXT:   DB	0	;  /
RCNT:     DB	0,0 	; /
DATAFLG:  DB	0	;/
RECDNOE   EQU	$	;END OF TABLE MARKER
;
CRCVAL:	  DW	0
DIALCT:	  DW	0
HLSAVE:	  DW	BOTTRAM
HLSAVE1:  DW	BOTTRAM
HLSAVE2:  DW	BOTTRAM	
;
ABORTFLG: DB	0
CRCFLAG:  DB	TRUE
CRFLAG:	  DB	0	;CONTINUOUS REDIAL FLAG	
DLYFLG:	  DB	0
ECHOFLG:  DB	FALSE
EXACFLG:  DB	0
EXITFLG:  DB	TRUE
FIRSTME:  DB	TRUE	;FIRST SOH RECEIVED SET FLAG TO ZERO
FSTFLG:	  DB	TRUE
LASTBYT1: DB	0
LASTBYT2: DB	0
LISTFLG:  DB	FALSE
LISTMOR:  DB	FALSE	
LOCFLG:	  DB	FALSE
MFFLG1:	  DB	0	;1ST TIME SWITCH
MODCTLB:  DB	07FH
NFILFLG:  DB	FALSE	;ALLOWS WRITE TO MEMORY IN TERMINAL MODE
NSEEFLG:  DB	TRUE	;FALSE TO SEE FILE NAME IN QUIET MODE
ONERR:    DB	0
OPTION:	  DB	0
RINGBKFL: DB	0
SAVEFLG:  DB	FALSE
UARTCTLB: DB	ORIGMOD	;FOR ORIGINATE MODE
UARTFLG:  DB	FALSE	;FOR ORIGINATE MODE
CMDBUF:	  DB	80H,0	;COMMAND BUFFER, TWO PAGES PLUS ONE BYTE
;
	  DS	80H
BGNMS:	  DS	2
DISKNO:	  DS	1
DISKSAV:  DS	1
FILECT:	  DS	1
FTYCNT:	  DS	1
NAMECT:	  DS	1
NBSAVE:	  DS	2
OLDUSER:  DS	1
ORIGSAV:  DS	1
SENDFLG:  DS	1
SAVUSR:	  DS	1
          DS	100	;STACK DEPTH
STACK:	  DS	0
;
FCB3:	  DS	33
FCB4:	  DS	33
FCBBUF:	  DS	15
MFNAME5:  DS	12	;REQUESTED NAME
MFNAME6:  DS	12	;CURRENT NAME
DBUF	  EQU	$	
NAMEBUF	  EQU	DBUF+(DBUFSIZ*1024)	;BUFFER FOR NAMES IN BATCH MODE.
;.....
;
;
; BDOS EQUATES
;
RDCON:	  EQU	1
WRCON:	  EQU	2
LSTOUT:	  EQU	5
PRINT:	  EQU	9
RDBUF:	  EQU	10
CONST:	  EQU	11
CPMVER:	  EQU	12
RESET:	  EQU	13
SELDSK:	  EQU	14
OPEN:	  EQU	15
CLOSE:	  EQU	16
SRCHF:	  EQU	17
SRCHN:	  EQU	18
ERASE:	  EQU	19
READ:	  EQU	20
WRITE:	  EQU	21
MAKE:	  EQU	22
REN:	  EQU	23
CURDSK:	  EQU	25
SETDMA:	  EQU	26
DSKALL:	  EQU	27
DSKPAR:	  EQU	31
USER:	  EQU	32
FILSIZ:	  EQU	35
BDOS:	  EQU	0005H
REIPL:	  EQU	0
FCB:	  EQU	5CH
FCBEXT:	  EQU	FCB+12
FCBSNO:	  EQU	FCB+32
FCBRNO:	  EQU	FCB+32
FCB2:	  EQU	6CH
;
LAST	  END	100H
                                                                                                                          
