		VERSION	EQU 14
;		DDT RELOCATOR PROGRAM, INCLUDED WITH THE MODULE TO PERFORM
;		THE MOVE FROM 200H TO THE DESTINATION ADDRESS
		BIAS	EQU 703H		;DISTANCE UP TO DEMON
		ORG		100H
		STACK	EQU 200H
		BDOS	EQU 0005H
		PRHT	EQU 9			;BDOS PRINT FUNCTION
		MODULE	EQU 200H		;MODULE ADDRESS
;
		LXI		B, 0			;ADDRESS FIELD FILLED-IN WHEN MODULE BUILT
		JMP		START
		DB		'COPYRIGHT (C) 1976, DIGITAL RESEARCH'
SIGNON:
		DB		'DDT VERS '
		DB		VERS ION/10+'0', '.'
		DB		VERSION MOD 10 + '0', '$'
START:
		LXI		SP, STACK
		PUSH	B
		PUSH	B
		LXI		D, SIGNON
		MVI		C, PRNT
		CALL	BDOS
		POP		B				;RECOVER LENGTH OF MOVE
		LXI		H, BDOS+2		;ADDRESS FIELD OF JUMP TO BDOS (TOP MEMORY)
		MOV		A, M			;A HAS HIGH ORDER ADDRESS OF MEMORY TOP
		DCR		A				;PAGE DIRECTLY BELOW BDOS
		SUB		B				;A HAS HIGH ORDER ADDRESS OF RELOC AREA
		MOV		D, A
		MVI		E, 0			;D,E ADDRESSES BASE OF RELOC AREA
		PUSH	D				;SAVE FOR RELOCATION BELOW
;
		LXI		H, MODULE		;READY FOR THE MOVE
MOVE:
		MOV		A, B			;BC=0?
		ORA		C
		JZ		RELOC
		DCX		B				;COUNT MODULE SIZE DOWN TO ZERO
		MOV		A, M			;GET NEXT ABSOLUTE LOCATION
		STAX	D				;PLACE IT INTO THE RELOC AREA
		INX		D
		INX		H
		JMP		MOVE
;
RELOC:							;STORAGE MOVED, READY FOR RELOCATION
								;HL ADDRESSES BEGINNING OF THE BIT MAP FOR RELOCATION
		POP		D				;RECALL BASE OF RELOCATION AREA
		POP		B				;RECALL MODULE LENGTH
		PUSH	H				;SAVE BIT MAP BASE IN STACK
		MOV		H, D			;RELOCATION BIAS IS IN D

REL0:
		MOV		A, B			;BC=0?
		ORA		C
		JZ		ENDREL
;
;		NOT END OF THE RELOCATION, MAY BE INTO NEXT BYTE OF BIT M
		DCX		B				;COUNT LENGTH DOWN
		MOV		A, E
		ANI		111B			;0 CAUSES FETCH OF NEXT BYTE
		JNZ		REL1
								;FETCH BIT MAP FROH STACKED ADDRESS
		XTHL
		MOV		A, M			;NEXT 8 BITS OF MAP
		INX		H
		XTHL					;BASE ADDRESS GOES BACK TO STACK
		MOV		L, A			;L HOLDS THE MAP AS WE PROCESS 0 LOCATION
REL1:
		MOV		A, L
		RAL						;CY SET TO 1 IF RELOCATION NECESSARY
		MOV		L, A			;BACK TO L FOR NEXT TIME AROUND
		JNC		REL2			;SKIP RELOCATION IF CY=0
;
;		CURRENT ADDRESS REQUIRES RELOCATION
		LDAX	D
		ADD		H				;APPLY BIAS IN H
		STAX	D
REL2:
		INX		D				;TO NEXT ADDRESS
		JMP		REL0			;FOR ANOTHER BYTE TO RELOCATE
;
ENDREL:							;END OF RELOCATION
		POP		D				;CLEAR STACKED ADDRESS
		MVI		L, 0
		LXI		D, BIAS
		DAD		D
		PCHL					;GO TO RELOCATED PROGRAM
		END
		ORG		100H
		BDOS	EQU $+1106H
;		CP/M DEBUGGER DISASSEMBLER/ASSEMBLER MODULE
;		RELOCATABLE VERSION
;
;		COPYRIGHT (C) 1376
;		DIGITAL RESEARCH
;		BOX 579 PACIFIC GROVE
;		CALIFORNIA 93950
;
;
		FALSE	EQU 0
		TRUE	EQU NOT FALSE
;
		DEMON	EQU $+700H
;
		JLOC1	EQU 5H
;
		GETBUFF	EQU DEMON+9H
		GNC		EQU DEMON+0CH
;
		CI		EQU GNC			;SYNONYM FOR GNC
		CONO	EQU 2			;CONSOLE OUTPUT FUNCTION
		CHKIO	EQU 11			;CHECK FOR CHARACTER INPUT DURING LIST
;
		CR		EQU 0DH
		LF		EQU 0AH
		TAB		EQU 09H
;
MODLOC:							;MODULE LOCATION
		JMP		DEMON			;BRANCH AROUND DISASSEMBLER IF USED
		JMP		INIT			;INITIALIZE JUMPS
		JMP		DISENT
		JMP		ASMEN			;ENTRY POINT FOR ASSEMBLER
PC:
		DS		2				;CURRENT FAKED PC DURING DISASSEMBLY
MPC:
		DS		2				;MAX VALUE FOR PC (STOP ADDRESS)
PAGM:
		DS		1				;PAGE MODE IF NON ZERO
TPC:
		DS		2				;TEMPORARY PC FOR ASSEMBLER RESTORE ON ERROR
OLDSP:
		DS		2				;ENTRY SP VALUE
;
;
;
CO:								;PRINT CHARACTER IN REGISTER C
		PUSH	PSW
		PUSH	B
		PUSH	D
		PUSH	H
		MOV		E, C			;CHARACTER MOVES TO E
		MVI		C, CONO			;OUTPUT FUNCTION
		CALL	BDOS
		POP		H
		POP		D
		POP		B
		POP		PSW
		RET
;
;
DELIM:							;CHECK FOR DELIMITER
		CPI		' '
		RZ
		CPI		TAB
		RZ
		CPI		','
		RZ
		CPI		CR
		RZ
		CPI		7FH
		JZ		ASMEN			;RESTART CURRENT LINE
		RET
;
CRLF:							;RETURN AND LINE FEED
		MVI		C, CR
		CALL	CO
		MVI		C, LF
		CALL	CO
		RET
;
SCAN:							;FILL OPCODE WITH CHARACTERS
;
SC1:
		CALL	CI
SCAN0:							;ENTER HERE IF CHARACTER SCANNED
		CPI		CR
		JZ		ERR
		CALL	DELIM
		JZ		SCI
;
;		CLEAR BUFFER
		MVI		C, 4
		LXI		H, OPCODE
SC0:
		MVI		M, ' '
		INX		H
		DCR		C
		JNZ		SCO
;
;		GARBAGE REMOVED AT BEGINNING OF SCAN
		MVI		C, 5
		LXI		H, OPCODE
SC2:
		MOV		M, A			;STORE CHARACTER
		CALL	CI
		CALL	DELIM
		JZ		SC3
		INX		H
		DCR		C
		JZ		ERR				;TOO LONG
		JMP		SC2
;
SC3:							;END OF CURRENT SCAN, COMPARE FOR EMPTY
		LDA		OPCODE
		CPI		' '
		RET
;
HEX:							;CONVERT ACCUMULATOR TO HEXADECIMAL
		SUI		'0'
		CPI		10
		RC						;'0' - '9'
		ADI		('0'-'A'+10) AND 0FFH
		CPI		16
		RC

		JMP		ERR
;
GADDR:							;GET ADDRESS VALUE TO B (HIGH ORDER) AND C (LOW) WITH COPY OF
		CALL	SCAN
		JZ		ERR
		LXI		D, 0
		LXI		B, 0			;OPCODE INDEX
GAD:
		LXI		H, OPCODE
		DAD		B
		MOV		A, M			;NEXT CHARACTER
		CPI		' '
		JZ		GAI
		CALL	HEX				;CONVERT ACCUMULATOR
		MOV		L, E
		MOV		H, D			;COPY D,E TO H,L
		DAD		H				;*2
		DAD		H				;*4
		DAD		H				;*8
		DAD		H				;*16
		MOV		E, A
		MVI		D, 0
		DAD		D				;+CHAR
		XCHG					;BACK TO D,E
		INX		B				;NEXT POSITION
		MOV		A, C
		CPI		4
		JNZ		GAO				;FOR ANOTHER
;
CAI:							;D,E CONTAINS RESULT
		MOV		B, D
		MOV		C, E
		MOV		A, E			;COPY OF LOW BYTE TO ACCUMULATOR
		DCR		B
		INR		B				;SETS ZERO FLAG IF B IS ZERO
		RET
;
GBYTE:							;GET BYTE VALUE TO ACCUMULATOR AND C, CHECK FOR HIGH ORDER ZE
		CALL	GADDR
		JNZ		ERR
		RET
;
INIT:							;INITIALIZE THE JUMPS AROUND DISASSEMBLER
		LXI		H, JLOCI+1		;ADDRESS FIELD OF JUMP AT 5H
		MVI		A, MODLOC AND 0FFH	;LOW ORDER ADDRESS OF THIS MO
		SUB		M				;ALREADY ADDRESSING THIS MODULE
		INX		H				;OR A MODULE BELOW THIS POINT?
		MVI		A, MODLOC SHR 0	;IF SO, SKIP THIS OPERATION
		SBB		M
		RNC						;NO CARRY IF (5H) <= MODLOC
		LXI		H, MODLOC		;CHANGE ADDRESS
		SHLD	JLOC1+1			;FIELD OF JUMP AT 5H
		RET
;
;		************************************************************
;		********* ASSEMBLER MODULE STARTS HERE *********************
;		************************************************************
;
ADJ:							;MOVE REGISTER INDICATOR TO MIDDLE FIELD OF CODE
		RAL
		RAL
		RAL
		ANI		111000B
		RET
;
ADJ4:							;MOVE TO LEFT BY 4 AND MASK
		RAL
		RAL
		RAL
		RAL
		ANI		110000B
		RET
;
SEAR2:							;SAME AS SEAR, EXCEPT 2 CHARACTER MATCH
								;H,L ADDRESS TABLE TO MATCH ON
		XCHG
		LHLD	OPCODE			;2ND BYTE IN D, 1ST BYTE IN E
		XCHG					;H,L ADDRESS TABLE
SEA0:
		MOV		A, E			;GET 1ST BYTE
		CMP		M				;MATCH?
		JNZ		SEA1			;TO ADDRESS NEXT ELT
		INX		H				;NEXT TO MATCH
		MOV		A, D			;2ND CHAR
		CMP		M
		RZ						;MATCH AT CURRENT ENTRY
		DCX		H
SEA1:
		DCX		H
		DCX		H				;ADDRESSES NEXT ELEMENT
		DCR		C
		JNZ		SEA0			;FOR ANOTHER COMPARE
;
;		NO MATCH IN TABLE, RETURN WITH NON-ZERO VALUE
		DCR		C
		RET
;
;
SEAR:							;SEARCH FOR MATCH IN OPCODE TABLE, LENGTH OF TABLE IN REG-
								;D,E CONTAINS ADDRESS OF BINARY EQUIVALENT OF OPCODE
								;H,L ADDRESS FOUR CHARACTER OPCODE TO MATCH
								;OPCODE CONTAINS FOUR BYTE OPCODE TYPED AT CONSOLE
								;RETURNS WITH ZERO VALUE IF OPCOE FOUND, WITH D,E
								;ADDRESSING PROPER BYTE, NON-ZERO IF NOT FOUND.
		MVI		B, 4			;4 CHARACTER MATCH
;
		PUSH	D				;SAVE THE CURRENT BYTE VALUE LOCATION
		LXI		D, OPCODE		;ADDRESS CHARACTERS TYPED
SE1:
		LDAX	D				;POINT TO FIRST BYTE TO MATCH
		CMP		M				;SAME CHARACTER AS TABLE?
		JNZ		SE2				;NO, SKIP TO NXT TABLE ENTRY
		INX		H				;YES, LOOK AT NEXT CHARACTER
		INX		D				;MOVE TO NEXT CHARACTER TYPED
		DCR		B				;DECREMENT CHARACTER COUNT
		JNZ		SE1				;MORE TO MATCH?
;
								;COMPLETE MATCH, RETURN WITH D,E ADDRESSING BYTE VALUE
		POP		D
		RET
;
								;MISMATCH, FINISH COUNT
SE2:
		INX		H
		DCR		B
		JNZ		SE2
