;	<< ZAPPLE 2-K MONITOR SYSTEM >>
;		by
;
;	TECHNICAL DESIGN LABS, INC.
;	RESEARCH PARK
;	PRINCETON, NEW JERSEY  08540
;
;	COPYRIGHT JULY 1976 BY TDL INC.
;
;	ASSEMBLED BY ROGER AMIDON
;
; SEPTEMBER 2017 BY UDO MUNK:
;	MODIFIED TO ZILOG/MOSTEK SYNTAX TO ASSEMBLE WITH Z80ASM
;	FIXED TYPOS AND BUGS
;	CHANGED TYPEWRITER I/O TO MITS 2SIO CHANNEL A
;	CHANGED CASSETTE I/O TO MITS ACR SIO
;
; USE Z80ASM VERSION 1.8, WON'T ASSEMBLE CORRECT WITH VERSIONS BEFORE!
;
;
BASE	EQU	0F000H
USER	EQU	BASE+800H
;
	TITLE	<Zapple Monitor, Version 1.11, Dec. 18, 1976>
;
RST7	EQU	38H	     ;RST 7 (LOCATION FOR TRAP)
;IOBYT	EQU	2	     ;R/W PORT FOR TEMP. STORAGE
IOBYT	EQU	0EFFFH	     ;MEMORY LOCATION FOR TEMP. STORAGE
;SENSE	EQU	3	     ;PORT FOR INITIAL I/O CONFIGURATION (IN)
SWITCH	EQU	0FFH	     ;FRONT PANEL SENSE SWITCHES
;RCP	EQU	SENSE	     ;READER CONTROL PORT (OUT)
NN	EQU	0	     ;"I" REGISTER INITIAL VALUE
;
;	EXTERNAL EQUATES
;
;	NAME	ZAPPLE
;	EXT	COLOC
;	EXT	LNLOC
;	EXT	LULOC
;	EXT	PTPL
;	EXT	PULOC
;	EXT	CSLOC
;	EXT	CILOC
;	EXT	RPTPL
;	EXT	RULOC
;
;
;	<I/O DEVICES>
;
;-TELEPRINTER
;
TTI	EQU	11H	     ;DATA IN PORT
TTO	EQU	11H	     ;DATA OUT PORT
TTS	EQU	10H	     ;STATUS PORT (IN)
TTS2	EQU	12H	     ;STATUS PORT MITS 2SIO B
TTYDA	EQU	01H	     ;DATA AVAILABLE MASK BIT
TTYBE	EQU	02H	     ;XMTR BUFFER EMPTY MASK
;
;-C.R.T. SYSTEM
;
CRTI	EQU	51H	     ;DATA PORT (IN)
CRTS	EQU	50H	     ;STATUS PORT (IN)
CRTO	EQU	51H	     ;DATA PORT (OUT)
CRTDA	EQU	40H	     ;DATA AVAILABLE MASK
CRTBE	EQU	80H	     ;XMTR BUFFER EMPTY MASK
;
;-CASSETTE SYSTEM
;
RCSD	EQU	07H	     ;DATA IN PORT
RCSS	EQU	06H	     ;STATUS PORT (IN)
RCSDA	EQU	01H	     ;DATA AVAILABLE MASK
PCASO	EQU	07H	     ;DATA PORT (OUT)
PCASS	EQU	06H	     ;CONTROL PORT (OUT)
PCSBE	EQU	80H	     ;XMTR BUFFER EMPTY MASK
;
;	<CONSTANTS>
;
FALSE	EQU	0	     ;ISN'T SO
TRUE	EQU	~FALSE       ;IT IS SO
CR	EQU	0DH	     ;ASCII CARRIAGE RETURN
LF	EQU	0AH	     ;ASCII LINE FEED
BELL	EQU	7	     ;DING
RUB	EQU	0FFH	     ;RUB OUT
FIL	EQU	00	     ;FILL CHARACTER AFTER CRLF
MAX	EQU	7	     ;NUMBER OF QUES IN EOF
;
;	<I/O CONFIGURATION MASKS>
;
CMSK	EQU	11111100B    ;CONSOLE DEVICE
RMSK	EQU	11110011B    ;STORAGE DEVICE (IN)
PMSK	EQU	11001111B    ;STORAGE DEVICE (OUT)
LMSK	EQU	00111111B    ;LIST DEVICE
;
;
;-CONSOLE CONFIGURATION
CTTY	EQU	0	     ;TELEPRINTER
CCRT	EQU	1	     ;C.R.T.
BATCH	EQU	2	     ;READER FOR INPUT, LIST FOR OUTPUT
CUSE	EQU	3	     ;USER DEFINED
;
;-STORAGE INPUT CONFIGURATION
RTTY	EQU	0	     ;TELEPRINTER READER
RPTR	EQU	4	     ;HIGH-SPEED RDR (EXTERNAL ROUTINE)
RCAS	EQU	8	     ;CASSETTE
RUSER	EQU	0CH	     ;USER DEFINED
;
;-STORAGE OUTPUT CONFIGURATION
PTTY	EQU	0	     ;TELEPRINTER PUNCH
PPTP	EQU	10H	     ;HIGH-SPEED PUNCH (EXTERNAL ROUTINE)
PCAS	EQU	20H	     ;CASSETTE
PUSER	EQU	30H	     ;USER DEFINED
;
;-LIST DEVICE CONFIGURATION
LTTY	EQU	0	     ;TELEPRINTER PRINTER
LCRT	EQU	40H	     ;C.R.T. SCREEN
LINE	EQU	80H	     ;LINE PRINTER (EXTERNAL ROUTINE)
LUSER	EQU	0C0H	     ;USER DEFINED
;
;
;	VECTOR FOR USER DEFINED ROUTINES
;
CILOC	EQU	USER	     ;CONSOLE INPUT
COLOC	EQU	CILOC+3	     ;CONSOLE OUTPUT
RPTPL	EQU	COLOC+3	     ;HIGH-SPEED READER
RULOC	EQU	RPTPL+3	     ;USER DEFINED STORAGE (INPUT)
PTPL	EQU	RULOC+3	     ;HIGH-SPEED PUNCH
PULOC	EQU	PTPL+3	     ;USER DEFINED STORAGE (OUTPUT)
LNLOC	EQU	PULOC+3	     ;LINE PRINTER
LULOC	EQU	LNLOC+3	     ;USER DEFINED PRINTER
CSLOC	EQU	LULOC+3	     ;CONSOLE INPUT STATUS ROUTINE
J	EQU	CSLOC+3
;
;	PROGRAM CODE BEGINS HERE
;
;
	ORG	BASE
	JP	BEGIN	     ;GO AROUND VECTORS
;
;	<VECTOR FOR CALLING PROGRAMS>
;
; THESE VECTORS MAY BE USED BY USER WRITTEN
; PROGRAMS TO SIMPLIFY THE HANDLING OF I/O
; FROM SYSTEM TO SYSTEM.  WHATEVER THE CURRENT
; ASSIGNED DEVICE, THESE VECTORS WILL PERFORM
; THE REQUIRED I/O OPERATION, AND RETURN TO
; THE CALLING PROGRAM.  (RET)
;
; THE REGISTER CONVENTION USED FOLLOWS-
;
; ANY INPUT OR OUTPUT DEVICE
;	CHARACTER TO BE OUTPUT IN 'C' REGISTER.
;	CHARACTER WILL BE IN 'A' REGISTER UPON
;	RETURNING FROM AN INPUT OR OUTPUT.
; 'CSTS'-
;	RETURNS TRUE (0FFH IN 'A' REG.) IF THERE IS
;	SOMETHING WAITING, AND ZERO (00) IF NOT.
; 'IOCHK'-
;	RETURNS WITH THE CURRENT I/O CONFIGURATION
;	BYTE IN 'A' REGISTER.
; 'IOSET'-
;	ALLOWS A PROGRAM TO DYNAMICALLY ALTER THE
;	CURRENT I/O CONFIGURATION, AND REQUIRES
;	THE NEW BYTE IN 'C' REGISTER.
; 'MEMCK'-
;	RETURNS WITH THE HIGHEST ALLOWED USER
;	MEMORY LOCATION. 'B'=HIGH BYTE, 'A'=LOW.
; 'TRAP'-
;	THIS IS THE 'BREAKPOINT' ENTRY POINT,
;	BUT MAY BE 'CALLED'. IT WILL SAVE
;	THE MACHINE STATE. RETURN CAN BE MADE WITH
;	A SIMPLE 'G[CR]' ON THE CONSOLE.
;
	JP	CI	     ;CONSOLE INPUT
	JP	RI	     ;READER INPUT
	JP	CO	     ;CONSOLE OUTPUT
	JP	PUO	     ;PUNCH OUTPUT
	JP	LO	     ;LIST OUTPUT
	JP	CSTS	     ;CONSOLE STATUS
	JP	IOCHK	     ;I/O CHECK
	JP	IOSET	     ;I/O SET
	JP	MEMCK	     ;MEMORY LIMIT CHECK
TRAP:	JP	RESTART	     ;BREAKPOINT
;
;	ANNOUNCEMENT OF MONITOR NAME & VERSION
MSG:	DEFB	CR,LF,FIL,FIL,FIL
	DEFB	'Zapple V'
	DEFB	'1.1'
MSGL	EQU	$-MSG
;
;	LET US BEGIN
;
; *NOTE- THE CODE UP TO THE 'IN SENSE' MAY
; BE REPLACED BY ENOUGH CODE TO INITIALIZE
; AN ACIA OR SIO DEVICE. ADDITIONAL DEVICES
; MAY BE INITIALIZED USING THE 'Q' COMMAND.
; (OR STANDARD ROUTINES FOR INITILIZATION
; MAY BE LOADED & EXECUTED IN THE USER AREA).
;
BEGIN:
	LD	A,3	     ;RESET BOTH MITS 2SIO ACIA
	OUT	(TTS),A
	OUT	(TTS2),A
	LD	A,15H	     ;SET BOTH MITS 2SIO ACIA TO 8N1
	OUT	(TTS),A
	OUT	(TTS2),A
;
;	LD	A,NN	     ;FOR 'I' REG. IF NEEDED.
;	LD	I,A
;	NOP		     ;SPARE BYTE
;	XOR	A	     ;CLEAR READER CONTROL PORT
;	OUT	(RCP),A
;	IN	A,(SENSE)    ;INITIALIZE I/O CONFIGURARTION
;	OUT	(IOBYT),A
;
	IN	A,(SWITCH)   ;INITALIZE I/O CONFIGURATION
	LD	(IOBYT),A    ;  FROM FRONT PANEL SENSE SWITCHES
;
	LD	SP,AHEAD-4   ;SET UP A FAKE STACK
	JP	MEMSIZ+1     ;GET MEMORY SIZE
	DEFW	AHEAD
