;	<< ZAPPLE 2-K MASKED ROM MONITOR SYSTEM >>
;			by
;
;	COMPUTER DESIGN LABS
;	342 COLUMBUS AVE.
;	TRENTON, NEW JERSEY 08629
;
;
;	COPYRIGHT 1979 COMPUTER DESIGN LABS;
;
.PABS	;THIS MONITOR IN ABSOLUTE FORMAT
;
;
BASE	= 0F000H
USER	= BASE+800H
;
.TITLE " <Zapple **MASKED ROM** Monitor, Version 1.05, Dec. 18 1976>"
.SBTTL	/ Copyright 1979 by COMPUTER DESIGN LABS/
;
RST7	= 38H	;RST 7 (LOCATION FOR TRAP)
IOBYT	= 76H	;R/W PORT FOR TEMP. STORAGE
SENSE	= 7AH	;SWITCH WORD FOR INITIAL DEFAULT
SWITCH	= 0FFH	;TEST PORT TO ABORT READ OPERATION
RCP	= 7AH	;READER CONTROL PORT (OUT)
NN	= 0F8H	;"I" REGISTER INITIAL VALUE
;
;	<I/O DEVICES>
;
;-TELEPRINTER
;
TTI	= 71H	;DATA IN PORT
TTO	= 71H	;DATA OUT PORT
TTS	= 70H	;STATUS PORT (IN)
TTYDA	= 1	;DATA AVAILABLE MASK BIT
TTYBE	= 02	;XMTR BUFFER EMPTY MASK
;
;-C.R.T. SYSTEM
;
CRTI	= 73H	;DATA PORT (IN)
CRTS	= 72H	;STATUS PORT (IN)
CRTO	= 73H	;DATA PORT (OUT)
CRTDA	= 1	;DATA AVAILABLE MASK
CRTBE	= 02	;XMTR BUFFER EMPTY MASK
;
;-CASSETTE SYSTEM
;
RCSD	= 75H	;DATA IN PORT
RCSS	= 74H	;STATUS PORT (IN)
RCSDA	= 1	;DATA AVAILABLE MASK
PCASO	= 75H	;DATA PORT (OUT)
PCASS	= 74H	;CONTROL PORT (OUT)
PCSBE	= 02	;XMTR BUFFER EMPTY MASK
;
;	<CONSTANTS>
;
FALSE	= 0		;ISN'T SO
TRUE	= # FALSE	;IT IS SO
CR	= 0DH		;ASCII CARRIAGE RETURN
LF	= 0AH		;ASCII LINE FEED
BELL	= 7		;DING
RUB	= 0FFH		;RUB OUT
FIL	= 00		;FILL CHARACTERS AFTER CRLF
MAX	= 7		;NUMBER OF QUES IN EOF
;
;	<I/O CONFIGURATION MASKS>
;
CMSK	= 11111100B	;CONSOLE DEVICE
RMSK	= 11110011B	;STORAGE DEVICE (IN)
PMSK	= 11001111B	;STORAGE DEVICE (OUT)
LMSK	= 00111111B	;LIST DEVICE
;
;
;-CONSOLE CONFIGURATION
CTTY	= 0	;TELEPRINTER
CCRT	= 1	;C.R.T.
BATCH	= 2	;READER FOR INPUT, LIST FOR OUTPUT
CUSE	= 3	;USER DEFINED
;
;-STORAGE INPUT CONFIGURATION
RTTY	= 0	;TELEPRINTER READER
RPTR	= 4	;HIGH-SPEED RDR (EXTERNAL ROUTINE)
RCAS	= 8	;CASSETTE
RUSER	= 0CH	;USER DEFINED
;
;-STORAGE OUTPUT CONFIGURATION
PTTY	= 0	;TELEPRINTER PUNCH
PPTP	= 10H	;HIGH-SPEED PUNCH (EXTERNAL ROUTINE)
PCAS	= 20H	;CASSETTE
PUSER	= 30H	;USER DEFINED
;
;-LIST DEVICE CONFIGURATION
LTTY	= 0	;TELEPRINTER PRINTER
LCRT	= 40H	;C.R.T. SCREEN
LINE	= 80H	;LINE PRINTER (EXTERNAL ROUTINE)
LUSER	= 0C0H	;USER DEFINED
;
;
;	VECTORS FOR USER DEFINED ROUTINES
;
.LOC	USER
CILOC:	.BLKB 3	;CONSOLE INPUT
COLOC:	.BLKB 3	;CONSOLE OUTPUT
RPTPL:	.BLKB 3	;HIGH-SPEED READER
RULOC:	.BLKB 3	;USER DEFINED STORAGE (INPUT)
PTPL:	.BLKB 3	;HIGH-SPEED PUNCH
PULOC:	.BLKB 3	;USER DEFINED STORAGE (OUTPUT)
LNLOC:	.BLKB 3	;LINE PRINTER
LULOC:	.BLKB 3	;USER DEFINED PRINTER
CSLOC:	.BLKB 3	;CONSOLE INPUT STATUS ROUTINE
J =.
;
;	PROGRAM CODE BEGINS HERE
;
.LOC	BASE
	JMP	BEGIN	;GO AROUND VECTORS
;
;	<VECTORS 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.
;
	JMP	CI	;CONSOLE INPUT
	JMP	RI	;READER INPUT
	JMP	CO	;CONSOLE OUTPUT
	JMP	PO	;PUNCH OUTPUT
	JMP	LO	;LIST OUTPUT
	JMP	CSTS	;CONSOLE STATUS
	IN	IOBYT	;I/O CHECK
	RET
	JMP	IOSET	;I/O SET
	JMP	MEMCK	;MEMORY LIMIT CHECK
TRAP:	JMP	RESTART	;BREAKPOINT
;
;	ANNOUNCEMENT OF MONITOR NAME & VERSION
;
MSG:	.BYTE	CR,LF,FIL,FIL,FIL
	.ASCII	'Zapple V'
	.ASCII	'1.0R'
MSGL	= .-MSG
;
;	LET US BEGIN
;
BEGIN:	MVI	A,053H	;INITIALIZE THE HARDWARE
	OUT	TTS
	OUT	CRTS
	OUT	RCSS
	MVI	A,051H
	OUT	TTS
	OUT	CRTS
	DCR	A
	OUT	RCSS
	XRA	A
	OUT	IOBYT+1
	OUT	RCP	;CLEAR RDR CONTROL PORT
	DCR	A
	OUT	IOBYT
	MVI	A,4
	OUT	IOBYT+1	;WHEW!
;
	IN	SENSE	;INITIALIZE I/O CONFIGURATION
	OUT	IOBYT
	MVI	A,NN	;INITIAL 'I' REG. CONFIGURATION
	STAI		;SET FOR PAGE 'NN' ON INTERUPT
	LXI	SP,AHEAD-4	;SET UP A FAKE STACK
	JMP	MEMSIZ+1	;GET MEMORY SIZE
	.WORD	AHEAD
