;  CONSOLE COMMAND PROCESSOR
;
;  FOR CP/M 86
;
;  1983.8.8.
;
;  EQUATIONS OF BDOS FUNCTION
;
CRSTSY	EQU	0		;RESET SYSTEM
CCONIN	EQU	1		;CONSOLE INPUT
CCONOT	EQU	2		;CONSOLE OUTPUT
CRDCBF	EQU	10		;READ CONSOLE BUFFER
CCONST	EQU	11		;CONSOLE STATUS
CINBDS	EQU	13		;INITIALIZE BDOS
CSELDR	EQU	14		;SELECT DRIVE
COPEN	EQU	15		;OPEN FILE
CCLOSE	EQU	16		;CLOSE FILE
CSERCH	EQU	17		;SEARCH DIRECTORY FIRST
CSERCN	EQU	18		;SEARCH NEXT
CDELET	EQU	19		;DELETE FILE
CREADN	EQU	20		;READ SEQUENTIAL
CRENAM	EQU	23		;RENAME
CGTDRV	EQU	25		;INTERROGATE DRIVE
CSTDMA	EQU	26		;SET DMA OFFSET
CGTUSR	EQU	32		;GET/SET USER CODE
CDBIOS	EQU	50		;DIRECT BIOS CALL
CSTDMS	EQU	51		;SET DMA SEGMENT
CMFREE	EQU	58		;FREE ALL MEMORY
CLOADP	EQU	59		;LOAD PROGRAM
;
;  EQUATIONS OF DATA
;
BDOSI	EQU	0E0H		;BDOS INTERRUPT
LF	EQU	0AH		;LINE FEED
CR	EQU	0DH		;CARRIAGTE RETURN
EOF	EQU	1AH		;END OF FILE
SCTLNG	EQU	128		;ONE SECTOR DATA LENGTH
;
BDOS	EQU	.0B00H		;BODS ENTRY
;
;  EQUATIONS OF BASE PAGE OFFSET
;
DFPAGE	EQU	0		;BASE PAGE TOP
DFESSG	EQU	0FH		;EXTRA SEGMENT
DFCB	EQU	5CH		;DEFAULT FCB
DFCMBF	EQU	80H		;DEFAULT COMMAND BUFFER
SYSDMA	EQU	80H		;SYSTEM DMA ADDRESS
;
;
	CSEG
	ORG	0
;
TOP:				;TAG FOR BIASED ADDRESS
;
;  CCP ENTRY JUMP TABLE
;
	JMP	CCPCLD		;COLD START
	JMP	CCPABE
	JMP	CCPHOT		;HOT START
;
;  COMMAND READ BUFFER
;
CMBUFF	DB	127		;BUFFER LENGTH
	DB	0		;LENGTH OF CODE
	DB	'                '
	DB	'COPYRIGHT (C) 1980, '
	DB	'DIGITAL RESEARCH  '
	RS	74
;
;  TO BDOS
;
ENBDOS:
	INT	BDOSI		;TO BDOS
	MOV	BP,CS
	MOV	ES,BP
	RET
;
;  SYSTEM RESET
;
SYSRST:
	MOV	CL,CRSTSY
	XOR	DX,DX
	JMPS	ENBDOS
;
;  CONSOLE OUT
;  INPUT
;  AL:CODE
;
CONOUT:
	MOV	DL,AL
	MOV	CL,CCONOT
	JMPS	ENBDOS
;
;  SPACE
;
SPACE:
	MOV	AL,' '
CONOTB:
	PUSH	CX
	CALL	CONOUT
	POP	CX
	RET
;
;  CARRIAGE RETURN & LINE FEED
;
CRLF:
	MOV	AL,CR
	CALL	CONOTB
	MOV	AL,LF
	JMPS	CONOTB
;
;  PRINT BUFFERED STRING
;  INPUT
;  CX:STRING POINTER
;
BUFPRN:
	PUSH	CX
	CALL	CRLF
	POP	BX
BUFPRL:
	MOV	AL,[BX]		;GET CODE
	OR	AL,AL
	JNZ	BUFPRS		;GET ACTIVE CODE
	RET			;END BY 0
;
BUFPRS:
	INC	BX
	PUSH	BX
	CALL	CONOUT
	POP	BX
	JMPS	BUFPRL		;TO NEXT
;
;  LOAD PROGRAM
;
LOADPR:
	MOV	DX,OFFSET WKFCB
	MOV	CL,CLOADP
	JMPS	ENBDOS
;
;  DIRECT BIOS SELECT DISK
;
SELDSK:
	MOV	CX,CDBIOS
	MOV	DX,OFFSET WKBIOS
	JMPS	ENBDOS
;
;  FREE ALL MEMORY
;
MEMFRE:
	MOV	CL,CMFREE
	JMPS	ENBDOS
;
;  INITIALIZE BDOS
;
INBDOS:
	MOV	CL,CINBDS
	JMPS	ENBDOS
;
;  SELECT DRIVE
;  INPUT
;  AL:DRIVE NUMBER
;
SELDRV:
	MOV	DL,AL
	MOV	CL,CSELDR
	JMPS	ENBDOS
;
;  DIRECTORY PROCESS COMMON
;  OUTPUT
;  ZF:ON ERROR
;
DIRCOM:
	CALL	ENBDOS
	MOV	BSDIRC,AL	;SAVE BIAS OF DIRECTORY
	INC	AL
	RET
;
;  OPEN FILE
;
OPEN:
	MOV	CL,COPEN
	JMPS	DIRCOM
;
;  OPEN BY WORK FCB
;
OPENW:
	MOV	WKFCB+32,0	;CLEAR CURRENT RECORD
	MOV	DX,OFFSET WKFCB
	JMPS	OPEN
;
;  CLOSE FILE
;
CLOSE:
	MOV	CL,CCLOSE
	CALL	DIRCOM
	JZ	CLOSER
	RET
;
CLOSER:				;CLOSE ERROR
	MOV	CX,OFFSET CCLSER
	JMPS	WHYPR
;
;  SEARCH FIRST
;
SEARCH:
	MOV	CL,CSERCH
	JMPS	DIRCOM
