; Typed in by Larry Kraemer  07/30/2018
;
; Edited by Mike Douglas to match the original listing
;   as shown in the "SBC880 Reference Manual" 
;
; Assemble with the TDL assembler
;
;	******************************************
;	* SYSTEM MONITOR, VERSION 1.1 REV A      *
;	* REQUIRES SBC880 CPU BOARD              *
;	* SW1-1=OFF,2=ON,3=OFF,4=ON,5=ON         *
;	* SW2-1 THRU 6 = ON                      *
;	* SW3-1 THRU 5 = OFF, 6 = ON             *
;	* WRITTEN BY R.D. CATILLER               *
;	* COPYRIGHT 1981 (C) COMPUTIME           *
;	* DATE - 04/05/1981                      *
;	******************************************
;
.PABS
;
;	MEMORY USED BY MONITOR
;
BASE	=	0F800H		;MONITOR BASE ADDRESS
STACK	=	00FFH		;MONITOR STACK
REGSTR	=	0010H		;CPU REGISTER STORAGE
OLDOP	=	REGSTR+16
BRKSTR	=	REGSTR+17
HLSTR	=	REGSTR+19
RST7	= 	38H		;RST 7 (LOC FOR TRAP)
;
;	CONSTANTS FOR MONITOR
;
CR	=	0DH		;ASCII CARRIAGE RETURN
LF	=	0AH		;ASCII LINE FEED
;
;	I/O PORTS ON CPU BOARD
;
T0	=	28H
T1	=	29H
T2	=	2AH
TCTL	=	2BH
INOUT	=	2CH
CONDTA	=	2EH
CONCTL	=	2FH
CONSTS	=	CONCTL
;
;	PROGRAM CODE BEGINS
;
.LOC	BASE
;
;LET US BEGIN
;
	JMP	BEGIN		;RESET JUMP LATCH
BEGIN:	MVI	A,0		;CLEAR REGISTER, STORE
	LXI	H,REGSTR
	MOV	M,A
	LXI	D,REGSTR+1
	LXI	B,18
	LDIR
	MVI	A,0C3H		;SET BREAKPOINT TRAP
	STA	RST7
	LXI	H,BREAK
	SHLD	RST7+1
	SHLD	REGSTR+14	;SET INITIAL PC
	LXI	SP,STACK	;SET UP STACK
	SSPD	REGSTR+8	
	MVI	A,80H		;SET UP PRINTER
	OUT	INOUT
	MVI	A,0FAH		;SET USART MODE
	OUT	CONCTL
	MVI	A,36H		;SET TIMER MODE
	OUT	TCTL
	MVI	A,13		;SET BAUD RATE TO 9600
	OUT	T0
	XRA	A
	OUT	T0
	MVI	A,37H		;ENABLE XMT & REC
	OUT	CONCTL
HELLO:	MVI	B,MSGL		;SAY HELLO
	CALL	MESG
START:	LXI	SP,STACK	;RESTORE STACK
	CALL	CRLF
	MVI	C,'/'
	CALL 	CO
	CALL	MAININ		;GET INPUT
	CPI	'D'
	JZ	DISP		;D = DISPLAY MEMORY
	CPI	'F'
	JZ	FILL		;F = FILL MEMORY
	CPI	'G'
	JZ	GOTO		;G = GOTO USER PROGRAM
	CPI	'H'
	JZ	HEXN		;H = HEX MATH
	CPI	'I'
	JZ	INPUT		;I = INPUT FROM PORT
	CPI	'J'
	JZ	TEST		;J = RAM TEST
	CPI	'M'
	JZ	MOVE		;M = MEMORY MOVE
	CPI	'O'
	JZ	OUTPUT		;O = OUTPUT TO PORT
	CPI	'S'
	JZ	SUBS		;S = SUBSTITUTE/EXAMINE
	CPI	'V'
	JZ	VERIFY		;V = VERIFY MEMORY
	CPI	'X'
	JZ	XAM		;X = EXAMINE REGISTERS
ERROR:	LXI	SP,STACK	;RESTORE STACK
	MVI	C,'*'		;DISPLAY ASTERISK
	CALL	CO
	JMP	START		;GO GET INPUT
