*
* DIR: Enhanced directory display utility
*
* Copyright 1983-2005 Dave Dunfield
* All rights reserved.
*
TSIZ	EQU	24		SIZE OF DIR TABLE
DIRLOC	EQU	0		STARTING DIRECTORY LOCATION
	ORG	OSRAM
DIR	CMPA	#'?'		QUERY OPERAND?
	BNE	QUAL		NO, LOOK FOR QUALIFIERS
	SSR	25
	FCC	'Use: DIR[/DISK/LOAD/SIZE/TOTAL/NOHEADER/PROT]'
	FCCZ	' [<directory>]'
	RTS
* PARSE	FOR COMMAND QUALIFIERS
QUAL	LDA	,Y		GET CHAR FROM COMMAND LINE
	CMPA	#'/'		IS IT A QUALIFIER?
	BNE	MAIN		NO, CONTINUE WITH MAIN PROGRAM
	LEAX	QTABLE,PCR	POINT TO QUALIFIER TABLE
	SSR	18		LOOK IT UP
	CMPB	#QMAX		IS IT IN RANGE
	BHS	QERR		IF SO, IT'S INVALID
	LEAX	QFLAGS,PCR	POINT TO QUALIFIER FLAGS
	CLR	B,X		SET THE FLAG
	BRA	QUAL		LOOK FOR ANOTHER QUALIFIER
QERR	SSR	24		DISPLAY MESSAGE
	FCCZ	/Invalid qualifier: '/
	LDA	,Y+		GET CHARACTER
DSQU1	SSR	33		DISPLAY
	LDA	,Y+		GET NEXT CHAR
	BEQ	GOABO		NULL IS DELIMITER
	CMPA	#'/'		START OF ANOTHER QUALIFIER?
	BEQ	GOABO		IF SO, QUIT
	CMPA	#' '		SPACE?
	BEQ	GOABO		IF SO, QUIT
	CMPA	#$0D		END OF LINE?
	BNE	DSQU1		NO, KEEP DUMPING
GOABO	SSR	25		DISPLAY MESSAGE
	FCB	$27,0		CHARACTERS TO DISPLAY
	LDA	#1		INVALID OPERAND RETURN CODE
	RTS
* FIRST	GET PARAMETERS,	AND ADJUST FOR DEFAULTS
MAIN	LDA	SIZE		SEE IF '/SIZE' SPECIFIED
	ANDA	RUNADR		OR '/RUNADR'
	ANDA	DSKADR		OR '/DISKADR'
	ANDA	ATTR		OR '/ATTRIBUTES'
	STA	INFO		IF SO, SET INFORMATION MODE (SINGLE COLUMN)
	SSR	4		LOOK FOR PARAMETER
	BEQ	DEFPRM		NONE, USE DEFAULT
	PSHS	Y		SAVE OPERAND POINTER
ADVP	SSR	5		GET CHAR FROM OP
	BEQ	ADVP2		END OF LINE ?
	CMPA	#']'		END OF DIRECTORY
	BEQ	ADVP1		IF SO, MABY HAFTA INSERT *.*
	CMPA	#':'		END OF OPRAND?
	BNE	ADVP		IF SO, OK
	LDA	,Y		GET NEXT
	CMPA	#'['		DIRECTORY?
	BEQ	ADVP		ALLOW IT
* END OF DIRECTORY SPECIFICATION, SEE IF FILE SPEC SUPPLIED
ADVP1	LDA	,Y		GETR NEXT CHAR
	BEQ	ADVP3		IF END, INSERT DEFAULT
	CMPA	#$0D		END OF LINE?
	BEQ	ADVP3		YES, INSERT DEFAULT
	CMPA	#' '		END OF OPERAND?
	BNE	ADVP2		NO, FILE SPEC MUST BE SUPPLIED
ADVP3	LDX	#DEFNAM		POINT TO DEFAULT FILENAME
ADVP4	LDA	,X+		GET CHAR FROM DEFAULT
	STA	,Y+		APPEND TO OPERAND
	BNE	ADVP4		CONTINUE TILL ALL MOVED
* OPERAND IS OK, GET NAME AND BEGIN SCANNING DIRECTORY
ADVP2	PULS	Y		RESTORE POINTER TO OPERAND
	BRA	SUPPRM		PROCESS PARAMETER
