	TITLE	ZCPR Console Command Processor - Version D&J
	SUBTTL	Last Modified: 5 March 1994
;
;  CP/M Z80 Command Processor Replacement (CPR) Version 1.0
;	CCPZ CREATED AND CUSTOMIZED FOR ARIES-II BY RLC
;	FURTHER MODIFIED BY RGF AS V2.0
;	FURTHER MODIFIED BY RLC AS V2.1
;	FURTHER MODIFIED BY KBP AS V2.2
;	FURTHER MODIFIED BY RLC AS V2.4 (V2.3 skipped)
;	FURTHER MODIFIED BY RLC AS V2.5
;	FURTHER MODIFIED BY RLC AS V2.6
;	FURTHER MODIFIED BY SBB AS V2.7
;	FURTHER MODIFIED BY RLC AS V2.8
;	FURTHER MO
;
;		DCK - Don Kirkpatrick
;
; Further modified for better polling during LIST/TYPE, 16 July 1987.
;
; Further modified to include boot command and to permit multiple
; commands per line. Fixed bug in jump. Modified type so character
; is not echoed, 4 July 1988.
;
; Modified to add PAGE command 31 December 1989.
;
; Added BELL and SAK (Strike Any Key) command.
;
; Added ZCPR3 style drive/user number to all FCB parsing. For Example:
;	A>c4:		Changes to drive C/user 4
;	A>c4:<program>	Runs <pDIFIED BY RLC AS V2.9
;	FURTHER MODIFIED BY RLC AS V3.0
;	FURTHER MODIFIED BY RLC AS V3.1
;	FURTHER MODIFIED BY RLC AS V4.0
;	ZCPR VERSION 1.0 CREATED FROM CCPZ VERSION 4.0 BY RLC IN
;		A COORDINATED EFFORT WITH CCP-GROUP
;	FURTHER MODIFIED BY SBB (AS CCPZ-V4.1 11/27/81)
;	& MORE MODS BY ROBERT FISHER (CA. 12/1/81)
;	[RETROFITTED TO ZCPR BY BEN BRONSON (12/22/81) AS ZCPR-BB]
;
;	FURTHER MODIFIED BY DCK AS Version D&J
;
;	ZCPR is a group effort by CCP-GROUP, whose active membership involved
; inrogram> found on drive C/user 4
;	A>dir c4:	Gives directory of drive C/user 4
;	A>ren <new name>=c4:<old name> 
;			Renames file found on drive C/user 4
; Both the drive and user number are optional; 15: is a valid designation.
; S1 in the FCB is used to store the user number. If S1 contains a valid
; user number, bit 7 will be set. If no user number is specified, S1 will
; contain 0.
;
; Added POKE and changed SCL to a toggle, 12 August 1992.
;
; Added PEEK 30 August 1993.
;
;******** Structur this project consists of the following:
;		RLC - Richard Conn
;		RGF - Ron Fowler
;		KBP - Keith Peterson
;		FJW - Frank Wancho
;	The following individual also provided a contribution:
;		SBB - Steve Bogolub
;
; (Note by BB: SBB's and R Fisher's changes came too late in the 
;  history of CCPZ to be included in the first release of ZCPR)
;
;	Extensive modifications to add ERAQ, DIR for all usrnum,
; LIST x.x P, and fix TYPE when FF encountered was done by Don
; Kirkpatrick, 20 September 1986.
e Notes ********
;
;	This CPR is divided into a number of major sections. The following
; is an outline of these sections and the names of the major routines
; located therein.
;
; Section	Function/Routines
; -------	-----------------
;
;   --		Opening Comments, Equates, and Macro Definitions
;
;    0		JUMP Table into CPR
;
;    1		Buffers
;
;    2		CPR Starting Modules
;			CPR1	CPR	RESTRT
;
;    3		Utilities
;			CRLF	PRINTC	PRINT	PRINTS	BELL
;			CONOUT	BREAK	CHKETX	ABORT	READF
;			READT   - TRUE to build at intermediate address to debug via debugger.
;
;  COMLD  - TRUE to test and execute as a .com file.
;
;  REL    - TRUE if integration is to be done via MOVCPM.
;
;  BASE   - Base Address of user's CP/M system (normally 0 for DR version).
;	    This equate eases modification by non-standard CP/M (eg. H89).
;
;  P2DOS  - Address of BDOS/P2DOS.
;
TEST	EQU	FALSE	 	;SET TO LOAD/RUN AT 8000H FOR DEBUG
COMLD	EQU	FALSE		;SET TO LOAD AND EXECUTE AS A .COM FILE
REL	EQU	FALSE		;SET T	WRITE	DEFDMA	DMASET	SEARF
;			SEARDE	SEARN	OPENF	OPEN	CLOSE
;			CREATE	BDOSFN	SUBKIL	DELETE	TLOGIN
;			DLOGIN	LOGIN	NEWUSR	RSTUSR	SETUSR
;			BDOSEA	BDOSJP	BDOSBC	BDOSDE
;
;     4 	CPR Utilities
;			PROMPT	REDBUF	CNVBUF	UCASE	SDELM
;			ADVAN	SBLANK	ADDAH	NUMBER	A2NUM
;			HEXNUM	USRNUM	ERROR	DIRPTR	ULOGIN
;			SCANER	SCANT	SCANF	CMDSER	SETUDB
;
;     5 	CPR-Resident Commands and Functions
;     5A		DIR	DIRPR	PRFN
;     5B		ERA
;     5C		ERAQ	PRNNF
;     5D		SAK	REPLY
;     5E		BELL
;     5F	O TRUE FOR MOVCPM INTEGRATION
				;LEAVE ALL FALSE FOR SYSGEN IMAGE
;
BASE	EQU	0		;BASE OF CP/M SYSTEM
P2DOS	EQU	0E400H		;BASE OF BDOS/P2DOS
ZCPRSZ	EQU	00800H		;SIZE OF ZCPR
P2DOSSZ	EQU	00E00H		;SIZE OF P2DOS	
BIOS	EQU	P2DOS+P2DOSSZ	;BASE OF BIOS
CPRLOC	DEFL	P2DOS-ZCPRSZ	;STANDARD EXECUTION ADDRESS
;
	IF	REL
CPRLOC	DEFL	0		;MOVCPM IMAGE
	ENDIF
;
	IF	TEST
CPRLOC	DEFL	8000H
	ELSE	
BOOT	EQU	BIOS		;BIOS COLD BOOT ENTRY
LISTST	EQU	BIOS+002DH	;ENTRY POINT FOR LIST STATUS	
	ENDIF
;
;  The foll	LIST
;     5G		TYPE	PAGER
;     5H		EJECT	
;     5I		SAVE
;     5J	 	REN
;     5K		USER	SUSER
;     5L		DFU
;     5M		SCL
;     5N		PEEK
;     5O		POKE	
;     5P		JUMP
;     5Q		COM
;     5R		GO 	CLLPRG	ERRLOG	ERRJMP
;     5S		GET	MEMLD	PRNLE
;     BIOS		BOOT
;
;
FALSE	EQU	0
TRUE	EQU	NOT FALSE
;
;
;  CUSTOMIZATION EQUATES
;
;  The following equates may be used to customize this CPR for the user's
;    system and integration technique. The following constants are provided:
;
;  TESowing is presented as an option, but is not normally user-customize-
; able. A basic design choice had to be made in the design of ZCPR concerning
; the execution of SUBMIT files. The original CCP had a problem in this sense
; in that it ALWAYS looked for the SUBMIT file from drive A: and the SUBMIT
; program itself (SUBMIT.COM) would place the $$$.SUB file on the currently
; default drive. When the user was logged into B: and he issued a SUBMIT
; command, the $$$.SUB was placed on B: and did not execspecific drive, and A: is the choice for said drive.
; With this facility engaged as such, Indirect Command Files like:
;
;		DIR
;		B:
;		DIR
;
; can be executed, even though the currently default drive is changed
; during execution. If the $$$.SUB file was present on the currently
; default drive, the above series of commands would not work since the
; ZCPR would be looking for $$$.SUB on the default drive, and switching
; default drives without moving the $$$.SUB file as well would cause
; proute. The CPR looked
; for $$$.SUB on A: and never found it.
;
;  After much debate it was decided to have ZCPR perform the same type of
; function as CCP (look for the $$$.SUB file on A:), but the problem with
; SUBMIT.COM still exists. Hence, RGF designed SuperSUB and RLC took his
; SuperSUB and designed SUB from it; both programs are set up to allow the
; selection at assembly time of creating the $$$.SUB on the default drive
; or on drive A:.
;
;  A final definition of the Indirect Command Filecessing to abort.
;
;  Note that the same problem can occur if the user number of the
; $$$.SUB file is not predefined. It is assumed that the $$$.SUB file
; is located on user 0 of the specified drive.
;
;  The trick of using the $ flag returned by DISK RESET is used to
; to speed the search for a $*.* file on drive A. This trick will not
; work if the $$$.SUB file is located on another drive.
;
;
;  Under the ZCPR, three command levels exist:
;
;	(1) that command issued by the user from his c ($$$.SUB or SUBMIT
; File) is presented as follows:
;
;		"An Indirect Command File is one which contains
;		 a series of commands exactly as they would be
;		 entered from a CP/M Console. The SUBMIT Command
;		 (or SUB Command) reads this file and transforms
;		 it for processing by the ZCPR (the $$$.SUB File).
;		 ZCPR will then execute the commands indicated
;		 EXACTLY as if they were typed at the Console."
;
;  Hence, to permit this to happen, the $$$.SUB file must always
; be present on a onsole at the '>' prompt
;	(2) that command issued by a $$$.SUB file at the '$' prompt
;	(3) that command issued by a user program by placing the command into
;	    CIBUFF and setting the character count in CBUFF
;
;  To use CIBUFF, the user program stores the command line and character
; count; ZCPR will initialize the pointers properly, store the ending zero,
; and capitalize the command line for processing. Once the command line is
; properly stored, the user executes the command line by reenteriOMPT INDICATING SUBMIT COMMAND
COMCHR	EQU	';'		;BEGIN COMMENT CHARACTER
CMDCHR	EQU	';'		;BEGIN NEXT COMMAND CHARACTER
NUMBASE	EQU	'H'		;CHARACTER USED TO SPECIFY HEXIDECIMAL BASE
RECFLG	EQU	'R'		;CHARACTER FOR SAVE COMMAND TO SAVE RECORDS
SUPRES	EQU	TRUE		;TRUE TO SUPPRESS USER NUMBER FOR USER 0
MULTPL	EQU	TRUE		;TRUE TO ALLOW MULTIPLE COMMANDS ON ONE LINE
REBOOT	EQU	TRUE		;TRUE TO INCLUDE BOOT COMMAND
;
	IF	TEST