;
;MESSAGE OUTPUT ROUTINE
;
MESG:	LXI	H,MSG
MESG1:	MOV	C,M		;GET A CHARACTER
	INX	H		;MOVE POINTER
	CALL	CO		;OUTPUT IT
	DJNZ	MESG1		;KEEP GOING TILL B=0
	RET
;
;CRLF BEFORE HLBLK ROUTINE
;
CRLFHL:	CALL CRLF
;
;PRINT THE CURRENT VALUE OF H&L
;AND A SPACE.
;
HLBLK:	CALL	DISPHL
;
;PRINT A SPACE ON THE CONSOLE
;
SPACE:	MVI	C,' '
;
;THIS IS THE MAIN CONSOLE
;OUTPUT ROUTINE
;
CO:	IN	CONCTL
	ANI	01H
	JZ	CO
	MOV	A,C
	OUT	CONDTA
	RET
;
;CONVERT TO HEX
;
HTA:	ANI	0FH		;LOW NIBBLE ONLY
	ADI	90H
	DAA
	ACI	40H
	DAA
	MOV	C,A
	RET
;
;CONSOLE CARRIAGE RETURN &
;LINE FEED ROUTINE
;
CRLF:	PUSH	H		;SAVE HL
	MVI	B,2		;CRLF LENGTH
	CALL	MESG		;SEND CRLF
	POP	H
	RET
;
;CONSOLE STATUS TEST ROUTINE
;
CSTS:	IN	CONCTL
	ANI	02H
	MVI	A,0FFH
	RNZ
	CMA
	RET
;
;PRINT H&L ON CONSOLE
;
DISPHL:	MOV	A,H
	CALL	DISPB
	MOV	A,L
DISPB:	PUSH	PSW
	RRC
	RRC
	RRC
	RRC
	CALL	HTA2
	POP	PSW
HTA2:	CALL	HTA
	JMP	CO
;
;MAIN KEYBOARD ROUTINE
;
MAININ:	CALL	CI		;GET INPUT
	MOV	C,A		;ECHO IT
	JMP	CO
;
;MAIN PARAMETER GETTING ROUTINE
;
GPARAM:	LXI	H,0		;CLEAR HL
GPNEXT:	CALL	MAININ		;GET INPUT
GP1:	MOV	B,A		;SAVE IT
	CPI	' '		;TEST FOR SPACE
	RZ			;RETURN IF SPACE
	CPI	','		;TEST FOR COMMA
	RZ
	CPI	CR		;TEST FOR CR
	RZ			;RETURN IF CR
	SUI	'0'		;TEST < 0
	JC	ERROR		;INPUT ERROR
	CPI	'G'-'0'		;TEST IF > F
	JNC	ERROR		;INPUT ERROR
	CPI	10		;TEST FOR NUMBER
	JC	DONE		;GO SAVE NUMBER
	SUI	'A'-'9'-1	;ADJUST LETTER
	CPI	0AH		;TEST FOR . THRU @
	JC	ERROR		;INPUT ERROR
DONE:	DAD	H		;SHIFT HL 1 DIGIT
	DAD	H
	DAD	H
	DAD	H
	ORA	L		;OR L WITH DIGIT
	MOV	L,A
	JMP	GPNEXT		;GET MORE INPUT
;
;GETS START & END ADDRESS AND DETERMINES LENGTH
;
RANGE:	CALL	GPARAM		;GET START ADDRESS
	CPI	CR		;TEST FOR CR
	JZ	ERROR		;INPUT ERROR
	MOV	D,H		;PUT HL IN DE
	MOV	E,L
	CALL GPARAM		;GET END ADDRESS
	PUSH H			;SAVE IT
	ORA	A		;END - START
	DSBC	D
	MOV	B,H		;PUT LENGTH IN BC
	MOV	C,L
	MOV	H,D		;PUT START IN HL
	MOV	L,E
	POP	D		;PUT END IN DE
	RET
RANGE2:	CALL	RANGE		;GET 2 PARAMETERS
	CPI	CR		;TEST FOR CR
	JNZ	ERROR		;INPUT ERROR
	RET
RANGE3:	CALL	RANGE		;GET 2 PARAMETERS
	CPI	CR		;TEST FOR CR
	JZ	ERROR		;INPUT ERROR
	SHLD	HLSTR		;SAVE START