AHEAD:	SPHL		;SET TRUE STACK
	XCHG
	LXI	B,ENDX-EXIT
	LXI	H,EXIT
	LDIR		;MOVE TO RAM
	XCHG
	LXI	B,-5FH	;SET UP A USER'S STACK VALUE
	DAD	B
	PUSH	H	;PRE-LOAD STACK VALUE
	LXI	H,0	;INITIALIZE OTHER REGISTERS
	MVI	B,10	; (20 OF THEM)
STKIT:	PUSH	H	; TO ZERO
	DJNZ	STKIT
HELLO:	MVI	B,MSGL	;SAY HELLO TO THE FOLKS	
	CALL	TOM1	;OUTPUT SIGN-ON MSG
START:	LXI	D,START	;MAIN 'WORK' LOOP
	PUSH	D	;SET UP A RETURN TO HERE
	CALL	CRLF
	MVI	C,'>'
	CALL	CO
STAR0:	CALL	TI	;GET A CONSOLE CHARACTER
	ANI	7FH	;IGNORE NULLS
	JRZ	STAR0	;GET ANOTHER
	SUI	'A'	;QUALIFY THE CHARACTER
	RM		;<A
	CPI	'Z'-'A'+1
	RNC		;INVALID CHARACTER
	ADD	A	;A*2
	LXI	H,TBL	;POINT TO COMMAND TABLE
	ADD	L	;ADD IN DISPLACEMENT
	MOV	L,A
	MOV	A,M
	INX	H
	MOV	H,M
	MOV	L,A
	MVI	C,2	;SET C UP
	PCHL		;GO EXECUTE COMMAND.
;
;		<COMMAND BRANCH TABLE>
;
TBL:
.WORD	ASSIGN	;A - ASSIGN I/O
.WORD	BYE	;B - SYSTEM SHUT-DOWN
.WORD	COMP	;C - COMPARE MEMORY VS. READER INPUT
.WORD	DISP	;D - DISPLAY MEMORY ON CONS. IN HEX
.WORD	EOF	;E - END OF FILE TAG FOR HEX DUMPS
.WORD	FILL	;F - FILL MEMORY WITH A CONSTANT
.WORD	GOTO	;G - GOTO [ADDR]<,>BREAKPOINTS (2)
.WORD	HEXN	;H - HEX MATH. <SUM>,<DIFFERENCE>
.WORD	J	;I * USER DEFINED
	J=J+3	;INCREMENT VECTOR ADDR
.WORD	TEST	;J - NON-DESTRUCTIVE MEMORY TEST
.WORD	J	;K * USER DEFINED
	J=J+3	;INCREMENT VECTOR ADDR
.WORD	LOAD	;L - LOAD A BINARY FORMAT FILE
.WORD	MOVE	;M - MOVE BLOCKS OF MEMORY
.WORD	NULL	;N - PUNCH NULLS ON PUNCH DEVICE
.WORD	J	;O * USER DEFINED
.WORD	PUTA	;P - 'PUT' ASCII INTO MEMORY.
.WORD	QUERY	;Q - QI(N)=DISP. N; QO(N,V)=OUT N,V
.WORD	READ	;R - READ A HEX FILE (W/CHECKSUMS)
.WORD	SUBS	;S - SUBSTITUTE &/OR EXAMINE MEMORY
.WORD	TYPE	;T - TYPE MEMORY IN ASCII
.WORD	UNLD	;U - MEMORY TO PUNCH (BINARY FORMAT)
.WORD	VERIFY	;V - COMPARE MEMORY AGAINST MEMORY
.WORD	WRITE	;W - MEMORY TO PUNCH (HEX FORMAT)
.WORD	XAM	;X - EXAMINE & MODIFY CPU REGISTERS
.WORD	WHERE	;Y - FIND SEQUENCE OF BYTES IN MEM.
.WORD	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 STRUCTURED 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 XX = 00, THE DEVICE IS ALWAYS THE
; TELEPRINTER.  WHEN XX = 11, THE DEVICE IS ALWAYS THE
; USER DEFINED.  SEE OPERATORS MANUAL FOR FURTHER
; DETAILS.
;
ASSIGN:	CALL	TI	;GET DEVICE NAME
	LXI	H,LTBL	;POINT TO DEVICE TABLE
	LXI	B,400H	;4 DEVICES TO LOOK FOR
	LXI	D,5	;IDENTIFIER + 4 DEV. IN TABLE
..A0:	CMP	M	;LOOK FOR MATCH
	JRZ	..A1
	DAD	D	;GO THRU TABLE
	INR	C	;KEEP TRACK OF DEVICE
	DJNZ	..A0
	JMPR	..ERR	;WRONG IDENTIFIER
..A1:	MOV	E,C	;SAVE DEVICE NUMBER
..A2:	CALL	TI	;SCAN PAST '='
	CPI	'='
	JRNZ	..A2
	CALL	TI	;GET NEW ASSIGNMENT
	LXI	B,400H	;4 POSSIBLE ASSIGNMENTS
..A3:	INX	H	;POINT TO ASSIGNMENT NAME
	CMP	M	;LOOK FOR PROPER MATCH
	JRZ	..A4	;MATCH FOUND
	INR	C	;KEEP TRACK OF ASSIGNMENT NMBR
	DJNZ	..A3
..ERR:	JMP	ERROR	;NO MATCH, ERROR
..A4:	MVI	A,3	;SET UP A MASK
	INR	E
..A5:	DCR	E	;DEVICE IN E
	JRZ	..A6	;GOT IT
	SLAR	C	;ELSE MOVE MASKS
	SLAR	C
	RAL
	RAL		;A=DEVICE MASK
	JMPR	..A5
..A6:	CMA		;INVERT FOR AND'ING
	MOV	D,A	;SAVE IN D
..A7:	CALL	PCHK	;WAIT FOR [CR]
	JRNC	..A7
	IN	IOBYT	;GET PRESENT CONFIGURATION
	ANA	D	;MODIFY ONLY SELECTED DEVICE
	ORA	C	;'OR' IN NEW BIT PATTERN
	MOV	C,A	;NEW CONFIGURATION
;
; THIS ALLOWS USER PROGRAMS TO MODIFY
; THE I/O CONFIGURATION DYNAMICALLY
; DURING EXECUTION.
;
IOSET:	MOV	A,C	;NEW I/O BYTE PASSED IN C REG
	OUT	IOBYT	;IN AN I/O PORT LATCH
	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
..BY:	CALL	KI
	CPI	1EH	;CONTROL-SHIFT-N
	JRNZ	..BY
	POP	D	;REMOVE THE RETURN
	JMP	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-ARROW [_]
; 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	H
..A1:	CALL	KI	;GET A CHARACTER
	CPI	4	;CONTROL-D? (EOT)
	JZ	LFADR	;YES, STOP & PRINT ADDR.
	CPI	'_'	;ERASE MISTAKE?
	JRZ	..A3	; YES.
	MOV	M,A	;ELSE STORE IT IN MEMORY
	MOV	C,A
	INX	H
..A2:	CALL	CO	;ECHO ON CONSOLE
	JMPR	..A1
..A3:	DCX	H	;BACK UP POINTER
	MOV	C,M
	JMPR	..A2	;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.
..C:	CALL	RIFF	;GET A FULL READER BYTE
	CMP	M	;8 BIT COMAPARE
	CNZ	CERR	;CALL IF INVALID COMPARE
	CALL	HILOX	;SEE IF RANGE SATISFIED
	JMPR	..C
