	TITLE	'CP/M "DCOPY" FUNCTION 1/78';;	DISK COPY FUNCTION, COPIES FROM DISK A TO DISK B UNTIL 0E5H'S;;	COPYRIGHT (C) 1977, 1978;	DIGITAL RESEARCH;	BOX 579 PACIFIC GROVE;	CALIFORNIA, 93950;	ORG	100H	JMP	START	DB	'COPYRIGHT (C) 1978, DIGITAL RESEARCH ';;	GLOBAL EQUATESBOOT	EQU	0000HBDOS	EQU	0005H;SPT	EQU	58	;SECTORS PER TRACKBPS	EQU	128	;BYTES PER SECTORBPT	EQU	BPS*SPT	;BYTES PER TRACKTPD	EQU	77	;TRACKS PER DISKOSTRKS	EQU	2	;TRACKS FOR OS;CONIN	EQU	1	;READ CONSOLE DEVICERDBUFF	EQU	10	;READ BUFFERPBUFF	EQU	9	;PRINT BUFFERCR	EQU	0DHLF	EQU	0AH;READTRK	EQU	$WRITTRK	EQU	$+3REREAD	EQU	$+6	JMP	READ$DISK	JMP	WRITE$DISK	JMP	RE$READ$DISKTRACK:	DS	1	;SET TO TRACK TO READ/WRITEBUFFA:	DS	2	;SET TO BUFFER ADDRESS TO READ/WRITEIOF:	DS	1	;IO FUNCTION 0 = READ, 1 = WRITE;READ$DISK:	;READ DISK DRIVE A, FROM TRACK 'TRACK'	;INTO THE ADDRESS GIVEN BY 'BUFFA'	XRA A! CALL SEL ;SELECT DRIVE A	JMP READ$D;;WRITE$DISK:	;WRITE TO DISK DRIVE B, TO TRACK 'TRACK'	;FROM THE ADDRESS GIVEN BY 'BUFFA'	MVI A,1! STA IOF ;SET IOFUNCTION TO WRITE	CALL SEL ;SELECT DRIVE B	JMP RW$DISK;RE$READ$DISK:	;READ FROM DISK DRIVE B, FROM TRACK 'TRACK'	;TO THE ADDRESS GIVEN BY 'BUFFA'	MVI A,1! CALL SEL ;DRIVE B SELECTED	READ$D: XRA A! STA IOF ;SET TO READ FUNCTION	RW$DISK: ;READ OR WRITE DISK		LXI H,TRACK! MOV C,M ;GET TRACK NUMBER		CALL TRK ;TRACK SELECTED		LHLD BUFFA ;GET DMA ADDRESS		LXI D,spt ;D = 0, E = spt		RW$LOOP: ;READ/WRITE LOOP			INR D ;TO NEXT SECTOR			PUSH D! PUSH H			mov c,d! mvi b,0			lxi h,skewtbl-1! dad b			MOV C,m! CALL SEC ;SECTOR SET			POP B! PUSH B ;GET DMA ADDRESS			CALL DMA ;DMA ADDRESS SET			;PERFORM IO FUNCTION			LDA IOF! ORA A ;SET FLAGS, 0=READ, 1=WRITE			JNZ WRITEFUNC				;READ DISK				CALL DREAD				JMP RWCOMPLETE			WRITEFUNC:				;WRITE DISK				CALL DWRITE			RWCOMPLETE: ;FUNCTION COMPLETE				POP H ;RECALL DMA ADDRESS				LXI D,80H! DAD D ;TO NEXT DMA				POP D ;RECALL SECTOR AND COUNT			; CHECK ERROR CONDITIONS			ORA A! RNZ ;RETURN WITH NON ZERO FLAG SET			DCR E ;COUNT = COUNT - 1			JNZ RW$LOOP ;FOR ANOTHER SECTOR			RET ;WITH ZERO FLAG SET FOR IO COMPLETE;;;;	UTILITY SUBROUTINES FOR DIRECT DISK IOWBOOT	EQU	1	;WARM BOOT ADDRESSSELDSK	EQU	24	;SELECT DISKSETTRK	EQU	27	;SET TRACKSETSEC	EQU	30	;SET SECTORSETDMA	EQU	33	;SET DMA ADDRESSREADF	EQU	36	;READ DISKWRITF	EQU	39	;WRITE DISK;SEL:	;SELECT DRIVE GIVEN BY REGISTER A	MOV C,A! LHLD WBOOT! LXI D,SELDSK! DAD D! PCHL;TRK:	;SET TRACK GIVEN BY C	LHLD WBOOT! LXI D,SETTRK! DAD D! PCHL;SEC:	;SET SECTOR GIVEN BY C	LHLD WBOOT! LXI D,SETSEC! DAD D! PCHL;DMA:	;SET DMA ADDRESS TO VALUE OF B,C	LHLD WBOOT! LXI D,SETDMA! DAD D! PCHL;DREAD:	;PERFORM READ OPERATION	LHLD WBOOT! LXI D,READF! DAD D! PCHL;DWRITE:	;PERFORM WRITE OPERATION	LHLD WBOOT! LXI D,WRITF! DAD D! PCHL;START:	LXI	SP,STACKRDDSK:	;PRINT PROMPT AND WAIT FOR RESPONSE TO CONTINUE	CALL INSMSG! CALL CI ;WAIT FOR RESPONSE	cpi 03! jz boot! cpi 0dh! jnz rddsk;	;NEW DISK IS READY, TRY THE COPY OPERATION	LXI H,TRACK! MVI M,ostrks ;CLEAR THE TRACK NUMBER	LXI H,TRCOUNT! MVI M,'0'! INX H! MVI M,'0';RDTRK:	;READ THE NEXT SOURCE TRACK, COMPARE WITH 0E5H FOR END	LXI H,IBUFF! SHLD BUFFA! CALL READTRK		JZ READOK! CALL READ0MSG! JMP RDDSK	READOK:		LDA TRACK! CPI OSTRKS! JC WRTRK ;MAY BE DATA DISK		;TRACK IN MEMORY, CHECK FOR LAST TRACK		LXI H,IBUFF! LXI B,TRLEN		TRCOMP:	MVI A,0E5H! CMP M! JNZ WRTRK			INX H! DCX B! MOV A,C! ORA B! JNZ TRCOMP		;END OF COPY, ALL 0E5H'S		JMP ENDCOPY	;TERMINATE COPY AND RETURN	;	;NOT END OF COPY, WRITE TRACK TO DISK FROM IBUFF	WRTRK:	CALL WRITTRK		JZ WROK! CALL WRITE0MSG! JMP RDDSK	WROK:		;WRITTEN TO DISK, NOW READ IT BACK AND COMPARE		LXI H,OBUFF! SHLD BUFFA! CALL REREAD			JZ READ1OK! CALL READ1MSG! JMP RDDSK		READ1OK:		LXI H,IBUFF! LXI D,OBUFF! LXI B,TRLEN		WRCOMP: LDAX D! CMP M! JNZ WRERR			INX H! INX D! DCX B! MOV A,C! ORA B			JNZ WRCOMP		;COMPARE WENT OK, INCREMENT TRACK COUNT AND CYCLE		LXI H,TRACK! INR M		MOV A,M! CPI TPD! JNC ENDCOPY ;TERMINATE BY END OF DISK		LXI H,TRCOUNT+1! INR M! MOV A,M! CPI '9'+1		JC RDTRK ;OVERFLOW TO HIGH ORDER TRACK NUMBER		MVI M,'0'! DCX H! INR M! JMP RDTRK		;	WRERR:	;VERIFY ERROR		CALL VERERR! JMP RDDSK;;ENDCOPY:;	ARRIVE HERE AT END OF COPY TO PRINT FINAL MESSAGE AND BOOT	LXI D,TRMSG! CALL PRMSG ;NUMBER OF TRACKS	JMP RDDSK;;;;	UTILITY SUBROUTINESCI:	MVI C,CONIN! JMP BDOS ;READ A CHARACTER;PRMSG:	MVI C,PBUFF! JMP BDOS ;PRINT A BUFFER;;;;	PRINT STRINGSINSMSG:	LXI D,$+6! JMP PRMSG	db cr,lf,'DCS-2 Double Density'	DB CR,LF,'INSERT SOURCE DISK IN A, NEW DISK IN B, TYPE RETURN$';;VERERR:	LXI D,$+6! JMP PRMSG	DB CR,LF,'VERIFICATION ERROR, BAD DISK$';READ0MSG:	LXI D,$+6! JMP PRMSG	DB CR,LF,'ERROR ON SOURCE DISK, REPLACE$';WRITE0MSG:	LXI D,$+6! JMP PRMSG	DB CR,LF,'CANNOT WRITE NEW DISK, REPLACE$';READ1MSG:	LXI D,$+6! JMP PRMSG	DB CR,LF,'CANNOT RE-READ NEW DISK, REPLACE$';;;	MISCELLANEOUS DATA AREAS;TRMSG:	DB	CR,LFTRCOUNT:	DB	'00 TRACKS VERIFIED$';SKEWTBL:	DB	1,19,37,55	DB	15,33,51,11	DB	29,47,7,25	DB	43,3,21,39	DB	57,17,35,53	DB	13,31,49,9	DB	27,45,5,23	DB	41,10,28,46	DB	6,24,42,2	DB	20,38,56,16	DB	34,52,12,30	DB	48,8,26,44	DB	4,22,40,58	DB	18,36,54,14	DB	32,50	DS	32	;STACKSTACK:TRLEN	EQU	SPT*BPS	;BUFFER SIZEIBUFF:	DS	TRLENOBUFF:	DS	TRLEN	END	100H