*THIS PROGRAM TRANSFERS A FILE FROM A DEC FORMAT DISK TO A
* CP/M FORMAT DISK
*
*
*CP/M DEFINITIONS FOR PRIMITIVES
*
RDCON	EQU	1	;GET CHAR FROM CONSOLE
WRTCON	EQU	2	;TYPE CHAR ON CONSOLE
RDRDR	EQU	3	;GETCHAR FROM PAPER TAPE READER
WRTPCH	EQU	4	;SEND CHAR TO PUNCH
WRTLST	EQU	5	;SEND CHAR TO LIST DEVICE
IOSTAT	EQU	7	;INTERROGATE I/O STATUS (NOT USED HERE)
ALTIO	EQU	8	;ALTER I/O STATUS (NOT USED HERE)
PCONBF	EQU	9	;PRINT CONSOLE BUFFER
RCONBF	EQU	10	;READ CONSOLE BUFFER
CONST	EQU	11	;CHECK CONSOLE STATUS (BIT0 SET IF READY)
LIFTHD	EQU	12	;LIFT DISK HEAD (NOT USED HERE)
RSTDSK	EQU	13	;DMA ADDR TO 80H,SELECT DISK A
SELDSK	EQU	14	;SELECT DISK
OPENF	EQU	15	;OPEN FILE
CLOSEF	EQU	16	;CLOSE FILE
SRCH1	EQU	17	;SEARCH FOR FIRST FILE OCCURRENCE
SCHNXT	EQU	18	;SEARCH FOR NEXT FILE OCCURRENCE
DELETF	EQU	19	;DELETE FILE
READF	EQU	20	;READ TO BUFFER
WRITEF	EQU	21	;WRITE TO BUFFER
MAKEF	EQU	22	;CREATE A FILE ENTRY
RENAMF	EQU	23	;RENAME A FILE
INTLOG	EQU	24	;INTERROGATE LOGIN VECTOR
INTDSK	EQU	25	;INTERROGATE DISK (RETURNS SELECTED DISK #)
SETDMA	EQU	26	;SET DMA ADDR
INTALL	EQU	27	;INTERROGATE ALLOCATION VECTOR
*
BDOS	EQU	0005H	;DOS ENTRY POINT
FCB	EQU	5CH	;DEFAULT FILE CONTROL BLOCK ADDRESS
BUFF	EQU	80H	;DEFAULT DMA ADDRESS
*
	ORG	0100H
*
*SET UP STACK
	LXI	H,0
	DAD	SP
	SHLD	OLDSP
	LXI	SP,STKTOP
	JMP	MAIN
*
*STACK AREA
OLDSP:	DS	2
STACK:	DS	64
STKTOP	EQU	$
*
*
*SUBROUTINES
PCHAR:	;PRINT CHAR IN REG A
	PUSH H!	PUSH D!	PUSH B	;ENVIRONMENT SAVED
	MVI	C,WRTCON
	MOV	E,A
	CALL	BDOS
	POP B!	POP D!	POP H	;ENVIRONMENT RESTORED
	RET
*
CRLF:	;PRINT A CARRIAGE RETURN & LINE FEED
	MVI	A,0DH
	CALL	PCHAR
	MVI	A,0AH
	CALL	PCHAR
	RET
*
PNIB:	;PRINT NIBBLE IN REG A
	ANI	0FH	;LOWER 4 BITS
	CPI	10
	JNC	P10
	;LESS THAN OR EQUAL TO 9
	ADI	'0'
	JMP	PRN
	;GREATER THAN OR EQUAL TO 10
P10:	ADI	'A'-10
PRN:	CALL	PCHAR
	RET
*
PHEX:	;PRINT HEX CHAR IN REG A
	PUSH	PSW
	RRC
	RRC
	RRC
	RRC
	CALL	PNIB	;PRINT NIBBLE
	POP	PSW
	CALL	PNIB
	RET
*
CHIN:	;GET A CHAR FROM CONSOLE 
	PUSH H!	PUSH D!	PUSH B
	MVI	C,RDCON
	CALL	BDOS
	POP B!	POP D!	POP H
	RET
*
MSG:	;PRINT A MESSAGE POINTED TO BY HL (END OF MESSAGE=0FFH)
	MOV	A,M
	CPI	0FFH
	RZ		;RETURN IF END OF MESSAGE
	CALL	PCHAR
	INX	H
	JMP	MSG
*
SETTRK:	;SET TRACK IN C
	LHLD	1
	LXI	D,27
	DAD	D
	PCHL
*
SETSEC:	LHLD	1
	LXI	D,30
	DAD	D
	PCHL
*
RDSEC:	LHLD	1
	LXI	D,36
	DAD	D
	PCHL
*
DISKRD:	;READ FROM DISK B-TRACK IN "TRACK",SECTOR IN "SECTOR"
	PUSH	B	;SAVE LOGICAL TRACK & SECTOR
	LDA	TRACK
	STA	BTRACK
	LDA	SECTOR
	STA	BSECT
	LDA	INTLEV	;GET INTERLEAVE FLAG
	ORA	A
	JZ	CONSEC	;0 > CONSECUTIVE SECTORS
*
*INTERLEAVE ALGORITHM FOR STANDARD DEC DISKS
*
	PUSH	D	;SAVE DMA ADDR
	MVI	H,0
	LDA	BTRACK
	MOV	L,A
	DCX	H	;HL=TRACK-1;NOW MULTIPLY BY 6
	MOV	A,L
	ADD	A
	MOV	L,A
	MOV	A,H
	RAL
	MOV	H,A
	SHLD	X2	;HL*2
INTLV3:	MOV	A,L
	ADD	A
	MOV	L,A
	MOV	A,H
	RAL
	MOV	H,A
	XCHG
	LHLD	X2
	DAD	D	;HL*6 IN HL
* 6*(TRACK-1) IN HL
*
INTLV0:	MOV	A,H
	ORA	A
	JNZ	INTLV5
	MOV	A,L
	CPI	26
	JM	INTLV4
INTLV5:	LXI	D,0-26
	DAD	D
	JMP	INTLV0
INTLV4:	LDA	BSECT
	DCR	A	;SHIFT SECTOR DOWN (0-25)
	PUSH	PSW
	ADD	A
	MOV	E,A	;SAVE S2
	POP	PSW
	CPI	13
	MOV	A,E	;GET S2 BACK TO ACC.
	JM	INTLV2
	INR	A
INTLV2:	ADD	L	;ADD BIAS
INTLV1:	SUI	26
	JP	INTLV1
	ADI	27
	STA	BSECT	;NEW PHYSICAL SECTOR TO BSECT
	POP	D	;RESTORE DMA ADDR
CONSEC:	LDA	BSECT
	MOV	C,A
	CALL	SETSEC
	LDA	BTRACK
	MOV	C,A
	CALL	SETTRK
	CALL	RDSEC
	POP	B
	RET
*
GETDIR:	;GET DIRECTORY SEGMENT 1 INTO THE DIRECTORY BUFFER
	; ASSUME FILE WILL BE IN SEGMENT 1
	MVI	C,SELDSK
	MVI	E,1
	CALL	BDOS	;SEL DISK B
	MVI	A,2
	STA	COUNT
	LXI	D,0
	MVI	A,01H
	STA	TRACK
	MVI	A,19H
	STA	SECTOR
	LXI	H,DRBUFF
	SHLD	BUFFPT	;INIT. BUFFPT
GTDIR1:	LHLD	BUFFPT
	DAD	D
	SHLD	BUFFPT
	XCHG
	MVI	C,SETDMA
	CALL	BDOS
	CALL	DISKRD	;READ SECTOR FROM DISK
	LXI	D,128
	MVI	A,1AH
	STA	SECTOR
	LDA	COUNT
	DCR	A
	STA	COUNT
	JNZ	GTDIR1	;READ IN FIRST 2 SECTORS
	MVI	A,6
	STA	COUNT
	MVI	A,02
	STA	TRACK
	DCR	A
	STA	SECTOR
GTDIR2:	LXI	D,128	;LENGTH OF A SECTOR
	LHLD	BUFFPT
	DAD	D
	SHLD	BUFFPT
	XCHG		;DMA ADDR > DE
	MVI	C,SETDMA
	CALL	BDOS
	CALL	DISKRD
	LDA	SECTOR
	INR	A
	STA	SECTOR
	LDA	COUNT
	DCR	A
	STA	COUNT
	JNZ	GTDIR2
	RET
*
X50:	;MULTIPLY HL BY 50Q & RETURN IN HL
	PUSH	B
	PUSH	D
	MVI	B,3
X50A:	MOV	A,L
	ADD	A
	MOV	L,A
	MOV	A,H
	RAL
	MOV	H,A
	DCR	B
	JNZ	X50A
	SHLD	X8
	MVI	B,2
X50B:	MOV	A,L
	ADD	A
	MOV	L,A
	MOV	A,H
	RAL
	MOV	H,A
	DCR	B
	JNZ	X50B
	XCHG
	LHLD	X8
	DAD	D
	POP	D
	POP	B
	RET
REGMOD:	;MODIFY DRIVE B REGISTERS AFTER SECTOR READ
	LDA	SECTOR
	CPI	26
	JZ	RM1
	INR	A
	STA	SECTOR
	RET
RM1:	MVI	A,1
	STA	SECTOR
	LDA	TRACK
	INR	A
	STA	TRACK
	RET
*
CMP16:	;COMPARES HL & DE & SETS USUAL FLAGS
	MOV	A,H
	CMP	D
	RNZ
	MOV	A,L
	CMP	E
	RET
*
NEGDE:	;NEGATE DE REGISTER (2'S COMP)
	PUSH	PSW
	MOV	A,D
	CMA
	MOV	D,A
	MOV	A,E
	CMA
	MOV	E,A
	INX	D
	POP	PSW
	RET
*
DCR16:	;DECREMENT HL BY 1 & SET FLAG C IF RESULT >= 0
	; NC IF RESULT < 0
	PUSH	D
	LXI	D,0FFFFH	;-1
	DAD	D
	POP	D
	RET
*
*
*
FINIS:	CALL	CRLF
	LHLD	OLDSP
	SPHL
	RET
*
SPACE:	;PRINTS A SPACE ON CRT
	PUSH	PSW
	MVI	A,20H
	CALL	PCHAR
	POP	PSW
	RET
*
R50ASC:	;CONVERTS A BASIC RADIX 50 CHAR TO ASCII
	CPI	0
	JNZ	RASC1
	MVI	A,20H
	RET
RASC1:	CPI	1BH
	JP	RASC2
	ADI	40H
	RET
RASC2:	CPI	1BH
	JNZ	RASC3
	MVI	A,24H
	RET
RASC3:	CPI	1CH
	JNZ	RASC4
	MVI	A,2EH
	RET
RASC4:	ADI	12H
	RET
*
RAD50:	;DECODES RADIX 50 WORD TO 3 ASCII CHARS & PRINTS THEM
	SHLD	R50
	LXI	D,0-1600
	MVI	C,0
RAD1:	DAD	D
	JNC	RAD2
	INR	C
	JMP	RAD1
RAD2:	MOV	A,C
	STA	CHAR1
	MOV	L,A
	MVI	H,0
	CALL	X50
	CALL	X50
	XCHG
	CALL	NEGDE
	LHLD	R50
	DAD	D
	SHLD	R50
	LXI	D,0-40
	MVI	C,0
RAD3:	DAD	D
	JNC	RAD4
	INR	C
	JMP	RAD3
RAD4:	MOV	A,C
	STA	CHAR2
	MOV	L,A
	MVI	H,0
	CALL	X50
	XCHG
	CALL	NEGDE
	LHLD	R50
	DAD	D
	MOV	A,L
	STA	CHAR3
	LDA	CHAR1
	CALL	R50ASC
	CALL	PCHAR
	LDA	CHAR2
	CALL	R50ASC
	CALL	PCHAR
	LDA	CHAR3
	CALL	R50ASC
	CALL	PCHAR
	RET
*
LDECWD:	;PRINTS DECIMAL EQUIV. OF HL
	PUSH B!	PUSH PSW!	PUSH H!	PUSH D!
	XRA	A
	STA	BLANK0
	MVI	B,30H
	LXI	D,10000
	CALL	LDEC0
	LXI	D,1000
	CALL	LDEC0
LDECB1:	LXI	D,100
	CALL	LDEC0
	MVI	E,10
	CALL	LDEC0
	MVI	E,1
	CALL	LDEC0
	POP D!	POP H!	POP PSW!	POP B
	RET
*
LDEC0:	MVI	C,30H
LDEC1:	MOV	A,L
	SUB	E
	MOV	L,A
	MOV	A,H
	SBB	D
	MOV	H,A
	JC	LDEC2
	INR	C
	JMP	LDEC1
LDEC2:	DAD	D
	MOV	A,C
	CPI	30H
	JNZ	LDEC3
	MOV	A,B
	JMP	CO
LDEC3:	MVI	B,30H
	JMP	CO
CO:	CPI	30H
	JNZ	CO1
	PUSH	PSW
	LDA	BLANK0
	RAR
	JNC	CO2
	POP	PSW
	JMP	PCHAR
CO2:	POP	PSW
	MVI	A,20H
	JMP	PCHAR
CO1:	PUSH	PSW
	MVI	A,1
	STA	BLANK0
	POP	PSW
	JMP	PCHAR
*
*
*
*
*
MAIN:	;MAIN BODY OF PROGRAM-LISTS DEC DIRECTORY
	CALL	CRLF
*
DECINT:	LXI	H,M0	;IS DEC DISK INTERLEAVED?
	CALL	MSG
	CALL	CHIN
	CPI	'Y'
	JNZ	NO1
	MVI	A,1
	STA	INTLEV	;SET INTERLEAVE FLAG
	JMP	REDY
NO1:	CPI	'N'
	JNZ	DECINT
	XRA	A
	STA	INTLEV
	CALL	CRLF
*
REDY:	MVI	C,SELDSK
	MVI	E,1
	CALL	BDOS	;SEL DISK B
	CALL	GETDIR	;GET DIRECTORY INTO DRBUFF
	LHLD	ENTRYS
	SHLD	ENTNUM
	LXI	H,ENTRYS
	SHLD	DRBFPT
*
DRLOOP:	LHLD	ENTNUM
	MVI	A,2
	CMP	H
	JZ	EMPTFL	;THIS ENTRY AN EMPTY FILE
	MVI	A,4
	CMP	H
	JZ	PERMFL	;THIS ENTRY IS A PERMANENT FILE
	MVI	A,8
	CMP	H
	JZ	FINIS	;END OF DIRECTORY
	LXI	H,M2	;ILLEGAL STATUS WORD
	CALL	MSG
	JMP	DECINT
*
EMPTFL:	CALL	CRLF
	LXI	H,M3	;< UNUSED >
	CALL	MSG
	LHLD	DRBFPT
	LXI	D,8
	DAD	D
	MOV	E,M
	INX	H
	MOV	D,M	;FILE LENGTH IN DE
	XCHG
	CALL	SPACE
	CALL	SPACE
	CALL	LDECWD
	XCHG
	LXI	D,5
	DAD	D	;IGNORE REST OF ENTRY INFO
	SHLD	DRBFPT
	MOV	A,M
	STA	ENTNUM
	INX	H
	MOV	A,M
	STA	ENTNUM+1
	JMP	DRLOOP	;DO NEXT ENTRY
*
PERMFL:	CALL	CRLF
	LHLD	DRBFPT
	INX	H
	INX	H
	MOV	A,M
	STA	FILELO	;GET FILNAM.EXT FOR LISTING
	INX	H
	MOV	A,M
	STA	FILEHI
	INX	H
	MOV	A,M
	STA	NAMELO
	INX	H
	MOV	A,M
	STA	NAMEHI
	INX	H
	MOV	A,M
	STA	EXTLO
	INX	H
	MOV	A,M
	STA	EXTHI	;FILNAM.EXT STORED
	PUSH	H
	LHLD	FILELO
	CALL	RAD50	;PRINT OUT FIL
	LHLD	NAMELO
	CALL	RAD50	;PRINT OUT NAM
	MVI	A,'.'
	CALL	PCHAR	;PRINT OUT '.'
	LHLD	EXTLO
	CALL	RAD50	;PRINT OUT EXT
	CALL	SPACE
	CALL	SPACE
	POP	H	;RESTORE BUFFER POINTER
	INX	H
	MOV	E,M
	INX	H
	MOV	D,M	;FILE LENGTH IN DE
	XCHG
	CALL	LDECWD	;PRINT LENGTH IN DECIMAL
	XCHG
	LXI	D,5
	DAD	D	;IGNORE REST OF ENTRY INFO.
	SHLD	DRBFPT
	MOV	A,M
	STA	ENTNUM
	INX	H
	MOV	A,M
	STA	ENTNUM+1	;SET UP FOR NEXT ENTRY
	JMP	DRLOOP	; & GO TO IT
*
*
*VARIABLES
ENTNUM:	DS	2	;ENTRY POINTER
BUFFPT:	DS	2	;XFER BUFFER POINTER
INTLEV:	DS	1	;INTERLEAVE FLAG
BLANK0:	DS	1	;SUPRESS LEADING 0 FLAG
CHAR1:	DS	1	;1ST RAD50 CHAR
CHAR2:	DS	1	;2ND "
CHAR3:	DS	1	;3RD "
R50:	DS	2	;TEMP RADIX 50 STORAGE
X2:	DS	2	;HL*2
BSECT:	DS	1
COUNT2:	DS	1	;SECOND UTILITY COUNTER
R50NUM:	DS	2	;RADIX 50 CONVERSION OF 3 ASCII CHARS
X8:	DS	2	;HL*8
FILELO:	DS	1	;PERMANENT FILE NAME & EXT. STORAGE
FILEHI:	DS	1
NAMELO	DS	1
NAMEHI	DS	1
EXTLO	DS	1
EXTHI	DS	1	;END OF PERM. NAME STORAGE
ENTRY:	DS	2	;ENTRY STATUS WORD POINTER
BLKCNT:	DS	2	;BLOCK COUNT (UPDATED EVERY ENTRY)
BLOCKS:	DS	2	;# OF BLOCKS TO FILE (VALID ONLY IF FOUND)
LENGTH:	DS	2	;LENGTH OF FILE FOUND (IN BLOCKS)
TRACK:	DS	1	;TRACK OF FOUND FILE
SECTOR:	DS	1	;SECTOR OF FOUND FILE
FILE:	DS	2	;FILE NAME
NAME:	DS	2	; & EXT. OF
EXT:	DS	2	;  REQUESTED FILE (DEC)
FLNMPT:	DS	2	;FILE NAME POINTER
FLBFPT:	DS	2	;PERM. FILE NAME POINTER
BTRACK:	DS	1	;PHYSICAL TRACK
COUNT:	DS	1	;UTILITY COUNTER LOCATION
DRBFPT:	DS	2	;DIRECTORY BUFFER POINTER
DRBUFF:			;DIRECTORY BUFFER
HDWD1:	DS	2	;SEGMENTS AVAILABLE
HDWD2:	DS	2	;NEXT SEGMENT
HDWD3:	DS	2	;HIGHEST OPEN SEGMENT
HDWD4:	DS	2	;EXTRA WORDS/ENTRY
HDWD5:	DS	2	;FILE STARTING BLOCK
ENTRYS:	DS	1014	;ENTRIES
ENDBUF:	DS	1
*
*
*MESSAGES
*
M0:	DB	0DH,0AH,'IS DEC DISK INTERLEAVED (Y/N)?',0FFH
M2:	DB	0DH,0AH,'ILLEGAL STATUS WORD ENCOUNTERED',0FFH
M3:	DB	'< UNUSED >',0FFH
*
*
PAD:	DS	4
*
PRGEND	EQU	$
*
*
*
	END
