	.title	"Digital Research CCP, Version 2.2"
	.page	49

MON	.EQU	1		;ADD THE CCP MON COMMAND
USRDSP	.EQU	1		;SHOW THE USER NUMBER
CHKU0B	.EQU	0		;CHECK FOR TRANSIENTS ON USER 0 TOO
ENDFIL	.EQU	1		;FILE FULL CCP SIZE
;
;**************************************************************
;*
;* C C P  -   C O N S O L E   C O M M A N D   P R O C E S S O R
;*
;**************************************************************
;*
IOBYTE:	.EQU	3		; I/O DEFINITION BYTE.
TDRIVE:	.EQU	4		; CURRENT DRIVE NAME AND USER NUMBER.
ENTRY:	.EQU	5		; ENTRY POINT FOR THE CP/M BDOS.
TFCB:	.EQU	5CH		; DEFAULT FILE CONTROL BLOCK.
TBUFF:	.EQU	80H		; I/O BUFFER AND COMMAND LINE STORAGE.
TBASE:	.EQU	100H		; TRANSIANT PROGRAM STORAGE AREA.
;
;   SET CONTROL CHARACTER .EQUATES.
;
CNTRLC:	.EQU	03H		; CONTROL-C
CNTRLE:	.EQU	05H		; CONTROL-E
BS:	.EQU	08H		; BACKSPACE
TAB:	.EQU	09H		; TAB
LF:	.EQU	0AH		; LINE FEED
FF:	.EQU	0CH		; FORM FEED
CR:	.EQU	0DH		; CARRIAGE RETURN
CNTRLP:	.EQU	10H		; CONTROL-P
CNTRLR:	.EQU	12H		; CONTROL-R
CNTRLS:	.EQU	13H		; CONTROL-S
CNTRLU:	.EQU	15H		; CONTROL-U
CNTRLX:	.EQU	18H		; CONTROL-X
CNTRLZ:	.EQU	1AH		; CONTROL-Z (END-OF-FILE MARK)
DEL:	.EQU	7FH		; RUBOUT
;
;   SET ORIGIN FOR CP/M
;

NK	.EQU	59             ;SYSTEM SIZE
BASE	.EQU	(NK*1024)-5000H
CCPO	.EQU	BASE+3400H     ;CCP ORIGIN
BDOSO	.EQU	BASE+3C00H     ;BDOS ORIGIN
BIOSO	.EQU	BASE+4A00H     ;BIOS ORIGIN

	.ORG	CCPO
;
CBASE:	JP	COMMAND		; EXECUTE COMMAND PROCESSOR (CCP).
	JP	CLEARBUF	; ENTRY TO EMPTY INPUT BUFFER BEFORE STARTING CCP.