* NO OPERAND WAS SUPPLIED, POINT TO DEFAULT (ALL FILES)
DEFPRM	LDY	#DEFNAM		POINT TO DEFAULT OPERAND
SUPPRM	SSR	9		INFORM DOS OF FILENAME
	LBNE	ABORT		OPERAND WAS INVALID, QUIT
	LDA	-1,X		GET DRIVE
	STA	DRIVE		SAVE IT
	SSR	76		SELECT DRIVE
* INITIALIZE RAM TABLE
	LDA	#$FF		INDICATE END OF TABLE
	STA	RAM+512		PLACE AT BEGINNING OF TABLE
* OPEN DIRECTORY, AND START READING
	LDD	#DIRLOC		DIRECTORY STARTS HERE
RDSEC	STD	SECTOR		SAVE CURRENT DIRECTORY SECTOR
	LDX	#RAM		POINT TO WORK AREA
	SSR	92		READ SECTOR
	LBNE	ABORT		DISK ERROR, QUIT
* TEST THIS DIRECTORY ENTRY FOR	MATCH
RDENT	LDA	,X		GET FIRST CHAR
	BEQ	NXTENT		UNUSED ENTRY, SKIP
	SSR	19		DUZ IT MATCH STORED FILENAME?
	BNE	NXTENT		NO, SKIP
* NAME MATCHES,	INSERT INTO TABLE
	LDY	#RAM+512	POINT TO TABLE
INSNAM	PSHS	X,Y		SAVE TABLE AND DIRECTORY POINTERS
	LDA	,Y		TEST FOR END OF TABLE
	BMI	INSERT		YES, INSERT HERE
	LDB	#19		COMPARE 19 CHARS (FULL NAME)
CMPNAM	LDA	,X+		GET CHAR FROM DIRECTORY
	CMPA	,Y+		COMPARE WITH TABLE ENTRY
	BLO	INSERT		LESS, INSERT NAME HERE
	BNE	CMPN1		MUST BE HIGHER, SKIP THIS ENT
	DECB			REDUCE COUNT
	BNE	CMPNAM		KEEP GOING
* ENTRY	WAS NOT	LESS THAN THIS ONE, TRY	NEXT
CMPN1	PULS	X,Y		RESTORE TABLE AND DIRECTORY POINTERS
	LEAY	TSIZ,Y		ADVANCE TO NEXT TABLE ENTRY
	BRA	INSNAM		PERFORM TEST AGAIN
* INSERT NAME HERE
INSERT	LDX	2,S		GET TABLE POINTER
INS1	LDA	,X+		TEST FOR END OF TABLE
	BMI	INS15		YES, WE FOUND END
	LEAX	TSIZ-1,X	ADVANCE REMAINDER OF ENTRY
	BRA	INS1		AND KEEP LOOKING FOR IT
INS15	LEAY	TSIZ,X		ADVANCE EXTRA SPACE FOR NEW ENTRY
INS2	LDA	,-X		GET CHAR FROM OLD
	STA	,-Y		SAVE IN NEW POSITION
	CMPX	2,S		ARE WE AT INSERT POSITION YET?
	BHI	INS2		NO, KEEP MOVEING
	PULS	X,Y		RESTORE TABLE AND DIRECTORY POINTERS
	PSHS	X		SAVE DIRECTORY POSITION
	LDB	#TSIZ		MOVE # CHARS (DIR ENT)
INS3	LDA	,X+		GET CHAR FROM DIRECTORY
	STA	,Y+		SAVE IN TABLE
	DECB			REDUCE COUNT
	BNE	INS3		MOCE ENTIRE NAME
	PULS	X		RESTORE DIRECTORY POSITION
* ADVANCE TO NEXT DIRECTORY ENTRY, AND TEST IT
NXTENT	LEAX	32,X		ADVANCE TO NEXT ENTRY
	CMPX	#RAM+512	ARE WE OVER THE SECTOR LIMIT
	BLO	RDENT		NO, TEST THIS ONE
	LDD	SECTOR		GET SECTOR NUMBER BACK
	SSR	77		FIND NEXT LINK
	BNE	RDSEC		IF MORE, KEEP LOOKING
* WE HAVE ALL MATCHING NAMES IN	TABLE, NOW DISPLAY IT
	LDY	#RAM+512	POINT TO TABLE
DISP0	CLR	XPOS		STARTS AT COLUMN NUMBER 0
DISP1	LDA	,Y		GET CHAR FROM TABLE
	LBMI	DISPEND		END OF TABLE, QUIT
	PSHS	Y		SAVE POINTER
	LDA	NOHEAD		DO WE HAVE HEADERS?
	BEQ	DIROK		NO, DISPLAY NORMALLY
	LDB	#8		COMPARE 8 CHARS
	LDX	#SAVDIR		POINT TO SAVED DIRECTORY NAME