;
; THIS SUBOUTINE IS USED TO DISPLAY THE
; CURRENT LOCATION OF THE 'M' REGISTER POINTERS (HL),
; AND THE VALUE AT THE LOCATION, AND THE CONTENTS
; OF THE ACCUMULATOR. USED BY TWO ROUTINES.
;
CERR:	MOV	B,A	;SAVE ACC.
	CALL	HLSP	;DISPLAY H&L
	MOV	A,M
	CALL	LBYTE	;PRINT 'M'
	CALL	BLK	;SPACE OVER
	MOV	A,B
	CALL	LBYTE	;PRINT ACC.
	JMP	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
..D0:	CALL	LFADR	;CRLF & PRINT ADDR.
..D1:	CALL	BLK	;SPACE OVER
	MOV	A,M
	CALL	LBYTE
	CALL	HILOX	;RANGE CHECK
	MOV	A,L
	ANI	0FH	;SEE IF TIME TO CRLF
	JRNZ	..D1
	JMPR	..D0
;
; 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
	MVI	C,':'	;FILE MARKER CUE
	CALL	PO
	XRA	A	;ZERO LENGTH
	CALL	PBYTE
	POP	H
	CALL	PADR	;PUNCH OPTIONAL ADDR.
	LXI	H,0	;FILE TYPE=0
	CALL	PADR	;PUNCH IT
	JMP	NULL	;TRAILER & RETURN
;
; THIS COMMAND WILL FILL A BLOCK OF MEMORY
; WITH A VALUE. IE: F0,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 BEFORE LOADING
; A PROGRAM. (ZERO IS ESPECIALLY USEFUL.)
;
FILL:	CALL	EXPR3	;GET 3 PARAMETERS
..F:	MOV	M,C	;STORE THE BYTE
	CALL	HILO
	JRNC	..F
	POP	D	;RESTORE STACK
	JMP	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
; BREAKPOINT MUST OCCUR ON AN INTRUCTION
; BYTE.
;
GOTO:	CALL	PCHK	;GET A POSSIBLE ADDRESS
	JRC	..G3	;CR ENTERED
	JRZ	..G0	;DELIMETER ENTERED
	CALL	EXF	;GET ONE EXPRESSION
	POP	D
	LXI H,	PLOC	;PLACE ADDRESS IN 'P' LOCATION
	DAD	SP
	MOV	M,D	;HIGH BYTE
	DCX	H
	MOV	M,E	;LOW BYTE
	MOV	A,B
	CPI	CR	;SEE IF LAST CHARACTER WAS CR
	JRZ	..G3	;YES, LEAVE
..G0:	MVI	D,2	;TWO BREAKPOINTS MAX
	LXI H,	TLOC	;POINT TO TRAP STORAGE
	DAD	SP
..G1:	PUSH	H	;SAVE STORAGE POINTER
	CALL	EXPR1	;GET A TRAP ADDRESS
	MOV	E,B	;SAVE DELIMETER
	POP	B	;TRAP ADDR.
	POP	H	;STORAGE
	MOV	A,B	;LOOK AT TRAP ADDR
	ORA	C
	JRZ	..G2	;DON'T SET A TRAP AT 0
	MOV	M,C	;SAVE BKPT ADDR
	INX	H
	MOV	M,B
	INX	H
	LDAX	B	;PICK UP INST. BYTE
	MOV	M,A	;SAVE THAT TOO
	INX	H
	MVI	A,0FFH	;RST 7
	STAX	B	;SOFTWARE INTERUPT
..G2:	MOV	A,E	;LOOK AT DELIMITER
	CPI	CR
	JRZ	..G2A
	DCR	D	;COUNT BKPTS
	JRNZ	..G1	;GET ONE MORE
..G2A:	MVI	A,JMP	;SET UP JMP INSTRUCTION
	STA	RST7	; AT RESTART TRAP LOC.
	LXI	H,TRAP	; TO MONITOR VECTOR
	SHLD	RST7+1
..G3:	CALL	CRLF
	POP	D	;CLEAR SYSTEM RETURN
	LXI	H,22	;FIND 'EXIT' ROUTINE
	DAD	SP	;UP IN STACK
	PCHL		;GOOD LUCK.
;
; 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
..T1:	MOV	A,M	;READ A BYTE
	MOV	B,A	;SAVE IN B REG.
	CMA
	MOV	M,A	;READ/COMPLIMENT/WRITE
	XRA	M	; & COMPARE
	JRZ	..T2	;SKIP IF ZERO (OK)
	PUSH	D	;SAVE END POINTER
	MOV	D,B	;SAVE BYTE
	MOV	E,A	;SET-UP TO DISPLAY
	CALL	HLSP	;PRINT BAD ADDR
	CALL	BITS	;PRINT BAD BIT LOC.
	CALL	CRLF
	MOV	B,D	;RESTORE BYTE
	POP	D	;RESTORE DE
..T2:	MOV	M,B	;REPLACE BYTE
	CALL	HILOX	;RANGE TEST
	JMPR	..T1
;
; 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
; CARELESSLY IMPLEMENTED.
;
;	M<1>,<2>,<3>
;
MOVE:	CALL	EXPR3	;GET 3 PARAMETERS
..M:	MOV	A,M	;PICK UP
	STAX	B	;PUT DOWN
	INX	B	;MOVE UP
	CALL	HILOX	;CHECK IF DONE
	JMPR	..M
;
; THIS COMMAND READS THE CHECK-SUMMED HEX FILES
; FOR BOTH THE NORMAL INTEL FORMAT AND THE CDL
; 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
	MOV	A,B	;LOOK AT DELIMITER
	SUI	CR	;ALL DONE?
	MOV	B,A	;SET UP RELOCATION OF 0
	MOV	C,A	; IF CR ENTERED
	POP	D	;BIAS AMOUNT
	JRZ	..R0	;CR ENTERED
	CALL	EXPR1	;GET RELOCATION
	POP	B	;ACTUAL RELOCATION VALUE
..R0:	XCHG
	EXX		;HL'=BIAS, BC'=RELOCATION
	CALL	CRLF
LOD0:	CALL	RIX	;GET A CHARACTER
	SUI	':'	;ABSOLUTE FILE CUE?
	MOV	B,A	;SAVE CUE CLUE
	ANI	0FEH	;KILL BIT 0
	JRNZ	LOD0	; NO, KEEP LOOKING
	MOV	D,A	;ZERO CHECKSUM
	CALL	SBYTE	;GET FILE LENGTH
	MOV	E,A	;SAVE IN E REG.
	CALL	SBYTE	;GET LOAD MSB
	PUSH	PSW	;SAVE IT
	CALL	SBYTE	;GET LOAD LSB
	EXX		;CHANGE GEARS
	POP	D	;RECOVER MSB
	MOV	E,A	;FULL LOAD ADDR
	PUSH	B	;BC'=RELOCATION
	PUSH	D	;DE'=LOAD ADDR
	PUSH	H	; HL'=BIAS
	DAD	D	; BIAS+LOAD
	XTHL		;RESTORE HL'
	POP	X	; X=BIAS+LOAD
	EXX		;DOWNSHIFT
	POP	H	;HL=LOAD ADDR
	CALL	SBYTE	;GET FILE TYPE
	DCR	A	;1=REL. FILE, 0=ABS.
	MOV	A,B	;SAVE CUE BIT
	POP	B	;BC=RELOCATION
	JRNZ	..A	;ABSOLUTE FILE
	DAD	B	;ELSE RELOCATE
	DADX	B	;BOTH X & HL
