;************************************************************
;THIS PROGRAM IS A MODIFICATION OF "COPYATOB.COM" WHICH
;HAS BEEN RE__MODIFIED TO DO BOTH SINGLE AND DOUBLE
;DENSITY COPIES USING THE MICROMATION CONTROLLER
;************************************************************
	ORG	100H
;
;
	JMP	VECTOR
;************************************************************
CONIN	JMP	DUMYADR
CONOUT	JMP	DUMYADR
HOME:	JMP	DUMYADR
SELDSK:	JMP	DUMYADR
SETTRK:	JMP	DUMYADR
SETSEC1:	JMP	DUMYADR
SETDMA:	JMP	DUMYADR
READ:	JMP	DUMYADR
WRITE:	JMP	DUMYADR
;************************************************************
;EQUATES
CONTROLLER	EQU	0F800H
WRCONT		EQU	CONTROLLER+600H
RDSTAT	EQU	WRCONT
EXITCPM	EQU	0
SDLASTSEC	EQU	26
DDLASTSEC	EQU	52
BUFF		EQU	CONTROLLER+400H
DENBYTE		EQU	BUFF+1
CONTROLBYTE	EQU	BUFF+3
PRESDISK	EQU	BUFF+5
BSECTOR		EQU	BUFF+0AH
BDMA		EQU	BUFF+0BH
BTWOSIDE	EQU	BUFF+0FH
;************************************************************
;
DRIVE	DB	'  DRIVE $'
MESGA:	DB	0DH,0AH,'+ MEMORY COMPARE ERROR ON TRACK $'
ERM:	DB	0DH,0AH,'+ ERROR ON TRACK $'
MEM	DB	13,10,'MEMORY ADDRESS   $'
MESGB:	DB	'(HEX) SECTOR (HEX)$'
MESGC:	DB	13,10,'**********     PERMANENT      **********$'
MESGD:	DB	13,10,'+ READ ERROR  $'
MESGE:	DB	13,10,'+ WRITE ERROR  $'
SIGNON:	DB	13,10,'+SOURCE ON '
SOURCEMESS	DS	1
	DB	13,10,'+OBJECT ON '
OBJECTMESS	DS	1
SINOFF:	DB	13,10,'+TYPE <RET>$'
DATAM	DB	'           DATA     $'
REPMES	DB	13,10,'TYPE RETURN (OR R TO REPEAT)$'
CRLF:	DB	13,10,'$'
INIT	 DB	13,10,'SINGLE AND DOUBLE DENSITY COPY PROGRAM (F800 SYSTEM)$'
ABORTMESS	DB	13,10,'DENSITY INCOMPATIBILITY$'
SOURCE	DB	13,10,'SOURCE DRIVE? A,B,C,D$'
OBJECT	DB	13,10,'OBJECT DRIVE? A,B,C,D$'
SIDEMESS	DB	13,10,'DISKETTE OR DRIVE INCOMPATIBILITY$'
;
PRTHEX:	PUSH	PSW	;SAVE FOR LSN
	RAR		;SHIFT MSNIBLE TO LSN
	RAR
	RAR
	RAR
	CALL	PRTNBL	;PRINT IT
	POP	PSW	;NOW FOR LSN
PRTNBL:	ANI	0FH
	ADI	30H	;SHIFT TO ASCII VALUE
	CPI	3AH	;OVER 9?
	JC	SML
	ADI	7	;SHIFT TO ALPHA
SML:
	MOV	C,A	;FOR BDOS CALL
	CALL	CONOUT
	RET
;
;
COPY:	LDA	SOURCEDRIVE
	MOV	C,A
	CALL	SELDSK	;SELECT SOURCE DRIVE
	CALL	HOME
	MVI	C,2
	CALL	SETTRK
	MVI	A,10H
	STA	TWOSIDES
	STA	ERR1
	LDA	RDSTAT
	ANI	40H
	STA	SIDES
	LDA	DENBYTE
	STA	DENTEST
	STA	DENMEM
	LDA	TRKSRT	;FIRST TRACK TO MOVE
	STA	TRK	;MAKE CURRENT
	MOV	C,A
	CALL	SETTRK	;AND SELECT IT ON DISK A
	LDA	OBJECTDRIVE
	MOV	C,A
	CALL	SELDSK	;ALSO OBJECTDRIVE
	CALL	HOME
	MVI	C,2
	CALL	SETTRK
	LDA	DENTEST
	MOV	C,A
	LDA	DENBYTE
	CMP	C
	JNZ	ABORT
	LDA	DENMEM
	ORA	A
	JZ	SKIP1
	LDA	RDSTAT
	ANI	40H
	MOV	C,A
	LDA	SIDES
	CMP	C
	JNZ	ABORT1