AHEAD:	LD	SP,HL	     ;SET TRUE STACK
	EX	DE,HL
	LD	BC,ENDX-EXIT
	LD	HL,EXIT
	LDIR		     ;MOVE TO RAM
	EX	DE,HL
	LD	BC,-5FH	     ;SET UP A USER'S STACK VALUE
	ADD	HL,BC
	PUSH	HL	     ;PRE-LOAD USER'S STACK VALUE
	LD	HL,0	     ;INITIALIZE OTHER REGISTERS
	LD	B,10	     ; (16 OF THEM)
STKIT:	PUSH	HL	     ; TO ZERO
	DJNZ	STKIT
HELLO:	LD	B,MSGL	     ;SAY HELLO TO THE FOLKS
	CALL	TOM	     ;OUTPUT SIGN-ON MSG
START:	LD	DE,START     ;MAIN 'WORK' LOOP
	PUSH	DE	     ;SET UP A RETURN TO HERE
	CALL	CRLF
	LD	C,'>'
	CALL	CO
STARO:	CALL	TI	     ;GET A CONSOLE CHARACTER
	AND	7FH	     ;IGNORE NULLS
	JR	Z,STARO	     ;GET ANOTHER
	SUB	'A'	     ;QUALIFY THE CHARACTER
	RET	M	     ;<A
	CP	'Z'-'A'+1
	RET	NC	     ;>Z
	ADD	A,A	     ;A*2
	LD	B,0
	LD	C,A	     ;POINT TO PLACE ON TABLE
	LD	HL,TBL	     ;POINT TO COMMAND TABLE
	ADD	HL,BC	     ;ADD IN DISPLACEMENT
	LD	E,(HL)
	INC	HL
	LD	D,(HL)
	EX	DE,HL	     ;D&E=ROUTINE ADDRESS
	LD	C,2	     ;SET C UP
	JP	(HL)	     ;GO EXECUTE COMMAND
;
;		<COMMAND BRANCH TABLE>
;
TBL:	
	DEFW	ASSIGN	    ;A - ASSIGN I/O
	DEFW	BYE	    ;B - SYSTEM SHUT-DOWN
	DEFW	COMP	    ;C - COMPARE MEMORY VS. READER INPUT
	DEFW	DISP	    ;D - DISPLAY MEMORY ON CONS. IN HEX
	DEFW	EOF	    ;E - END OF FILE TAG FOR HEX DUMPS
	DEFW	FILL	    ;F - FILL MEMORY WITH A CONSTANT
	DEFW	GOTO	    ;G - GOTO [ADDR]<,>BREAKPOINTS (2)
	DEFW	HEXN	    ;H - HEX MATH. <SUM>,<DIFFERENCE>
;	DEFW	J	    ;I * USER DEFINED, INSERT VECTOR
	DEFW	ERROR
	DEFW	TEST	    ;J - NON-DESTRUCTIVE MEMORY TEST
;	DEFW	J+3	    ;K * USER DEFINED, INSERT VECTOR
	DEFW	ERROR
	DEFW	LOAD	    ;L - MOVE A BINARY FORMAT FILE
	DEFW	MOVE	    ;M - MOVE BLOCKS OF MEMORY
	DEFW	NULL	    ;N - PUNCH NULLS ON PUNCH DEVICE
;	DEFW	J+6	    ;O * USER DEFINED, INSERT VECTOR
	DEFW	ERROR
	DEFW	PUTA	    ;P - 'PUT' ASCII INTO MEMORY.
	DEFW	QUERY	    ;Q - QI(N)=DISP. N; QO(N,V)=OUT N,V
	DEFW	READ	    ;R - READ A HEX FILE (W/CHECKSUMS)
	DEFW	SUBS	    ;S - SUBSTITUTE &/OR EXAMINE MEMORY
	DEFW	TYPE	    ;T - TYPE MEMORY IN ASCII
	DEFW	UNLD	    ;U - MEMORY TO PUNCH (BINARY FORMAT)
	DEFW	VERIFY	    ;V - COMPARE MEMORY AGAINST MEMORY
	DEFW	WRITE	    ;W - MEMORY TO PUNCH (HEX FORMAT)
	DEFW	XAM	    ;X - EXAMINE & MODIFY CPU REGISTERS
	DEFW	WHERE	    ;Y - FIND SEQUENCE OF BYTES IN RAM
	DEFW	SIZE	    ;Z - ADDRESS OF LAST R/W LOCATION
;
;
;
;	THIS ROUTINE CONTROLS THE CONFIGURATION
; OF THE VARIOUS I/O DRIVERS & DEVICES. THIS IS
; ACCOMPLISHED VIA A HARDWARE READ/WRITE PORT.
;	THIS PORT IS INITIALIZED UPON SIGN-ON
; BY THE VALUE READ ON PORT 'SENSE'.  IT MAY BE
; DYNAMICALLY MODIFIED THROUGH CONSOLE COMMANDS.
;
; THE VALUE ON THE 'IOBYT' PORT REPRESENTS THE
; CURRENT CONFIGURATION.  IT IS STURCTURED THUSLY:
;
; 000000XX - WHERE XX REPRESENTS THE CURRENT CONSOLE
; 0000XX00 - WHERE XX REPRESENTS THE CURRENT READER
; 00XX0000 - WHERE XX REPRESENTS THE CURRENT PUNCH
; XX000000 - WHERE XX REPRESENTS THE CURRENT LISTER
;
; WHEN USING A MEMORY LOCATION FOR IOBYT, THE
; POLARITY IS REVERSED.  FOR AN I/O PORT,
; WHEN XX = 11, THE DEVICE IS ALWAYS THE
; TELEPRINTER.  WHEN XX = 00, THE DEVICE IS ALWAYS
; USER DEFINED.  SEE OPERATOR'S MANUAL FOR FURTHER
; DETAILS.
;
ASSIGN:	CALL	TI	     ;GET DEVICE NAME
	LD	HL,LTBL	     ;POINT TO DEVICE TABLE
	LD	BC,400H	     ;4 DEVICES TO LOOK FOR
	LD	DE,5	     ;4 DEV. + IDENT.
ASS0:	CP	(HL)	     ;LOOK FOR MATCH
	JR	Z,ASS1
	ADD	HL,DE	     ;GO THRU TABLE
	INC	C	     ;KEEP TRACK OF DEVICE
	DJNZ	ASS0
	JR	ASERR	     ;WRONG IDENTIFIER
ASS1:	LD	E,C	     ;SAVE DEVICE NUMBER
ASS2:	CALL	TI	     ;SCAN PAST '='
	CP	'='
	JR	NZ,ASS2
	CALL	TI	     ;GET NEW ASSIGNMENT
	LD	BC,400H	     ;4 POSSIBLE ASSIGNMENTS
ASS3:	INC	HL	     ;POINT TO ASSIGNMENT NAME
	CP	(HL)	     ;LOOK FOR PROPER MATCH
	JR	Z,ASS4	     ;MATCH FOUND
	INC	C	     ;KEEP TRACK OF ASSIGNMENT NMBR
	DJNZ	ASS3
ASERR:	JP	ERROR	     ;NO MATCH, ERROR
ASS4:	LD	A,3	     ;SET UP A MASK
	INC	E
ASS5:	DEC	E	     ;DEVICE IN E
	JR	Z,ASS6	     ;GOT IT
	SLA	C	     ;ELSE MOVE MASKS
	SLA	C
	RLA	
	RLA		     ;A=DEVICE MASK
	JR	ASS5
ASS6:	CPL		     ;INVERT FOR AND'ING
	LD	D,A	     ;SAVE IN D
ASS7:	CALL	PCHK	     ;WAIT FOR [CR]
	JR	NC,ASS7
	CALL	IOCHK	     ;GET PRESENT CONFIGURATION
	AND	D	     ;MODIFY ONLY SELECTED DEVICE
	OR	C	     ;'OR' NEW BIT PATTERN
	LD	C,A	     ;NEW CONFIGURATION
;
; THIS ALLOWS USER PROGRAMS TO MODIFY
; THE I/O CONFIGURATIMN DYNAMICALLY
; DURING EXECUTION.
;
IOSET:	LD	A,C	     ;NEW I/O BYTE PASSED IN C REG
;	CPL		     ;WE SAVE THE INVERTED BYTE
;	OUT	(IOBYT),A    ;IN AN I/O PORT LATCH
	LD	(IOBYT),A    ;SAVE NEW I/O BYTE IN MEMORY
	RET	
;
; THIS RETURNS THE CURRENT I/O
; CONFIGURATION IN THE A REG.
;
IOCHK:	;IN	A,(IOBYT)    ;GET SAVED VALUE
;	CPL		     ;AND INVERT IT AGAIN
	LD	A,(IOBYT)    ;GET SAVED VALUE
	RET	
;
; THIS ROUTINE IS USED AS A SIMPLE MEANS TO PREVENT
; UNAUTHORIZED SYSTEM OPERATION. THE SYSTEM LOCKS UP,
; MONITORING FOR A 'CONT.-SHIFT-N', AT WHICH TIME IT
; WILL SIGN-ON AGAIN. NO REGISTER ASSIGNMENTS OR I/O
; CONFIGURATIONS WILL BE ALTERED.
;
BYE:	CALL	CRLF
BY1:	CALL	KI
	CP	1EH	     ;CONTROL-SHIFT-N
	JR	NZ,BY1
	POP	DE	     ;REMOVE THE RETURN
	JP	HELLO	     ;AND SIGN-ON AGAIN
;
; THIS ALLOWS ENTERING OF ASCII TEXT INTO MEMORY
; FROM THE CONSOLE DEVICE. THE PARITY BIT IS CLEARED,
; AND ALL WILL BE STORED EXCEPT THE BACK-ARROR [_]
; WHICH DELETES THE PREVIOUS CHARACTER, AND
; CONTROL-D, WHICH RETURNS CONTROL TO THE MONITOR.
; THIS COMMAND, COMBINED WITH THE 'Y' COMMAND,
; PROVIDES A RUDIMENTARY TEXT PROCESSING ABILITY.
;
PUTA:	CALL	EXPR1	     ;GET THE STARTING ADDR.
	CALL	CRLF
	POP	HL
PUTA1:	CALL	KI	     ;GET A CHARACTER
	CP	4	     ;CONTROL-D? (EOT)
	JP	Z,LFADR	     ;YES, STOP & PRINT
	CP	'_'	     ;ERASE MISTAKE?
	JR	Z,PUTA3	     ; YES.
	LD	(HL),A	     ;ELSE STORE IT IN MEMORY
	LD	C,A
	INC	HL