..A:	INR	E	;TEST LENGTH
	DCR	E	;0=DONE
	JRZ	DONE
	DCR	A	;TEST CUE
	JRZ	LODR	;RELATIVE
..L1:	CALL	SBYTE	;NEXT
	CALL	STORE	;STORE IT
	JRNZ	..L1	;MORE COMING
LOD4:	CALL	SBYTE	;GET CHECKSUM
	JRZ	LOD0	;GOOD CHECKSUM
ERR2:	PUSH	X
	POP	H	;TRANSFER
	CALL	LADR	;PRINT CURRENT LOAD ADDR
	JMP	ERROR	;ABORT
DONE:	MOV	A,H
	ORA	L	;DON'T MODIFY IF ZERO
	RZ
	XCHG		;STORE PC
	LXI H,	PLOC
	DAD	SP
	MOV	M,D	;IN STACK AREA
	DCX	H
	MOV	M,E
	RET
LODR:	MVI	L,1	;SET-UP BIT COUNTER
..L1:	CALL	LODCB	;GET THE BIT
	JRC	..L3	;DOUBLE BIT
..L5:	CALL	STORE	;WRITE IT
	JRNZ	..L1
	JMPR	LOD4	;TEST CHECKSUM
..L3:	MOV	C,A	;SAVE LOW BYTE
	CALL	LODCB	;NEXT CONTROL BIT
	MOV	B,A	;SAVE HIGH BYTE
	EXX
	PUSH	B	;GET RELOCATION
	EXX
	XTHL		;INTO HL
	DAD	B	;RELOCATE
	MOV	A,L	;LOW BYTE
	CALL	STORE	;STORE IT
	MOV	A,H	;HIGH BYTE
	POP	H	;RESTORE HL
	JMPR	..L5	;DO THIS AGAIN
LODCB:	DCR	L	;COUNT BITS
	JRNZ	..LC1	;MORE LEFT
	CALL	SBYTE	;GET NEXT
	DCR	E	;COUNT BYTES
	MOV	H,A	;SAVE THE BITS
	MVI	L,8	;8 BITS/BYTE
..LC1:	CALL	SBYTE	;GET A DATA BYTE
	SLAR	H	;TEST NEXT BIT
	RET
SBYTE:	PUSH	B	;PRESERVE BC
	CALL	RIBBLE	;GET A CONVERTED ASCII CHAR.
	RLC
	RLC
	RLC
	RLC		;MOVE IT TO HIGH NIBBLE
	MOV	C,A	;SAVE IT
	CALL	RIBBLE	;GET OTHER HALF
	ORA	C	;MAKE WHOLE
	MOV	C,A	;SAVE AGAIN IN C
	ADD	D	;UPDATE CHECKSUM
	MOV	D,A	;NEW CHECKSUM
	MOV	A,C	;CONVERTED BYTE
	POP	B
	RET
STORE:	MOV	0(X),A	;WRITE TO MEMORY
	CMP	0(X)	;VALID WRITE?
	JRNZ	ERR2	; NO.
	INX	X	;ADVANCE POINTER
	DCR	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	H
..S0:	MOV	A,M
	CALL	LBYTE	;DISPLAY THE BYTE
	CALL	COPCK	;MODIFY?
	RC		; NO, ALL DONE
	JRZ	..S1	;DON'T MODIFY
	CPI	'_'	;BACKUP?
	JRZ	..S2
	PUSH	H	;SAVE POINTER
	CALL	EXF	;GET NEW VALUE
	POP	D	;VALUE IN E
	POP	H
	MOV	M,E	;MODIFY
	MOV	A,B	;TEST DELIMITER
	CPI	CR
	RZ		;DONE
..S1:	INX	H
..S3:	MOV	A,L	;SEE IF TIME TO CRLF
	ANI	7
	CZ	LFADR	;TIME TO CRLF
	JMPR	..S0
..S2:	DCX	H	;DECREMENT POINTER
	JMPR	..S3	;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
..T0:	CALL	LFADR	;DISPLAY ADDRESS
	MVI	B,64	;CHARACTERS PER LINE
..T1:	MOV	A,M
	ANI	7FH	;KILL PARITY BIT
	CPI	' '	;RANGE TEST
	JRNC	..T3	;=>SPACE
..T2:	MVI	A,'.'	;REPLACE NON-PRINTING
..T3:	CPI	07CH	;ABOVE LOWER CASE z
	JRNC	..T2
	MOV	C,A	;SEND IT
	CALL	CO
	CALL	HILOX	;MORE TO GO?
	DJNZ	..T1	;SEE IF TIME TO CRLF
	JMPR	..T0	; 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
; OCCURENCE OF THE REQUESTED STRING ARE PRINTED
; ON THE CONSOLE DEVICE.
;
WHERE:	MVI	D,0	;COUNT SEARCH BYTES
..W0:	CALL	EXPR1	;GET ONE BYTE
	POP	H	;PICK IT UP
	MOV	H,L	;STICK IN HIGH BYTE
	PUSH	H	;PUT IT IN STACK
	INX	SP	;ADJUST STACK
	INR	D	;COUNT UP
	MOV	A,B	;TEST DELIMITER
	SUI	CR
	JRNZ	..W0	;MORE TO GO
	MOV	B,A	;CHEAP ZEROES
	MOV	C,A
	MOV	H,A
	MOV	L,D	;GET BYTE COUNT IN L
	DCR	L	;-1
	DAD	SP	;BYTES STORED IN STACK
	PUSH	H
	PUSH	B
FINDC:	PUSH	B	;SAVE THAT POINTER
	CALL	CRLF
	POP	B	;RESTORE
FIND:	POP	H	;HL=SEARCH ADDR
	POP	X	;X=SEARCH BYTE POINTER
	MOV	E,D	;RESET COUNT
	MOV	A,0(X)	;GET THE FIRST SEARCH BYTE
	CCIR		;COMPARE, INCR., & REPEAT
	JPO	DONE2	;ODD PARITY=DONE
	PUSH	X	;SAVE POINTERS
	PUSH	H
FOUND:	DCR	E
	JRZ	TELL	;FOUND ALL
	MOV	A,-1(X)	;LOOK AT NEXT MATCH
	CMP	M	;TEST NEXT
	JRNZ	FIND	;NO MATCH
	INX	H	;BUMP POINTERS
	DCX	X
	JMPR	FOUND	;TEST NEXT MATCH
TELL:	POP	H
	PUSH	H
	DCX	H
	PUSH	B	;SAVE SEARCH COUNT LIMIT
	CALL	LADR	;TELL CONSOLE
	POP	B	;RESTORE
	JMPR	FINDC
DONE2:	INX	SP
	DCR	E	;RESET STACK
	JRNZ	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