;
;  SEARCH NEXT
;
SEARCN:
	MOV	CL,CSERCN
	JMPS	DIRCOM
;
;  SEARCH BY WORK FCB
;
SEARCW:
	MOV	DX,OFFSET WKFCB
	JMPS	SEARCH
;
;  DELETE FILE
;
DELETF:
	MOV	CL,CDELET
	JMPS	TENBDS
;
;  READ WRITE COMMON
;  OUTPUT
;  ZF:ON OK
;
FRWCOM:
	CALL	ENBDOS
	OR	AL,AL
	RET
;
;  READ SEQUENTIAL
;
READNX:
	MOV	CL,CREADN
	JMPS	FRWCOM
;
;  READ WORK FCB FILE
;
READNW:
	MOV	DX,OFFSET WKFCB
	JMPS	READNX
;
;  ERROR COMMENT OUT & END
;
WHYPR:
	CALL	BUFPRN
	JMP	ENCPRC
;
;  RENAME
;
RENAME:
	MOV	CL,CRENAM
	JMPS	TENBDS
;
;  GET/SET USER CODE
;
GETUSR:
	MOV	DL,0FFH
GETUSS:
	MOV	CL,CGTUSR
TENBDS:
	JMP	ENBDOS
;
;  MODIFY LOWER CASE TO UPER CASE ALPHABET
;  INPUT/OUTPUT
;  AL:CODE
;
MODIFY:
	CMP	AL,'A'+20H
	JC	MODIFE		;TOO SMALL
	CMP	AL,'Z'+21H
	JNC	MODIFE		;TOO LARGE
	AND	AL,05FH		;TO LOWER CASE
MODIFE:
	RET
;
;  READ COMMAND LINE
;
RDCOMN:
	TEST	MDSUBE,0FFH
	JZ	RDCOMK		;NO SUBMIT FILE TO KEY INPUT
	TEST	CURDRV,0FFH
	JZ	RDCOMS		;CURRENT DRIVE IS HOME
	XOR	AX,AX
	CALL	SELDRV		;TO HOME DRIVE
RDCOMS:
	MOV	DX,OFFSET SUBFCB
	CALL	OPEN		;OPEN SUBMIT FILE
	JZ	RDCOMK		;NOT FOUND SO TO KEY INPUT
	MOV	AL,SUBFCB+15
	DEC	AL
	MOV	SUBFCB+32,AL	;SET BOTTOM RECORD OF FILE
	MOV	DX,OFFSET SUBFCB
	CALL	READNX		;GET LAST LINE
	JNZ	RDCOMK		;READ ERROR SO TO KEY INPUT
	MOV	DI,OFFSET CMBUFF+1
	MOV	SI,OFFSET RWBUFF
	MOV	CX,SCTLNG
	CALL	COPY		;MOVE TO COMMAND BUFFER
	MOV	SUBFCB+14,0	;CLEAR EXTENT
	DEC	SUBFCB+15	;DOWN LENGTH
	MOV	DX,OFFSET SUBFCB
	CALL	CLOSE		;SET RECORD COUNT
	JZ	RDCOMK		;CLOSE ERROR SO TO KEY INPUT
	MOV	AL,CURDRV
	CALL	SELDRV		;TO CURRENT DRIVE
	MOV	BX,OFFSET CMBUFF+2
	CALL	BUFPRL		;OUT CURRENT COMMAND LINE
	CALL	CHKCIT		;CHECK KEY INTERRUPT
	JZ	RDCOMD		;OK TO INTERPRET COMMAND LINE
	CALL	DELSUB		;CANCEL SUBMIT MODE
	JMP	CCPLOP
;
RDCOMK:				;KEY INPUT MODE
	CALL	DELSUB		;DELETE SUBMIT FILE
	MOV	CL,CRDCBF
	MOV	DX,OFFSET CMBUFF
	CALL	ENBDOS		;GET COMMAND FROM KEY
RDCOMD:
	MOV	BX,OFFSET CMBUFF+2
	XOR	CX,CX
	MOV	CL,CMBUFF+1	;GET COUNT
	JCXZ	RDCOME		;NO LENGTH
RDCOML:				;COMMAND LINE MODIFY LOOP
	MOV	AL,[BX]
	CALL	MODIFY		;LOWER CASE TO UPER CASE
	MOV	[BX],AL
	INC	BX
	LOOP	RDCOML
RDCOME:
	MOV	[BX],CH		;SET END MARK
	MOV	PNTCMD,OFFSET CMBUFF+2 ;SET COMMAND POINTER TO TOP
	RET
;
;  CHECK KEY INTERRUPT
;  OUTPUT
;  ZF:OFF INTERRUPTED
;
CHKCIT:
	MOV	CL,CCONST
	CALL	ENBDOS
	OR	AL,AL
	JNZ	CHKCIG		;GET SOME DATA
	RET			;NOT INTERRUPTED
;
CHKCIG:
	MOV	CL,CCONIN
	CALL	ENBDOS		;GET DATA
	OR	AL,AL		;SET FLAG
	RET
;
;  INTERROGATE DRIVE NUMBER
;
GTDRVN:
	MOV	CL,CGTDRV
	JMPS	STDMAC
;
;  SET DMA SEGMENT
;
STDMAS:
	MOV	CL,CSTDMS
	JMPS	STDMAC
;
;  SET DEFAULT DMA ADDRESS
;
STDMAA:
	MOV	DX,DDMASG
	CALL	STDMAS
	MOV	DX,SYSDMA	;SYSTEM DMA ADDRESS OFFSET
;
;  SET DMA OFFSET
;
STDMAO:
	MOV	CL,CSTDMA
STDMAC:
	JMP	ENBDOS
;
;  DELETE SUBMIT FILE
;
DELSUB:
	TEST	MDSUBE,0FFH
	JNZ	DELSUS		;EXIST SUBMIT FILE
	RET			;NO SUBMIT FILE