PUTA2:	CALL	CO	     ;ECHO ON CONSOLE
	JR	PUTA1
PUTA3:	DEC	HL
	LD	C,(HL)
	JR	PUTA2	     ;ECHO & CONTINUE
;
; THIS ROUTINE COMPARES THE READER INPUT
; DEVICE WITH THE MEMORY BLOCK SPECIFIED.
; IT TESTS ALL EIGHT BITS, AND ANY DISCREPENCIES
; WILL BE OUTPUT TO THE CONSOLE. THIS IS USEFUL
; WHEN USED WITH THE BINARY DUMP FORMAT TO BOTH
; VERIFY PROPER READING & STORAGE, OR TO DETECT
; PROGRAM CHANGES SINCE IT WAS LAST LOADED.
;
COMP:	CALL	EXLF	     ;GET START ' STOP ADDR.
COM1:	CALL	RIFF	     ;GET A FULL READER BYTE
	CP	(HL)	     ;8 BIT COMPARE
	CALL	NZ,CERR	     ;CALL IF INVALID COMPARE
	CALL	HILOX	     ;SEE IF RANGE SATISFIED
	JR	COM1
;
; THIS SUBROUTINE IS USED TO DISPLAY THE
; CURRENT LOCATION OF THE 'M' REGISTER POINTER (HL),
; AND THE VALUE AT THE LOCATION, AND THE CONTENTS
; OF THE ACCUMULATOR. USED BY TWO ROUTINES.
;
CERR:	LD	B,A	     ;SAVE ACC.
	CALL	HLSP	     ;DISPLAY H&L
	LD	A,(HL)
	CALL	LBYTE	     ;PRINT 'M'
	CALL	BLK	     ;SPACE OVER
	LD	A,B
	CALL	LBYTE	     ;PRINT ACC.
	JP	CRLF	     ;CRLF & RETURN
;
; THIS DISPLAYS THE CONTENTS OF MEMORY IN BASE HEX
; WITH THE STARTING LOCATION ON EACH LINE. (BETWEEN
; THE TWO PARAMETERS GIVEN). 16 BYTES PER LINE MAX.
;
DISP:	CALL	EXLF	     ;GET DISPLAY RANGE
DIS0:	CALL	LFADR	     ;CRLF & PRINT ADDR.
DIS1:	CALL	BLK	     ;SPACE OVER
	LD	A,(HL)
	CALL	LBYTE
	CALL	HILOX	     ;RANGE CHECK
	LD	A,L
	AND	0FH	     ;SEE IF TIME TO CRLF
	JR	NZ,DIS1
	JR	DIS0
;
; THIS OUTPUTS THE END OF FILE (EOF) PATTERN
; FOR THE CHECKSUM LOADER.  IT IS USED AFTER
; PUNCHING A BLOCK OF MEMORY WITH THE 'W'
; COMMAND.  AN ADDRESS PARAMETER MAY BE GIVEN,
; AND UPON READING, THIS ADDRESS WILL BE
; AUTOMATICALLY PLACED IN THE 'P' COUNTER. THE
; PROGRAM CAN THEN BE RUN WITH A SIMPLE 'G[CR]'
; COMMAND.
;
EOF:	CALL	EXPR1	     ;GET OPTIONAL ADDR.
	CALL	PEOL	     ;CRLF TO PUNCH
	LD	C,':'	     ;FILE MARKER CUE
	CALL	PUO
	XOR	A	     ;ZERO LENGTH
	CALL	PBYTE
	POP	HL
	CALL	PADR	     ;PUNCH OPTIONAL ADDR.
	LD	HL,0	     ;FILE TYPE=0
	CALL	PADR	     ;PUNCH IT
	JP	NULL	     ;TRAILER & RETURN
;
; THIS COMMAND WILL FILL A BLOCK OF MEMORY
; WITH A VALUE. IE: FO,1FFF,0 FILLS FROM
; <1> TO <2> WITH THE BYTE <3>. HANDY FOR
; INITIALIZING A BLOCK TO A SPECIFIC VALUE, OR
; MEMORY TO A CONSTANT VALUE BEFOR LOADING
; A PROGRAM.  (ZERO IS ESPECIALLY USEFUL.)
;
FILL:	CALL	EXPR3	     ;GET 3 PARAMETERS
FI1:	LD	(HL),C	     ;STORE THE BYTE
	CALL	HILO
	JR	NC,FI1
	POP	DE	     ;RESTORE STACK
	JP	START	     ; IN CASE OF ACCIDENTS
;
; THIS COMMAND ALLOWS EXECUTION OF ANOTHER
; PROGRAM WHILE RETAINING SOME MONITOR
; CONTROL BY SETTING BREAKPOINTS.
;
; TO SIMPLY EXECUTE, TYPE 'G<ADDR>[CR]'. TO SET
; A BREAKPOINT TRAP, ADD THE ADDRESS(ES) TO THE
; COMMAND. IE: G<ADDR>,<BKPT>[CR]. TWO BREAKPOINTS
; ARE ALLOWED, ENOUGH TO SATISFY MOST REQUIREMENTS.
; ONCE A BREAKPOINT HAS BEEN REACHED, THE
; REGISTERS MAY BE EXAMINED OR MODIFIED. THE
; PROGRAM CAN THEN BE CONTINUED BY TYPING ONLY
; A 'G[CR]'. OR ANOTHER BREAKPOINT COULD BE
; IMPLEMENTED AT THAT TIME BY TYPING 'G,<BKPT>[CR]'.
;
; *NOTE: THIS IS SOFTWARE CONTROLLED, AND THE
; BREAKPOINT MUST OCCUR ON AN INSTRUCTION
; BYTE.
;
GOTO:	CALL	PCHK	     ;GET A POSSIBLE ADDRESS
	JR	C,GOT3	     ;CR ENTERED
	JR	Z,GOT0	     ;DELIMITER ENTERED
	CALL	EXF	     ;GET ONE EXPRESSION
	POP	DE
	LD	HL,PLOC	     ;PLACE ADDRESS IN 'P' LOCATION
	ADD	HL,SP
	LD	(HL),D	     ;HIGH BYTE
	DEC	HL
	LD	(HL),E	     ;LOW BYTE
	LD	A,B
	CP	CR	     ;SEE IF LAST CHARACTER WAS A CR
	JR	Z,GOT3	     ;YES, LEAVE
GOT0:	LD	D,2	     ;TWO BREAKPOINTS MAX
	LD	HL,TLOC	     ;POINT TO TRAP STORAGE
	ADD	HL,SP
GOT1:	PUSH	HL	     ;SAVE STORAGE POINTER
	CALL	EXPR1	     ;GET A TRAP ADDRESS
	LD	E,B	     ;SAVE DELIMITER
	POP	BC	     ;TRAP ADDR.
	POP	HL	     ;STORAGE
	LD	A,B	     ;LOOK AT TRAP ADDR
	OR	C
	JR	Z,GOT2	     ;DON'T SET A TRAP AT 0
	LD	(HL),C	     ;SAVE BKPT ADDR
	INC	HL
	LD	(HL),B
	INC	HL
	LD	A,(BC)	     ;PICK UP INST. BYTE
	LD	(HL),A	     ;SAVE THAT TOO
	INC	HL
	LD	A,0FFH	     ;RST 7
	LD	(BC),A	     ;SOFTWARE INTERUPT
GOT2:	LD	A,E	     ;LOOK AT DELIMITER
	CP	CR
	JR	Z,GOT2A
	DEC	D	     ;COUNT BKPTS
	JR	NZ,GOT1	     ;GET ONE MORE
GOT2A:	LD	A,0C3H	     ;SET UP JUMP INSTRUCTION
	LD	(RST7),A     ; AT RESTART TRAP LOC.
	LD	HL,TRAP	     ; TO MONITOR VECTOR
	LD	(RST7+1),HL
GOT3:	CALL	CRLF
	POP	DE	     ;CLEAR SYSTEM RETURN
	LD	HL,22	     ;FIND 'EXIT' ROUTINE
	ADD	HL,SP	     ;UP IN STACK
	JP	(HL)	     ;GO SOMPLACE
;
; THIS IS A 'QUICKIE' MEMORY TEST TO SPOT
; HARD MEMORY FAILURES, OR ACCIDENTLY
; PROTECTED MEMORY LOCATIONS. IT IS NOT
; MEANT TO BE THE DEFINITIVE MEMORY DIAGNOSTIC.
; IT IS, HOWEVER, NON-DESTRUCTIVE. ERRORS ARE
; PRINTED ON THE CONSOLE AS FOLLOWS-
; <ADDR> 00000100 WHERE <1> IS THE BAD BIT.
; BIT LOCATION OF THE FAILURE IS EASILY
; DETERMINED. NON-R/W MEMORY WILL RETURN
; WITH- 11111111
;
TEST:	CALL	EXLF	     ;GET TWO PARAMS
TEST1:	LD	A,(HL)	     ;READ A BYTE
	LD	B,A	     ;SAVE IN B REG.
	CPL	
	LD	(HL),A	     ;READ/COMPLIMENT/WRITE
	XOR	(HL)	     ; & COMPARE
	JR	Z,TEST2	     ;SKIP IF ZERO (OK)
	PUSH	DE	     ;SAVE END POINTER
	LD	D,B	     ;SAVE BYTE
	LD	E,A	     ;SET-UP TO DISPLAY
	CALL	HLSP	     ;PRINT BAD ADDR
	CALL	BITS	     ;PRINT BAD BIT LOC.
	CALL	CRLF
	LD	B,D	     ;RESTORE BYTE
	POP	DE	     ;RESTORE DE
TEST2:	LD	(HL),B	     ;REPLACE BYTE
	CALL	HILOX	     ;RANGE TEST
	JR	TEST1
;
; THIS COMMAND MOVES MASS AMOUNTS OF MEMORY
; FROM <1> THRU <2> TO THE ADDRESS STARTING
; AT <3>.  THIS ROUTINE SHOULD BE USED WITH
; SOME CAUTION, AS IT COULD SMASH MEMORY IF
; CARLESSLY IMPLEMENTED.
;
;	M<1>,<2>,<3>
;
MOVE:	CALL	EXPR3	     ;GET 3 PARAMETERS
MO1:	LD	A,(HL)	     ;PICK UP
	LD	(BC),A	     ;PUT DOWN
	INC	BC	     ;MOVE UP
	CALL	HILOX	     ;CHECK IF DONE
	JR	MO1
