;-------------------------------------------------
; RETYPED BY MARTIN EBERHARD 14 NOV 2013
; A FEW SMALL SYNTAX CHANGES JUST TO MAKE IT
; ASSEMBLE WITH DIGITAL RESEARCH'S ASM:
;    "-1" REPLACED WITH "0FFH" IN 3 PLACES
;    "POP M" REPLACED WITH "POP PSW" IN ONE PLACE
; SUCCESSFULLY COMPARED TO AN ACTUAL POLY-88 ROM.
;-------------------------------------------------
;
;FINAL VERSION 4.0 MONITOR NOC 22 1976
;
;COPYRIGHT 1976 BY
;POLYMORPHIC SYSTEMS
;A DIVISION OF
;INTERACTIVE PRODUCTS CORPORATION
;737 S. KELLOGG AVE.
;GOLETA, CA 93017
;
;********** 4.0 MONITOR **********
;
;WRITTEN BY             D.L.FAIMAN
;                       D.W.SALLUME
;                       R.L.DERAN
;
;POLY-88 RESIDENT MONITOR VERSION 4.0. RUNS FROM 000H
;TO 3FFH IN FIRST CPU ROM SOCKET. FRONT PANEL RESET OR JUMP
;THRU ZERO GETS A "POLY-FORMAT" ABSOLUTE TAPE LOADER
;WHICH WILL RUN THE CPU RESIDENT USART TO READ BYTE-STANDARD
;('B') OR "POLY-PHASE" ('P') AUDIO CASSETTE TAPES.
;CONTROL-Z AT ANY TIME ON SYSTEM KBD BRINGS UP FRONT PANEL
;DISPLAY WITH MEMORY MODIFY WINDOW IN HEX. COMMANDS THEN
;ALLOW MEMORY REGISTER MODIFICATION AND SINGLE-STEP/EXECUTE
;OF INTERRUPTED PGM.
;
;UTILITY PGMS AVAILABLE FOR USER ARE:
;DSPLY  PUTS CHAR ON SYSTEM VIDEO SCRN. RECOGNIZES
;       ALL STANDARD CTL CHARS AND SCROLLS TEXT UP.
;       ACCESSIBLE BY CALL TO WORMHOLE 1 (WH1) AT 0C24H.
;KI     GETS CHAR FROM SYSTEM CONSOLE KBD.
;       ACCESSIBLE FROM WORMHOLE ZERO (WH0) AT 0C20H.
;USRTI  GETS CHAR FROM USART BACKGROUND LOAD
;       TYPE ROUTINE.
;HEX0   PUTS OUT LOW NIBBLE OF A IN HEX THRU WH1
;BYTE   PUTS OUT A IN HEX THRU WH1.
;DEOUT  PUTS OUT D,E IN HEX THROUGH WH1.
;HEXC   GETS A HEX NUMBER UP TO 2 BYTES LONG IN H,L FROM
;       WH0, ECHOING ON WH1. NON-HEX CHARACTER
;       TERMINATES INPUT. THE TERM. CHAR IS LEFT IN A.
;MOVE   TRANSFERS #BYTES IN BC FROM ADDR IN HL TO ADDR IN DE.
;       TERMINATES WITH HL=HL+BC,DE=DE+BC,BC=0.
;IORET  A SECTION OF CODE THAT TERMINATES AN
;       INTERRUPT SERVICE ROUTINE BY RESTORING
;       ALL REGS IN STANDARD ORDER, EI, RET.
;TIME   EXECUTES 60 TIMES A SECOND AUTOMATICALLY, INCREMENT-
;       ING FOUR BYTE LOCATION CALLED TIMER. IF TIMER=0
;       ALL REGS SAVED AND ROUTINE AT ADDR IN LOCATION
;       WAKEUP IS JUMPED TO. THIS ROUTINE MAY TERMINATE
;       BY USING IORET.
;
;******SYSTEM RAM ALLOCATION******
;
;DEDICATED LOCATIONS.
;
	ORG	0C00H	;BEGIN ONBD RAM
TIMER:	DS	4	;INCREMENTED BY 60HZ CLOCK.
			;LOW BYTE=LEAST SIGNIFICANT.
TANI:	DS	4	;TIME AT NEXT INT. USED BY
TBUFF:	DS	2	;USART TRANSMIT BUFFER
			;FLAG AND ONE BYTE BUFFER.
			;USED BY EXTERNAL DUMPERS.
RBUFF:	DS	2	;USART RECEIVE BUFFER FLAG
			;AND ONE BYTE BUFFER.
			;USED BY MONITOR TAPE LOADER.
KBUFF:	DS	2	;KBD BUFF-FULL FLAG AND BUFFER
POS:	DS	2	;CURSOR POSITION FOR DSPLY
;INTERRUPT SERVICE ROUTINE ADDRESS TABLE.
SRA1:	DS	2	;VI7
SRA2:	DS	2	;VI6
SRA3:	DS	2	;VI5
SRA4:	DS	2	;VI4: USART INT',FIRST INITED SR
SRA5:	DS	2	;VI3: KBD INT.
WAKEUP:	DS	2	;ADDRESS JUMPED TO WHEN CLOCK TIME
			;OUT IS IN THIS LOC. IT FUNCTIONS
			;EXACTLY LIKE SRA, BUT US ACTUALLY
			;JUMPED TO BY THE CLOCK SOFTWARE.
			;EFFECTIVELY SIMULATES A HARDWARE