;
;   STANDARD CP/M CCP INPUT BUFFER. FORMAT IS (MAX LENGTH),
; (ACTUAL LENGTH), (CHAR #1), (CHAR #2), (CHAR #3), ETC.
;
INBUFF:	.DB 127			; LENGTH OF INPUT BUFFER.
; N8VEM - if add any text after this point, change .DB 0 below to length
; and put a 0 after the text, and delete the same number of zeros after the dig
; so that inpoint ends up at the same spot
; INBUFF+1 is cleared on the next warm boot, so only runs once.
	.DB	0	;CURRENT LENGTH OF CONTENTS.


;	.DB 17			; Autoboot length of string
;	.DB    "SUPERSUB AUTOEXEC"
;	.DB 0			; zero at end


	.DB "COPYRIGHT"
	.DB " 1979 (C) BY "
	.DB "DIGITAL RESEARCH      "
	.FILL	((INBUFF + 128) - $),055H


INPOINT:.DW INBUFF+2		; INPUT LINE POINTER
NAMEPNT:.DW 0			; INPUT LINE POINTER USED FOR ERROR MESSAGE. POINTS TO
;				;START OF NAME IN ERROR.
;
;   ROUTINE TO PRINT (A) ON THE CONSOLE. ALL REGISTERS USED.
;
PRINT:	LD	E,A		; SETUP BDOS CALL.
	LD	C,2
	JP	ENTRY
;
;   ROUTINE TO PRINT (A) ON THE CONSOLE AND TO SAVE (BC).
;
PRINTB:	PUSH	BC
	CALL	PRINT
	POP	BC
	RET
;
;   ROUTINE TO SEND A CARRIAGE RETURN, LINE FEED COMBINATION
; TO THE CONSOLE.
;
CRLF:	LD	A,CR
	CALL	PRINTB
	LD	A,LF
	JP	PRINTB
;
;   ROUTINE TO SEND ONE SPACE TO THE CONSOLE AND SAVE (BC).
;
SPACE:	LD	A,' '
	JP	PRINTB
;
;   ROUTINE TO PRINT CHARACTER STRING POINTED TO BE (BC) ON THE
; CONSOLE. IT MUST TERMINATE WITH A NULL BYTE.
;
PLINE:	PUSH	BC
	CALL	CRLF
	POP	HL
PLINE2:	LD	A,(HL)
	OR	A
	RET	Z
	INC	HL
	PUSH	HL
	CALL	PRINT
	POP	HL
	JP	PLINE2
;
;   ROUTINE TO RESET THE DISK SYSTEM.
;
RESDSK:	LD	C,13
	JP	ENTRY
;
;   ROUTINE TO SELECT DISK (A).
;
DSKSEL:	LD	E,A
	LD	C,14
	JP	ENTRY
;
;   ROUTINE TO CALL BDOS AND SAVE THE RETURN CODE. THE ZERO
; FLAG IS SET ON A RETURN OF 0FFH.
;
ENTRY1:	CALL	ENTRY
	LD	(RTNCODE),A	; SAVE RETURN CODE.
	INC	A		; SET ZERO IF 0FFH RETURNED.
	RET
;
;   ROUTINE TO OPEN A FILE. (DE) MUST POINT TO THE FCB.
;
OPEN:	LD	C,15
	JP	ENTRY1
;
;   ROUTINE TO OPEN FILE AT (FCB).
;
OPENFCB:XOR	A		; CLEAR THE RECORD NUMBER BYTE AT FCB+32
	LD	(FCB+32),A
	LD	DE,FCB
	JP	OPEN
;
;   ROUTINE TO CLOSE A FILE. (DE) POINTS TO FCB.
;
CLOSE:	LD	C,16
	JP	ENTRY1
;
;   ROUTINE TO SEARCH FOR THE FIRST FILE WITH AMBIGUEOUS NAME
; (DE).
;
SRCHFST:LD	C,17
	JP	ENTRY1
;
;   SEARCH FOR THE NEXT AMBIGEOUS FILE NAME.
;
SRCHNXT:LD	C,18
	JP	ENTRY1
;
;   SEARCH FOR FILE AT (FCB).
;
SRCHFCB:LD	DE,FCB
	JP	SRCHFST
;
;   ROUTINE TO DELETE A FILE POINTED TO BY (DE).
;
DELETE:	LD	C,19
	JP	ENTRY
;
;   ROUTINE TO CALL THE BDOS AND SET THE ZERO FLAG IF A ZERO
; STATUS IS RETURNED.
;
ENTRY2:	CALL	ENTRY
	OR	A		; SET ZERO FLAG IF APPROPRIATE.
	RET
;
;   ROUTINE TO READ THE NEXT RECORD FROM A S.EQUENTIAL FILE.
; (DE) POINTS TO THE FCB.
;
RDREC:	LD	C,20
	JP	ENTRY2
;
;   ROUTINE TO READ FILE AT (FCB).
;
READFCB:LD	DE,FCB
	JP	RDREC
;
;   ROUTINE TO WRITE THE NEXT RECORD OF A S.EQUENTIAL FILE.
; (DE) POINTS TO THE FCB.
;
WRTREC:	LD	C,21
	JP	ENTRY2
;
;   ROUTINE TO CREATE THE FILE POINTED TO BY (DE).
;
CREATE:	LD	C,22
	JP	ENTRY1
;
;   ROUTINE TO RENAME THE FILE POINTED TO BY (DE). NOTE THAT
; THE NEW NAME STARTS AT (DE+16).
;
RENAM:	LD	C,23
	JP	ENTRY
;
;   GET THE CURRENT USER CODE.
;
GETUSR:	LD	E,0FFH
;
;   ROUTNE TO GET OR SET THE CURRENT USER CODE.
; IF (E) IS FF THEN THIS IS A GET, ELSE IT IS A SET.
;
GETSETUC:
	LD	C,32
	JP	ENTRY
;
;   ROUTINE TO SET THE CURRENT DRIVE BYTE AT (TDRIVE).
;
SETCDRV:CALL	GETUSR		; GET USER NUMBER
	ADD	A,A		; AND SHIFT INTO THE UPPER 4 BITS.
	ADD	A,A
	ADD	A,A
	ADD	A,A
	LD	HL,CDRIVE	; NOW ADD IN THE CURRENT DRIVE NUMBER.
	OR	(HL)
	LD	(TDRIVE),A	; AND SAVE.
	RET
;
;   MOVE CURRENTLY ACTIVE DRIVE DOWN TO (TDRIVE).
;
MOVECD:	LD	A,(CDRIVE)
	LD	(TDRIVE),A
	RET
;
;   ROUTINE TO CONVERT (A) INTO UPPER CASE ASCII. ONLY LETTERS
; ARE AFFECTED.
;
UPPER:	CP	'A'		; CHECK FOR LETTERS IN THE RANGE OF 'A' TO 'Z'.
	RET	C
	CP	'{'
	RET	NC
	AND	5FH		; CONVERT IT IF FOUND.
	RET
;
;   ROUTINE TO GET A LINE OF INPUT. WE MUST CHECK TO SEE IF THE
; USER IS IN (BATCH) MODE. IF SO, THEN READ THE INPUT FROM FILE
; ($$$.SUB). AT THE END, RESET TO CONSOLE INPUT.
;
GETINP:	LD	A,(BATCH)	; IF =0, THEN USE CONSOLE INPUT.
	OR	A
	JP	Z,GETINP1
;
;   USE THE SUBMIT FILE ($$$.SUB) WHICH IS PREPARED BY A
; SUBMIT RUN. IT MUST BE ON DRIVE (A) AND IT WILL BE DELETED
; IF AND ERROR OCCURES (LIKE EOF).
;
	LD	A,(CDRIVE)	; SELECT DRIVE 0 IF NEED BE.
	OR	A
	LD	A,0		; ALWAYS USE DRIVE A FOR SUBMIT.
	CALL	NZ,DSKSEL	; SELECT IT IF REQUIRED.
	LD	DE,BATCHFCB
	CALL	OPEN		; LOOK FOR IT.
	JP	Z,GETINP1	; IF NOT THERE, USE NORMAL INPUT.
	LD	A,(BATCHFCB+15)	; GET LAST RECORD NUMBER+1.
	DEC	A
	LD	(BATCHFCB+32),A
	LD	DE,BATCHFCB
	CALL	RDREC		; READ LAST RECORD.
	JP	NZ,GETINP1	; QUIT ON END OF FILE.
;
;   MOVE THIS RECORD INTO INPUT BUFFER.
;
	LD	DE,INBUFF+1
	LD	HL,TBUFF	; DATA WAS READ INTO BUFFER HERE.
	LD	B,128		; ALL 128 CHARACTERS MAY BE USED.
	CALL	HL2DE		; (HL) TO (DE), (B) BYTES.
	LD	HL,BATCHFCB+14
	LD	(HL),0		; ZERO OUT THE 'S2' BYTE.
	INC	HL		; AND DECREMENT THE RECORD COUNT.
	DEC	(HL)
	LD	DE,BATCHFCB	; CLOSE THE BATCH FILE NOW.
	CALL	CLOSE
	JP	Z,GETINP1	; QUIT ON AN ERROR.
	LD	A,(CDRIVE)	; RE-SELECT PREVIOUS DRIVE IF NEED BE.
	OR	A
	CALL	NZ,DSKSEL	; DON'T DO NEEDLESS SELECTS.
;
;   PRINT LINE JUST READ ON CONSOLE.
;
	LD	HL,INBUFF+2
	CALL	PLINE2
	CALL	CHKCON		; CHECK CONSOLE, QUIT ON A KEY.
	JP	Z,GETINP2	; JUMP IF NO KEY IS PRESSED.
;
;   TERMINATE THE SUBMIT JOB ON ANY KEYBOARD INPUT. DELETE THIS
; FILE SUCH THAT IT IS NOT RE-STARTED AND JUMP TO NORMAL KEYBOARD
; INPUT SECTION.
;
	CALL	DELBATCH	; DELETE THE BATCH FILE.
	JP	CMMND1		; AND RESTART COMMAND INPUT.
;
;   GET HERE FOR NORMAL KEYBOARD INPUT. DELETE THE SUBMIT FILE
; INCASE THERE WAS ONE.
;
GETINP1:CALL	DELBATCH	; DELETE FILE ($$$.SUB).
	CALL	SETCDRV		; RESET ACTIVE DISK.
	LD	C,10		; GET LINE FROM CONSOLE DEVICE.
	LD	DE,INBUFF
	CALL	ENTRY
	CALL	MOVECD		; RESET CURRENT DRIVE (AGAIN).
;
;   CONVERT INPUT LINE TO UPPER CASE.
;
GETINP2:LD	HL,INBUFF+1
	LD	B,(HL)		; (B)=CHARACTER COUNTER.
GETINP3:INC	HL
	LD	A,B		; END OF THE LINE?
	OR	A
	JP	Z,GETINP4
	LD	A,(HL)		; CONVERT TO UPPER CASE.
	CALL	UPPER
	LD	(HL),A
	DEC	B		; ADJUST CHARACTER COUNT.
	JP	GETINP3
GETINP4:LD	(HL),A		; ADD TRAILING NULL.
	LD	HL,INBUFF+2
	LD	(INPOINT),HL	; RESET INPUT LINE POINTER.
	RET
;
;   ROUTINE TO CHECK THE CONSOLE FOR A KEY PRESSED. THE ZERO
; FLAG IS SET IS NONE, ELSE THE CHARACTER IS RETURNED IN (A).
;
CHKCON:	LD	C,11		; CHECK CONSOLE.
	CALL	ENTRY
	OR	A
	RET	Z		; RETURN IF NOTHING.
	LD	C,1		; ELSE GET CHARACTER.
	CALL	ENTRY
	OR	A		; CLEAR ZERO FLAG AND RETURN.
	RET
;
;   ROUTINE TO GET THE CURRENTLY ACTIVE DRIVE NUMBER.
;
GETDSK:	LD	C,25
	JP	ENTRY
;
;   SET THE STABDARD DMA ADDRESS.
;
STDDMA:	LD	DE,TBUFF
;
;   ROUTINE TO SET THE DMA ADDRESS TO (DE).
;
DMASET:	LD	C,26
	JP	ENTRY
;
;  DELETE THE BATCH FILE CREATED BY SUBMIT.
;
DELBATCH:
	LD	HL,BATCH	; IS BATCH ACTIVE?
	LD	A,(HL)
	OR	A
	RET	Z
	LD	(HL),0		; YES, DE-ACTIVATE IT.
	XOR	A
	CALL	DSKSEL		; SELECT DRIVE 0 FOR SURE.
	LD	DE,BATCHFCB	; AND DELETE THIS FILE.
	CALL	DELETE
	LD	A,(CDRIVE)	; RESET CURRENT DRIVE.
	JP	DSKSEL
;
;   PRINT BACK FILE NAME WITH A '?' TO INDICATE A SYNTAX ERROR.
;
SYNERR:	CALL	CRLF		; END CURRENT LINE.
	LD	HL,(NAMEPNT)	; THIS POINTS TO NAME IN ERROR.
SYNERR1:LD	A,(HL)		; PRINT IT UNTIL A SPACE OR NULL IS FOUND.
	CP	' '
	JP	Z,SYNERR2
	OR	A
	JP	Z,SYNERR2
	PUSH	HL
	CALL	PRINT
	POP	HL
	INC	HL
	JP	SYNERR1
SYNERR2:LD	A,'?'		; ADD TRAILING '?'.
	CALL	PRINT
	CALL	CRLF
	CALL	DELBATCH	; DELETE ANY BATCH FILE.
	JP	CMMND1		; AND RESTART FROM CONSOLE INPUT.
;
;   CHECK CHARACTER AT (DE) FOR LEGAL COMMAND INPUT. NOTE THAT THE
; ZERO FLAG IS SET IF THE CHARACTER IS A DELIMITER.
;
CHECK:	LD	A,(DE)
	OR	A
	RET	Z
	CP	' '		; CONTROL CHARACTERS ARE NOT LEGAL HERE.
	JP	C,SYNERR
	RET	Z		; CHECK FOR VALID DELIMITER.
	CP	'='
	RET	Z
	CP	'_'
	RET	Z
	CP	'.'
	RET	Z
	CP	':'
	RET	Z
	CP	$3B
	RET	Z
	CP	'<'
	RET	Z
	CP	'>'
	RET	Z
	RET
;
;   GET THE NEXT NON-BLANK CHARACTER FROM (DE).
;
NONBLANK:
	LD	A,(DE)
	OR	A		; STRING ENDS WITH A NULL.
	RET	Z
	CP	' '
	RET	NZ
	INC	DE
	JP	NONBLANK
;
;   ADD (HL)=(HL)+(A)
;
ADDHL:	ADD	A,L
	LD	L,A
	RET	NC		; TAKE CARE OF ANY CARRY.
	INC	H
	RET
;
;   CONVERT THE FIRST NAME IN (FCB).
;
CONVFST:LD	A,0
;
;   FORMAT A FILE NAME (CONVERT * TO '?', ETC.). ON RETURN,
; (A)=0 IS AN UNAMBIGEOUS NAME WAS SPECIFIED. ENTER WITH (A) .EQUAL TO
; THE POSITION WITHIN THE FCB FOR THE NAME (EITHER 0 OR 16).
;
CONVERT:LD	HL,FCB
	CALL	ADDHL
	PUSH	HL
	PUSH	HL
	XOR	A
	LD	(CHGDRV),A	; INITIALIZE DRIVE CHANGE FLAG.
	LD	HL,(INPOINT)	; SET (HL) AS POINTER INTO INPUT LINE.
	EX	DE,HL
	CALL	NONBLANK	; GET NEXT NON-BLANK CHARACTER.
	EX	DE,HL
	LD	(NAMEPNT),HL	; SAVE POINTER HERE FOR ANY ERROR MESSAGE.
	EX	DE,HL
	POP	HL
	LD	A,(DE)		; GET FIRST CHARACTER.
	OR	A
	JP	Z,CONVRT1
	SBC	A,'A'-1		; MIGHT BE A DRIVE NAME, CONVERT TO BINARY.
	LD	B,A		; AND SAVE.
	INC	DE		; CHECK NEXT CHARACTER FOR A ':'.
	LD	A,(DE)
	CP	':'
	JP	Z,CONVRT2
	DEC	DE		; NOPE, MOVE POINTER BACK TO THE START OF THE LINE.
CONVRT1:LD	A,(CDRIVE)
	LD	(HL),A
	JP	CONVRT3
CONVRT2:LD	A,B
	LD	(CHGDRV),A	; SET CHANGE IN DRIVES FLAG.
	LD	(HL),B
	INC	DE
;
;   CONVERT THE BASIC FILE NAME.
;
CONVRT3:LD	B,08H
CONVRT4:CALL	CHECK
	JP	Z,CONVRT8
	INC	HL
	CP	'*'		; NOTE THAT AN '*' WILL FILL THE REMAINING
	JP	NZ,CONVRT5	; FIELD WITH '?'.
	LD	(HL),'?'
	JP	CONVRT6
CONVRT5:LD	(HL),A
	INC	DE
CONVRT6:DEC	B
	JP	NZ,CONVRT4
CONVRT7:CALL	CHECK		; GET NEXT DELIMITER.
	JP	Z,GETEXT
	INC	DE
	JP	CONVRT7
CONVRT8:INC	HL		; BLANK FILL THE FILE NAME.
	LD	(HL),' '
	DEC	B
	JP	NZ,CONVRT8
;
;   GET THE EXTENSION AND CONVERT IT.
;
GETEXT:	LD	B,03H
	CP	'.'
	JP	NZ,GETEXT5
	INC	DE
GETEXT1:CALL	CHECK
	JP	Z,GETEXT5
	INC	HL
	CP	'*'
	JP	NZ,GETEXT2
	LD	(HL),'?'
	JP	GETEXT3
GETEXT2:LD	(HL),A
	INC	DE
GETEXT3:DEC	B
	JP	NZ,GETEXT1
GETEXT4:CALL	CHECK
	JP	Z,GETEXT6
	INC	DE
	JP	GETEXT4
GETEXT5:INC	HL
	LD	(HL),' '
	DEC	B
	JP	NZ,GETEXT5
GETEXT6:LD	B,3
GETEXT7:INC	HL
	LD	(HL),0
	DEC	B
	JP	NZ,GETEXT7
	EX	DE,HL
	LD	(INPOINT),HL	; SAVE INPUT LINE POINTER.
	POP	HL
;
;   CHECK TO SEE IF THIS IS AN AMBIGEOUS FILE NAME SPECIFICATION.
; SET THE (A) REGISTER TO NON ZERO IF IT IS.
;
	LD	BC,11		; SET NAME LENGTH.
GETEXT8:INC	HL
	LD	A,(HL)
	CP	'?'		; ANY QUESTION MARKS?
	JP	NZ,GETEXT9
	INC	B		; COUNT THEM.
GETEXT9:DEC	C
	JP	NZ,GETEXT8
	LD	A,B
	OR	A
	RET
;
;   CP/M COMMAND TABLE. NOTE COMMANDS CAN BE EITHER 3 OR 4 CHARACTERS LONG.
;
	.IF	MON
NUMCMDS:.EQU	7		; NUMBER OF COMMANDS
	.ELSE
NUMCMDS:.EQU	6		; NUMBER OF COMMANDS
	.ENDIF

CMDTBL:	.DB	"DIR "
	.DB	"ERA "
	.DB	"TYPE"
	.DB	"SAVE"
	.DB	"REN "
	.DB	"USER"
	.IF	MON
	.DB	"MON "
	.ENDIF
	
CMDADR:	.DW	DIRECT
	.DW	ERASE
	.DW	TYPE
	.DW	SAVE
	.DW	RENAME
	.DW	USER
	.IF	MON
	.DW	MONITOR
	.ENDIF
	.DW	UNKNOWN
;
;   SEARCH THE COMMAND TABLE FOR A MATCH WITH WHAT HAS JUST
; BEEN ENTERED. IF A MATCH IS FOUND, THEN WE JUMP TO THE
; PROPER SECTION. ELSE JUMP TO (UNKNOWN).
; ON RETURN, THE (C) REGISTER IS SET TO THE COMMAND NUMBER
; THAT MATCHED (OR NUMCMDS+1 IF NO MATCH).
;
SEARCH:	LD	HL,CMDTBL
	LD	C,0
SEARCH1:LD	A,C
	CP	NUMCMDS		; THIS COMMANDS EXISTS.
	RET	NC
	LD	DE,FCB+1	; CHECK THIS ONE.
	LD	B,4		; MAX COMMAND LENGTH.
SEARCH2:LD	A,(DE)
	CP	(HL)
	JP	NZ,SEARCH3	; NOT A MATCH.
	INC	DE
	INC	HL
	DEC	B
	JP	NZ,SEARCH2
	LD	A,(DE)		; ALLOW A 3 CHARACTER COMMAND TO MATCH.
	CP	' '
	JP	NZ,SEARCH4
	LD	A,C		; SET RETURN REGISTER FOR THIS COMMAND.
	RET
SEARCH3:INC	HL
	DEC	B
	JP	NZ,SEARCH3
SEARCH4:INC	C
	JP	SEARCH1
;
;   SET THE INPUT BUFFER TO EMPTY AND THEN START THE COMMAND
; PROCESSOR (CCP).
;
CLEARBUF:
	XOR	A
	LD	(INBUFF+1),A	; SECOND BYTE IS ACTUAL LENGTH.
COMMAND:LD	SP,CCPSTACK	; SETUP STACK AREA.
	PUSH	BC		; NOTE THAT (C) SHOULD BE .EQUAL TO:
	LD	A,C		; (UUUUDDDD) WHERE 'UUUU' IS THE USER NUMBER
	RRA			; AND 'DDDD' IS THE DRIVE NUMBER.
	RRA
	RRA
	RRA
	AND	0FH		; ISOLATE THE USER NUMBER.
	LD	E,A
	CALL	GETSETUC	; AND SET IT.
	CALL	RESDSK		; RESET THE DISK SYSTEM.
	LD	(BATCH),A	; CLEAR BATCH MODE FLAG.
	POP	BC
	LD	A,C
	AND	0FH		; ISOLATE THE DRIVE NUMBER.
	LD	(CDRIVE),A	; AND SAVE.
	CALL	DSKSEL		; ...AND SELECT.
	LD	A,(INBUFF+1)
	OR	A		; ANYTHING IN INPUT BUFFER ALREADY?
	JP	NZ,CMMND2	; YES, WE JUST PROCESS IT.
;
;   ENTRY POINT TO GET A COMMAND LINE FROM THE CONSOLE.
;
CMMND1:	LD	SP,CCPSTACK	; SET STACK STRAIGHT.
	CALL	CRLF		; START A NEW LINE ON THE SCREEN.
	CALL	GETDSK		; GET CURRENT DRIVE.
	ADD	A,'A'
	CALL	PRINT		; PRINT CURRENT DRIVE.
	.IF	USRDSP
	CALL	GETUSR		;GET CURRENT USER NUMBER
	CP	10		;TWO DIGITS?
	JR	C,CMMND3	;NO
	LD	A,'1'		;PRINT LEADING '1'
	CALL	PRINT
	CALL	GETUSR		;GET CURRENT USER NUMBER
	SUB	10		;SUBTRACT 10
CMMND3: ADD	A,'0'
	CALL	PRINT
	.ENDIF
	LD	A,'>'
	CALL	PRINT		; AND ADD PROMPT.
	CALL	GETINP		; GET LINE FROM USER.
;
;   PROCESS COMMAND LINE HERE.
;
CMMND2:	LD	DE,TBUFF
	CALL	DMASET		; SET STANDARD DMA ADDRESS.
	CALL	GETDSK
	LD	(CDRIVE),A	; SET CURRENT DRIVE.
	CALL	CONVFST		; CONVERT NAME TYPED IN.
	CALL	NZ,SYNERR	; WILD CARDS ARE NOT ALLOWED.
	LD	A,(CHGDRV)	; IF A CHANGE IN DRIVES WAS INDICATED,
	OR	A		; THEN TREAT THIS AS AN UNKNOWN COMMAND
	JP	NZ,UNKNOWN	; WHICH GETS EXECUTED.
	CALL	SEARCH		; ELSE SEARCH COMMAND TABLE FOR A MATCH.
;
;   NOTE THAT AN UNKNOWN COMMAND RETURNS
; WITH (A) POINTING TO THE LAST ADDRESS
; IN OUR TABLE WHICH IS (UNKNOWN).
;
	LD	HL,CMDADR	; NOW, LOOK THRU OUR ADDRESS TABLE FOR COMMAND (A).
	LD	E,A		; SET (DE) TO COMMAND NUMBER.
	LD	D,0
	ADD	HL,DE
	ADD	HL,DE		; (HL)=(CMDADR)+2*(COMMAND NUMBER).
	LD	A,(HL)		; NOW PICK OUT THIS ADDRESS.
	INC	HL
	LD	H,(HL)
	LD	L,A
	JP	(HL)		; NOW EXECUTE IT.
;
;   READ ERROR WHILE TYPEING A FILE.
;
RDERROR:LD	BC,RDERR
	JP	PLINE
RDERR:	.DB	"Read Error",0
;
;   REQUIRED FILE WAS NOT LOCATED.
;
NONE:	LD	BC,NOFILE
	JP	PLINE
NOFILE:	.DB	"No File",0
;
;   DECODE A COMMAND OF THE FORM 'A>FILENAME NUMBER{ FILENAME}.
; NOTE THAT A DRIVE SPECIFIER IS NOT ALLOWED ON THE FIRST FILE
; NAME. ON RETURN, THE NUMBER IS IN REGISTER (A). ANY ERROR
; CAUSES 'FILENAME?' TO BE PRINTED AND THE COMMAND IS ABORTED.
;
DECODE:	CALL	CONVFST		; CONVERT FILENAME.
	LD	A,(CHGDRV)	; DO NOT ALLOW A DRIVE TO BE SPECIFIED.
	OR	A
	JP	NZ,SYNERR
	LD	HL,FCB+1	; CONVERT NUMBER NOW.
	LD	BC,11		; (B)=SUM REGISTER, (C)=MAX DIGIT COUNT.
DECODE1:LD	A,(HL)
	CP	' '		; A SPACE TERMINATES THE NUMERAL.
	JP	Z,DECODE3
	INC	HL
	SUB	'0'		; MAKE BINARY FROM ASCII.
	CP	10		; LEGAL DIGIT?
	JP	NC,SYNERR
	LD	D,A		; YES, SAVE IT IN (D).
	LD	A,B		; COMPUTE (B)=(B)*10 AND CHECK FOR OVERFLOW.
	AND	0E0H
	JP	NZ,SYNERR
	LD	A,B
	RLCA
	RLCA
	RLCA			; (A)=(B)*8
	ADD	A,B		; .......*9
	JP	C,SYNERR
	ADD	A,B		; .......*10
	JP	C,SYNERR
	ADD	A,D		; ADD IN NEW DIGIT NOW.
DECODE2:JP	C,SYNERR
	LD	B,A		; AND SAVE RESULT.
	DEC	C		; ONLY LOOK AT 11 DIGITS.
	JP	NZ,DECODE1
	RET
DECODE3:LD	A,(HL)		; SPACES MUST FOLLOW (WHY?).
	CP	' '
	JP	NZ,SYNERR
	INC	HL
DECODE4:DEC	C
	JP	NZ,DECODE3
	LD	A,B		; SET (A)=THE NUMERIC VALUE ENTERED.
	RET
;
;   MOVE 3 BYTES FROM (HL) TO (DE). NOTE THAT THERE IS ONLY
; ONE REFERENCE TO THIS AT (A2D5H).
;
MOVE3:	LD	B,3
;
;   MOVE (B) BYTES FROM (HL) TO (DE).
;
HL2DE:	LD	A,(HL)
	LD	(DE),A
	INC	HL
	INC	DE
	DEC	B
	JP	NZ,HL2DE
	RET
;
;   COMPUTE (HL)=(TBUFF)+(A)+(C) AND GET THE BYTE THAT'S HERE.
;
EXTRACT:LD	HL,TBUFF
	ADD	A,C
	CALL	ADDHL
	LD	A,(HL)
	RET
;
;  CHECK DRIVE SPECIFIED. IF IT MEANS A CHANGE, THEN THE NEW
; DRIVE WILL BE SELECTED. IN ANY CASE, THE DRIVE BYTE OF THE
; FCB WILL BE SET TO NULL (MEANS USE CURRENT DRIVE).
;
DSELECT:XOR	A		; NULL OUT FIRST BYTE OF FCB.
	LD	(FCB),A
	LD	A,(CHGDRV)	; A DRIVE CHANGE INDICATED?
	OR	A
	RET	Z
	DEC	A		; YES, IS IT THE SAME AS THE CURRENT DRIVE?
	LD	HL,CDRIVE
	CP	(HL)
	RET	Z
	JP	DSKSEL		; NO. SELECT IT THEN.
;
;   CHECK THE DRIVE SELECTION AND RESET IT TO THE PREVIOUS
; DRIVE IF IT WAS CHANGED FOR THE PRECEEDING COMMAND.
;
RESETDR:LD	A,(CHGDRV)	; DRIVE CHANGE INDICATED?
	OR	A
	RET	Z
	DEC	A		; YES, WAS IT A DIFFERENT DRIVE?
	LD	HL,CDRIVE
	CP	(HL)
	RET	Z
	LD	A,(CDRIVE)	; YES, RE-SELECT OUR OLD DRIVE.
	JP	DSKSEL
	
;
;**************************************************************
;*
;*           M O N I T O R   C O M M A N D
;*
;**************************************************************
;
	.IF	MON
MONITOR:RST	38H
	.ENDIF

;
;**************************************************************
;*
;*           D I R E C T O R Y   C O M M A N D
;*
;**************************************************************
;
DIRECT:	CALL	CONVFST		; CONVERT FILE NAME.
	CALL	DSELECT		; SELECT INDICATED DRIVE.
	LD	HL,FCB+1	; WAS ANY FILE INDICATED?
	LD	A,(HL)
	CP	' '
	JP	NZ,DIRECT2
	LD	B,11		; NO. FILL FIELD WITH '?' - SAME AS *.*.
DIRECT1:LD	(HL),'?'
	INC	HL
	DEC	B
	JP	NZ,DIRECT1
DIRECT2:LD	E,0		; SET INITIAL CURSOR POSITION.
	PUSH	DE
	CALL	SRCHFCB		; GET FIRST FILE NAME.
	CALL	Z,NONE		; NONE FOUND AT ALL?
DIRECT3:JP	Z,DIRECT9	; TERMINATE IF NO MORE NAMES.
	LD	A,(RTNCODE)	; GET FILE'S POSITION IN SEGMENT (0-3).
	RRCA
	RRCA
	RRCA
	AND	60H		; (A)=POSITION*32
	LD	C,A
	LD	A,10
	CALL	EXTRACT		; EXTRACT THE TENTH ENTRY IN FCB.
	RLA			; CHECK SYSTEM FILE STATUS BIT.
	JP	C,DIRECT8	; WE DON'T LIST THEM.
	POP	DE
	LD	A,E		; BUMP NAME COUNT.
	INC	E
	PUSH	DE
	AND	03H		; AT END OF LINE?
	PUSH	AF
	JP	NZ,DIRECT4
	CALL	CRLF		; YES, END THIS LINE AND START ANOTHER.
	PUSH	BC
	CALL	GETDSK		; START LINE WITH ('A:').
	POP	BC
	ADD	A,'A'
	CALL	PRINTB
	LD	A,':'
	CALL	PRINTB
	JP	DIRECT5
DIRECT4:CALL	SPACE		; ADD SEPERATOR BETWEEN FILE NAMES.
	LD	A,':'
	CALL	PRINTB
DIRECT5:CALL	SPACE
	LD	B,1		; 'EXTRACT' EACH FILE NAME CHARACTER AT A TIME.
DIRECT6:LD	A,B
	CALL	EXTRACT
	AND	7FH		; STRIP BIT 7 (STATUS BIT).
	CP	' '		; ARE WE AT THE END OF THE NAME?
	JP	NZ,DRECT65
	POP	AF		; YES, DON'T PRINT SPACES AT THE END OF A LINE.
	PUSH	AF
	CP	3
	JP	NZ,DRECT63
	LD	A,9		; FIRST CHECK FOR NO EXTENSION.
	CALL	EXTRACT
	AND	7FH
	CP	' '
	JP	Z,DIRECT7	; DON'T PRINT SPACES.
DRECT63:LD	A,' '		; ELSE PRINT THEM.
DRECT65:CALL	PRINTB
	INC	B		; BUMP TO NEXT CHARACTER PSOITION.
	LD	A,B
	CP	12		; END OF THE NAME?
	JP	NC,DIRECT7
	CP	9		; NOPE, STARTING EXTENSION?
	JP	NZ,DIRECT6
	CALL	SPACE		; YES, ADD SEPERATING SPACE.
	JP	DIRECT6
DIRECT7:POP	AF		; GET THE NEXT FILE NAME.
DIRECT8:CALL	CHKCON		; FIRST CHECK CONSOLE, QUIT ON ANYTHING.
	JP	NZ,DIRECT9
	CALL	SRCHNXT		; GET NEXT NAME.
	JP	DIRECT3		; AND CONTINUE WITH OUR LIST.
DIRECT9:POP	DE		; RESTORE THE STACK AND RETURN TO COMMAND LEVEL.
	JP	GETBACK
;
;**************************************************************
;*
;*                E R A S E   C O M M A N D
;*
;**************************************************************
;
ERASE:	CALL	CONVFST		; CONVERT FILE NAME.
	CP	11		; WAS '*.*' ENTERED?
	JP	NZ,ERASE1
	LD	BC,YESNO	; YES, ASK FOR CONFIRMATION.
	CALL	PLINE
	CALL	GETINP
	LD	HL,INBUFF+1
	DEC	(HL)		; MUST BE EXACTLY 'Y'.
	JP	NZ,CMMND1
	INC	HL
	LD	A,(HL)
	CP	'Y'
	JP	NZ,CMMND1
	INC	HL
	LD	(INPOINT),HL	; SAVE INPUT LINE POINTER.
ERASE1:	CALL	DSELECT		; SELECT DESIRED DISK.
	LD	DE,FCB
	CALL	DELETE		; DELETE THE FILE.
	INC	A
	CALL	Z,NONE		; NOT THERE?
	JP	GETBACK		; RETURN TO COMMAND LEVEL NOW.
YESNO:	.DB	"All (Y/N)?",0
;
;**************************************************************
;*
;*            T Y P E   C O M M A N D
;*
;**************************************************************
;
TYPE:	CALL	CONVFST		; CONVERT FILE NAME.
	JP	NZ,SYNERR	; WILD CARDS NOT ALLOWED.
	CALL	DSELECT		; SELECT INDICATED DRIVE.
	CALL	OPENFCB		; OPEN THE FILE.
	JP	Z,TYPE5		; NOT THERE?
	CALL	CRLF		; OK, START A NEW LINE ON THE SCREEN.
	LD	HL,NBYTES	; INITIALIZE BYTE COUNTER.
	LD	(HL),0FFH	; SET TO READ FIRST SECTOR.
TYPE1:	LD	HL,NBYTES
TYPE2:	LD	A,(HL)		; HAVE WE WRITTEN THE ENTIRE SECTOR?
	CP	128
	JP	C,TYPE3
	PUSH	HL		; YES, READ IN THE NEXT ONE.
	CALL	READFCB
	POP	HL
	JP	NZ,TYPE4	; END OR ERROR?
	XOR	A		; OK, CLEAR BYTE COUNTER.
	LD	(HL),A
TYPE3:	INC	(HL)		; COUNT THIS BYTE.
	LD	HL,TBUFF	; AND GET THE (A)TH ONE FROM THE BUFFER (TBUFF).
	CALL	ADDHL
	LD	A,(HL)
	CP	CNTRLZ		; END OF FILE MARK?
	JP	Z,GETBACK
	CALL	PRINT		; NO, PRINT IT.
	CALL	CHKCON		; CHECK CONSOLE, QUIT IF ANYTHING READY.
	JP	NZ,GETBACK
	JP	TYPE1
;
;   GET HERE ON AN END OF FILE OR READ ERROR.
;
TYPE4:	DEC	A		; READ ERROR?
	JP	Z,GETBACK
	CALL	RDERROR		; YES, PRINT MESSAGE.
TYPE5:	CALL	RESETDR		; AND RESET PROPER DRIVE
	JP	SYNERR		; NOW PRINT FILE NAME WITH PROBLEM.
;
;**************************************************************
;*
;*            S A V E   C O M M A N D
;*
;**************************************************************
;
SAVE:	CALL	DECODE		; GET NUMERIC NUMBER THAT FOLLOWS SAVE.
	PUSH	AF		; SAVE NUMBER OF PAGES TO WRITE.
	CALL	CONVFST		; CONVERT FILE NAME.
	JP	NZ,SYNERR	; WILD CARDS NOT ALLOWED.
	CALL	DSELECT		; SELECT SPECIFIED DRIVE.
	LD	DE,FCB		; NOW DELETE THIS FILE.
	PUSH	DE
	CALL	DELETE
	POP	DE
	CALL	CREATE		; AND CREATE IT AGAIN.
	JP	Z,SAVE3		; CAN'T CREATE?
	XOR	A		; CLEAR RECORD NUMBER BYTE.
	LD	(FCB+32),A
	POP	AF		; CONVERT PAGES TO SECTORS.
	LD	L,A
	LD	H,0
	ADD	HL,HL		; (HL)=NUMBER OF SECTORS TO WRITE.
	LD	DE,TBASE	; AND WE START FROM HERE.
SAVE1:	LD	A,H		; DONE YET?
	OR	L
	JP	Z,SAVE2
	DEC	HL		; NOPE, COUNT THIS AND COMPUTE THE START
	PUSH	HL		; OF THE NEXT 128 BYTE SECTOR.
	LD	HL,128
	ADD	HL,DE
	PUSH	HL		; SAVE IT AND SET THE TRANSFER ADDRESS.
	CALL	DMASET
	LD	DE,FCB		; WRITE OUT THIS SECTOR NOW.
	CALL	WRTREC
	POP	DE		; RESET (DE) TO THE START OF THE LAST SECTOR.
	POP	HL		; RESTORE SECTOR COUNT.
	JP	NZ,SAVE3	; WRITE ERROR?
	JP	SAVE1
;
;   GET HERE AFTER WRITING ALL OF THE FILE.
;
SAVE2:	LD	DE,FCB		; NOW CLOSE THE FILE.
	CALL	CLOSE
	INC	A		; DID IT CLOSE OK?
	JP	NZ,SAVE4
;
;   PRINT OUT ERROR MESSAGE (NO SPACE).
;
SAVE3:	LD	BC,NOSPACE
	CALL	PLINE
SAVE4:	CALL	STDDMA		; RESET THE STANDARD DMA ADDRESS.
	JP	GETBACK
NOSPACE:.DB	"No Space",0
;
;**************************************************************
;*
;*           R E N A M E   C O M M A N D
;*
;**************************************************************
;
RENAME:	CALL	CONVFST		; CONVERT FIRST FILE NAME.
	JP	NZ,SYNERR	; WILD CARDS NOT ALLOWED.
	LD	A,(CHGDRV)	; REMEMBER ANY CHANGE IN DRIVES SPECIFIED.
	PUSH	AF
	CALL	DSELECT		; AND SELECT THIS DRIVE.
	CALL	SRCHFCB		; IS THIS FILE PRESENT?
	JP	NZ,RENAME6	; YES, PRINT ERROR MESSAGE.
	LD	HL,FCB		; YES, MOVE THIS NAME INTO SECOND SLOT.
	LD	DE,FCB+16
	LD	B,16
	CALL	HL2DE
	LD	HL,(INPOINT)	; GET INPUT POINTER.
	EX	DE,HL
	CALL	NONBLANK	; GET NEXT NON BLANK CHARACTER.
	CP	'='		; ONLY ALLOW AN '=' OR '_' SEPERATOR.
	JP	Z,RENAME1
	CP	'_'
	JP	NZ,RENAME5
RENAME1:EX	DE,HL
	INC	HL		; OK, SKIP SEPERATOR.
	LD	(INPOINT),HL	; SAVE INPUT LINE POINTER.
	CALL	CONVFST		; CONVERT THIS SECOND FILE NAME NOW.
	JP	NZ,RENAME5	; AGAIN, NO WILD CARDS.
	POP	AF		; IF A DRIVE WAS SPECIFIED, THEN IT
	LD	B,A		; MUST BE THE SAME AS BEFORE.
	LD	HL,CHGDRV
	LD	A,(HL)
	OR	A
	JP	Z,RENAME2
	CP	B
	LD	(HL),B
	JP	NZ,RENAME5	; THEY WERE DIFFERENT, ERROR.
RENAME2:LD	(HL),B		; 	RESET AS PER THE FIRST FILE SPECIFICATION.
	XOR	A
	LD	(FCB),A		; CLEAR THE DRIVE BYTE OF THE FCB.
RENAME3:CALL	SRCHFCB		; AND GO LOOK FOR SECOND FILE.
	JP	Z,RENAME4	; DOESN'T EXIST?
	LD	DE,FCB
	CALL	RENAM		; OK, RENAME THE FILE.
	JP	GETBACK
;
;   PROCESS RENAME ERRORS HERE.
;
RENAME4:CALL	NONE		; FILE NOT THERE.
	JP	GETBACK
RENAME5:CALL	RESETDR		; BAD COMMAND FORMAT.
	JP	SYNERR
RENAME6:LD	BC,EXISTS	; DESTINATION FILE ALREADY EXISTS.
	CALL	PLINE
	JP	GETBACK
EXISTS:	.DB	"File Exists",0
;
;**************************************************************
;*
;*             U S E R   C O M M A N D
;*
;**************************************************************
;
USER:	CALL	DECODE		; GET NUMERIC VALUE FOLLOWING COMMAND.
	CP	16		; LEGAL USER NUMBER?
	JP	NC,SYNERR
	LD	E,A		; YES BUT IS THERE ANYTHING ELSE?
	LD	A,(FCB+1)
	CP	' '
	JP	Z,SYNERR	; YES, THAT IS NOT ALLOWED.
	CALL	GETSETUC	; OK, SET USER CODE.
	JP	GETBACK1
;
;**************************************************************
;*
;*        T R A N S I A N T   P R O G R A M   C O M M A N D
;*
;**************************************************************
;
UNKNOWN:LD	A,(FCB+1)	; ANYTHING TO EXECUTE?
	CP	' '
	JP	NZ,UNKWN1
	LD	A,(CHGDRV)	; NOPE, ONLY A DRIVE CHANGE?
	OR	A
	JP	Z,GETBACK1	; NEITHER???
	DEC	A
	LD	(CDRIVE),A	; OK, STORE NEW DRIVE.
	CALL	MOVECD		; SET (TDRIVE) ALSO.
	CALL	DSKSEL		; AND SELECT THIS DRIVE.
	JP	GETBACK1	; THEN RETURN.
;
;   HERE A FILE NAME WAS TYPED. PREPARE TO EXECUTE IT.
;
UNKWN1:	LD	DE,FCB+9	; AN EXTENSION SPECIFIED?  
	LD	A,(DE)
	CP	' '
	JP	NZ,SYNERR	; YES, NOT ALLOWED.
UNKWN2:	PUSH	DE
	CALL	DSELECT		; SELECT SPECIFIED DRIVE.
	POP	DE
	LD	HL,COMFILE	; SET THE EXTENSION TO 'COM'.  LD HL,COMFILE
	CALL	MOVE3		; MOVE 3 BYTES FROM (HL) TO (DE) TO ADD .COM
	CALL	OPENFCB		; AND OPEN THIS FILE.
	.IF	CHKU0B
	JP	NZ,UNKWNA	; GOT IT
	LD	E,0		; TRY USER 0, THIS DRIVE
	CALL	GETSETUC	; OK, SET USER CODE.
	CALL	OPENFCB
	JP	NZ,UNKWNA	; GOT IT
	LD	HL,FCB		; SEE IF ON DRIVE B, USER 0
	LD	(HL),2
	CALL	OPENFCB
	.ENDIF
	JP	Z,UNKWN9	; NOPE
;
;   LOAD IN THE PROGRAM.
;
UNKWNA:	LD	HL,TBASE	; STORE THE PROGRAM STARTING HERE.
UNKWN3:	PUSH	HL
	EX	DE,HL
	CALL	DMASET		; SET TRANSFER ADDRESS.
	LD	DE,FCB		; AND READ THE NEXT RECORD.
	CALL	RDREC
	JP	NZ,UNKWN4	; END OF FILE OR READ ERROR?
	POP	HL		; NOPE, BUMP POINTER FOR NEXT SECTOR.
	LD	DE,128
	ADD	HL,DE
	LD	DE,CBASE	; ENOUGH ROOM FOR THE WHOLE FILE?
	LD	A,L
	SUB	E
	LD	A,H
	SBC	A,D
	JP	NC,UNKWN0	; NO, IT CAN'T FIT.
	JP	UNKWN3
;
;   GET HERE AFTER FINISHED READING.
;
UNKWN4:	POP	HL
	DEC	A		; NORMAL END OF FILE?
	JP	NZ,UNKWN0
	CALL	RESETDR		; YES, RESET PREVIOUS DRIVE.
	CALL	CONVFST		; CONVERT THE FIRST FILE NAME THAT FOLLOWS
	LD	HL,CHGDRV	; COMMAND NAME.
	PUSH	HL
	LD	A,(HL)		; SET DRIVE CODE IN DEFAULT FCB.
	LD	(FCB),A
	LD	A,16		; PUT SECOND NAME 16 BYTES LATER.
	CALL	CONVERT		; CONVERT SECOND FILE NAME.
	POP	HL
	LD	A,(HL)		; AND SET THE DRIVE FOR THIS SECOND FILE.
	LD	(FCB+16),A
	XOR	A		; CLEAR RECORD BYTE IN FCB.
	LD	(FCB+32),A
	LD	DE,TFCB		; MOVE IT INTO PLACE AT(005CH).
	LD	HL,FCB
	LD	B,33
	CALL	HL2DE
	LD	HL,INBUFF+2	; NOW MOVE THE REMAINDER OF THE INPUT
UNKWN5:	LD	A,(HL)		; LINE DOWN TO (0080H). LOOK FOR A NON BLANK.
	OR	A		; OR A NULL.
	JP	Z,UNKWN6
	CP	' '
	JP	Z,UNKWN6
	INC	HL
	JP	UNKWN5
;
;   DO THE LINE MOVE NOW. IT ENDS IN A NULL BYTE.
;
UNKWN6:	LD	B,0		; KEEP A CHARACTER COUNT.
	LD	DE,TBUFF+1	; DATA GETS PUT HERE.
UNKWN7:	LD	A,(HL)		; MOVE IT NOW.
	LD	(DE),A
	OR	A
	JP	Z,UNKWN8
	INC	B
	INC	HL
	INC	DE
	JP	UNKWN7
UNKWN8:	LD	A,B		; NOW STORE THE CHARACTER COUNT.
	LD	(TBUFF),A
	CALL	CRLF		; CLEAN UP THE SCREEN.
	CALL	STDDMA		; SET STANDARD TRANSFER ADDRESS.
	CALL	SETCDRV		; RESET CURRENT DRIVE.
	CALL	TBASE		; AND EXECUTE THE PROGRAM.
;
;   TRANSIANT PROGRAMS RETURN HERE (OR REBOOT).
;
	LD	SP,BATCH	; SET STACK FIRST OFF.
	CALL	MOVECD		; MOVE CURRENT DRIVE INTO PLACE (TDRIVE).
	CALL	DSKSEL		; AND RESELECT IT.
	JP	CMMND1		; BACK TO COMAND MODE.
;
;   GET HERE IF SOME ERROR OCCURED.
;
UNKWN9:	CALL	RESETDR		; INPROPER FORMAT.
	JP	SYNERR
UNKWN0:	LD	BC,BADLOAD	; READ ERROR OR WON'T FIT.
	CALL	PLINE
	JP	GETBACK
BADLOAD:.DB	"Bad Load",0
COMFILE:.DB	"COM"		; COMMAND FILE EXTENSION.
;
;   GET HERE TO RETURN TO COMMAND LEVEL. WE WILL RESET THE
; PREVIOUS ACTIVE DRIVE AND THEN EITHER RETURN TO COMMAND
; LEVEL DIRECTLY OR PRINT ERROR MESSAGE AND THEN RETURN.
;
GETBACK:CALL	RESETDR		; RESET PREVIOUS DRIVE.
GETBACK1:
	CALL	CONVFST		; CONVERT FIRST NAME IN (FCB).
	LD	A,(FCB+1)	; IF THIS WAS JUST A DRIVE CHANGE REQUEST,
	SUB	' '		; MAKE SURE IT WAS VALID.
	LD	HL,CHGDRV
	OR	(HL)
	JP	NZ,SYNERR
	JP	CMMND1		; OK, RETURN TO COMMAND LEVEL.
;
;   CCP STACK AREA.
;
	.DB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
CCPSTACK:	.EQU	$	;END OF CCP STACK AREA.

;
;   BATCH (OR SUBMIT) PROCESSING INFORMATION STORAGE.
;
BATCH:	.DB	0			; BATCH MODE FLAG (0=NOT ACTIVE).
BATCHFCB:.DB	0,"$$$     SUB"
	.DB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;
;   FILE CONTROL BLOCK SETUP BY THE CCP.
;
FCB:	.DB	0,"           ",0,0,0,0,0
	.DB	"           ",0,0,0,0,0
RTNCODE:.DB	0			; STATUS RETURNED FROM BDOS CALL.
CDRIVE:	.DB	0			; CURRENTLY ACTIVE DRIVE.
CHGDRV:	.DB	0			; CHANGE IN DRIVES FLAG (0=NO CHANGE).
NBYTES:	.DW	0			; BYTE COUNTER USED BY TYPE.

	.IF	ENDFIL
	.FILL	((CCPO + 0800H) - $),055H
	.ENDIF

	.END