;
; THIS COMMAND READS THE CHECK-SUMMED HEX FILES
; FOR BOTH THE NORMAL INTEL FORMAT AND THE TDL
; RELOCATING FORMAT. ON BOTH FILES, A 'BIAS' MAY
; BE ADDED, WHICH WILL CAUSE THE OBJECT CODE TO
; BE PLACED IN A LOCATION OTHER THAN ITS
; INTENDED EXECUTION LOCATION. THE BIAS IS ADDED
; TO WHAT WOULD HAVE BEEN THE NORMAL LOADING
; LOCATION, AND WILL WRAP AROUND TO ENABLE
; LOADING ANY PROGRAM ANYWHERE IN MEMORY.
;
; WHEN LOADING A RELOCATABLE FILE, AN ADDITIONAL
; PARAMETER MAY BE ADDED, WHICH REPRESENTS THE
; ACTUAL EXECUTION ADDRESS DESIRED. THIS ALSO MAY
; BE ANY LOCATION IN MEMORY.
;
; EXAMPLES:
;
; R[CR] =0 BIAS, 0 EXECUTION ADDR.
; R<ADDR1>[CR] =<1>BIAS, 0 EXECUTION ADDR.
; R,<ADDR1>[CR] =0 BIAS, <1> EXECUTION ADDR.
; R<ADDR1>,<ADDR2>[CR] =<1>BIAS, <2>EXECUTION ADDR.
;
READ:	CALL	EXPR1	     ;GET BIAS, IF ANY
	LD	A,B	     ;LOOK AT DELIMITER
	SUB	CR	     ;ALL DONE?
	LD	B,A	     ;SET UP RELOCATION OF 0
	LD	C,A	     ; IF CR ENTERED
	POP	DE	     ;BIAS AMOUNT
	JR	Z,REA0	     ;CR ENTERED
	CALL	EXPR1	     ;GET RELOCATION
	POP	BC	     ;ACTUAL RELOCATION VALUE
REA0:	EX	DE,HL
	EXX		     ;HL'=BIAS, BC'=RELOCATION
	CALL	CRLF
LOD0:	CALL	RIX	     ;GET A CHARACTER
	SUB	':'	     ;ABSOLUTE FILE CUE?
	LD	B,A	     ;SAVE CUE CLUE
	AND	0FEH	     ;KILL BIT 0
	JR	NZ,LOD0	     ; NO, KEEP LOOKING
	LD	D,A	     ;ZERO CHECKSUM
	CALL	SBYTE	     ;GET FILE LENGTH
	LD	E,A	     ;SAVE IN E REG.
	CALL	SBYTE	     ;GET LOAD MSB
	PUSH	AF	     ;SAVE IT
	CALL	SBYTE	     ;GET LOAD LSB
	EXX		     ;CHANGE GEARS
	POP	DE	     ;RECOVER MSB
	LD	E,A	     ;FULL LOAD ADDR
	PUSH	BC	     ;BC'=RELOCATION
	PUSH	DE	     ;DE'=LOAD ADDR
	PUSH	HL	     ;HL'=BIAS
	ADD	HL,DE	     ; BIAS+LOAD
	EX	(SP),HL	     ;RESTORE HL'
	POP	IX	     ; X=BIAS+LOAD
	EXX		     ;DOWNSHIFT
	POP	HL	     ;HL=LOAD ADDR
	CALL	SBYTE	     ;GET FILE TYPE
	DEC	A	     ;1=REL. FILE, 0=ABS.
	LD	A,B	     ;SAVE CUE BIT
	POP	BC	     ;BC=RELOCATION
	JR	NZ,ABS0      ;ABSOLUTE FILE
	ADD	HL,BC	     ;ELSE RELOCATE
	ADD	IX,BC	     ;BOTH X & HL
ABS0:	INC	E	     ;TEST LENGHT
	DEC	E	     ;0=DONE
	JR	Z,DONE
	DEC	A	     ;TEST CUE
	JR	Z,LODR	     ;RELATIVE
LLO1:	CALL	SBYTE	     ;NEXT
	CALL	STORE	     ;STORE IT
	JR	NZ,LLO1	     ;MORE COMING
LOD4:	CALL	SBYTE	     ;GET CHECKSUM
	JR	Z,LOD0	     ;GOOD CHECKSUM
ERR3:	PUSH	IX
	POP	HL	     ;TRANSFER
	CALL	LADR	     ;PRINT CURRENT LOAD ADDR
ERR2:	JP	ERROR	     ;ABORT
DONE:	LD	A,H	     ;DON'T MODIFY IF ZERO
	OR	L
	RET	Z
	EX	DE,HL	     ;ELSE STORE IN PC
	LD	HL,PLOC
	ADD	HL,SP
	LD	(HL),D	     ;IN STACK AREA
	DEC	HL
	LD	(HL),E
	RET	
LODR:	LD	L,1	     ;SET-UP BIT COUNTER
LOD1:	CALL	LODCB	     ;GET THE BIT
	JR	C,LOD3	     ;DOUBLE BIT
LOD5:	CALL	STORE	     ;WRITE IT
	JR	NZ,LOD1
	JR	LOD4	     ;TEST CHECKSUM
LOD3:	LD	C,A	     ;SAVE LOW BYTE
	CALL	LODCB	     ;NEXT CONTROL BIT
	LD	B,A	     ;SAVE HIGH BYTE
	EXX	
	PUSH	BC	     ;GET RELOCATION
	EXX	
	EX	(SP),HL	     ;INTO HL
	ADD	HL,BC	     ;RELOCATE
	LD	A,L	     ;LOW BYTE
	CALL	STORE	     ;STORE IT
	LD	A,H	     ;HIGH BYTE
	POP	HL	     ;RESTORE HL
	JR	LOD5	     ;DO THIS AGAIN
LODCB:	DEC	L	     ;COUNT BITS
	JR	NZ,LC1	     ;MORE LEFT
	CALL	SBYTE	     ;GET NEXT
	DEC	E	     ;COUNT BYTES
	LD	H,A	     ;SAVE THE BITS
	LD	L,8	     ;8 BITS/BYTE
LC1:	CALL	SBYTE	     ;GET A DATA BYTE
	SLA	H	     ;TEST NEXT BIT
	RET	
SBYTE:	PUSH	BC	     ;PRESERVE BC
	CALL	RIBBLE	     ;GET A CONVERTED ASCII CHAR.
	RLCA	
	RLCA	
	RLCA	
	RLCA		     ;MOVE IT TO HIGH NIBBLE
	LD	C,A	     ;SAVE IT
	CALL	RIBBLE	     ;GET OTHER HALF
	OR	C	     ;MAKE WHOLE
	LD	C,A	     ;SAVE AGAIN IN C
	ADD	A,D	     ;UPDATE CHECKSUM
	LD	D,A	     ;NEW CHECKSUM
	LD	A,C	     ;CONVERTED BYTE
	POP	BC
	RET	
STORE:	LD	(IX+0),A     ;WRITE TO MEMORY
	CP	(IX+0)	     ;VALID WRITE?
	JR	NZ,ERR3	     ; NO.
	INC	IX	     ;ADVANCE POINTER
	DEC	E	     ;COUNT DOWN
	RET	
;
; THIS ROUTINE ALLOWS BOTH INSPECTION OF &
; MODIFICATION OF MEMORY ON A BYTE BY BYTE
; BASIS. IT TAKES ONE ADDRESS PARAMETER,
; FOLLOWED BY A SPACE.  THE DATA AT THAT
; LOCATION WILL BE DISPLAYED. IF IT IS
; DESIRED TO CHANGE IT, THE VALUE IS THEN
; ENTERED.  A FOLLOWING SPACE WILL DISPLAY
; THE NEXT BYTE.  A CARRIAGE RETURN [CR]
; WILL TERMINATE THE COMMAND.  THE SYSTEM
; ADDS A CRLF AT LOCATIONS ENDING WITH EITHER
; XXX0 OR XXX8. TO AID IN DETERMINING THE
; PRESENT ADDRESS, IT IS PRINTED AFTER
; EACH CRLF.  A BACKARROW [_] WILL BACK
; UP THE POINTER AND DISPLAY THE
; PREVIOUS LOCATION.
;
SUBS:	CALL	EXPR1	     ;GET STARTING ADDR
	POP	HL
SUB0:	LD	A,(HL)
	CALL	LBYTE	     ;DISPLAY THE BYTE
	CALL	COPCK	     ;MODIFY?
	RET	C	     ; NO, ALL DONE
	JR	Z,SUB1	     ;DON'T MODIFY
	CP	05FH	     ;BACKUP?
	JR	Z,SUB2
	PUSH	HL	     ;SAVE POINTER
	CALL	EXF	     ;GET NEW VALUE
	POP	DE	     ;VALUE IN E
	POP	HL
	LD	(HL),E	     ;MODIFY
	LD	A,B	     ;TEST DELIMITER
	CP	CR
	RET	Z	     ;DONE
SUB1:	INC	HL
SUB3:	LD	A,L	     ;SEE IF TIME TO CRLF
	AND	7
	CALL	Z,LFADR	     ;TIME TO CRLF
	JR	SUB0
SUB2:	DEC	HL	     ;DECREMENT POINTER
	JR	SUB3	     ;AND PRINT DATA THERE.
;
; THIS ROUTINE TRANSLATES THE DATA IN
; MEMORY TO AN ASCII FORMAT.  ALL NON-
; PRINTING CHARACTERS ARE CONVERTED TO
; PERIODS. [.]
; THERE ARE 64 CHARACTERS PER LINE.
;
TYPE:	CALL	EXLF	     ;DISPLAY RANGE
TYP0:	CALL	LFADR	     ;DISPLAY ADDRESS
	LD	B,64	     ;CHARACTERS PER LINE
TYP1:	LD	A,(HL)
	AND	7FH	     ;KILL PARITY BIT
	CP	' '	     ;RANGE TEST
	JR	NC,TYP3	     ;=>SPACE
TYP2:	LD	A,'.'	     ;REPLACE NON-PRINTING
TYP3:	CP	07CH	     ;ABOVE LOWER CASE Z
	JR	NC,TYP2
	LD	C,A	     ;SEND IT
	CALL	CO
	CALL	HILOX	     ;MORE TO GO?
	DJNZ	TYP1	     ;SEE IF TIME TO CRLF
	JR	TYP0	     ;YES