CPRMPT	EQU	'<'		;CPR PROMPT INDICATING TEST MODE
	ELSE	
CPRMPT	EQU	'>'		;CPR PROMPTng ZCPR
; through CPRLOC [NOTE: The C register MUST contain a valid User/Disk Flag
; (see location 4) at this time.]
;
;
; Directory customization equates
;
TWOCOL	EQU	FALSE		;TRUE FOR TWO-COLUMN DIRECTORY DISPLAY
WIDE	EQU	TRUE		;TRUE IF WIDE DIRECTORY DISPLAY
FENCE	EQU	'|'		;CHARACTER BETWEEN FILES
USRDLM	EQU	':'		;CHARACTER BETWEEN USER NUMBER AND FILE
USRFLG	EQU	'A'		;LIST $SYS AND $DIR FOR ALL USER NUMBERS
SYSFLG	EQU	'B'		;LIST $SYS AND $DIR
SOFLG	EQU	'S'		;LIST $SYS ONLY
;
; List and Typ INDICATING USER COMMAND
	ENDIF	
;
; END OF CUSTOMIZATION SECTION
;
ETX	EQU	03H
BELL	EQU	07H
BS	EQU	08H
TAB	EQU	09H
LF	EQU	0AH
FF	EQU	0CH
CR	EQU	0DH
;
WBOOT	EQU	BASE+0000H	;CP/M WARM BOOT ADDRESS
UDFLAG	EQU	BASE+0004H	;USER NUMBER IN HIGH NIBBLE, DISK IN LOW
BDOS	EQU	BASE+0005H	;BDOS FUNCTION CALL ENTRY POINT
TFCB	EQU	BASE+005CH	;DEFAULT FCB BUFFER
TBUFF	EQU	BASE+0080H	;DEFAULT DISK I/O BUFFER
TPA	EQU	BASE+0100H	;BASE OF TPA
;
;
;**** Section 0 ****
;
	.Z80
	ASEG
	ORG	100H
;
; LOAe command customization equates
;
NLINES	EQU	20		;NUMBER OF LINES ON CRT PAGE
NLINEP	EQU	60		;NUMBER OF LINES ON LIST DEVICE
FFKILL	EQU	TRUE		;TRUE SUPPRESSES FF UNTIL FIRST CHARACTER
PGDFLG	EQU	'P'		;TYPE AND LIST COMMAND DEFAULT TOGGLE
NOSTAT	EQU	FALSE		;SET TO TRUE IF BIOS LISTST NOT IMPLEMENTED
;
; Other customization equates
;
BUFLEN	EQU	80		;SIZE OF COMMAND INPUT BUFFER 
MAXUSR	EQU	15		;MAXIMUM USER NUMBER ACCESSIBLE
DEFUSR	EQU	0		;DEFAULT USER NUMBER FOR COM FILES
SPRMPT	EQU	'$'		;CPR PRDER FOR TEST PURPOSES
;   ALLOWS ONE TO EXECUTE ZCPR AS A .COM FILE
;
	IF	COMLD OR TEST
	LD	HL,BGNXFR
	LD	DE,CPRLOC
	LD	BC,ENDLD-CPRLOC
	LDIR
	LD	BC,(UDFLAG)
	JP	CPRLOC
BGNXFR	EQU	$
	ENDIF
;
	.PHASE	CPRLOC
;
;  ENTRY POINTS INTO ZCPR
;
;    If the ZCPR is entered at location CPRLOC (at the JUMP to CPR), then
; the default command in CIBUFF will be processed. If the ZCPR is entered
; at location CPRLOC+3 (at the JUMP to CPR1), then the default command in
; CIBUFF will NOT be processed.
;PUT COMMAND LINE AND DEFAULT COMMAND
;
;   The command line to be executed is stored here. This command line
; is generated in one of three ways:
;
;	(1) by the user entering it through the BDOS READLN function at
;	    the du> prompt [user input from keyboard].
;	(2) by the SUBMIT File Facility placing it there from a $$$.SUB
;	    file.
;	(3) by an external program or user placing the required command
;	    into this buffer.
;
;   In all cases, the command line is placed into the buffer starti
;    NOTE: Entry into ZCPR in this way is permitted under ZCPR Version 4.0,
; but in order for this to work, CIBUFF and CBUFF MUST be initialized properly
; AND the C register MUST contain a valid User/Disk Flag (see Location 4: the
; most significant nibble contains the User Number and the least significant
; nibble contains the Disk Number.)
;
;    Some user programs (such as SYNONYM3) attempt to use the default
; command facility. Under the original CPR, it was necessary to initialize
; a pointng at
; CIBUFF. This line contains the last character but NOT the Carriage
; Return, and the count is of all characters in the command line up to and
; including the last character. This count is placed into location CBUFF
; (immediately before the command line at CIBUFF.) If ZCPR is entered via
; CPRLOC, the command line is then parsed, interpreted, and the indicated
; command is executed. ZCPR places the terminating zero after the command
; and CIBPTR is properly initialized.
;
;   WARNING: The cer located at the end of the command buffer to point to the first
; byte in the command buffer. Under Version 4.x of ZCPR, this is no longer
; the case. This pointer, CIBPTR (Command Input Buffer PoinTeR), has been
; moved and the former location is now reserved for the stack. ZCPR
; Version 4.x automatically initializes CIBPTR in all cases.
;
ENTRY:
	JP	CPR		; Process potential default command
	JP	CPR1		; Do NOT process potential default command
;
;**** Section 1 ****
;
; BUFFERS ET AL
;
; INommand line must NOT exceed BUFLEN characters in length.
; For user programs which load this command, the value of BUFLEN can be
; obtained by examining the byte at CPRLOC+6.
;
; It is now possible to place multiple commands on one line. Each command
; is separated from its neighbor by a ";". This feature only works for ZCPR
; commands and programs that return to ZCPR via a RET instruction. Any
; warm boot reloads ZCPR and destroys the contents of the command buffer.
; The multiple command feature mAP
FCBCR:	DEFS	1		;CURRENT RECORD NUMBER
;
; Type and List Variables
;
CHRCNT:	DEFS	1		;CHARACTER COUNT FOR TYPE AND LIST
LNCNT:	DEFS	1		;LINE COUNT FOR TYPE AND LIST
TYPLST:	DEFS	1		;FLAG FOR TYPE OR LIST
TABCNT:	DEFS	1		;TAB COUNT FOR TYPE AND LIST
SYSTST:	DEFB	0		;LIST SYSTEM FILES IN DIRECTORY FLAG
;
; General Variables
;
CIBPTR:	DEFW	CIBUFF		;POINTER TO COMMAND INPUT BUFFER
CIPTR:	DEFW	CIBUFF		;POINTER TO CURRENT CMD FOR ERROR REPORTING
TMPUSR:	DEFB	0		;TEMPORARY USER NUMBER
TDRIVE:	DEFay be turned off with the SCL command.
;
MBUFF:	DEFB	BUFLEN		;MAXIMUM BUFFER LENGTH
CBUFF:	DEFB	0		;NUMBER OF CHARACTERS IN COMMAND LINE
CIBUFF:	DEFB	'             '	;DEFAULT (COLD BOOT) COMMAND
	DEFB	0		;COMMAND STRING TERMINATOR
	DEFB	'  ZCPR-D&J of 5 March 1994  '
	DEFB	0		;TERMINATOR FOR DUMP IDENTIFICATION
	DEFS	BUFLEN-($-CIBUFF)+1
	DEFW	0		;SENTINEL FOR STACK END
	DEFS	24		;STACK AREA
STACK	EQU	$		;TOP OF STACK
;
; SUBMIT FILE CONTROL BLOCK
;
SUBDN:	DEFB	1		;DISK DRIVE (A: CONTAINS $$$.B	0		;DEFAULT DRIVE
DFUSR:	DEFB	DEFUSR		;DEFAULT USER
LDADR:	DEFW	TPA		;MEMORY LOAD ADDRESS
;
; CPR BUILT-IN COMMAND TABLE
;   EACH ENTRY IS COMPOSED OF THE BIT 7 TERMINATED COMMAND AND 2-BYTE ADDRESS
;
CMDTBL:
	DC	'DIR'
	DEFW	DIR
	DC	'LIST'
	DEFW	LIST
	DC	'TYPE'
	DEFW	TYPE
	DC	'USER'
	DEFW	USER
	DC	'DFU'
	DEFW	DFU
	DC	'PAGE'
	DEFW	EJECT
	DC	'BELL'
	DEFW	RING
	DC	'SAK'
	DEFW	SAK
	DC	'GO'
	DEFW	GO
	DC	'ERA'
	DEFW	ERA
	DC	'ERAQ'
	DEFW	ERAQ
	DC	'SAVE'
	DEFW	SAVE
	DC	'REN'
	DEFWSUB)
SUBFN:	DEFB	'$$$     '	;FILE NAME
SUBFT:	DEFB	'SUB'		;FILE TYPE
SUBEX:	DEFB	0		;EXTENT NUMBER
SUBS1	EQU	SUBDN+13	;S1
SUBS2	EQU	SUBDN+14	;S2
SUBRC	EQU	SUBDN+15	;RECORD COUNT
SUBDM	EQU	SUBDN+16	;DISK GROUP MAP
SUBCR	EQU	SUBDN+32	;CURRENT RECORD NUMBER
;
; COMMAND FILE CONTROL BLOCK
;
FCBDN:	DEFS	1		;DISK DRIVE
FCBFN:	DEFS	8		;FILE NAME
FCBFT:	DEFS	3		;FILE TYPE
FCBEX:	DEFS	1		;EXTENT NUMBER
FCBS1:	DEFS	1		;S1
FCBS2:	DEFS	1		;S2
FCBRC:	DEFS	1		;RECORD COUNT
FCBDM:	DEFS	16		;DISK GROUP M	REN
	DC	'GET'
	DEFW	GET
	DC	'JUMP'
	DEFW	JUMP
	DC	'PEEK'
	DEFW	PEEK
	DC	'POKE'
	DEFW	POKE
