;
;****************************************
;*                                      *
;*                                      *
;*            DKCOPY                    *
;*                                      *
;*       A FILE COPY PROGRAM            *
;*      FOR SINGLE DRIVE SYSTEMS        *
;*                                      *
;*                                      *
;****************************************
;
; ASSEMBLED WITH Z80ASM FROM CPMUG VOL #16
;
; WRITTEN JAN 24,1981 BY
;
;	KEN STEPHENSON
;	PHYSICS DIVISION
;	ARGONNE NATIONAL LABORATORY
;	ARGONNE,IL 60439
;
;
CRLF	EQU	0D0AH
CR	EQU	0DH
LF	EQU	0AH
TPA	EQU	0100H
BDOS	EQU	5
BOOT	EQU	0
;
;
	ORG	TPA
	LD	SP,LSTACK
	LD	DE,SIGNON
	LD	C,9
	CALL BDOS			;PRINT SIGNON MESSAGE
;
;
RSET	LD	A,0			;CLEAR TWO FLAGS
	LD	(AST),A			;ASTERISK IN NAME OR TYPE
	LD	(FIRSTF),A		;FILE COUNTER
;
GETFILE	LD	HL,(FCBBSPT)		;CLEAR OUT
	LD	(HL),0			;DR FIELD.
	INC	HL			;PUT BLANKS
	PUSH	HL			;INTO
	POP	DE
	INC	DE			;NAME
	LD	BC,11			;AND
	LD	(HL),20H		;TYPE
	LDIR				;FIELDS.
	LD	(HL),0
	LD	BC,30			;CLEAR OUT REST OF FCB
	LDIR
;
	LD	E,25H			;OUTPUT
	LD	C,2			;PROMPT.
	CALL BDOS
;
	LD	A,1			;INITIALIZE FOR FILE
	LD	(NAMEPT),A		;NAME FETCH.
;
FNAME	LD	C,1			;GET
	CALL BDOS			;CHARACTER.
	CP	3			;CHECK FOR CNTL-C
	JP	Z,BOOT
	CP	8			;CHECK FOR BACKSPACE
	JR	NZ,NOTBS-$
	LD	A,(NAMEPT)		;CHECK FOR BEGINNING OF LINE
	CP	1
	JR	Z,FNAME-$
	DEC	A			;NOT BEGINNING OF LINE
	LD	(NAMEPT),A		;DECREMENT NAME POINTER
	LD	E,A			;RESTORE SPACE IN NAME
	LD	D,0
	LD	HL,(FCBBSPT)
	ADD	HL,DE
	LD	(HL),20H
	LD	E,20H
	LD	C,2
	CALL	BDOS			;SPACE
	LD	E,8
	LD	C,2
	CALL	BDOS			;BACKSPACE
	JR	FNAME-$
NOTBS	CP	CR
	JR	Z,CKDONE-$		;IF RETURN, NAME IS IN-
					;GO SEE IF DONE.
	CP	2AH			;CHECK FOR *
	JR	NZ,NOTSTAR-$
	LD	A,(NAMEPT)		;CHARACTER IS A STAR.
	CP	9			;CHECK
	JR	NC,TYPE-$		;FOR FILE NAME OR TYPE.
	LD	HL,(FCBBSPT)		;FILE NAME-LOAD IN
	INC	HL			;???????? FOR NAME.
	PUSH	HL
	POP	DE
	INC	DE
	LD	BC,7
	LD	(HL),3FH
	LDIR
	LD	A,9			;SET CHARACTER
	LD	(NAMEPT),A		;POINTER TO FILE TYPE.
	LD	A,1			;TURN ON
	LD	(AST),A			;NAME-STAR FLAG.
	JR	FNAME-$			;KEEP GOING UNTIL DECIMAL PT.
;
TYPE	LD	HL,(FCBBSPT)		;FORM POINTER
	LD	DE,9			;IN HL
	ADD	HL,DE			;TO FILE TYPE AREA.
	LD	D,3FH			;LOAD IN
	LD	(HL),D			;???
	INC	HL			;FOR
	LD	(HL),D			;FILE
	INC	HL			;TYPE.
	LD	(HL),D
	LD	A,12			;SET CHARACTER POINTER PAST
	LD	(NAMEPT),A		;FILE TYPE AREA.
	LD	A,1			;TURN ON
	LD	(AST),A			;TYPE-STAR FLAG.
	JR	FNAME-$			;KEEP GOING UNTIL CARRIAGE RET.