;
; THIS IS A HEXADECIMAL SEARCH ROUTINE. IT
; TAKES NO ADDRESS PARAMETERS. AS MANY
; BYTES MAY BE ENTERED, SEPARATED BY A COMMA,
; AS DESIRED.  THE MAXIMUM IS 255, BUT 3-4 IS
; TYPICAL, AND MORE THAN 12 WOULD BE UNUSUAL.
; THE ENTIRE MEMORY IS SEARCHED STARTING
; FROM ZERO, AND ALL STARTING ADDRESSES OF EACH
; OCCURANCE OF THE SEARCH STRING ARE PRINTED
; ON THE CONSOLE DEVICE.
;
WHERE:	LD	D,0	     ;COUNT SEARCH STRING
WHER0:	CALL	EXPR1	     ;GET ONE BYTE
	POP	HL	     ;PICK IT UP
	LD	H,L	     ;STICK IN HIGH BYTE
	PUSH	HL	     ;PUT IT IN STACK
	INC	SP	     ;ADJUST STACK
	INC	D	     ;COUNT UP
	LD	A,B	     ;TEST DELIMITER
	SUB	CR
	JR	NZ,WHER0     ;MORE TO GO
	LD	B,A	     ;CHEAP ZEROS
	LD	C,A
	LD	H,A
	LD	L,D	     ;GET BYTE COUNT IN L
	DEC	L	     ;-1
	ADD	HL,SP	     ;BYTES STORED IN STACK
	PUSH	HL
	PUSH	BC
FINDC:	PUSH	BC	     ;SAVE THAT POINTER
	CALL	CRLF
	POP	BC	     ;RESTORE
FIND:	POP	HL	     ;HL=SEARCH ADDR
	POP	IX	     ;X=SEARCH BYTE POINTER
	LD	E,D	     ;RESET COUNTER
	LD	A,(IX+0)     ;GET THE FIRST SEARCH BYTE
	CPIR		     ;COMPARE, INCR., & REPEAT
	JP	PO,DONE	     ;ODD PARITY=DONE
	PUSH	IX	     ;SAVE POINTERS
	PUSH	HL
FOUND:	DEC	E
	JR	Z,TELL	     ;FOUND ALL
	LD	A,(IX+-1)    ;LOOK AT NEXT MATCH
	CP	(HL)	     ;TEST NEXT
	JR	NZ,FIND	     ;NO MATCH
	INC	HL	     ;BUMP POINTERS
	DEC	IX
	JR	FOUND	     ;TEST NEXT MATCH
TELL:	POP	HL
	PUSH	HL
	DEC	HL
	PUSH	BC	     ;SAVE SEARCH COUNT LIMIT
	CALL	LADR	     ;TELL CONSOLE
	POP	BC	     ;RESTORE
	JR	FINDC
DONE2:	INC	SP
	DEC	E	     ;RESET STACK
	JR	NZ,DONE2
	RET	
;
; THIS ROUTINE DUMPS MEMORY IN THE STANDARD
; INTEL HEX-FILE FORMAT.  A START & END
; PARAMETER IS REQUIRED. AT THE CONCLUSION
; OF THE DUMP, AN "END OF FILE" SHOULD BE
; GENERATED WITH THE "E" COMMAND.
;
WRITE:	CALL	EXLF	     ;GET TWO PARAMETERS
	CALL	WAIT	     ;PAUSE IF TTY CONFIGURATION
WRT0:	CALL	PEOL	     ;CRLF TO PUNCH
	LD	BC,':'	     ;START OF FILE
	CALL	PUO	     ;PUNCH IT
	PUSH	DE	     ;SAVE
	PUSH	HL	     ;POINTERS
WRT1:	INC	B	     ;CALCULATE FILE LENGTH
	CALL	HILO
	JR	C,WRT4	     ;SHORT FILE
	LD	A,24	     ;24 BYTES PER FILE
	SUB	B	     ;ENOUGH YET?
	JR	NZ,WRT1	     ; NO.
	POP	HL	     ;GET START ADDR BACK.
	CALL	WRT2	     ;SEND THE BLOCK
	POP	DE	     ;RESTORE END OF FILE POINTER
	JR	WRT0	     ;KEEP GOING
WRT2:	LD	D,A	     ;INITIALIZE CHECKSUM
	LD	A,B	     ;FILE LENGTH
	CALL	PBYTE	     ;PUNCH IT
	CALL	PADR	     ;PUNCH ADDRESS
	XOR	A	     ;FILE TYPE=0
	CALL	PBYTE	     ;PUNCH IT
WRT3:	LD	A,(HL)	     ;GET A DATA BYTE
	CALL	PBYTE	     ;PUNCH IT
	INC	HL	     ;POINT TO NEXT BYTE
	DJNZ	WRT3	     ;DECREMENT FILE COUNT
	XOR	A
	SUB	D	     ;CALCULATE CHECKSUM
	JP	PBYTE	     ;PUNCH IT, RETURN
WRT4:	POP	HL	     ;CLEAR STACK
	POP	DE	     ; OF POINTERS
	XOR	A	     ;SET UP A
	JR	WRT2	     ;FINISH UP & RETURN
;
;
;	THIS ROUTINE ALLOWS DISPLAYING THE
; USER'S CPU REGISTERS. THEY ALSO MAY BE 
; USING THE REGISTER NAME AFTER TYPEING THE "X".
; I.E. XA 00-
; THE REGISTER MAY BE SKIPPED OVER, OR MODIFIED,
; SIMILARLY TO THE "S" COMMAND.
;
; TO DISPLAY THE "NORMAL" SYSTEM STATUS,
; SIMPLY TYPE "X[CR]".  TO DISPLAY THE
; ADDITIONAL Z-80 REGISTERS, FOLLOW
; THE "X" WITH AN APOSTROPHE.  I.E. "X'[CR]",
; OR TO EXAMINE A SINGLE "PRIME" REGISTER,
; TYPE THE REGISTER IDENTIFIER AFTER THE
; APOSTROPHE.  I.E.  X'X 0000-
;
; THESE REGISTER VALUES ARE PLACED INTO THE CPU
; UPON EXECUTING ANY "GO" COMMAND. [G]
;
XAM:	CALL	TI
	LD	HL,ACTBL
	CP	CR	     ;FULL REG. DISPLAY
	JR	Z,XAM6
	CP	27H	     ;SEE IF PRIMES WANTED
	JR	NZ,XAM0
	LD	HL,PRMTB
	CALL	TI
	CP	CR	     ;FULL REG. DISPLAY
	JR	Z,XAM6
XAM0:	CP	(HL)	     ;TEST FOR REGISTER NAME
	JR	Z,XAM1
	BIT	7,(HL)	     ;SEE IF END OF TABLE
	JP	NZ,ERROR
	INC	HL
	INC	HL
	JR	XAM0
XAM1:	CALL	BLK
XAM2:	INC	HL
	LD	A,(HL)
	LD	B,A	     ;SAVE FOR FLAGS
	AND	3FH	     ;CLEAR FLAGS FOR BIAS
	EX	DE,HL
	LD	L,A	     ;DISPLACEMENT FROM STACK
	LD	H,0
	ADD	HL,SP
	EX	DE,HL	
	INC	HL
	LD	A,(DE)	     ;PICK UP REG. VALUE
	CALL	LBYTE	     ;PRINT IT
	BIT	7,B
	JR	Z,XAM3
	DEC	DE
	LD	A,(DE)
	CALL	LBYTE
XAM3:	CALL	COPCK	     ;MODIFY
	RET	C	     ;CR ENTERED, ALL DONE
	JR	Z,XAM5	     ;SKIP TO NEXT REG.
	PUSH	HL
	PUSH	BC
	CALL	EXF	     ;GET NEW VALUE
	POP	HL
	POP	AF
	PUSH	BC
	PUSH	AF
	LD	A,L
	LD	(DE),A
	POP	BC
	BIT	7,B	     ;SEE IF 8 BIT OR 16 BIT REG.
	JR	Z,XAM4	     ;8 BIT
	INC	DE
	LD	A,H	     ;HIGH BYTE OF 16 BIT REG.
	LD	(DE),A
XAM4:	POP	BC
	POP	HL
	LD	A,B	     ;TEST DELIMITER
	CP	CR
	RET	Z	     ;CR ENTERED, ALL DONE
XAM5:	BIT	7,(HL)	     ;SEE IF END OF TABLE
	RET	NZ	     ;RETURN IF SO
	JR	XAM2
XAM6:	CALL	CRLF
XAM7:	CALL	BLK
	LD	A,(HL)
	INC	HL
	OR	A
	RET	M
	LD	C,A
	CALL	CO
	LD	C,'='
	CALL	CO
	LD	A,(HL)
	LD	B,A	     ;SAVE FLAGS
	AND	3FH	     ;CLEAR UP FOR OFFSET
	INC	HL
	EX	DE,HL
	LD	L,A
	LD	H,0
	ADD	HL,SP
	EX	DE,HL
	BIT	6,B	     ;TEST FOR SPECIAL "M"
	JR	NZ,XAM9	     ;PRINT OUT ACTUAL "M"
	LD	A,(DE)
	CALL	LBYTE	     ;PRINT REG. VALUE
	BIT	7,B	     ;SINGLE OR DOUBLE?
	JR	Z,XAM7	     ;SINGLE.
	DEC	DE
	LD	A,(DE)
XAM8:	CALL	LBYTE
	JR	XAM7
XAM9:	PUSH	HL	     ;SAVE HL
	LD	A,(DE)	     ;GET REG. POINTER
	LD	H,A	     ;HIGH BYTE
	DEC	DE
	LD	A,(DE)
	LD	L,A	     ;LOW BYTE
	LD	A,(HL)	     ;GET VALUE
	POP	HL	     ;RESTORE HL
	JR	XAM8	     ;PRINT VALUE & CONTINUE
;
; THIS IS A MESSAGE OUTPUT ROUTINE.
; IT IS USED BY THE SIGN-ON AND THE CRLF.
; POINTER IS IN HL (WHEN ENTERED AT
; TOM1) AND LENGTH IN B REG.
;
TOM:	LD	HL,MSG
TOM1:	LD	C,(HL)	     ;GET A CHARACTER
	INC	HL	     ;MOVE POINTER
	CALL	CO	     ;OUTPUT IT
	DJNZ	TOM1	     ;KEEP GOING TILL B=0
	CALL	CSTS	     ;SEE IF AN ABORT REQUEST
	OR	A	     ; WAITING
	RET	Z	     ;NO.
;
; SEE IF CONTROL-C IS WAITING
; ABORT IF SO.
;
CCHK:	CALL	KI
	CP	3	     ;CONTROL-C?
	RET	NZ
;
; SYSTEM ERROR ROUTINE. THIS
; WILL RESTORE THE SYTEM AFTER
; A SYSTEM ERROR HAS BEEN TAKEN.
; THE I/O CONFIGURATION IS NOT
; AFFECTED.
;
ERROR:	CALL	MEMSIZ
	LD	DE,-22	     ;STACK POINTER OFFSET
	ADD	HL,DE
	LD	SP,HL
	LD	C,'*'	     ;ANNOUNCE ERROR
	CALL	CO
	JP	START	     ;BACK TO WORK