NCMNDS	DEFL	17		;NUMBER OF COMMANDS
;
	IF	MULTPL
	DC	'SCL'
	DEFW	SINGLE
NCMNDS	DEFL	NCMNDS+1
	ENDIF
;
	IF	REBOOT
	DC	'BOOT'
	DEFW	BOOT
NCMNDS	DEFL	NCMNDS+1
	ENDIF	
;
;
;**** Section 2 ****
; CPR STARTING POINTS
;
; START CPR AND DON'T PROCESS DEFAULT COMMAND STORED
;
CPR1:
	XOR	A		;SET NO DEFAULT COMMAND
	LD	(CBUFF),A
;
; START CPR AND POSSIBLY PROCESS DEFAULT COMMAND
;
CPR:
	LD	SP,
;
	CALL	ADVAN		;GET ANY CHARACTER
	JR	Z,RESTRT	;NONE, END OF LINE
	LD	(CIPTR),DE	;UPDATE START OF LINE IN CASE ERROR
	INC	DE		;NOT END OF LINE, MUST BE DELIMITER
	LD	(CIBPTR),DE	;SAVE POINTER
;
	IF	MULTPL
	LD	HL,NEWCMD	;COMMAND?
	CP	(HL)
RS4:
	JP	NZ,ERROR	;NO
	CALL	ADVAN		;STEP OVER DELIMITER
	JR	RS3
	ELSE
RS4:
	JP	ERROR
	ENDIF
;
;
;**** Section 3 ****
; I/O UTILITIES
;
; OUTPUT <CRLF>
;
CRLF:
	CALL	PRINT		;PRINT STRING
	DEFB	CR,LF+80H
	RET
;
; PRINT STRING POINTED TO BY RET STACK	;MAKE SURE WE HAVE A VALID STACK
	LD	A,C		;C=USER/DISK NUMBER (SEE LOC 4)
	RRA			;EXTRACT USER NUMBER
	RRA	
	RRA	
	RRA	
	AND	0FH
	LD	(TMPUSR),A	;SET USER NUMBER
	LD	A,C		;GET DISK NUMBER (SEE LOC 4)
	AND	0FH		;EXTRACT DEFAULT DISK DRIVE
	LD	(TDRIVE),A	;SAVE DEFAULT DRIVE
	LD	C,0DH		;RESET DISK SYSTEM
	CALL	BDOS
	LD	(SUBFLG),A	;SAVE SUBMIT FLAG CLUE
	DEFB	0F6H		;SET NZ FLAG (OR A,n)
;
; PROMPT USER AND PROCESS INPUT COMMAND
;
RESTRT:
	XOR	A		;SET ZERO FLAG
	LD	SP,STACK	;RESET STACK
ADR; START WITH <CRLF>
;
PRINTC:
	CALL	CRLF		;NEW LINE
;
; PRINT STRING POINTED TO BY RET ADR
;
PRINT:
	EX	(SP),HL		;GET POINTER TO STRING
	CALL	PRINTS
	EX	(SP),HL		;RESTORE HL AND RETURN ADDRESS
	RET
;
; PRINT STRING POINTED TO BY HL
;
PRINT1:
	CALL	CONOUT		;PRINT CHARACTER
PRINTS:
	LD	A,(HL)		;GET NEXT BYTE
	INC	HL		;POINT TO NEXT BYTE
	AND	A		;TEST FOR 0 OR BIT 7 SET
	RET	Z		;DONE
	JP	P,PRINT1	;NOT LAST CHARACTER
;
; OUTPUT CHARACTER IN A REG
;
CONOUT:
	PUSH	BC
	PUSH	DE
	LD	C
;
; PROCESS INPUT LINE
;
	CALL	REDBUF		;CAPITALIZE, NULL TERMINATE, SKIP SPACES
RS3:
	CP	COMCHR		;COMMENT?
	JR	Z,RESTRT	;YES, SKIP REST OF LINE
	CALL	SCANER		;PARSE COMMAND NAME FROM COMMAND LINE
	JR	NZ,RS4		;ERROR IF NAME CONTAINS A "?"
	CALL	DEFDMA		;SET TBUFF TO DMA ADDRESS
	CALL	DLOGIN		;ASSURE PROPER DRIVE
	CALL	RSTUSR		;ASSURE PROPER USER NUMBER
	CALL	SETUDB		;SET UD BYTE TO MATCH USER/DRIVE
	CALL	CMDSER		;SCAN FOR CPR-RESIDENT COMMAND
;
; ENTRY POINT FOR CONTINUED SCAN OF COMMAND LINE,02H
	RES	7,A		;STRIP MSB IN CASE SET FOR EOS
	LD	E,A
	JR	BDOSDE
;
; GET CHARACTER FROM CONSOLE AND CHECK FOR ^C
;
BREAK:
	PUSH	BC
	LD	C,0BH		;CONSOLE STATUS CHECK
	CALL	BDOSJP
	LD	C,01H		;GET CHARACTER FROM CON: WITH ECHO
	CALL	NZ,BDOSJP	;GET CHARACTER
	POP	BC
	RET	Z		;NO CHARACTER
CHKETX:
	CP	ETX		;^C?
	RET	NZ	 	;NO
ABORT:
	CALL	SUBKIL		;KILL ANY SUBMIT
	JR	RESTRT		;AND RESTART
;
; BDOS FUNCTIONS
;
READF:
	LD	DE,FCBDN	;FALL THRU TO READ
READ:
	LD	C,14H
	DEFB	3AH		;SKIP NEXT TWODOSEA		;SAVE SOME CODE SPACE
NEWUSR:
	LD	(TMPUSR),A	;SET NEW USER NUMBER
RSTUSR:
	LD	A,(TMPUSR)	;RESET TEMPORARY USER
SETUSR:
	LD	C,20H		;GET/SET USER NUMBER (GET IF E=FFH)
BDOSEA:
	LD	E,A		;STUFF PARAMETER INTO REG E
BDOSJP:
	PUSH	BC
BDOSBC:
	PUSH	DE		; zcpr does not use any BDOS calls that
BDOSDE:
	PUSH	HL		; return a value in HL. Those HL calls
	CALL	BDOS		; are:
	POP	HL		;   get active drive - #24
	POP	DE		;   get allocation vector - #27
	POP	BC		;   get read-only map - #29
	AND	A		;  BYTES
WRITE:
	LD	C,15H		;FALL THRU TO BDOS CALL
	JR	BDOSJP
DEFDMA:
	LD	DE,TBUFF	;TBUFF = DEFAULT ADDRESS
DMASET:
	LD	C,1AH		;SET DMA ADDRESS
	JR	BDOSJP
SEARF:
	LD	DE,FCBDN	;SPECIFY FCB
SEARDE:
	LD	C,11H		;SEARCH FOR FILE
	DEFB	3AH		;SKIP NEXT TWO BYTES
SEARN:
	LD	C,12H		;SEARN IGNORES DE AND USES THE PREVIOUS
	JR	BDOSFN		;VALUE FROM THE LAST BDOS CALL
OPENF:
	XOR	A
	LD	(FCBCR),A
	LD	DE,FCBDN	;FALL THRU TO OPEN
OPEN:
	LD	C,0FH		;OPEN FILE
	DEFB	3AH		;SKIP NEXT TWO BYTES 
CLOSE:
	LD	  get disk parameters - #31
	RET
;
;
;**** Section 4 ****
; CPR UTILITIES
;
; PRINT PROMPT (DU>)
;
PROMPT:
	CALL	CRLF		;PRINT PROMPT
	LD	A,(TDRIVE)	;CURRENT DRIVE IS PART OF PROMPT
	ADD	A,'A'		;CONVERT TO ASCII A-P
	CALL	CONOUT
	LD	A,(TMPUSR)	;GET USER NUMBER
;
	IF	SUPRES		;IF SUPPRESSING USER # REPORT FOR USER 0
	AND	A
	JR	Z,PRPT1		;ZERO, SUPRESS
	ENDIF	
;
PRUSRN:
	ADD	A,0		;CONVERT HEX TO BCD
	DAA
	PUSH	AF		;SAVE UNITS DIGIT
	AND	0F0H
	LD	A,'1'
	CALL	NZ,CONOUT	;PRINT IF OVER 10
C,10H		;CLOSE FILE
	DEFB	3AH		;SKIP NEXT TWO BYTES
CREATE:
	LD	C,16H		;CREATE FILE
BDOSFN:
	CALL	BDOSJP
	INC	A		;SET ERROR RETURN FLAG
	RET
SUBKIL:
	LD	HL,SUBFLG	;ABORT SUBMIT FILE
	LD	A,(HL)		;SUB FILE IN EXECUTION?
	AND	A
	RET	Z		;NO
	LD	(HL),0		;KILL SUB FILE EXECUTION FLAG
	LD	DE,SUBDN	;DELETE $$$.SUB
DELETE:
	LD	C,13H		;DELETE FILE
	JR	BDOSJP		;SAVE MORE SPACE
TLOGIN:
	LD	(TDRIVE),A	;SAVE NEW DEFAULT DRIVE
DLOGIN:
	LD	A,(TDRIVE)	;LOG IN DEFAULT DRIVE
	LD	C,0EH		;SELECT DISK
	JR	B
	POP	AF
	OR	'0'		;OUTPUT 1'S DIGIT (CONVERT TO ASCII)
	CALL	CONOUT
PRPT1:
	JP	PRINT		;GO PRINT PROMPT CHARACTER
;
; INPUT NEXT COMMAND TO CPR
;
;	This routine determines if a SUBMIT file is being processed
; and extracts the command line from it if so or from the user's console.
; This routine also invokes the DU> prompt.
;
REDBUF:
	JR	NZ,CNVBUF	;PROCESS DEFAULT COMMAND IF ANY
