;
;		    MLIST.ASM - V3.4
;		by Keith Petersen, W8SDZ
;		    (revised 9/21/80)
;
; This program lists any size ASCII file by name, reading
; up to 16k of the file into memory at one time, in order
; to minimize disk activity during printout.
;
; Allows listing of multiple files by using
; normal CP/M ambiguous file names (i.e.,
; MLIST *.ASM).  Before each file is printed,
; the FILENAME.TYPE is displayed.
;
; Use CTL-S to pause, CTL-C to abort.
; Other characters are ignored.
;
; This program allows CP/M 1.4 users to have protected
; ASCII files on a remote system, provided that the CCP
; 'REN' (rename) and 'TYPE' functions have been changed
; to some other characters and MLIST.COM has been renamed
; to TYPE.COM.  To protect a file, rename it so the last
; character of the file type is #.  Example: MYFILE.AS#
;
; CP/M 2.x users may use 'TAG.COM' to set the f1' attribute
; of a file, which will prevent this program from listing it.
;
;
;05/27/80 Revised to abort on attempting to
;	  list a CP/M .COM file.  TVC
;
;09/09/80 Revised check for '.COM' and '.OBJ' files so
;	  during attempt to list multiple files these
;	  would not abort the routine. Modified to
;	  issue an error message and continue with the
;	  next valid file. Added check for '#' character
;	  as the last character in the file type indicat-
;	  ing the file was not for distribution. Routine
;	  issues an error message and continues. Added
;	  check for 'first time flag' to exit routine so
;	  if no file is found meeting the requested
;	  parameters, '++NOT FOUND++' is issued to the
;	  console. NOTE: This required modifying the manner
;	  in which 'MFFLG1' was handled.   J. Seymour
;
;09/20/80 Added ILPRT routine, revised messages, added new
;	  abort routine, added CP/M 2.x f1' protect test,
;	  cleaned up file. (KBP)
;
;09/21/80 Added test for SYS files, moved TAG test,
;	  removed extra OPEN of file. (KBP)
;
; NOTE: REQUIRES 'MAC' AND SEQIO.LIB TO ASSEMBLE
;
	ORG	100H
;
	MACLIB	SEQIO	;DEFINE MACRO LIBRARY
;
START:	JMP	START2	;JMP AROUND IDENT
	DB	'MLIST.COM ver 3.4  9/21/80'
;
START2:	LXI	H,0
	DAD	SP	;GET OLD STACK
	SHLD	OLDSTK	;SAVE IT
	LXI	SP,STACK;SET NEW STACK
	LHLD	1	;POINT TO CP/M'S JMP TABLE
	LXI	D,3	;READY FOR ADD
	DAD	D	;POINT TO CONSOLE STATUS
	SHLD	CSTSC+1	;MODIFY CALL ADDRESS
	DAD	D	;POINT TO CONSOLE INPUT
	SHLD	CIC+1	;MODIFY CALL ADDRESS
	CALL	ILPRT	;PRINT:
	DB	'MLIST ver 3.4',CR,LF
	DB	'CTL-S pauses, CTL-C aborts',0
	LDA	FCB+1
	CPI	' '	;SEE IF FILENAME THERE
	JNZ	MORE
	CALL	ILPRT	;PRINT:
	DB	'++NO FILE NAME SPECIFIED++',0
	JMP	EXIT
;
MORE:	CALL	MFNAME
	JNC	CKFIL	;ANOTHER FILE FOUND, PRINT IT
	LDA	MFFLG1	;NOTHING FOUND, CHECK...
	ORA	A	;... FIRST TIME FLAG
	JZ	DONE	;AT LEAST ONE WAS FOUND
	CALL	ILPRT	;PRINT:
	DB	'++FILE NOT FOUND++',0
	JMP	EXIT
;
DONE	CALL	ILPRT	;PRINT:
	DB	'DONE',0
	JMP	EXIT
;
;CHECK HERE FOR FILE PROTECTED BY CP/M 2.x f1' ATTRIBUTE
;
CKFIL	LDA	MFCUR+1	;POINT TO TAG FILE ATTR
	ANI	80H	;IS IT TAGGED?
	JZ	CKFIL2	;IF NOT, CONTINUE
;
PROXIT	CALL	ILPRT	;PRINT:
	DB	'++FILE NOT FOR DISTRIBUTION, SORRY++',0
	JMP	MORE	;SEE IF ANOTHER
;
CKFIL2	LDA	MFCUR+10 ;POINT TO SYS FILE ATTR
	ANI	80H	;IS IT SYS?
	JZ	MOVNAM	;IF NOT, CONTINUE
	JMP	PROXIT	;SYS FILE, CAN'T PRINT IT
;
;MOVE FILENAME FROM FCB+1 TO FNAME
MOVNAM	LXI	H,FCB+1
	LXI	D,FNAME
	LXI	B,8
	CALL	MOVER
;MOVE FILETYPE FROM FCB+9 TO FNAME+9
	LXI	H,FCB+9
	LXI	D,FNAME+9
	LXI	B,3
	CALL	MOVER
	CALL	ILPRT	;PRINT:
	DB	CR,LF,'--> FILE: '