SRA7:	DS	2	;SINGLE-STEP INTERRUPT. NORMALLY
			;AT ITS INITED ADDR WHICH BRINGS
			;UP FRONT PANEL DISPLAY. IT CAN BE
			;CHANGED FOR EXTERNAL PGMS TO USE FOR
			;DEBUGGING OR FANCY PGMING.
;VIDEO SCREEN ADDRESS PARAMETERS USED IN DSPLY.
;INITED TO F800H,FCH, BUT MAY BE CHANGED AFTER
;SYSTEM STARTS UP.
SCEND:	DS	1	;SCREEN END FOR DISPLAY
SCRHM:	DS	1	;SCREEN HOME FOR DOSPLAY
;WORMHOLE VECTOR. THIS TABLE IS FULL OF CALL-RETURN PAIRS
;WHICH CALL SYSTEM I/O PROGRAMS. THEY MAY BE CHANGED AFTER
;INITIALIZATION RO CALL ANY PHYSICAL DEVICE DRIVER IT IS
;DESIRED TO INSTALL. THIS IS NORMALLY DONE WITH LINK PR
;AS DESCRIBED IN MANUALS. THE FIRSTTWO WORMHOLES ARE INITED
;TO THE SYSTEM CONSOLE KBD AND SYSTEM VIDEO DISPLAY.
;ALL USER I/O SHOULD BE DONE THRU THE WH'S RO INSURE
;COMPATIBILITY WITH ANY SUPERVISOR SYSTEM AND TO ALLOW
;DYNAMIC REASSIGNMENT OF I/O FOR FIXED USER OBJECT PGMS.
WH0:	DS	4	;CONSOLE IN: INITED TO CALL SYS. KBD
WH1:	DS	4	;CONSOLE OUT: INITED TO CALL DSPLY
WH2:	DS	4	;SYSIN: USED EXTRN;Y BY TAPE OR
			;INPUT DRIVERS. A CALL GETS BYTE
INITLEN	EQU	SRA4-$	;LENGTH OF INITIALIZED MEMORY
WH3:	DS	4	;SYSOT: USED BY TAPE OR DISK OUT
			;DRIVERS. A CALL OUTPUTS BYTE IN A
WH4:	DS	4	;SYSIN2: SECONDARY SYSTEM INPUT.
WH5:	DS	4	;SYSOT2: SECONDARY SYSTEM OUTPUT.
WH6:	DS	4	;READ: TEXT TYPE INPUT USED
			;BY EXTRNL TAPE,DISK,KBD DRIVERS
WH7:	DS	4	;LIST: TEXT TYPE OUTPUT TO LINE
			;PRINTERS OR TEXT FILE ETC.
WH8:	DS	4	;AUX WH: IN
WH9:	DS	4	;AUX WH: OUT
;VCB BLOCKS TO BE TEMPORARILY SWAPPED FOR SCRHM,SCEND AND POS
;IN ORDER TO USE DSPLY ON OTHER THAN SYSTEM VIDEO DISPLAY.
;A LINK PGM DOES SWAPPING, AND IS CALLED FROM WH1 IN-
;STEAD OF DSPLY. IT THEN CALLS DSPLY, AND RESTORES
;CONTENTS OF SCRM,SCEND, AND POS BEFORE RET..
VCB2:			;SECONDARY VDO SCRN CONTEXT
SCND2:	DS	1
SCRH2:	DS	1
POS2:	DS	2
VCB3:			;TERTIARY VDO SCRN CTX.
SCND3:	DS	1
SCRH3:	DS	1
POS3:	DS	2
;
;TEMPORARY LOCATIONS USED BY FRONT PANEL MODE.
;
WINDOW:	DS	2	;MEM. MODIFY WINDOW POINTER.
SAVPC:	DS	2	;USED BY S.S.WHEN STACK UNAVAILABLE
;
;TEMPORARY LOCATIONS USED BY TAPE LOADER
;
FNAME:	DS	8	;"FIND" NAME FOR TAPE LOADER.
RNAME:	DS	8	;READ RECD NAME -FOUND ON TAPE.
RRN:	DS	2	;READ RECD NUMBER.
RLEN:	DS	1	;READ RECD LENGTH.
RADR:	DS	2	;READ RECD ADDR (BIAS).
RTYPE:	DS	1	;READ RECD TYPE.
;FREE ONBOARD RAM ONWARDS.
;
;***MONITOR PROGRAM***
;
;VECTOR INTERRUPT LOCATIONS
	ORG	0
RESET:	LXI	SP,STACK ;FRNT PANEL RST OR POWER UP GET
	JMP	RST1	;RST1 INITS SYSTEM RAM.ENDS IN TAPE
;
;THESE TWO INSTRUCTIONS CAN BE CALLED TO GET THE
;ADDDRESS OF THE CALLING PROGRAM INTO H,L.  THIS
;IS NECESSARY IN WRITING SELF RELOCATING CODE.
;
	POP	H
	PCHL
VI6:	PUSH	PSW	;STANDARD REGISTER PUSH SEQUENCE
	PUSH	B
	PUSH	D
	PUSH	H
	LHLD	SRA1	;GET SERVICE ROUTINE ADDRESS
	PCHL		;GO EXECUTE IT. IT WILL RETRN THR
VI5:	PUSH	PSW	;SAME AS ABOVE
	PUSH	B
	PUSH	D
	PUSH	H
	LHLD	SRA2
	PCHL