RD0:
	CALL	DEFDMA		;SELECT TBUFF FOR READ
	XOR	A		;SELECT USER 0 FOR SUBMIT SEARCH
	CALL	SETUSR
	LD	DE,SUBDN	;OPEASE $$$.SUB
RB2:
	CALL	PROMPT		;PRINT PROMPT
	DEFB	CPRMPT+80H
	LD	C,0AH		;READ COMMAND LINE FROM USER
	LD	DE,MBUFF
	CALL	BDOS
;
; CAPITALIZE STRING (ENDING IN 0) IN CBUFF AND SET POINTER FOR PARSING
;
CNVBUF:
	LD	HL,CBUFF	;POINT TO USER'S COMMAND BUFFER
	LD	A,(HL)		;ANY CHARACTERS IN BUFFER?
	AND	A
	JR	Z,RD0	 	;NO, FILL BUFFER
	INC	HL
	LD	(CIBPTR),HL	;INITIALIZE COMMAND LINE POINTER
	LD	B,A		;INITIALIZE CHARACTER COUNTER
CB1:
	LD	A,(HL)		;CAPITALIZE COMMAND CHARACTER
	CALL	UCASE
	LD	(HLN $$$.SUB
SUBFLG	EQU	$+1		;IN LINE SUBMIT FLAG
	LD	A,0		;SUBMIT IN PROGRESS?
	AND	A
	CALL	NZ,OPEN		;CALL OPEN IF SUBMIT IN PROGRESS
	JR	Z,RB2		;NONE FOUND SO GET COMMAND LINE
	LD	A,(SUBRC)	;GET VALUE OF LAST RECORD IN FILE
	DEC	A		;POINT TO NEXT TO LAST RECORD
	LD	(SUBCR),A	;SAVE NEW VALUE OF LAST RECORD IN $$$.SUB
	CALL	READ		;DE=SUBDN
	JR	NZ,RB1		;ABORT $$$.SUB IF ERROR IN READING LAST REC
	LD	HL,SUBS2	;POINT TO S2 OF $$$.SUB FCB
	LD	(HL),A		;SET S2 TO ZERO
	INC	HL		;POINT TO RECORD COUNT
	D),A
	INC	HL		;POINT TO NEXT CHARACTER
	DJNZ	CB1		;CONTINUE TO END OF COMMAND LINE
	LD	(HL),B		;STORE ENDING <NULL>
;
; ADVANCE INPUT POINTER TO FIRST NON-BLANK AND FALL THROUGH TO SBLANK
;
ADVAN:
	LD	DE,(CIBPTR)
;
; SKIP STRING POINTED TO BY DE (STRING ENDS IN 0) UNTIL END OF STRING
;   OR NON-BLANK ENCOUNTERED (BEGINNING OF TOKEN)
;
SBLANK:
	LD	A,(DE)
	OR	A
	RET	Z
	CP	' '
	RET	NZ
	INC	DE
	JR	SBLANK
;
; CONVERT CHARACTER IN A TO UPPER CASE
;
UCASE:
	CP	61H		;LOWER-CASE A
	RET	C
	CEC	(HL)		;DECREMENT RECORD COUNT OF $$$.SUB
	PUSH	AF		;SAVE ZERO FLAG
	CALL	Z,SUBKIL	;KILL SUBMIT IF ZERO RECORDS LEFT
	POP	AF		;ELSE
	CALL	NZ,CLOSE	;JUST CLOSE FILE
	CALL	PROMPT		;PRINT SUBMIT PROMPT
	DEFB	SPRMPT+80H
	LD	HL,TBUFF+1	;PRINT COMMAND LINE FROM $$$.SUB
	CALL	PRINTS
	LD	HL,TBUFF	;MOVE COMMAND LINE TO COMMAND BUFFER	
	LD	DE,CBUFF
	LD	BC,BUFLEN
	LDIR
	CALL	BREAK		;CHECK FOR ABORT (ANY CHARACTER)
	JR	Z,CNVBUF	;NONE
;
; INPUT COMMAND LINE FROM USER CONSOLE
;
RB1:
	CALL	SUBKIL		;ERP	7BH		;GREATER THAN LOWER-CASE Z?
	RET	NC
	AND	5FH		;CAPITALIZE
	RET	
;
; CHECK TO SEE IF DE POINTS TO DELIMITER; IF SO, RET W/ZERO FLAG SET
;
SDELM:
	LD	A,(DE)
	OR	A		;0=DELIMITER
	RET	Z
	CP	' '		;ERROR IF < <SP>
	JP	C,ERROR
	RET	Z		;<SP> =DELIMITER
	CP	'.'		;"." =DELIMITER
	RET	Z
	CP	'['		;"[" =DELIMITER
	RET	Z
	CP	']'		;"]" =DELIMITER
	RET	Z
	CP	'>'		;">" =DELIMITER BUT GREATER NOT
	RET	NC
	CP	':'		;":"  ";"  "<"  "=" =DELIMITERS
	RET	C		;NO DELIMITER FOUND
	CP	A		;SET ZERO FLAG
R OVERFLOW
;   BASE 10 ASSUMED - MAXIMUM VALUE IS 255
;
A2NUM:
	LD	A,(DE)		;GET DIGIT
	SUB	'0'		;CONVERT TO BINARY (ASCII 0-9 TO BINARY)
	CP	10		;ERROR IF >= 10
	CCF			;FLIP CARRY
	RET	C
	LD	C,A		;DIGIT IN C
	LD	A,L		;NEW VALUE = OLD VALUE * 10
	RLCA			;*2
	RET	C		;ERROR
	RLCA			;*4
	RET	C		;ERROR
	ADD	A,L		;*5
	RET	C		;ERROR
	RLCA			;*10
	RET	C		;ERROR
	ADD	A,C		;NEW VALUE = OLD VALUE * 10 + DIGIT
	RET	C		;DON'T INC DE IF ERROR
	LD	L,A		;SET NEW VALUE
	INC	DE		;GOOD DIGIT
	RET
;
; 
	RET	

;
; ADD A TO HL (HL=HL+A)
;
ADDAH:
	ADD	A,L
	LD	L,A
	RET	NC
	INC	H
	RET	
;
; EXTRACT DECIMAL NUMBER FROM COMMAND LINE
;   RETURN WITH 8-BIT VALUE IN REG A AND 16-BIT VALUE IN HL
;   ALL REGISTERS MAY BE AFFECTED
;
NUMBER:
	CALL	SCANER		;PARSE NUMBER AND PLACE IN FCBFN
	LD	HL,FCBFN+10	;POINT TO END OF TOKEN FOR CONVERSION
	LD	B,11		;11 CHARACTERS MAX
;
; CHECK FOR SUFFIX FOR HEXADECIMAL NUMBER
;
NUMS:
	LD	A,(HL)		;GET CHARACTERS FROM END, SEARCHING FOR SUFFIX
	DEC	HL		;BACK UEXTRACT HEXADECIMAL NUMBER FROM COMMAND LINE
;   RETURN WITH 8-BIT VALUE IN REG A AND 16-BIT VALUE IN HL
;   ALL REGISTERS MAY BE AFFECTED
;
HEXNUM:
	CALL	SCANER		;PARSE NUMBER AND PLACE IN FCBFN
HNUM1:
	LD	HL,0		;HL=ACCUMULATED VALUE
	LD	DE,FCBFN	;POINT TO TOKEN FOR CONVERSION
HNUM2:
	LD	A,(DE)		;GET CHARACTER
	CP	' '		;DONE?
	JR	Z,NUM3		;RETURN IF SO
	CP	'H'		;DONE IF H SUFFIX
	JR	Z,NUM3
	SUB	'0'		;CONVERT TO BINARY
	CP	10		;0-9?
	JR	C,HNUM3
	SUB	17		;A-F?
	CP	6		;ERROR?
	JR	NC,ERROR
P
	CP	NUMBASE		;CHECK AGAINST BASE SWITCH FLAG
	JR	Z,HNUM1
	CP	' '		;SPACE?
	JR	NZ,NUM1		;CHECK FOR LAST DIGIT
	DJNZ	NUMS		;COUNT DOWN
;
; PROCESS DECIMAL NUMBER
;
NUM1:
	LD	HL,0		;CLEAR GRAND TOTAL
	LD	DE,FCBFN	;POINT TO BEGINNING OF TOKEN
NUM2:
	LD	A,(DE)		;GET CHARACTER
	CP	' '		;DONE IF <SP>
NUM3:
	LD	A,L		;TOTAL TO A IN CASE DONE
	RET	Z		;ALL DONE
	CALL	A2NUM		;CONVERT DIGIT
	JR	NC,NUM2		;NO ERROR
	JR	ERROR
;
; ASCII TO NUMERICAL CONVERSION
;   RETURNS WITH CARRY SET IF INVALID O	ADD	A,10
HNUM3:
	INC	DE		;POINT TO NEXT CHARACTER
	ADD	HL,HL		;LEFT SHIFT 4
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL
	OR	L		;MASK IN NEW LOW
	LD	L,A		;NEW LOW BYTE IN L
	JR	HNUM2
;
; GET THE REQUESTED USER NUMBER FROM THE COMMAND LINE AND VALIDATE IT.
;
USRNUM:
	CALL	NUMBER
	LD	E,A
	CP	MAXUSR+1
	RET	C
;
; INVALID COMMAND -- PRINT IT
;
ERROR:
	CALL	CRLF		;NEW LINE
	LD	HL,(CIPTR)	;POINT TO BEGINNING OF COMMAND LINE
ERR1:
	LD	A,(HL)		;GET CHARACTER
	CP	' '+1		;SIMPLE '?' IF <SP> OR LESS
	CAR),DE	;SET POINTER TO NON-BLANK OR END OF LINE
	JR	Z,SCAN3		;END OF COMMAND LINE
	SBC	A,'A'		;CONVERT POSSIBLE DRIVE SPEC TO NUMBER
	CP	16		;VALID DRIVE?
	INC	A		;CONVERT TO DRIVE (A=1, AND SO ON)
	JR	C,SCAN2		;YES
	XOR	A		;SELECT DEFAULT DRIVE
	DEC	DE		;DON'T MOVE TO NEXT CHARACTER
