;
;LIST.ASM CP/M PRINT UTILITY
;
;LISTS DISK FILE ON "LST:" DEVICE
;FCB FOR FILE MUST BE SET UP BEFORE ENTRY,
;AS FROM CCP "LIST NAME.TYP" COMMAND
;OR DDT "INAME.TYP" COMMAND.
;OUTPUT DEVICE IS CHANGEABLE BY MANIPULATING
;IO STATUS BYTE.
;LISTING CAN BE ABORTED BY TYPING CONTROL-C.
;OUPUT DEVICE IS ASSUMED TO HAVE 66 LINES PER PAGE
;
;MODIFIED 1/2/79 BAW TO REMOVE FINAL CNTL-L
;AND TO SEND BEGINNING CAR. RETURN
;
;PRINT PARAMETER EQUATES
;
PGSIZ	EQU	66		;LINES PER PAGE
LINSPP	EQU	60		;LINES PRINTED PER PAGE
NOCOL	EQU	64		;COLUM FOR PAGE NO
;
;CP/M ADDRESS EQUATES
;
ENTRY	EQU	5		;CPM CALL ADDRESS
FCB	EQU	5CH		;ADDR OF FILE CONTROL BLOCK
NR	EQU	FCB+32		;NEXT RECORD TO READ
TBUFF	EQU	80H		;WHERE CCP PUTS COMMAND LINE
DMA	EQU	80H		;DISK SECTOR BUFFER
TBASE	EQU	100H		;TPA ADDRESS
;
;EQUATES FOR ASCII CONTROL CHARS
;
TAB	EQU	9		;TAB - CNTL-I
LF	EQU	0AH		;LINE FEED
FF	EQU	0CH		;FORM FEED
ALTFF	EQU	0BH		;LET VTAB(CNTL-K)=FORM FEED
CR	EQU	0DH		;CARRIAGE RETURN
CTRLZ	EQU	1AH		;CONTROL Z. EOF.
;
;ENTRY POINT
;
	ORG	0100H
LIST:	LXI	SP,STACK
	CALL	INLMSG
	DB	'LIST VER 1.4.1',CR,LF,LF,'$'
;
;SET UP TITLE TO WHAT WAS TYPED AFTER "LIST".
;
	LXI	H,TTLBUF
	XCHG
	LXI	H,TBUFF		;WHERE CCP LEFT TEXT
	MOV	C,M		;NUMBER OF CHARS IN TBUFF
;
;COPY TEXT
;
TITLUP:	DCR	C
	JM	TITL2		;STOP IF INPUT USED UP
	INX	H		;ELSE MOVE 1 CHARACTER
	MOV	A,M
	STAX	D
	INX	D
	JNZ	TITLUP
TITL2:	XRA	A
	STAX	D		;TERMINATE WITH A ZERO
;
;OPEN FILE
;
	MVI	C,15
	LXI	D,FCB
	CALL	ENTRY		;CALL SYSTEM
	CPI	255
	LXI	D,EMFNF		;MESSAGE IF ERROR
	JZ	OPNERR		;IF NOT FOUND, ERROR EXIT
	XRA	A
	STA	NR		;SAY START AT RECORD 0
	STA	ICOUNT		;SAY EMPTY INPUT BUFFER
;
;INIT OUTPUT
;
	XRA	A		;INITIALIZE CURSOR POSITION
	STA	COL
	STA	LINE
	STA	PAGE+1
	INR	A
	STA	PAGE		;AND PAGE NO.
	MVI	A,00		;1 NULL FOR SPOOLER
	CALL	LOCH
	MVI	A,CR		;DO INITIAL CAR. RET
	CALL	LOCH
	MVI	A,FF		;AND FORM FEED
	CALL	LOCH
	CALL	PTITL		;PRINT TITLE FOR 1ST PAGE
;
;LIST RECORD -- OUTPUT CHARACTER LOOP
;
CLOOP:	CALL	INCH		;GET CHARACTER
	PUSH	B
	PUSH	H
	CALL	LSTCH		;PROCESS & LIST 1 CHAR
	MVI	C,11		;CHECK CONSOLE STATUS
	CALL	ENTRY
	RAR			;TEST LSB
	JNC	GOON
	MVI	C,1
	CALL	ENTRY		;GET CHAR
	CPI	03H		;CNTL-C ?
	JZ	0		;YES-ABORT
