	TITLE	'MITS 88DCDD DISK TO CP/M FILE TRANSFER'
	PAGE	58
 ; MITS TO CP/M FILE CONVERSION ROUTINE
; CODED 11/80 THRU 1/81 (MY FIRST CP/M PROGRAM)
; FOLLOWS CONVPATB FAIRLY CLOSELY ( SEE THIS WELL DOCUMENTED PROGRAM )
; USES DIFFERENT USER INTERFACE ETC...
;
;  Updated 3/2013 by Mike Douglas:
;
;     1) Replace deleted source lines that prevented assembly.
;
;     2) Re-select drive zero upon head unload to allow CPM to run
;	 on the same controller as the Altair floppy disk that is 
;	 being copied.
;
;     3) Use bit 3 of the drive status register to detect presence 
;	 of a floppy instead of bit 5 (INTE). (SIMH and Altair32 emulators
;	 do not properly set/clear INTE.)
;
TRUE	EQU	0FFFFH
FALSE	EQU	NOT TRUE
DEBUGGING EQU	TRUE	; SAY BUGS NOT OUT YET ***** CHANGE LATER *****
CHECKOUT EQU	FALSE	; USED TO INTERFERE WITH CARD BUFFER
LOCATION	EQU	100H	; LOCATION OF THE START OF THIS STUFF
NFILES	EQU	255	; NUMBER OF FILES IN MITS DIRECTORY
NSECTS	EQU	32	; 32 SECTORS PER TRACK
DBIAS	EQU	7	; BIAS IN MITS DIRECTORY
			; WHY ISN'T ANY PROGRAM IN HARMONY WITH ITS DOC?
DSIZE	EQU	16	; LENGTH OF MITS DIRECTORY ENTRY
BSIZE	EQU	137	; SECTOR LENGTH ON 88-DCDD PERTEC FD-400'S
NFPS	EQU	BSIZE/DSIZE ; NUMBER FILES/SECTOR (TRUNCATED)
VERS	EQU	10	; VERSION 1.0
MODL	EQU	1	; MODIFICATION LEVEL 0
DTRACK	EQU	70	; DIRECTORY TRACK
ENDSLOT EQU	0377Q	; FLAG FOR LAST FILE
CTLC	EQU	'C'-64	; CONTROL C
CTLU	EQU	'U'-64	; CONTROL U
BACKSP	EQU	'H'-64	; BACKSPACE (CTL H)
CTLD	EQU	'D'-64	; CONTROL D
CTLP	EQU	'P'-64	; CONTROL P
CTLZ	EQU	'Z'-64	; CONTROL Z
CTLS	EQU	'S'-64
CTLQ	EQU	'Q'-64
CR	EQU	0DH	; CARRIAGE RETURN
LF	EQU	0AH	; LINE FEED
;
; MACROS
;
CPM	MACRO	?F,?P
	PUSH	B
	PUSH	D
	PUSH	H
	IF	NOT NUL ?F
	MVI	C,?F
	ENDIF
	IF	NOT NUL ?P
	LXI	D,?P
	ENDIF
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	ENDM
MSG	MACRO	?M,?J
	IF	NOT NUL ?M
	LXI	H,?M
	ENDIF
	CALL	PRMSG
	IF	NOT NUL ?J
	JMP	?J
	ENDIF
	ENDM
;
;
	ORG	LOCATION ; START OF SOMETHING
;
; THIS PROGRAM WILL READ A MITS FILE THRU THE 88-DCDD CONTROLLER AND
; BY MEANS OF RESIDENT CP/M WRITE THE FILE TO A CP/M DISK.
; .........................................................................
;
;	PROGRAMMED BY A. L. BENDER, M.D.
;
; .........................................................................
;
; MCNVT WILL USE ANY REPRESENTATION OF THE CP/M FILENAME ALLOWED
;
	JMP	MCNVT
	IF	DEBUGGING
PATCH	DS	50
	ENDIF
OND	DS	NFILES*DSIZE
OP	DS	1	; CURRENT
ADDR	DW	0	; I/O ADDRESS IN MITS PACKAGE (LIKE DMA ADDR)
NWDS	DB	0	; NUMBER OF WORDS TO BE READ BY MITS PACKAGE
FCOUNT	DS	1	; NUMBER OF FILES ACTUALLY IN MITS DIRECTORY
BUFFER	DS	BSIZE	; READ MITS BUFFER
FCB	DS	33	; FILE CONTROL BLOCK
FN	DB	0	; CURRENT FILE NUMBER BEING PROCESSED
RWFLAG	DB	0	; READ/WRITE FLAG FOR MAKEFCB
RANDFLAG: DB	0	; 0=SEQUENTIAL 2=RANDOM 1=ISFMS (SPECIAL NSI FILE)
WRCOUNT:DB	0	; BYTES WRITTEN
MITSNAME: DS	8	; MITS FILE NAME
CRCEL	DW	0	; I-RECORD ADDR
CRCL1	DW	0	; L RECORD ADDR
FRSTCH:	DB	0	; FIRST CHARACTER IN MITS FILE
NREC:	DW	0	; NUMBER RECORDS WRITTEN
DISK	DB	0	; DISK NUMBER BEING ACCESSED (ADDED BY M DOUGLAS)
TRACK	DB	0	; TRACK BEING ACCESSED (ADDED BY M DOUGLAS)
SECTOR	DB	0	; SECTOR BEING ACCESSED (ADDED BY M DOUGLAS)
;
; --- CP/M INTERFACE EQUATES ---
;
BDOS	EQU	5	; ENTRY TO CP/M I/O ROUTINE
DOSBUF	EQU	0080H	; DEFAULT BUFFER
CLOSEF	EQU	16	; CLOSE FILE
CONS	EQU	1	; READ CONSOLE INPUT BYTE TO A
CONSTAT	EQU	11
EXIT	EQU	0	; EXIT ADDRESS
CREATEF	EQU	22	; CREATE FILE
DELETEF	EQU	19	; DELETE FILE COMMAND
OPENF	EQU	15	; OPEN FILE
READF	EQU	20	; READ FILE
WRITEF	EQU	21	; WRITE FILE
TBUFF	EQU	0080H	; DEFAULT BUFFER
TFCB	EQU	005CH	; DEFAULT FCB
SETDMA: EQU	26	; SET ADDRESS OF DMA
RDBUF:	EQU	10	; READ BUFFERED CONSOLE
TYPEF	EQU	2	; CONSOLE OUTPUT
SRCHF	EQU	17	; SEARCH FOR FILE IN DIRECTORY
;
;----- CONVASCI - CONVERT BINARY NUMBER IN BC TO ASCII
;		  IF RADIX=8 CONVERSION WILL BE OCTAL
;		  IF RADIX=10 CONVERSION WILL BE DECIMAL
;
; ENTER WITH NUMBER IN BC (B=LSB, C=MSB)
; RETURNS WITH NUMBER IN M1-M5 (LSB->MSB) AND
; ADDRESS OF M1 IN BC
;
; REGISTERS DE AND HL PRESERVED
;
; RADIX IS IN A ON ENTRY (A=10 OR A=8) (THIS WORKS FOR ANY BASE <=10)
;
; IF ENTRY IS AT SETRADIX THEN A MUST BE SET IF CONVASCI IS USED THEN
; RADIX IS ASSUMED 10 OR SET.
;
SETRADIX STA	RADIX
		RET