VI4:	PUSH	PSW
	PUSH	B
	PUSH	D
	PUSH	H
	LHLD	SRA3
	PCHL
VI3:	PUSH	PSW
	PUSH	B
	PUSH	D
	PUSH	H
	LHLD	SRA4
	PCHL
VI2:	PUSH	PSW
	PUSH	B
	PUSH	D
	PUSH	H
	LHLD	SRA5
	PCHL
CLOCK:	PUSH	PSW	;THE CLOCK INT ALWAYS GOES TO THE
	PUSH	B	;TIMER COUNTER ROUTINE.
	PUSH	D
	PUSH	H
	JMP	TIME
	DB	0
SS:	PUSH	PSW
	PUSH	B
	PUSH	D
	PUSH	H
	LHLD	SRA7
	PCHL
TIME:	OUT	8	;WNABLE INT FOR NEXT 60HZ CYCLE
	LXI	H,TIMER	;COUNTER LOCATION
	MVI	A,4	;4 BYTES TO INCR
TIME2:	INR	M	;INC ONE LOC.
	JNZ	IORET	;DONE, STANDARD RETURN
	INX	H
	DCR	A
	JNZ	TIME2
	LHLD	WAKEUP	;CNTR IS ZERO, SO INITIATE  WAKEUP
	PCHL		;GO TO THE WAKEUP TASK
;USART INTERRUPT SERVICE ROUTINE FOR INPUT
;ITS ADDRESS IS INITED INTO SRA4.
USRTSR:	IN	1
	ANI	2
	JZ	IORET
	IN	0
	LXI	H,RBUFF
;THIS CODE IS SHARED BY ANY SERVICE ROUTINE
;WHICH HAS FOUND A CHARACTER.  HL SHOULD HAVE THE
;BUFFER ADDRESS, FLAG FIRST-THEN ONE BYTE BUFF.
;ONLY USED BY INPUT ISR'S.
;
IOPUT:	MVI	M,0	;ZERO THE FLAG: WE GOT THE CHAR
	INX	H	;MOVE UP TO DATA BUFFER
	MOV	M,A	;PUT CHAR IN DATA BUFF
			;FALL THRU TO IORET
IORET:	POP	H	;THIS CODE SECTION CAN BE JUMPED TO
			;FOR STANDARD SEQ.REG.POPS AND
			;AS FOR ANY INTERRUPT SERVICE RTN
	POP	D
	POP	B
	POP	PSW
	EI
	RET
;WORMHOLE END OF KBD CHAR FETCH RTNS.
;WHEN CALLED BY WH0,WAITS FOR VALID DATA FLG IN KBUFF,
;THEN RETURNS CHAR FROM KBUFF+1 ON A.
KI:	PUSH	H	;WE CAN ONLY WRECK A, SO SAVE H,L
	LXI	H,KBUFF
KI1:	MOV	A,M	;GET FLAG
	ORA	A	;IS IT ZERO?
	JNZ	KI1	;NO,TRY AGAIN
	DCR	M
	INX	H
	MOV	A,M
	POP	H
	RET
USRTI:	PUSH	H
	LXI	H,RBUFF
	JMP	KI1
;
;****** VIDEO DISPLAY DRIVER ******
;
;DSPLY IS THE FAMOUS "TELETYPE SIMULATOR" WHICH
;DRIVES A POLYMORPHICS VTI AND SCROLLS TEXT WHEN
;THE SCRN FILLS.  IT RECOGNIZES ALL IMPORTANT CONTROL
;CHARACTERS AND USES THE SCRHM,SCEND, AND POS LOCATIONS
;IN SYSTEM RAM WHICH ARE INITIALIZED TO GIVE A SCREEN
;AT 0F800H TO 0FBFFH ON POWER-UP OR FPRST.  AT
;THE SAME TIME, ITS OWN ADDRESS IS PUT IN WH1 FOR THE
;DEFAULT SYSTEM CONSOLE DISPLAY DRIVER.
;
DSPLY:	PUSH	PSW	;A WH PGM MUST SAVE ALL REGS
	PUSH	B
	PUSH	D
	PUSH	H
	LHLD	POS
CTLX	EQU	18H	;ASCII "CAN" CLEARS CUR. LINE
	CPI	CTLX
	JZ	CLINE
	LXI	D,SCRL	;ALL DSPLY CHARACTER
	PUSH	D	;HANDLING SUBROUTINES EXCEPT
			;CLINE RETUEN TO SCRL TO CHECK
			;SCRN OVERFLOW AND SCROLL
			;IF NECESSARY.
	MVI	M,07FH	;BLANK THE CURSOR SO WE
			;WON'T HAVE TO LATER.
			;USE A GRAPHICS BLANK
			;INSTEAD OF A SPACE.
RB	EQU	7FH	;ASCII "DEL" OR RUBOUT
			;BACKSPACE AND DELETE CHAR.
	CPI	RB
	JZ	RBR
	CPI	20H	;IF CHAR IS ABOVE 20H, PRINT IT
	JNC	NORM	;ELSE IT'S NOT A NORMAL CHAR,
			;SO TEST IT FOR VALID CTL CODE
CR	EQU	0DH	;CARRIAGE RETURN. MOVES DOWN
			;A LINE, LEFT-ZEROES CURSOR.
	SUI	CR
	JZ	CRR