SKIP1	LDA	TRKSRT	;FIRST TRACK TO MOVE
	MOV	C,A
	CALL	SETTRK	;AND SELECT IT ON DISK B
	LDA	SOURCEDRIVE
	MOV	C,A
	CALL	SELDSK
RDLOOP	XRA	A
	STA	CMPERR
TRYAGAIN	LDA	TRK	;GET TRACK
	MOV	C,A
	CALL	READT	;READ ENTIRE TRACK
	LDA	OBJECTDRIVE
	MOV	C,A
	CALL	SELDSK
	LDA	TRK
	MOV	C,A
	CALL	WRITET	;WRITE TRACK
	LDA	TRK
	MOV	C,A
	CALL	READT	;READ TRACK JUST WRITTEN
	LDA	SOURCEDRIVE
	MOV	C,A
	CALL	SELDSK
	LDA	TRK
	MOV	C,A
	CALL	COMPT
	JNZ	TRYAGAIN	;RETRY IF ERR
	LDA	DENMEM
	ORA	A
	JZ	SKIP
	LDA	SIDES
	ORA	A
	JNZ	SKIP
	LDA	TWOSIDES
	ORA	A
	JNZ	SIDE1
	MVI	A,10H
	STA	TWOSIDES
SKIP	LDA	TRK
	INR	A
	STA	TRK
	LXI	H,TRKSRT+1	;POINT TO LAST TRACK+1 STORAGE
	CMP	M	;ARE WE DONE?
	JNZ	RDLOOP	;LOOP IF NOT
	LDA	CONTROLBYTE
	ORI	80H
	STA	CONTROLBYTE
	STA	BTWOSIDE
	RET
ABORT	LXI	D,ABORTMESS
	CALL	PRINT
	JMP	EXIT
;
ABORT1	LXI	D,SIDEMESS
	CALL	PRINT
	JMP	EXIT
SIDE1	XRA	A
	STA	TWOSIDES
	JMP	RDLOOP
;
SIDETEST	LDA	SIDES
		ORA	A
		RNZ
		LDA	DENMEM
		ORA	A
		RZ
		LDA	TWOSIDES
		ORA	A
		JNZ	SIDEZERO
		LDA	CONTROLBYTE
		ANI	7FH
		STA	CONTROLBYTE
		STA	BTWOSIDE
		RET
SIDEZERO	LDA	CONTROLBYTE
		ORI	80H
		STA	CONTROLBYTE
		STA	BTWOSIDE
		RET
COMPT:	LDA	ERR1
	ORA	A
	JZ	SKIP2
	LXI	H,BUF1
	CALL	RT2	;REREAD INTO BUF1
	LDA	ERR1
	ORA	A
	JZ	SKIP2
	LHLD	LASTSEC128
	MOV	B,H
	MOV	C,L
	LXI	H,BUF0
	LXI	D,BUF1
CMPLP:	LDAX	D
	CMP	M
	JNZ	CERR
	INX	H
	INX	D
	DCX	B
	MOV	A,C
	ORA	B
	JNZ	CMPLP
	RET
CERR:	PUSH	H
	PUSH	D
	PUSH	B
	LXI	D,MESGA
	CALL	PRINT
	LDA	TRK
	CALL	PRTHEX
	LXI	D,MESGB
	CALL	PRINT
	POP	H
	DCX	H
	DAD	H
	LDA	LASTSEC
	SUB	H
	CALL	PRTHEX
	LXI	D,MEM
	CALL	PRINT
	POP	H
	MOV	A,M
	STA	DATA1
	PUSH	H
	MOV	A,H
	CALL	PRTHEX
	POP	H
	MOV	A,L
	CALL	PRTHEX
	MVI	C,','
	CALL	CONOUT
	POP	H
	MOV	A,M
	STA	DATA2
	PUSH	H
	MOV	A,H
	CALL	PRTHEX
	POP	H
	MOV	A,L
	CALL	PRTHEX
	LXI	D,DATAM
	CALL	PRINT
	LDA	DATA1
	CALL	PRTHEX
	MVI	C,','
	CALL	CONOUT
	LDA	DATA2
	CALL	PRTHEX