;
CONVASCI PUSH	H
	PUSH	B
	LXI	H,M1
	XRA	A
	MVI	B,5
CV1:
	MOV	M,A
	INX	H
	DCR	B
	JNZ	CV1
	POP	B
	MOV	H,B
	MOV	L,C
	PUSH	D
	MVI	D,5
	LXI	B,M1
CV2	CALL	CONVONE
	STAX	B
	INX	B
	DCR	D
	JNZ	CV2
	POP	D
	POP	H
	LXI	B,M1
	RET
CONVONE	PUSH	B
	MVI	C,10
RADIX	EQU	$-1
	CALL	DIVIDE
	POP	B
	ADI	'0'
	RET
M1	DB	0,0,0,0,0
;
;
; DIVIDE 16 BITS BY 8 BITS
; HL=>DIVIDEND
; C=>DIVISOR
;
; RETURNS WITH HL=>QUOTIENT
; C=>DIVISOR
; A=>REMAINDER
;
DIVIDE	XRA	A
	CMP	C
	STC
	RZ
	MVI	B,16	; NUMBER OF TIMES TO LOOP
D1	DAD	H
	RAL
	CMP	C
	JC	D2
	SUB	C
	INX	H
D2	DCR	B
	JNZ	D1
	RET
; DIRECTORY LOOKUP ROUTINE
; USED TO SEARCH MFD BEGINNING AT OND
;
LOOKUP:	LXI	H,OND	; GET BASE OF DIRECTORY
	LDA	FCOUNT	; NUMBER OF FILES IN DIRECTORY
	MOV	B,A	; NUMBR OF FILES IN DIRECTORY
LOOK1	MVI	C,8	; NUMBER OF BYTES IN FILENAME
	PUSH	D
LOOK2	LDAX	D	; INPUT FILE TO LOOKUP ADDR IN DE
	CMP	M
	JNZ	LOOK3	; NOT THIS ENTRY
	INX	D
	INX	H
	DCR	C
	JNZ	LOOK2
	MOV	A,M
	STA	TRACK	; SET TRACK ADDRESS
	INX	H
	MOV	A,M
	STA	SECTOR
	INX	H
	MOV	A,M	; FILE TYPE
	SUI	2	; ZERO FOR SEQUENTIAL
	STA	RANDFLAG ; RANDOM/SEQUENTIAL FLAG
	INX	H
	MOV	A,M	; FILE NUMBER
	STA	FN	; SAVE FILE NUMBER (PREVENT FILE LINK ERROR LATER)
	POP	D
	ORA	A	; CLEAR CARRY
	RET		;HL=>ENTRY
LOOK3	DCR	B	; DECREMENT NUMBER OF FILES
	JNZ	LOOK4	; JUMP IF MORE TO DO
	POP	D
	STC		; FAILED, FILE NOT IN DIRECTORY
	RET
LOOK4	MVI	A,DSIZE-8
	ADD	C	; NUMBER OF BYTES TO SKIP PAST
	CALL	ADDAHL	; ADD A TO HL
	POP	D
	JMP	LOOK1
;
PRMPT	PUSH	H
	PUSH	D
	CALL	CRLF
	MVI	A,'*'
	CALL	OUTEEE
	POP	D
	POP	H
	RET
NAMEMOV:
	LXI	B,8
	MVI	A,' '
	LXI	D,MITSNAME
	PUSH	D
	CALL	FILLB
	POP	D
	MVI	C,9	; MITS FILE NAME SIZE+1
MOVE1:
	MOV	A,M	; PICK UP MITS FILE NAME OR DISK
	CALL	TERMT	; CHECK TERMINATION
	RZ		; PROPER
	STAX	D	; SAVE IT AWAY
	INX	H
	INX	D
	DCR	C	; COUNT
	JNZ	MOVE1
	MSG	BMFN	; IMPROPER MITS FILE NAME
	XRA	A
	STA	TBUFF
	JMP	INPUTX	; GET CARD IMAGE
BADTERM: MSG	BADPUNK,INPUTX	; IMPROPER PUNCTUATION
BADDISK: MSG	DSKERR,INPUTX	; BAD DISK NUMBER (MITS DISK)
;
INPUTCDI:
	LXI	H,TBUFF
	MOV	A,M	; GET CHARACTER COUNT OF TBUFFER
	CPI	2	; IF 0 OR 1 CHARACTER, NO INPUT ON TBUFF
	JC	INPUT1	; NO LINE IMAGE
	PUSH	H
	INR	A	; POSITION BEYOND INPUT
	CALL	ADDAHL	; UPDATE POINTER
	MVI	M,CR	; PUT CR AT END OF LINE BUFFER
	POP	H
	LXI	D,FCB	; SET FCB ADDRESS
	INX	H	; SET H TO FW OF TBUFF
	CALL	SKIPS	; SKIP BLANKS LEADING MSG
	MOV	A,M	; GET F.C OF IMAGE
	CPI	'='	; IF FC IS = THEN WANT DIRECTORY ONLY
	JZ	PUTDIR	; PUT OUT DIRECTORY THEN RESTORE STACK REINITIALIZE
	CALL	MAKEFCB	; BUILD FCB
	JNC	SCAN2	; GO TO SCAN MITS FILE NAME
	LXI	H,CPFMSG ; INDICATE CP/M FILE NAME IS IN ERROR
INPERR:	CALL	PRMSG
INPUTX:	XRA	A
	LXI	H,TBUFF
	MOV	M,A
	INX	H
	LXI	B,080H	; C=128 BYTE BUFFER, B=NR WDS READ
INPUT1	CALL	PRMPT	; PROMPT INPUT FROM CONSOLE
	MVI	A,125	; SO IT WILL FIT TBUFF...
	STA	BUFFER	; CONSTRUCT READ BUFFER
	CPM	RDBUF,BUFFER
	LXI	D,BUFFER+1 ; TRANSFER IMAGE TO TBUFF
	LXI	H,TBUFF	; [PRETEND IT WAS THERE ALWAYS]
	LDA	BUFFER+1 ; GET COUNT OF BUFFER BYTES
	INR	A	; COUNT BYTE
	MOV	B,A	; STUFF INTO COUNTER