PARAM1:	PUSH	B		;SAVE B
	CALL	GPARAM		;GET 3RD PARAMETER
	POP	B		;RESTORE BC
	CPI	CR		;TEST FOR CR
	JNZ	ERROR		;INPUT ERROR
	RET
ENDTST:	PUSH	H		;SAVE HL
	ORA	A		;HL - DE
	DSBC	D
	POP	H		;RESTORE HL
	RET			;RETURN FLAGS
SDL:	CALL	RANGE3		;GET 3 PARAMETERS
	MOV	D,H		;DEST TO DE
	MOV	E,L
	LHLD	HLSTR		;SOURCE TO HL
	RET			;BC = LENGTH
;
;MAIN CONSOLE INPUT ROUTINE
;
CI:	IN	CONCTL
	ANI	02H
	JZ	CI
	IN	CONDTA
	ANI	7FH
	RET
;
;PRINTER PUTPUT ROUTINE
;
PRINT:	IN	INOUT
	ANI	1
	JNZ	PRINT
	MOV	A,C
	ORI	80H
	OUT	INOUT
	ANI	7FH
	OUT	INOUT
	ORI	80H
	OUT	INOUT
	RET
;
;DISPLAYS CONTRNTS OF MEMORY IN HEX & ASCII
;
DISP:	CALL	RANGE2		;GET PARAMETERS
	MOV	A,L		;ADJUST START ADDRESS
	ANI	0F0H
	MOV	L,A
DISP1:	MOV	A,E		;ADJUST END ADDRESS
	ANI	0FH
	JZ	DISP2
	INX	D
	JMP	DISP1
DISP2:	CALL	CRLFHL		;DISPLAY CRLF & ADDRESS
DISP3:	CALL	SPACE		;DISPLAY SPACE
	MOV	A,M		;GET DATA
	CALL	DISPB		;DISPLAY IT
	MOV	A,L		;TEST FOR RND OF LINE
	ANI	0FH
	CPI	0FH
	JZ	DISP4		;DISPLAY ASCII
	INX	H		;NEXT
	JMP	DISP3
DISP4:	CALL	SPACE		;DISPLAY A SPACE
	CALL	SPACE		;DISPLAY A SPACE
	MOV	A,L		;BACK UP ADDRESS
	ANI	0F0H
	MOV	L,A
NEXTA:	MOV	A,M		;GET DATA
	ANI	7FH		;KILL PARITY
	CPI	' '		;TEST IF = SPACE
	JNC	DISP6		;TEST FURTHER
DISP5:	MVI	A,'.'		;REPLACE WITH A PERIOD
DISP6:	CPI	7CH		;> LOWER CASE Z
	JNC	DISP5		;REPLACE IT
	MOV	C,A		;DISPLAY IT
	CALL	CO
	INX	H		;STEP TO NEXT
	MOV	A,L		;TEST FOR END OF LINE
	ANI	0FH
	JNZ	NEXTA		;DO NEXT
	CALL	ENDTST		;TEST FOR END
	JNZ	DISP2		;NEXT LINE
	JMP	START
;
;FILL MEMORY WITH A CONSTANT
;
FILL:	CALL	RANGE3		;GET 2 PARAMETERS
	MOV	A,L		;PUT DATA IN A
	LHLD	HLSTR		;START ADDRESS TO HL
	MOV	M,A		;WRITE DATA AT START
	MOV	D,H		;COPY HL TO DE
	MOV	E,L
	INX	D		;DEST = SOURCE +1
	DCX	B		;ADJUST LENGTH
	LDIR			;WRITE DATA
	JMP	START
;
;GOTO USER PROGRAM WITH OPTIONAL BREAKPOINT
;
GOTO:	CALL	CI		;GET INPUT
	CPI	CR		;TEST FOR CR
	JZ	GOTO1		;USE OLD PC VALUE

	MOV	C,A		;ECHO INPUT
	CALL	CO
	CPI	' '		;TEST FOR SPACE
	JZ	GOTO2		;OLD PC. NEW BREAKPOINT
	CPI	','		;TEST FOR COMMA
	JZ	GOTO2		;OLD PC, NEW BREAKPOINT
	LXI	H,0		;CLEAR HL
	CALL	GP1		;GET PARAMETER
	SHLD	REGSTR+14		;SET NEW PC
	CPI	CR		;TEST FOR CR
	JZ	GOTO1		;JUMP TO NEW PC