SKIP2	MVI	A,10H
	STA	ERR1
	LDA	CMPERR
	INR	A
	STA	CMPERR	;INCREMENT ERROR COUNT
	CPI	10
	RNZ
	LXI	D,MESGC
	CALL	PRINT
	XRA	A
	RET
;
DMASET:	PUSH	B
	MOV	C,L
	MOV	B,H
	CALL	SETDMA
	POP	B
	RET
;
;
READT:	LXI	H,BUF0	;TRACK # IN C
RT2:	SHLD	DMAAD
	CALL	SETTRK
	CALL	SIDETEST
	LDA	DENBYTE
	STA	DENTEST
	ORA	A
	MVI	A,SDLASTSEC
	JZ	SET26
	MVI	A,DDLASTSEC
SET26	STA	LASTSEC
	CALL	SECSET
	MVI	C,0
RT3:	PUSH	B
	CALL	READTRAN
	CALL	READ
	RAR		;WAS A BIT 0 SET BY DISK ERROR?
	CC	FAILR
	POP	B
	INR	C
	LDA	LASTSEC
	CMP	C
	RZ
	JMP	RT3
;
;
WRITET:	LXI	H,BUF0	;TRACK # IN C
WT2:	SHLD	DMAAD
	CALL	SETTRK
	CALL	SIDETEST
	LDA	DENTEST
	MOV	L,A
	LDA	DENBYTE
	CMP	L
	JNZ	ABORT
	MVI	C,0
WT3:	PUSH	B
	CALL	WRITETRAN
	CALL	WRITE
	RAR		;WAS A BIT 0 SET BY DISK ERROR?
	CC	FAILW
	POP	B
	INR	C
	LDA	LASTSEC
	CMP	C
	RZ
	JMP	WT3
CMPERR:	DB	0	;NUMBER OF COMPARE ERRORS
TRK:	DB	0
LASTSEC	DS	1
LASTSEC128	DS	2
SOURCEDRIVE	DS	1
OBJECTDRIVE	DS	1
DENTEST		DS	1
DATA1	DS	1
DATA2	DS	1
DMAAD:	DS	2
SIDES	DS	1
TWOSIDES	DS	1
DENMEM	DS	1
ERR1	DS	1
SECTOR	DS	1
STK:	DS	64
STKTOP:	DB	0
;
SECSET	LDA	LASTSEC
	MOV	L,A
	MVI	H,0
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	SHLD	LASTSEC128
	RET
;
;
;
;************************************************************
VECTOR:
;SET UP JUMP VECTORS FOR  ACCESS TO BIOS PRIMITIVES
BASE	EQU	0	;FIND WBOOT JMP ADDRESS AT RST0
DUMYADR	EQU	0	;WHO CARES?
;
	LHLD	BASE+1	;GET WBOOT ADDRESS
	SPHL		;SAVE IT IN SP FOR DAD
	LXI	H,06
	DAD	SP
	SHLD	CONIN+1
	LXI	H,09H
	DAD	SP
	SHLD	CONOUT+1
;
	LXI	H,15H
	DAD	SP
	SHLD	HOME+1
;
	LXI	H,18H
	DAD	SP
	SHLD	SELDSK+1
;
	LXI	H,1BH
	DAD	SP
	SHLD	SETTRK+1
;
	LXI	H,1EH
	DAD	SP
	SHLD	SETSEC1+1
;
	LXI	H,21H
	DAD	SP
	SHLD	SETDMA+1
;
	LXI	H,24H
	DAD	SP
	SHLD	READ+1
;
	LXI	H,27H
	DAD	SP
	SHLD	WRITE+1
;
	LXI	SP,STKTOP