;
NOTSTAR	CP	2EH			;CHECK FOR DECIMAL PT.
	JR	NZ,NOTDOT-$
	LD	A,9			;CHARACTER IS DECIMAL PT.
	LD	(NAMEPT),A		;SET CHAR. PT. TO FILE TYPE.
	JP	FNAME			;GO BACK FOR FILE TYPE.
;
NOTDOT	LD	HL,(FCBBSPT)		;CHARACTER PASSES ALL TRAPS
	LD	DE,(NAMEPT)		;FORM
	LD	D,0			;POINTER
	ADD	HL,DE			;IN HL.
	CP	61H			;CHECK FOR LOWER CASE
	JR	C,UPPERC-$
	CP	7BH
	JR	NC,UPPERC-$
	AND	01011111B
UPPERC	LD	(HL),A			;STORE CHARACTER.
	INC	E			;INCREMENT
	LD	A,E
	LD	(NAMEPT),A		;CHARACTER COUNTER.
	JP	FNAME			;GO BACK FOR ANOTHER CHAR.
;
CKDONE	LD	E,LF			;OUTPUT A LINEFEED
	LD	C,2
	CALL	BDOS
	LD	HL,(FCBBSPT)		;CHECK FOR BLANK IN
	INC	HL			;FIRST
	LD	A,(HL)			;BYTE
	CP	20H			;OF NAME.
	JP	Z,WRITEF		;IF SO,THEN DONE WITH READS.
;
	LD	HL,(FCBBSPT)		;MORE FILES TO READ.
	LD	DE,12
	ADD	HL,DE			;CLEAR OUT SPURIOUS
	PUSH	HL			;CHARACTERS AT
	POP	DE			;END OF FCB.
	INC	DE
	LD	(HL),0
	LD	BC,20
	LDIR
	LD	HL,(FCBBSPT)		;CHECK FOR ? IN NAME
					;OR TYPE FIELDS.
	LD	B,11
QLOOP	INC	HL
	LD	A,(HL)
	CP	'?'
	JR	NZ,NOTQ-$
	LD	A,1			;THERE IS A ? IN NAME OR
	LD	(AST),A			;TYPE FIELDS - FLAG FOR
					;LOOP ON ALL NAME MATCHES.
NOTQ	DJNZ	QLOOP-$
					;TEST ASTERISK OR ? FLAGS
	LD	A,(AST)
	CP	1
	JP	NZ,OPEN			;NO FLAGS-GO OPEN FILE.
;
STAR	LD	DE,80H			;STAR FLAG SET.
	LD	C,26			;SET DMA ADDRESS TO
	CALL	BDOS			;80H.
	LD	A,(FIRSTF)		;CHECK
	CP	0			;FOR FIRST FILE.
	JR	NZ,NOT1ST-$
	LD	DE,FCBNAME		;1ST FILE.
	LD	HL,(FCBBSPT)		;COPY NAME
	LD	BC,33			;INTO
	LDIR				;STORAGE AREA.
NOT1ST	LD	DE,(FCBBSPT)		;COPY NAME
	LD	HL,FCBNAME		;INTO FCB.
	LD	BC,33
	LDIR
	LD	A,0			;ZERO FILE
	LD	(FCOUNT),A		;COUNTER.
	LD	DE,(FCBBSPT)
	LD	C,17
	CALL	BDOS			;CPM SEARCH FOR FIRST FUNC.
	CP	255
	JR	Z,NMATCH-$
SLOOP	PUSH	AF
	LD	A,(FIRSTF)		;SEE IF
	LD	C,A			;THIS
	LD	A,(FCOUNT)		;FILE
	CP	C			;HAS ALREADY
	JR	Z,GOTFILE-$		;BEEN STORED.
	INC	A			;YES, GO ON 
	LD	(FCOUNT),A		;TO SEARCH FOR
	POP	AF			;NEXT
	LD	C,18			;FILE
	CALL	BDOS			;CPM SEARCH FOR NEXT FUNC.
	CP	255
	JP	Z,RSET
	JR	SLOOP-$