FF	EQU	0CH	;FORM FEED. CLEARS SCRN, HOMES
			;CURSOR.
	INR	A
	JZ	FFR
VT	EQU	0BH	;VERTICAL TAB. JUST HOMES CURSOR.
	INR	A
	JZ	VTR
TAB	EQU	09H	;TAB. MOVES CURSOR RIGHT TO
			;NEXT EVEN/8 POSITION.
	INR	A
	INR	A
	RNZ		;IF NOT A TAB, RETURN
	MOV	A,L	;BACK UP CURSOR TO EVEN/8
	ANI	0F8H
	MOV	L,A
	LXI	B,8	;MOVE UP 8 POSITIONS
	DAD	B
	RET
NORM:	ORI	80H	;WE HAVE A PRINTING CHAR, SO MAKE
			;IT INTO CHAR AREA OF VTI SPACE.
	MOV	M,A	;PUT IT IN REFRESH MEM.
	INX	H	;MOVE UP A POSITION.
	RET		;GOTO SCRL.
;
;SCRL SCROLLS TEXT UP THE SCREEN IF NECESSARY,
;THEN FALLS INTO CURP, WHICH RESTORES THE CURSOR
;AND RETURNS TO USER THRU IORET.
;
SCRL:	LDA	SCEND
	CMP	H
	JNZ	CURP
	LHLD	SCEND
	MOV	A,H
	SUB	L
	MOV	D,H
	MVI	L,40H
	MVI	E,0
	MOV	C,L
	MOV	B,A
	CALL	MOVE
	DCX	H
;
;CLINE CLEARS THE CURRENT LINE
;
CLINE:	MVI	A,3FH
	MOV	D,A
	ORA	L
	MOV	L,A
WIPE:	MVI	M,7FH
	DCX	H
	DCR	D
	JNZ	WIPE
CURP:	MVI	M,0FFH
	SHLD	POS
	JMP	IORET
RBR:	DCX	H	;RUBOUT ROUTINE
	RET
CRR:	LXI	B,64	;CARRIAGE RETURN RTN.
	MOV	A,L
	ANI	0C0H
	MOV	L,A
	DAD	B
	RET
FFR:	CALL	VTR	;FORM FEED ROUTINE
FF1:	MVI	M,7FH
	INX	H
	CMP	H
	JNZ	FF1
VTR:	LHLD	SCEND	;VERTICAL TAB RTN.
	MOV	A,L
	MVI	L,0
	RET
;
;MOV MOVES -BC BYTES FROM THE AREA STARTING AT
;(HL) TO THE AREA STARTING AT (DE)
;
MOVE:	MOV	A,M
	STAX	D
	INX	D
	INX	H
	INR	C
	JNZ	MOVE
	INR	B
	JNZ	MOVE
	RET
;
;KEYBOARD INTERUPT SERVICE ROUTINE FOR SYSTEM CONSLE
;KEYBOARD AT 0F8H.  ITS ADDRESS  IS INITED INTO SRA5.
;IT WATCHES FOR CTL/Z.  IF IT FINDS ONE, IT FALLS
;THRU INTO SAVE, THUS ENTERING FRONT PANEL MODE.
;KBD ADDR IS FIXED BY SCREEN ADDR, WHICH IS 0F800H
;SINCE A POLYMORPHIC VTI USES SAME DECODER FOR KBD
;AS FOR VIDEO REFRESH MEMORY.
;
KSR:	IN	0F8H
	LXI	H,KBUFF
CTLZ	EQU	01AH
	CPI	CTLZ
	JNZ	IOPUT
;
;****** FRONT PANEL MODE ******
;
;SAVE IS THE ENTRY POINT INTO FRONT PANEL
;MODE IF REGISTERS HAVE BEEN ALREADY PUSHED IN
;STANDARD SEQUENCE.  IT PUSHES PC AND SP
;ON TOP OF REGISTERS FOR DISP TO USE.
;
SAVE:	LXI	H,10
	DAD	SP
	PUSH	H
	DCX	H
	MOV	D,M
	DCX	H
	MOV	E,M
	PUSH	D
;
;WARM IS THE EHTRY POINT TO FRONT PAMEL MODE
;IF PC AND SP HAVE ALREADY BEEN PUSHED DOWN
;ON TOP OF REGISTERS IN STANDARD SEQUENCE
;
WARM:	CALL	CLEAR
	EI
	CALL	VTR	;SET HL TO BEGINNING OF SCREEN
	LXI	B,337	;OFFSET FROM SCRHM FOR UPARROW
	DAD	B
	MVI	M,9CH	;VTI CODE FOR UPARROW
	LXI	B,175H	;OFFSET FROM UPARROW FOR
			;RIGHT ARROW
	DAD	B
	MVI	M,9AH	;VTI CODE FOR RIGHT ARROW
;
;DISP IS THE ENTRY POINT TO FRONT PANEL MODE IF
;RHE SCREEN ALREADY SHOWS A FRONT PANEL DISPLAY.
;IT DOES NOT CLEAR THE SCREEN, SO WILL NOT
;BLINK WHEN SCREEN IS UPDATED.
;
DISP:	MVI	A,CTLX	;ERASE LAST COMMAND ON SCRN
	CALL	DSPLY
	MVI	A,0BH
	CALL	DSPLY
	MVI	A,6
	LXI	H,0
	DAD	SP
	LXI	B,MSG
	PUSH	PSW