SCAN2:
	LD	H,A		;STORE NUMBER (A:=0, B:=1, ETC) IN H
	INC	DE		;POINT TO NEXT CHARACTER
	LD	L,0		;ZERO TOTAL
	CALL	A2NUM		;CONVERT FIRST DIGIT
	JR	C,SCAN3		;NOT VALID
	CALL	A2NUM		;CONVERT SECOND DIGIT
	LD	A,L
	SELL	NC,CONOUT	;PRINT COMMAND CHARACTER OR FALL THRU
	INC	HL		;POINT TO NEXT
	JR	NC,ERR1		;CONTINUE
	CALL	PRINT		;PRINT '?'
	DC	'?'
	JP	ABORT		;RESTART CPR
;
; POINT TO DIRECTORY ENTRY IN TBUFF WHOSE OFFSET IS SPECIFIED BY A AND C
;
DIRPTR:
	LD	HL,TBUFF	;POINT TO TEMP BUFFER
	ADD	A,C		;POINT TO 1ST BYTE OF DIR ENTRY
	CALL	ADDAH		;POINT TO DESIRED BYTE IN DIR ENTRY
	LD	A,(HL)		;GET DESIRED BYTE
	RET	
;
; CHECK FOR VALID USER AND LOG IN IF VALID
;
ULOGIN:
	LD	A,(FCBS1)	;GET USER NUMBER
ALOGIT	7,L		;MAKE VALID JUST IN CASE
	CP	MAXUSR+1	;TOO BIG?
	JR	C,SCAN3	 	;NO
	LD	A,(DE)		;ANY ':'?
	CP	':'
	JP	Z,NAMERR	;YES, NAME ERROR
SCAN3:
	LD	A,(DE)		;SEE IF LAST CHARACTER IS A COLON (:)
	INC	DE		;POINT TO BYTE AFTER ':'
	CP	':'
	JR	Z,SCAN4		;YES, WE HAVE A DRIVE SPEC
	LD	HL,0		;NOT VALID DRIVE SPEC, SWITCH TO DEFAULT
	LD	DE,(CIPTR)	;RESTART SCAN
;
; EXTRACT FILENAME FROM POSSIBLE FILENAME.TYP
;
SCAN4:
	LD	B,H		;MOVE DRIVE TO B
	EX	(SP),HL		;GET BACK FCB POINTER AND SAVE USER NUMBER
	LN:
	ADD	A,80H		;VALID?
	CALL	P,SETUSR	;SET IF VALID
	RET
;
; EXTRACT TOKEN FROM COMMAND LINE AND PLACE IT INTO FCBDN;
;   FORMAT FCBDN FCB IF TOKEN RESEMBLES FILE NAME AND TYPE (FILENAME.TYP);
;   ON INPUT, CIBPTR PTS TO CHARACTER AT WHICH TO START SCAN;
;   ON OUTPUT, CIBPTR PTS TO CHARACTER AT WHICH TO CONTINUE AND ZERO FLAG IS
;     RESET IF '?' IS IN TOKEN
;
SCANER:
	LD	HL,FCBDN	;POINT TO FCBDN