CMPDIR	LDA	,X+		GET CHAR FROM SAVED
	CMPA	,Y+		SAME AS OURS?
	BNE	DISPDIR		NO, NEW DIRECTORY
	DECB			REDUCE COUNT
	BNE	CMPDIR		KEEP TESTING TILL DUN
	BRA	DIROK		NO HEADER TO DISPLAY, (SAME DIR)
* DISPLAY DIRECTORY HEADER
DISPDIR	LDD	NDIR		GET DIRECTORY COUNT
	BEQ	DISPD9		FIRST ONE, DON'T DISPLAY TOTALS
	LBSR	FSUM		DISPAY FILE TOTAL SUMMARY
DISPD9	LDD	NDIR		GET NUMBER AGAIN
	ADDD	#1		INCREMENT
	STD	NDIR		RESAVE
	CLRA			GET A ZERO
	CLRB			16 BYTE ZERO
	STD	FTOTAL		CLEAR INTERMEDIATE FILE TOTALS
	LBSR	LFCR		NEW LINE
	SSR	24		OUTPUT MESSAGE
	FCCZ	'Directory '
	LDA	>DRIVE		GET DRIVE
	ADDA	#'A'
	SSR	33		OUTPUT
	SSR	24		OUTPUT MESSAGE
	FCCZ	':['		INFO
	LDB	#8		DISPAY MAX 8 CHARS
	LDY	,S		GET POINTER TO ENTRY BACK
	LDX	#SAVDIR		POINT TO SAVED DIRECTORY
DISPD1	LDA	,Y+		GET CHAR FROM ENTRY
	STA	,X+		SAVE IN NEW SAVED DIRECTORY NAME
	BEQ	DISPD2		DON'T DISPLAY ZERO PADS
	SSR	33		DISPLAY ON TERMINAL
DISPD2	DECB			REDUCE COUNT
	BNE	DISPD1		KEEP DISPLAYING
	SSR	25		DISPLAY MESSAGE
	FCB	']',$0A,0
	CLR	XPOS		START IN COLUMN ZERO
DIROK	PULS	Y		RESTORE FILE POINTER
	LDD	FTOTAL		GET FILE TOTAL
	ADDD	#1		INCREMENT
	STD	FTOTAL		RESAVE
	LDD	GTOTAL		GET GRAND TOTAL
	ADDD	#1		INCREMENT
	STD	GTOTAL		RESAVE
	LDA	TOTAL		ARE WE ASKING FOR '/TOTAL'S ONLY?
	BEQ	TOTON		IF SO, DON'T DISPLAY NAME
	LDX	#23		DEFAULT SPACEING FOR '/NOHEAD'
	LDA	NOHEAD		IS '/NOHEAD' IN EFFECT?
	BEQ	NOH1		IF SO, DISPLAY SEPERATE DIRECTORY HEADER
	LEAY	8,Y		ADVANCE PAST DIRECTORY
	LEAX	-8,X		REDUCE FIELD WIDTH FOR FILENAME
	LDA	INFO		ARE WE DISPLAYING INFORMATION WITH FILES?
	BEQ	NOH15		IF SO, DON'T DISPLAY NAME IN COLUMNS
* DISPLAY FILENAMES IN SHORT FORM (COLUMNS)
	LDX	#14		FIELD WIDTH FOR COLUMN DISPLAY
	LDB	#8		SIZE OF FILENAME
	LBSR	DISPB		DISPLAY FILENAME
	LDA	#'.'		SEPERATOR FOR TYPE
	SSR	33		DISPLAY
	LDB	#3		SIZE OF FILETYPE
	LBSR	DISPB		DISPLAY FILETYPE
	LEAY	TSIZ-19,Y	SKIP EXTRA INFO
* FILL WITH SPACES TO NEXT COLUMN
	INC	XPOS		ADVANCE COLUMN NUMBER
	LDA	XPOS		GET COLUMN NUMBER
	CMPA	#5		ARE WE OVER?
	BHS	DISPN		IF SO, GO TO A NEW LINE
SPAC1	LDA	#' '		GET SPACE
	SSR	33		DISPLAY
	LEAX	-1,X		REDUCE FIELD WIDTH
	BNE	SPAC1		FILL FIELD
	LBRA	DISP1		DISPLAY NEXT ENTRY