;
DELSUS:
	MOV	AL,0
	MOV	MDSUBE,AL	;CLEAR SUBMIT FILE EXIST MODE
	CALL	SELDRV		;TO HOME DRIVE
	MOV	DX,OFFSET SUBFCB
	CALL	DELETF		;DELETE SUBMIT FILE
	MOV	AL,CURDRV
	JMP	SELDRV		;TO CURRENT DRIVE
;
;  CHECK USER ID CODE
;
CHKUID:
	MOV	DI,OFFSET IDCODE
	MOV	SI,OFFSET BDOS	;ID CODE IN BDOS
	MOV	CX,6		;ID CODE LENGTH
	REPZ	CMPSB
	JCXZ	CHKUIP		;OK END
	JMPS	CHKUIM		;MISS MATCH
;
CHKUIP:
	RET
;
CHKUIM:				;MISS MATCH STOP
	HLT
;
;  CHECK TERMINATOR
;  INPUT
;  SI:DATA POINTER
;  OUTPUT
;  ZF:ON TERMINATOR
;
CHKTRM:
	MOV	AL,[SI]		;GET CODE
	OR	AL,AL
	JNZ	CHKTRN
	RET			;ZERO IS END CODE
;
CHKTRN:
	CMP	AL,' '
	JNC	CHKTRT
	JMP	COMERR		;CONTROL CODE SO ERROR
;
CHKTRT:
	PUSH	DI
	MOV	DI,OFFSET IXTERM
	MOV	CX,9
	CLD
	REPNZ	SCASB		;CHECK
	POP	DI
	RET
;
;  SEARCH TOP
;  OUTPUT
;  ZF:ON NO DATA
;
SRCHTP:
	MOV	AL,[SI]
	CMP	AL,0
	JNZ	SRCHTT
	RET			;END OF DATA
;
SRCHTT:
	CMP	AL,' '
	JZ	SRCHTN		;TO NEXT
	RET			;GET SOME CODE
;
SRCHTN:				;TO NEXT
	INC	SI
	JMPS	SRCHTP
;
;  FILL BY SPACE  FOR FILE NAME
;
FILLSP:
	INC	BX
	MOV	BYTE PTR [BX],' '
	LOOP	FILLSP
	RET
;
;  GET ONE COMMAND BLOCK
;  INPUT
;  CX:BLOCK LENGTH
;  BX:DESTINATION POINTER
;  SI:SOURCE POINTER
;
GTONBK:
	PUSH	CX
	CALL	CHKTRM		;CHECK TERMINATOR
	POP	CX
	JZ	FILLSP		;GET TERMINATOR SO END
	INC	BX
	CMP	AL,'*'
	JNZ	GTONBN		;NORMAL CODE
	MOV	AL,'?'		;WILD CARD
	JMPS	GTONBG
;
GTONBN:				;NORMAL CODE
	INC	SI
GTONBG:
	MOV	[BX],AL		;SET CODE
	LOOP	GTONBK
GTONBF:				;OVER COUNT CODE PASS READ
	CALL	CHKTRM
	JZ	GTONBE		;GET TERMINATOR
	INC	SI
	JMPS	GTONBF		;TO NEXT
;
GTONBE:
	RET
;
;  GET FILE NAME
;  OUTPUT
;  AH:WILD CARD COUNT  -1 ERROR
;  ZF:ON NO WILD CARD
;
GTFNAM:				;READ NORMAL
	MOV	AX,0
GTFNAS:
	MOV	BX,OFFSET WKFCB
	ADD	BX,AX		;GET FCB TOP
	PUSH	BX
	MOV	TDRVNU,0	;CLEAR TEMPORARY DRIVE
	MOV	SI,PNTCMD	;GET COMMAND POINTER
	CALL	SRCHTP		;GET TOP
	MOV	TPNCMD,SI	;SAVE TEMPORARY TOP FOR RECOVER
	JZ	GTFNAC		;END OF DATA
	SBB	AL,'A'-1
	CMP	BYTE PTR 1[SI],':'
	JZ	GTFNAT		;WITH DRIVE CODE
GTFNAC:				;NO DRIVE SPECIFICATION
	MOV	AL,CURDRV
	JMPS	GTFNAN
;
GTFNAT:				;WITH DRIVE CODE
	CMP	AL,16
	JA	GTFNAR		;OVER
	CMP	AL,0
	JA	GTFNAD		;OK IN RANGE
GTFNAR:				;DRIVE NUMBER MISS
	MOV	AH,0FFH
	POP	BX
	JMPS	GTFNAE
;
GTFNAD:				;WITH DRIVE CODE
	MOV	TDRVNU,AL	;SET DRIVE
	INC	SI
	INC	SI
GTFNAN:
	MOV	[BX],AL		;SET DRIVE CODE
	MOV	CX,8
	CALL	GTONBK		;GET FILE NAME
	MOV	CX,3
	CMP	AL,'.'
	JNZ	$+3		;NOT AVAILABLE TERMINATOR
	INC	SI
	CALL	GTONBK		;GET FILE TYPE
	INC	BX
	MOV	DI,BX
	MOV	AX,CX
	MOV	CX,3
	CLD
	XOR	AX,AX
	REP	STOSB		;CLEAR EXTENT & RECORD COUNT
	MOV	PNTCMD,SI	;SET NEXT POINT TO COMMAND POINTER
	POP	BX
	MOV	CX,11		;FILE NAME LENGTH
GTFNAW:				;CHECK WILD CARD
	INC	BX
	CMP	BYTE PTR [BX],'?'
	JNZ	$+4
	INC	AH		;WILD CARD
	LOOP	GTFNAW
	MOV	AL,[SI]		;GET NEXT CODE
GTFNAE:
	OR	AH,AH		;SET FLAG BY WILD CARD COUNT
	RET
;
;  CHECK RESIDENT COMMAND
;  OUTPUT
;  AX:CODE  1-6 RESIDENT COMMAND 7 NOT FOUND
;
CKRSCM:
	MOV	DI,OFFSET IXRSCM
	MOV	BX,6		;COUNT OF COMMAND
CKRSCL:
	MOV	SI,OFFSET WKFCB+1
	MOV	CX,4		;COMPARE LENGTH
	REPZ	CMPSB
	JZ	CKRSCG		;OK GET
	ADD	DI,CX		;FAIL TO NEXT
	DEC	BX
	JNZ	CKRSCL