GOTFILE	POP	AF			;SEARCH WAS SUCCESSFUL
	ADD	A
	ADD	A			;A*32 POINTS
	ADD	A			;TO LOCATION
	ADD	A			;OF FCB IN
	ADD	A			;DMA AREA.
	LD	HL,80H
	LD	D,0
	LD	E,A
	ADD	HL,DE			;HL POINTS TO FCB AS READ
	INC	HL			;FROM DISK.
	LD	DE,(FCBBSPT)		;COPY NAME
	INC	DE			;INTO NEW
	LD	BC,11			;FCB AREA.
	LDIR
	CALL	OUTFCB			;PRINT FILE NAME.
	LD	DE,MATCHED
	LD	C,9
	CALL	BDOS
	LD	A,(FIRSTF)		;INCREMENT SEARCH
	INC	A			;POINTER.
	LD	(FIRSTF),A
	JR	OPEN-$			;GO OPEN FILE.
;
NMATCH	LD	DE,NOMATCH		;NO FILE MATCH.
	LD	C,9			;OUTPUT
	CALL	BDOS			;ERROR MESSAGE.
	JP	RSET			;GO BACK FOR MORE.
;
;
OPEN	LD	DE,(FCBBSPT)		;OPEN FILE.
	LD	C,15
	CALL	BDOS
	CP	255			;CHECK STATUS OF OPEN
	JR	NZ,FILEOK-$
	LD	DE,NOTOPN
	LD	C,9			;FILE NOT OPENED-OUTPUT
	CALL	BDOS			;ERROR MESSAGE.
	JP	RSET			;START OVER.
;
FILEOK	LD	DE,(FCBBSPT)		;FILE OPENED SUCCESSFULLY.
	LD	C,35
	CALL	BDOS			;CPM COMPUTE FILE SIZE FUNC.
	LD	BC,(FCBBSPT)
	LD	HL,34			;COMPUTE RAM SPACE
	ADD	HL,BC			;LEFT FOR FILES.
	PUSH	HL
	POP	BC
	LD	HL,(BDOS+1)		;FBASE INTO HL
	OR	A
	SBC	HL,BC			;HL CONTAINS RAM SPACE IN BYTES
	LD	C,H
	LD	L,H			;CALCULATE # OF 128 BYTE SCTRS
	LD	H,0
	LD	B,0
	ADD	HL,BC
	DEC	HL			;LESS 128 BYTES FOR OVERHEAD.
	LD	IX,(FCBBSPT)
	LD	B,(IX+34)		;BC CONTAINS #
	LD	C,(IX+33)		;RECORDS IN FILE.
	OR	A
	SBC	HL,BC			;COMPARE RAM SPACE WITH DISK
	JR	NC,MEMOK-$
	LD	DE,SHRTMEM		;NOT ENOUGH MEMORY FOR FILE.
	LD	C,9
	CALL	BDOS
	JP	RSET
;
MEMOK	LD	HL,(FCBBSPT)		;FORM POINTER TO 
	LD	DE,33			;RECORD
	ADD	HL,DE			;COUNTER.
	LD	(RECNTPT),HL
	LD	(HL),0			;INITIALIZE COUNTER.
	INC	HL
	LD	(HL),0
	INC	HL			;NOW HL IS DMA POINTER.
	LD	(DATAPT),HL
;
GETREC	LD	DE,(DATAPT)		;START READ LOOP.
	LD	C,26			;SET DMA ADDRESS.
	CALL	BDOS
	LD	DE,(FCBBSPT)
	LD	C,20			;READ A
	CALL	BDOS			;SECTOR.
	CP	0			;END OF FILE?
	JR	NZ,ENDFR-$
	LD	HL,(DATAPT)		;NOT EOF
	LD	DE,128			;INCREMENT
	ADD	HL,DE			;DMA POINTER.
	LD	(DATAPT),HL
	LD	HL,(RECNTPT)		;INCREMENT
	LD	D,(HL)			;RECORD
	INC	HL			;COUNTER.
	LD	E,(HL)
	INC	DE
	LD	(HL),E
	DEC	HL
	LD	(HL),D
	JR	GETREC-$
;
ENDFR	LD	A,(NUMFILE)		;INCREMENT FILE
	INC	A			;COUNTER.
	LD	(NUMFILE),A
	LD	HL,(DATAPT)		;CALCULATE
	LD	(FCBBSPT),HL
	LD	A,(AST)			;AS WE IN ASTERISK LOOP?
	CP	1
	JP	Z,STAR
	JP	RSET			;NOT STAR LOOP-
					;BACK FOR KEYBD INPUT.