;
; THIS GETS A READER CHARACTER,
; AND COMPARES IT WITH THE 'D' REG.
; IT ABORTS ON AN 'OUT-OF-DATA'
; CONDITION.
;
RIFF:	CALL	RI	     ;GET READER CHARACTER
	JR	C,ERROR	     ;ABORT ON CARRY
	CP	D	     ;TEST D
	RET	
;
; THIS ROUTINE WILL RETURN THE
; CURRENT VALUE OF THE HIGHEST
; READ/WRITE MEMORY LOCATION THAT
; IS AVAILABLE ON THE SYSTEM.
; IT WILL "SEARCH" FOR MEMORY
; STARTING AT THE BOTTOM OF MEMORY
; AND GO UPWARDS UNTIL NON-R/W MEMORY
; IS FOUND.
;
SIZE:	CALL	MEMSIZ	     ;GET THE VALUE
	LD	BC,ENDX-EXIT
	ADD	HL,BC	     ;ADJUST IT
;
;
; CRLF BEFORE HLSP ROUTINE
;
LFADR:	CALL	CRLF
;
; PRINT THE CURRENT VALUE OF H&L,
; AND A SPACE.
;
HLSP:	CALL	LADR
;
; PRINT A SPACE ON THE CONSOLE
;
BLK:	LD	C,' '
;
; THIS IS THE MAIN CONSOLE
; OUTPUT ROUTINE
;
CO:	CALL	IOCHK
	AND	~CMSK
	JR	NZ,CO0
;
; TELEPRINTER CONFIGURATION
; I/O DRIVER.
;
TTYOUT:	IN	A,(TTS)
	AND	TTYBE
	JR	Z,TTYOUT
	LD	A,C
	OUT	(TTO),A
	RET	
CO0:	DEC	A	     ;CCRT?
	JR	NZ,CO1	     ; NO.
;
; C.R.T. CONFIGURATION DRIVER.
;
CRTOUT:	IN	A,(CRTS)
	AND	CRTBE
	JR	NZ,CRTOUT
	LD	A,C
	OUT	(CRTO),A
	RET	
;
CO1:	DEC	A	     ;BATCH
	JP	NZ,COLOC     ; NO, MUST BE USER
;
; LIST OUTPUT DRIVER ROUTINE
; -A USER VECTORED ROUTINE, USED
; BY THE ASSEMBLER, ETC. ALSO,
; WHEN THE ASSIGNED MODE IS "BATCH",
; THIS IS THE ROUTINE USED FOR THE
; MONITOR OUTPUT THAT WOULD NORMALLY
; GO TO THE "CONSOLE".
;
LO:	CALL	IOCHK
	AND	~LMSK
	JR	Z,TTYOUT
	CP	LCRT
	JR	Z,CRTOUT
	CP	LINE
	JP	Z,LNLOC	     ;EXTERNAL VECTOR
	JP	LULOC	     ;USER DEFINED VECTOR
;
; SEND CRLF TO PUNCH DEVICE
;
PEOL:	LD	C,CR
	CALL	PUO
	LD	C,LF
;
; PUNCH OUTPUT DRIVER ROUTINE
;
PUO:	CALL	IOCHK
	AND	~PMSK
	JR	Z,TTYOUT     ;PUNCH=TELEPRINTER
	CP	PCAS	     ;CASSETTE?
	JR	NZ,PO1	     ; NO.
;
PO0:	IN	A,(PCASS)    ;CASSETTE DRIVER
	AND	PCSBE
	JR	NZ,PO0
	LD	A,C
	OUT	(PCASO),A
	RET	
;
PO1:	CP	PPTP
	JP	Z,PTPL	     ;EXTERNAL VECTOR
	JP	PULOC	     ;USER VECTOR
;
;
; THIS IS A BINARY DUMP ROUTINE THAT MAY BE
; USED WITH BOTH PAPER-TAPE AND/OR CASSETTE
; SYSTEMS.  IT PUNCHES A START-OF-FILE MARK
; AND THEN PUNCHES IN FULL 8-BITS DIRECTLY
; FROM MEMORY.  IT IS FOLLOWED BY AN END-OF-
; FILE MARKER. THESE DUMPS MAY BE LOADED
; USING THE "L" COMMAND. THEY ARE USEFUL
; FOR FAST LOADING, AND MAY BE VERIFIED
; USING THE "C" (COMPARE) COMMAND.
;
; U<A1>,<A2>[CR]
; PUNCHES FROM <A1> THRU <A2>
;
UNLD:	CALL	EXLF	     ;GET TWO PARAMETERS
	CALL	WAIT	     ;PAUSE FOR PUNCH-ON (TTY)
	CALL	LEAD	     ;PUNCH LEADER
	CALL	MARK	     ;PUNCH FILE MARKER
UNL:	LD	C,(HL)	     ;GET MEMORY BYTE
	CALL	PUO	     ;PUNCH IT
	CALL	HILO	     ;SEE IF DONE
	JR	NC,UNL
	CALL	MARK	     ;PUNCH END OF FILE MARKER
;
; THIS PUNCHES NULLS (LEADER/TRAILER).
; IT RETURNS "QUIET" IN CASE THE PUNCH
; AND CONSOLE ARE THE SAME.
;
NULL:	CALL	LEAD	     ;PUNCH NULLS
;
; THIS ROUTINE WILL PAUSE FOR
; A KEYBOARD CHARACTER. IT IS
; USED AS A DELAY TO GIVE THE
; OPERATOR TIME TO TURN ON THE
; TELEPRINTER PUNCH BEFORE SENDING
; A HEX FILE OR BINARY FILE TO
; THE PUNCH.  IT WILL SIMPLY
; RETURN IF THE PUNCH & CONSOLE
; ARE NOT BOTH ASSIGNED TO THE
; DEFAULT. (TELEPRINTER)
;
WAIT:	CALL	IOCHK
	AND	~CMSK | ~PMSK
	RET	NZ
	JP	STARO	     ;RETURN "QUIET"
;
; CONVERT HEX TO ASCII
;
CONV:	AND	0FH	     ;LOW NIBBLE ONLY
	ADD	A,90H
	DAA	
	ADC	A,40H
	DAA	
	LD	C,A
	RET	
;
; GET TWO PARAMETERS, PLACE
; THEM IN DE & HL, AND THEN
; CRLF.
;
EXLF:	CALL	EXPR
	POP	DE
	POP	HL
;
; CONSOLE CARRIAGE RETURN &
; LINE FEED ROUTINE.
;
; THE NUMBER OF FILL CHARACTERS
; MAY BE ADJUSTED TO 0-3 BY THE 
; VALUE PLACED IN THE B REG. MINIMUM
; VALUE FOR "B" IS TWO (2). MAXIMUM
; IS FIVE (5).
;
CRLF:	PUSH	HL	     ;SAVE HL
	LD	B,4	     ;CRLF LENGTH (SET FOR 2 FILLS)
	CALL	TOM	     ;SEND CRLF
	POP	HL
	RET	
;
; TEST THE CURRENT CONSOLES
; KEYBOARD FOR A KEY-PRESS.
; RETURN TRUE (0FFH IN A REG)
; IF THERE IS A CHARACTER
; WAITING IN THE UART.
;
CSTS:	CALL	IOCHK
	AND	~CMSK
	JR	NZ,CS0
	IN	A,(TTS)
	JR	CS1
CS0:	DEC	A	     ;CCRT
	JR	NZ,CS3
	IN	A,(CRTS)
CS1:	AND	TTYDA
	LD	A,FALSE
CS2:	RET	Z
	CPL	
	RET	
CS3:	DEC	A	     ;BATCH
	RET	Z
	JP	CSLOC	     ;USER DEFINED FUNCTION
;
; GET THREE PARAMETERS AND
; CRLF.
;
EXPR3:	INC	C
	CALL	EXPR
	CALL	CRLF
	POP	BC
	POP	DE
	POP	HL
	RET	
;
; GET ONE PARAMETER.
; NO CRLF.
;
EXPR1:	LD	C,1
;
; THIS IS THE MAIN "PARAMETER-GETTING" ROUTINE.
; THIS ROUTINE WILL ABORT ON A NON-HEX CHARACTER.
; IT TAKES THE MOST RECENTELY TYPED FOUR VALID
; HEX CHARACTERS, AND PLACES THEM UP ON THE STACK.
; (AS ONE 16 BIT VALUE, CONTAINED IN TWO
; 8-BIT BYTES.)  IF A CARRIAGE RETURN IS ENTERED,
; IT WILL PLACE THE VALUE OF "0000" IN THE STACK.
;
EXPR:	LD	HL,0	     ;INITIALIZE HL TO ZERO
EX0:	CALL	TI	     ;GET SOMETHING FROM CONSOLE
EX1:	LD	B,A	     ;SAVE IT
	CALL	NIBBLE	     ;CONVERT ASCII TO HEX
	JR	C,EX2	     ;ILLEGAL CHARACTER DECTECTED
	ADD	HL,HL	     ;MULTIPLY BY 16
	ADD	HL,HL
	ADD	HL,HL
	ADD	HL,HL
	OR	L	     ;OR IN THE SINGLE NIBBLE
	LD	L,A
	JR	EX0	     ;GET SOME MORE
EX2:	EX	(SP),HL	     ;SAVE UP IN STACK
	PUSH	HL	     ;REPLACE THE RETURN
	LD	A,B	     ;TEST THE DELIMITER
	CALL	QCHK
	JR	NC,EX3	     ;CR ENTERED
	DEC	C	     ;SHOULD GO TO ZERO
	RET	Z	     ; RETURN IF IT DOES
EX3:	JP	NZ,ERROR     ;SOMETHING WRONG
	DEC	C	     ;DO THIS AGAIN?
	JR	NZ,EXPR	     ; YES.
	RET		     ;ELSE RETURN
EXF:	LD	C,1
	LD	HL,0
	JR	EX1
;
; RANGE TESTING ROUTINES.
; CARRY SET INDICATES RANGE EXCEEDED.
;
HILOX:	CALL	HILO
	RET	NC	     ;OK
	POP	DE	     ;RETURN ONE LEVEL BACK
	RET	
;
HILO:	INC	HL	     ;INCREMENT HL
	LD	A,H	     ;TEST FOR CROSSING 64K BORDER
	OR	L
	SCF		     ;CARRY SET=STOP
	RET	Z	     ;YES, BORDER CROSSED
	LD	A,E	     ;NOW, TEST HL VS. DE
	SUB	L
	LD	A,D
	SBC	A,H
	RET		     ;IF CARRY WAS SET, THEN STOP