GOON:	POP	H
	POP	B
	JMP	CLOOP
;
;ERROR ROUTINES
;
RDERR:	LXI	D,RERMSG		;DISK READ ERROR
OPNERR:	MVI	C,9		;DE POINTS TO TEXT
	CALL	ENTRY		;PRINT BUFFER
	JMP	0
;
RERMSG:	DB	CR,LF,'DISK READ ERROR',CR,LF,'$'
EMFNF:	DB	'FILE NOT FOUND',CR,LF,'$'
;
;******************************
;
;INPUT CHARACTER SUBROUTINE
;
NEWREC:	MVI	C,20
	LXI	D,FCB
	CALL	ENTRY		;READ DISK BLOCK
	CPI	1
	JZ	0		;ON END OF FILE
	ORA	A		;SET FLAGS
	JNZ	RDERR		;MISC. OTHER ERROR
	LXI	H,ICOUNT
	MVI	M,128		;INIT BUFFER COUNTER
	LXI	H,DMA
	SHLD	IPOINT		;INIT BUFFER POINTER
	POP	H
;
;
;
INCH:	PUSH	H
	LXI	H,ICOUNT
	DCR	M		;COUNT CHARS USED FROM RECORD
	JM	NEWREC		;IF RECORD USED UP, GET ANOTHER
	LHLD	IPOINT		;GET BUFFER POINTER
	MOV	A,M		;FETCH CHARACTER
	CPI	CTRLZ
	JZ	0		;ON EOF, GO TO EOF ROUTINE
	INX	H		;POINT TO NEXT CHAR
	SHLD	IPOINT		;AND SAVE POINTER
	POP	H
	RET
;
;***********************************
;
;LIST CHAR IN A WITH PROCESSING OF SPECIAL CHARS
;
;KEEPS TRACK OF COLUMN, LINE, PAGE.
;EXPANDS TABS WITH STOPS EVERY 8 COLUMNS
;SIMULATES FORM FEEDS WITH LINE FEEDS.
;
LSTCH:	LXI	H,COL
	INR	M		;INCREMENT COLUMN COUNTER
	ANI	7FH		;MASK OUT PARITY BIT
	CPI	' '		;PROCESS CONTROL CHARS SEP.
	JP	LOCH		;GO PRINT IT
	DCR	M		;ELSE RESTORE COLUMN COUNTER
;
;PROCESS SPECIAL CHARS
;
	PUSH	PSW
	CPI	CR
	JNZ	LSC2
	XRA	A
	STA	COL
POPLOC:	POP	PSW		;GET CHAR BACK
	JMP	LOCH		;GO LIST IT
LSC2:	CPI	LF
	JNZ	LSC3
	LDA	LINE
	CPI	LINSPP-1
	JP	LISFF		;PAGE FULL, MAKE LIKE FORM FEED
	POP	PSW		;NORMAL, CLR STACK & PRINT LF
LISLF:	PUSH	PSW
	MVI	A,LF
	CALL	LOCH
	LDA	LINE
	INR	A		;INCRMENT LINE COUNT
	CPI	PGSIZ
	JM	LSC2A		;ON BOT OF PG, DO TOF
	XRA	A
	LHLD	PAGE
	INX	H
	SHLD	PAGE		;PAGE NO. INCREMENTED
LSC2A:	STA	LINE
	POP	PSW
	RET
;
LSC3:	CPI	ALTFF
	JZ	LISFF		;ALTERNATE FORM FEED
	CPI	FF
	JNZ	LSC4
;
;PRINT	CR, LF'S TILL LINE=0
;
LISFF:	CALL	FAKEFF		;SIMULATE FFORM FEED
;
;NEED A TITLE AT TOP OF NEXT PAGE, BUT FIRST SEE IF ANY MORE
;NON-CR, NON-LF, NON-FF CHARACTERS IN FILE.
;
IGNORE:	CALL	INCH		;INPUT NEXT CHAR
	CPI	CR
	JZ	IGNORE
	CPI	LF
	JZ	IGNORE
	CPI	FF
	JZ	IGNORE