DISPN	LBSR	LFCR1		PERFORM LINE-FEED, CARRIAGE RETURN
	LBRA	DISP0		DISPLAY NEXT ENTRY, AT COLUMN ZERO
* ONLY TOTALS ARE BEING	DISPLAYED, DON'T GIVE HIM THE NAMES
TOTON	LEAY	TSIZ,Y		ADVANCE TO NEXT ENTRY
	LBRA	DISP1		CHECK NEXT ENTRY
* NOHEAD IS IN EFFECT, DISPLAY DIRECTORY PREFIX
NOH1	LDA	>DRIVE
	ADDA	#'A'
	SSR	33		OUTPUT DRIVE
	SSR	24
	FCCZ	':['
	LDB	#8		SIZE OF DIRECTORY NAME
	LBSR	DISPB		DISPLAY DIRECTORY NAME
	LDA	#']'		DIRECTORY END CHARACTER
	SSR	33
* DISPLAY FILENAME, AND	ANY INFO REQUESTED
NOH15	LDB	#8		SIZE OF FILENAME
	LBSR	DISPB		DISPLAY FILENAME
	LDA	#'.'		FILENAME SEPERATOR
	SSR	33		DISPLAY
	LDB	#3		SIZE OF FILETYPE
	LBSR	DISPB		DISPLAY FILETYPE
	LDA	INFO		TEST FOR INFO TO DISPLAY
	BNE	NOSIZ		NO, DISPLAY NEXT FILENAME
* PAD WITH SPACES
NOH2	LDA	#' '		GET SPACE
	SSR	33		DISPLAY
	LEAX	-1,X		REDUCE COUNT
	BNE	NOH2		FILL FIELD
* TEST FOR '/RUNADR' DISPLAY
	LDA	RUNADR		DO WE WISH TO DISPLAY RUNADDRESS
	BNE	NORUN		NO, DON'T DISPLAY
	LDD	2,Y		GET RUN ADDRESS
	SSR	27		DISPLAY IN HEX
	SSR	24		DISPLAY MESSAGE
	FCCZ	'     '		SPACES
* TEST FOR '/DSKADR' DISPLAY
NORUN	LDA	DSKADR		DO WE WANT DISK ADDRESS DISPLAYED
	BNE	NODSK		NO, DON'T DISPLAY
	LDD	,Y		GET DISK ADDRESS
	SSR	27		DISPLAY
	SSR	24		DISPLAY MESSAGE
	FCCZ	'     '		SPACES
* TEST FOR '/ATTRIBUTES' DISPLAY
NODSK	LDA	ATTR		ATTRIBUTES
	BNE	NOATTR		NO
	LDB	4,Y		GET ATTRIBUTES
	LDX	#ATRTAB		PT TO TABLE
	LDA	#9		FLAGS
	STA	XPOS		SAVE IT
NODS1	TSTB			ANY LEFT
	BEQ	NODS2		NO
	LDA	,X+		GET CHAR
	LSLB			SHIFT IT
	BCC	NODS1		NONE
	DEC	XPOS		INDICATE CHAR OUT
	SSR	33		OUTPUT
	BRA	NODS1		CONTINUE
NODS2	SSR	21		DISPLAY SPACE
	DEC	XPOS		REDUCE
	BNE	NODS2		MORE, KEEP GOING
* TEST FOR '/SIZE' DISPLAY
NOATTR	LDA	SIZE		DO WE WISH TO DISPLAY SIZE?
	BNE	NOSIZ		NO, DON'T DISPLAY
	PSHS	Y		SAVE POINTER TO ENTRY
	LDD	,Y		GET DISK ADDRESS
	LDY	#0		START WITH SIZE OF ZERO
* TRAVERSE LINK	CHAIN, DETERMINING SIZE	OF FILE
SIZ1	LEAY	1,Y		INCREMENT SIZE BY ONE SECTOR
	SSR	77		LOOK FOR NEXT CHAIN
	BNE	SIZ1		KEEP TRAVERSING
	TFR	Y,D		COPY SIZE TO D FOR DISPLAY
	SSR	26		DISPLAY IN DECIMAL
	PULS	Y		RESTORE POINTER TO ENTRY
NOSIZ	LEAY	TSIZ-19,Y	SKIP INFO
	LBRA	DISPN		DISPLAY NEXT ENTRY
