; PROGRAM TO WRITE A DIRECTORY LISTING TO AN ASCII FILE
; IN A FORM SUITABLE FOR USE WITH A SUBMIT FILE (AFTER
; SUITABLE PROCESSING WITH ED).
;
; THE COMMAND FORMAT IS:
;
;	A>DIRLST  NAME.EXT
;
;	  WHERE  NAME.EXT IS THE FILE NAME TO SAVE THE DIRECTORY IN.
;
;
;
;
;	BY BRUCE KENDALL  1/1980
;	BUG FIXED 2/9/80
;		 10/4/80
;		  1/11/81	; ADDED MORE '???' FOR WILD CARD
;				;  TO FIX CP/M 2.2 BUG
;
;	4/10/81			;changed formatting to eliminate
;				;extraneous characters at start of
;				;each file name (Ray Glueck)
;
; ---CP/M EQUATES ---
;
FCB	EQU	5CH
BDOS	EQU	05
FPRT	EQU	9
FCLOSE	EQU	16
DELETE	EQU	19
WRITE	EQU	21
MAKE	EQU	22
SDMA	EQU	26
SRCH	EQU	17
SRCHX	EQU	18
;
DMA	EQU	80H	; DMA LOCATION
;
	ORG	100H	;CP/M TPA
;
	LXI	H,0
	DAD	SP
	SHLD	OLDSTK	;SAVE OLD STACK POINTER
;
;
START:	LXI	SP,STACK
;
	LXI	D,MSG1	;POINT TO NAME ERROR MESSAGE
	LDA	FCB+1	;GET FIRST CHAR. OF NAME
	CPI	20H
	JZ	ERROR+3
	JC	ERROR+3	;IF BAD NAME
;
	LXI	D,MSG	;POINT TO STARTUP MESSAGE
	CALL	PTMSG	;PRINT OUT MESSAGE
;
	LXI	D,DMA	;GET STD DMA ADDRESS
	MVI	C,SDMA
	CALL	BDOS
;
	LXI	D,FCB	;POINT TO FCB
	MVI	C,DELETE	;FUNCTION TO DELETE A FILE
	CALL	BDOS
;
	XRA	A
	STA	FCB+12	; CLEAR EXTENT BYTE
	STA	FCB+32	; CLEAR NEXT RECORD BYTE
	LXI	D,FCB
	MVI	C,MAKE
	CALL	BDOS	;CREATE FILE
	CPI	0FFH
	JZ	ERROR
;
	LXI	H,BUFF	;POINT TO START OF MEMORY BUFFER
	SHLD	BUFPTR	;SAVE POINTER
;
	MVI	C,SRCH	;SETUP FOR DIRECTORY SEARCH
LST:	LXI	D,FCB1	;POINT TO WILD CARD FCB
	CALL	BDOS
	CPI	0FFH	;TEST FOR END OF DIRECTORY
	JZ	FLZ	;YES, DUMP BUFFER TO DISC FILE
	ANI	03H	;NO, SO MASK BYTE ADDRESS
	RLC
	RLC		;MULTIPLY BY 32 (32 BYTES/FCB)
	RLC
	RLC
	RLC
	ADI	DMA AND 00FFH	;ADD IN START OF DMA BUFFER
	LXI	D,DMA	; GET INTO (D,E)
	MOV	E,A
	INX	D	;POINT TO START OF FILE NAME
	LXI	H,11	;GET OFFSET TO EXTENT BYTE
	DAD	D	;POINT TO EXTENT
	MOV	A,M	;GET IT
	ORA	A	;IS IT ZERO?
	JNZ	LST1	;IF NOT FIRST EXTENT
;	MVI	A,':'	;GET DELIMITER
;	CALL	STORE
;	CALL	STORE
;	CALL	STORE	;PUT DELIMITERS AHEAD OF FILE NAME
;
	MVI	B,8	;LENGTH OF FILE NAME
	CALL	STOREN	;SAVE NAME
;
	MVI	A,'.'	;DELIMITER BETWEEN NAME AND EXTENT
	CALL	STORE
;
	MVI	B,3	;LENGTH OF EXTENT
	CALL	STOREN	;SAVE EXTENT
;
	MVI	A,0DH	;PUT IN CRLF
	CALL	STORE
	MVI	A,0AH
	CALL	STORE
;
LST1:	MVI	C,SRCHX ;SET TO SEARCH FOR NEXT NAME
	JMP	LST