GOTO2:	CALL	GPARAM		;GET BREAKPOINT ADDRESS
	CPI	CR		;TEST FOR CR
	JNZ	ERROR		;INPUT ERROR
	MOV	A,M		;GET OLD OP
	STA	OLDOP		;SAVE IT
	SHLD	BRKSTR		;SAVE BREAKPOINT ADDRESS
	MVI	A,0FFH		;STORE A BREAKPOINT
	MOV	M,A
GOTO1:	LHLD	REGSTR		;GET PSW
	PUSH 	H
	POP	PSW
	LBCD	REGSTR+2	;GET BC
	LDED	REGSTR+4	;GET DE
	LSPD	REGSTR+8	;GET SP
	LHLD	REGSTR+14	;GET PC
	PUSH H
	LHLD	REGSTR+6	;GET HL
	LIXD	REGSTR+10	;GET IX
	LIYD	REGSTR+12	;GET IY
	RET			;GO TO USER PROGRAM
;
;HEXADECIMAL MATH ROUTINE
;
HEXN:	CALL	RANGE2		;GET PARAMETERS
	DAD	D		;ADD PARAMETERS
	PUSH	B		;SAVE DIFFERENCE
	CALL	CRLFHL		;DISPLAY SUM
	POP	H		;GET DIFFERENCE
	CALL	CRLFHL		;DISPLAY IT
	JMP	START
;
;EXTENDED MEMORY TEST
;
TEST:	CALL	RANGE2		;GET 2 PARAMETERS
	MOV	B,H		;SAVE START IN BC
	MOV	C,L
	MVI	A,0		;CLEAR I
LOOP:	STAI
FILLIT:	LDAI			;BUILD DATA
	XRA	L
	XRA	H
	MOV	M,A		;WRITE DATA
	INX	H		;NEXT DATA
	MOV	A,H		;TEST FOR END
	CMP	D
	JNZ	FILLIT		;CONTINUE WRITING
	MOV	A,L		;TEST FOR END
	CMP	E
	JNZ	FILLIT		;CONTINUE WRITING
	MOV	H,B		;RESTORE START
	MOV	L,C
TEST1:	LDAI			;BUILD DATA
	XRA	L
	XRA	H
	CMP	M		;COMPARE IT
	CNZ	MERR		;DISPLAY ERRORS
	INX	H
	MOV	A,H		;TEST FOR END
	CMP	D
	JNZ	TEST1		;CONTINUE TEST
	MOV	A,L		;TEST FOR END
	CMP	E
	JNZ	TEST1		;CONTINUE TEST
	MOV	H,B		;RESTORE START
	MOV	L,C
	IN	CONCTL		;TEST KEYBOARD
	ANI	02H
	JNZ	START		;ABORT IF KEY PRESSED
	LDAI			;INCREMENT TALLY
	INR	A
	JMP	LOOP		;ANOTHER PASS
;
MERR:	PUSH	B		;SAVE BC
	PUSH	PSW		;SAVE DATA
	CALL	CRLFHL		;DISPLAY ADDRESS
	POP	PSW		;DISPLAY DATA
	CALL	DISPB
	CALL	SPACE		;DISPLAY A SPACE
	MOV	A,M		;GET MEM DATA
	CALL	DISPB		;DISPLAY IT
	POP	B		;RESTORE BC
	RET			;CONTINUE TESTING
;
;MOVE BLOCK OF MEMORY
;
MOVE:	CALL	SDL		;SRC, DEST, LNGTH
	LDIR			;DO MOVE
	JMP	START
;
;INPUT DATA FROM AN I/O PORT
;
INPUT:	CALL	PARAM1		;GET PARAMETER
	MOV	C,L		;PUT IO ADDR IN C
	INP	A		;INPUT DATA TO A
	PUSH	PSW		;SAVE IT
	CALL	CRLF		;DISPLAY CRLF
	POP	PSW		;GET DATA
	CALL	DISPB		;DISPLAY IT
	JMP	START
;
;OUTPUT DATA TO AN I/O PORT
;
OUTPUT:	CALL	RANGE2		;GET 2 PARAMETERS
	MOV	C,L		;OUTPUT DATA
	OUTP	E
	JMP	START