DISP1:	STC
	CALL	FLDSY
	CALL	FLDSY
	CALL	BLK
	MOV	E,M
	INX	H
	MOV	D,M
	INX	H
	CALL	DEOUT
	POP	PSW
	DCR	A
	JZ	FLAGS
	PUSH	PSW
	PUSH	B
	XCHG
	LXI	B,-3
	DAD	B
	XCHG
	CALL	HEXO8
	POP	B
	JMP	DISP1
MSG:	DB	'PCSPHLDEBCAFCMZ'
;
;FIELD DISPLAY PUTS OUT CHAR IN ADDR IN B IFF CY SET.
;IFF CY ZERO, PUT BLANK TO VDO DISPLAY.
;IN EITHER CASE, B IS INCREMENTED.
;
FLDSY:	PUSH	PSW
	CNC	BLK
	LDAX	B
	CC	DSPLY
	POP	PSW
	INX	B
	RET
FLAGS:	CALL	TABBER
	MOV	A,E
	RRC
	CALL	FLDSY
	RLC
	RLC
	CALL	FLDSY
	RLC
	CALL	FLDSY
;
;MMOD PLACES THE MEMORY MODIFY DISPLAY
;ON THE SCREEN   WINDOW POINT TO THE BYTE
;TO BE MODIFIED
;
MMOD:	CALL	CROUT
	CALL	CROUT
	LHLD	WINDOW
	LXI	B,-32
	DAD	B
	MVI	C,8
	XCHG
MMOD1:	CALL	DEOUT
	CALL	TABBER
	MVI	A,7FH
	CALL DSPLY
	CALL	HEXO8
	DCR	C
	JNZ	MMOD1
;
;COMD CALLS HEXC TO GET HEX NUMBERS TO BE ENTERED INTO MEMORY
;THEN EVALUATES THE NON-HEX TERMINATING CHARACTER TO SEE IF
;IT IS A COMMAND
;
COMD:	CALL	HEXC
	MOV	A,C
	ORA	A
	CNZ	STORE
	MOV	A,B
	LXI H,DISP
	PUSH	H
	LXI	H,MTBL
	CALL	LOOKUP
	MVI	D,0
	JNC	ADDIT
	CALL	LOOKUP
	RC
	LXI	H,RTN
	DAD	D
	PCHL
;
;LOOKUP COMPARES THE ACCUMULATOR
;AGAINST THE ENTRY IN TABLE
;POINTED TO BY HL AND RETURNS WITH
;THE BYTE FOLLOWING IT IN E.
;CARRY FLAG SET IF NO MATCH
;TABLE MUST END IN 0FFH,EACH ENTRY IS 2 BYTES
;
LOOKUP:	CMP	M
	INX	H
	MOV	E,M
	RZ
	INX	H
	MOV	E,M
	INR	E
	JNZ	LOOKUP
	INX	H
	STC
	RET
;
;MTBL IS THE TABLE OF COMMANDS FOR
;MEMORY MODIFY
;
MTBL:	DB	' '	;SPACE MOVES POINTER FORWARD
	DB	17
	DB	8	;BACKSPACE MOVES BACKWARDS ONE
	DB	15
	DB	13	;RETURN MOVES FWD 8 BYTES
	DB	24
	DB	10	;LINE FEED MOVES BACK 8 BYTES
	DB	8
	DB	0FFH	;END OF 1ST HALF TABLE
	DB	'G'	;GO
	DB	G-RTN
	DB	'S'	;SET REGISTER
	DB	SETR-RTN
	DB	'X'	;EXECUTE (SINGLE STEP)
	DB	X-RTN
	DB	'I'	;INDIRECT
	DB	IND-RTN
	DB	'T'	;TAPE LOADER
	DB	TAPE-RTN
	DB	'L'	;LOAD MEMORY POINTER
	DB	LOD-RTN
	DB	'J'	;JUMBO - LOAD 2 BYTES
	DB	DOUBLE-RTN
	DB	0FFH
;
;RST1 IS THE INITIALIZATION ROUTINE
;IT SETS UP THE WORMHOLES USED IN THE
;MONITOR, THEN CHECKS FOR A SECOND ROM
;AND CALLS IT IF IT IS THERE
;
RTN	EQU	$	;ALL ROUTINES REFERENCE TO HERE
RST1:	LXI	D,SRA4
	LXI	H,INITER
	LXI	B,INITLEN
	CALL	MOVE	;INIT WORMHOLES
	LDA	400H	;GET 1ST BYTE OF 2ND ROM
	INR	A	;IF IT WAS NOT 0FFH
	CNZ	400H	;CALL IT
	EI		;TURN ON INTERRUPTS
;
;TAPE IS THE BOOTSTRAP LOADER ROUTINE
;IT EXPECTS TO GET A B,P,OR C OR IT WILL
;WAIT FOR ONE
;
TAPE:	CALL	CLEAR
START:	CALL	LCFLD	;GET A CASE-FOLDED B OR P
	MOV	C,A	;SAVE THE B OR P FOR ECHOING.
	CPI	'P'	;POLYPJASE
	JZ	POLY
	SUI	'B'	;BYTE STANDARD
	JZ	BITE
	DCR	A
	JZ	HEAD	;CONTINUE
	JMP	START	;NOT A B OR C OR P : TRY AGAIN