;
								;H,L AT END OF FOUR BYTE AREA, MOVE BACK 8
		LXI		D, -8
		DAD		D				;H,L READY FOR NXT, MATCH
;
		POP		D				;RESTORE BYTE POINTER
		INX		D				;MOVE TO NEXT IN CASE MATCH OK
		DCR		C				;MORE OPCODES TO MATCH?
		JNZ		SEAR			;LOOK FOR MORE
;
								;NO MATCH FOUND IH TABLE, SET NON-ZERO VALUE AND RETURN
		DCR		C
		RET
;
;
GETREG:							;SCAN FOR SIMPLE REGISTER REFERENCE
		PUSH	B
		CALL	SCAN
		JZ		ERR
		MVI		C, 8			;8 REGISTERS
		LXI		H, SREG			;SIMPLE REGISTERS
		CALL	SEAR2			;LOOK FOR 2 CHAR HATCH
		JNZ		ERR
		DCR		C
		MOV		A, C
		POP		B
		RET
;
GETD:							;GET DOUBLE PRECISION REGISTER
		PUSH	B
		CALL	SCAN
		JZ		ERR
		MVI		C, 5
		LXI		H, DREG
		CALL	SEAR
		JNZ		ERR
		DCR		C
		MOV		A, C
		POP		B
		RET
;
GETDR:							;GET DOUBLE REGISTER (BDHSP)
		CALL	GETD
		CPI		4				;PSW?
		JZ		ERR
		RET
;
GETPR:							;GET PUSH/POP REGISTER (BDH OR PSW)
		CALL	GETD
		CPI		3
		JZ		ERR
		CPI		4
		PHZ
		DCR		A				;PSW MUST BE ADJUSTED
		RET
;
GCON:							;GET CONDITION CODE
								;BUFFER IS SCANNED, MOVE LEFT BEFORE COMPARE
		LXI		H, OPCODE
		LXI		D, OPCODE+1
		MVI		C, 2			;MOVE TWO CHARACTERS
MOP:
		LDAX	D				;LOAD CHARACTER TO MOVE
		MOV		M, A			;MOVE LEFT
		INX		H				;NEXT DESTINATION
		INX		D				;NEXT SOURCE
		DCR		C
		JNZ		MOP
;
								;MUST BE BLANK AT END
		LDAX	D
		CPI		' '
		JNZ		ERR
		MOV		M, A
;
								;NOW READY TO DO THE COMPARE
		LXI		H, CREG
		MVI		C, 8
		CALL	SEAR2
		JNZ		ERR
		DCR		C
		MOV		A, C
		CALL	ADJ				;MOVE TO BITS
		RET
;
GCONA:							;GET CONDITION CODE TO REGISTER A, DOUBLE ADDRESS TO B,C
		CALL	GCON			;CONDITION CODE TO A
		PUSH	PSW
		CALL	GADDR			;VALUE TO B,C
		POP		PSW
								;INCLUDE HIGH ORDER 11'S FOR J AND C OPCODES
		ORI		11000000B
		RET
;
SETMD:							;SET MEMORY AT LOCATION PC TO VALUE ADDRESSED BY D
		LDAX	D				;VALUE TO ACCUM
;
SETM:							;SET MEMORY AT LOCATION PC TO VALUE IN ACCUM, INC PC
		LHLD	PC
		MOV		M, A			;STORE AT PC
		INX		H				;PC=PC+1
		SHLD	PC
		RET
;
;
;
GETOP:							;PROCESS NEXT OPCODE
		CALL	CI
		CPI		CR
		JZ		GOBACK			;RETURN IF SIMPLE INPUT
		CALL	SCAN0
		JZ		ERR
;
CHK0:							;CHECK FOR OPCOES WITH NO OPERANDS
		MVI		C, 17			;LENGTH OF GROUP-0
		LXI		H, ETAB1		;END OF GROUP-0
		LXI		D, TABLE		;FIRST BYTE VALUE
		CALL	SEAR			;LOOK FOR MATCH
		JNZ		CHK1			;NO MATCH, CHECK FOR GROUP-1
;
								;MATCHED OPCODE, D,E ADDRESS BYTE VALUE
		JMP		SETMD			;SET MEMORY AT PC AND INC PC
;
								;CHECK GROUP-1 VALUES
CHK1:
		MVI		C, 10			;LENGTH OF GROUP-1
		LXI		H, ETAB2
		CALL	SEAR			;D,E REMAIN SET
		JNZ		CHK2			;NO MATCH, CHECK NEXT GROUP
;
								;MATCH FOUND, SET BYTE AND GET BYTE OPERAND
		CALL	SETMD
		CALL	GBYTE			;GETS BYTE VALUE TO ACCUMULATOR
		JMP		SETM			;PUTS BYTE VALUE TO MEMORY AT PC
;
								;CHECK GROUP-2 OPCODES. REQUIRE DOUBLE BYTE OPERAND
CHK2:
		MVI		C, 6
		LXI		H, ETAB3
		CALL	SEAR
		JNZ		CHK3			;NO MATCH
;
								;FOUND MATCH, GET OPCODE BIT PATTERN AND STORE
		CALL	SETMD
0P2:							;ENTER HERE FOR DOUBLE BYTE OPERANDS
		CALL	GADDR			;VALUE IN B,A
		CALL	SETM
		MOV		A, B
		JMP		SETM
;
CHK3:							;CHECK FOR MOV INSTRUCTION
		MVI		C, 1
		LXI		H, PMOV
		CALL	SEAR
		JNZ		CHK4
;
								;MOV INSTRUCTION GET DESTINATION OPERAND
		CALL	GETREG			;VALUE TO ACCUMULATOR
		CALL	ADJ
		MOV		B, A			;SAVE IN B
		MVI		C, 01000000B	;BIT PATTERN FOR MOV
;
OP1:							;GET NEXT OPERAND FOR MOV, FIRST OPERAND FOR ACCUM/REG OPERAT
		CALL	GETREG
		ORA		C				;SETS HIGH ORDER TWO BITS
		ORA		B				;SETS DESTINATION/OPERATOR
		JMP		SETM
;
CHK4:							;CHECK FOR GROUP-5 (ACCUM/REG OPERATOR)
		MVI		C, 8
		LXI		H, ETAB5
		CALL	SEAR
		JNZ		CHK5
;
								;ACCUM/REG INSTRUCTION, C COUNTS OPERATORS AS SEARCH PROCEEDS
		DCR		C
		MOV		A, C
		CALL	ADJ
		MOV		B, A
								;OPERATOR NUMBER (SHIFTED) SAVED FOR LATER MASK
		MVI		C, 10000000B	;ACCUM/REG OPERATOR INDICATOR
		JMP		OP1				;GETS OPERAND AND SAVES BYTE IN MEMORY
;
CHK5:							;MAY BE INR/DCR
		MVI		C, 2
		LXI		H, PDCR
		CALL	SEAR
		JNZ		CHK6
;
								;C=2 IF DCR, =1 IF INR
		INR		C				;+1
		INR		C				;+2
		INR		C				;+3
		CALL	GETREG			;VALUE TO ACCUM
		CALL	ADJ
		ORA		C				;FILL PROPER INSTRUCTION INDICATOR
		JMP		SETM
;
CHK6:							;MAY BE A MVI INSTRUCTION
		MVI		C, 1
		LXI		H, PMVI
		CALL	SEAR
		JNZ		CHK7
;
								;MVI INSTRUCTION, GET REGISTER
		CALL	GETREG			;VALUE GOES TO ACCUMULATOR
		CALL	ADJ
		ORI		110B
		CALL	SETM
		CALL	GBYTE
		JMP		SETM
;
CHK7:							;CHECK FOR GROUP-7
		MVI		C, 6
		LXI		H, ETAB7
		CALL	SEAR
		JNZ		CHK8
;
								;LXI,STAX,INX,DAD,LDA, OR DCX
		MOV		A, C			;A=1...6
		CPI		4
		JC		IN0
;
								;MUST BE DAD,LDA, OR DCX
		ADI		5				;CHANGES  ACCUM TO 9,10, OR 11
IN0:							;ACCUMULATOR CONTAINS CODE, SAVE IT
		MOV		B, A
		CALL	GETDR			;DOUBLE REGISTER VALUE TO ACCUM
		CALL	ADJ4			;ADJUST VALUE TO MIDDLE FIELD
		ORA		B				;FILLS REMAINING BITS
		CALL	SETM
								;MAY BE LXI
		ANI		11001111B
		CPI		1
		RNZ						;NOT LXI
		JMP		OP2				;PICK  UP OPERAND
;
;
;
CHK8:	;RST?
		MVI		C, 1
		LXI		H, PRST
		CALL	SEAR
		JNZ		CHK9
;
;		RST, GET OPERAND
		CALL	GBYTE
		CPI		B
		JNC		ERR
		CALL	ADJ
		ORI		11000111B
		JMP		SETM
;
CHK9:							;POP/PUSH?
		MVI		C, 2
		LXI		H, PPOP+4
		CALL	SEAR
		JNZ		CHK10
;
								;C=2 IF PUSH, 1 IF POP
		DCR		C
		JNZ		PP0
;
								;POP, SET BIT PATTERN
		MVI		C, 11000001B
		JMP		PP1
;
PP0:							;PUSH
		MVI		C, 110001018
PP1:
		CALL	GETPR			;DOUBLE PUSH/POP REGISTER TO PROPER FIELD
		CALL	ADJ4			;MOVE TO FIELD
		ORA		C
		JMP		SETM
;
CHK10:							;J/C/R?
		LDA		OPCODE
		CPI		'J'
		JNZ		CHK11
		CALL	GCONA
								;CONDITION CODE TO FIELD IN ACCUM, ADDRESS TO B,C
		ORI		010B
		JMP		FADDR			;FILL ADDRESS
;
CHK11:
		CPI		'C'
		JNZ		CHK12
		CALL	GCONA
		ORI		100B
;
FADDR:
		CALL	SETM
		MOV		A, C
		CALL	SETM
		MOV		A, B
		JMP		SETM

CHK12:
		CPI		'R'
		JNZ		ERR
		CALL	GCON
		ORI		11000000B
		JMP		SETM
;
;		*****************************************************************
;		************* END OF ASSEMBLER MODULE, START DISASSEMBLER *******
;		*****************************************************************
;
RDBYTE:
		LHLD	MPC
		PUSH	D				;SAVE DE
		XCHG					;MAX PC TO D,E
		LHLD	PC				;CURRENT PC
								;SUBTRACT PC FROM MPC, STOP IF CARRY GENERATED
		MOV		A, E
		SUB		L
		MOV		A, D
		SBB		H
		JNC		RD0
;
								;PC EXCEEDS MPC, RETURN
		LHLD	OLDSP
		SPHL					;RESTORE ORIGINAL STACK POINTER
		RET
;
RD0:
		POP		D				;RESTORE D,E
		MOV		A, M
		INX		H
		SHLD	PC
		RET

RGPRNT:
		INR		A
		ANI		B7
		CPI		B6
		JC		RGP1
		ADI		03
RGP1:
		CPI		05
		JC		RGP2
		ADI		02
RGP2:
		ADI		41H
		MOV		C, A
		JMP		CO

DECODE:
		MOV		B, A
		ANI		0F0H
		RRC
		RRC
		RRC
		RRC
		ADI		90H
		DAA
		ACI		40H
		DAA
		MOV		C, A
		CALL	CO
		MOV		A, B
		ANI		0FH
		ADI		90H
		DAA
		ACI		40H
		DAA
		MOV		C, A
		JMP		CO

PRINT:
		MVI		B, 4
P1:
		MOV		C, M
		CALL	CO
		INX		H
		DCR		B
		JNZ		P1
		MVI		C, 20H
		JMP		CO
XTRACT:
		MOV		A, D
		ANI		38H
		RRC
		RRC
		RRC
		RET

CCPRNT:
		CALL	XTRACT
		ADD		A
		MOV		C, A
		LXI		H, CCODE
		DAD		B
		MOV		C, M
		CALL	CO
		INX		H
		MOV		C, M
		CALL	CO
		MVI		C, 20H
		CALL	CO
		JMP		CO

RPPRNT:
		CALL	XTRACT
		ANI		B6
		CPI		06
		JNZ		RGPRNT
		MVI		C, 53H
		CALL	CO
		MVI		C, 50H
		JMP		CO

PRPC:							;PRINT CRLF FOLLOWED BY PC VALUE
		CALL	CRLF
		LHLD	PC
		MOV		A, H
		CALL	DECODE
		MOV		A, L
		CALL	DECODE
		MVI		C, ' '
		CALL	CO
		CALL	CO
		RET
;
DISENT:							;ENTER HERE FROM DEBUGGER - SET UP JMPS
		LX1		H, 0
		DAD		SP
		SHLD	OLDSP			;SP SAVED FOR LATER RETURN
		CALL	INIT