;
;IF HERE, NOT AT EOFF AND NEXT CHAR IS IN A
;
	CALL	PTITL		;PRINT TITLE
	POP	H
	JMP	LSTCH		;CLR STK, LIST CHAR
LSC4:	CPI	TAB
	JNZ	LSC5
;
;PRINT SPACES TILL LO 3 BITS OF COL = 0
;
LSC4A:	MVI	A,' '
	CALL	LSTCH
	LDA	COL
	ANI	7
	JNZ	LSC4A
LPOPX:	POP	PSW
	RET
;
;MISCELLANEOUS	CHARACTERS, PRINT ^ AND LETTER
;
LSC5:	MVI	A,'^'
	CALL	LSTCH
	POP	PSW
	ORI	40H
	JMP	LSTCH
;
;PROCESS AND OUTPUT (SIMULATED) FORM FEED
;
FAKEFF:	MVI	A,CR
	CALL	LSTCH
LSFF2:	LDA	LINE
	ORA	A
	CNZ	LISLF
	JNZ	LSFF2
	RET
;
;LIST	OUTPUT CHAR IN A, WITHOUT PROCESSING
;
LOCH:	MOV	E,A
	MVI	C,5
	JMP	ENTRY
;
;SUBROUTINE TO PRINT PAGE TITL
;
PTITL:	PUSH	PSW
	PUSH	H
	LXI	H,TTLBUF
	CALL	PRTSTR
PAGN1:	MVI	A,' '
	CALL	LSTCH		;SPACING TO PAGE NO. COLUMN
	LDA	COL
	SBI	NOCOL
	JM	PAGN1		;WHEN WE GET THERE
	LXI	H,PGTXT
	CALL	PRTSTR
	LHLD	PAGE
	CALL	DECPR
	MVI	A,CR
	CALL	LSTCH		;FOLLOW PG. NO WITH CR
	MVI	A,LF
	CALL	LSTCH
	MVI	A,LF
	CALL	LSTCH		;AND TWO LINE-FEEDS
TITLX:	POP	H
	POP	PSW
	RET
;
;ROUTINE TO PRINT H,L TO HEX 00
;
PRTSTR:	MOV	A,M
	ORA	A
	RZ
	INX	H
	PUSH	H
	CALL	LSTCH
	POP	H
	JMP	PRTSTR
;
;DECIMAL PRINT HL, UNSIGNED
;
DECPR:	PUSH	B
	PUSH	D
	PUSH	H
	LXI	B,-10		;MINUS RADIX
	LXI	D,-1		;BECOMES NUMBER DIVIDED BY RADIX
DECPR1:	DAD	B
	INX	D
	JC	DECPR1		;SUB TILL NEGATIVE
	LXI	B,10
	DAD	B		;ADD RADIX BACK ONCE
	XCHG			;HAVE N/10 IN HL, REM IN D,E
	MOV	A,H
	ORA	L
	CNZ	DECPR		;PRT DIG. LEF TO THIS IF ANY
	MOV	A,E
	ADI	'0'
	CALL	LOCH		;PRINT THIS DIGIT
	POP	H
	POP	D
	POP	B
	RET
;
;OUTPUT IN-LINE MESSAGE TO CONSOLE
;
INLMSG:	XTHL			;SAVE H, GET TEXT LOCATION
	PUSH	PSW
	MOV	A,M
INLML:	CALL	CONO
	INX	H
	MOV	A,M
	CPI	'$'
	JNZ	INLML
	INX	H
	POP	PSW
	XTHL
	RET			;RETURN AFTER TEXT
;
;OUTPUT	CHAR FROM A
;
CONO:	PUSH	PSW
	PUSH	B
	PUSH	D
	PUSH	H
	MOV	E,A
	MVI	C,2
CALLEN:	CALL	ENTRY
	POP	H
	POP	D
	POP	B
	POP	PSW
	RET
;
;DATA STORAGE
;
COL:	DS	1
LINE:	DS	1
PAGE:	DS	2
ICOUNT:	DS	1		;INPUT BUFFER DOWN-COUNTER
IPOINT:	DS	2		;INPUT BUFFER POINTER
PGTXT:	DB	'PAGE ',0
TTLBUF:	DS	100H
STACK:	EQU	$
	END	LISTER