;
;	HEXADECIMAL MATH ROUTINE
;
; THIS ROUTINE IS USEFUL FOR
; DETERMINING RELATIVE JUMP
; OFFSETS.  IT RETURNS THE SUM
; & DIFFERENCE OF TWO PARAMETERS.
;
;  H<X>,<Y>
;
; X+Y   X-Y
;
HEXN:	CALL	EXLF
	PUSH	HL	     ;SAVE HL FOR LATER
	ADD	HL,DE	     ;GET SUM
	CALL	HLSP	     ;PRINT IT
	POP	HL	     ;THIS IS LATER
	OR	A	     ;CLEAR CARRY
	SBC	HL,DE	     ;GET DIFFERENCE & PRINT IT
;
; PRINT H&L ON CONSOLE
;
LADR:	LD	A,H
	CALL	LBYTE
	LD	A,L
LBYTE:	PUSH	AF
	RRCA	
	RRCA	
	RRCA	
	RRCA	
	CALL	LAD
	POP	AF
LAD:	CALL	CONV
	JP	CO
; THIS ROUTINE SENDS EIGHT RUBOUTS
; TO THE PUNCH DEVICE.
;
MARK:	LD	BC,08FFH     ;SET-UP B&C
	JR	LE0
;
; THIS ROUTINE SENDS BLANKS TO THE
; PUNCH DEVICE.
;
LEAD:	LD	BC,4800H     ;PRESET SOME NULLS
LE0:	CALL	PUO
	DJNZ	LE0
	RET	
;
; THIS ROUTINE RETURNS TO A USER
; PROGRAM THE CURRENT TOP OF
; MEMORY VALUE MINUS WORKSPACE
; AREA USED BY THE MONITOR.
;
MEMCK:	PUSH	HL
	CALL	MEMSIZ
	LD	A,L
	SUB	2CH
	JR	NC,MEMC
	DEC	H
MEMC:	LD	B,H
	POP	HL
	RET	
;
; THIS IS A CALLED ROUTINE USED
; TO CALCULATE THE TOP OF MEMORY
; STARTING FROM THE BOTTOM OF
; MEMORY, AND SEARCHING UPWARD UNTIL
; FIRST R/W MEMORY IS FOUND, AND THEN
; CONTINUING UNTIL THE END OF THE R/W
; MEMORY. THIS ALLOWS R.O.M. AT ZERO,
; AND INSURES A CONTINUOUS MEMORY BLOCK
; HAS BEEN FOUND.
; IT IS USED BY THE ERROR ROUTINE TO
; RESET THE STACK POINTER AS WELL.
;
MEMSIZ:	PUSH	BC
	LD	BC,BASE	     ;POINT TO START OF MONITOR
	LD	HL,-1	     ;RAM SEARCH STARTING PT.
MEM0:	INC	H	     ;FIRST FIND R/W MEMORY
	LD	A,(HL)
	CPL	
	LD	(HL),A
	CP	(HL)
	CPL	
	LD	(HL),A
	JR	NZ,MEM0
MEM1:	INC	H	     ;R/W FOUND, NOW FIND END
	LD	A,(HL)
	CPL	
	LD	(HL),A
	CP	(HL)
	CPL	
	LD	(HL),A
	JR	NZ,MEM2
	LD	A,H	     ;TEST FOR MONITOR BORDER
	CP	B
	JR	NZ,MEM1	     ;NOT THERE YET
MEM2:	DEC	H	     ;BACK UP, SUBTRACT WORKSPACE
	LD	BC,EXIT-ENDX
	ADD	HL,BC
	POP	BC	     ;RESTORE BC
	RET		     ;VALUE IN HL
;
;
RIBBLE:	CALL	RIX
NIBBLE:	SUB	'0'	     ;QUALIFY & CONVERT
	RET	C	     ;<0
	CP	'G'-'0'	     ;>F?
	CCF		     ;PERVERT CARRY
	RET	C
	CP	10	     ;NMBR?
	CCF		     ;PERVERT AGAIN
	RET	NC	     ;RETURN CLEAN
	SUB	'A'-'9'-1    ;ADJUST
	CP	0AH	     ;FILTER ":" THRU "@"
	RET	
;
; SEND H&L VALUE TO PUNCH DEVICE
;
PADR:	LD	A,H
	CALL	PBYTE
	LD	A,L
;
; PUNCH A SINGLE BYTE
;
PBYTE:	PUSH	AF	     ;NIBBLE AT A TIME
	RRCA	
	RRCA	
	RRCA	
	RRCA	
	CALL	CONV
	CALL	PUO
	POP	AF	     ;NEXT NIBBLE
	PUSH	AF	     ;SAVE FOR CHECKSUM
	CALL	CONV
	CALL	PUO
	POP	AF	     ;ORIGINAL BYTE HERE
	ADD	A,D	     ;ADDED TO CHECKSUM
	LD	D,A	     ;UPDATE CHECKSUM
	RET	
;
;
COPCK:	LD	C,'-'	     ;PROMPT FOR CONSOLE
	CALL	CO
;
PCHK:	CALL	TI
;
; TEST FOR DELIMITERS
;
QCHK:	CP	' '	     ;RETURN ZERO IF DELIMITER
	RET	Z
	CP	','
	RET	Z
	CP	CR	     ;RETURN W/CARRY SET IF CR
	SCF	
	RET	Z
	CCF		     ;ELSE NON-ZERO, NO CARRY
	RET	
;
; MAIN CONSOLE INPUT ROUTINE
;
CI:	CALL	IOCHK
	AND	~CMSK
	JR	NZ,CI1
;
; TELEPRINTER ROUTINE
;
TTYIN:	IN	A,(TTS)
	AND	TTYDA
	JR	Z,TTYIN
	IN	A,(TTI)
	RET	
;
CI1:	DEC	A	     ;CONSOLE=CRT?
	JR	NZ,CI2
;
; C.R.T. INPUT ROUTINE
;
CRTIN:	IN	A,(CRTS)
	AND	CRTDA
	JR	Z,CRTIN
	IN	A,(CRTI)
	RET	
;
CI2:	DEC	A	     ;BATCH?
	JP	NZ,CILOC     ;NO, MUST BE USER DEFINED
;
;
; READER INPUT ROUTINE, WITH
; TIME-OUT DELAY. INCLUDES
; PULSING OF HARDWARE PORT
; TO INDICATE REQUEST FOR
; READER DATA.
;
RI:	PUSH	HL
	CALL	IOCHK
	AND	~RMSK
;	CPL	
;	OUT	(RCP),A	     ;PULSE READER CONTROL PORT
;	CPL		     ;CLEAR IT
;	OUT	(RCP),A
	JR	NZ,RI3	     ;NOT TTY
	LD	H,A	     ;CLEAR FOR-TIME OUT TEST
RI0:	IN	A,(TTS)
	AND	TTYDA
	JR	NZ,RI2
	PUSH	BC
	LD	B,0
DL0:	EX	(SP),HL	     ;WASTE TIME
	EX	(SP),HL	     ;FOR DELAY
	DJNZ	DL0
	POP	BC
	DEC	H
	JR	NZ,RI0
RI1:	XOR	A
	SCF	
	POP	HL
	RET	
RI2:	IN	A,(TTI)
RID:	OR	A
	POP	HL
	RET	
RI3:	CP	RCAS
	JR	NZ,RI6
	IN	A,(SWITCH)   ;READ INITIAL SENSE CONDX.
	LD	L,A
RI4:	IN	A,(SWITCH)   ;SEE IF SW. ALTERED
	CP	L
	JR	NZ,RI1	     ;ABORT IF SO
	IN	A,(RCSS)     ;CASSETTE INPUT DRIVER
	AND	RCSDA	     ;DATA YET?
	JR	NZ,RI4	     ;KEEP LOOKING
RI5:	IN	A,(RCSD)
	JR	RID
RI6:	POP	HL
	CP	RPTR
	JP	Z,RPTPL	     ;EXTERNAL ROUTINE
	JP	RULOC	     ;USER VECTOR
;
; THIS ROUTINE GETS READER INPUT
; AND KILLS THE PARITY BIT.
;
RIX:	CALL	RIFF
	AND	7FH
	RET	
;
; THIS ROUTINE READS A BINARY FILE
; IMAGE, IN THE FORM AS PUNCHED IN
; THE "U" (UNLOAD) COMMAND.  IT TAKES
; ONE PARAMETER, WHICH IS THE STARTING
; ADDRESS OF THE LOAD, AND WILL PRINT
; THE LAST ADDRESS (+1) LOADED ON THE
; CONSOLE DEVICE.
;
LOAD:	CALL	EXPR1	     ;INITIAL LOAD ADDRESS
	POP	HL
	CALL	CRLF
	LD	D,0FFH	     ;START-OF-FILE TAG
LOAD0:	LD	B,4	     ;FIND AT LEAST FOUR 0FFH'S
LOAD1:	CALL	RIFF
	JR	NZ,LOAD0
	DJNZ	LOAD1
LOAD2:	CALL	RIFF	     ;4 FOUND, NOW WAIT FOR NON-0FFH
	JR	Z,LOAD2
	LD	(HL),A	     ;FIRST REAL DATA BYTE
	LD	A,BELL	     ;TELL TTY
	OUT	(TTO),A
LOAD3:	INC	HL
	CALL	RIFF
	JR	Z,ELOA	     ;POSSIBLE END OF FILE
	LD	(HL),A
	JR	LOAD3
ELOA:	LD	E,1	     ;INITIALIZE
ELOA0:	CALL	RIFF
	JR	NZ,ELOA1
	INC	E	     ;COUNT QUES
	LD	A,MAX	     ;LOOK FOR EOF
	CP	E	     ;FOUND MAX?
	JR	NZ,ELOA0     ;NOPE
	JP	LADR	     ;YEP, PRINT END ADDR
ELOA1:	LD	(HL),D
	INC	HL
	DEC	E	     ;RESTORE
	JR	NZ,ELOA1
	LD	(HL),A	     ;REAL BYTE
	JR	LOAD3
;
; THIS IS THE BREAKPOINT "TRAP" HANDLING
; ROUTINE.  ALL USER REGISTERS ARE SAVED
; FOR DISPLAY PURPOSES, AND THE CONTENTS
; ARE RESTORED WHEN EXECUTING A "GO" (G)
; COMMAND.
;
RESTART:
	PUSH	HL	     ;PUSH ALL REGISTERS
	PUSH	DE
	PUSH	BC
	PUSH	AF
	CALL	MEMSIZ	     ;GET MONITOR'S STACK VALUE
	EX	DE,HL
	LD	HL,10	     ;GO UP 10 BYTES IN STACK
	ADD	HL,SP
	LD	B,4	     ;PICK OFF REG.
	EX	DE,HL
