;  CONSOLE COMMAND PROCESSOR FOR CP/NET-86
;
;  1983.9.4.	VER.1.00
;
	TITLE	'CONSOLE COMMAND PROCESSOR FOR CP/NET-86'
;
;
BASE	EQU	0			;BASE FOR RELOCATION
;
;  EQUATIONS OF BDOS FUNCTION
;
CRSTSY	EQU	0			;RESET SYSTEM
CCONIN	EQU	1			;CONSOLE INPUT
CCONOT	EQU	2			;CONSOLE OUTPUT
CLIST	EQU	5			;LIST OUT
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
CFRDSK	EQU	39			;FREE DISK
CGTSYA	EQU	49			;GET SYSTEM ADDRESS
CSTDMS	EQU	51			;SET DMA SEGMENT
CMFREE	EQU	58			;FREE ALL MEMORY
CLOADP	EQU	59			;LOAD PROGRAM
CGTCTB	EQU	69			;GET CONFIGRATION TABLE POINT
CSTDAT	EQU	70			;SET DEFAULT ATTRIBUTE
;
;  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
;
;  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	BASE
;
;  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) 1983, '
	DB	'XYZ (DIGITAL RESEARCH)  '
	RS	68
;
;  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
;
;  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
;*/
	OR	WKFCB+6,80H		;FILE MODE TO READ ONLY
;/*
	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 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	CL,CGTSYA
	CALL	ENBDOS			;GET SYSTEM DATA ADDRESS
	MOV	SYSADD,BX		;SAVE POINT
	POP	CX
;/*
	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
;*/
	MOV	CL,CFRDSK
	MOV	DX,-1
	CALL	ENBDOS			;FREE ALL DISK
	MOV	BX,OFFSET BDOS+12
	PUSH	BX
	TEST	BYTE PTR [BX],-1
	JZ	CCPLOL			;NO LIST OUT DATA
	TEST	BYTE PTR 1[BX],-1
	JNZ	CCPLOL			;NOT TRANSIENT LIST OUT MODE     CTRL-P OR SO
	MOV	CL,CGTCTB
	CALL	ENBDOS			;GET CONFIGRATION TABLE POINT
	TEST	BYTE PTR 36[BX],80H
	JZ	CCPLOL			;LOCAL LISTER
	MOV	DL,0FFH			;LISTER TERMINATION CODE
	MOV	CL,CLIST
	CALL	ENBDOS			;OUT TO LISTER FOR TERMINATE CURRENT
CCPLOL:
	POP	BX
	MOV	BYTE PTR [BX],0		;CLEAR LIST OUT FLAG
;/*
	CALL	CRLF
;*/
	CALL	GETUSR			;GET USER CODE
	OR	AL,AL
	JZ	CCPLOU			;ZERO SO NO USER CODE STAMP
	CALL	USERPR
CCPLOU:
;/*
	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
;*/
	MOV	BX,SYSADD		;GET SYSTEM ADDRESS
	CMP	BYTE PTR 64[BX],60
	JNC	DIROUP			;LONG LINE
	AND	AL,1			;SHORT LINE
;/*
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
	CALL	USERPR			;OUT USER CODE
	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
;*/
;
;  OUT USER NUMBER
;  INPUT
;  AL:USER CODE
;
USERPR:
	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:
	JMP	CONOUT
;/*
;
;  TRANSIENT COMMAND OR CHANGE DRIVE
;
TRCDSL:
	CMP	WKFCB+1,' '
	JNZ	TRNCMD			;SOME COMMAND
	MOV	AL,TDRVNU		;CHANGE DRIVE
	OR	AL,AL
	JZ	TRCDSE			;NO DRIVE SPECIFICATION
	DEC	AL
;*/
	MOV	BX,OFFSET CMBUFF+1	;CLEAR BUFFER LENGTH
	MOV	AH,[BX]
	MOV	BYTE PTR [BX],0		;CLEAR COUNTER FOR ERROR
	PUSH	AX
	CALL	SELDRV
	POP	AX
	MOV	CMBUFF+1,AH		;RESTORE COUNTER
	MOV	CURDRV,AL		;SET SELECTED DISK
;/*
TRCDSE:
	JMP	ENDPRT
;
;  MEMORY NOT AVAILABLE IN PROGRAM LOADING
;
MEMNAV:
	MOV	CX,OFFSET CMNAVL
	CALL	BUFPRN
	JMP	RENAMN
;
;  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:
;*/
	MOV	SI,OFFSET WKFCB+5
	MOV	CX,4
	MOV	DL,0
	STD
TRNCML:					;LOOP FOR GETTING ATTRIBUTE
	LODSB
	ROL	AL,1
	RCR	DL,1			;GET ONE BIT
	LOOP	TRNCML			;TO NEXT
	TEST	DL,10H
	JZ	TRNCMA
	OR	DL,70H
TRNCMA:
	MOV	CL,CSTDAT
	CALL	ENBDOS			;SET ATTRIBUTE
;/*
	CALL	LOADPR			;LOAD PROGRAM
;*/
	PUSH	BX
	MOV	DX,OFFSET WKFCB
	CALL	CLOSE			;CLOSE COMMAND FILE
	POP	BX
	MOV	AX,BX
;/*
	INC	AX
	JZ	MEMNAV			;TOO LARGE CANNOT LOAD IN MEMORY
	MOV	DDMASG,BX		;SAVE BASE PAGE SEGMENT  DS
	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
;
DTAREA	EQU	$
	DSEG
	ORG	OFFSET DTAREA
;
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
;
PNTCMD	DW	CMBUFF+2		;COMMAND BUFFER POINTER
TPNCMD	DW	0			;COMMAND BUFFER TEMPORARY FOR ERROR
CURDRV	DB	0			;CURRENT DRIVE
TDRVNU	DB	0			;TEMPORARY DRIVE MODE
SYSADD	DW	0			;SYSTEM DATA ADDRESS
;
;  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 CODE DUMMY
;
	DB	0,0,0,0,0,0
;
;  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
;
;  BDOS TOP VECTOR
;
	ORG	((OFFSET $+255) AND 0FF00H)
BDOS:
;
;
	END