FNAME	DB	'XXXXXXXX.XXX'
	DB	CR,LF,0
;
; DEFINE SOURCE FILE:
;
;	INFILE	= INPUT FILE MODE
;	DISKIN = INTERNAL NAME
;	(NUL)	= DEFAULT DISK DRIVE
;	1	= FIRST DEFAULT NAME (TFCB)
;	(NUL)	=   "      "    TYPE
;	16384	= BUFFER SIZE
;	DSKBUF	= DISK BUFFER AREA
;
	FILE	INFILE,DISKIN,,1,,16384,DSKBUF
;
;CHECK HERE FOR FILE PROTECTED BY A '#' AS THE LAST
;CHARACTER IN THE FILETYPE (EG. MLIST.AS#).
;
	LXI	H,FCB+11 ;POINT TO LAST CHAR IN FCB
	MOV	A,M	;GET IT
	ANI	7FH	;STRIP CP/M 2.x ATTR
	CPI	'#'	;PROTECTED FILE?
	JZ	PROXIT	;PROTECTED FILE, EXIT WITH MSG
;
;CHECK HERE FOR .COM FILE, WHICH CAN'T BE PRINTED
;EITHER
;
	CPI	'M'	;WAS LAST CHAR AN 'M'?
	JNZ	OBJCHK	;IF NOT, CHK FOR '.OBJ' TYPE
	DCX	H
	MOV	A,M	;CHK NEXT
	ANI	7FH	;STRIP CP/M 2.x ATTR
	CPI	'O'	;AN 'O'?
	JNZ	READLP	;IF NOT IT'S OK TO PRINT
	DCX	H
	MOV	A,M	;WAS 'O', CHK NEXT CHAR
	ANI	7FH	;STRIP CP/M 2.x ATTR
	CPI	'C'	; 'C' AS IN '.COM'?
	JNZ	READLP	;IF NOT, IT'S OK TO PRINT
	CALL	ILPRT	;PRINT:
	DB	'++CAN''T LIST A .COM FILE++',0
	JMP	MORE	;MORE TO PRINT?
;
;HERE WE CHECK FOR AN ATTEMPT TO LIST AN OBJECT FILE
;
OBJCHK	CPI	'J'	;WAS LAST CHAR AN 'J' THEN?
	JNZ	READLP	;IF NOT, OK TO LIST
	DCX	H
	MOV	A,M	;MIGHT BE '.OBJ', CHK NEXT CHR
	ANI	7FH	;STRIP CP/M 2.x ATTR
	CPI	'B'	;IS IT A 'B'?
	JNZ	READLP	;IF NOT, LIST
	DCX	H
	MOV	A,M	;WAS, CHK FIRST CHAR
	ANI	7FH	;STRIP CP/M 2.x ATTR
	CPI	'O'	; 'O' AS IN '.OBJ'?
	JNZ	READLP	;IF NOT, PRINT THE FILE, IF SO
	CALL	ILPRT	;PRINT:
	DB	'++CAN''T LIST AN .OBJ FILE++',0
	JMP	MORE	;MORE TO PRINT?
;
;WRITE THE FILE TO CONSOLE
;
READLP:	GET	DISKIN
	CPI	EOF	;END OF FILE?
	JZ	MORE	;YES, MORE FILES TO PRINT?
	CALL	TYPE	;SEND CHAR TO CONSOLE
	CALL	CSTS	;KEY PRESSED?
	ORA	A
	CNZ	CKKB	;CHECK WHAT KEY
	JMP	READLP
;
CKKB	CALL	CI	;SEE WHAT CHAR
	CPI	'S'-40H	;CTL-S?
	CZ	CI	;YES, GET VALUE
	CPI	'C'-40H	;ABORT?
	JZ	EXITA	;YES, PRINT ABORT MSG, EXIT
	RET
;
CSTS	PUSH	B
	PUSH	D
	PUSH	H
CSTSC	CALL	$-$	;CHANGED BY INIT
	POP	H
	POP	D
	POP	B
	RET		;FROM "CSTS"
;
CI	PUSH	B
	PUSH	D
	PUSH	H
CIC	CALL	$-$	;CHANGED BY INIT
	POP	H
	POP	D
	POP	B
	RET		;FROM "CI"
;
;
;INLINE PRINT ROUTINE
;	CALL	ILPRT
;	DB	'MSG',0
;
ILPRT	MVI	A,CR
	CALL	TYPE
	MVI	A,LF
	CALL	TYPE
	XTHL		;SAVE HL, GET MSG
;
ILPLP	MOV	A,M	;GET CHAR
	CALL	TYPE	;OUTPUT IT
	INX	H	;POINT TO NEXT
	MOV	A,M	;TEST
	ORA	A	;..FOR END
	JNZ	ILPLP
	MVI	A,CR
	CALL	TYPE
	MVI	A,LF
	CALL	TYPE
	XTHL		;RESTORE HL, RET ADDR
	RET		;RET PAST MSG
;
;TYPE CHAR IN A
;
TYPE:	PUSH	B
	PUSH	D
	PUSH	H
	ANI	7FH	;STRIP PARITY BIT
	MOV	E,A	;CHARACTER TO E FOR CP/M
	MVI	C,WRCON
	CALL	BDOS
	POP	H
	POP	D
	POP	B
	RET
;
EXITA	MVI	C,CSTAT	;GET CONSOLE STATUS
	CALL	BDOS
	ORA	A	;CHARACTER WAITING?
	MVI	C,RDCON
	CNZ	BDOS	;YES, CLEAR CHARACTER FROM CP/M
	CALL	ILPRT	;PRINT:
	DB	CR,LF,'++ABORTED++',0
;
EXIT	LXI	D,80H	;SET DMA ADDRESS TO NORMAL
	MVI	C,STDMA	;FUNCTION NUMBER TO DO IT
	CALL	BDOS	;DO IT
	LHLD	OLDSTK	;GET OLD STACK
	SPHL		;RESTORE IT
	RET		;RETURN TO CP/M
;
;MULTI-FILE ACCESS SUBROUTINE.  ALLOWS PROCESSING
;OF MULTIPLE FILES (I.E. *.ASM) FROM DISK.  THIS
;ROUTINE BUILDS THE PROPER NAME IN THE FCB EACH
;TIME IT IS CALLED. CARRY IS SET IF NO MORE NAMES
;CAN BE FOUND. THE ROUTINE IS COMMENTED IN PSEUDO
;CODE, EACH PSEUDO CODE STATEMENT IS IN <<...>>
;
MFNAME:	;<<INIT DMA ADDR, FCB>>
	MVI	C,STDMA
	LXI	D,80H
	CALL	BDOS
	XRA	A
	STA	FCBEXT
	STA	FCBRNO
;<<IF FIRST TIME>>
	LDA	MFFLG1
	ORA	A
	JZ	MFN01
;<<SAVE THE REQUESTED NAME>>
;SAVE ORIG REQ
	LXI	H,FCB
	LXI	D,MFREQ
	LXI	B,12
	CALL	MOVER
	LDA	FCB
	STA	MFCUR	;SAVE DISK IN CURR FCB
;<<SRCHF REQ NAME>>
	LXI	H,MFREQ
	LXI	D,FCB
	LXI	B,12
	CALL	MOVER
	MVI	C,SRCHF
	LXI	D,FCB
	CALL	BDOS
;<<ELSE>>
	JMP	MFN02
;
MFN01:	;<<SRCHF CURR NAME>>
	LXI	H,MFCUR
	LXI	D,FCB
	LXI	B,12
	CALL	MOVER
	MVI	C,SRCHF
	LXI	D,FCB
	CALL	BDOS
;<<SRCHN REQ NAME>>
	LXI	H,MFREQ
	LXI	D,FCB
	LXI	B,12
	CALL	MOVER
	MVI	C,SRCHN
	LXI	D,FCB
	CALL	BDOS
;<<ENDIF>>
MFN02:	;<<RETURN CARRY IF NOT FOUND>>
	INR	A
	STC
	RZ
;<<MOVE NAME FOUND TO CURR>>
	DCR	A
	ANI	3
	ADD	A
	ADD	A
	ADD	A
	ADD	A
	ADD	A
	ADI	81H
	MOV	L,A
	MVI	H,0
	PUSH	H	;SAVE NAME POINTER
	LXI	D,MFCUR+1
	LXI	B,11
	CALL	MOVER
;<<MOVE NAME FOUND TO FCB>>
	POP	H
	LXI	D,FCB+1
	LXI	B,11
	CALL	MOVER
;<<SETUP FCB>>
	XRA	A
	STA	FCBEXT
	STA	FCBRNO
	STA	MFFLG1	;TURN OFF 1ST TIME SW
;<<RETURN>>
	RET
;------------------------------------------------
;
;MOVE SUBROUTINE
;
MOVER	MOV	A,M
	STAX	D
	INX	H
	INX	D
	DCX	B
	MOV	A,B
	ORA	C
	JNZ	MOVER
	RET
;
;MULTI-FILE ACCESS WORK AREA
;
MFFLG1	DB	1	;1ST TIME SW
MFREQ	DS	12	;REQ NAME
MFCUR	DS	12	;CURR NAME
;
	DS	60	;STACK AREA
STACK:	EQU	$
OLDSTK:	DS	2	;OLD STACK POINTER SAVED HERE
;
DSKBUF:	DS	16384	;16K BUFFER
;
;BDOS/CBIOS EQUATES
;
RDCON	EQU	1
WRCON	EQU	2
PRINT	EQU	9
CSTAT	EQU	11
OPEN	EQU	15
SRCHF	EQU	17
SRCHN	EQU	18
STDMA	EQU	26
BDOS	EQU	5
FCB	EQU	5CH 
FCBEXT	EQU	FCB+12
FCBRNO	EQU	FCB+32
;
	END