..W0:	CALL	PEOL	;CRLF TO PUNCH
	LXI	B,':'	;START-OF-FILE CUE
	CALL	PO	;PUNCH IT
	PUSH	D	;SAVE
	PUSH	H	; POINTERS
..W1:	INR	B	;CALCULATE FILE LENGTH
	CALL	HILO
	JRC	..W4	;SHORT FILE
	MVI	A,24	;24 BYTES PER FILE
	SUB	B	;ENOUGH YET?
	JRNZ	..W1	; NO.
	POP	H	;GET START ADDR BACK.
	CALL	..W2	;SEND THE BLOCK
	POP	D	;RESTORE END OF FILE POINTER
	JMPR	..W0	;KEEP GOING
..W2:	MOV	D,A	;INITIALIZE CHECKSUM
	MOV	A,B	;FILE LENGTH
	CALL	PBYTE	;PUNCH IT
	CALL	PADR	;PUNCH ADDRESS
	XRA	A	;FILE TYPE=0
	CALL	PBYTE	;PUNCH IT
..W3:	MOV	A,M	;GET A DATA BYTE
	CALL	PBYTE	;PUNCH IT
	INX	H	;POINT TO NEXT BYTE
	DJNZ	..W3	;DECREMENT FILE COUNT
	XRA	A
	SUB	D	;CALCULATE CHECKSUM
	JMP	PBYTE	;PUNCH IT, RETURN
..W4:	POP	H	;CLEAR STACK
	POP	D	; OF POINTERS
	XRA	A	;SET-UP A
	JMPR	..W2	;FINISH UP & RETURN
;
;
;	THIS ROUTINE ALLOWS DISPLAYING THE
; USER'S CPU REGISTERS. THEY ALSO MAY BE
; USING THE REGISTER NAME AFTER TYPING 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
	LXI	H,ACTBL
	CPI	CR	;FULL REG. DISPLAY
	JRZ	..X6
	CPI	"'"	;SEE IF PRIMES WANTED
	JRNZ	..X0
	LXI	H,PRMTB
	CALL	TI
	CPI	CR	;FULL REG. DISPLAY
	JRZ	..X6
..X0:	CMP	M	;TEST FOR REGISTER NAME
	JRZ	..X1
	BIT	7,M  	;SEE IF END OF TABLE
	JNZ	ERROR
	INX	H
	INX	H
	JMPR	..X0
..X1:	CALL	BLK
..X2:	INX	H
	MOV	A,M
	MOV	B,A	;SAVE FOR FLAGS
	ANI	3FH	;CLEAR FLAGS FOR BIAS
	XCHG
	MOV	L,A	;DISPLACEMENT FROM STACK
	MVI	H,0
	DAD	SP
	XCHG
	INX	H
	LDAX	D	;PICK UP REG. VALUE
	CALL	LBYTE	;PRINT IT
	BIT	7,B
	JRZ	..X3
	DCX	D
	LDAX	D
	CALL	LBYTE
..X3:	CALL	COPCK	;ASK CONSOLE
	RC		;CR ENTERED, ALL DONE
	JRZ	..X5	;SKIP TO NEXT REG.
	PUSH	H
	PUSH	B
	CALL	EXF	;GET NEW VALUE
	POP	H
	POP	PSW
	PUSH	B
	PUSH	PSW
	MOV	A,L
	STAX	D
	POP	B
	BIT	7,B	;SEE IF 8 BIT OR 16 BIT REG.
	JRZ	..X4	;8 BIT
	INX	D
	MOV	A,H	;HIGH BYTE OF 16 BIT REG.
	STAX	D
..X4:	POP	B
	POP	H
	MOV	A,B	;TEST KEYBOARD
	CPI	CR
	RZ		;ALL DONE
..X5:	BIT	7,M	;SEE IF END OF TABLE
	RNZ		;RETURN IF SO
	JMPR	..X2
..X6:	CALL	CRLF
..X7:	CALL	BLK
	MOV	A,M
	INX	H
	ORA	A
	RM
	MOV	C,A
	CALL	CO
	MVI	C,'='
	CALL	CO
	MOV	A,M
	MOV	B,A	;SAVE FLAGS
	ANI	3FH	;CLEAN UP FOR OFFSET
	INX	H
	XCHG
	MOV	L,A
	MVI	H,0
	DAD	SP
	XCHG
	BIT	6,B	;TEST FOR SPECIAL "M"
	JRNZ	..X9	;PRINT OUT ACTUAL "M"
	LDAX	D
	CALL	LBYTE	;PRINT REG. VALUE
	BIT	7,B	;SINGLE OR DOUBLE?
	JRZ	..X7	;SINGLE.
	DCX	D
	LDAX	D
..X8:	CALL	LBYTE
	JMPR	..X7
..X9:	PUSH	H	;SAVE HL
	LDAX	D	;GET REG. POINTER
	MOV	H,A	;HIGH BYTE
	DCX	D
	LDAX	D
	MOV	L,A	;LOW BYTE
	MOV	A,M	;GET VALUE
	POP	H	;RESTORE HL
	JMPR	..X8	;PRINT VALUE & CONTINUE
;
; THIS IS A MESSAGE OUTPUT ROUTINE.
; IT IS USED BY THE SIGN-ON AND CRLF.
; POINTER IS IN HL (WHEN ENTERED AT
; TOM) AND LENGTH IN B REG.
;
TOM1:	LXI	H,MSG
TOM:	MOV	C,M	;GET A CHARACTER
	INX	H	;MOVE POINTER
	CALL	CO	;OUTPUT IT
	DJNZ	TOM	;KEEP GOING TILL B=0
	CALL	CSTS	;SEE IF AN ABORT REQUEST
	ORA	A	; WAITING.
	RZ		;NO.
;
; SEE IF CONTROL-C IS WAITING
; ABORT IF SO.
;
CCHK:	CALL	KI
	CPI	3	;CONTROL-C?
	RNZ
;
; SYSTEM ERROR ROUTINE. THIS
; WILL RESTORE THE SYSTEM AFTER
; A SYSTEM ERROR HAS BEEN TAKEN.
; THE I/O CONFIGURATION IS NOT
; AFFECTED.
;
ERROR:	CALL	MEMSIZ
	LXI	D,-22	;STACK POINTER OFFSET
	DAD	D
	SPHL		;RESET STACK
	MVI	C,'*'	;ANNOUNCE ERROR
	CALL	CO
	JMP	START	;BACK TO WORK
;
; THIS GETS A READER CHARACTER,
; AND ALSO COMPARES IT WITH "D" REG.
; IT WILL ABORT ON AN "OUT-OF-DATA"
; CONDITION.
;
RIFF:	CALL	RI	;NORMAL READER ROUTINE
	JRC	ERROR	;ABORT ON A CARRY
	CMP	D	;COMPARE W/"D" REG.
	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	MEMSIZE	;GET THE VALUE
	LXI	B,(ENDX-EXIT)
	DAD	B	;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:	MVI	C,' '
;
; THIS IS THE MAIN CONSOLE
; OUTPUT ROUTINE.
;
CO:	IN	IOBYT
	ANI	# CMSK
	JRNZ	CO0