INPUT2	LDAX	D	; MOVE STRING FROM BUFFER TO TBUFF
	MOV	M,A ;
	INX	H ;
	INX	D ;
	DCR	B ;
	JNZ	INPUT2	; LOOP
	MVI	A,CR	; TACK ON FINAL C/R CHARACTER
	MOV	M,A	; TO BUFFER (10 FUNCTION DOESN'T PUT IT THERE)
	CALL	CRLF
	JMP	INPUTCDI
SCAN2:	CPI	CR	; SEE IF IMAGE IS NOT COMPLETE
	JNZ	SCAN3	; SO FAR SO GOOD
	LXI	H,NOMITS
	JMP	INPERR	; ERROR IN INPUT
SCAN3:	LXI	D,MITSNAME
	CALL	NAMEMOV	; MOVE MITS FILE NAME
	JC	BADTERM
	CPI	','	; LOOK FOR COMMA TERM
	JNZ	BADTERM
	INX	H	; GET TO THE NUMBER NOT THE COMMA
	CALL	DN	; CONVERT DISK NUMBER TO BINARY
	STA	DISK
	CPI	16	; HIGHEST DISK + 1
	JNC	BADDISK
	MOV	A,M
	CALL	TERMT
	JNZ	BADDISK
	XRA	A
	STA	TBUFF
	RET
;
; DN / CONVERTS STRING AT HL TO BINARY IN A
; HL ADVANCED TO END OF INTEGER
DN:	XRA	A
	PUSH	D
DN1:	MOV	D,A	; SAVE A
	MOV	A,M
	SUI	'0'	; TAKE BIAS AWAY
	JC	DNX	; DONE, GET OUT
	CPI	10	; DONE, IF >
	JNC	DNX
	MOV	E,A
	MOV	A,D
	RLC	;
	RLC	;		*4
	ADD	D	; *5
	RLC	;		*10
	ADD	E	; ADD DIGIT
	INX	H
	JMP	DN1
DNX:
	MOV	A,D
	POP	D
	RET
; MAKEFCB.LIB 9/4/78
; ORIGINAL VERSION IN CP/M LIBRARY VOL 8
; CORRECTED 9/78 BY P. HOLLIDAY
;
; LOCAL SYMBOLS
;
FCBSIZ:	EQU	33	; SIZE OF FCB
FNMLEN:	EQU	11	; LENGTH OF FILE NAME
MAKEFCB:DS	0	; ENTRY POINT LABEL
MTFCB:	PUSH	H	; COMMAND STRING POINTER
	PUSH	D	; FCB ADDRESS
	STA	RWFLAG	; SAVE READ/WRITE FLAG
	LXI	B,FCBSIZ ; FILL FCB WITH ZERO
	CALL	CLRB	; CLEAR FCB
	LXI	D,FCB+1
	LXI	B,FNMLEN	; FILL FILE NAME AREA
	MVI	A,' '	; WITH BLANKS
	CALL	FILLB
	POP	D
	POP	H	; RESTORE POINTERS
	CALL	SKIPS	; PASS LEADING BLANKS
	INX	H	; CHECK FOR DISK CODE
	MOV	A,M
	DCX	H
	CPI	':'	; EXPLICIT DISK
	JNZ	MTFCB1	; NOT EXPLICIT DISK
	MOV	A,M	; VALID DISK CODE?
	INX	H
	INX	H
	SBI	'@'	; SENSE A-Z
	RC		; IN CASE ZERO TEST FAILS
	CPI	'Z'-'A'+1
	CMC
	RC		; SET IF IN ERROR
	STAX	D	; SAVE DISK CODE AT FCB+0
;PROCESS FILE NAME FIELD
MTFCB1:	INX	D
	MVI	C,8
	CALL	GETNAM
	MOV	A,M	; TEST FOR FILE TYPE SEPARATOR
	INX	H
	CPI	'.'
	JNZ	MTFCB2
	MVI	C,3
	CALL	GETNAM
	MOV	A,M
	INX	H
;CHECK TERMINATION OF FIELD
MTFCB2:	CALL	TERMT
	RET		; RETURN TO USER
;
;PROCESS NAME FIELD
;
GETNAM:	MOV	A,M	; GET CHARACTER FROM COMMAND STRING
	INX	H
	CPI	'?'	; ALLOW AMBIGUITY TO EXIST IN NAME
	JNZ	GETN20	; NOT AMBIGUOUS CHARACTER
	LDA	RWFLAG	; GET R/W FLAG
	ORA	A	; SET FLAGS
	MVI	A,'?'	; RESET ? CHAR
	JZ	GETNA1	; STORE AMBIG CHAR
	JMP	GETNA3	; NG,WRITING FILE ? DISALLOWED
GETN20:	CPI	'*'	; CHECK FOR FULL FIELD OF ???
	JZ	GETNA2
	CALL	VALCHR	; TEST FOR VALID CHARACTERS IN NAME
	JC	GETNA3	; INVALID, SKIP OVER REMAINDER OF FIELD
GETNA1:	STAX	D	; SAVE FILE NAME OR TYPE
	INX	D
	DCR	C	; ACCUMULATE EVERYTHING
	JNZ	GETNAM	; LOOP TO FINISH FIELD
	RET		; DONE WITH SCAN
GETNA2:	LDA	RWFLAG
	ORA	A	; TEST FOR WRITE OPERATION ON FILE
	JZ	GETNA3	; NG,WRITE ON AMBIGUOUS FILE NAME
	MVI	A,'?'
	MVI	B,0	; FILL WITH ?
	JMP	FILLB	; FILLB WILL RETURN TO USER
GETNA3:	INX	D	; SKIP TO END OF FIELD IN FCB
	DCR	C
	JNZ	GETNA3
	DCX	H	; POINT TO NEXT CHARACTER IN INPUT STRING
	RET
; TEST FOR VALID CHARACTER IN NAME FIELD
; RETURN IF INVALID WITH CARRY SET
; ADDED TEST FOR = SIGN ALSO 12/19/80
;
VALCHR:	CPI	CR	; TEST FOR C/R
	CMC	; 	COMPL CARRY
	RZ
	CPI	'*'
	CMC
	RZ
	CPI	','
	CMC
	RZ
	CPI	'='
	CMC
	RZ
	CPI	'.'
	CMC
	RZ
	CPI	' '
	RC
	CPI	'^'+1
	CMC
	RC
	CPI	':'
	CMC
	RNC
	CPI	'A'-1	
	RET
;
;TEST FOR VALID FILE NAME TERMINATOR
;
TERMT:	CPI	' '
	RZ
	CPI	','
	RZ
	CPI	CR
	RZ
	CPI	';'
	RZ
	CPI	'='
	RZ
	STC
	RET
;
;SKIP SPACES IN COMMAND STRING
;
SKIPS:	MVI	A,' '
SKIPS1:	CMP	M
	RNZ
	INX	H
	JMP	SKIPS1
; FILL BLOCK WITH VALUE
; ENTER WITH VALUE IN A
; DE=START OF BLOCK
; BC=LENGTH OF BLOCK
;
CLRB:	XRA	A	; ENTRY TO ZERO BLOCK
FILLB:	INR	B	; DOUBLE TALK TO AVOID MESSING WITH A
	DCR	B
	JNZ	FILLB1
	INR	C
	DCR	C
	RZ
FILLB1:	STAX	D
	INX	D
	DCX	B
	JMP	FILLB
;
; END OF MAKEFCB.LIB
;
;
;
;
; FNCALC - CALCULATES THE FILE NUMBER RELATIVE TO  THE OLD DIRECTORY
;
; ENTER WITH B=SLOT-K
;
; THE TERM NEW DIRECTORY REFERS TO THE MITS DIRECTORY WITH ALL DELETED FILES
; REMOVED.  OND=>IS THE  "ORIGIN OF THE NEW DIRECTORY" FCOUNT=>THE NUMBER OF
; FILES REALLY PRESENT IN THE NEW DIRECTORY
;
FNCALC	LDA	BUFFER+1
	PUSH	B
	RLC	; *2
	RLC	; *4
	RLC	; *8 (THE BOOK IS WRONG, ITS 8*SSECTOR+)
	MOV	C,A	; SECTOR
	MVI	A,9
	SUB	B
	ADD	C	; 8*SECTOR+(SLOT+1)
	POP	B
	RET
;
;
; MESSAGES
;
SIGNON	DB	0DH,0AH,'MITS FILE COPY VERS '
	DB	VERS/10+'0','.',VERS MOD 10+'0'
	DB	' (,',MODL+'0',')'
	DB	0
FMTERR	DB	0DH,0AH,'DIRECTRY FMT ERR'
	DB	0
NFMSG	DB	0DH,0AH,'NMBR OF FILES IN CURRENT '
	DB	'DIRECTORY:',0
FLERRM	DB	0DH,0AH,'FILE LINK ERROR ON MITS DISK',0
CKSUM	DB	0DH,0AH,'CHECKSUM ERROR ON MITS FILE',0
DIRRD	DB	0DH,0AH,'ERROR TRYING TO RECOVER MITS DIRECTORY FROM DISK',0
CPFMSG	DB	0DH,0AH,'CP/M FILE NAME IN ERROR',0
TRKERR	DB	0DH,0AH,'BAD TRACK ADDRESS',0
SECERR	DB	0DH,0AH,'BAD SECTOR ADDRESS',0
FMTNG	DB	0DH,0AH,'DATA SECTOR FORMAT IMPROPER',0
RDMSG	DB	0DH,0AH,'READING MITS FILE',0
ENDMSG	DB	CR,0AH,'END OF CP/M DISK MEDIUM',0
EXTMSG	DB	CR,0AH,'ERROR ENCOUNTERED EXTENDING CP/M DISK',0
FULMSG:	DB	CR,0AH,'CP/M DIRECTORY FULL',0
NOMITS:	DB	CR,0AH,'NO MITS DISK FILE SPECIFIED',0
NAMERR	DB	CR,0AH,'ERROR SPECIFYING MITS DISK',0
DSKERR	DB	CR,0AH,'ERROR IN CONVERTING DISK NUMBER',0
NFMDMS	DB	' FILES IN MITS DIRECTORY',CR,LF,0
	DB	CR,0AH,'TOO MANY OR TOO LONG ARGUMENTS',0
BMFN	DB	CR,LF,'BAD MITS FILE NAME (TOO LONG)',0
BADPUNK	DB	CR,LF,'IMPROPER FILE SYNTAX',0
FSRCHF	DB	CR,LF,'MITS FILE SEARCH FAILED',0
;
; CHARACTER OUTPUT TO CONSOLE
;
OUTEEE:	MOV	E,A
	CPM	TYPEF	; TYPE A CHARACTER
	RET
CRLF	MVI	A,0DH
	CALL	OUTEEE
	MVI	A,0AH
	JMP	OUTEEE
;
PRMSG:
;
;PRINT MESSAGE TO ZERO BYTE
;FOR DETAILS SEE INTEL ISIS MANUAL OR CP/M SAMPLE BIOS
	MOV	A,M
	ORA	A
	RZ
	MOV	E,A
	CPM	TYPEF
	INX	H
	JMP	PRMSG
;
;
;
; START OF MAIN PROGRAM
;
MCNVT	LXI	H,0
	DAD	SP	; SAVE CP/M STATUS AS THIS PROGRAM DOESN'T CLOBBER IT
	SHLD	CPMSTK	; STACK POINTER FOR CP/M
MCNVT1	LXI	SP,STACK ; GET NEW STACK ADDRESS
	MSG	SIGNON	; PUT OUT SIGNON MESSAGE
MCNVT1A:	CALL	INITIAL	; INITIALIZE
	CALL	SETFILES
	CALL	MDRD	; RECOVER MITS FILE DIRECTRY
	CALL	SORT	; SORT DIRECTORY
	CALL	PRINTDIRECTRY
	LXI	D,MITSNAME
	CALL	LOOKUP	; LOOKUP NAME IN DIRECTORY
	JNC	MCNVT2	; SEARCH SUCCESSFUL
	MSG	FSRCHF,MCNVT1A	; SEARCH FAILED
MCNVT2:	CALL	COPYFILE
	CALL	CRLF
	LHLD	NREC	; GET WRITE COUNTER
	MOV	B,H
	MOV	C,L
	CALL	CONVASCI	; CONVERT TO ASCII
	LXI	H,M1+4	; START OF DIGIT STRING
	MVI	B,5	; NO OF ASCII DIGITS
	MVI	E,0	; FLAG TO SUPRESS ZERO
MCNVT3:	MOV	A,M	; GET A DIGIT
	CPI	'0'
	JZ	MCNVT6
	MOV	E,A	; SET FLAG SIGNIFICANT DIGIT
MCNVT4:	CALL	OUTEEE
MCNVT5:	DCX	H
	DCR	B
	JNZ	MCNVT3
	CALL	MCNVT8
	MSG	BLOCKMSG,MCNVT7
MCNVT6:	MOV	D,A
	MOV	A,E
	ORA	A
	JZ	MCNVT5	; LEADING ZEROS
	MOV	A,D	; IN SIGNIFICANT PART OF INTEGER
	JMP	MCNVT4
BLOCKMSG: DB	' SECTORS COPIED TO CP/M FILE.',CR,LF,0
MCNVT7:	CALL	CLWRF	; CLOSE WRITE FILE
	JMP	MCNVT1A
MCNVT8:	LXI	H,BINARY
	LDA	FRSTCH
	INR	A
	JZ	MCNVT9	; JUMP IF BINARY DATA
	LXI	H,ASCII
MCNVT9:	CALL	PRMSG
	RET
BINARY:	DB	' BINARY DATA',0
ASCII:	DB	' ASCII BYTE DATA',0
; PRINT DIRECTORY ON MITS DISK - INVOKED BY =N
;
PUTDIR:	INX	H
	CALL	DN
	STA	DISK
	CALL	PMITS	; PRINT SORTED DIRECTORY
	XRA	A
	STA	TBUFF	; ZEROIZE TO PREVENT COMING BACK IN A LOOP
	LXI	SP,STACK
	JMP	MCNVT1A
; PRINT MITS FILE DIRECTORY
; THE DIRECTORY IS STORED AT OND
; IT MAY BE PRESORTED BY SORT OR IT MAY BE PRINTED
; WITHOUT SORTING.
;
PRINTDIRECTRY:
	CALL	CRLF
	LDA	FCOUNT
	CALL	DECOUT
	MSG	NFMDMS	; PUT OUT NUMBER OF FILES
	LDA	FCOUNT	; GET PRESET
	MOV	B,A	; NUMBER OF FILES IN DIRECTORY
	LXI	D,OND	; ORIGIN OF THE NEW MITS DIRECTORY
PRDIR1:	CALL	DLIST	; PRINT ONE DIRECTORY ENTRY
	LXI	H,DSIZE	; LENGTH OF A DIRECTORY ENTRY
	DAD	D	; PLUS ADDRESS
	XCHG		; TO D
	DCR	B
	JNZ	PRDIR1	; LOOP UNTIL ENTIRE DIRECTORY PRINTED
	RET
DLIST:	PUSH	H
	PUSH	D
	PUSH	B	; SAVE EVERYTHING
	XCHG		; HL=ADDRESS OF THIS ENTRY
	LXI	B,0803H	; MVI C,3; MVI B,8
DLIST1	MOV	A,M	; FILE NAME TO A
	CALL	OUTEEE
	INX	H
	DCR	B
	JNZ	DLIST1
	MVI	A,' '	; BLANK
DLIST2:	CALL	OUTEEE	; (THREE OF THEM)
	DCR	C
	JNZ	DLIST2	; TO PRINTER
	MOV	A,M	; GET TRACK NUMBER
	CALL	DECOUT	; PRINT IT
	MVI	A,','	; PRINT BLANK
	INX	H
	CALL	OUTEEE
	MOV	A,M	; GET SECTOR NUMBER
	CALL	DECOUT	; PRINT SECTOR NUMBER
	MVI	A,','
	CALL	OUTEEE
	INX	H
	MOV	A,M
	MVI	B,'R'
	CPI	4	; 4=RANDOM
	JZ	DLIST3
	MVI	B,'S'
DLIST3:	MOV	A,B
	CALL	OUTEEE	; PRINT FILE TYPE
	MVI	A,','
	CALL	OUTEEE
	INX	H	; GET TO FILE NUMBER
	MOV	A,M
	CALL	DECOUT	; PRINT FILE NUMBER
	CALL	CRLF
	POP	B
	POP	D
	POP	H
	RET
;
; DECOUT => DECIMAL OUTPUT
;
; SUPPRESS LEADING ZERO
; OUTPUT A BLANK INSTEAD
;
DECOUT:	PUSH	D
	PUSH	B
	MVI	E,0	; CLEAR ZERO FLAG
	MVI	C,100	; DIVIDE BY 100
	CALL	DECOU1
	MVI	C,10	; DIVIDE BY 10
	CALL	DECOU1
	ADI	'0'	; DIVIDE BY '1'
	CALL	OUTEEE	; UNITS
	POP	B
	POP	D
	RET
DECOU1:	MVI	B,'0'-1
	INR	B
	SUB	C
	JNC	DECOU1+2	; LOOP UNTIL DIVIDE RESULTS IN REMAINDER
	ADD	C
	MOV	D,A
	MOV	A,B
	CPI	'0'	; SENSE ZERO
	JNZ	DECOU2	; NOT ZERO, SET FLAG NZ, OUTPUT ASCII
	MOV	A,E	; GET ZERO FLAG
	ORA	A	; SET
	MOV	A,D
	RZ
DECOU2:	INR	E	; SET FLAG
	MOV	A,B
	CALL	OUTEEE
	MOV	A,D
	RET
;
; COPYFILE => READS MITS FILE / WRITES CPM FILE
;
; AT THE START OF THE COPY, TRACK=TRACK ADDRESS OF FILE
; SECTOR = SECTOR ADDRESS OF FILE.  DISK IS SELECTED FROM READ OF DIRECTORY
; TRACK AND SECTOR WERE SET BY DIRECTORY SEARCH SUBROUTINE.
;
; COPY PROCEEDS ONE SECTOR AT A TIME.
; READ MITS SECTOR, UPDATE TRACK AND SECTOR, WRITE CP/M SECTOR LOOP ETC.
; TERMINATES ON ZERO TRACK/SECTOR OR EOF CHARACTER.
;
COPYFILE:
	LDA	RANDFLAG	; IS FILE RANDOM
	ORA	A	; SET
	JNZ	APOLOGY	; DONT DO AT THIS TIME
CPYFL1:	CALL	RDMITS	; READ MITS DISK
	CALL	WRCPM	; WRITE CP/M FILE
	LHLD	BUFFER+5
	MOV	A,L
	ORA	H
	JNZ	CPYFL1
	RET
APOLOGY: MSG	APMSG,MCNVT
APMSG	DB	CR,LF,'CANT DO RANDOM FILES YET',0
	;
;INITIALIZE
;
INITIAL: LXI	H,BUFFER	; SET BUFFER ADDRESS
	SHLD	ADDR
	MVI	A,BSIZE
	STA	RWFLAG	; SAY READING
	STA	NWDS
	XRA	A
	STA	OP	; READING=0
	STA	RWFLAG
	IF	CHECKOUT
	STA	TBUFF
	ENDIF
	OUT	8	; SELECT DRIVE 0
	LXI	H,0
	SHLD	NREC	; INITIALIZE WRITE COUNTER
	CALL	INPUTCDI
	RET
;
; PMITS => RECOVERS AND PRINTS MITS DIRECTORY
;
PMITS	CALL	MDRD
	CALL	SORT
	CALL	PRINTDIRECTRY
	RET
;
; SETFILES
; THIS ROUTINE SETS UP THE OUTPUT FILE
; IT CALLS ON CP/M TO SEARCH FOR THE FILE AND THEN IT
; DESTROYS IT IF FOUND.
;
SETFILES: LXI	D,FCB	; SET UP FCB ADDRESS AS INPUT
	PUSH	D
	CPM	SRCHF
	INR	A	; NOT FOUND?
	JZ	SET1	; YES
	POP	D
	PUSH	D
	CPM	DELETEF
SET1	POP	D
	PUSH	D
	CPM	CREATEF
	POP	D
	CALL	SETUPO	; OPEN FILE
	CPM	SETDMA,BUFFER+7 ; DMA ADDRESS TO WRITE MITS FILE
	RET		; RETURN TO USER
;
; END OF PROGRAM
;
;
; SECTOR TRACK ROUTINE FOR 88-DCDD
;
SECGET	DI	; SECTOR ACQUIRE DON'T ALLOW TRAPPING
SG1	IN	9 ; GET CURRENT DATA STUFF
	RAR
	JC	SG1
	ANI	31	; MASK OFF SECTOR NUMBER
	CMP	E ; E=>DESIRED SECTOR
	JNZ	SG1 ; NXT ONE MAYBE
	RET
;
; TRACK ROUTINE
;
TRACKGET IN	8 ; GET STATUS OF DISK
	ANI	4 ; IS HEAD LOADED?
	CNZ	LOADHEAD ; NOPE, LOAD IT
	CALL	FINDTRACK ; FIND TRACK IN RAT
	LDA	TRK ; FOR DEBUGGING TRK IS PUT HERE WHEN FOUND IN RAT
	CMP	D ; IS THIS THE DESIRED TRACK ON THIS DISK?
	RZ	; YES
	PUSH	PSW ; SAVE RESULTS OF COMPARE
	CALL	LOADHEAD
	POP	PSW
	
	JM	STEPIN ; NEGATIVE MEANS HEAD IS TOO FAR TOWARDS EDGE
STEPOUT
	CALL	POUT ; POSITIVE, MEANS TOO FAR TOWARDS CENTER
	LDA	TRK
	DCR	A
	STA	TRK ; COUNT DOWN TRACK AS WE STEP HEAD
	CMP	D ; IS THIS THE DESIRED TRACK?
	JNZ	STEPOUT ; NO, KEEP COUNTING
	CALL	STORETRACK ; PUT TRACK BACK IN RAT
	JMP	MOVE
STEPIN	CALL	PIN
	LDA	TRK
	INR	A
	STA	TRK ; INCREMENT AS  WE GO IN TOWARDS THE HUB
	CMP	D
	JNZ	STEPIN
	CALL	STORETRACK
	JMP	MOVE
PIN	CALL	MOVE
	MVI	A,1
	OUT	9
	RET	; STEPS HEAD INWARDS 1 TRACK
LOADHEAD MVI	A,4 ; 4 SAYS MOVE HEAD ONTO THE SURFACE
	OUT	9
LH1	IN	8 ; GET DISK STATUS
	ANI	4 ; MOVEMENT ALLOWED?
	RZ
	JMP	LH1
TRACK0	XRA	A
	STA	TRK ; SET IT TO ZERO
	CALL	STORETRACK ; FIX RAT
TR01	CALL	MOVE
	IN	8
	ANI	0100Q ; CHECK IF ON TRACK ZERO
	RZ	; YES, DONE
	CALL	POUT ; STEP HEAD TOWARDS TRACK 0
	JMP	TR01
POUT	CALL	MOVE
	MVI	A,2 ; COMMAND TO STEP OUT
	OUT	9
	RET
MOVE	IN	8
	ANI	2 ; IS HEAD MOVEMENT ALLOWED (VALID SECTOR INDEX PULSE)
	RZ ; YES
	JMP	MOVE
HEADUNLOAD MVI	A,8 ; UNLOAD COMMAND
	OUT	9
	XRA	A	; SELECT DRIVE 0 (POSSIBLY CP/M DRIVE) (ADDED BY M DOUGLAS)
	OUT	8
	RET
FINDTRACK PUSH  H ; FINDS TRACK IN RAPID ACCESS TABLE
	LDA	DISK
	LXI	H,RAT
	CALL	ADDAHL ; ADD  A TO HL (GET WHICH DISK IT IS)
	MOV	A,M ; GET THE ENTRY FOR THAT DISK
	STA	TRK ; SET THAT TOO
	POP	H
	RET
ADDAHL:
	ADD	L
	MOV	L,A
	RNC
	INR	H
	RET	; THATS ALL THERE IS TO IT
STORETRACK PUSH H
	LXI	H,RAT
	LDA	DISK
	CALL	ADDAHL ; ADD A TO HL GET THE RIGHT SLOT IN RAT
	LDA	TRK
	MOV	M,A
	POP	H
	RET
	; RAPID ACCESS TABLE
RAT	DB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
TRK	EQU	RAT+16
;
; READ A SECTOR FROM MITS DISK.  SECTOR AND TRACK ARE ASSUMED SET
; PRIOR TO ENTRY.  IF SECTOR AND TRACK ARE WRONG FOR FILE
; GROUP INDICATES "FILE LINK ERROR"
;
; IF CHECKSUM IS IN ERROR, "CHECKSUM ERROR" WILL BE INDICATED
;
RDMITS	LDA	TRACK
	CPI	77	; SENSE OFF DISK
	JP	BADTRK
	ADI	0
	JM	BADTRK
	LDA	SECTOR
	ADI	0
	JM	BADSEC
	CPI	32
	JP	BADSEC
	LXI	H,BUFFER
	SHLD	ADDR
	MVI	A,BSIZE
	STA	NWDS
	CALL	DISKIN	; INPUT THE SECTOR
	LDA	FN	; GET CURRENT FILE NUMBER
	LXI	H,BUFFER+2 ; FILENUMBER ON DISK
	CMP	M	; SHOULD ALWAYS BE =
	JNZ	BADLNK	; FILE LINK ERROR
	INX	H
	MOV	A,M	; NUMBER DATA BYTES IN SECTOR
	STA	WRCOUNT ; SAVE NUMBER OF BYTES TO WRITE
	INX	H
	MOV	C,M	; GET CHECKSUM
	LHLD	BUFFER+5
	MOV	A,H
	ANI	1
	MOV	A,H
	JZ	RDMIT1
	ADI	16
	ANI	1FH
RDMIT1:	STA	SECTOR
	MOV	A,L
	STA	TRACK
	ADD	H
	MOV	B,A
	LDA	FN
	ADD	B
	MOV	B,A
	LDA	WRCOUNT
	ADD	B
	MVI	B,128
	LXI	H,BUFFER+7
CSCALC	ADD	M
	INX	H
	DCR	B
	JNZ	CSCALC
	XRA	C	; CHECKSUM
	JNZ	BADCKS
	PUSH	H
	LHLD	NREC
	MOV	A,H
	ORA	L
	JNZ	SKIPIT
	LDA	BUFFER+7
	STA	FRSTCH	; SAVE FIRST CHARACTER OF FILE
SKIPIT:	POP	H
	IF	DEBUGGING
	MOV	A,M	; LOOK FOR CHECK BYTE
	INR	A	; 255+1=0
	RZ
	LXI	H,CKBYTE ; CHECK BYTE ERROR
	JMP	CPMERR
CKBYTE	DB	CR,LF,'CHECK BYTE NOT FOUND IN MITS FILE'
	ENDIF
	IF	NOT DEBUGGING
	RET
	ENDIF
; 
; WRITE CP/M DISK FILE
;
WRCPM:	LDA	WRCOUNT	; GET WORD COUNT
	CPI	128	; CHECK FOR FULL BUFFER
	JZ	WRCPM1	; YES,WRITE IT
	MOV	B,A	; SAVE COUNT
	LXI	H,BUFFER+7 ; START OF DATA REGION
	CALL	ADDAHL	; ADD WORDS WRITTEN
	LDA	FRSTCH
	INR	A	; =255=>BINARY FILE
	JZ	ZSR	; ZERO OUT REMAINDER OF BUFFER
	MVI	A,1AH	; EOF MARK FOR ASCII FILES
ZSR	MOV	M,A	; STORE ZERO OR 1A IN BUFFER
	MVI	A,128
	SUB	B
	INX	H
	DCR	A
	JZ	WRCPM1	; JUMP IF ONLY ONE CHARACTER REMAINING (DONE)
	MOV	B,A
	XRA	A
ZRLOOP:	MOV	M,A	; ZEROIZE THE REST OF THE BUFFER
	INX	H
	DCR	B
	JNZ	ZRLOOP
WRCPM1:	CPM	WRITEF,FCB
	LHLD	NREC	; INCREMENT RECORD COUNT
	INX	H
	SHLD	NREC
	ORA	A
	RZ		; WRITE OPERATION COMPLETED OK
	CPI	2	; < MEANS ERROR EXTENDING > MEANS DIRECTRY ERR
	JZ	ENDDSK
	JC	EXTERR
	JMP	DIRFUL
;
; SET UP CPM FILE
;
SETUPO:	CPM	OPENF	; OPEN CP/M FILE
	CPI	255
	JZ	DIRFUL
	RET
;
; SET UP FCB FOR OUTPUT
;
; DATA IS IN TFCB AND TFCB+16
;
KATHY:	PUSH	B
	LDAX	D
	MOV	M,A
	INX	D
	INX	H
	DCX	B
	MOV	A,B
	ORA	C
	JNZ	KATHY+1
	POP	B
	RET
;
; CLOSE WRITE FILE
;
CLWRF:	CPM	CLOSEF,FCB ; CLOSE WRITE FILE
	RET
;
;
;
; ERROR CONDITIONS
;
BADLNK	LXI	H,FLERRM
	CALL	PRMSG
	JMP	EXIT	; WE ARE ROGH ON ERRORS - YOU MIGHT WANT TO GO ON
BADSEC	LXI	H,SECERR	; SECTOR NOT 0-31
	CALL	PRMSG
	JMP	EXIT
BADTRK	LXI	H,TRKERR	; TRACK NOT 0-76
	CALL	PRMSG
	JMP	EXIT
BADCKS	LXI	H,CKSUM
	CALL	PRMSG
	JMP	EXIT
BADFMT	LXI	H,FMTNG
	CALL	PRMSG
	JMP	EXIT
ENDDSK:	LXI	H,FULMSG	; DISK FULL
	JMP	CPMERR	; ERROR ENCOUNTERED IN CP/M SEGMENT OF PROGRAM
EXTERR:	LXI	H,EXTMSG
	JMP	CPMERR
DIRFUL	LXI	H,FULMSG
CPMERR	CALL	PRMSG
	JMP	EXIT
;
;
;; READ MITS FILE DIRECTORY
;
; DESTROYS EVERYTHING - USES EVERYTHING
; DISK IS LEFT WITH HEAD UNLOADED ON TRACK 70
;
; DOESN'T SORT DIRECTORY
;
;
MDRD	LDA	DISK	; SELECT DISK
	CALL	DISKSET
	XRA	A
	STA	SECTOR
	STA	FCOUNT	; ZER OFILE COUNTER
	STA	OP	; READ=>0
	MVI	A,DTRACK	; DIRECTORY TRACK
	STA	TRACK	; DIRECTORY TRACK
	LXI	D,OND	; SET ORIGIN OF THE NEW DIRECTORY
MDRD1	LXI	H,BUFFER ; SET ORIGIN OF INPUT BUFFER
	SHLD	ADDR	; SET ADDRESS OF INPUT BUFFER TO READ RTN
	MVI	A,BSIZE ; BUFFER SIZE
	STA	NWDS	; SET
	CALL	DISKIN	; READ A SECTOR
	LXI	H,BUFFER+DBIAS ; START OF MEANINGFUL DATA IN DIRECTORY
	MVI	B,NFPS
MDRD2	MOV	A,M
	ORA	A
	JZ	MDRD5	; DELETED OR EMPTY FILE
	CPI	ENDSLOT	; LAST ENTRY IN MITS DIRECTORY
	RZ
	PUSH	H
	MVI	A,11
	CALL	ADDAHL	; POINT TO FIRST UNUSED LOC IN THIS ENTRY
	CALL	FNCALC
	MOV	M,A	; PUT FILE NUMBER IN OLD DIRECTORY
	IF	DEBUGGING
	LDA	SECTOR
	INX	H
	MOV	M,A
	INX	H
	MVI	A,9
	SUB	B
	MOV	M,A
	ENDIF
	POP	H
	MVI	C,DSIZE ; SIZE OF ENTRY
MDRD3	MOV	A,M
	STAX	D
	INX	D
	INX	H
	DCR	C
	JNZ	MDRD3	; LOOP TILL DIRECTORY IS OBTAINED
	LDA	FCOUNT	; INCREMENT FILE COUNT
	INR	A
	STA	FCOUNT
MDRD4	DCR	B	; NUMBER OF DIRECTORY ENTRIES/SECTOR
	JNZ	MDRD2
	JMP	MDRD6	; READ NEXT DIRECTORY SECTOR
MDRD5	PUSH	D
	LXI	D,DSIZE	; PASS VACANT DIRECTORY ENTRY
	DAD	D
	POP	D
	JMP	MDRD4
MDRD6	LDA	SECTOR
	ADI	17	; LATENCY CALCULATION SCHTICK
	CPI	32
	JC	MDRD7
	SUI	32	; REDUCE MODULO 32
MDRD7	STA	SECTOR
	JMP	MDRD1
;SHELL-METZNER SORT
; THIS IS AN 8080 ADAPTATION OF THE SHELL SORT AS MODIFIED BY MARLENE METZNER
; 
; IT WILL SORT ANY FIXED LENGTH RECORD OF UP TO 255 BYTES INTO ASCENDING ORDER.
; BY MODIFICATION OF THE PROGRAM AT "COMP" IT CAN SORT INTO DESCENDING ORDER OR
; CAN BE MADE TO EXIT EACH TIME THAT AN EQUAL RECORD IS FOUND.
;
; 
;
; REGISTER USE:
;
; B=VAR I , C= VAR J , D= VAR K , E= VAR L , H= VAR M
; FOR MORE DETAILS SEE KNUTH, DONALD E.: THE ART OF COMPUTER PROGRAMMING,
;	VOL. 3: SORTING AND SEARCHING. ADDISON-WESLEY, 1973
;	THERE IS NO DIRECT REFERENCE TO METZNER'S MODIFICATION
SORT:	LDA	FCOUNT	; NUMBER OF RECORDS TO SORT
	MOV	H,A	; PUT IT IN H (FIRST TIME ONLY)
SORT1:	MOV	A,H	; START NEW PASS
	ORA	A	; CLEAR CARRY FLAG
	RAR		;M=M/2 (VARM)
	ORA	A	; CLEAR CARRY
	MOV	H,A	; M=INT(M/2)
	RZ		; SORT FINISHED
	LDA	FCOUNT	; GET N (NUMBER OF RECORDS)
	SUB	H	; MINUS M
	MOV	D,A	; SAVE IN D (K)
	MVI	C,1	; SET VAR J=1
SORT2:	MOV	B,C	; SET I=J INNER LOOP
SORT3:	MOV	A,B
	ADD	H	; L=I+M (VAR L)
	MOV	E,A
SORT4:	PUSH	H
	PUSH	D
	PUSH	B
	MOV	A,B	; GET I
	CALL	SETAD	; CALCULATE ADDRESS (DISPLACEMENTS INTO RECORD)
	SHLD	CRCEL	; SAVE I ADDRESS DISPLACED
	POP	B
	POP	D
	POP	H
SORT5:	PUSH	H
	PUSH	D
	PUSH	B
	MOV	A,E	; GET L
	CALL	SETAD	; CALCULATE ADDRESS (DISPLACEMENT INTO RECORD)
	SHLD	CRCL1	; SAVE L ADDRESS DISPLACED
	POP	B
	POP	D
	POP	H
SORT6:	PUSH	H
	PUSH	D
	PUSH	B
	MVI	B,8	; LENGTH OF SORT FIELD
	LHLD	CRCL1	; L RECORD ADDRESS
	XCHG		; MOVE L RECORD COMPARE ADDRESS TO DE
	LHLD	CRCEL	; I-RECORD
	XCHG		; I-RECORD ADDRESS TO DE, L RECORD TO HL
	CALL	COMP	; COMPARE STRINGS
	POP	B
	POP	D
	POP	H
TEST:	ORA	A
	JZ	SORT7
	JM	SORT7	; SORT7=>NO SWAP
	CALL	XFER	; SWAP SUBROUTINE
	MOV	A,B
	SUB	H
	MOV	B,A	; I=I-M
	JC	SORT7
	JNZ	SORT3	; SET NEW L
SORT7:	INR	C	; INCREMENT J COUNT
	MOV	A,D
	CMP	C	; J>K?
	JC	SORT1	; YES, START NEW (NEXT) PASS
	JMP	SORT2	; ELSE CONTINUE THIS PASS
; SUBROUTINES
;SETAD - SET ADDRESS
;
SETAD:	MVI	D,0
	MOV	E,A
	MVI	A,DSIZE	; LENGTH OF RECORD TO SORT
	MOV	H,D
	MOV	L,D
	MVI	B,8
SETAD1:	DAD	H
	RLC
	JNC	SETAD2
	DAD	D
SETAD2:	DCR	B
	JNZ	SETAD1
	XCHG
	LXI	H,OND-DSIZE
	DAD	D
	RET
;
; XFER - SWAPS STRINGS I AND J
;
XFER:	PUSH	H
	PUSH	D
	PUSH	B
	MVI	B,DSIZE
	LHLD	CRCEL
	XCHG
	LHLD	CRCL1
XFER1:	LDAX	D
	MOV	C,A
	MOV	A,M
	STAX	D
	MOV	M,C
	INX	D
	INX	H
	DCR	B
	JNZ	XFER1
	POP	B
	POP	D
	POP	H
	RET
COMP:	DCR	B
	RM
	LDAX	D
	SUB	M
	INX	D
	INX	H
	JZ	COMP
	RET
;
; HARD SECTOR DISK INPUT
;
HSDI	CALL	SECGET
	MVI	C,BSIZE
HSDI1	IN	8
	ORA	A
	JM	HSDI1
	IN	10
	MOV	M,A
	INX	H
	DCR	C
	JZ	HSDI2
	DCR	C
	NOP
	IN	10
	MOV	M,A
	INX	H
	JNZ	HSDI1
HSDI2	EI
	RET
;
;DISK INPUT DRIVER COUPLER
;
DISKIN	PUSH	H
	PUSH	D
	PUSH	B
	LDA	DISK
	OUT	8	; SELECT DISK
	LDA	TRACK
	MOV	D,A
	CALL	TRACKGET
	LDA	SECTOR
	MOV	E,A
	LHLD	ADDR
	CALL	HSDI
	CALL	HEADUNLOAD
	POP	B
	POP	D
	POP	H
	RET
DISKSET:
	PUSH	PSW
	OUT	8	; SELECT DISK
	NOP		; IN CASE HARDWARE DOESN'T WORK
	IN	8	; SENSE READY
	ANI	08H	; THIS BIT LOW WHEN DRIVE SELECTED (ADDED M DOUGLAS)
;;	ANI	020H	; SENSE INTERRUPTS ENABLED = DRIVE SELECTED
	JNZ	WAITUP	;
	POP	PSW
	CALL	TRACK0
	RET
WAITUP:	MVI	A,200
WAIT1:	DCR	A
	JNZ	WAIT1
	POP	A
	OUT	8
	NOP
	NOP
	JMP	DISKSET
	DS	50	; STACK REGION
STACK	EQU	$
CPMSTK	DW	0	; CP/M STACK POINTER
	END	0100H	; START OF TPA