CKRSCE:				;NOT FOUND END
	MOV	AL,7		;NOT FOUND CODE      AX IS BETTER
	RET
;
CKRSCG:				;MATCH FIRST 4 BYTES
	MOV	AL,[SI]
	CMP	AL,' '
	JNZ	CKRSCE		;ERROR NET CODE MUST BE SPACE
	MOV	AX,BX		;OK SET NUMBER
	RET
;
;  SET DMA ADDRESS TO R/W WORK
;
STWKDM:
	MOV	DX,CS
	CALL	STDMAS		;SET DMA SEGMENT
	MOV	DX,OFFSET RWBUFF
	CALL	STDMAO		;SET OFFSET
	RET
;
;  CCP MAIN
;
;  HOT START
;
CCPHOT:
	MOV	PNTCMD,OFFSET CMBUFF+2 ;SET COMMAND POINTER
	CMP	CMBUFF+2,3	;CTRL-C
	JNZ	CCPHOC		;COMMAND BUFFER IS ACTIVE
	MOV	CMBUFF+1,0	;COMMAND BUFFER CANCELED
CCPHOC:
	MOV	SP,OFFSET STACK
	CALL	STDRUC		;SET USER CODE & DRIVE
	JMPS	CCPLOE
;
;
CCPABE:				;ABORT ENTRY
	MOV	CMBUFF+1,0
;
;  COLD START
;  INPUT
;  CL:USER CODE & DRIVE
;
CCPCLD:
	MOV	SP,OFFSET STACK
	PUSH	CX
	MOV	AL,CL
	MOV	CL,4
	RCR	AL,CL
	AND	AL,00FH		;GET USER CODE
	MOV	DL,AL
	MOV	USRCOD,AL
	CALL	GETUSS		;SET USER CODE
	CALL	INBDOS
	MOV	MDSUBE,AL	;SAVE SUBMIT MODE
	CALL	MEMFRE		;FREE ALL MEMORY
	POP	AX
	AND	AL,0FH
	MOV	CURDRV,AL	;DRIVE
	CALL	SELDRV		;SET DRIVE
CCPLOE:
	CALL	STWKDM		;SET DMA ADDRESS TO WORK
	CMP	CMBUFF+1,0
	JNZ	CCPLOS		;SOME DATA
;
;  LOOP OF CCP
;
CCPLOP:
	CLD
	MOV	SP,OFFSET STACK
	CALL	CRLF
	CALL	GTDRVN		;GET CURRENT DRIVE
	ADD	AL,'A'
	CALL	CONOUT
	MOV	AL,'>'
	CALL	CONOUT		;X>  OUT PROMPT
	CALL	STWKDM		;SET DMA ADDRESS
	CALL	RDCOMN		;READ COMMAND
CCPLOS:
	CLD
	CALL	GTDRVN		;GET DRIVE
	MOV	CURDRV,AL	;SAVE CURRENT DRIVE
	CMP	CMBUFF+2,';'
	JZ	CCPLOP		;COMMENT LINE TO NEXT
	MOV	SI,PNTCMD	;GET COMMAND POINT
	CALL	SRCHTP		;TO TOP OF CODE
	JZ	CCPLOP		;NO CODE
	CALL	GTFNAM		;GET COMMAND
	JNZ	COMERR		;WILD CARD IS ERROR
	TEST	TDRVNU,0FFH
	JZ	$+5		;CHECK RESIDENT COMMAND
	JMP	TRCDSL		;NOT RESIDENT COMMAND AS SOME DRIVE SPECIFIED
;
	CMP	WKFCB+1,' '
	JZ	COMERR		;NO CODE SO ERROR
	CALL	CKRSCM		;CHECK RESIDENT COMMAND
	DEC	AX
	MOV	BX,OFFSET IXRSRT
	ADD	BX,AX
	ADD	BX,AX
	MOV	DX,[BX]		;GET ROUTINE
	JMP	DX		;TO EACH ROUTINE
;
;  READ ERROR
;
REDERR:
	MOV	CX,OFFSET CRDERR
	JMPS	FNFERS
;
;  FILE NOT FOUND
;
FNFERR:
	MOV	CX,OFFSET CNOFIL
FNFERS:
	JMP	BUFPRN
;
;  COMMAND ERROR
;
COMERR:
	CALL	CRLF
	MOV	BX,TPNCMD	;CURRENT PROCESSED COMMAND TOP
COMERL:
	MOV	AL,[BX]
	CMP	AL,' '
	JZ	COMERE		;END OF BLOCK
	OR	AL,AL
	JZ	COMERE
	PUSH	BX
	CALL	CONOUT		;OUT COMMAND LINE
	POP	BX
	INC	BX
	JMPS	COMERL
;
COMERE:
	MOV	AL,'?'
	CALL	CONOUT
	CALL	CRLF
	MOV	CMBUFF+1,0	;CANCEL CURRENT COMMAND LINE
	JMP	CCPLOP
;
;  GET DECIMAL NUMBER
;  OUTPUT
;  AL:NUMBER BY BINARY		NO DATA 21H
;
GTDNUM:
	CALL	GTFNAM		;GET BLOCK
	TEST	TDRVNU,0FFH
	JNZ	COMERR		;CANNOT HAVE DRIVE NAME
	MOV	BX,OFFSET WKFCB+1
	MOV	CX,11		;CODE MAX LENGTH & DATA 0
	CMP	BYTE PTR [BX],' '
	JNZ	GTDNUL		;SOME CODE
	MOV	AL,021H		;NO CODE
	RET
;
GTDNUL:
	MOV	AL,[BX]
	CMP	AL,' '
	JZ	GTDNUE		;END OF CODE
	INC	BX
	SUB	AL,'0'
	CMP	AL,10
	JNC	COMERR		;ILLEGAL CHARACTER
	MOV	DH,AL
	TEST	CH,0E0H
	JNZ	COMERR		;OVERFLOW
	MOV	AL,CH
	MOV	CL,3
	ROL	AL,CL		;*8
	ADD	AL,CH		;*9
	JC	COMERR		;OVER
	ADD	AL,CH		;*10
	JC	COMERR		;OVER
	ADD	AL,DH
	JC	COMERR		;OVER
	MOV	CH,AL		;TO NEXT
	DEC	CL
	JNZ	GTDNUL
	RET			;LENGTH FULL