;
;
;
;DOUBLE GETS A HEX NUMBER FROM THE CONSOLE
;AND LOADS IT INTO THE NEXT 2 BYTES IN MEMORY
;(OR A REGISTER) LOW ORDER BYTE FIRST
;J<HEX #>(CR)
;
DOUBLE:	CALL	HEXC
	XCHG
	LHLD	WINDOW
	MOV	M,E
	INX	H
	MOV	M,D
	RET
;
;LOD LOADS WINDOW WITH THE NUMBER
;FOLLOWING THE L COMMAND
;L<HEX NUMBER>(CR)
;
LOD:	CALL	HEXC
SVW:	SHLD	WINDOW
	RET
;
;ADDIR MOVES THE MEMORY POINTER (WNDOW)
;BY FORWARD OR BACKWARDS BY
;THE VALUE IN E (D=0)
;E IS OFFSET BY 16
;
ADDIT:	LHLD	WINDOW
	LXI	B,-16
	DAD	B
	DAD	D
	JMP	SVW
;
;IND LOADS THE NEXT 2 BYTES IN MEMORY
;INTO WINDOW
;
IND:	LHLD	WINDOW
	MOV	E,M
	INX	H
	MOV	D,M
	XCHG
	JMP	SVW
;
;STORE STORES THE BYTE IN L (ENTERED
;FROM CONSOLE) INTO MEMORY
;
STORE:	MOV	A,L
	LHLD	WINDOW
	MOV	M,A
	RET
;
;X EXECCUTES ONE INSTRUCTION POINTED TO
;BY SAVPC AND RETURNS TO RST7
;
X:	POP	H	;2 DUMMY POPS
	POP	H	;GET PC
	SHLD	SAVPC	;SAVE IT
	POP	H
	POP	H	;GET REGISTERS
	POP	D
	POP	B
	POP	PSW
	XTHL	;RESTORE PC
	LHLD	SAVPC
	XTHL
	EI
	OUT	12	;ENABLE SINGLE STEP LOGIC
	RET	;GO TO USER PGM.
;
;G ACTS THE SAME AS X BUT DOES NOT
;ENABLE SINGLE STEP LOGIC, AND
;THEREFORE DOES NOT RETURN
;TYPING CTL-Z WILL RETURN FROM THE
;PROGRAM BEING EXECUTED AND SAVE
;ALL REGISTERS
;IF A RST7 IS ENCOUNTERED THIS WILL
;ALSO HAPPEN
;
G:	POP	H
	POP	H
	SHLD	SAVPC
	POP	H
	POP	H
	POP	D
	POP	B
	POP	PSW
	XTHL
	LHLD	SAVPC
	XTHL
	RET
;
;SETR POINTS TO ONE OF THE 8080 REGISTERS
;AS SAVED IN MEMORY
;MAY BE USED WITH JUMBO COMMAND TO
;SET A REGISTER PAIR, OR WITH OTHER
;COMMANDS TO SET INDIVIDUAL REGISTERS
;S<P/H/D/B/A>
;
SETR:	CALL	LCFLD	;GET REGISTER DESIGNATION
	LXI	H,RTAB	;AND LOOK UP POSITION
	CALL	LOOKUP
	RC		;RETURN IF NOT VALID REGISTER
	LXI	H,2
	MOV	D,H	;SET D-0
	DAD	SP	;ADD 2 TO STACK POINTER (FOR CALL)
	DAD	D
	JMP	SVW	;PUT WINDOW
;
;RTAB IS A TABLE OF THE 8080 REGISTERS
;AND THEIR RELATIVE POSITION AS
;STORED ON THE STACK
;
RTAB:	DB	'P'
	DB	0
	DB	'H'
	DB	4
	DB	'D'
	DB	6
	DB	'B'
	DB	8
	DB	'A'
	DB	10
	DB	0FFH
;
;GET IS USED BY THE LOADER TO GET
;C BYTES AND STORE THEM AT HL TO HL+C-1
;
GET:	XRA	A
	MOV	B,A
GET1:	CALL	TI
	MOV	M,A	;PUT BYTE IN MEMORY
	INX	H	;INCREMENT POINTER
	DCR	C
	JNZ	GET1
;
;TI GETS A CHARACTER FROM WH2
;AND KEEPS A CHECKSUM IN B
;D IS USED AS A TEMPORARY
;
TI:	CALL	WH2
	MOV	D,A
	ADD	B
	MOV	B,A
	MOV	A,D
	RET
;
;SETUP PUTS IMMEDIATE BYTES INTO BAUD RATE GEN.,
;AND THEN USART CTL PORT.  THE TERM CHAR IS 00H,
;WHICH IS ALSO XMTED TO USART, LEAVING IT IDLING.
;WHEN DONE, JUMPS TO LOC. AFTER
;IMMED BYTES.
;
SETUP:	POP	H	;GET ADDR FOLLOWING CALL TO SETUP
	MOV	A,M	;GET DATA FOR BRG
	OUT	4	;PUT IN BRG
SET1:	INX	H	;NEXT BYTE
	MOV	A,M
	OUT	1	; USART PORT
	ORA	A	;WAS THAT 00H?
	JNZ	SET1	;NO,NEXT BYTE
	PCHL		;JUMP TO THE 00H,EXEC. IT AS A NOP
			;CONTINUE