;
;************************************************************
RUNTYP:	JMP	BUFMSR
;THIS ROUTINE SETS UP THE PARAMETERS FOR THE COPY ROUTINE.
;COPY CAN BE USED TO TRANSFER:	SYS	TRACKS  0- 1
;				DAT	TRACKS  2-76
;				ALL	TRACKS	0-76
;THE ROUTINE SEARCHES THE DEFAULT BUFFER AT 80H FOR THE
;RUN PARAMETER TO BE USED
;************************************************************
;ROUTINE EQUATES
TBUFF	EQU	80H
;************************************************************
;DATA TABLES
SYSMSG:	DB	'YSTEM$'	;SYSTEM MESSAGE
DATMSG:	DB	'ATA$'		;DATA MESSAGE
ALLMSG:	DB	'LL$'		;ALL MESSAGE
TRKSRT:	DW	0		;STORAGE FOR FIRST AND LAST+1 TRACK NUMBERS
CMDER1:	DB	'+COMMAND "MMCOPY$'
CMDER2:	DB	'" HAS SYNTAX ERROR',0DH,0AH,'$'
CMDINF:	DB	'+THIS PROGRAM IS INITIATED WITH THE COMMAND',0DH,0AH
	DB	'+"MMCOPY SYSTEM", "MMCOPY DATA" OR "MMCOPY ALL"$'
DONMSG:	DB	13,10,13,10,'********    COPY COMPLETE    ********$'
;FIRST WE MEASURE THE INPUT BUFFER MESSAGE
;AND DELIMIT IT WITH A $ PER BDOS CALL 9
BUFMSR:	LXI	H,TBUFF
	XRA	A		;CLEAR ACC.
	ADD	M		;GET MESSAGE SIZE
	JZ	NOMSG		;NONE FOUND
	INX	H		;ADD FOR ADDR. PAST MESSAGE
	MVI	B,0		;EMPTY FOR DAD
	MOV	C,A
	DAD	B		;ADD CHARACTER COUNT TO HL
	MVI	M,'$'		;END BUFFER CHARACTER
;************************************************************
;NEXT IS A TEST FOR WHICH MESSAGE IS PRESENT
	LDA	TBUFF+2		;FIRST CHARACTER ADDRESS
	CPI	'S'
	JZ	SYSSET
	CPI	'D'
	JZ	DATSET
	CPI	'A'
	JZ	ALLSET
	JMP	BADMSG		;FIRST CHARACTER NOT ONE OF 3 PERMITTED
;************************************************************
SYSSET:
	LXI	D,SYSMSG
	MVI	C,6
	CALL	MSGTST
	MVI	L,0		;FIRST TRACK TO TRANSFER
	MVI	H,2		;LAST TRACK PLUS ONE
	JMP	PUTPAR
;************************************************************
DATSET:
	LXI	D,DATMSG
	MVI	C,4
	CALL	MSGTST
	MVI	L,2		;FIRST TRACK TO TRANSFER
	MVI	H,77		;LAST TRACK PLUS ONE
	JMP	PUTPAR
;************************************************************
ALLSET:
	LXI	D,ALLMSG
	MVI	C,3
	CALL	MSGTST
	MVI	L,0		;FIRST TRACK TO TRANSFER
	MVI	H,77		;LAST TRACK PLUS ONE
PUTPAR:	SHLD	TRKSRT		;PUT PARAMETERS IN TRKSRT AND TRKSRT+1
;************************************************************
REPEAT	LXI	SP,STKTOP
	LXI	D,INIT
	CALL	PRINT
	LXI	D,SOURCE
	CALL	PRINT
SOURCELOOP	CALL	CONIN
	CPI	'A'
	JZ	SETSOURCE
	CPI	'B'
	JZ	SETSOURCE
	CPI	'C'
	JZ	SETSOURCE
	CPI	'D'
	JZ	SETSOURCE
	JMP	SOURCELOOP
SETSOURCE	STA	SOURCEMESS
	SBI	41H
	STA	SOURCEDRIVE
	LXI	D,CRLF
	CALL	PRINT
	LXI	D,OBJECT
	CALL	PRINT
OBJECTLOOP	CALL	CONIN
	CPI	'A'
	JZ	SETOBJECT
	CPI	'B'
	JZ	SETOBJECT
	CPI	'C'
	JZ	SETOBJECT
	CPI	'D'
	JZ	SETOBJECT
	JMP	OBJECTLOOP
SETOBJECT	STA	OBJECTMESS
	SBI	41H
	STA	OBJECTDRIVE
	LXI	D,SIGNON
	CALL	PRINT
AGIN	CALL	CONIN
	CPI	3
	JZ	EXITCPM
	CPI	13
	JNZ	AGIN
	LXI	D,CRLF
	CALL	PRINT