;
;
WRITEF	LD	C,29
	CALL	BDOS
	LD	DE,WMSG
	LD	C,9
	CALL	BDOS
	LD	E,23H			;KEYBD PROMPT
	LD	C,2
	CALL	BDOS
	LD	C,1
	CALL	BDOS
	CP	3			;CHECK FOR CNTL-C
	JP	Z,BOOT
	CP	47H			;WAIT FOR CONSOLE INPUT OF
	JR	Z,GORITE-$		;G OR g BEFORE STARTING.
	CP	67H
	JR	Z,GORITE-$
	JR	WRITEF-$		;KEYBD ENTRY ERROR.
;
GORITE	LD	DE,NLINE
	LD	C,9
	CALL	BDOS
      	LD	HL,BUFSTRT		;STARTING FCB ADDR.
	LD	(FCBBSPT),HL
	LD	DE,(FCBBSPT)
	LD	C,15			;TRY TO OPEN A FILE
	CALL	BDOS			;SOLE PURPOSE OF THIS
					;IS TO FORCE CPM TO TEST
					;FOR A DISK CHANGE.
	LD	C,29			;RETURN
	CALL	BDOS			;R/O VECTOR.
	BIT	0,L			;BIT 0 OF L SET MEANS
	JR	NZ,DRVOK-$		;DISK HAS BEEN CHANGED.
	LD	DE,DCHANGE		;CPM SAYS DISK HAS
	LD	C,9			;NOT BEEN CHANGED.
	CALL	BDOS
	LD	E,23H
	LD	C,2
	CALL	BDOS			;KEYBD PROMPT
	LD	C,1			;LET USER OVERIDE
	CALL	BDOS			;IF HE WANTS.
	CP	47H
	JR	Z,DRVOK-$
	CP	67H
	JR	Z,DRVOK-$
	JR	WRITEF-$		;ABORT IN NICK OF TIME-
					;GO TRY ANOTHER DISK.
DRVOK	LD	DE,NLINE
	LD	C,9
	CALL	BDOS
     	LD	C,13			;WRITE ENABLE DISK
	CALL	BDOS
FLOOP	LD	A,(NUMFILE)		;SEE IF MORE FILES TO RITE.
	CP	0
	JP	Z,DONE
	LD	DE,(FCBBSPT)		;MORE FILES.
	LD	C,19			;DELETE PRESENT FILE IF
	CALL	BDOS			;ALREADY ON DISK.
;
	LD	HL,(FCBBSPT)	;CLEAR OUT NON-NAME PART
	LD	DE,12
	ADD	HL,DE
	PUSH	HL			;OF FCB
	POP	DE
	INC	DE
	LD	(HL),0
	LD	BC,20
	LDIR
	LD	DE,(FCBBSPT)		;CREATE FILE.
	LD	C,22
	CALL	BDOS
	CP	255
	JR	NZ,MAKEOK-$
	LD	DE,MAKEBAD		;ERROR IN FILE CREATION.
	LD	C,9
	CALL	BDOS
	JP	DONE
;
MAKEOK	CALL	OUTFCB			;FILE CREATED SUCCESSFULLY
	LD	DE,CREATED
	LD	C,9
	CALL	BDOS
;
	LD	HL,(FCBBSPT)		;CALCULATE
	LD	DE,33			;ADDRESS OF
	ADD	HL,DE			;RECORD
	LD	(RECNTPT),HL		;COUNTER.
	INC	HL
	INC	HL			;STARTING ADDR
	LD	(DATAPT),HL		;OF DATA.
;
RLOOP	LD	HL,(RECNTPT)		;SEE IF ALL RECORDS HAVE
	LD	A,(HL)			;BEEN READ.
	CP	0
	JR	NZ,MOREREC-$
	INC	HL
	LD	A,(HL)
	CP	0
	JR	NZ,MOREREC-$
	LD	DE,(FCBBSPT)		;NO MORE RECORDS IN
	LD	C,16			;THIS FILE. CLOSE FILE.
	CALL	BDOS
	LD	HL,(DATAPT)		;SET NEW FCB ADDR.
	LD	(FCBBSPT),HL
	LD	A,(NUMFILE)		;DECREMENT FILE COUNTER.
	DEC	A
	LD	(NUMFILE),A
	JR	FLOOP-$