;
; TELEPRINTER CONFIGURATION
; I/O DRIVER.
;
TTYOUT:	IN	TTS
	ANI	TTYBE
	JRZ	TTYOUT
	MOV	A,C
	OUT	TTO
	RET
CO0:	DCR	A	;CCRT?
	JRNZ	CO1	; NO.
;
; C.R.T. CONFIGURATION DRIVER.
;
CRTOUT:	IN	CRTS
	ANI	CRTBE
	JRZ	CRTOUT
	MOV	A,C
	OUT	CRTO
	RET
;
CO1:	DCR	A	;BATCH?
	JNZ	COLOC	; NO, MUST BE USER
;
; LIST OUTPUT DRIVER ROUTINE
; -AN EXTERNALLY 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:	IN	IOBYT
	ANI	# LMSK
	JRZ	TTYOUT
	CPI	LCRT
	JRZ	CRTOUT
	CPI	LINE
	JZ	LNLOC	;EXTERNAL VECTOR
	JMP	LULOC	;USER DEFINED VECTOR
;
; SEND CRLF TO PUNCH DEVICE
;
PEOL:	MVI	C,CR
	CALL	PO
	MVI	C,LF
;
; PUNCH OUTPUT DRIVER ROUTINE
;
PO:	IN	IOBYT
	ANI	# PMSK
	JRZ	TTYOUT	;PUNCH=TELEPRINTER
	CPI	PCAS	;CASSETTE?
	JRNZ	PO1	; NO.
;
PO0:	IN	PCASS	;CASSETTE DRIVER
	ANI	PCSBE
	JRZ	PO0
	MOV	A,C
	OUT	PCASO
	RET
;
PO1:	CPI	PPTP
	JZ	PTPL	;EXTERNAL VECTOR
	JMP	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
..U:	MOV	C,M	;GET MEMORY BYTE
	CALL	PO	;PUNCH IT
	CALL	HILO	;SEE IF DONE
	JRNC	..U
	CALL	MARK	;PUNCH END 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:	IN	IOBYT
	ANI	# CMSK ! # PMSK
	RNZ
	JMP	STAR0	;RETURN "QUIET"
;
; CONVERT HEX TO ASCII
;
CONV:	ANI	0FH	;LOW NIBBLE ONLY
	ADI	90H
	DAA
	ACI	40H
	DAA
	MOV	C,A
	RET
;
; GET TWO PARAMETERS, PLACE
; THEM IN DE & HL, AND THEN
; CRLF.
;
EXLF:	CALL	EXPR
	POP	D
	POP	H
;
; CONSOLE CARRIAGE RETURN &
; LINE FEED ROUTINE.
;
; THE NUMBER OF FILL CHARACTERS
; IS SET TO 3 TO ALLOW A
; LARGER NUMBER OF TERMINALS TO
; BE USED WITH THIS MONITOR.
; THE NUMBER OF FILLS MAY NOT BE
; ADJUSTED.
;
CRLF:	PUSH	H	;SAVE HL
	MVI	B,5	;CRLF LENGTH
	CALL	TOM1	;SEND CRLF
	POP	H
	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:	IN	IOBYT
	ANI	# CMSK
	JRNZ	CS0
	IN	TTS
	JMPR	CS1
CS0:	DCR	A	;CCRT
	JRNZ	CS3
	IN	CRTS
CS1:	ANI	TTYDA
	MVI	A,TRUE
CS2:	RNZ
	CMA
	RET
CS3:	DCR	A	;BATCH
	RZ
	JMP	CSLOC	;USED DEFINED VECTOR
;
; GET THREE PARAMETERS AND
; CRLF.
;
EXPR3:	INR	C
	CALL	EXPR
	CALL	CRLF
	POP	B
	POP	D
	POP	H
	RET