;
GTDNUE:
	CMP	BYTE PTR [BX],' '
	JNZ	COMERR		;END FORM ERROR
	INC	BX
	DEC	CL
	JNZ	GTDNUE
	MOV	AL,CH
	RET
;
;  COPY DATA
;  INPUT
;  DI:DESTINATION POINTER
;  SI:SOURCE POINTER
;  CX:LENGTH COUNT
;
COPY:
	CLD
	REP	MOVSB
	RET
;
;  GET DIRECTORY TOP
;  INPUT
;  AL:BIAS 1
;  CL:BIAS 2
;
GTDRTP:
	MOV	BX,OFFSET RWBUFF
	MOV	AH,0
	ADD	AL,CL
	ADD	BX,AX
	MOV	AL,[BX]		;GET CODE
	RET
;
;  SELECT TARGET DRIVE
;
SLTGDR:
	MOV	WKFCB,0
	MOV	AL,TDRVNU
	OR	AL,AL
	JZ	SLCRDE		;DEFAULT
	DEC	AL
	MOV	BX,OFFSET CURDRV
	CMP	AL,[BX]		;CHECK WITH CURRENT
	JZ	SLCRDE		;SAME
	JMPS	SLCRDD		;SELECT DRIVE
;
;  SET USER CODE & DRIVE
;
STDRUC:
	MOV	DL,USRCOD
	CALL	GETUSS		;SET USER CODE
	JMPS	SLCRDS		;SELECT DRIVE
;
;  SELECT TO CURRENT DRIVE
;
SLCRDR:
	MOV	AL,TDRVNU
	OR	AL,AL
	JZ	SLCRDE		;CURRENT DRIVE
	DEC	AL
	MOV	BX,OFFSET CURDRV
	CMP	AL,[BX]
	JNZ	SLCRDS		;NOT SAME DRIVE
SLCRDE:
	RET
;
SLCRDS:				;SELECT TO CURRENT DRIVE
	MOV	AL,CURDRV
SLCRDD:
	JMP	SELDRV
;
;  DIRS:DIRECTORY OUT OF SYSTEM FILE
;
DIRSYS:
	MOV	MODDIR,1	;TO SYSTEM FILE MODE
	CALL	DIROUT		;DIRECTORY OUT BODDY
	CMP	MODIRE,0
	JZ	DIRSYE		;NO NON-SYSTEM FILE
	MOV	CX,OFFSET CNSYSF
	CALL	BUFPRN		;WITH NON-SYSTEM FILE
DIRSYE:
	JMPS	DIRNOE
;
;  DIR:DIRECTORY OUT OF NON-SYSTEM FILE
;
DIRNON:
	MOV	MODDIR,0	;TO NON-SYSTEM FILE MODE
	CALL	DIROUT
	CMP	MODIRE,0
	JZ	DIRNOE		;NO SYSTEM FILE
	MOV	CX,OFFSET CSYSFL
	CALL	BUFPRN		;WITH SYSTEM FILE
DIRNOE:
	JMP	ENCPRC
;
;  DIRECTORY OUT BODDY
;
DIROUT:
	MOV	CMBUFF+1,0	;CLEAR COMMAND COUNT
	MOV	MODIRE,0	;CLEAR UNVISIBLE DIRECTORY EXIST MODE
	CALL	GTFNAM		;GET FILE NAME
	CMP	AH,0FFH
	JNZ	DIROUG		;OK GET SOME NAME
	JMP	COMERR		;FILE NAME ERROR
;
DIROUG:
	CALL	SLTGDR		;TO TARGET DRIVE
	MOV	BX,OFFSET WKFCB+1
	CMP	BYTE PTR [BX],' '
	JNZ	DIROUS		;EXIST SOME FILE NAME
	MOV	CH,11
DIROUW:				;FILL WILD CARD
	MOV	BYTE PTR [BX],'?'
	INC	BX
	DEC	CH
	JNZ	DIROUW
DIROUS:
	MOV	DL,0		;CLEAR POSITION COUNT
	PUSH	DX
	CALL	SEARCW		;SEARCH FIRST
	JNZ	DIROUL		;GET FIRST
	CALL	FNFERR		;NOT FOUND END
DIROUL:				;ONE DIRECTORY OUT LOOP
	JNZ	DIROUO		;GET FILE
	JMP	DIROUE		;END OF DIRECTORY
;
DIROUO:				;GET FILE
	MOV	AL,BSDIRC
	MOV	CL,3
	ROR	AL,CL		;GET BIAS TO DIRECTORY DATA
	MOV	CL,AL
	MOV	AL,10
	CALL	GTDRTP		;GET SYSTEM FILE MODE BYTE
	RCL	AL,1
	JNC	DIRONS		;NON-SYSTEM FILE
	TEST	MODDIR,0FFH	;SYSTEM FILE
	JNZ	DIROUD		;SYSTEM FILE  OUT MODE
	MOV	MODIRE,1	;NOT OUT MODE SO SET FLAG
	JMPS	DIRONO
;
DIRONS:				;NON-SYSTEM FILE
	TEST	MODDIR,0FFH
	JZ	DIROUD		;NON-SYSTEM FILE OUT MODE
	MOV	MODIRE,1	;NOT OUT MODE SET FLAG
	JMPS	DIRONO
;
DIROUD:				;OUT FILE NAME
	POP	DX
	MOV	AL,DL
	INC	DL		;UP DISPLAY POSITION COUNT
	PUSH	DX
	JMP	DIRPAT		;GET DISPLAY WIDTH MODE
;
DIROUP:
	AND	AL,3		;GET POSITION
	PUSH	AX
	JNZ	DIRONP		;NOT LINE TOP
	CALL	CRLF		;LINE TOP
	PUSH	CX
	CALL	GTDRVN
	POP	CX
	ADD	AL,'A'
	CALL	CONOTB		;OUT DRIVE NAME
	MOV	AL,':'
	CALL	CONOTB
	JMPS	DIRONN