;
								;CHECK FOR PAGE MODE DISPLAY
		LDA		PAGM			;GET PAGE MODE (NUMBER OF LINES TO PRINT)
		ORA		A				;SET FLAGS
		JZ		DISASM			;NOT PAGE MODE
;
								;SET MPC TO 0FFFFH
		LXI		H, 0FFFFH
		SHLD	MPC
								;255 IMPLIES TRACE MODE
		INR		A
		JNZ		DISASM			;NOT TRACE MODE IF 8R
								;TRACE MODE, SET TO 1 AND IGNORE ADDRESS FIELD
		INR		A				;I IN ACC
		STA		PAGM
		LHLD	PC				;RECOVER PC
		JMP		DIS1
;
;
DISASM:
								;CHECK FOR BREAK AT CONSOLE
		MVI		C, CHKIO
		CALL	BDOS
		ANI		1
		JNZ		GOBACK
;
								;CHECK TO SEE IF ENOUGH LINES PRINTED IN PAGE MODE
		LXI		H, PAGM
		MOV		A, M
		ORA		A				;ZERO?
		JZ		DIS0			;JMP IF NOT PAGE MODE
;
								;PAGE MODE, DECREMENT AND CHECK FOR ZERO
		DCR		M
		JZ		GOBACK
;
DIS0:
		CALL	PRPC			;LINE NUMBER
DIS1:
		CALL	RDBYTE
		MOV		D, A
		LXI		H, TABLE
		LXI		B, 11H
D1:
		CMP		M
		JZ		TG1
		INX		H
		DCR		C
		JNZ		D1
		MVI		C, 0AH
D2:
		CMP		M
		JZ		TG2
		INX		H
		DCR		C
		JNZ		D2
		MVI		C, 6
D3:
		CMP		M
		JZ		TG3
		INX		H
		DCR		C
		JNZ		D3
		ANI		0C0H
		CPI		40H
		JZ		MG0
		CPI		80H
		JZ		MG1
		MOV		A, D
		ANI		BC7H
		SUI		04
		JZ		MG2
		DCR		A
		JZ		MG3
		DCR		A
		JZ		MG4
		MOV		A, D
		ANI		0C0H
		JZ		MG5
		MOV		A, D
		ANI		0C7H
		SUI		0C0H
		JZ		MG6
		SUI		02
		JZ		MG7
		SUI		02
		JZ		MG8
		SUI		03
		JZ		MG9
		MOV		A, D
		ANI		07
		MOV		C, A
		LXI		H, PPOP-1
		DAD		B
		CALL	PRINT
		CALL	XTRACT
		CPI		06
		JNZ		D6
		LXI		H, PPSW
		CALL	PRINT
		JMP		DISASM
MG9:
		LXI		H, PRST
		CALL	PRINT
		CALL	XTRACT
		CALL	DECODE
		JMP		DISASM
MG8:
		MVI		C, 43H
		CALL	CO
		CALL	CCPRNT
		JMP		D7
MG7:
		MVI		C, 4AH
		CALL	CO
		CALL	CCPRNT
		JMP		D7
MG6:
		MVI		C, 52H
		CALL	CO
		CALL	CCPRNT
		JMP		DISASM
MG5:
		LXI		H, PLXI
		MOV		A, D
		ANI		0FH
		DCR		A
		JZ		MG51
		CPI		B4
		JC		D4
		SUI		05
D4:
		ADD		A
		ADD		A
		MOV		C, A
		DAD		B
		CALL	PRINT
		CALL	RPPRNT
		JMP		DISASM
MG51:
		CALL	PRINT
		CALL	RPPRNT
		MVI		C, 2CH
		CALL	CO
		JMP		D7
MG4:
		LXI		H, PMVI
		CALL	PRINT
		CALL	XTRACT
		CALL	RGPRNT
		MVI		C, 2CH
		CALL	CO
		JMP		D8
MG3:
		LXI		H, PDCR
		JMP		D5
MG2:
		LXI		H, PINR
D5:
		CALL	PRINT
		CALL	XTRACT
D6:
		CALL	RGPRNT
		JMP		DISASM
MG1:
		MOV		A, D
		ANI		38H
		RRC
		MOV		C, A
		LXI		H, PADD
		DAD		B
		CALL	PRINT
		JMP		D9
MG0:
		LXI		H, PMOV
		CALL	PRINT
		CALL	XTRACT
		CALL	RGPRNT
		MVI		C, 2CH
		CALL	CO
D9:
		MOV		A, D
		ANI		07
		CALL	RGPRNT
		JMP		DISASM
TG3:
		MOV		A, C
		ADD		A
		ADD		A
		MOV		C, A
		LXI		H, TAB3-4
		DAD		B
		CALL	PRINT
D7:
		CALL	RDBYTE
		MOV		D, A
		CALL	RDBYTE
		CALL	DECODE
		MOV		A, D
		CALL	DECODE
		JMP		DISASM
TG2:
		MOV		A, C
		ADD		A
		ADD		A
		MOV		C, A
		LXI		H, TAB2-4
		DAD		B
		CALL	PRINT
D8:
		CALL	RDBYTE
		CALL	DECODE
		JMP		DISASM
TG1:
		MOV		A, C
		ADD		A
		ADD		A
		MOV		C, A
		LXI		H, TAB1-4
		DAD		B
		CALL	PRINT
		JMP		DISASM
ERR:							;ENTER HERE FOR ERROR REPORTING
		CALL	CRLF
		MVI		C, '?'
		CALL	CO
;
		LHLD	OLDSP
		SPHL
		LHLD	TPC				;RESTORE PC
		SHLD	PC
;
;
ASMEH:							;ENTER HERE FROM DEBUGGER
		LXI		H, 0
		DAD		SP
		SHLD	OLDSP
		CALL	INIT
;
ASM0:
		CALL	PRPC			;PRINT PC VALUE
		SHLD	TPC				;SAVE PC VALUE
		CALL	GETBUFF			;FILL INPUT BUFFER
		CALL	GETOP			;GET OPERATION
		JMP		ASM0
;
GOBACK:
		LHLD	OLDSP
		SPHL
		RET
;
TABLE:
		DB		B00H, 007H, 00FH, 017H
		DB		01FH, B27H, 02FH, 837H
		DB		03FH, 076H, 0C9H, 8E3H
		DB		0E9H, 0EBH, 0F3H, 0F9H
		DB		0F8H, 0C6H, 0CEH, 0D3H
		DB		0D6H, 0DBH, 0DEH, 0E6H
		DB		0EEH, 0F6H, 0FEH, 022H
		DB		02AH, 032H, 03AH, 0C3H
		DB		0CDH
TAB1:
		DB		'EI  ', 'SPHL', 'DI  ', 'XCHG'


		DB		'PCHL', 'XTHL', 'RET ', 'HLT '


		DB		'CMC ', 'STC ', 'CMA ', 'DAA '


		DB		'RAR ', 'RAL ', 'RRC ', 'RLC '


ETAB1:	DB 'HOP '
TAB2:	DB 'CPI ', 'ORI ', 'XRI ', 'ANI '
		DB 'SBI ', 'IN ', 'SUI ', 'OUT '

		DB		'ACI '
ETAB2:
		DB		'ADI '
;
TAB3:
		DB		'CALL', 'JMP ', 'LDA ', 'STA '

		DB		'LHLD'
ETAB3:
		DB		'SHLD'
;
PMOV:
		DB		'MOV '
PADD:
		DB		'ADD ', 'ADC ', 'SUB ', 'SBB '

		DB		'ANA ', 'XRA ', 'ORA '
ETAB5:
		DB		'CMP '

PINR:
		DB		'INR '
PDCR:
		DB		'DCR '
PMVI:
		DB		'MVI '
PLXI:
		DB		'LXI ', 'STAX', 'INX ', 'DAD '

		DB		'LDAX'
ETAB7:
		DB		'DCX '
;

PRST:
		DB		'RST '
PPSW:
		DB		'PSW '
PPOP:
		DB		'POP ', 'PUSH'

CCODE:
		DB		'NZ', 'Z ', 'HC', 'C '

		DB		'PO', 'PE', 'P '
CREG:
		DB		'M '

;
		DB		'B ', 'C ', 'D ', 'E '
		DB		'H ', 'L ', 'M '
SREG:
		DB		'A '
;
		DB		'B   ', 'D   ', 'H   ', 'SP  '
DREG:
		DB		'PSW '
;
OPCODE:
		DS		4
		END


		ORG		100H
;		CP/M DEBUGGER VERSION 1.0
;		RELOCATABLE VERSION
;
;		COPYRIGHT (C) 1976
;		DIGITAL RESEARCH
;		BOX 579 PACIFIC GROVE
;		CALIFORNIA 93950
;
		FALSE	EQU 0
		TRUE	EQU NOT FALSE
		DISIH	EQU $+3
		DEMON	EQU $+700H
		BDOS	EQU $+1106H
		BDOSE	EQU 5H			;ENTRY POINT TO DOS FROM USER PROGRAMS
		PCBASE	EQU 100H		;DEFAULT PC
		SPBASE	EQU 100H		;DEFAULT SP
		DISEH	EQU DISIN+3		;DISASSEMBLER ENTRY POINT
		ASSEM	EQU DISEN+3		;ASSEMBLER ENTRY POINT
		DISPC	EQU ASSEM+3		;DISASSEMBLER PC VALUE
		DISPM	EQU DISPC+2		;DISASSEMBLER PC MAX VALUE
		D1SPG	EQU DISPM+2		;DISASSEMBLER PAGE MODE IF NON ZERO
		PSIZE	EQU 12			;NUMBER OF ASSEMBLY LINES TO LIST WITH
		CSIZE	EQU 32			;COMMAND BUFFER SIZE
		SSIZE	EQU 50			;LOCAL STACK SIZE
;
								;BASIC DISK OPERATING SYSTEM CONSTANTS
		CIF		EQU 1
		COF		EQU 2
		RIF		EQU 3
		POF		EQU 4
		LOF		EQU 5
;
		IDS		EQU 7
		GETF	EQU 10			;FILL BUFFER FROM CONSOLE
		CHKIO	EQU 11			;CHECK IO STATUS
		LIFT	EQU 12			;LIFT HEAD ON DISK
		OPF		EQU 15			;DISK FILE OPEN
		RDF		EQU 20			;READ DISK FILE
		DMAF	EQU 26			;SET DMA ADDRESS
;
		DBP		EQU 5BH			;DISK BUFFER POINTER
		DBF		EQU 80H			;DISK BUFFER ADDRESS
		DFCB	EQU 5CH			;DISK FILE CONTROL BLOCK
		FCB		EQU DFCB
		FDN		EQU 0			;DISK NAME
		FFN		EQU 1			;FILE NAME
		FFT		EQU 9			;FILE TYPE
		FRL		EQU 12			;REEL NUMBER
		FRC		EQU 15			;RECORD COUNT
		FCR		EQU 32			;CURRENT RECORD
		FLN		EQU 33			;FCB LENGTH
;
		DEOF	EQU 1AH			;CONTROL-Z (E0F)
		CR		EQU 0DH
		LF		EQU BAH
;
		RSTNUM	EQU 7			;RESTART NUMBER
		RSTLOC	EQU RSTNUM+S	;RESTART LOCATION
		RSTIN	EQU BC7H OR (RSTNUM SHL 3)	;RESTART INSTRUCTION
;
;		TEMPLATE FOR PROGRAMMED BREAKPOINT
;		---------
;		PCH  ,  PCL
;		HLH  ,  HLL
;		SPH  ,  SPL
;		RA   ,  FLG
;		B    ,  C
;		D    ,  E
;		-----------
;		FLG FIELD,   MZ0I0E1C (MINUS,IEPO,IDC,EVEN,CARRY)
;
		AVAL	EQU 5			;A REGISTER COUNT IN HEADER
		BVAL	EQU 6
		DVAL	EQU 7
		HVAL	EQU 8
		SVAL	EQU 9
		PVAL	EQU 10
;
;
		ORG		DEMON			;START OF DEBUGGER
								;DEMON ENTRY POINTS
		JMP		TRAPAD			;TRAP ADDRESS FOR RETURN IN CASE INTERR
		JMP		BEGIN
BREAKA:
		JMP		BREAKP
								;USEFUL ENTRY POINTS FOR PROGRAMS RUNNING WITH DDT
		JMP		GETBUFF			;GET ANOTHER BUFFER FULL
		JMP		GNC				;GET NEXT CHARACTER
		JMP		PCHAR			;PRINT A CHARACTER FROM A
		JMP		PBYTE			;PRINT BYTE IN REGISTER A
		JMP		PADDX			;PRINT ADDRESS IN REGISTERS D,E
		JMP		SCANEXP			;SCAN 0,1,2, OR 3 EXPRESSIONS
		JMP		GETVAL			;GET VALUE TO H,L