;************************************************************
	CALL	COPY		;MAIN ROUTINE
	LXI	D,DONMSG	;SAY WE'RE DONE
	CALL	PRINT
	JMP	EXIT		;DONE. NOW GET OUT
;************************************************************
MSGTST:	LXI	H,TBUFF+3
	LDAX	D
	CMP	M		;SAME AS MESSAGE?
	JNZ	BADMSG
	INX	H
	INX	D
	DCR	C		;REDUCE CHARACTER COUNTER
	RZ			;FINISHED OK
	JMP	MSGTST+3	;CHECK OUT NEXT CHARACTER
;************************************************************
BADMSG:	LXI	D,CMDER1
	CALL	PRINT
	LXI	D,TBUFF+1		;PRINT ERRONEOUS COMMAND
	CALL	PRINT
	LXI	D,CMDER2
	CALL	PRINT
NOMSG:	LXI	D,CMDINF
	CALL	PRINT
	JMP	EXITCPM
;************************************************************
FAILR:	LXI	D,MESGD
	JMP	DIE
FAILW:	LXI	D,MESGE
DIE	CALL	PRINT
	LXI	D,ERM
	CALL	PRINT
	LDA	TRK
	CALL	PRTHEX
	LXI	D,MESGB
	CALL	PRINT
	LDA	SECTOR
	CALL	PRTHEX
	LXI	D,DRIVE
	CALL	PRINT
	LDA	PRESDISK
	ADI	41H
	MOV	C,A
	CALL	CONOUT
	XRA	A
	STA	ERR1
	RET
;************************************************************
EXIT:	LXI	D,REPMES
	CALL	PRINT
	CALL	CONIN
	CPI	'R'
	JZ	REPEAT
	CPI	13
	JNZ	EXIT
	MVI	C,0
	CALL	SELDSK
	JMP	EXITCPM
PRINT	LDAX	D
	CPI	'$'
	RZ
	PUSH	D
	MOV	C,A
	CALL	CONOUT
	POP	D
	INX	D
	JMP	PRINT
READTRAN	LDA	DENBYTE
	ORA	A
	JZ	SDSKEW
	LXI	H,READTABLE
	MVI	B,0
	DAD	B
	MOV	C,M
	PUSH	B
	CALL	SETSEC
	POP	B
	CALL	FINDDMA
	RET
SETSEC	MOV	A,C
	STA	SECTOR
	CALL	SETSEC1
	RET
WRITETRAN	LDA	DENBYTE
	ORA	A
	JZ	SDSKEW
	LXI	H,READTABLE
	MVI	B,0
	DAD	B
	MOV	C,M
	PUSH	B
	CALL	SETSEC
	POP	B
	CALL	FINDDMA
	RET
;SDSKEW	LXI	H,SDTABLE
	MVI	B,0
	DAD	B
	MOV	C,M
	PUSH	B
	CALL	SETSEC
	POP	B
	CALL	FINDDMA
	RET
SDSKEW	INR	C
	MOV	A,C
	STA	SECTOR
	STA	BSECTOR
	LHLD	DMAAD
	SHLD	BDMA
	LXI	D,128
	DAD	D
	SHLD	DMAAD
	RET
FINDDMA	MVI	H,0
	DCR	C
	MOV	L,C
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	DAD	H
	XCHG
	LHLD	DMAAD
	DAD	D
	CALL	DMASET
	RET
SDTABLE		DB	1,3,5,7,9,11,13,15,17,19,21,23,25
		DB	2,4,6,8,10,12,14,16,18,20,22,24,26
READTABLE	DB	1,3,5,7,9,11,13,15,17,19,21,23,25
		DB	27,29,31,33,35,37,39,41,43,45,47
		DB	49,51,2,4,6,8,10,12,14,16,18,20
		DB	22,24,26,28,30,32,34,36,38,40
		DB	42,44,46,48,50,52
WRITETABLE	DB	1,5,9,13,17,21,25,29,33,37,41
		DB	45,49,2,6,10,14,18,22,26,30,34
		DB	38,42,46,50,3,7,11,15,19,23,27
		DB	31,35,39,43,47,51,4,8,12,16,20
		DB	24,28,32,36,40,44,48,52
BUF0	DS	128*DDLASTSEC
BUF1	DS	128*DDLASTSEC