;
DIRONP:				;NOT LINE TOP
	CALL	SPACE
	MOV	AL,':'
	CALL	CONOTB
DIRONN:
	CALL	SPACE
	MOV	CH,1		;CHARACTER COUNT
DIRONL:
	MOV	AL,CH
	CALL	GTDRTP		;GET DATA
	AND	AL,07FH
	CMP	AL,' '
	JNZ	DIROON		;EXIST CODE
	POP	AX
	PUSH	AX
	CMP	AL,3
	JNZ	DIROSP		;NOT END POSITION
	MOV	AL,9
	CALL	GTDRTP		;GET TYPE
	AND	AL,07FH
	CMP	AL,' '
	JZ	DIRONX		;TO LINE END
DIROSP:				;OUT SPACE
	MOV	AL,' '
DIROON:
	CALL	CONOTB		;OUT CODE
	INC	CH
	CMP	CH,12
	JNC	DIRONX		;ALL CODE END
	CMP	CH,9
	JNZ	DIRONL
	CALL	SPACE		;NAME TO TYPE
	JMPS	DIRONL
;
DIRONX:				;END OF ONE FILE NAME OUT
	POP	AX
DIRONO:
	CALL	CHKCIT		;CHECK CONSOLE INTERRUPT
	JNZ	DIROUE		;INTERRUPTED
	CALL	SEARCN		;TO NEXT
	JMP	DIROUL
;
DIROUE:				;DIRECTORY OUT END
	POP	DX
	RET
;
;  ERA:ERASE FILE
;
ERASE:
	MOV	CMBUFF+1,0	;CLEAR COMMAND COUNTER
	CALL	GTFNAM		;GET FILE NAME
	CMP	AH,11
	JNZ	ERASES		;NOT ALL ERASE
	MOV	CX,OFFSET CALLOK
	CALL	BUFPRN		;ALL ERASE
	CALL	RDCOMN		;CHECK ERASE OK
	MOV	BX,OFFSET CMBUFF+1
	DEC	BYTE PTR [BX]
	JZ	ERASEA		;RESPONSE LENGTH OK
	JMP	CCPLOP		;RESPONSE IS NOT SUITABLE
;
ERASEA:
	INC	BX
	CMP	BYTE PTR [BX],'Y'
	JZ	ERASEO		;OK ERASE
	JMP	CCPLOP		;CANCEL
;
ERASEO:				;ERASE
	INC	BX
	MOV	PNTCMD,BX	;SET COMMAND POINTER
ERASES:
	CMP	WKFCB+1,' '
	JZ	TYPERR		;NO FILE SPECIFICATION
	CALL	SLTGDR		;TO TARGET DRIVE
	MOV	DX,OFFSET WKFCB
	CALL	DELETF		;DELETE
	INC	AL
	JNZ	ERASEN		;OK ERASED
ERASNF:				;NOT FOUND
	CALL	FNFERR
ERASEN:
	JMPS	TYPEOF
;
;  TYPE:TYPE OUT FILE
;
TYPEOT:
	MOV	CMBUFF+1,0	;CLEAR COMMAND LENGTH
	CALL	GTFNAM		;GET FILE NAME
	JNZ	TYPERR		;CANNOT HAVE WILD CARD
	CMP	WKFCB+1,' '
	JZ	TYPERR		;NO FILE NAME
	CALL	SLTGDR		;TO TARGET DRIVE
	CALL	OPENW		;OPEN
	JZ	ERASNF		;NOT FOUND
	CALL	CRLF
	MOV	BX,255		;DUMMY FOR READ FIRST SECTOR
TYPEOL:				;ONE BYTE OUT LOOP
	CMP	BX,SCTLNG
	JC	TYPEOS		;NOT SECTOR BOUNDARY
	PUSH	BX		;TO NEXT SECTOR
	CALL	READNW		;GET ONE SECTOR
	POP	BX
	JNZ	TYPEOE		;END OR ERROR
	MOV	BX,0
TYPEOS:
	INC	BX
	MOV	SI,OFFSET RWBUFF-1
	ADD	SI,BX		;GET DATA POINT
	MOV	AL,[SI]
	CMP	AL,EOF
	JZ	TYPEOF		;END OF FILE
	PUSH	BX
	CALL	CONOUT		;OUT CODE
	CALL	CHKCIT		;CHECK CONSOLE INTERRUPT
	POP	BX
	JNZ	TYPEOF		;INTERRUPTED END
	JMPS	TYPEOL		;TO NEXT CHARATCTER
;
TYPEOE:				;END OR ERROR
	DEC	AL
	JNZ	TYPEOR		;READ ERROR
TYPEOF:				;END OF COMMAND
	JMP	ENCPRC
;
TYPEOR:				;READ ERROR
	CALL	REDERR
	CALL	SLCRDR		;TO CURRENT DRIVE
TYPERR:				;ERROR
	JMP	COMERR
;
;  REN:RENAME FILE
;
RENAMP:
	MOV	CMBUFF+1,0	;CLEAR COMMAND COUNT
	CALL	GTFNAM		;GET NEW FILE NAME
	JNZ	TYPERR		;CANNOT HAVE WILD CARD
	MOV	AL,TDRVNU
	PUSH	AX		;SAVE DRIVE
	CALL	SLTGDR		;TO TARGET DRIVE
	CALL	SEARCW		;SEARCH
	JZ	RENAMS		;NOT FOUND OK
	JMPS	RENADP		;DUPLICATE FILE ERROR
;
RENAMS:
	MOV	SI,OFFSET WKFCB
	MOV	DI,OFFSET WKFCB+16
	MOV	CX,16
	CALL	COPY		;SET TO NEW NAME POSITION
	MOV	SI,PNTCMD
	CALL	SRCHTP		;GET NEXT TOP
	CMP	AL,'='
	JZ	RENAMF		;TERMINATOR OK
	CMP	AL,'_'
	JNZ	RENAER		;TERMINATOR ERROR
