;q.asm - dumps TPA size and 00-ff.
;
;	If given an operand: @xxxx
;	the dump will start at hex xxxx.
;	press control-c to stop.
;
;	While dumping, pressing the space
;	bar bumps the address by 100.
;
BDOS	EQU	5
CONST	EQU	11
CONIN	EQU	1
FCB	EQU	5CH
	ORG	100H
;	
;INIT LOCAL STACK
;
	LXI	H,0		;HL=0
	DAD	SP		;HL=STACK
	SHLD	STACK		;SAVE IT
	LXI	SP,STACK	;LOAD LOCAL STACK
;
	LDA	FCB+1		;SEE IF 
	CPI	'@'		;	@XXXX
	JZ	DUMPAT		;	YES, GET ADDR
;
;PRINT BDOS ENTRY ADDRESS
;
TPASIZE	LHLD	BDOS+1		;GET JMP TO BDOS
;
; remove following instruction to have Q print BDOS entry
; address instead of TPA size (which is BDOS-100).
;
 	DCR	H		;compute TPA size
	CALL	PRADDR		;PRINT THE ADDR
	CALL	CRLF		;	THEN CR-LF
	CALL	CRLF		;	AND AGAIN
DUMP0	LXI	H,0		;GET DEFAULT ADDR
LP	CALL	PRADDR		;PRINT THE ADDR
	CALL	PRLINE		;THEN THE LINE
	INR	H		;THIS SETS PSW TO
	DCR	H		;	ZERO IF H=0
	JZ	LP		;LOOP IF NOT YET 
				;AT 0100 (H = 01)
;
;RETURN TO CP/M
;
EXIT	LHLD	STACK		;GET CP/M'S STACK
	SPHL			;RESTORE IT
	RET			;	AND RETURN
;
;PRINT ADDR IN HEX
;
PRADDR	MOV	A,H		;GET H
	CALL	HEX		;	AND PRINT IT
	MOV	A,L		;THEN L
	CALL	HEX		;	AND PRINT IT
;
;SPACE 2 TIMES
;
SPACE2	CALL	SPACE		
;
;SPACE ONCE
;
SPACE	MVI	A,' '
;
;CONSOLE OUT
;
CONOUT	PUSH	B		;SAVE 
	PUSH	D		;	THE
	PUSH	H		;	REGS
	MOV	E,A		;CHAR IN E FOR BDOS
	MVI	C,2		;FUNCTION 2 = WRITE CON.
	CALL	BDOS		;PRINT THE CHAR
	POP	H		;RESTORE
	POP	D		;	THE
	POP	B		;	REGS
	RET			;AND RETURN
;
;PRINT (A) IN HEX
;
HEX	PUSH	PSW		;SAVE INCOMING
	RAR			;ROTATE LEFT
	RAR			;	4 BITS
	RAR			;	INTO
	RAR			;	RIGHT 4
	CALL	NIBBL		;PRINT THEM
	POP	PSW		;GET BACK, 
NIBBL	ANI	0FH		;ISOLATE NIBBLE
	ADI	90H		;SEE TEXT FOR 
	DAA			;	EXPL OF 
	ACI	40H		;	THIS BINARY
	DAA			;	TO ASCII	
	JMP	CONOUT		;	CONVERSION
;
;PRINT ONE LINE
;
PRLINE	PUSH	H		;SAVE ADDR
PRHEX	MOV	A,M		;GET A BYTE
	CALL	HEX		;PRINT IN HEX
SPACE4	MOV	A,L		;SEE IF
	ANI	3		;	TIME
	INR	A		;	TO 
	CPI	4		;	SPACE
	CZ	SPACE		;YES
SPACE8	MOV	A,L		;SEE IF TIME TO
	ANI	7		;	DOUBLE
	INR	A		;	SPACE
	CPI	8		;	IN COLUMN 8
	CZ	SPACE		;YES
CKDONE	INX	H		;TO NEXT BYTE
	MOV	A,L		;GET LOW ADDR
	ANI	0FH		;END OF LINE?
	JNZ	PRHEX		;	NO, LOOP
NOWASC	CALL	FENCE		;PRINT FENCE CHAR
	POP	H		;RESTORE ADDR
PRASC	MOV	A,M		;GET BYTE FOR ASCII
	CPI	' '		;SEE IF CONTROL CHAR
	JC	PRPER		;PRINT PERIOD IF SO