;
STOREN: LDAX	D	;GET CHAR. OF FILE NAME
 	CPI	' '	;IS IT A SPACE?
 	CNZ	STORE	;NO, SO SAVE IT
	INX	D	;INCREMENT POINTER
	DCR	B	;COUNT DOWN CHARACTERS
	JNZ	STOREN	;LOOP UNTIL DONE
	RET
;
FLZ:	MVI	A,'Z'-40H	;GET A CONTROL-Z
CZ1:	CALL	STORE	;PUT IT IN BUFFER
	JNZ	CZ1	;FILL OUT SECTOR BUFFER WITH CTL-Z
;
	LXI	H,BUFF	;POINT TO START OF BUFFER
	SHLD	WPTR	;SAVE POINTER
WMORE:	LHLD	WPTR	;GET POINTER
	XCHG		;INTO (D,E)
	MVI	C,SDMA	;SET TO MOVE DMA BUFFER
	CALL	BDOS	;DO IT
	LXI	D,FCB	;POINT TO FCB
	MVI	C,WRITE	;SET TO WRITE DMA BUFFER TO DISC
	CALL	BDOS	;DO IT
	ORA	A
	JNZ	ERROR	;IF ERROR, EXIT WITH MESSAGE
;
	LHLD	WPTR	;GET BUFFER POINTER
	LXI	D,80H	;SIZE OF DMA BUFFER
	DAD	D	;COMPUTE NEW POINTER
	SHLD	WPTR	;SAVE IT
	LDA	BUFPTR+1	;GET UPPER ADDRESS OF BUFFER
	CMP	H	;COMPARE IT WITH CURRENT WRITE POINTER
	JZ	CLOSE	;CLOSE FILE IF THEY ARE THE SAME
	JNC	WMORE	;LOOP TO SAVE ALL OF BUFFER TO DISC
;
CLOSE:	LXI	D,80H	;GET STD DMA ADDRESS
	MVI	C,SDMA
	CALL	BDOS	;RESET DMA ADDRESS
	LXI	D,FCB
	MVI	C,FCLOSE
	CALL	BDOS	;CLOSE FILE
;
EXIT:	LHLD	OLDSTK	;GET OLD STACK POINTER BACK
	SPHL
	JMP	0	;RETURN TO CP/M
;
STORE:	LHLD	BUFPTR	;GET BUFFER POINTER
	MOV	M,A	;SAVE BYTE IN MEMORY BUFFER
	MOV	C,A	;AND IN (C)
	INX	H	;POINT TO NEXT LOCATION
	MOV	A,L	;GET LOWER ADDRESS BYTE
	ORA	A	;IS IT ZERO?
	MOV	A,C	;RESTORE BYTE
	SHLD	BUFPTR	;SAVE NEW BUFFER POINTER
	RET
;
PTMSG:	MVI	C,FPRT	;GET CP/M MESSAGE PRINT CODE
	JMP	BDOS	;EXECUTE PRINT FUNCTION
;
ERROR:	LXI	D,MSGE	;POINT TO ERROR MESSAGE
	CALL	PTMSG
	JMP	EXIT	;RETURN TO CP/M
;
MSG:	DB	0DH,0AH,' --- DIRECTORY SAVER ver 1.1 ---',0DH,0AH,'$'
MSG1:	DB 0DH,0AH,07,' -- INVALID FILE NAME --',0DH,0AH,0DH,0AH
	DB ' THE PROPER CALLING SEQUENCE IS:',0DH,0AH,0DH,0AH
	DB '        A>DIRLST  NAME.EXT',0DH,0AH,0DH,0AH
	DB '   WHERE  NAME.EXT IS THE FILE NAME TO SAVE THE DIRECTORY IN.'
	DB 0DH,0AH,'$'
MSGE:	DB	0DH,0AH,07,' -- R/W ERROR --',0DH,0AH,'$'
;
FCB1:	DB 0,'???????????????????'	;FCB FOR DIRECTORY SEARCH
;
OLDSTK:	DS	2	;BUFFER FOR OLD STACK POINTER
BUFPTR:	DS	2	;BUFFER POINTER FOR FILLING IT
WPTR:	DS	2	;BUFFER POINTER FOR SAVING IT ON DISC
	DS	80H	;ROOM FOR STACK
STACK:	DS	1
;
	ORG	(($+101H) AND 0FF00H)	;START BUFFER ON PAGE BOUNDARY
BUFF	DB	0
;
	END