;
;
TRAPAD:							;GET THE RETURN ADDRESS FOR THIS JUMP TO BDOS IN CASE O
								;A SOFT INTERRUPT DURING BDOS PROCESSING
		XTHL					;PC TO HL
		SHLD	RETLOC			;MAY NOT NEED IT
		XTHL
		JMP		BDOS
;
BEGIN:
;
		LXI		H, DEMON
		SHLD	BDOSC+1			;CHANGE ENTRY POINT ADDRESS FOR BOS
		XRA		A				;ZERO ACC
		STA		BREAKS			;CLEARS BREAK POINT COUNT
;
		LXI		H, PCBASE
		SHLD	DISPC			;INITIAL VALUE FOR DISASSEMBLER
		SHLD	DISLOC			;INITIAL VALUE FOR DISPLAY
		SHLD	MLOAD			;MAX LOAD LOCATION
;
								;SETUP RESTART TEMPLATE
		SHLD	PLOC
		LXI		H, SPBASE
		LXI		SP, STACK-4
		PUSH	H				;INITIAL SP
		LXI		H, 10B			;INITIAL PSW
		PUSH	H
		DCX		H
		DCX		H				;CLEARED
		SHLD	HLOC			;H,L CLEARED
		PUSH	H				;B,C CLEARED
		PUSH	H				;D,E CLEARED
		SHLD	TRACER			;CLEAR TRACE FLAG
		SHLD	USERBRK			;CLEAR USER BREAK DURING TRACE/UNTRACE
;
		MVI		A, 0C3H			;(JMP RESTART)
		STA		RSTLOC
		LXI		H, BREAKA		;BREAK POINT SUBROUTINE
		SHLD	RSTLOC+1		;RESTART LOCATION ADDRESS FIELD
;
								;CHECK FOR FILE NAME PASSED TO DEMON, AND LOAD IF PRESENT
		LDA		FCB+FFN			;BLANK IF NO NAME PASSED
		CPI
		JZ		START
;
								;PUSH A ZERO, AND READ
		LXI		H, 0
		PUSH	H
		JMP		RINIT
;
;
;MAIN COMMAND LOOP
;
START:
		LXI		SP, STACK-12	;INITIALIZE SP IN CASE OF ERROR
		CALL	CRLF			;INITIAL CRLF
		MVI		A, '-'
		CALL	PCHAR			;OUTPUT PROMPT
;
								;GET INPUT BUFFER
		CALL	GETBUFF			;FILL COMMAND BUFFER
;
		CALL	GNC				;GET CHARACTER
		CPI		CR
		JZ		START
		SUI		'A'				;LEGAL CHARACTER?
		JC		CERROR			;COMMAND ERROR
		CPI		'Z'-'A'+1
		JNC		CERROR
								;CHARACTER IN REGISTER A IS COMMAND, MUST BE IN THE RANGE A-Z
		MOV		E, A			;INDEX TO E
		MVI		D, 0			;DOUBLE PRECISION INDEX
		LXI		H, JMPTAB		;BASE OF TABLE
		DAD		D
		DAD		D				; INDEXED
		MOV		E, M			;LO BYTE
		INX		H
		MOV		D, M			;NO BYTE
		XCHG					;TO H,L
		PCHL					;GONE...
;
JMPTAB:							;JUMP TABLE TO SUBROUTINES
		DW		ASSM			;A ENTER ASSEMBLER LANGUAGE
		DW		CERROR			;B
		DW		CALLPR			;C CALL PROGRAM
		DW		DISPLAY			;D DISPLAY RAM MEMORY
		DW		CERROR			;E
		DW		FILL			;F FILL MEMORY
		DW		GOTO			;G GO TO MEMORY ADDRESS
		DW		HEXARI			;H HEXADECIMAL SUM AND DIFFERENCE
		DW		INFCB			;I FILL INPUT FILE CONTROL BLOCK
		DW		CERROR			;J
		DW		CERROR			;K
		DW		LASSM			;L LIST ASSEMBLY LANGUAGE
		DW		MOVE			;M MOVE MEMORY
		DW		CERROR			;N
		DW		CERROR			;O
		DW		CERROR			;P
		DW		CERROR			;Q
		DW		READ			;R READ HEXADECIMAL FILE
		DW		SETMEM			;S SET MEMORY COMMAND
		DW		TRACE			;T
		DW		UNTRACE			;U
		DW		CERROR			;V
		DW		CERROR			;W
		DW		EXAMINE			;X EXAMINE AND MODIFY REGISTERS
		DW		CERROR			;Y
		DW		CERROR			;Z
;
;
OPN:							;FILE OPEN ROUTINE, THIS SUBROUTINE OPENS THE DISK INPUT
		PUSH	H
		PUSH	D
		PUSH	B
		XRA		A
		STA		DBP				;CLEAR BUFFER POINTER
		MVI		C, OPF
		LXI		D, DFCB
		CALL	TRAPAD			;TO BDS
		POP		B
		POP		D
		POP		H
		RET
;
ASSM:							;ASSEMBLER LANGUAGE INPUT
								;CHECK FOR ASSM PRESENT
		LXI		H, ASSEM		;BASE OF ASSEMBLER
		CALL	COMLOAD			;COMPARE AGAINST MLOAD
		JNC		CERROR			;NOT THERE
;
		CALL	SCANEXP			;SCAN THE EXPRESSIONS WHICH FOLLOW
		DCR		A				;ONE EXPRESSION EXPECTED
		JNZ		CERROR
		CALL	GETVAL			;GET EXPRESSION TO H,L
		SHLD	DISPC
		CALL	ASSEM
		JMP		START
;
LASSM:							;ASSEMBLER LANGUAGE OUTPUT LISTING
								;L(CR)    LISTS FROM CURRENT DISASSM PC FOR SEVERAL LINES
								;L(NUMBER)(CR)  LISTS FROM (NUMBER) FOR SEVERAL LINES
								;L(NUMBER),(NUMBER)  LISTS BETWEEN LOCATIONS
		CALL	CHKDIS			;DISASSM PRESENT?

		JNC		CERROR
;
		CALL	SCANEXP			;SCAN EXPRESSIONS WHICH FOLLOW
		JZ		SPAGE			;DRANCH IF NOT EXPRESSIONS
		CALL	GETVAL			;EXP1 TO H,L
		SHLD	DISPC			;SETS BASE PC FOR LIST
		DCR		A				;ONLY EXPRESSION?
		JZ		SPAGE			;SETS SINGLE PAGE MODE
;
								;ANOTHER EXPRESSION FOLLOWS
		CALL	GETVAL
		SHLD	DISPM			;SETS MAX VALUE
		DCR		A
		JNZ		CERROR			;ERROR IF MORE EXPN'S
		XRA		A				;CLEAR PAGE MODE
		JMP		SPAG0
;
SPACE:	MVI A, PSIZE	;SCREEN SIZE FOR LIST
SPAG0:	STA DISPG
		CALL	DISEN			;CALL DISASSEMBLER
		JMP		START			;FOR ANOTHER COMMAND
;
;		DISPLAY MEMORY,    FORMS ARE
;		D                  DISPLAY FROM CURRENT DISPLAY LINE
;		DNNN               SET DISPLAY LINE AND ASSUME D
;		DNNN,MMM           DISPLAY NNN TO MMM
;		NEW DISPLAY LINE IS SET TO NEXT TO DISPLAY
;
CALLPR:
								;CALL USER PROGRAM FROM DDT
		CALL	SCANEXP
		JC		CERROR			;CANNOT BE ,XXX
		JZ		CERROR			;CANNOT BE C ALONE
		CALL	GETVAL			;ADDRESS TO CALL IN H,L
		PUSH	H				;READY FOR CALL
								;GET REMAINING PARAMETERS
								;REG-A CONTAINS 1,2,OR 3 CORRESPONDING TO NUMBER OF VALUES
		LXI		B, 0
		DCR		A
		JNZ		CALL0
								;NO PARAMETERS, STACK TWO ZEROES
		PUSH	B
		PUSH	B
		JMP		CALL2
CALL0:							;AT LEAST ONE PARAMETER
		CALL	GETVAL
		PUSH	H
		DCR		A
		JNZ		CALL1
								;ONLY ONE PARAMETER, STACK A ZERO
		PUSH	B
		JMP		CALL2
CALL1:							;MUST BE TWO PARAMETERS FOR THE CALL
		CALL	GETVAL
		PUSH	H
CALL2:							;SET UP PARAMETERS IN B,C AND D,E
		POP		D				;RECALL SECOND PARAMETER
		POP		B				;RECALL FIRST PARAMETER
								;READY FOR THE USER PROGRAM CALL
		LXI		H, START		;RETURN ADDRESS
		XTHL					;CALL ADDRESS IN H,L RETURN IN STACK
		PCHL					;CALL USER
;
DISPLAY:
		CALL	SCANEXP			;GET 0, 1, OR 2 EXPNS
		JZ		DISP1			;ASSUME CURRENT DISLOC
		CALL	GETVAL			;GET VALUE TO H,L
		JC		DISFO			;CARRY SET IF ,B FORM
		SHLD	DISLOC			;OTHERWISE D1SPC ALREADY SET
DISP0:							;GET NEXT VALUE
		ANI		7FH				;IN CASE ,B
		DCR		A
		JZ		DISP1			;SET HALF PAGE MODE
		CALL	GETVAL
		DCR		A				;A,B,C NOT ALLOWED
		JNZ		CERROR
		JMP		DISP2
;
DISP1:							;0 OR 1 EXPN, DISPLAY HALF SCREEN
		LHLD	DISLOC
		MOV		A, L
		ANI		BF0H			;NORMALIZE TO LINE START
		MOV		L, A
		LXI		D, PSIZE*16-1
		DAD		D
DISP2:
		SHLD	DISMAX
								;DISPLAY MEMORY FROM DISLOC TO DISMAX
DISP3:
		CALL	CRLF
		CALL	BREAK			;BREAK KEY?
		JNZ		START			;STOP CURRENT EXPANSION
		LHLD	DISLOC
		SHLD	TDISP
		CALL	PADDR			;PRINT LINE ADDRESS
DISP4:
		CALL	BLANK
		MOV		A, M			;GET NEXT DATA BYTE
		CALL	PBYTE			;PRINT BYTE
		INX		H
		CALL	DISCOM			;COMPARE H,L WITH DISMAX
		JC		DISCH			;CARRY SET IF H,L > DISMAX
		MOV		A, L			;CHECK FOR LINE OVERFLOW
		ANI		BFH
		JNZ		DISP4			;JUMP FOR ANOTHER BYTE
;
DISCH:							;DISPLAY AREA IN CHARACTER FORM
		SHLD	DISLOC			;UPDATE FOR NEXT WRITE
		LHLD	TDISP
		XCHG
		CALL	BLANK
;
DISCH0:
		LDAX	D				;GET BYTE
		CALL	PGRAPH			;PRINT IF GRAPHIC CHARACTER
		INX		D
		LHLD	DISLOC			;COMPARE FOR END OF LINE
		MOV		A, L
		SUB		E
		JNZ		DISCH0
		MOV		A, H
		SUB		D
		JNZ		DISCH0

								;DROP THRU AT END OF CHARACTERS
		LHLD	DISLOC
		CALL	DISCOOM			;END OF DISPLAY?
		JC		START
;
								;NO, CONTINUE WITH HEXT LINE
		JMP		DISP3
;
;
								;FILL MEMORY AREA WITH FIXED DATA ELEMENT
;
SCAN3:							;SCAN THREE EXPN'S FOR FILL AND MOVE
		CALL	SCANEXP
		CPI		3
		JNZ		CERROR
		CALL	GETVAL
		PUSH	H
		CALL	GETVAL
		PUSH	H
		CALL	GETVAL
		POP		D
		POP		B				;BC,DE,HL
		RET