RENAMF:
	INC	SI
	MOV	PNTCMD,SI
	CALL	GTFNAM		;GET OLD FILE NAME
	JNZ	RENAER		;CANNOT HAVE WILD CARD
	POP	AX
	MOV	CH,AL
	MOV	BX,OFFSET TDRVNU
	MOV	AL,[BX]
	OR	AL,AL
	JZ	RENAMK		;NO DRIVE SPECIFICATION
	CMP	AL,CH
	MOV	[BX],CH
	JNZ	RENAER		;DIFFERENT DRIVE IS ERROR
RENAMK:
	MOV	[BX],CH
	MOV	WKFCB,0		;CLEAR DRIVE CODE
	CALL	SEARCW
	JZ	RENANF		;OLD FILE NOT FOUND
	MOV	DX,OFFSET WKFCB
	CALL	RENAME		;RENAME
RENAMN:
	JMPS	TYPEOF
;
RENANF:				;NOT FOUND ERROR
	CALL	FNFERR
	JMPS	RENAMN
;
RENAER:				;ERROR
	CALL	SLCRDR
	JMPS	USERER
;
RENADP:				;DUPLICATE FILE ERROR
	MOV	CX,OFFSET CFLEXT
	CALL	BUFPRN
	JMPS	RENAMN
;
;  USER:SET USER NUMBER
;
USER:
	CALL	GTDNUM		;GET NUMBER
	CMP	AL,021H
	JNZ	USERST		;SET MODE
	CALL	CRLF		;INTERROGATE MODE
	CALL	GETUSR		;GET USER CODE
	OR	AL,'0'
	CMP	AL,'9'
	JBE	USEROT		;0 TO 9
	PUSH	AX		;10 TO 15
	MOV	AL,'1'
	CALL	CONOUT
	POP	AX
	SUB	AL,10
USEROT:
	CALL	CONOUT
	JMPS	TRCDSE
;
USERST:				;SET MODE
	CMP	AL,16
	JC	USERSS		;OK IN RANGE
	JMPS	USERER		;OVER
;
USERSS:
	MOV	DL,AL
	CMP	WKFCB+1,' '
	JNZ	USERSE		;HAVE SOME NUMBER
USERER:				;ERROR
	JMP	COMERR
;
USERSE:
	MOV	USRCOD,AL	;SET USER CODE
	CALL	GETUSS
	JMP	ENDPRT
;
;  MEMORY NOT AVAILABLE IN PROGRAM LOADING
;
MEMNAV:
	MOV	CX,OFFSET CMNAVL
	CALL	BUFPRN
	JMPS	RENAMN
;
;  TRANSIENT COMMAND OR CHANGE DRIVE
;
TRCDSL:
	CALL	CHKUID		;CHECK USER ID
	CMP	WKFCB+1,' '
	JNZ	TRNCMD		;SOME COMMAND
	MOV	AL,TDRVNU	;CHANGE DRIVE
	OR	AL,AL
	JZ	TRCDSE		;NO DRIVE SPECIFICATION
	DEC	AL
	MOV	CURDRV,AL	;SET AS CURRENT DRIVE
	MOV	WORD PTR WKBIOS+1,AX
	CALL	SELDSK		;SELECT BY DIRECT BIOS CALL
	OR	BX,BX
	JZ	USERER		;SELECT ERROR
	MOV	AL,CURDRV	;OK SELECT
	CALL	SELDRV
TRCDSE:
	JMP	ENDPRT
;
;  TRANSIENT COMMAND
;
TRNCMD:
	CMP	WKFCB+9,' '
	JZ	TRNCMK		;OK
	JMPS	USERER		;NON RESIDENT COMMAND NAME CANNOT HAVE TYPE
;
TRNCMK:
	CALL	SLTGDR		;TO TARGET DRIVE
	MOV	DI,OFFSET WKFCB+9
	MOV	SI,OFFSET CODCMD
	MOV	CX,3
	REP	MOVSB		;SET 'CMD'  TYPE
	MOV	DX,OFFSET WKFCB
	CALL	OPENW		;OPEN COMMAND FILE
	JNZ	TRNCMO		;OK
	CALL	SLCRDR		;NOT FOUND SO COMMAND ERROR
	JMP	COMERR
;
TRNCMO:
	CALL	LOADPR		;LOAD PROGRAM
	INC	AX
	JZ	MEMNAV		;TOO LARGE CANNOT LOAD IN MEMORY
	MOV	DDMASG,BX	;SAVE BASE PAGE SEGMENT  DS
	MOV	ES,BX
	CALL	SLCRDR		;TO CURRENT DRIVE
	MOV	AX,DS
	MOV	ES,AX
	CALL	GTFNAM		;GET LEFT COMMAND FIRST FILE NAME
	MOV	BX,OFFSET TDRVNU
	PUSH	BX
	MOV	AL,[BX]
	MOV	WKFCB,AL
	MOV	AX,16
	CALL	GTFNAS		;GET SECOND FILE NAME
	POP	BX
	MOV	AL,[BX]
	MOV	WKFCB+16,AL
	MOV	WKFCB+32,0	;CLEAR CURRENT RECORD COUNT
	MOV	DI,DFCB		;DEFAULT FCB IN BASE PAGE
	MOV	ES,DDMASG	;BASE PAGE SEGMENT
	MOV	SI,OFFSET WKFCB
	MOV	CX,33		;FCB LENGTH
	CALL	COPY		;SET TO DEFAULT FCB
	MOV	SI,OFFSET CMBUFF+2
	CALL	SRCHTP		;GET TOP
	OR	AL,AL
	JZ	TRNCMS		;NO CODE
TRNCMT:
	LODSB
	OR	AL,AL
	JZ	TRNCMS		;NO LEFT CODE
	CMP	AL,' '
	JZ	TRNCMN		;GET LEFT CODE TOP
	JMPS	TRNCMT		;PASS TRANSIENT COMMAND NAME
;
TRNCMN:				;GET LEFT CODE POINT
	CALL	SRCHTP