;
MOREREC	LD	DE,(DATAPT)		;SET DMA ADDR.
	LD	C,26
	CALL	BDOS
	LD	DE,(FCBBSPT)		;WRITE SECTOR.
	LD	C,21
	CALL	BDOS
	CP	0			;CHECK FOR DISK FULL.
	JR	Z,RITEOK-$
	LD	DE,DISKFUL		;DISK IS FULL.
	LD	C,9
	CALL	BDOS
	LD	DE,(FCBBSPT)		;DELETE LAST FILE.
	LD	C,19
	CALL BDOS
	JP	DONE
;
RITEOK	LD	HL,(RECNTPT)		;DECREMENT 
	LD	D,(HL)			;RECORD
	INC	HL			;COUNTER.
	LD	E,(HL)
	DEC	DE
	LD	(HL),E
	DEC	HL
	LD	(HL),D
	LD	HL,(DATAPT)		;INCREMENT DATA POINTER
	LD	DE,128
	ADD	HL,DE
	LD	(DATAPT),HL
	JP	RLOOP
;
DONE	JP	0			;DONE - TRY TO BOOT CPM
;
;
;
;
OUTFCB	LD	HL,(FCBBSPT)		;TRANSFER FILE NAME
	INC	HL
	LD	DE,OUTBUF		;TO BUFFER.
	LD	BC,8
	LDIR
	INC	DE			;SAME FOR FILE TYPE.
	LD	BC,3
	LDIR
	LD	DE,OUTBUF
	LD	C,9
	CALL	BDOS			;PRINT STRING
	RET
;
;	DATA AREA
;
AST	DEFB	0			;ASTERISK FLAG
FIRSTF	DEFB	0			;FILE SEARCH POINTER.
FCOUNT	DEFB	0			;FILE COUNTER IN SEARCH.
FCBNAME	DEFS	33			;STORAGE FOR FILE NAME,TYPE.
;
OUTBUF	DEFB	'        .    IS $'
MATCHED	DEFB	'MATCHED'
	DEFW	CRLF
	DEFB	'$'
CREATED	DEFB	'CREATED'
	DEFW	CRLF
	DEFB	'$'
;
SIGNON	DEFW	CRLF
      	DEFB	' COPY ROUTINE FOR SINGLE DRIVE SYSTEMS'
	DEFW	CRLF
	DEFB	LF
	DEFB	' INSERT READ DISK '
	DEFW	CRLF
	DEFB	'$'
;
	DEFS	32			;LOCAL STACK AREA
LSTACK	EQU	$
;
NOMATCH	DEFB	' NO MATCH '
	DEFW	CRLF
	DEFB	'$'
;
NOTOPN	DEFB	' FILE COULD NOT BE OPENED '
	DEFW	CRLF
	DEFB	'$'
;
SHRTMEM	DEFB	' NOT ENOUGH MEMORY FOR FILE - TRY ANOTHER OR '
	DEFB	'TYPE RETURN TO END'
	DEFW	CRLF
	DEFB	'$'
WMSG	DEFW	CRLF
    	DEFB	' LOAD IN WRITE DISK'
	DEFW	CRLF
	DEFB	' WHEN READY TO GO, TYPE G '
	DEFW	CRLF
	DEFB	'$'
MAKEBAD	DEFB	' COULD NOT CREATE FILE'
	DEFW	CRLF
	DEFB	'$'
DISKFUL	DEFB	' DISK FULL - FILE DELETED'
	DEFW	CRLF
	DEFB	'$'
DCHANGE	DEFW	CRLF
       	DEFB	' CPM SAYS DISK NOT CHANGED '
	DEFW	CRLF
	DEFB	' TO OVERIDE -  TYPE G OR g '
	DEFW	CRLF
	DEFB	' TO ABORT   -  TYPE ANYTHING ELSE'
NLINE	DEFW	CRLF
	DEFB	'$'
;
DATAPT	DEFW	BUFSTRT+35
RECNTPT	DEFW	BUFSTRT+33
NAMEPT	DEFB	1
FCBBSPT	DEFW	BUFSTRT
NUMFILE	DEFB	0
BUFSTRT	DEFB	0
ENDLAB	END