;
BCDE:							;COMPARE BC > DE (CARRY GEN'D IF TRUE)
		MOV		A, E
		SUB		C
		MOV		A, D
		SBB		B
		RET
;
FILL:
		CALL	SCAN3			;EXPRESSIONS SCANNED BC , DE , HL
		MOV		A, H			;MUST BE ZERO
		ORA		A
		JNZ		CERROR
FILL0:
		CALL	BCDE			;END OF FILL?
		JC		START
		MOV		A, L			;DATA
		STAX	B				;TO MEMORY
		INX		B				;NEXT TO FILL
		JMP		FILL0
;
								;GO COMMAND UITH OPTIONAL BREAKPOINTS
;
GOTO:
		CALL	CRLF			;READY FOR GO.
		CALL	SCANEXP			;0, 1, OR 2 EXPS
		CALL	GETVAL
		PUSH	H				;START ADDRESS
		CALL	GETVAL
		PUSH	H				;BKPT1
		CALL	GETVAL
		MOV		B, H			;BKPT2
		MOV		C, L
		POP		D				;BKPT1
		POP		H				;GOTO ADDRESS
;
GOPR:
		DI
		JZ		GOP1			;NO BREAK POINTS
		JC		GOP0
								;SET PC
		SHLD	PLOC			;INT0 MACHINE STATE
GOP0:							;SET BREAKS
		ANI		7FH				;CLEAR, BIT
		DCR		A				;IF 1 THEN SKIP (2,3 IF BREAKPOINTS)
		JZ		GOP1
		CALL	SETBK			;BREAK POINT FROM D,E
		DCR		A
		JZ		GOP1
								;SECOND BREAK POINT
		MOV		E, C
		MOV		D, B			;TO D,E
		CALL	SETBK			;SECOND BREAK POINT SET
;
GOP1:							;RESTORE MACHINE STATE AND START IT
		LXI		SP, STACK-12
		POP		D
		POP		B
		POP		PSW
		POP		H				;SP IN HL
		SPHL
		LHLD	PLOC			;PC IN HL
		PUSH	H				;INTO USER'S STACK
		LHLD	HLOC			;HL RESTORED
		EI
		RET
;
SETBK:							;SET BREAK POINT AT LOCATION D,E
		PUSH	PSW
		PUSH	B
		LXI		H, BREAKS		;NUMBER OF BREAKS SET SO FAR
		MOV		A, M
		INR		M				;COUNT BREAKS UP
		ORA		A				;ONE SET ALREADY?
		JZ		SETBK0
								;ALREADY SET, MOVE PAST ADDR,DATA FIELDS
		INX		H
		MOV		A, M			;CHECK = ADDRESSES
		INX		H
		MOV		B, M			;CHECK HO ADDRESS
		INX		H
								;DON'T SET TWO BREAKPOINTS IF EQUAL
		CMP		E				;LOW =?
		JNZ		SETBKB
		MOV		A, B
		CMP		D				;HIGH =?
		JNZ		SETBK0
								;EQUAL ADDRESSES, REPLACE REAL DATA
		MOV		A, M			;GET DATA BYTE
		STAX	D				;PUT BACK INTO CODE
SETBK0:
		INX		H				;ADDRESS FIELD
		MOV		M, E			;LSB
		INX		H
		MOV		M, D			;MSB
		INX		H				;DATA FIELD
		LDAX	D				;GET BYTE FROM PROGRAM
		MOV		M, A			;TO BREAKS VECTOR
		MVI		A, RSTIN		;RESTART INSTRUCTION
		STAX	D				;TO CODE
		POP		B
		POP		PSW
		RET
;
;
								;HEXADECIMAL ARITHMETIC
;
HEXARI:
		CALL	SCANEXP
		CPI		2
		JNZ		CERROR
		CALL	GETVAL			;FIRST VALUE TO H,L
		PUSH	H
		CALL	GETVAL			;SECOND VALUE TO H,L
		POP		D				;FIRST VALUE TO D,E
		PUSH	H				;SAVE A COPY OF SECOND VAALUE
		CALL	CRLF			;NEW LINE
		DAD		D				;SUM IN H,L
		CALL	PADDR
		CALL	BLANK
		POP		H				;RESTORE SECOND VALUE
		XRA		A				;CLEAR ACCUM FOR SUBTRACTION
		SUB		L
		MOV		L, A			;BACK TO L
		MVI		A, 0			;CLEAR IT AGAIN
		SBB		H
		MOV		H, A
		DAD		D				;DIFFERENCE IN HL
		CALL	PADDR
		JMP		START
;
; SET INPUT FILE CONTROL BLOCK (AT SCH) TO SIMULATE CONSOLE COMMAND
INFCB:
								;FILL FCB AT 5CH
		XRA		A
		STA		FCB+FCR			;CLEAR CURRENT RECORD
		STA		FCB				;CLEAR DISK NUM8ER
		CALL	GNC				;CHARACTER IN A
		MVI		C, 9			;FILE NAME LENGTH+1
		LXI		H, FCB+FFN		;START OF NAME
;
FLP:							;FILL NAME
		MOV		M, A
		INX		H
		DCR		C
		JZ		CERROR			;FILE NAME TOO LONG.
;
		CALL	GNC				;READ NEXT CHAR
		CPI		' '
		JZ		FLB				;FOUND ., BLANK OUT
								;NOT       MAY BE CR
		CPI		CR
		JNZ		FLP				;FOR ANOTHER STORE
;
								;NAME FILLED, EXTEND WITH BLANKS
FLB:
		DCR		C
		JZ		TFT
		MVI		M, ' '
		INX		H
		JMP		FLB
;
								;BLANKS FILLED, SCAN FILE TYPE IF '.' FOUND
TFT:
		MVI		C, 4
		CPI		'.'				;ENDED WITH . OR CR
		JNZ		FLB1			;FILL REMAINDER WITH BLANKS
;
								;SCAN FILE TYPE
		LXI		H, FCB+FFT
;
FLP1:
		CALL	GNC
		CPI		CR
		JZ		FLB1
		MOV		M, A
		INX		H
		DCR		C
		JZ		CERROR			;TOO LONG
		JMP		FLP1
;
								;FILL WITH BLANKS
FLB1:
		DCR		C
		JZ		FLZ
		MVI		M, ' '
		INX		H
		JMP		FLB1
;
								;ZER0 THE EXTENT
FLZ:
		MVI		M, 0
		JMP		START
;
								;MOVE MEMORY
MOVE:
		CALL	SCAN3			;BC,DE,HL
MOVED:							;HAS B,C PASSED D,E?
		CALL	BCDE
		JC		START			;END OF MOVE
		LDAX	B				;CHAR TO ACCUM
		INX		B				;NEXT TO GET
		MOV		M, A			;MOVE IT TO MEMORY
		INX		H
		JMP		MOVE0			;FOR ANOTHER
;
								;READ FILES (HEX OR COM)
;
QCOM:							;COM FILE IF ZERO AT END
		LXI		H, FCB+FFT
		MOV		A, M
		CPI		'C'
		RNZ
		INX		H
		MOV		A, M
		CPI		'O'
		RNZ
		INX		H
		MOV		A, M
		CPI		'M'
		RET
;
COMLOAD:						;COMPARE HL > MLOAD
		XCHG					;H,L TO D,E
		LHLD	MLOAD			;ML0AD TO H,L
		MOV		A, L			;ML0AD LSB
		SUB		E
		MOV		A, H
		SBB		D				;MLOAD-OLDHL GENS CARRY IF HL>MLOAD
		XCHG
		RET
;
CKMLOAD:						;CHECK FOR HL > MLOAD AND SET MLOAD IF SO
		CALL	COMLOAD			;CARRY IF HL>MLOAD
		RNC
		SHLD	MLOAD			;CHANGE IT
		RET
;
CHKDIS:							;CHECK FOR DISASSM PRESENT
		PUSH	H
		LXI		H, DISEN		;ENTRY POINT
		CALL	COMLOAD
		POP		H
		RET
;
READ:
		CALL	SCANEXP
		LXI		H, 0
		JZ		READN
		DCR		A				;ONE EXPRESSION?
		JNZ		CERROR
		CALL	GETVAL			;EXPRESSION TO H,L
READH:
		PUSH	H				;SAVE IT FOR BELOW
RINIT:
		CALL	OPN				;OPEN INPUT FILE
		CPI		255
		JZ		CERROR
								;CONTINUE IF FILE OPEN WENT OK
								;DISK FILE OPENED AHD INITIALIZED
;
								;CHECK FOR 'COM' FILE AND LOAD DIRECT TIL EOF
		CALL	QCOM			;LOOK FOR 'COM'
		JNZ		HREAD
;
								;COM FILE, LOAD WITH OFFSET GIVEN BY PUSHED REGISTER H
		POP		H
		LXI		D, 100H			;BASE OF TRANSIENT AREA
		DAD		D
								;REG H HOLDS LOAD ADDRESS
LCOM0:							;LOAD COM FILE
		PUSH	H				;SAVE DMA ADDRESS
		LXI		D, DFCB
		MVI		C, RDF			;READ SECTOR
		CALL	TRAPAD
		POP		H
		ORA		A				;SET FLAGS TO CHECK RETURN CODE
		JNZ		RLIFT
								;MOVE FROM 80H TO LOAD ADDRESS IN H,L
		LXI		D, DBF
		MVI		C, 80H			;BUFFER SIZE
LCOM1:
		LDAX	D				;LOAD NEXT BYTE
		INX		D
		MOV		M, A			;STORE NEXT BYTE
		INX		H
		DCR		C
		JNZ		LC0M1
								;LOADED, CHECK ADDRESS AGAINST MLOAD
		CALL	CKMLOAD
		JMP		LCOM0
;
;
								;OTHERWISE ASSUME HEX FILE IS BEING LOADED
HREAD:
		CALL	DISKR			;NEXT CHAR TO ACCUM
		CPI		DEOF			;PAST END OF TAPE?
		JZ		CERROR			;FOR ANOTHER COMMAND
		SBI		':'
		JNZ		HREAD			;LOOKING FOR START OF RECORD
;
								;START FOUND, CLEAR CHECKSUM
		MOV		D, A
		POP		H
		PUSH	H
		CALL	RBYTE
		MOV		E, A			;SAVE LENGTH
		CALL	RBYTE			;HIGH ORDER ADDR
		PUSH	PSW
		CALL	RBYTE			;LOW ORDER ADDR
		POP		B
		MOV		C, A
		DAD		B				;BIASED ADDR IN H
		MOV		A, E			;CHECK FOR LAST RECORD
		ORA		A
		JNZ		RDTYPE
								;END OF TAPE, SET LOAD ADDRESS
		MOV		H, B
		MOV		L, C
		SHLD	PLOC			;SET PC VALUE
		JMP		RLIFT			;FOR ANOTHER COMMAND
;
RDTYPE:
		CALL	RBYTE			;RECORD TYPE = 8
;
								;LOAD RECORD
RED1:
		CALL	RBYTE
		MOV		M, A
		INX		H
		DCR		E
		JNZ		RED1			;FOR ANOTHER BYTE
								;OTHERWISE AT END OF RECORD - CHECKSUM
		CALL	RBYTE
		PUSH	PSW				;FOR CHECKSUM CHECK
		CALL	CKMLOAD			;CHECK AGAINST MLOAD
		POP		PSW
		JNZ		CERROR			;CHECKSUM ERROR
		JMP		HREAD			;FOR ANOTHER RECORD
;
RBYTE:							;READ ONE BYTE FROM BUFF AT WBP TO REG-A
								;COMPUTE CHECKSUM IN REG-D
		PUSH	B
		PUSH	H
		PUSH	D
;
		CALL	DISKR			;GET ONE MORE CHARACTER
		CALL	HEXCON			;CONVERT TO HEX (OR ERROR)
;
								;SHIFT LEFT AND MASK
		RLC
		RLC
		RLC
		RLC
		ANI		0F0H
		PUSH	PSW				;SAVE FOR A FEW STEPS
		CALL	DISKR
		CALL	HEXCON
;
								;OTHERWISE SECOND NIBBLE OK, SO MERGE
		POP		B				;PREVIOUS NIBBLE TO REG-B
		ORA		B
		MOV		B, A			;VALUE IS NOW IN B TEMPORARILY
		POP		D				;CHECKSUM
		ADD		D				;ACCUMULATING
		MOV		D, A			;BACK TO CS
								;ZERO FLAG REMAINS SET
		MOV		A, B			;BRING BYTE BACK TO ACCUMULATOR
		POP		H
		POP		B				;BACK TO INITIAL STATE WITH ACCUM SET
		RET
RLIFT:							;LIFT HEAD ON DISK BEFORE RETURNING
		MVI		C, LIFT
		CALL	TRAPAD
								;'NEXT' ' PC'
		LXI		H, LMSG			;LOAD MESSAGE
RLI0:
		MOV		A, M
		ORA		A				;LAST CHAR?
		JZ		RLI1
		CALL	PCHAR
		INX		H				;NEXT CHAR
		JMP		RLI0
RLI1:
		CALL	CRLF
		LHLD	MLOAD
		CALL	PADDR
		CALL	BLANK
		LHLD	PLOC
		CALL	PADDR
		JMP		START
LMSG:
		DB		CR, LF, 'NEXT PC', 0
;
								;SET MEMORY COMMAND
;
SETMEM:							;ONE EXPRESSION EXPECTED
		CALL	SCANEXP			;SETS FLAGS
		DCR		A				;ONE EXPRESSION ONLY
		JNZ		CERROR
		CALL	GETVAL			;START ADDRESS IS IN H,L
SETM0:
		CALL	CRLF			;NEW LINE
		PUSH	H				;SAVE CURRENT ADDRESS
		CALL	PADDR			;PRINTED
		CALL	BLANK			;SEPARATOR
		POP		H				;GET DATA
		MOV		A, M
		PUSH	H				;SAVE ADDRESS TO FILL
		CALL	PBYTE			;PRINT BYTE
		CALL	BLANK			;ANOTHER SEPARATOR
		CALL	GETBUFF			;FILL INPUT BUFFER
		CALL	GNC				;MAY BE EMPTY (NO CHANGE)
		POP		H				;RESTORE ADDRESS TO FILL
		CPI		CR
		JZ		SETM1
		CPI		'.'
		JZ		START
								;DATA IS BEING CHANGED
		PUSH	H				;SAVE ADDR TO FILL
		CALL	SCANEX			;FIRST CHARACTER ALREADY SCANNED
		DCR		A				;ONE ITEM?
		JNZ		CERROR			;MORE THAN ONE
		CALL	GETVAL			;VALUE TO H,L
		MOV		A, H
		ORA		A				;HO ZERO?
		JNZ		CERROR			;DATA IS IN L
		MOV		A, L
		POP		H				;RESTORE DATA VALUE
		MOV		M, A
SETM1:
		INX		H				;NEXT ADDRESS READY
		JMP		SETM0
;
								;UNTRACE MODE
UNTRACE:
		XRA		A				;CLEAR TRACE MODE FLAG
		JMP		ETRACE
;
								;START TRACE
TRACE:
		MVI		A, 0FFH			;SET TRACE MODE FLAG
ETRACE:
		STA		TMODE
		CALL	SCANEXP
		LXI		H, 0
		SHLD	USERBRK			;CLEAR USERBRK
		JZ		TRAC0
;		EXPRESSIONS WERE GIVEN, FORMS ARE
;		TX       TRACE FOR X STEPS   ACC = 1
;		TX,BRK   TRACE FOR X STEPS, CALL 'BRK' AT EACH STOP  ACC=2
;		T,BRK    CALL 'BRK'          ACC = 1, CY = 1
;
		JC		SETTR0
		CALL	GETVAL			;TO H,L
		PUSH	PSW
		MOV		A, L			;CHECK FOR ZERO
		ORA		H
		JZ		CERROR
		POP		PSW				;RECALL NUMBER OF PARAMETERS
		DCX		H				;TRACE VALUE - 1
SETTR0:							;H,L CONTAINS TRACE COUNT, SAVE IT FOR LATER
		PUSH	H
								;LOOK FOR BREAK ADDRESS
		DCR		A				;IF ONLY ONE SPECIFIED, THEN SKIP USERBRK
		JZ		SETTR1
		DCR		A				;MUST BE TWO VALUES
		JNZ		CERROR			;MORE THAN TWO SPECIFIED
		CALL	GETVAL			;VALUE TO H,L
		SHLD	USERBRK
SETTR1:							;RECALL TRACE COUNT
		POP		H
TRAC0:
		SHLD	TRACER
		CALL	DSTATE			;STARTIHG STATE IS DISPLAYED
		JMP		GOPR			;SETS BREAKPOINTS AND STARTS EXECUTION
;
								;EXAMINE AND MODIFY CPU REGISTERS
EXAMINE:
		CALL	GNC				;CR?
		CPI		CR
		JNZ		EXAM0
		CALL	DSTATE			;DISPLAY CPU STATE
		JMP		START
;
EXAM0:							;REGISTER CHANGE OPERATION
		LXI		B, PVAL+l		;B=0,C=PVAL (MAX REGISTER NUMBER)
								;LOOK FOR REGISTER MATCH IN RVECT
		LXI		H, RVECT
EXAM1:
		CMP		M				;MATCH IN RVECT?
		JZ		EXAM2
		INX		H				;NEXT RVECT
		INR		B				;INCREMENT COUNT
		DCR		C				;END OF RVECT?
		JNZ		EXAM1
								;NO MATCH
		JMP		CERROR
;
EXAM2:							;MATCH IN RVECT, B HAS REGISTER NUMBER
		CALL	GNC
		CPI		CR				;ONLY CHARACTER?
		JNZ		CERROR
;
								;WRITE CONTENTS, AND GET ANOTHER BUFFER
		PUSH	B				;SAVE COUNT
		CALL	CRLF			;NEW LINE FOR ELEMENT
		CALL	DELT			;ELEMENT WRITTEN
		CALL	BLANK
		CALL	GETBUFF			;FILL COMMAND  BUFFER
		CALL	SCANEXP			;GET INPUT EXPRESSION
		ORA		A				;NONE?
		JZ		START
		DCR		A				;MUST BE ONLY ONE
		JNZ		CERROR
		CALL	GETVAL			;VALUE IS IN H,L
		POP		B				;RECALL REGISTER NUMBER
								;CHECK CASES FOR FLAGS, REG-A, OR DOUBLE REGISTER
		MOV		A, B
		CPI		AVAL
		JNC		EXAM4
								;SETTING FLAGS, MUST BE ZERO OR ONE
		MOV		A, H
		ORA		A
		JNZ		CERROR
		MOV		A, L
		CPI		2
		JNC		CERROR
								;0 OR 1 IN H,L REGISTERS - GET CURRENT FLAGS AND MASK POSITION
		CALL	FLGSHF
								;SHIFT COUNT IN C, D,E ADDRESS FLAG POSITION
		MOV		H, A			;FLAGS TO H
		MOV		B, C			;SHIFT COUNT TO B
		MVI		A, 0FEH			;111111110 IN ACCUM TO ROTATE
		CALL	LROTATE			;ROTATE REG-A LEFT
		ANA		H				;MASK ALL BUT ALTERED BIT
		MOV		B, C			;RESTORE SHIFT COUNT TO B
		MOV		H, A			;SAVE MASKED FLAGS
		MOV		A, L			;0/1 TO LSB OF ACCUM
		CALL	LROTATE			;ROTATED TO CHANGED POSITION
		ORA		H				;RESTORE ALL OTHER FLAGS
		STAX	D				;BACK TO MACHINE STATE
		JMP		START			;FOR ANOTHER COMMAND
;
LROTATE:						;LEFT ROTATE FOR FLAG SETTING
								;PATTERN IS IN REGISTER A, COUNT IN REGISTER B
		DCR		B
		RZ						;ROTATE COMPLETE
		RLC						;END-AROUND ROTATE
		JMP		LROTATE
;
EXAM4:							;MAY BE ACCUMULATOR CHANGE
		JNZ		EXAM5
								;MUST BE BYTE VALUE
		MOV		A, H
		ORA		A
		JNZ		CERROR
		MOV		A, L			;GET BYTE TO STORE
		LXI		H, ALOC			;A REG LOCATION IN MACHINE STATE
		MOV		M, A			;STORE IT AWAY
		JMP		START
;
EXAM5:							;MUST BE DOUBLE REGISTER PAIR
		PUSH	H				;SAVE VALUE
		CALL	GETDBA			;DOUBLE ADDRESS TO HL
		POP		D				;VALUE TO D,E
		MOV		M, E
		INX		H
		MOV		M, D			;ALTERED MACHINE STATE
		JMP		START
;
DISKR:							;DISK READ
		PUSH	H
		PUSH	D
		PUSH	B
;
RDI:							;READ DISK INPUT
		LDA		DBP
		ANI		7FH
		JZ		NDI				;GET NEXT DISK INPUT RECORD
;
								;READ CHARACTER
RDC:
		MVI		D, 0
		MOV		E, A
		LXI		H, DBF
		DAD		D
		MOV		A, M
		CPI		DEOF
		JZ		DEF				;END OF FILE
		LXI		H, DBP
		INR		M
		ORA		A
		JMP		RRET
;
NDI:							;NEXT BUFFER IN
		MVI		C, RDF
		LXI		D, DFCB
		CALL	TRAPAD
		ORA		A
		JNZ		DEF
;
								;BUFFER READ OK
		STA		DBP				;STORE 00H
		JMP		RDC
;
DEF:							;SET CARRY AND RETURN (END FILE)
		STC
RRET:
		POP		B
		POP		D
		POP		H
		RET
;
CERROR:							;ERROR IN COMMAND
		CALL	CRLF
		MVI		A, '?'
		CALL	PCHAR
		JMP		START
;
; SUBROUTINES
GETBUFF:						;FILL COMMAND BUFFER AND SET POINTERS
		MVI		C, GETF			;GET BUFFER FUNCTION
		LXI		D, COMLEN		;START OF COMMAND 8UFFER
		CALL	TRAPAD			;FILL BUFFER
		LXI		H, COMBUF		;NEXT TO GET
		SHLD	NEXT COM
		RET
;
BLANK:
		MVI		A, ' '
;
PCHAR:							;PRINT CHARACTER TO CONSOLE
		PUSH	H
		PUSH	D
		PUSH	B
		MOV		E, A
		MVI		C, COF
		CALL	TRAPAD
		POP		B
		POP		D
		POP		H
		RET
;
TRANS:
								;TRANSLATE TO UPPER CASE
		CPI		7FH				;RUBOUT?
		RZ
		CPI		('A' OR 0100000B)	;UPPER CASE A
		RC
		ANI		1011111B		;CLEAR UPPER  CASE BIT
		RET
;
GNC:
								;GET NEXT BUFFER CHARACTER FROM CONSOLE
		PUSH	H				;SAVE FOR REUSE LOCALLY
		LXI		H, CURLEN
		MOV		A, M
		ORA		A				;ZERO?
		MVI		A, CR
		JZ		GNCRET			;RETURN UITH CR IF EXHAUSTED
		DCR		M				;CURLEN=CURLEN-1
		LHLD	NEXTCOM
		MOV		A, M			;GET NEXT CHARACTER
		INX		H				;NEXTCOM=NEXTCOM+1
		SHLD	NEXTCOM			;UPDATED
		CALL	TRANS
GNCRET:
		POP		H				;RESTORE ENVIRONMENT
		RET
;
PNIB:							;PRINT NIBBLE IN LO ACCUM
		CPI		10
		JNC		PNIBH			;JUMP IF A-F
		ADI		'0'
		JMP		PCHAR			;RET THRU PCHAR
PNIBH:
		ADI		'A'-IO
		JMP		PCHAR
;
PBYTE:
		PUSH	PSW				;SAVE A COPY FOR LO NIBBLE
		RAR
		RAR
		RAR
		RAR
		ANI		0FH				;MASK HO NIBBLE TO LO NIBBLE
		CALL	PNIB
		POP		PSW				;RECALL BYTE
		ANI		0FH
		JMP		PNIB
;
CRLF:							;CARRIAGE RETURN LINE FEED
		MVI		A, CR
		CALL	PCHAR
		MVI		A, LF
		JMP		PCHAR
;
BREAK:							;CHECK FOR BREAK KEY
		PUSH	B
		PUSH	D
		PUSH	H
		MVI		C, CHKIO
		CALL	TRAPAD
		ANI		18
		POP		H
		POP		D
		POP		B
		RET
;
PADDX:							;SAME AS PADDR, EXCEPT PRINT VALUE IN D,E
		XCHG
;
PADDR:							;PRINT THE ADDRESS VALUE IN H,L
		MOV		A, H
		CALL	PBYTE
		MOV		A, L
		JMP		PBYTE
;
PGRAPH:							;PRINT GRAPHIC CHARACTER IN REG-A OR '.' IF NOT
		CPI		7FH
		JNC		PPERIOD
		CPI		' '
		JNC		PCHAR
PPERIOD:
		MVI		A, '.'
		JMP		PCHAR
;
DISCOM:							;COMPARE H,L AGAINST DISMAX, CARRY SET IF HL > DISMAX AND
		XCHG
		LHLD	DISMAX
		MOV		A, L
		SUB		E
		MOV		L, A			;REPLACE FOR ZERO TESTS LATER
		MOV		A, H
		SBB		D
		XCHG
		RET
;
DELIM:							;CHECK FOR DELIMITER CHARACTER
		CPI		CR
		RZ
		CPI		','
		RZ
		CPI		' '
		RET
;
HEXCON:							;CONVERT ACCUMULATOR TO PURE BINARY FROM EXTERNAL HEX
		SUI		'0'
		CPI		10
		RC						;MUST BE 0-9
		ADI		('0'-'A'+10) AND 0FFH
		CPI		16
		RC						;MUST BE 0-15
		JMP		CERROR			;BAD HEX DIGIT
;
GETVAL:							;GET NEXT EXPRESSION VALUE TO H,L (POINTER IN D,E ASSUMED)
		XCHG
		MOV		E, M
		INX		H
		MOV		D, M
		INX		H
		XCHG
		RET
;
GETEXP:							;GET HEX VALUE TO D,E
		XCHG
		LXI		H, 0
GETEXP0:
		CALL	HEXCON
		DAD		H				;*2
		DAD		H				;*4
		DAD		H				;*8
		DAD		H				;*16
		ORA		L				;HL=HL+HEX
		MOV		L, A
		CALL	GNC
		CALL	DELIM			;DELIMITER?
		JNZ		GETEXP0
		XCHG
		RET
;
SCSTORE:						;STORE D,E TO H,L AND INCREMENT ADDRESS
		MOV		M, E
		INX		H
		MOV		M, D
		INX		H
		PUSH	H
		LXI		H, EXPLIST
		INR		M				;COUNT NUMBER OF EXPN'S
		POP		H
		RET
;
SCANEXP:						;SCAN EXPRESSIONS - CARRY SET IF ,B
								;ZERO SET IF NO EXPRESSIONS, A SET TO NUMBER OF EXPRESSIONS
								;H1 ORDER BIT SET IF ,B ALSO
		CALL	GNC
SCANEX:							;ENTER HERE IF CHARACTER ALREADY SCANNED
		LXI		H, EXPLIST
		MVI		M, 0			;ZERO EXPRESSIONS
		INX		H				;READY TO FILL EXPRESSION LIST
		CPI		CR				;END OF LINE?
		JZ		SCANRET
;
								;NOT CR, MUST BE DIGIT OR COMMA
		CPI		','
		JNZ		SCANE0
								;MARK AS COMMA
		MVI		A, 80H
		STA		EXPLIST
		LXI		D, 0
		JMP		SCANE1
;
SCANE0:							;NOT CR OR COMMA
		CALL	GETEXP			;EXPRESSION TO D,E
SCANE1:
		CALL	SCSTORE			;STORE THE EXPRESSION AND INCREMENT H,L
		CPI		CR
		JZ		SCANRET
		CALL	GNC
		CALL	GETEXP
		CALL	SCSTORE
								;SECOND DIGIT SCANNED
		CPI		CR
		JZ		SCANRET
		CALL	GNC
		CALL	GETEXP
		CALL	SCSTORE
		CPI		CR
		JNZ		CERROR
SCANRET:
		LXI		D, EXPLIST		;LOOK AT COUNT
		LDAX	D				;LOAD COUNT TO ACC
		CPI		81H				;, WITHOUT B?
		JZ		CERROR
		INX		D				;READY TO EXTRACT EXPN'S
		ORA		A				;ZERO FLAG MAY BE SET
		RLC
		RRC						;SET CARRY IF HO BIT SET (,B)
		RET						;WITH FLAGS SET
;
;
								;SUBROUTINES FOR CPU STATE DISPLAY
FLGSHF:							;SHIFT COMPUTATION FOR FLAG GIVEN BY REG-B
								;REG A CONTAINS FLAG UPON EXIT (UNSHIFTED)
								;REG C CONTAINS NUMBER OF SHIFTS REQUIRED+1
								;REGS D,E CONTAIN ADDRESS OF FLAGS IN TEMPLATE
		PUSH	H
		LXI		H, FLGTAB		;SHIFT TABLE
		MOV		E, B
		MVI		D, 0
		DAD		D
		MOV		C, M			;SHIFT COUNT TO C
		LXI		H, FLOC			;ADDRESS OF FLAGS
		MOV		A, M			;TO REG A
		XCHG					;SAVE ADDRESS
		POP		H
		RET
;
GETFLG:							;GET FLAG GIVEN BY REG-B TO REG-A AND MASK
		CALL	FLGSHF			;BITS TO SHIFT IN REG-A
GETFLO:
		DCR		C
		JZ		GETFL1
		RAR
		JMP		GETFL0
GETFL1:
		ANI		IB
		RET
;
GETDBA:							;GET DOUBLE BYTE ADDRESS CORRESPONDING TO REG-A TO HL
		SUI		BVAL			;NORMAL1ZE TO 0,1,...
		LXI		H, RINX			;INDEX TO STACKED VALUES
		MOV		E, A			;INDEX TO E
		MVI		D, 0			;DOUBLE PRECISION
		DAD		D				;INDEXED INTO VECTOR
		MOV		E, M			;OFFSET TO E
		MVI		D, 0FFH			;-1
		LXI		H, STACK
		DAD		D				;HL HAS BASE ADDRESS
		RET
;
GETDBL:							;GET DOUBLE BYTE CORRESPONDING TO REG-A TO HL
		CALL	GETDBA			;ADDRESS OF ELT IN HL
		MOV		E, M			;LSB
		INX		H
		MOV		D, M			;MSB
		XCHG					;BACK TO HL
		RET
;
DELT:							;DISPLAY CPU ELEMENT GIVEN BY COUNT IN REG-B, ADDRESS IN H,L
		MOV		A, M			;GET CHARACTER
		CALL	PCHAR			;PRINT IT
		MOV		A, B			;GET COUNT
		CPI		AVAL			;PAST A?
		JNC		DELT0			;JMP IF NOT FLAG
;
								;DISPLAY FLAG
		CALL	GETFLG			;FLAG TO REG-A
		CALL	PNIB
		RET
;
DELT0:							;NOT FLAG, DISPLAY = AND DATA
		PUSH	PSW
		MVI		A, '='
		CALL	PCHAR
		POP		PSW
		JNZ		DELT1			;JUMP IF NOT REG-A
;
								;REGISTER A, DISPLAY BYTE VALUE
		LXI		H, ALOC
		MOV		A, M
		CALL	PBYTE
		RET
;
DELT1:							;DOUBLE BYTE DISPLAY
		CALL	GETDBL			;TO H,L
		CALL	PADDR			;PRINTED
		RET
;
DSTATE:							;DISPLAY CPU STATE
		LXI		H, RVECT		;REGISTER VECTOR
		MVI		B, 0			;REGISTER COUNT
		CALL	CRLF
DSTA0:
		PUSH	B
		PUSH	H
		CALL	DELT			;ELEMENT DISPLAYED
		POP		H				;RVECT ADDRESS RESTORED
		POP		B				;COUNT RESTORED
		INR		B				;NEXT COUNT
		INX		H				;NEXT REGISTER
		MOV		A, B			;LAST COUNT?
		CPI		PVAL+1
		JNC		DSTA1			;JMP IF PAST END
		CPI		AVAL			;BLANK AFTER?
		JC		DSTA0
								;YES, BLANK AND GO AGAIN
		CALL	BLANK
		JMP		DSTA0
;
								;READY TO SEND DECODED INSTRUCTION
DSTA1:
		CALL	BLANK
		CALL	NBRK			;COMPUTE BREAKPOINTS IN CASE OF TRACE
		PUSH	PSW				;SAVE EXPRESSION COUNT - B,C AND D,E HAVE
		PUSH	D				;SAVE BP ADDRESS
		PUSH	B				;SAVE AUX BREAKPOINT
		CALL	CHKDIS			;CHECK TO SEE IF DISASSEMBER IS HERE
		JNC		DCHEX			;DISPLAY HEX IF NOT
								;DISASSEMBLE CODE
		LHLD	PLOC			;GET CURRENT PC
		SHLD	DISPC			;SET DISASSM PC
		LXI		H, DISPG		;PAGE MODE = 0FFH TO TRACE
		MVI		M, 0FFH
		CALL	DISEN
		JMP		DSTRET
;
DCHEX:							;DISPLAY HEX
		DCX		H				;POINT TO LAST TO WRITE
		SHLD	DISMAX			;SAVE FOR COMPARE BELOW
		LHLD	PLOC			;START ADDRESS OF TRACE
		MOV		A, M			;GET OPCODE
		CALL	PBYTE
		INX		H				;READY FOR NEXT BYTE
		CALL	DISCOM			;ZERO SET IF ONE BYTE TO PRINT, CARRY IF NO MO
		JC		DSTRET
		PUSH	PSW				;SAVE RESULT OF ZERO TEST
		CALL	BLANK			;SEPARATOR
		POP		PSW				;RECALL ZERO
		ORA		E				;ZERO TEST
		JZ		DSTA2
								;DISPLAY DOUBLE BYTE
		MOV		E, M
		INX		H
		MOV		D, M
		XCHG
		CALL	PADDR			;PRINT ADDRESS
		JMP		DSTRET
;
DSTA2:							;PRINT BYTE VALUE
		MOV		A, M
		CALL	PBYTE
DSTRET:
		POP		B				;AUX BREAKPOINT
		POP		D				;RESTORE BREAKPOINT
		POP		PSW				;RESTORE COUNT
		RET
;
								;DATA VECTORS FOR CPU DISPLAY
RVECT:
		DB		'C ZMEIABDHSP'
RINX:
		DB		(BLOC-STACK) AND 0FFH	;LOCATION OF BC
		DB		(DLOC-STACK) AND 0FFH	;LOCATION OF DE
		DB		(HLOC-STACK) AND 0FFH	;LOCATION OF HL
		DB		(SLOC-STACK) AND 0FFH	;LOCATION OF SP
		DB		(PLOC-STACK) AND 0FFH	;LOCATION OF PC
								;FLGTAB ELEMENTS DETERMINE SHIFT COUNT TO SET/EXTRACT FLAGS
FLGTAB:
		DB		. 1, 7, 8, 3, 5	;CY, ZER, SIGN, PAR, IDCY
;
CLRTRACE:						;CLEAR THE TRACE FLAG
		LXI		H, 0
		SHLD	TRACER
		RET
;
BREAKP:							;ARRIVE HERE WHEN PROGRAMMED BREAK OCCURS
		DI
		SHLD	HLOC			;HL SAVED
		POP		H				;RECALL RETURN ADDRESS
		DCX		H				;DECREMENT FOR RESTART
		SHLD	PLOC
								;DAD SP BELOW DESTROYS CY, SO SAVE AND RECALL
		PUSH	PSW				;INTO USER'S STACK
		LXI		H, 2			;BIAS SP 8Y 2 BECAUSE OF PUSH
		DAD		SP				;SP IN HL
		POP		PSW				;RESTORE CY AND FLAGS
		LXI		SP, STACK-4		;LOCAL STACK
		PUSH	H				;SP SAVED
		PUSH	PSW
		PUSH	B
		PUSH	D
								;MACHINE STATE SAVED, CLEAR BREAK POINTS
		LHLD	PLOC			;CHECK FOR RST INSTRUCTION
		MOV		A, M			;OPCODE TO A
		CPI		RSTIN
								;SAVE CONDITION CODES FOR LATER TEST
		PUSH	PSW
								;SAVE PLOC FOR LATER INCREMENT OR DECREMENT
		PUSH	H
;
								;CLEAR BREAKPOINTS WHICH ARE PENDING
		LXI		H, BREAKS
		MOV		A, M
		MVI		M, 0			;SET TO ZERO BREAKS
CLER0:
		ORA		A				;ANY MORE?
		JZ		CLER1
		DCR		A
		MOV		B, A			;SAVE COUNT
		INX		H				;ADDRESS OF BREAK
		MOV		E, M			;LOW ADDR
		INX		H
		MOV		D, M			;HIGH ADDR
		INX		H
		MOV		A, M			;INSTRUCTION
		STAX	D				;BACK TO PROGRAM
		MOV		A, B			;RESTORE COUNT
		JMP		CLER0
;
CLER1:							;CLEARED, CONTINUE TRACING, OR STOP EXECUTION
		POP		H				;RESTORE PLOC
		POP		PSW				;RESTORE CONDITION FLAGS
		JZ		BREAK0			;BRANCH IF PROGRAMMED INTERRUPT
;
								;MUST BE FRONT PANEL INTERRUPT, CHECK IF IN BDOS
		INX		H				;DON'T DECREMENT ON PANEL INTERRUPT
		SHLD	PLOC			;RESTORE TO NEXT LOGICAL INSTRUCTION
		XCHG					;TO D,E FOR COMPARE
		LXI		B, BDOS			;BASE OF DOS
		CALL	BCDE			;CY IF BDOS >= PL0C
		JC		BREAK0			;BRANCH IF PLOC <= BDOS
;
								;IN THE BDOS, DON'T BREAK UNTIL THE RETURN OCCURS
		CALL	CLRTRACE		;CLEAR TRACE FLAGS
		LHLD	RETLOC			;TRAPPED RETLOC ON ENTRY TO DOS
		XCHG					;TO D,E READY FOR BREAKPOINT
		MVI		A, 82H			;LOOKS LIKE G,8888
		ORA		A				;SETS FLAGS
		STC						;SUBSEQUENT TEST FOR CY
		JMP		GOPR			;START PROGRAM EXECUTION, WITH BREAKPOINT
;
BREAK0:							;NORMAL BREAKPOINT
		EI
		LHLD	TRACER
		MOV		A, H
		ORA		L
		JZ		STOPEX
;
								;TRACE IS ON
		DCX		H
		SHLD	TRACER
		CALL	BREAK			;BREAK KEY DEPRESSED?
		JNZ		STOPEX
		LDA		TMODE			;TRACE MODE T IF 0FFH
		ORA		A
		JNZ		BREAK1
								;NOT IRACING, BUT MONITORING, SO SET BREAKPOINTS
		CALL	NBRK
		JMP		GOPR
;
BREAK1:							;TRACING AND MONITORING
		CALL	DSTATE			;STATE DISPLAYED, CHECK FOR BREAKPOINTS
		JMP		GOPR			;STARTS EXECUTION
;
STOPEX:
		LXI		H, 0
		SHLD	USERBRK			;CLEAR USER BREAK ADDRESS
		CALL	CLRTRACE		;TRACE FLAGS GO TO ZERO
		MVI		A, '*'
		CALL	PCHAR
		LHLD	PLOC
								;CHECK TO ENSURE DISASSEMBLER IS PRESENT
		CALL	CHKDIS
		JNC		STOP0
		SHLD	DISPC
STOP0:
		CALL	PADDR
		LHLD	HLOC
		SHLD	DISLOC
		JMP		START
;
CAT:							;DETERMINE OPCODE CATEGORY - CODE IN REGISTER B
								;D,E CONTAIN DOUBLE PRECISION CATEGORY NUMBER ON RETURN
		LXI		D, OPMAX		;D=0,E=OPMAX
		LXI		H, OPLIST
CAT0:
		MOV		A, M			; MASK TO A
		AHA		B				;MASK OPCODE FROM B
		INX		H				;READY FOR COMPARE
		CMP		M				;SAME AFTER MASK?
		INX		H				;READY FOR NEXT COMPARE
		JZ		CAT1			;EXIT IF COMPARED OK
		INR		D				;UP COUNT IF NOT MATCHED
		DCR		E				;FINISHED?
		JNZ		CAT0
CAT1:
		MOV		E, D			;E IS CATEGORY NUMBER
		MVI		D, 0			;DOUBLE PRECISION
		RET
;
NBRK:							;FIND NEXT BREAK POINT ADDRESS
								;UPON RETURN, REGISTER A IS SETUP AS IF USER TYPED G,B1,B2 OR
								;G,B1 DEPENDING UPON OPERATOR CATEGORY. B,C CONTAINS SECOND BP
								;D,E CONTAINS PRIMARY BP, HL ADDRESS NEXT OPCODE BYTE
		LHLD	PLOC
		MOV		B, M			;GET OPERATOR
		INX		H				;HL ADDRESS BYTE FOLLOWING OPCODE
		PUSH	H				;SAVE IT FOR LATER
		CALL	CAT				;DETERMINE OPERATOR CATEGORY
		LXI		H, CATNO		;SAVE CATEGORY NUMBER
		MOV		M, E
		LXI		H, CATTAB		;CATEGORY TABLE BASE
		DAD		D				;INXED
		DAD		D				;INXED*2
		MOV		E, M			;LOW BYTE TO E
		INX		H
		MOV		D, M			;HIGH BYTE TO D
		XCHG
		PCHL					;JUMP INTO TABLE
CAT TAB:
		DW		JMPOP			;JUMP OPERATOR
		DW		CCOP			;JUMP CONDITIONAL
		DW		JMPOP			;CALL OPERATOR (TREATED AS JMP)
		DW		CCOP			;CALL CONDITIONAL
		DW		RETOP			;RETURN FROM SUBROUTINE
		DW		RSTOP			;RESTART
		DW		PCOP			;PCHL
		DW		IMOP			;SINGLE PRECISION IMMEDIATE (2 BYTE)
		DW		IMOP			;ADI ... CPI
		DW		DIMOP			;DOUBLE PRECISION IMMEDIATE (3 BYTES)
		DW		DIMOP			;LHLD ... STA
		DW		RCOND			;RETURN CONDITIONAL
		DW		IMOP			;IN/OUT
								;NEXT DW MUST BE THE LAST IN THE SEQUENCE
		DW		SIMOP			;SIMPLE OPERATOR (1 BYTE)
;
JMPOP:							;GET OPERAND FIELD, CHECK FOR BDOS
		CALL	GETOPA			;GET OPERAND ADDRESS TO D,E AND COMPARE WITH
		JNZ		ENDOP			;TREAT AS SIMPLE OPERATOR IF NOT BDOS
								;OTHERWISE;TREAT AS A RETURN INSTRUCTION
RETOP:
		CALL	GETSP			;ADDRESS AT STACKTOP TO D,E
		JMP		ENDOP			;TREAT AS SIMPLE OPERATOR
;
CBDOS:							;COMPARE D,E WITH BDOS ADDRESS, RETURN ZERO FLAG IF EQUAL
		MVI		A, BDOS AND 0FFH
		CMP		E
		RNZ
		MVI		A, BDOS SHR 8
		CMP		D
		RET
;
GETOPA:							;GET OPERAND ADDRESS AND COMPARE WITH BDOS
		POP		B				;GET RETURN ADDRESS
		POP		H				;GET OPERAND ADDRESS
		MOV		E, M
		INX		H
		MOV		D, M
		INX		H
		PUSH	H				;UPDATED PC INTO STACK
		PUSH	B				;RETURN ADDRESS TO STACK
		JMP		CBDOS			;RETURN THROUGH CBDOS UITH ZERO FLAG SET
;
GETSP:							;GET RETURN ADDRESS FROM USER'S STACK TO D,E
		LHLD	SLOC
		MOV		E, M
		INX		H
		MOV		D, M
		RET
;
CCOP:							;CALL CONDITIONAL OPERATOR
		CALL	GETOPA			;GET OPERAND ADDRESS TO D,E / COMPARE WITH
		JZ		CCOP1
								;NOT THE BDOS, BREAK AT OPERAND ADDRESS AND NEXT ADDRESS
		POP		B				;NEXT ADDRESS TO B,C
		PUSH	B				;BACK TO STACK
		MVI		A, 2			;TWO BREAKPOINTS
		JMP		RETCAT			;RETURN FROM NBRK
;
CCOP1:							;BREAK ADDRESS AT NEXT LOCATION ONLY, WAIT FOR RETURN FROM
		POP		D
		PUSH	D				;BACK TO STACK
		JMP		ENDOP			;ONE BREAKPOINT ADDRESS
;
RSTOP:							;RESTART INSTRUCTION - CHECK FOR RST 7
		MOV		A, B
		CPI		RSTIN			;RESTART INSTRUCTION USED FOR SOFT INT
		JNZ		RST0
;
								;SOFT RST, NO BREAK POINT SINCE IT WILL OCCUR IMMEDIATELY
		XRA		A
		JMP		RETCAT1			;ZERO ACCUMULATOR
RST0:
		ANI		111000B			;GET RESTART NUMBER
		MOV		E, A
		MVI		D, 0			;DOUBLE PRECISION BREAKPOINT TO D,E
		JMP		ENDOP
;
PCOP:							;PCHL
		LHLD	HLOC
		XCHG					;HL VALUE TO D,E FOR BREAKPOINT
		CALL	CBDOS			;BDOS VALUE?
		JNZ		ENDOP
								;PCHL TO BDOS, USE RETURN ADDRESS
		JMP		RETOP
;
		JMP		ENDOP
;
SIMOP:							;SIMPLE OPERATOR, USE STACKED PC
		POP		D
		PUSH	D
		JMP		ENDOP
;
RCOND:							;RETURN CONDITIONAL
		CALL	GETSP			;GET RETURN ADDRESS FROM STACK
		POP		B				;B,C ALTERNATE LOCATION
		PUSH	B				;REPLACE IT
		MVI		A, 2
		JMP		RETCAT			;TO SET FLAGS AND RETURN
;
DIMOP:							;DOUBLE PRECISION IMMEDIATE OPERATOR
		POP		D
		INX		D				;INCREMENTED ONCE, DROP THRU FOR ANOTHER
		PUSH	D				;COPY BACK
;
IMOP:							;SINGLE PRECISION IMMEDIATE
		POP		D
		INX		D
		PUSH	D
;
ENDOP:							;END OPERATOR SCAN
		MVI		A, 1			;SINGLE BREAKPOINT
RETCAT:							;RETURN FROM NBRK
		INR		A				;COUNT UP FOR G,...
		STC
RETCAT1:
		PUSH	PSW				;SAVE REGISTER STATE IN CASE USERBRK
		LHLD	USERBRK
		MOV		A, H
		ORA		L
		JZ		RETCAT2			;NO USERBRK IF ZERO
;
		PUSH	D				;SAVE BREAK POINT
		PUSH	B				;SAVE AUX BREAK POINT
		PUSH	H				;SAVE USERBRK ADDRESS FOR PCHL BELOW
								;USER BREAK OCCURS HERE, CALL USER ROUTINE AND CHECK RETURN
		LXI		H, CATNO
		MOV		C, M			;OPCODE CATEGORY IS IN C
		LHLD	PLOC
		XCHG					;LOCATION OF INSTRUCTION IN D,E
		LXI		H, RETUSER
		XTHL					;RETURN ADDRESS TO STACK, USERBRK TO H,L
		PCHL
RETUSER:						;RETURN FROM USER BREAK, CHECK REGISTER A
		ORA		A
		POP		B				;RESTORE BREAKPOINTS
		POP		D
		JZ		RETCAT2
;        ABORT THE OPERATION WITH A CONDITION
		PUSH	PSW
		MVI		A, '#'
		CALL	PCHAR
		POP		PSW
		CALL	PBYTE
		MVI		A, ' '
		CALL	PCHAR
		JMP		STOPEX			;STOP EXECUTION
RETCAT2:
		POP		PSW				;RECALL G, STATE
		POP		H				;RECALL NEXT ADDRESS
		RET
;
;
;
;        OPCODE CATEGORY TABLES
OPLIST:
		DB		1111$1111B, 1100$0011B	;0 JMP
		DB		1100$0111B, 1100$0010B	;1 JCOHD
		DB		1111$1111B, 1100$1101B	;2 CALL
		DB		1100$0111B, 1100$0100B	;3 CCOHD
		DB		1111$1111B, 1100$1001B	;4 RET
		DB		1100$0111B, 1100$0111B	;5 RST 0..7
		DB		1111$1111B, 1110$1001B	;6 PCHL
		DB		1100$0111B, 0000$0110B	;7 MVI
		DB		1100$8111B, 1100$0110B	;8 ADI...CPI
		DB		1100$1111B, 0000$0001B	;9 LXI
		DB		1110$0111B, 0810$0010B	;10 LHLD  SHLD LDA S
		DB		1100$0111B, 1100$0000B	;11 RCOND
		DB		1111$8111B, 1101$0011B	;IN OUT
		OPMAX	EQU ($-OPLIST)/2
;
CATNO:	DS		1				;CATEGORY NUMBER SAVED IN NBRK
USERBRK:DS		2				;USER BREAK ADDRESS IF NON-ZERO
RETLOC:	DS		2				;RETURN ADDRESS TO USER FROM BDOS
TMODE:	DS		1				;TRACE MODE
TRACER:	DS		2				;TRACE COUNT
BREAKS:	DS		7				;#BREAKS/BKPT1/DAT1/BKPT2/DAT2
EXPLIST:DS		7				;C0UNT+(EXP1)(EXP2)(EXP3)
DISLOC:	DS		2				;DISPLAY LOCATION
DISMAX:	DS		2				;MAX VALUE FOR CURRENT DISPLAY
TDISP:	DS		2				;TEMP I6 BIT LOCATION
NEXTCOM:DS		2				;NEXT LOCATION FROM COMMAND BUFFER
COMLEN:	DB		CSIZE			;MAX COMMAND LENGTH
CURLEN:	DS		1				;CURRENT COMMAND LENGTH
COMBUF:	DS		CSIZE			;COMMAND BUFFER
MLOAD:	DS		2				;MAX LOAD ADDRESS
		DS		SSIZE			;STACK AREA
STACK:	PLOC	EQU STACK-2		;PC IN TEMPLATE
		HLOC	EQU STACK-4		;HL
		SLOC	EQU STACK-6		;SP
		ALOC	EQU STACK-7		;A
		FLOC	EQU STACK-8		;FLAGS
		BLOC	EQU STACK-10	;BC
		DLOC	EQU STACK-12	;D,E
;
		NOP						;FOR RELOCATION BOUNDARY
		END