RES0:	DEC	HL
	LD	(HL),D	     ;SAVE IN WORKAREA
	DEC	HL
	LD	(HL),E
	POP	DE
	DJNZ	RES0
	POP	BC
	DEC	BC	     ;ADJUST P.C. VALUE
	LD	SP,HL	     ;SET MONITOR STACK
	LD	HL,TLOCX
	ADD	HL,SP
	LD	A,(HL)
	SUB	C	     ;LOOK FOR A TRAP/MATCH
	INC	HL
	JR	NZ,RES1
	LD	A,(HL)
	SUB	B
	JR	Z,RES3	     ;NO TRAP HERE
RES1:	INC	HL
	INC	HL
	LD	A,(HL)
	SUB	C	     ;TEST FOR SECOND TRAP
	JR	NZ,RES2
	INC	HL
	LD	A,(HL)
	SUB	B
	JR	Z,RES3
RES2:	INC	BC	     ;NO TRAPS SET, RE-ADJUST P.C.
RES3:	LD	HL,LLOCX
	ADD	HL,SP
	LD	(HL),E	     ;STORE USER H&L
	INC	HL
	LD	(HL),D
	INC	HL
	INC	HL
	LD	(HL),C	     ;AND USER P.C.
	INC	HL
	LD	(HL),B
	PUSH	BC
	LD	C,'@'	     ;DISPLAY BREAK ADDRESS.
	CALL	CO
	POP	HL
	CALL	LADR
	LD	HL,TLOCX
	ADD	HL,SP
	LD	BC,200H
RES4:	LD	E,(HL)	     ;REPLACE BYTES TAKEN FOR TRAP
	LD	(HL),C	     ;ZERO OUT STORAGE AREA
	INC	HL
	LD	D,(HL)
	LD	(HL),C
	INC	HL
	LD	A,E
	OR	D	     ;DO NOTHING IF ZERO
	JR	Z,RES5
	LD	A,(HL)
	LD	(DE),A	     ;STORE BYTE
RES5:	INC	HL	     ;SAME THING
	DJNZ	RES4	     ;FOR OTHER BREAKPOINT
	EX	AF,AF'	     ;GET ALTERNATE SET OF REG.'S
	EXX	
	PUSH	HL	     ;AND STORE IN WORKSPACE
	PUSH	DE
	PUSH	BC
	PUSH	AF
	PUSH	IX
	PUSH	IY
	LD	A,I	     ;GET INTERUPT VECTOR BYTE
	LD	B,A
	LD	A,R	     ;GET REFRESH BYTE
	LD	C,A
	PUSH	BC	     ;SAVE
	JP	START	     ;BACK TO START
;
; THIS IS THE INTERNAL KEYBOARD
; HANDLING ROUTINE. IT WILL IGNORE
; RUBOUTS (0FFH) AND BLANKS (00),
; AND IT WILL NOT ECHO CR'S & N'S.
; (NO N'S FOR THE "NULL" COMMAND).
; IT CONVERTS LOWER CASE TO UPPER
; CASE FOR THE LOOK-UP OF COMMANDS.
;
; OTHER CHARACTERS ARE ECHOED AS THEY
; ARE RECEIVED.
;
KI:	CALL	CI	     ;GET CHARACTER FROM CONSOLE
	AND	7FH	     ;CLEAR PARITY BIT
	RET	
;
TI:	CALL	KI
	INC	A	     ;IGNORE RUBOUTS
	RET	M
	DEC	A	     ;IGNORE NULLS
	RET	Z
	CP	'N'	     ;IGNORE N'S FOR NULL CMND
	RET	Z
	CP	'n'
	JR	Z,TI0
	CP	CR	     ;IGNORE CR'S
	RET	Z
	PUSH	BC
	LD	C,A
	CALL	CO
	LD	A,C
	POP	BC
	CP	'A'-1	     ;CONVERT TO UPPER CASE
	RET	C
	CP	'z'+1
	RET	NC
TI0:	AND	05FH
	RET	
;
; THIS ROUTINE ALLOWS EXAMINATION OF
; ANY INPUT PORT, OR THE SENDING OF
; ANY VALUE TO ANY PORT.
;
; QO<N>,<V>[CR]
;	OUTPUT TO PORT <N>, THE VALUE <V>
;
; QI<N>[CR]
;	DISPLAY THE PORT <N>
;
QUERY:	CALL	TI
	CP	'O'
	JR	Z,QUO
	CP	'I'
	JP	NZ,ERROR
	CALL	EXPR1
	POP	BC
	IN	E,(C)
BITS:	LD	B,8	     ;DISPLAY 8 BITS
	CALL	BLK
QUE2:	SLA	E
	LD	A,'0'>1
	ADC	A,A	     ;MAKE "0" OR "1"
	LD	C,A
	CALL	CO
	DJNZ	QUE2
	RET	
QUO:	CALL	EXPR
	POP	DE
	POP	BC
	OUT	(C),E
	RET	
;
; THIS ROUTINE VERIFIES THE CONTENTS
; OF ONE MEMORY BLOCK WITH ANOTHER.
;
; V<ADDR1>,<ADDR2>,<ADDR3>
;	VERIFY FROM <1> THRU <2> WITH
; THE CONTENTS OF MEMORY BEGINNING AT <3>
;
VERIFY:	CALL	EXPR3	     ;GET 3 PARAMETERS
VERI0:	LD	A,(BC)
	CP	(HL)
	JR	Z,VERI1
	PUSH	BC
	CALL	CERR	     ;DISPLAY ERRORS
	POP	BC
VERI1:	INC	BC
	CALL	HILOX
	JR	VERI0
;
; <SYSTEM I/O LOOK-UP TABLE>
;
; THE FIRST CHARACTER IS THE DEVICE NAME
; (ONE LETTER) AND THE NEXT FOUR ARE THE
; NAMES OF THE FOUR POSSIBLE DRIVERS TO BE
; ASSIGNED.
;
LTBL:	
	DEFB	'C'	     ;CONSOLE ASSIGNMENTS
	DEFB	'T'	     ;CTTY	T=TELEPRINTER
	DEFB	'C'	     ;CCRT	C=CRT (VIDEO MONITOR)
	DEFB	'B'	     ;BATCH= COMMANDS FROM READER
	DEFB	'U'	     ;CUSE	USER
;
	DEFB	'R'	     ;READER ASSIGNMENTS
	DEFB	'T'	     ;RTTY
	DEFB	'P'	     ;RPTR	P=PAPER TAPE
	DEFB	'C'	     ;RCAS	C=CASSETTE
	DEFB	'U'	     ;RUSER	USER
;
	DEFB	'P'	     ;PUNCH ASSIGNMENTS
	DEFB	'T'	     ;PTTY
	DEFB	'P'	     ;PPTP
	DEFB	'C'	     ;PCAS	C=CASSETTE
	DEFB	'U'	     ;PUSER	USER
;
	DEFB	'L'	     ;LIST ASSIGNMENTS
	DEFB	'T'	     ;LTTY	LIST=TELEPRINTER
	DEFB	'C'	     ;LCRT	LIST=CRT
	DEFB	'L'	     ;LINE PRINTER
	DEFB	'U'	     ;LUSER	USER
;
;
; THIS IS A SHORT PROGRAM, EXECUTED
; UPON EXECUTING A "GO" COMMAND. IT
; IS PLACED IN THE WORK AREA WHEN
; THE MONITOR IS INITIALIZED, AS IT
; REQUIRES RAM FOR PROPER OPERATION.
;
EXIT:			     ;EXIT ROUTINE (LOADS ALL REGISTERS)
	POP	BC
	LD	A,C
	LD	R,A
	LD	A,B
	LD	I,A	
	POP	IY
	POP	IX
	POP	AF
	POP	BC
	POP	DE
	POP	HL
	EX	AF,AF'	
	EXX	
	POP	DE
	POP	BC
	POP	AF
	POP	HL
	LD	SP,HL
	NOP		     ;RESERVED FOR ENABLE INTERUPTS
	LD	HL,0
	JP	0
;
	DEFW	0	     ;STORAGE AREA FOR TRAP DATA
	DEFB	0
	DEFW	0
	DEFB	0
;
; DISPLACEMENTS OF REGISTER
; STORAGE FROM NORMAL STACK
; LOCATION.
;
ENDX:	
;
ALOC	EQU	15H
BLOC	EQU	13H
CLOC	EQU	12H
DLOC	EQU	11H
ELOC	EQU	10H
FLOC	EQU	14H
HLOC	EQU	31H
LLOC	EQU	30H
PLOC	EQU	34H
SLOC	EQU	17H
TLOC	EQU	35H
TLOCX	EQU	25H
LLOCX	EQU	20H
;
APLOC	EQU	09H
BPLOC	EQU	0BH
CPLOC	EQU	0AH
DPLOC	EQU	0DH
EPLOC	EQU	0CH
FPLOC	EQU	08H
HPLOC	EQU	0FH
LPLOC	EQU	0EH
XLOC	EQU	07
YLOC	EQU	05
RLOC	EQU	02
ILOC	EQU	03
;
;
; THIS IS THE TABLE USED TO DETERMINE
; A VALID REGISTER IDENTIFIER, AND IT'S
; DISPLACEMENT FROM THE STACK POINTER.
;
; POSITION ONE= REGISTER NAME, WITH BIT 7 INDICATING
; END OF TABLE.
;
; POSITION TWO=	BIAS FROM CURRENT STACK LEVEL OR'ED
; WITH A TWO-BIT FLAG.	00XXXXXX=BYTE
;			10XXXXXX=WORD
;			11XXXXXX=SPECIAL FOR "M" REG.
;
ACTBL:		;NORMAL SET OF REGISTERS (8080)
;		;PLUS THE INTERUPT REGISTER ("I")
;
	DEFB	'A',ALOC | 0
	DEFB	'B',BLOC | 0
	DEFB	'C',CLOC | 0
	DEFB	'D',DLOC | 0
	DEFB	'E',ELOC | 0
	DEFB	'F',FLOC | 0
	DEFB	'H',HLOC | 0
	DEFB	'L',LLOC | 0
	DEFB	'M',HLOC | 0C0H
	DEFB	'P',PLOC | 080H
	DEFB	'S',SLOC | 080H
	DEFB	'I',ILOC | 0
	DEFB	80H
;
PRMTB:		;ADDITIONAL SET OF REGISTERS (Z-80)
;
	DEFB	'A',APLOC | 0
	DEFB	'B',BPLOC | 0
	DEFB	'C',CPLOC | 0
	DEFB	'D',DPLOC | 0
	DEFB	'E',EPLOC | 0
	DEFB	'F',FPLOC | 0
	DEFB	'H',HPLOC | 0
	DEFB	'L',LPLOC | 0
	DEFB	'M',HPLOC | 0C0H
	DEFB	'X',XLOC | 080H
	DEFB	'Y',YLOC | 080H
	DEFB	'R',RLOC | 0
	DEFB	80H
;
Z:	
		;END OF PROGRAM
;
;
	END