PRTABLE	CPI	7FH		;SEE IF PRINTABLE
	JC	PRNPER		;	YES
PRPER	MVI	A,'.'		;PRINT A PERIOD
PRNPER	CALL	CONOUT		;PRINT WHAT'S IN A
MORE	INX	H		;TO NEXT CHAR
	MOV	A,L		;CHECK LOW ADDR
	ANI	0FH		;	FOR END OF LINE
	JNZ	PRASC		;LOOP IF NOT
	CALL	FENCE		;PRINT CLOSING FENCE
CRLF	MVI	A,0DH		;THEN "FALL INTO"
	CALL	CONOUT		;CR/LF ROUTINE
	MVI	A,0AH
	JMP	CONOUT
;
;PRINT ASCII DELIMITER CHAR - VERTICAL BAR "FENCE".
;
FENCE	MVI	A,'|'		;GET FENCE CHAR
	JMP	CONOUT		;PRINT IT
;
;OPERAND ON COMMAND SAID "@XXXX" SO GET ADDR
;	
DUMPAT	LXI	D,FCB+2		;SKIP @ SIGN
	LXI	H,0		;INIT BINARY RESULT
;
;THIS LOOP CONVERTS ASCII TO BINARY
;
GETAD	LDAX	D		;GET CHAR OF ADDR
	INX	D		;POINT TO NEXT
	CPI	' '		;SEE IF PAST ADDR
				;(REMEMBER FCB IS
				; PADDED WITH ' ')
	JZ	DUMPIT		;IF SO, GO DUMP IT
TIMES16	DAD	H		;HL =	2 X HL
	DAD	H		;	4
	DAD	H		;	8
	DAD	H		;      16
CKALPHA	CPI	'A'		;SEE IF CHAR IS 
	JC	NUM		;	NUMERIC?
				;(NOT THOROUGH TEST)
	SUI	7		;OTHERWISE FUDGE
NUM	SUI	'0'		;TO MAKE PRINTABLE
				;(SEE TEXT)
	ADD	L		;ADD THIS DIGIT
	MOV	L,A		;PUT IT BACK
	JMP	GETAD		;LOOP UNTIL DONE
;
DUMPIT	CALL	PRADDR		;FULL DUMP: PRINT ADDR,
	CALL	PRLINE		;	THEN LINE
CKSTAT	CALL	STAT		;THEN CHECK FOR INTERRUPT
	JZ	EXIT		;	AND EXIT IF SO.
STOPAT0	MOV	A,H		;CHECK IF HL = 0
	ORA	L		;BY ORING H WITH L
	JNZ	DUMPIT		;IF EITHER NOT ZERO, LOOP
	JMP	EXIT		;	ELSE DONE
;
;CHECK CONSOLE STATUS, PROCESS CONTROL-S AND CONTROL-C
;
STAT	PUSH	H		;SAVE DUMP ADDR POINTER
	MVI	C,CONST		;GET STATUS FUNCTION
	CALL	BDOS		;HAVE BDOS CHECK FOR KEY
	POP	H		;RESTORE ADDR
	ORA	A		;CHECK RETURN FROM BDOS
	JZ	NSTAT		;IF NO CHAR, JMP
GETCHAR	PUSH	H		;GOT A CHAR, SAVE ADDR
	MVI	C,CONIN		;GET CONSOLE IN FNC.
	CALL	BDOS		;GET THE CHAR
CKCTLS	MVI	C,CONIN		;SET UP FOR SECOND READ
	CPI	'S'-40H		;TEST FOR CTL-S PAUSE
	CZ	BDOS		;IF SO, READ 2ND CHAR
CKBREAK	POP	H		;RESTORE ADDR
	CPI	'C'-40H		;CHECK CHAR FOR ABORT
	JZ	EXIT		;EXIT IF SO
	CPI	0DH		;IF CARRIAGE RETURN,
	JZ	EXIT		;ALSO ABORT
INCRSP	CPI	' '		;IF ITS A SPACE, BUMP H.
	RNZ			;H, O
	INR	H		;BUMP ADDR BY 100 (H BY 1)
	RET			;AND RETURN
;
NSTAT	INR	A		;NOT INTERRUPT SO JUST
	RET			;	RETURN A =1
;
	DS	100		;STACK SPACE
STACK	DS	2