;
;POLY AND BITE CONTAIN SETUP
;INFORMATION FOR POLYPHASE OR BYTE
;OPERATION OF THE USART
;
POLY:	CALL	SETUP	;THE NEXT BYTES GOTO BRG AND USART
	DB	005H	;TO BRG: SELECT DEV 0, 2400 BAUD
	DB	0AAH	;FAKE SYNCH CHAR IF USART EXPECTS ONE
	DB	040H	;INTERN. RESET. GETS USART TO MODE LEVEL
	DB	00CH	;MODE CODE FOR SYNCHRONOUS, 8 BIT
			;NO PARITY, INTERN. SYNC, 2 SYNC BYTES
	DB	0E6H	;FIRST SINC CHAR. TO SRCH FOR
	DB	0E6H	;2ND SYNC CHAR.
	DB	000H	;LEAVE COMMAND AT 00H (IDLE), RTN
	JMP	NAMER
BITE:	CALL	SETUP
	DB	006H	;TO BRG: SEL. DEV. 0 300 BAUD
	DB	0AAH	;FAKE SINCH CHAR IF USART EXPECTS ONE
	DB	040H	;INT. RST. GETS US TO MODE LEVEL
	DB	0CEH	;MODE: ASYNCH., 8 BITS, NO PARITY
			;2 STOP BITS, 16X CLOCK SCALING
	DB	000H	;FOR NOW COMMAND IS IDLE
NAMER:	LXI	H,FNAME
	MOV	A,C	;ECHO THE B OR P
	CALL	WH1
	CALL	CROUT	;OUTPUT CR
	MVI	C,9
;
;NAM0 GETS THE NAME OF THE FILE
;TO BE LOADED FROM THE CONSOLE
;
NAM0:	CALL	WH0
	CALL	WH1	;ECHO CHAR.
	CPI	13
	JZ	NAM	;DONE IF CR
	MOV	M,A	;STORE IN MEMORY
	INX	H
	DCR	C
	JNZ	NAM0	;DONE IF 9 CHARACTERS
NAM:	MVI	M,20H	;FILL OUT WITH BLANKS
	INX	H
	DCR	C
	JP	NAM
;
;HEAD SEARCHES FOR A RECORD HEADER
;AND STORES IT IN RNAME
;COMP THEN COMPARES THE NAME AGAINST
;THE NAME IT IS SEARCHING FOR
;GETS NEXT HEADER IF NOT MATCH
;AFTER DISPLAYING NAME AND RECORD NUMBER
;IF CHECKSUM ERROR GOES TO ERROR
;
HEAD:	LXI	H,DNAME
	PUSH	H	;ANYTHING RETURNING AFTER HERE
			;WILL DISPLAY THE RECD NAME AND RECD#
HEAD6:	MVI	A,096H	;START USART READING, ENTER SEARCH MODE
			;IF SYNCHRONOIS, AND START MOTOR
	OUT	1	;TO USART CTL PORT
	CALL	WH2
HEAD7:	CPI	0E6H	;SYNC CHAR.
	JNZ	HEAD6	;RESYNC USART
	CALL	WH2
	CPI	001H	;SOH CHAR.
	JNZ	HEAD7
	LXI	H,RNAME
	MVI	C,14
	CALL	GET	;GET HEADER
	JNZ	ERROR
	LXI	H,RNAME	;COMPARE NAMES
	LXI	D,FNAME
	MVI	C,8
COMP:	LDAX	D
	CMP	M
	RNZ		;NOT MATCH
	INX	D
	INX	H
	DCR	C
	JNZ	COMP	;FALL THRU IF MATCH
	LHLD	RADR	;GET LOAD ADDRESS AND
	LDA	RLEN	;LENGTH IN PREPARATION FOR LOADING
	MOV	C,A
	LDA	RTYPE	;CHECK RECORD TYPE
	ORA	A
	JZ	GETD	;DATA, LOAD INTO RAM
	DCR	A
	JZ	COMNT	;COMMENT, DISPLAY IT
	DCR	A
	JZ	STOP	;END OF FILE, STOP TAPE
	DCR	A
	RNZ		;NOT TYPES 1-3, TRY AGAIN
	OUT	1	;STOP TAPE
	PCHL	;AUTO-EXECUTE, GO TO PGM.
;
;WERE DONE LOOKING AT OR READING A RECD, SO DISPLAY
;NAME AND RECD# OF LAST SEEN RECD.
;
DNAME:	LXI	B,RNAME
	MVI	D,8
DNAM2:	STC
	CALL	FLDSY
	DCR	D
	JNZ	DNAM2
	CALL	BLK
	LHLD	RRN	;DISPLAY R/N
	XCHG
	CALL	DEOUT
	CALL	CROUT
	JMP	HEAD
;
;COMNT DISPLAYS COMMENTS ON THE SCREEN
;
COMNT:	CALL	WH2	;ECHO TAPE ON CRT FOR A COMMENT
	CALL	DSPLY
	DCR	C
	JNZ	COMNT
	JMP	HEAD6
;
;GETD GETS DATA AND RETURNS IF CS2 IS GOOD
;OTHERWISE IT STOPS THE TAPE
;AND PRINTS A "?"
;
GETD:	CALL	GET
	RZ
ERROR:	MVI	A,'?'
	CALL	DSPLY
STOP:	CALL	CROUT
	XRA	A
	OUT	1	;OUTPUT NUL TO STOP USART
	POP	H	;CLEAN UP STACK
	JMP	START