SCAN1:
	PUSH	HL		;SAVE POINTER TO FCB
	CALL	ADVAN		;SKIP TO NON-BLANK OR END OF LINE
	LD	(CIPTD	(HL),B		;SAVE DRIVE
	LD	B,8	 	;MAX OF 8 CHARACTERS
	XOR	A		;CLEAR '?' COUNT
	EX	AF,AF		;AND SAVE
	CALL	SCANF		;GET POSSIBLE NAME
	CALL	SCANT		;AND POSSIBLE TYPE
;
; FILL IN EX, S1, S2, AND RC
;
	XOR	A
	INC	HL		;POINT TO NEXT BYTE IN FCBDN
	LD	(HL),A		;ZERO EX
	INC	HL
	POP	BC		;GET BACK USER NUMBER
	LD	(HL),C		;STUFF AWAY USER NUMBER IN S1
	INC	HL	
	LD	(HL),A		;ZERO S2
	INC	HL
	LD	(HL),A		;ZERO RC
;
; SCAN COMPLETE -- DE POINTS TO DELIMITER BYTE AFTER TOKEN
;
	LD	(CIBPTR),DE
	EX	AF,A;
; CMDTBL (COMMAND TABLE) SCANNER
;   JUMPS TO ADDRESS OF COMMAND IF CPR-RESIDENT
;   JUMPS TO COM IF NOT CPR-RESIDENT COMMAND
;
CMDSER:
	LD	A,(FCBFN)	;ANY COMMAND?
	CP	' '		;' ' MEANS COMMAND WAS 'D:' TO SWITCH
	LD	A,(FCBS1)	;GET USER NUMBER IF ANY
	LD	HL,FCBDN	;POINT TO DRIVE
	JR	NZ,CMS0		;NOT <SP>, SO MUST BE COMMAND
	ADD	A,80H		;CONVERT TO USER NUMBER
	CALL	P,NEWUSR	;SET IF VALID USER IN FCB
	LD	A,(HL)	 	;LOOK FOR DRIVE SPEC
	DEC	A		;ADJUST FOR LOG IN
	CALL	P,TLOGIN	;LOG IN DRIVE
SETUDBF		;GET NUMBER OF '?' IN FILENAME.TYP
	RET	
;
; EXTRACT FILE TYPE FROM POSSIBLE FILENAME.TYP
;
SCANT:
	LD	B,3		;PREPARE TO EXTRACT TYPE
	CP	'.'		;IF (DE) DELIMITER IS A '.', WE HAVE A TYPE
	JR	NZ,SCAN11	;FILL FILE TYPE WITH <SP>
	INC	DE		;POINT TO CHARACTER IN COMMAND LINE AFTER '.'
SCANF:
	LD	C,' '		;FILL CHARACTER
SCAN11:
	INC	HL		;STEP TO NEXT BYTE IN FCBN
	CALL	SDELM		;CHECK FOR DELIMITER
	JR	Z,SCAN12	;FILL REST WITH FILL BYTE IF A DELIMITER
	CP	'*'		;WILD?
	JR	NZ,SCAN13	;NO
	LD	C,'?'	:
	LD	A,(TMPUSR)	;GET CURRENT USER NUMBER
	ADD	A,A		;PLACE IT IN HIGH NIBBLE
	ADD	A,A
	ADD	A,A
	ADD	A,A
	LD	HL,TDRIVE	;ADD DEFAULT DRIVE NUMBER (LOW NIBBLE)
	OR	(HL)
	LD	(UDFLAG),A	;UPDATE USER/DRIVE BYTE
	RET
CMS0:
	OR	(HL)		;DRIVE OR USER NUMBER
	JR	NZ,CMS5		;YES, CAN'T BE BUILT IN COMMAND
	LD	HL,CMDTBL	;POINT TO COMMAND TABLE
	LD	B,NCMNDS	;SET COMMAND COUNTER
CMS1:
	LD	DE,FCBFN	;POINT TO STORED COMMAND NAME
CMS2:
	LD	A,(DE)		;COMPARE AGAINST TABLE ENTRY
	XOR	(HL)
	ADD	A,A
	JR	NZ,CMS3	;CHANGE FILL BYTE TO '?'
SCAN12:
	DEC	DE		;DON'T STEP OFF CURRENT SYMBOL
	LD	A,C		;GET FILL BYTE
SCAN13:
	CP	'?'		;QUESTION MARK?
	JR	NZ,SCAN14	;NO, JUST STORE CHARACTER
	EX	AF,AF		;GET QUESTION MARK COUNT
	INC	A		;COUNT IT
	EX	AF,AF		;AND SAVE COUNT
SCAN14:
	INC	DE		;POINT TO NEXT CHARACTER IN COMMAND LINE
	LD	(HL),A		;STORE CHARACTER IN FCBDN
	DJNZ	SCAN11		;COUNT DOWN CHARACTERS IN FILE TYPE (3 MAX)
SCAN15:
	CALL	SDELM		;SKIP REST OF CHARACTERS TO
	RET	Z		;DELIMITER
	INC	DE
	JR	SCAN15
		;NO MATCH
	INC	DE		;POINT TO NEXT CHARACTER
	INC	HL
	JR	NC,CMS2		;NOT END OF TABLE ENTRY
	LD	A,(DE)		;NEXT CHARACTER IN INPUT COMMAND MUST BE <SP>
	CP	' '
	JR	NZ,CMS4
	LD	A,(HL)		;FOUND COMMAND,
	INC	HL		;LOAD ADDRESS,
	LD	H,(HL)		;AND
	LD	L,A		;JUMP TO IT
	JP	(HL)		;COMMAND IS CPR-RESIDENT
CMS3:
	BIT	7,(HL)		;END OF TABLE ENTRY?
	INC	HL
	JR	Z,CMS3		;NO
CMS4:
	INC	HL		;SKIP ADDRESS
	INC	HL
	DJNZ	CMS1		;NOT TO END OF TABLE YET
CMS5:
	JP	COM		;COMMAND MAY BE DISK-RESIDENT
;
;**** SectD	A,B
	;DROP INTO DIRPR TO PRINT DIRECTORY
	;THEN RESTART CPR
;
; DIRECTORY PRINT ROUTINE; ON ENTRY, A IS 80H IF SYSTEM FILES EXCLUSIVELY
;
DIRPR:
	LD	D,A		;STORE SYSTEM FLAG IN D
	LD	A,B		;SAVE SYSTST
	LD	(SYSTST),A
	XOR	A		;SET COLUMN COUNTER TO 0
	LD	B,A		;AND USER NUMBER JUST IN CASE
DIRPR1:
	ADD	A,03H		;FORCE CRLF
	AND	0FCH
	LD	E,A
	PUSH	DE	
	INC	D		;ALL USER NUMBERS?
	PUSH	BC		;SAVE USER NUMBER
	LD	A,B		;AND
	CALL	Z,SETUSR	;SET IF ALL USER NUMBERS
	CALL	SEARF		;SEARCH FOR SPECIFIEion 5 ****
; CPR-Resident Commands
;
;
;Section 5A
;Command: DIR
;Function: To display a directory of the files on disk.
;Forms:
;	DIR <afn>	Display the DIR files
;	DIR <afn> S	Display the SYS files
;	DIR <afn> B	Display both DIR and SYS files
;	DIR <afn> A	Display both DIR and SYS files for all user numbers
;
DIR:
	CALL	SCANER		;EXTRACT POSSIBLE D:FILENAME.TYP TOKEN
	CALL	ULOGIN		;LOG ANY USER
	LD	HL,FCBFN	;MAKE FCB WILD (ALL '?') IF NO FILENAME.TYP
	LD	A,(HL)		;GET FIRST CHARACTER OF FILED FILE (FIRST OCCURRENCE)
DIRPR2:
	POP	BC		;GET BACK USER NUMBER
	POP	DE		;AND SYSTEM FLAG
	JR	NZ,DIRPR4	;FILE FOUND
	LD	A,B		;AT LAST USER NUMBER?
	INC	B		;STEP TO NEXT USER NUMBER
	CP	MAXUSR
	LD	A,E		;IN CASE DONE
	JR	NC,DIRPR3	;DONE
	LD	E,D		;EITHER WAY, E IS GOING TO BE CHANGED
	INC	E
	JR	Z,DIRPR1	;PRINT ALL USER NUMBERS
DIRPR3:
	AND	A		;ANY PRINTED?
	JP	CHKFND		;GO CHECK
;
; ENTRY SELECTION LOOP; ON ENTRY, A=OFFSET FROM SEARF OR SEARN
;
DIRPR4:
	DEC	A		;ADJUST TO RETURNED VALUE
	RRNAME.TYP
	CP	' '		;IF <SP>, ALL WILD
	JR	NZ,DIR2
	LD	B,11		;NUMBER OF CHARACTERS IN FN & FT
DIR1:
	LD	(HL),'?'	;STORE '?'
	INC	HL
	DJNZ	DIR1
DIR2:
	CALL	ADVAN		;LOOK AT NEXT INPUT CHARACTER
	LD	B,0FFH		;LOAD ALL FILES FLAG
	CP	USRFLG		;ALL FILES ON DISK?
	JR	Z,DIR4		;YES
	LD	B,80H		;IN CASE SYS ONLY
	CP	SOFLG		;SYS ONLY?
	JR	Z,DIR4		;YES
	CP	SYSFLG		;HAVE SYSTEM SPECIFIER?
	LD	A,B		;SET SYSTEM BIT EXAMINATION
	LD	B,0		;SYSTEM TOKEN DEFAULT
	JR	NZ,DIRPR
DIR4:
	INC	DE
	LD	(CIBPTR),DE
	LCA			;CONVERT NUMBER TO OFFSET INTO TBUFF
	RRCA	
	RRCA	
	LD	C,A		;OFFSET INTO TBUFF IN C (C=OFFSET TO ENTRY)
	LD	A,10		;ADD 10 TO POINT TO SYSTEM FILE ATTRIBUTE BIT
	CALL	DIRPTR
	PUSH	DE
	AND	D		;MASK FOR SYSTEM BIT
	INC	D		;ALL FILES?
	JR	Z,DIRPR5	;YES
	LD	HL,SYSTST	;SYSTEM FILE?
	CP	(HL)
	JR	NZ,DIRPR9	;NO
DIRPR5:
	LD	A,E		;WHAT TO PRINT
;
	IF	TWOCOL
	AND	01H		;OUTPUT <CR><LF> IF 2 ENTRIES PRINTED IN LINE
	ELSE	
;
	AND	03H		;OUTPUT <CR><LF> IF 4 ENTRIES PRINTED IN LINE
	ENDIF	
;
	CAL
	INC	HL		;STEP TO NEXT CHARACTER
	CP	C		;EAT SPACES?
	CALL	NZ,CONOUT
	DJNZ	PRFN1
	POP	BC
	RET	
;
;Section 5B
;Command: ERA
;Function: To erase files; names of the erased files are displayed.
;Forms:
;	ERA <afn>
;
ERA:
	CALL	SCANER		;PARSE FILE SPECIFICATION
	CP	11		;ALL WILD (ALL FILES = 11 '?')?
	JR	NZ,ERA1		;IF NOT, THEN DO ERASES
	CALL	REPLY
	JP	NZ,RESTRT	;RESTART CPR IF NOT
ERA1:
	CALL	ULOGIN		;LOG ANY USER
	XOR	A		;PRINT ALL FILES (EXAMINE SYSTEM BIT)
	LD	B,A		;NO SYS-ONLY OPT TL	Z,CRLF		;NEWLINE ALWAYS RETURNS ZERO TRUE
	JR	Z,DIRPR6
	CALL	PRINT
;
	IF	WIDE
	DEFB	'  '		;2 SPACES
	DEFB	FENCE		;THEN FENCE CHARACTER
	DC	'  '	 	;THEN 2 MORE SPACES
	ELSE	
;
	DEFB	' '		;SPACE
	DEFB	FENCE		;THEN FENCE CHARACTER
	DC	' '		;THEN SPACE
	ENDIF	
;
DIRPR6:
	POP	DE
	INC	E		;BUMP NUMBER OF FILES LISTED
	PUSH	DE
	INC	D		;PRINT WITH USER NUMBER?
	JR	NZ,DIRPR8	;NO
	LD	A,B		;GET USER NUMBER AND
	CALL	PRUSRN		;AND PRINT
	DEFB	USRDLM+80H	;USER NUMBER DELIMITER
DIRPR8:
	XOR	A		;DO DIRPR
	CALL	DIRPR		;PRINT DIRECTORY OF ERASED FILES
ERA2:
	LD	DE,FCBDN	;DELETE FILE SPECIFIED
	JP	DELETE		;REENTER CPR VIA DELETE
;
;Section 5C
;Command: ERAQ
;Function: To erase files with individual query.
;Forms:
;	ERAQ <afn>
;	<afn>? Y
;	  :
;	  :
;
ERAQ:
	CALL	SCANER		; parse file specification
	CALL	ULOGIN		; log any user
	LD	HL,01FFH	; load first flag
ERAQ1:
	CALL	SEARF		; find first entry
	JR	NZ,ERAQ2	; found one
	INC	L		; ever found any?
;
; Check for File Found
;
CHKFNDON'T EAT SPACES
	CALL	PRFN
DIRPR9:
	PUSH	BC
	CALL	SEARN		;GET NEXT FILENAME
	JR	DIRPR2
PRFN:
	PUSH	BC
	LD	B,A		;SAVE EAT SPACES FLAG
	LD	A,1
	CALL	DIRPTR		;HL NOW POINTS TO 1ST BYTE OF FILE NAME
	LD	C,B		;SAVE EAT SPACES FLAG
	LD	B,12		;12 CHARACTER TOTAL
PRFN1:
	LD	A,B		;CHECK FOR FILE TYPE
	CP	04H
	LD	A,(HL)
	RES	7,A
	JR	NZ,PRFN2	;NOT YET AT TYPE
	DEC	HL		;ADJUST HL FOR TYPE DELIMITER
	CP	' '		;NO FILE TYPE?
	JR	Z,PRFN2		;CONTINUE IF SO
	LD	A,'.'		;FILE TYPE EXISTS, PRINT DOT
PRFN2::
	RET	NZ		; yes
;
; No File Error Message
;
PRNNF:
	CALL	PRINTC		;NO FILE MESSAGE
	DC	'No File'
	RET	
ERAQ2:
	LD	L,H		; restart found count
ERAQ3:
	DEC	H		; at file to erase?
	JR	NZ,ERAQ5	; no
	INC	H		; reset H to 1
	INC	L		; step count in case don't delete
	PUSH	HL		; save flag first
	DEC	A		; compute offset
	RRCA	
	RRCA	
	RRCA	
	LD	C,A
	CALL	CRLF
	LD	A,' '		; eat spaces
	CALL	PRFN		; print file name
	CALL	REPLY1		; prompt
	JR	NZ,ERAQ4	; reply not 'Y'
	XOR	A
	CALL	DIRPTR		; getng
;
LIST:
;
	IF	FFKILL
	LD	HL,NLINEP+0580H	; lines/page, first ff and list flags
	ELSE	
	LD	HL,NLINEP+0500H	; lines/page and list flag
	ENDIF	
;
	JR	TYPE1
;
;Section 5G
;Command: TYPE
;Function: To display specified file on console.
;Forms:
;	TYPE <ufn>	Display file
;	TYPE <ufn> P	Display file without default paging
;
TYPE:
;
	IF	FFKILL
	LD	HL,NLINES+0280H	; lines/page, first ff and type flags
	ELSE	
	LD	HL,NLINES+0200H	; lines/page and type flag
	ENDIF	
;
TYPE1:
	LD	(LNCNT),HL	 FCB to delete
	LD	A,(FCBDN)	; get drive specification
	LD	(HL),A		; select drive
	EX	DE,HL
	CALL	DELETE		; go delete
	POP	HL		; get flags
	DEC	L		; reduce count since file deleted
	LD	H,L		; update next file to process
	JR	ERAQ1		; and restart process
ERAQ4:
	POP	HL		; get count
ERAQ5:
	CALL	SEARN		; find next file
	JR	NZ,ERAQ3	; more files, go ask
	RET			; done
;
;Section 5D
;Command: SAK
;Function: To pause until a key is struck; ^C warm boots.
;Forms:
;	SAK
;	? <any key>
;
SAK:
	; save list/type flag and line cnt
	XOR	A		; initialize tab count
	LD	(TABCNT),A	; initialize line and tab count
	CALL	SCANER		; extract filename.typ token
	JP	NZ,NAMERR	; error if any question mark
	CALL	ADVAN		; get pgdflg if it's there
	JR	Z,PGDON	 	; jump if no more on cmd line
	XOR	PGDFLG		; change page flag?
	JR	NZ,PGDON	; no
	INC	DE		; step over pgdflg
	LD	(CIBPTR),DE	; and save cmd buffer pointer
	DEC	A		; no page flag is 0ffh
	LD	(LNCNT),A	; save flag
PGDON:
	CALL	ULOGIN		; log any usCALL	CRLF		; strike any key
	JR	REPLY1
REPLY:
	CALL	PRINTC
	DC	'All'
REPLY1:
	CALL	PRINT
	DC	'? '
REPL2:
	CALL	BREAK		; get response
	JR	Z,REPL2		; none
	CALL	UCASE
	CP	'Y'
	RET	
;
;Section 5E
;Command: BELL
;Function: To ring terminal bell.
;Forms:
;	BELL
;
RING:
	LD	A,BELL		; load bell into A
	JP	CONOUT		; and output it
;
;Section 5F
;Command: LIST
;Function: To print specified file on list device.
;Forms:
;	LIST <ufn>	Print file
;	LIST <ufn> P	Print file without default pagier
	CALL	OPENF		; open selected file
	JR	Z,TYPE3		; abort if error
	CALL	CRLF		; new line
TYPE2:
	CALL	READF		; read next block
	JR	Z,TYPE4		; read ok (A register is zero)
	DEC	A		; error or eof?
	RET	Z		; eof
TYPE3:
	JP	PRNNF		; error
CHK4LF:
	LD	A,(LNCNT)	; get line count (just in case)
	DJNZ	CHK4VT		; not lf, try vertical tab
	RES	7,A		; reset first ff flag (if any)
	CP	07FH	 	; paging off?
	JR	Z,CHK4VT	; yes
	DEC	A		; time to page?
	JR	Z,CHKFF		; yes!
CHK4VT:
	DEC	B		; step over vt
ve character in e reg
	SUB	BS		; backspace?
	LD	B,A		; in case not bs
	JR	NZ,CHK4HT	; not bs
	DEC	(HL)		; step tab count and fall thru
CHK4HT:
	DJNZ	CHK4LF		; no, check for line feed
CHKHT:
	LD	E,' '		; load space into bdos character reg
	CALL	PAGER		; print space
	LD	A,(HL)		; now in col 0 mod 8?
	AND	07H
	JR	NZ,CHKHT	; go for more
	JR	NXTCHR
PAGER:
	CALL	BREAK		; check for abort
	LD	A,(TYPLST)	; get list/type flag
	LD	C,A
;
	IF	TEST OR NOT NOSTAT
	AND	00000010B	; list?
	EXX			; save rCHK4FF:
	DJNZ	CHK4CR		; not ff, try vt
	BIT	7,A		; first ff?
	JR	NZ,NXTCHR	; yes, ignore
CHKFF:
	LD	A,(TYPLST)
	BIT	0,A		; type or list?
	LD	E,FF		; load ff into character reg
	LD	A,NLINEP	; reset list count
	JR	NZ,CHK4CR	; list
CHKFF1:
	LD	C,06H		; direct console i/o
	LD	E,0FFH		; conditional console input
	CALL	BDOSJP
	JR	Z,CHKFF1	; no character yet
	CALL	CHKETX		; check for ^C
	LD	A,NLINES	; type line count
	LD	E,LF
CHK4CR:
	LD	(LNCNT),A	; save line count
››mmUým˙o˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙egisters
	CALL	Z,LISTST	; check busy
	EXX			; restore registers
	AND	A
	JR	Z,PAGER		; printer not ready
	ENDIF
;
	LD	A,E		; check for printing character
	CP	' '
	JR	C,PAGE2		; control character, don't count
	INC	(HL)		; step position
PAGE2:
	JP	BDOSJP		; return via bdos
;
;Section 5H
;Command: PAGE
;Function: To eject a page on list device via a form feed.
;Forms:
;	PAGE
;
EJECT:
	CALL	BREAK		; check for ^C
;
	IF	TEST OR NOT NOSTAT
	CALL	LISTST		; check printer ready
	AND	A
	JR	Z,Eer
	DJNZ	NXTCHR		; not cr
	LD	(HL),B		; reset tab count
NXTCHR:
	LD	A,(CHRCNT)	; get buffer pointer
	INC	A		; step to next character
	CP	128		; end-of-buffer?
	JR	NC,TYPE2	; yes, read next buffer
TYPE4:
	LD	(CHRCNT),A	; save buffer count
	LD	HL,TBUFF	; point to buffer
	CALL	ADDAH		; compute address of next character
	LD	A,(HL)		; get character to accumulator
	AND	7FH		; mask out msb
	CP	1AH		; end-of-file (^Z)?
	RET	Z		; yes, restart zcpr
	LD	HL,TABCNT	; pointer to tab counter
	LD	E,A		; saJECT	 	; not ready yet
	ENDIF
;
	LD	E,FF		; now for form feed
	LD	C,05H		; list output
	JP	BDOS		; output character and return via bdos
;
;Section 5I
;Command: SAVE
;Function: To save the contents of TPA onto disk as a file. Number of
;	     pages or records is in decimal. Saved area begins at 100H.
;Forms:
;	SAVE <Number of Pages> <ufn>
;	SAVE <Number of Records> <ufn> R
;
SAVE:
	CALL	NUMBER		;EXTRACT NUMBER FROM COMMAND LINE
	PUSH	HL		;SAVE IT
	CALL	SCANER		;EXTRACT FILENAME.TYP
	JP	NZ,RITE ERROR
SAVE4:
	JP	PRNLE		;PRINT 'NO SPACE' ERROR
;
;Section 5J
;Command: REN
;Function: To change the name of an existing file.
;Forms:
;	REN <newufn>=<oldufn>
;
REN:
	LD	HL,FCBDN+16	;PLACE FILENAME IN SECOND HALF OF FCB
	PUSH	HL		;SAVE POINTER FOR SEARCH FIRST
	CALL	SCAN1		;EXTRACT FILE NAME
	JR	NZ,NAMERR	;ERROR IF ANY '?' IN IT
	CALL	ADVAN		;ADVANCE CIBPTR
	CP	'='		;'=' OK
	JP	NZ,ERROR
	EX	DE,HL		;POINT TO CHARACTER AFTER '=' IN HL
	INC	HL
	LD	(CIBPTR),HL	;SAVE POINTER TO OLD FILE NAMERR	;MUST BE NO '?' IN IT
	CALL	ULOGIN		;LOG ANY USER
	CALL	ERA2		;DELETE FILE IF POSSIBLE
	CALL	CREATE		;CREATE NEW FILE
	JR	Z,SAVE4		;UNSUCCESSFUL
	XOR	A		;SET RECORD COUNT FIELD OF NEW FILE'S FCB
	LD	(FCBCR),A
	CALL	ADVAN		;LOOK FOR RECORD OPTION
	INC	DE		;POINT TO TOKEN
	POP	HL		;GET BACK PAGE COUNT
	CP	RECFLG
	JR	Z,SAVE1
	DEC	DE		;NO TOKEN, SO BACK UP
	ADD	HL,HL		;DOUBLE IT FOR HL=RECORD (128 BYTES) COUNT
SAVE1:
	LD	(CIBPTR),DE	;SET POINTER TO BAD TOKEN OR AFTER GOOD TOKEN
	LD	DE,TPANAME
	CALL	SCANER		;EXTRACT FILENAME.TYP TOKEN
	JR	NZ,NAMERR	;ERROR IF ANY '?'
	LD	A,(FCBDN+16+13)	;GET POSSIBLE USER NUMBER
	CALL	ALOGIN		;LOG ANY USER
	POP	DE	 	;GET POINTER FOR SEARCH FIRST
	CALL	SEARDE		;CHECK FOR NONE OF THAT NAME
	JR	Z,REN1	 	;NO FILE EXISTS
	CALL	PRINTC		;DUPLICATE NAME
	DC	'Delete'
	CALL	REPLY1		;GET REPLY
	JR	NZ,REN2		;NOT A 'Y'
	CALL	DELETE		;DELETE DUPLICATE
REN1:
	LD	A,(DE)		;GET POSSIBLE DRIVE
	LD	DE,FCBDN	;POINT TO FCB
	LD	(DE),A		;SAVE POSSIBLE DRIVE
	LD	C,17		;POINT TO START OF SAVE AREA (TPA)
SAVE2:
	LD	A,H		;DONE WITH SAVE?
	OR	L		;HL=0 IF SO
	JR	NZ,SAVE3
	LD	DE,FCBDN	;CLOSE SAVED FILE
	JP	CLOSE		;AND RESTART CPR
SAVE3:
	DEC	HL		;COUNT DOWN ON RECORDS
	PUSH	HL		;SAVE POINTER TO BLOCK TO SAVE
	CALL	DMASET		;SET DMA ADDRESS FOR WRITE (ADDRESS IN DE)
	LD	HL,128		;128 BYTES PER RECORD
	ADD	HL,DE		;POINT TO NEXT RECORD
	LD	DE,FCBDN	;WRITE RECORD
	CALL	WRITE
	EX	DE,HL		;GET POINTER TO NEXT RECORD IN DE
	POP	HL		;GET RECORD COUNT
	JR	Z,SAVE2		;NO WH		;BDOS RENAME FCT
	CALL	BDOSFN
	JP	CHKFND		;CHECK FOR FILE FOUND
NAMERR:
	CALL	PRINTC
	DC	'Name Error'
REN2:
	JP	ABORT
;
;Section 5K
;Command: USER
;Function: To change current user number; new user number is in decimal.
;Forms:
;	USER <usrnum>
;
USER:
	CALL	USRNUM		;EXTRACT USER NUMBER FROM COMMAND LINE
	JP	NEWUSR		;SET NEW USER NUMBER
;
;Section 5L
;Command: DFU
;Function: To set the Default User Number for the command/file scanner; new
;	     default user number is in decimal.
;F; done?
	RET	Z		; yes
	DJNZ	PEEK2		; not end of line
	JR	PEEK1		; end of line
PRHEXW:
	LD	A,H		; print hex word in hl
	CALL	PRHEXA
	LD	A,L
PRHEXA:
	PUSH	AF		; save right nibble
	RRCA			; move left nibble to right
	RRCA
	RRCA
	RRCA
	CALL	PRHEX		; display left nibble
	POP	AF		; get back right nibble
PRHEX:
	AND	0FH		; convert to ascii
	ADD	A,90H
	DAA
	ADC	A,40H
	DAA
	JP	CONOUT		; go display value
;
;
;Section 5O
;Command: POKE
;Function: To poke a string of hex values into a set of orms:
;	DFU <usrnum>
;
DFU:
	CALL	USRNUM		;GET USER NUMBER
	LD	(DFUSR),A	;PUT IT AWAY
	RET
;
;Section 5M
;Command: SCL
;Function: To force ZCPR to parse only a single command per line; reset
;	     to multiple command format at the next ^C.
;Forms:
;	SCL
;
	IF	MULTPL
SINGLE:
	LD	HL,NEWCMD	; point at current command separator
	LD	A,CMDCHR	; get default command separator
	XOR	(HL)		; flip current separator
	LD	(HL),A		; save new command separator
	RET
	ENDIF
;
;
;Section 5N
;Command:consecutive addresses.
;Forms:
;	POKE <hexadr> <hexval> [<hexval>]
;
POKE:
	CALL	HEXNUM		; get address
POKE1:
	PUSH	HL		; save address
	CALL	HEXNUM		; get next byte
	LD	A,(FCBFN)	; done?
	CP	' '
	LD	A,L		; save byte
	POP	HL		; get back address
	RET	Z		; done
	LD	(HL),A		; save byte
	INC	HL		; step to next address
	JR	POKE1		; go for more
;
;
;Section 5P
;Command: JUMP
;Function: To call the program (subroutine) at the specified address
;	     without loading from disk.
;Forms:
;	JUMP PEEK
;Function: To display hex values beginning at a specified address.
;Forms:
;	PEEK <hexadr> [<hexcnt>]
;
PEEK:
	CALL	HEXNUM		; get display address
	PUSH	HL		; save it
	CALL	HEXNUM		; get optional count
	LD	C,L		; save count
	POP	HL		; get back address
PEEK1:
	CALL	CRLF		; start new line
	CALL	PRHEXW		; print address
	LD	B,16		; 16 values per line
PEEK2:
	CALL	PRINT		; space over
	DC	' '
	LD	A,(HL)		; get hex value
	INC	HL		; step to next value
	CALL	PRHEXA		; display value
	DEC	C		 <hexadr> <command tail>
;
JUMP:
	CALL	HEXNUM		;GET LOAD ADDRESS IN HL
	JR	CLLPRG		;PERFORM CALL
;
;Section 5Q
;Command: COM file processing
;Function: To load the specified COM file from disk and execute it.
;Forms:
;	<command> <command tail>
;
COM:
	LD	HL,FCBFT	;FILE TYPE MUST BE BLANK
	LD	A,(HL)
	CP	' '
	JP	NZ,ERROR
	LD	(HL),'C'	;PLACE DEFAULT FILE TYPE (COM) INTO FCB
	INC	HL		;COPY INTO FILE TYPE
	LD	(HL),'O'	;3 BYTES
	INC	HL
	LD	(HL),'M'
	LD	HL,TPA		;SET EXECUTION/LOAD ADDRESS
	CR+0FF00H;INITIALIZE COUNT AND GET COMMAND FLAG
	LD	DE,TBUFF	;DESTINATION FOR COMMAND TAIL
COM2:
	INC	DE		;POINT TO DESTINATION
	INC	B		;INCREMENT CHARACTER COUNT
	LD	A,(HL)		;COPY CHARACTER TO TBUFF
	LD	(DE),A
	INC	HL		;STEP TO NEXT SOURCE CHARACTER
	OR	A		;END OF LINE?
;
	IF	MULTPL
	JR	Z,COM3		;YES, END OF LINE
	XOR	C		;START OF NEXT COMMAND?
	JR	NZ,COM2		;NO
	LD	(DE),A		;0 TERMINATE STRING
COM3:
;
	ELSE
;
	JR	NZ,COM2		;NOT END OF LINE
	ENDIF
;
	LD	A,B		;SAVE CHARACTER COUNT
	LD	(TBUALL	MEMLD		;LOAD MEMORY WITH FILE SPECIFIED
			 	;(NO RETURN IF ERROR OR TOO BIG)
;
;Section 5R
;Command: GO
;Function: To call the program in the TPA without loading from disk.
;	     Same as JUMP 100H, but more convenient, especially when
;	     used with parameters for programs like STAT.
;Form:
;	GO <command tail>
;
GO:
	LD	HL,TPA		;ALWAYS TO TPA
;
;
; CLLPRG IS THE ENTRY POINT FOR THE EXECUTION OF THE LOADED PROGRAM
;   ON ENTRY TO THIS ROUTINE, HL MUST CONTAIN THE EXECUTION
;   ADDRESFF),A
	DEC	HL		;BACK UP ONE CHARACTER
	LD	(CIBPTR),HL	;SAVE FOR START OF NEXT COMMAND SCAN
;
; RUN LOADED TRANSIENT PROGRAM
;
	CALL	CRLF		;NEW LINE
	CALL	DEFDMA		;SET DMA TO 0080
	CALL	RSTUSR		;RESET TO PROPER USER NUMBER
;
; EXECUTION (CALL) OF PROGRAM (SUBROUTINE) OCCURS HERE
;
	RET			;CALL TRANSIENT
;
;Section 5S
;Command: GET
;Function: To load the specified file from disk to the specified address
;Forms:
;	GET <hexadr> <ufn> Load the specified file at the specified page;
;
GET:
	CAS OF THE PROGRAM (SUBROUTINE) TO EXECUTE
;
CLLPRG:
	PUSH	HL		;SAVE EXECUTION ADDRESS
	LD	HL,(CIBPTR)	;SAVE THE COMMAND TAIL START ADDRESS
	PUSH	HL
	LD	HL,TFCB		;MAKE FCB FOR PROGRAM
	CALL	SCAN1		;SEARCH COMMAND LINE FOR NEXT TOKEN
	LD	HL,TFCB+16	;OFFSET FOR 2ND FILE SPEC
	CALL	SCAN1		;SCAN FOR IT AND LOAD IT INTO FCBDN+16
	XOR	A
	LD	(TFCB+32),A	;ZERO RECORD COUNT
;
; LOAD COMMAND LINE INTO TBUFF
;
	POP	HL		;GET LOCATION OF COMMAND TAIL
NEWCMD	EQU	$+1		;IN-LINE COMMAND SEPARATOR
	LD	BC,CMDCHLL	HEXNUM		;GET LOAD ADDRESS IN HL
	PUSH	HL		;SAVE ADDRESS
	CALL	SCANER		;GET FILE NAME
	POP	HL		;RESTORE ADDRESS
	JP	NZ,NAMERR	;MUST BE UNAMBIGUOUS
;
; LOAD MEMORY WITH COMMAND LINE FILE 
;   ON INPUT, HL CONTAINS STARTING ADDRESS TO LOAD
;   IF COM FILE TOO BIG, EXIT TO ERROR.
;
MEMLD:
	LD	(LDADR),HL	;SET LOAD ADDRESS
;
;   MLA is a reentry point for a non-standard CP/M Modification
; This is the return point when the .COM (or GET) file is not found the
; first time, the Default User is selST BELOW CPR
	CP	H		;ARE WE GOING TO OVERWRITE THE CPR?
	JR	C,PRNLE		;ERROR IF SO
	EX	DE,HL		;MOVE LOAD ADDRES FOR DMASET
	CALL	DMASET		;SET DMA ADDRESS
	LD	HL,128		;COMPUTE NEXT LOAD ADDRESS
	ADD	HL,DE		;AND SAVE ANSWER IN HL
	CALL	READF		;READ NEXT RECORD
	JR	Z,MLA2		;READ ERROR OR EOF?
	DEC	A		;LOAD COMPLETE
	JP	Z,RSTUSR	;GO RESET CORRECT USER
;
; LOAD ERROR
;
PRNLE:
	CALL	PRINTC
	DC	'Full'
PRNLE1:
	JP	ABORT
;
	IF	(($-ENTRY) GT ZCPRSZ)
	*ZCPR too large!!*
	ENDIF
;
	IF	TEST
LISTSTected for the second attempt
; and Drive A is selected for the final attempt.
;
MLA:
	CALL	ULOGIN		;LOG ANY USER
	LD	HL,(FCBS1)	;SAVE ANY USER NUMBER
	CALL	OPENF		;OPEN COMMAND.COM FILE
	JR	NZ,MLA1		;FILE FOUND - LOAD IT
;
; FILE NOT FOUND - SELECT DEFAULT USER
;
	LD	A,L	 	;GET FCB USER
	AND	A		;DEFAULT USER?
	JR	NZ,MLA0		;NO
	LD	HL,TMPUSR	;CURRENT USER SAME AS DEFAULT?
	LD	A,(DFUSR)	;GET DEFAULT USER
	CP	(HL)
	SET	7,A		;MAKE INTO VALID USER NUMBER
	LD	(FCBS1),A	;PUT USER INTO FCB
	JR	NZ,:
	LD	A,2DH		;COMPUTE LIST STATUS ENTRY
	DEFB	0FEH		;SKIP NEXT BYTE
BOOT:
	XOR	A		;COMPUTE BOOT ENTRY
	LD	HL,(BASE+1)	;GET PAGE ADDRESS OF BIOS
	LD	L,A		;ADD ENTRY
	JP	(HL)		;GO TO BIOS ROUTINE
	ENDIF

ENDLD	EQU	$

	END	

	PUSH	HL		;SAVE POIT RECORD
	JR	Z,MLA2		;READ ERROR OR EOF?
	DEC	A		;LOAD COMPLETE
	JP	Z,RSTUSR	;GO RESET CORRECT USER
;
; LOAD ERROR
;
PRNLE:
	CALL	PRINTC
	DC	'Full'
PRNLE1:
	JP	ABORT
;
	IF	(($-ENTRY) GT ZCPRSZ)
	*ZCPR too large!!*
	ENDIF
;
	IF	TEST
LISTSTMLA		;AND TRY AGAIN
;
; FILE NOT FOUND - SELECT DRIVE A IF DEFAULT WAS SOME OTHER DRIVE
;
MLA0:
	LD	A,(TDRIVE)	;DRIVE A DEFAULT?
	AND	A
	JR	Z,MLA3	 	;YES, ERROR
	XOR	A
	LD	HL,FCBDN	;POINT AT DRIVE IN FCB
	OR	(HL)		;DRIVE ALREADY SPECIFIED?
	LD	(