;
;SUBSTITUTE AND EXAMINE MEMORY
;
SUBS:	CALL	GPARAM		;GET PARAMETER
SUBS1:	CALL	CRLFHL		;DISPLAY ADDRESS
	MOV	A,M		;GET DATA
	CALL DISPB		;DISPLAY IT
	CALL SPACE		;DISPLAY A SPACE
	CALL	CI		;GET INPUT
	CPI	CR		;TEST FOR CR
	JZ	START		;DONE
	CPI	' '		;TEST FOR SPACE
	JNZ	SUBS2		;TEST FURTHER
SUBS4:	INX	H		;ADDRESS +1
	JMP	SUBS1		;CONTINUE DISPLAY
SUBS2:	CPI	7FH		;TEST FOR RUBOUT
	JNZ	SUBS3		;LOOK FOR PARAMETER
	DCX	H		;ADDRESS -1
	JMP	SUBS1		;CONTINUE DISPLAY
SUBS3:	MOV	C,A		;ECHO CHARACTER
	CALL	CO
	PUSH	H		;SAVE ADDRESS
	LXI	H,0		;CLEAR HL
	CALL	GP1		;GET PARAMETER
	MOV	B,A		;SAVE DELIMITER
	MOV	A,L		;PUT DATA IN A
	POP	H		;GET ADDRESS
	MOV	M,A		;STORE DATA
	MOV	A,B		;TEST FOR CR
	CPI	CR
	JZ	START		;DONE
	JMP	SUBS4		;CONTINUE
;
;VERIFY BLOCK OF MEMORY AGAINST MEMORY
;
VERIFY:	CALL	SDL		;SRC, DEST, LNGTH
VER1:	LDAX	D		;GET DEST DATA
	CCI			;COMPARE TO SOURCE
	JPO	START		;DONE
	DCX	H		;ADJUST ADDRESS
	CNZ	MERR		;DISPLAY ERRORS
	INX	H		;RESTORE ADDRESS
	INX	D		;DEST + 1
	JMP	VER1		;CONTINUE
;
;RETURN FROM BREAKPOINT
;
BREAK:	PUSH	PSW		;SAVE PSW
	SBCD	REGSTR+2	;STORE BC
	SDED	REGSTR+4	;STORE DE
	SHLD	REGSTR+6	;STORE HL
	POP	H		;GET PSW
	SHLD	REGSTR		;STORE PSW
	POP	H		;GET PC
	DCX	H		;PC -1
	SHLD	REGSTR+14	;STORE PC
	LHLD	BRKSTR		;GET BREAKPOINT ADDR
	LDA	OLDOP		;RESTORE OLD OP
	MOV	M,A
	SSPD	REGSTR+8	;STORE SP
	SIXD	REGSTR+10	;STORE IX
	SIYD	REGSTR+12	;STORE IY
	LXI	SP,STACK	;RESTORE STACK
;
;EXAMINE AND DISPLAY CPU REGISTERS
;
XAM:	LXI	H,XAMM		;POINT TO MESSAGE
	LXI	D,REGSTR	;POINT TO REGISTERS
	CALL	CRLF		;DISPLAY CRLF
	MVI	C,8		;SET TALLY
XAM1:	MVI	B,2
	PUSH	B		;SAVE BC
	CALL	MESG1		;DISPLAY REG NAME
	CALL	SPACE		;DISPLAY SPACE
	PUSH	H		;SAVE HL
	LDAX	D		;GET REGISTER DATA
	MOV	L,A
	INX	D
	LDAX	D
	MOV	H,A
	INX	D		;DEST +1
	CALL	HLBLK		;DISPLAY REG DATA
	CALL	SPACE		;DISPLAY SPACE
	POP	H		;GET HL
	POP	B		;GET BC
	DCR	C		;TALLY -1
	JZ	START		;DONE
	JMP	XAM1		;CONTINUE
;
XAMM:
.ASCII	'AFBCDEHLSPIXIYPC'
;
;	MONITOR SIGN-ON MESSAGE
;
MSG:	.BYTE	CR,LF
	.ASCII	'SYSTEM MONITOR 1.1 REV A'
MSGL	=	.-MSG
;
;END OF PROGRAM
.END