;
; GET ONE PARAMETER.
; NO CRLF.
;
EXPR1:	MVI	C,1
;
; THIS IS THE MAIN "PARAMETER-GETTING" ROUTINE.
; THIS ROUTINE WILL ABORT ON A NON-HEX CHARACTER.
; IT TAKES THE MOST RECENTLY TYPED FOUR VALID
; HEX CHARACTERS, AND PLACES THEM UP ON THE STACK.
; (AS GNE 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:	LXI	H,0	;INITIALIZE HL TO ZERO
EX0:	CALL	TI	;GET SOMETHING FROM CONSOLE
EX1:	MOV	B,A	;SAVE IT
	CALL	NIBBLE	;CONVERT ASCII TO HEX.
	JRC	..EX2	;ILLEGAL CHARACTER DETECTED
	DAD	H	;MULTIPLY BY 16
	DAD	H
	DAD	H
	DAD	H
	ORA	L	;OR IN THE SINGLE NIBBLE
	MOV	L,A
	JMPR	EX0	;GET SOME MORE
..EX2:	XTHL		;SAVE UP IN STACK
	PUSH	H	;REPLACE THE RETURN
	MOV	A,B	;TEST THE DELIMITER
	CALL	QCHK
	JRNC	..EX3	;CR ENTERED
	DCR	C	;SHOULD GO TO ZERO
	RZ		; RETURN IF IT DOES
..EX3:	JNZ	ERROR	;SOMETHING WRONG
	DCR	C	;DO THIS AGAIN?
	JRNZ	EXPR	; YES.
	RET		;ELSE RETURN
EXF:	MVI	C,1
	LXI	H,0
	JMPR	EX1
;
; RANGE TESTING ROUTINES.
; CARRY SET INDICATES RANGE EXCEEDED.
;
HILOX:	CALL	HILO
	RNC		;OK
	POP	D	;RETURN ONE LEVEL BACK
	RET
;
HILO:	INX	H	;INCREMENT HL
	MOV	A,H	;TEST FOR CROSSING 64K BORDER
	ORA	L
	STC		;CARRY SET=STOP
	RZ		;YES, BORDER CROSSED
	MOV	A,E	;NOW, TEST HL VS. DE
	SUB	L
	MOV	A,D
	SBB	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	H	;SAVE HL FOR LATER
	DAD	D	;GET SUM
	CALL	HLSP	;PRINT IT
	POP	H	;THIS IS LATER
	ORA	A	;CLEAR CARRY
	DSBC	D	;GET DIFFERENCE & PRINT IT
;
; PRINT H&L ON CONSOLE
;
LADR:	MOV	A,H
	CALL	LBYTE
	MOV	A,L
LBYTE:	PUSH	PSW
	RRC
	RRC
	RRC
	RRC
	CALL	..2
	POP	PSW
..2:	CALL	CONV
	JMP	CO
; THIS ROUTINE SENDS EIGHT RUBOUTS
; TO THE PUNCH DEVICE.
;
MARK:	LXI	B,08FFH	;SET-UP B&C
	JMPR	LE0
;
; THIS ROUTINE SENDS BLANKS TO THE
; PUNCH DEVICE.
;
LEAD:	LXI	B,4800H	;PRESET FOR SOME NULLS
LE0:	CALL	PO
	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	H
	CALL	MEMSIZ
	MOV	A,L
	SUI	3CH
	JRNC	..B
	DCR	H
..B:	MOV	B,H
	POP	H
	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.
;
MEMSIZ:	PUSH	B
	LXI	H,-1	;START AT THE BOTTOM
..M0:	INR	H	;FIRST FIND R/W
	MOV	A,M
	CMA
	MOV	M,A
	CMP	M
	CMA
	MOV	M,A
	JRNZ	..M0	;KEEP LOOKING FOR RAM
..M1:	INR	H	;R/W FOUND, NOW FIND END
	MOV	A,M
	CMA
        MOV     M,A
        CMP     M
        CMA
        MOV     M,A
        JRZ     ..M1    ;NOT THERE YET
..M2:   DCR     H       ;BACK UP, SUBTRACT WORKSPACE
        LXI     B,EXIT-ENDX
        DAD     B
        POP     B       ;RESTORE BC
	RET		;VALUE IN HL
;
;
RIBBLE:	CALL	RIX
NIBBLE:	SUI	'0'	;QUALIFY & CONVERT
	RC		;<0
	CPI	'G'-'0'	;>F?
	CMC		;PERVERT CARRY
	RC
	CPI	10	;NMBR?
	CMC		;PERVERT AGAIN
	RNC		;RETURN CLEAN
	SUI 'A'-'9'-1	;ADJUST
	CPI	0AH	;FILTER ":" THRU "@"
	RET
;
; SEND H&L VALUE TO PUNCH DEVICE
;
PADR:	MOV	A,H
	CALL	PBYTE
	MOV	A,L
;
; PUNCH A SINGLE BYTE
;
PBYTE:	PUSH	PSW	;NIBBLE AT A TIME
	RRC
	RRC
	RRC
	RRC
	CALL	CONV
	CALL	PO
	POP	PSW	;NEXT NIBBLE
	PUSH	PSW	;SAVE FOR CHECKSUM
	CALL	CONV
	CALL	PO
	POP	PSW	;ORIGINAL BYTE HERE
	ADD	D	;ADDED TO CHECKSUM
	MOV	D,A	;UPDATE CHECKSUM
	RET
;
;
COPCK:	MVI	C,'-'	;PROMPT FOR CONSOLE
	CALL	CO
;
PCHK:	CALL	TI
;
; TEST FOR DELIMITERS
;
QCHK:	CPI	' '	;RETURN ZERO IF DELIMITER
	RZ
	CPI	','
	RZ
	CPI	CR	;RETURN W/CARRY SET IF CR
	STC
	RZ
	CMC		;ELSE NON-ZERO, NO CARRY
	RET
;
; MAIN CONSOLE INPUT ROUTINE
;
CI:	IN	IOBYT
	ANI	# CMSK
	JRNZ	CI1
;
; TELEPRINTER ROUTINE
;
TTYIN:	IN	TTS
	RAR
	JRNC	TTYIN
	IN	TTI
	RET
;
CI1:	DCR	A	;CONSOLE=CRT?
	JRNZ	CI2
;
; C.R.T. INPUT ROUTINE
;
CRTIN:	IN	CRTS
	RAR
	JRNC	CRTIN
	IN	CRTI
	RET
;
CI2:	DCR	A	;BATCH?
	JNZ	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	H
	IN	IOBYT
	ANI	# RMSK
	CMA
	OUT	RCP	;INFORM OF DESIRE FOR INPUT
	CMA
	OUT	RCP
	JRNZ	RI3
	MOV	H,A	;CLEAR FOR TIME-OUT TEST
RI0:	IN	TTS
	RAR
	JRC	RI2
	PUSH	B
	MVI	B,0
DL0:	XTHL		;WASTE TIME
	XTHL		;FOR DELAY
	DJNZ	DL0
	POP	B
	DCR	H
	JRNZ	RI0
RI1:	XRA	A
	STC
	POP	H
	RET
RI2:	IN	TTI
RID:	ORA	A
	POP	H
	RET
RI3:	CPI	RCAS
	JRNZ	RI6
RI4:	IN	SWITCH	;TEST FOR AN ABORT
	MOV	L,A	;SAVE INITIAL STATUS
..R4A:	IN	SWITCH
	CMP	L	;SEE IF IT CHANGES
	JRNZ	RI1	;YES, ABORT
	IN	RCSS	;CASSETTE INPUT DRIVER
	RAR
	JRNC	..R4A
RI5:	IN	RCSD
	JMPR	RID
RI6:	POP	H
	CPI	RPTR
	JZ	RPTPL	;EXTERNAL ROUTINE
	JMP	RULOC	;USER VECTOR
;
; THIS ROUTINE GETS READER INPUT
; AND KILLS THE PARITY BIT.
;
RIX:	CALL	RIFF
	ANI	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	H
	CALL	CRLF
	MVI	D,0FFH	;START-OF-FILE TAG
..L0:	MVI	B,4	;FIND AT LEAST FOUR 0FFH'S
..L1:	CALL	RIFF
	JRNZ	..L0
	DJNZ	..L1
..L2:	CALL	RIFF	;4 FOUND, NOW WAIT FOR NON-0FFH
	JRZ	..L2
	MOV	M,A	;FIRST REAL DATA BYTE
	MVI	A,BELL	;TELL TTY
	OUT	TTO
..L3:	INX	H
	CALL	RIFF
	JRZ	..EL	;POSSIBLE END OF FILE
	MOV	M,A
	JMPR	..L3
..EL:	MVI	E,1	;INITIALIZE
..EL0:	CALL	RIFF
	JRNZ	..EL1
	INR	E	;COUNT QUES
	MVI	A,MAX	;LOOK FOR EOF
	CMP	E	;FOUND MAX?
	JRNZ	..EL0	;NOPE
	JMP	LADR	;YEP, PRINT END ADDR
..EL1:	MOV	M,D
	INX	H
	DCR	E	;RESTORE
	JRNZ	..EL1
	MOV	M,A	;REAL BYTE
	JMPR	..L3
;
; 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	H	;PUSH ALL REGISTERS
	PUSH	D
	PUSH	B
	PUSH	PSW
	CALL	MEMSIZ	;GET MONITOR'S STACK VALUE
	XCHG
	LXI H,	10	;GO UP 10 BYTES IN STACK
	DAD	SP
	MVI	B,4	;PICK OFF REG.
	XCHG
..R0:	DCX	H
	MOV	M,D	;SAVE IN WORKAREA
	DCX	H
	MOV	M,E
	POP	D
	DJNZ	..R0
	POP	B
	DCX	B	;ADJUST P.C. VALUE
	SPHL		;SET MONITOR STACK
	LXI H,	TLOCX
	DAD	SP
	MOV	A,M
	SUB	C	;LOOK FOR A TRAP/MATCH
	INX	H
	JRNZ	..R1
	MOV	A,M
	SUB	B
	JRZ	..R3	;NO TRAP HERE
..R1:	INX	H
	INX	H
	MOV	A,M
	SUB	C	;TEST FOR 2ND TRAP
	JRNZ	..R2
	INX	H
	MOV	A,M
	SUB	B
	JRZ	..R3
..R2:	INX	B	;NO TRAPS SET, RE-ADJUST P.C.
..R3:	LXI H,	LLOCX
	DAD	SP
	MOV	M,E	;STORE USER H&L
	INX	H
	MOV	M,D
	INX	H
	INX	H
	MOV	M,C	;AND USER P.C.
	INX	H
	MOV	M,B
	PUSH	B
	MVI	C,'@'	;DISPLAY BREAK ADDRESS.
	CALL	CO
	POP	H
	CALL	LADR
	LXI H,	TLOCX
	DAD	SP
	LXI	B,200H
..R4:	MOV	E,M	;REPLACE BYTES TAKEN FOR TRAP
	MOV	M,C	;ZERO OUT STORAGE AREA
	INX	H
	MOV	D,M
	MOV	M,C
	INX	H
	MOV	A,E
	ORA	D	;DO NOTHING IF ZERO
	JRZ	..R5
	MOV	A,M
	STAX	D	;STORE BYTE
..R5:	INX	H	;SAME THING
	DJNZ	..R4	;FOR OTHER BREAKPOINT
	EXAF		;GET ALTERNATE SET OF REG.'S
	EXX
	PUSH	H	;AND STORE IN WORKSPACE
	PUSH	D
	PUSH	B
	PUSH	PSW
	PUSH	X
	PUSH	Y
	LDAI		;GET INTERUPT VECTOR BYTE
	MOV	B,A
	LDAR		;GET REFRESH BYTE
	MOV	C,A
	PUSH	B	;SAVE
	JMP	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 RECIEVED.
;
KI:	CALL	CI	;GET CHARACTER FROM CONSOLE
	ANI	7FH	;CLEAR PARITY BIT
	RET
;
TI:	CALL	KI
	RZ		;NULL
	INR	A	;TEST FOR RUBOUT
	RM
	DCR	A
	CPI	CR	;DON'T ECHO CR'S
	RZ
	CPI	'N'	;IGNORE N'S FOR NULL CMND
	RZ
	CPI	'n'
	JRZ	..T
	PUSH	B
	MOV	C,A
	CALL	CO
	MOV	A,C
	POP	B
	CPI	'A'-1	;CONVERT TO UPPER CASE
	RC
	CPI	'z'+1
	RNC
..T:	ANI	05FH
	RET
;
; THIS ROUTINE ALLOWS EXAMINATION OF
; ANY INPUT PORT, OR THE SENDING OF
; ANY VALUE TO ANY OUTPUT PORT.
;
; QO<N>,<V>[CR]
;     OUTPUT TO PORT <N>, THE VALUE <V>
;
; QI<N>[CR]
;     DISPLAY THE PORT <N>
;
QUERY:	CALL	TI
	CPI	'O'
	JRZ	QU0
	CPI	'I'
	JNZ	ERROR
	CALL	EXPR1
	POP	B
	INP	E
BITS:	MVI	B,8	;DISPLAY 8 BITS
	CALL	BLK
..Q2:	SLAR	E
	MVI	A,'0' >1
	ADC	A	;MAKE "0" OR "1"
	MOV	C,A
	CALL	CO
	DJNZ	..Q2
	RET
QU0:	CALL	EXPR
	POP	D
	POP	B
	OUTP	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:	LDAX	B
	CMP	M
	JRZ	..B
	PUSH	B
	CALL	CERR	;DISPLAY ERRORS
	POP	B
..B:	INX	B
	CALL	HILOX
	JMPR	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:
.BYTE	'C'	;CONSOLE ASSIGNMENTS
.BYTE	'T'	;CTTY	T=TELEPRINTER
.BYTE	'V'	;CCRT	V=CRT (VIDEO MONITOR)
.BYTE	'B'	;BATCH= COMMANDS FROM READER
.BYTE	'U'	;CUSE	USER
;
.BYTE	'R'	;READER ASSIGNMENTS
.BYTE	'T'	;RTTY
.BYTE	'P'	;RPTR	P=PAPER TAPE
.BYTE	'C'	;RCAS	C=CASSETTE
.BYTE	'U'	;RUSER	USER
;
.BYTE	'P'	;PUNCH ASSIGNMENTS
.BYTE	'T'	;PTTY
.BYTE	'P'	;PPTP
.BYTE	'C'	;PCAS	C=CASSETTE
.BYTE	'U'	;PUSER	USER
;
.BYTE	'L'	;LIST ASSIGNMENTS
.BYTE	'T'	;LTTY	LIST=TELEPRINTER
.BYTE	'V'	;LCRT	LIST=CRT
.BYTE	'L'	;LINE PRINTER
.BYTE	'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	B
	MOV	A,C
	STAR
	MOV	A,B
	STAI
	POP	Y
	POP	X
	POP	PSW
	POP	B
	POP	D
	POP	H
	EXAF
	EXX
	POP	D
	POP	B
	POP	PSW
	POP	H
	SPHL
	NOP		;RESERVED FOR ENABLE INTERUPTS
	LXI	H,0
	JMP	0
;
	.WORD	0	;STORAGE AREA FOR TRAP DATA
	.BYTE	0
	.WORD	0
	.BYTE	0
;
; DISPLACEMENTS OF REGISTER
; STORAGE FROM NORMAL STACK
; LOCATION.
;
ENDX:
;
	ALOC	= 15H
	BLOC	= 13H
	CLOC	= 12H
	DLOC	= 11H
	ELOC	= 10H
	FLOC	= 14H
	HLOC	= 31H
	LLOC	= 30H
	PLOC	= 34H
	SLOC	= 17H
	TLOC	= 35H
	TLOCX	= 25H
	LLOCX	= 20H
;
	APLOC	= 09H
	BPLOC	= 0BH
	CPLOC	= 0AH
	DPLOC	= 0DH
	EPLOC	= 0CH
	FPLOC	= 08H
	HPLOC	= 0FH
	LPLOC	= 0EH
	XLOC	= 07
	YLOC	= 05
	RLOC	= 02
	ILOC	= 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")
;
	.BYTE	'A',	ALOC	!0
	.BYTE	'B',	BLOC	!0
	.BYTE	'C',	CLOC	!0
	.BYTE	'D',	DLOC	!0
	.BYTE	'E',	ELOC	!0
	.BYTE	'F',	FLOC	!0
	.BYTE	'H',	HLOC	!0
	.BYTE	'L',	LLOC	!0
	.BYTE	'M',	HLOC	!0C0H
	.BYTE	'P',	PLOC	!080H
	.BYTE	'S',	SLOC	!080H
	.BYTE	'I',	ILOC	!0
;
.RAD40	.C1976	;COPYRIGHT 1976
;
;
PRMTB:		;ADDITIONAL SET OF REGISTERS (Z-80)
;
	.BYTE	'A',	APLOC	!0
	.BYTE	'B',	BPLOC	!0
	.BYTE	'C',	CPLOC	!0
	.BYTE	'D',	DPLOC	!0
	.BYTE	'E',	EPLOC	!0
	.BYTE	'F',	FPLOC	!0
	.BYTE	'H',	HPLOC	!0
	.BYTE	'L',	LPLOC	!0
	.BYTE	'M',	HPLOC	!0C0H
	.BYTE	'X',	XLOC	!080H
	.BYTE	'Y',	YLOC	!080H
	.BYTE	'R',	RLOC	!0
	.BYTE	0C1H
;
	Z:
		;END OF PROGRAM
;
;
;
.END	BASE
;
;
   