;
;***** UTILITY SUBROUTINES *****
;
;THESE SUBROUTINES MAY BE USED EXTERNALLY, SO WE WANT
;THEM IN KNOWN LOCATIONS.
;
;HEXO8 OUTPUTS 8 BYTES FROM THE ADDRESS POINTED
;TO BY D,E LEAVING D,E POMITING TO THE NEXT
;LOCATION IN MEMORY.  IT PUTS THE BYTES OUT
;IN HEX WITH A SPACE BETWEEN THEM AND A
;CARRIAGE RETURN AT THE END OF THE LINE.
;
;D2 IS THE ACTUAL LOOP WHICH HEXO8 USES
;IT PUTS OUT THE NUMBER OF BYTES IN B
;INCRAMENTS D AND THEN PUTS OUT A
;CARRIAGE RETURN.
;
HEXO8:	MVI	B,8
D2:	CALL	BLK
	LDAX	D
	CALL	BYTE
	INX	D
	DCR	B
	JNZ	D2
;
;CROUT, CLEAR, BLK, AND TABBER
;OUTPUT A CARIAGE RETURN, FORM FEED, BLANK,
;OR HORIZONTAL TAB TO THE CRT DRIVER, RESPECTIVELY
;
CROUT:	MVI	A,CR	;PUT CAR RETRN ON CONSLE DSPLY
	JMP	DSPLY
CLEAR:	MVI	A,12	;CTL-L (FORM FEED)
	JMP	DSPLY
BLK:	MVI	A,' '	;SPACE
	JMP	DSPLY
TABBER:	MVI	A,9	;CTL-I TAB
	JMP	DSPLY
;
;LCFLD (LOWER CASE FOLD). GETS A CHAR FROM WH0.
;IF AN LC CHAR WAS FOLDED, CY=0,ELSE CY=1.
;WATCH RUBOUTS- THEY'RE FOLDED TO 5FH FROM NORMAL 7FH.
;
LCFLD:	CALL	WH0	;GET CHAR
	CPI	060H	;IF UPPER CASE,FORGET IT
	RC		;UC LETTERS ARE LESS THAN 60H
	SUI	020H	;FOLD THIS LOWER CASE LETTER ON
	RET
;
;HEXC INPUTS VARIABLE LENGTH HEX FROM WH0, ECHOING IN DSPLY.
;TERM CHAR IS ANY NON-HEX CHAR, AND IT IS RETURNED IN B.
;DIGIT COUNT RETURNED IN C.
;
HEXC:	LXI	H,0	;ZERO CONVERSION BUFFER
	MOV	C,L
NXNYB:	CALL	LCFLD	;GET CASE-FOLDED CHAR FROM WH0
	MOV	B,A	;SAVE THIS CHAR SO IT CAN BE USED IF
			;IT WAS THE TERM CHAR.
	CPI	'0'	;RETURN IF LESS THAN ASCII 0
	RC
	CALL	WH1	;ECHO EACH CHAR. VALID OR NOT
	SUI	'0'	;CHANGE ASCII INTO BINARY 0-15
	CPI	10
	JC	NXNB1
	SUI	7
	CPI	10
	RC		;RETURN IF NOT HEX
	CPI	16
	RNC		;RETURN IF NOT HEX
NXNB1:	INR	C	;COUNT # OF HEX CHARACTERS
	DAD	H	;SHIFT HL
	DAD	H	;OVER
	DAD	H	;FOR NEXT
	DAD	H	;DIGIT
	ORA	L	;OR IN NEW DIGIT
	MOV	L,A
	JMP	NXNYB
;
;DEOUT OUTPUTS DE TO THE SCREEN
;AS 4 HEX DIGITS
;
DEOUT:	MOV	A,D
	CALL	BYTE
	MOV	A,E
;
;BYTE OUTPUTS THE ACCUMULATOR
;AS 2 HEX DIGITS TO THE SCREEN
;
BYTE:	PUSH	PSW
	RRC
	RRC
	RRC
	RRC
	CALL	HEXO
	POP	PSW
;
;HEXO OUTPUTS 1 HEX DIGIT TO
;THE SCREEN - THE UPPER HALF
;OF A IS MASKED WITH ZEROS
;
HEXO:	ANI	15
	ADI	90H
	DAA
	ACI	40H
	DAA
	JMP	DSPLY	;OUTPUT HEX DIGIT AND USE RETURN
;
;****** INITIALIZATION PARAMETERS ******
;THE FOLLOWING INFORMATIO IS USED ON FPRST OR POC
;TO SETUP THE STARTING SYSTEM CONTEXT.
;
STACK:	EQU	01000H	;USED IN AN LXI,SP
;
;THE FOLLOWING BLOCK IS COPIED DIRECTLY OVER
;SYSTEM RAM STARTING AT SRA4.
;
INITER:	DW	USRTSR	;VI3 USART INTERRUPT
	DW	KSR	;VI2: THE STANDARD KBD INT
	DW	IORET	;WAKEUP: NOTHING FOR NOW
	DW	SAVE	;VI0: SINGLE STEP INT GOES BACK
	DB	0FCH	;VIDEO SCRN ENDS AT FC00H-1
	DB	0F8H	;VIDEO SCRN HOME AT F800H
	CALL	KI	;WORMHOLE 0: INIT TO KVD AT F8H
	RET		;STANDARD PART OF ANY WORMHOLE
	CALL	DSPLY	;WORMHOLE1: INIT TO VIDEO DSPLY
	RET
	CALL	USRTI	;WORMHOLE 2: INIT USART AT 0
	RET
	END