* END OF RAM TABLE, DISPLAY CLOSING SUMMARIES
DISPEND	LBSR	FSUM		DISPLAY FILE SUMMARY FOR LAST DIRECTORY
	LDD	NDIR		FIND OUT HOW MANY DIRECTORIES WE HIT
	CMPD	#1		WAS THERE MORE THAN ONE?
	BLS	DISPEX		NO, SKIP GRAND TOTAL
	SSR	24		DISPLAY MESSAGE
	FCB	$0A,$0D		NEW LINE
	FCCZ	'Grand total of '
	LDD	NDIR		GET NUMBER OF DIRECTORIES
	SSR	26		DISPLAY IN DECIMAL
	SSR	24		DISPLAY MESSAGE
	FCCZ	' directories, '
	LDD	GTOTAL		GET GRAND TOTAL OF FILES
	SSR	26		DISPLAY IN DECIMAL
	SSR	25		DISPLAY MESSAGE
	FCCZ	' files.'
DISPEX	CLRA			ZERO RETURN CODE
ABORT	SSR	0		RETURN TO DOS
* *** SUBROUTINES ***
*
* DISPLAY ENTRY	FOR MAX	CHARS IN B, DECREMENT FIELD POSITION (IN X)
DISPB	LDA	,Y+		GET CHAR FROM ENTRY
	BEQ	DISPB1		END OF ENTRY, QUIT
	SSR	33		DISPLAY
	LEAX	-1,X		REDUCE FIELD POSITION
DISPB1	DECB			REDUCE COUNT OF ENTRY SIZE
	BNE	DISPB		KEEP TRYING
	RTS
* SUMMARISE FILES
FSUM	TST	TOTAL		ARE WE DISPLAYING TOTAL
	BEQ	FSUM1		IS SO, SKIP EXTRA LFCR
	BSR	LFCR		NEW LINE
FSUM1	SSR	24		DISPLAY MESSAGE
	FCCZ	'Total of '
	LDD	FTOTAL		GET TOTAL
	SSR	26		OUTPUT NUMBER
	SSR	25		DISPLAY MESSAGE
	FCCZ	' files.'
	RTS
* LFCR ROUTINE
LFCR	BSR	LFCR1		DISPLAY NEW LINE
	LDA	XPOS		TEST FOR AT COLUMN ZERO
	BEQ	LFCRE		IF SO, ALL DONE
LFCR1	SSR	22		LFCR
LFCRE	RTS
* PREDEFINED STRINGS
DEFNAM	FCCZ	'*.*'		DEFAULT FILENAME OPERAND
ATRTAB	FCC	'RWED????'	ATTRIBUTE TABLE
* TABLE	OF VALID QUALIFIERS
QTABLE	FCB	$82
	FCC	'/TOTAL'	DISPLAY TOTALS ONLY
	FCB	$82
	FCC	'/NOHEADER'	NO DIRECTORY HEADER
	FCB	$82
	FCC	'/SIZE'		DISPLAY FILE SIZE
	FCB	$82
	FCC	'/LOAD'		DISPLAY FILE RUN ADDRESS
	FCB	$82
	FCC	'/DISK'		DISPLAY FILE DISK ADDRESS
	FCB	$82
	FCC	'/PROT'
	FCB	$80		END OF TABLE
QMAX	EQU	6		# QUALIFIERS
* QUALIFIER FLAGS
QFLAGS	EQU	*
TOTAL	FCB	$FF		TOTAL ONLY FLAG
NOHEAD	FCB	$FF		NO DIR. HEADER FLAG
SIZE	FCB	$FF		DISPLAY SIZE FLAG
RUNADR	FCB	$FF		DISPLAY RUN ADDRESS FLAG
DSKADR	FCB	$FF		DISPLAY DISK ADDRESS FLAG
ATTR	FCB	$FF		DISPLAY FILE ATTRIBUTES
INFO	FCB	$FF		0 IF ANY INFO PRINTING
SAVDIR	FCB	0,0,0,0,0,0,0,0
XPOS	FCB	0		OUTPUT COLUMN INDICATOR
NDIR	FDB	0		NUMBER OF DIRECTORIES FOUND
FTOTAL	FDB	0		INTERMEDIATE FILE TOTALS
GTOTAL	FDB	0		GRAND FILE COUNT TOTAL
SECTOR	RMB	2		SAVED CURRENT DIRECTORY SECTOR
DRIVE	RMB	1		DOS DRIVE
RAM	EQU	*		FREE RAM