TRNCMS:
	MOV	CH,0		;LEFT CODE LENGTH COUNT
	MOV	DI,DFCMBF+1
	DEC	SI
TRNCMM:
	LODSB
	STOSB			;SET LEFT COMMAND CODE
	OR	AL,AL
	JZ	TRNCMG		;END OF CODE
	INC	CH
	JMPS	TRNCMM		;TO NEXT
;
TRNCMG:
	MOV	AL,CH
	MOV	DI,DFCMBF
	STOSB			;SET LENGTH COUNT
	MOV	DI,DFPAGE	;BASE PAGE TOP
	MOV	AX,ES:3[DI]	;GET CODE SEGMENT
	MOV	CMDPTR+2,AX
	MOV	AL,ES:5[DI]	;GET ENTRY OFFSET  XX00H
	MOV	BYTE PTR CMDPTR+1,AL
	CALL	CRLF
	CALL	STDMAA		;SET DEFAULT DMA ADDRESS
	MOV	TRCMOD,0	;				NOT USED  ????
	MOV	CMBUFF+1,0	;CLEAR COMMAND COUNT
	MOV	ES,DDMASG
	MOV	DS,DDMASG
	MOV	BX,DFESSG
	CMP	WORD PTR [BX],0
	JZ	$+4		;8080 MODEL OR SMALL MODEL
	MOV	ES,[BX]		;COMPACT MODEL
	CALLF	DWORD PTR CMDPTR ;TO COMMAND ROUTINE
	MOV	SP,OFFSET STACK
	JMP	SYSRST		;END OF COMMAND
;
;  CCP COMMAND END PROCESS
;
ENCPRC:
	CALL	SLCRDR		;TO CURRENT DRIVE
ENDPRT:
	CALL	GTFNAM		;CHECK LEFT CODE
	MOV	AL,WKFCB+1
	SUB	AL,' '
	MOV	BX,OFFSET TDRVNU
	OR	AL,[BX]
	JNZ	ENDPRE		;SOME CODE LEFT SO ERROR
	JMP	CCPLOP		;OK END
;
ENDPRE:
	JMP	COMERR
;
;  WORK FOR CALL TO COMMAND FILE
;
CMDPTR	DW	0,0
;
;  DATA AREA
;
	DSEG
	ORG	800H
;
CODCMD:				;TRANSIENT COMMAND TYPE
	DB	'CMD'
;
DDMASG	DW	0		;BASE PAGE SEGMENT
MDSUBE	DB	0		;SUBMIT MODE
SUBFCB	DB	0		;FCB FOR SUBMIT FILE
	DB	'$$$     SUB',0,0,0,0
	DB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
;
WKFCB	DB	0		;FCB FOR WORK
	DB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	DB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
	DB	0,0,0,0
;
RWBUFF:				;ONE SECTOR READ WORK
	RS	128
	DB	0,0		;NOT USED		???
BSDIRC	DB	0		;BIAS OF DIRECTORY
USRCOD	DB	0		;USER CODE
TRCMOD	DB	0		;TRANSIENT COMMAND MODE    NOT USED ???
;
;
	RS	96
STACK:				;CCP STACK
;
WKBIOS	DB	9		;BIOS DIRECT CALL WORK  9 IS SELECT DISK
	DW	0		;CX
	DW	1		;DX
;
PNTCMD	DW	CMBUFF+2	;COMMAND BUFFER POINTER
TPNCMD	DW	0		;COMMAND BUFFER TEMPORARY POINTER FOR ERROR
CURDRV	DB	0		;CURRENT DRIVE
TDRVNU	DB	0		;TEMPORARY DRIVE MODE
;
;  INDEXED DATA
;
IXTERM:				;TERMINATOR
	DB	' =_.:;<>,'
IXRSCM:				;RESIDENT COMMAND
	DB	'DIRS'
	DB	'USER'
	DB	'REN '
	DB	'TYPE'
	DB	'ERA '
	DB	'DIR '
;
;  COMMENTS
;
CNOFIL	DB	'NO FILE',0
CALLOK	DB	'ALL (Y/N)?',0
CFLEXT	DB	'FILE EXISTS',0
CMNAVL	DB	'MEMORY NOT AVAILABLE',0
CRDERR	DB	'READ ERROR',0
CCLSER	DB	CR,LF,'CANNOT CLOSE',0
CNSYSF	DB	CR,LF,'NON-SYSTEM FILE(S) EXIST',0
CSYSFL	DB	CR,LF,'SYSTEM FILE(S) EXIST',0
;
;  USER ID CODE
;
IDCODE:
	DB	1		;OEM CODE
	DB	10		;VERSION NUMBER
	DB	0		;PRODUCT NUMBER
	DB	0,0,0		;USER ID NUMBER
;
;  RESIDENT COMMAND ROUTINE INDEX
;
IXRSRT:
	DW	DIRNON		;DIR
	DW	ERASE		;ERA
	DW	TYPEOT		;TYPE
	DW	RENAMP		;REN
	DW	USER		;USER
	DW	DIRSYS		;DIRS
	DW	TRCDSL		;NOT RESIDENT
;
;
;
MODIRE	DB	0		;OTHER SIDE FILE EXIST MODE  0 NOT EXIST
MODDIR	DB	0		;DIRECTORY MODE  0 NON-SYSTEM  1 SYSTEM FILE
;
;  PATCH AREA
;
;  EQATIONS OF EXTERNAL LABELS
;
				;24D8H	IS SYSTEM PAGE ???
Y24E0	EQU	024E0H		;MAX COLUMN
;
;
	CSEG
	ORG	0A00H
;
	DB	'12 January 1982'
;
	ORG	0A15H
	DB	12H,01H,82H
;
	ORG	0A40H
;
;  DIRECTORY OUT PATCH FOR SHORT LINE DISPLAY
;
DIRPAT:
	CMP	BYTE PTR .Y24E0,60
	JC	DIRPAS		;SHORT LINE
	JMP	DIROUP
;
DIRPAS:				;SHORT LINE
	AND	AL,01H
	JMP	DIROUP
;
	ORG	0A50H
;
	DB	'December 28 81'
;
;
	END
