;
;  PROGRAM:  DASM
;  VERSION:  1.5
;  AUTHOR:  RICHARD CONN
;  DATE:  16 AUG 82
;  PREVIOUS VERSIONS:  1.3 (23 MAY 82), 1.4 (12 JUNE 82)
;  PREVIOUS VERSIONS:  1.0 (1 MAY 82), 1.1 (8 MAY 82), 1.2 (15 MAY 82)
;  DERIVATION:	ZZSOURCE AND RESOURCE
;
;	DASM IS A TDL/ZILOG DISASSEMBLER DERIVED FROM DAVE BARKER'S
; ZZSOURCE AND WARD CHRISTENSEN'S RESOURCE BY RICHARD CONN.  REFER TO
; THE DOCUMENTATION ON RESOURCE AND THE BUILT-IN HELP DATA FOR INFORMATION
; ON THE COMMANDS USED FOR DASM.  A HELP FILE IS ALSO BEING PLANNED FOR DASM.
;
VERS	EQU	15	; VERSION NUMBER

;  INITIAL VALUES FOR DASM
FALSE		EQU	0
TRUE		EQU	.NOT.FALSE
RDCOMQ		EQU	FALSE		;TRUE OF QUERY USER TO READ COM FILE
					;  WHEN 'ALL' IS FILE TYPE
SYMMAX		EQU	12		;MAX NUMBER OF CHARS/SYMBOL (<= 12)
INITLCNT	EQU	20		;NUMBER OF LINES TO DISPLAY VIA L, A, B
INITDLEN	EQU	80H		;NUMBER OF BYTES TO DISPLAY VIA D
INITPC		EQU	100H		;INITIAL VALUE OF PC
INITELST	EQU	0FFFFH		;INITIAL END OF LIST VALUE
IBUFLEN 	EQU	80		;LENGTH OF INPUT LINE BUFFER

;  CP/M CONSTANTS
WBOOT	EQU	00H
BDOS	EQU	05H
FCB	EQU	5CH
FCBNR	EQU	7CH
FCBTYPE EQU	65H
RECLEN	EQU	80H

;
;  BEGINNING OF PROGRAM
;
	ORG	0100H

	JP	START
	JP	GETCMD		;THIS IS AN EASY ENTRY POINT FOR A RESTART.

;THIS ROUTINE IS THE 6502 MNEMONIC DISASSEMBLER MODULE FOR DASM     
;	HACKED BY: WILLIAM F. DUDLEY JR. (DUDLEY@NADC)
;
HEADER:
	DEFB	'DASM for 6502-Standard Mnemonics',0DH,0AH
	DEFB	'       Derived from ZZSOURCE/RESOURCE',0DH,0AH
	DEFB	'$',0
;
;  THIS IS THE DISASSEMBLER MODULE -- INSTRUCTION TO BE DISASSEMBLED
;    IS PTED TO BY PC
;
DASM:
	CALL	HSYM		;WRITE A SYMBOL IF IT EXISTS
	;.. AND PUT PC ON THE CRT
	LD	HL,(RPLPTR)	;SEE IF THIS LINE IS REPLACED
	LD	A,H
	OR	L
	JR	Z,DASM1
	LD	B,(HL)
	INC	HL		;SKIP THE '*'
	DEC	B
	CALL	NWLN0		;PRINT THE REPLACING LINE AS A COMMENT
DASM1:
	LD	HL,(PC) 
	EX	DE,HL
	LD	HL,(OFFSET)
	ADD	HL,DE		;HL IS NOW THE BIASED PC
	LD	(BIASED),HL
	EX	DE,HL		;DE IS NOW THE BIASED PC
	INC	HL
	LD	(PC),HL 	;THE NEW PC (NEXT BYTE)
	EX	DE,HL		;DE IS THE BYTE AFTER THE INSTRUCTION
	LD	B,(HL)
	LD	HL,OPC-4
	CALL	GTCD
	CALL	TYPEOC
	CP	02H		;TYPES 0 AND 1 ARE 1 BYTE
	JR	C,OLDPC 	; .. SO DON'T CHANGE THE PC
	LD	HL,(PC)
	INC	HL
	CP	09H		;TYPES 02 THRU 08H ARE 2-BYTERS
	JR	C,NEWPC
	INC	HL		;ELSE MUST BE 3 BYTES
NEWPC:
	LD	(PC),HL
OLDPC:
	PUSH	DE		;SAVE THE 'E' REGISTER (MAY BE 'X' OR 'Y')
	LD	E,A
	LD	D,0
	LD	HL,JMPTBL
	ADD	HL,DE		;ADD 2*OPCODE TYPE TO JMPTBL TO GET
	ADD	HL,DE		;.. ROUTINE ADDRESS
	LD	E,(HL)
	INC	HL
	LD	D,(HL)
	EX	DE,HL		;HL NOW CONTAINS THE ROUTINE ADDRESS
	POP	DE
	PUSH	HL
	LD	HL,(BIASED)
	RET			;'RETURN' TO THE ROUTINE
;
GTCD:
	LD	DE,4
NXTCD:
	ADD	HL,DE
NXTCD1:
	LD	A,(HL)
	OR	A		;SEE IF WE'RE AT THE NEXT MASK YET
	INC	HL
	JP	P,NXTCD1	;JUMP IF NOT
	AND	B		;MASK OUT VARIABLES IN THE INSTRUCTION
	CP	(HL)		;CHECK THE GENERIC INSTRUCTION TYPE
	JR	NZ,NXTCD
	INC	HL
	LD	A,(HL)		;AFTER A MATCH, GET THE OPCODE TYPE
	LD	(OPCTP),A
	RET	
;
TOC2:
	CP	20H		;CONVERT SPACES IN THE TABLE TO TABS
	JR	NZ,TOC1
	LD	A,9
TOC1:
	CALL	COUT
TYPEOC:
	INC	HL		;TYPE THE OPCODE THAT HL IS POINTING TO
	LD	A,(HL)
	OR	A
	JR	Z,TYPEOC
	JP	P,TOC2
	LD	HL,(PC)
	LD	A,(OPCTP)
	RET	
;
JMPTBL:
	DEFW	T0		;SIMPLE 1 BYTE INSTRUCTIONS
	DEFW	T2A		;UNDEFINED OPCODES	
	DEFW	TB		;8 BIT IMMEDIATE ARITH. & LOGICAL
	DEFW	TF		;RELATIVE JUMPS
	DEFW	TDZX		;ZERO, X
	DEFW	TDX		;IND, X
	DEFW	TDY		;IND, Y
	DEFW	TDZY		;ZERO, Y
	DEFW	TDZP		;ZERO PAGE
	DEFW	T11		;JUMPS & CALLS
	DEFW	TWX		;ABS, X
	DEFW	TWY		;ABS, Y
	DEFW	JPIND		;JUMP INDIRECT
;
;ONE BYTE INSTRUCTIONS, SIMPLE
;
T0:
	JP	DCRLF
;
;ARITHMETIC & LOGICAL IMMEDIATES
TB:
	INC	HL
DTABYT:
	LD	A,(HL)
	CP	' '
	JR	C,NOTASC
	CP	5BH
	JR	NC,NOTASC
	CALL	PASCII
	LD	A,''''
	CALL	COUT
	LD	A,(XCSW)	;WANT SYMBOL COMMENTS?
	OR	A
	JP	Z,DCRLF
	CALL	TAB
	CALL	SEMI
NOTASC:
	LD	A,(HL)
	CP	0AH
	JR	C,NTSC0
	CALL	PASHEX
	LD	A,'H'
	CALL	COUT
	JP	DCRLF
NTSC0:
	ADD	A,'0'
	CALL	COUT
	JP	DCRLF
;
TDX:
	CALL	LPAR
	INC	HL
	LD	E,(HL)
	LD	D,0
	CALL	PRNTDE
	CALL	C,PDERTN
;	LD	A,(HL)
;	CALL	PASHEX
;	LD	A,'H'
;	CALL	COUT
	CALL	COMMA
	LD	A,'X'
	CALL	COUT
	CALL	RPAR
	JP	DCRLF
;
TDY:
	CALL	LPAR
	INC	HL
	LD	E,(HL)
	LD	D,0
	CALL	PRNTDE
	CALL	C,PDERTN
;	LD	A,(HL)
;	CALL	PASHEX
;	LD	A,'H'
;	CALL	COUT
	CALL	RPAR
	CALL	COMMA
	LD	A,'Y'
	CALL	COUT
	JP	DCRLF
;
TDZX:
	INC	HL
	LD	A,(HL)
	CALL	PASHEX
	LD	A,'H'
	CALL	COUT
	CALL	COMMA
	LD	A,'X'
	CALL	COUT
	JP	DCRLF
;
TDZY:
	INC	HL
	LD	A,(HL)
	CALL	PASHEX
	LD	A,'H'
	CALL	COUT
	CALL	COMMA
	LD	A,'Y'
	CALL	COUT
	JP	DCRLF
;
TWY:	CALL	PRNN
	PUSH	AF
	CALL	COMMA
	LD	A,'Y'
	CALL	COUT
	POP	AF
	CALL	C,PDERTN
	JP	DCRLF
;
TWX:	CALL	PRNN
	PUSH	AF
	CALL	COMMA
	LD	A,'X'
	CALL	COUT
	POP	AF
	CALL	C,PDERTN
	JP	DCRLF
;
; ZERO PAGE ADDRESSES
;
TDZP:	INC	HL
	LD	E,(HL)
	LD	D,0
	CALL	PRNTDE
	CALL	C,PDERTN
	JP	DCRLF
;
;OTHER RELATIVE INSTRUCTIONS
TF:
	INC	HL
	LD	A,(HL)
	LD	E,A
	LD	D,0
	LD	HL,(PC)
	OR	A
	JP	P,PSTV
	DEC	D
PSTV:
	ADD	HL,DE
	EX	DE,HL
	CALL	PRNTDE
	CALL	C,PDERTN
	JP	DCRLF
;
;JUMPS AND CALLS
T11:
	CALL	PRNN
	CALL	C,PDERTN
	JP	DCRLF
;
JPIND:	CALL	DRADR
	CALL	C,PDERTN
	JP	DCRLF
;
DRADR:
	CALL	LPAR		;PRINT THE VALUE FOR DE IN PARENTHESIS
	CALL	PRNN
	PUSH	AF
	CALL	RPAR
	POP	AF
	RET	
;
;ALL UNDEFINED OPCODES COME HERE FOR A 'DB VALUE' TREATMENT
;
T2A:
	LD	HL,(BIASED)
	CALL	PSTG
	DEFB	'DB',9,0
	JP	DTABYT
;
;  VARIOUS CHARACTERS TO PRINT
;
COMMA:
	LD	A,','
	JP	COUT
TAB:
	LD	A,9
	JP	COUT
SEMI:
	LD	A,';'
	JP	COUT
LPAR:
	LD	A,'('
	JP	COUT
RPAR:
	LD	A,')'
	JP	COUT
PCMAA:
	CALL	COMMA
	LD	A,'A'
	JP	COUT
;
;  PRINT THE CONDITION CODE LETTERS FOR THIS INSTRUCTION.
;
PRCND:
	LD	A,(HL)
	AND	38H		;FOR A FULL SET OF CONDITION CODES
PRC:
	RRCA	
	RRCA	
	LD	HL,CNDTAB
	CALL	SKIP
	LD	A,(HL)
	CALL	COUT
	INC	HL
	LD	A,(HL)
	CP	'.'
	CALL	NZ,COUT
	RET	
PRCND1:
	LD	A,(HL)
	AND	18H
	JR	PRC
CNDTAB:
	DEFB	'NZZ.NCC.POPEP.M.'
;
;  PRINT THE SOURCE REGISTER FOR A BYTE
;
PSREG:
	LD	A,(HL)
PREG:
	LD	HL,REGTAB
	AND	7
	CP	6		;MUST CATCH THE (HL) REFERENCES
	JP	Z,PHLREG
	CALL	SKIP
	LD	A,(HL)
	JP	COUT
PHLREG:
	CALL	LPAR
	LD	A,'H'
	CALL	COUT
	LD	A,'L'
	CALL	COUT
	JP	RPAR
PDREG:
	LD	A,(HL)		;PRINT THE DESTINATION REGISTER FOR A BYTE
	RRA	
	RRA	
	RRA	
	JP	PREG
;
;  ADVANCE H&L BY (A)
;
SKIP:
	ADD	A,L
	LD	L,A
	RET	NC
	INC	H
	RET	
REGTAB:
	DEFB	'BCDEHLMA'	;'M' IS NEVER PRINTED - '(HL)' IS INSTEAD
;
;  PRINT A DOUBLE REGISTER PAIR
;
PXSREG:
	LD	A,(HL)
	LD	HL,DREGS
	JR	PXREG
PXQREG:
	LD	A,(HL)
	LD	HL,DREGQ
PXREG:
	RRA	
	RRA	
	RRA	
	AND	6
	CALL	SKIP
	LD	A,(HL)
	CALL	COUT
	INC	HL
	LD	A,(HL)
	JP	COUT
DREGS:
	DEFB	'BCDEHLSP'
DREGQ:
	DEFB	'BCDEHLAF'
IXREGS:
	DEFB	'BCDEIXSP'
IYREGS:
	DEFB	'BCDEIYSP'
;
PBIT:
	LD	A,(HL)
	RRA	
	RRA	
	RRA	
	AND	7
	ADD	A,'0'
	JP	COUT
PRXX:
	LD	A,'I'
	CALL	COUT
	LD	A,E
	JP	COUT
;
;PRINT A LEADING QUOTE AND THEN THE ASCII
;.. (PRINT '' FOR ').
;
PASCII:
	PUSH	AF
	LD	A,''''
	CALL	COUT
	POP	AF
	CP	''''
	JP	NZ,COUT
	PUSH	AF
	CALL	COUT
	POP	AF
	JP	COUT
;PRINT THE VALUE IN A AS HEX
;  WITH A LEADING ZERO IF NECESSARY
PASHEX:
	CP	0A0H
	JP	C,PHEX
	PUSH	AF
	LD	A,'0'
	CALL	COUT
	POP	AF
	JP	PHEX
;PRINT THE STRING AT (HL) FOR (B) CHARACTERS.
PRNT:
	LD	A,(HL)
	CALL	COUT
	INC	HL
	DEC	B
	JP	NZ,PRNT
	RET	
;
;PRINT A DISPLACEMENT IN THE FORM '(IX+d)'
PDISP:
	CALL	LPAR
	CALL	PRXX
	LD	A,'+'
	CALL	COUT
	LD	A,(HL)
	CALL	PASHEX
	LD	A,'H'
	CALL	COUT
	JP	RPAR
;
;PRINT THE NEXT 2 BYTES AS A SYMBOL (AND RETURN CY=1) IF POSSIBLE
;
PRNN:
	INC	HL
	LD	E,(HL)
	INC	HL
	LD	D,(HL)
PRNTDE:
	PUSH	DE
	CALL	SYMSCH
	JP	C,NOMTCH
	CALL	PRNT		;GOT ONE, SO PRINT IT
	POP	DE
	SCF			;INDICATE THAT A SYMBOL WAS PRINTED
	RET	
NOMTCH:
	LD	A,(BUILD)	;DO WE BUILD A SYMBOL?
	OR	A
	POP	DE
	JR	Z,NOBLD 	;JUST PRINT THE HEX VALUE
	PUSH	DE
	CALL	BLDSYM
	POP	DE
	JR	NOBLD
PDERTN:
	LD	A,(XCSW)
	OR	A
	RET	Z		;DON'T PRINT THE SYMBOL AS A COMMENT
	CALL	TAB		;WE'LL PRINT A VALUE AS A COMMENT
	CALL	SEMI
NOBLD:
	LD	A,D
	OR	E
	LD	A,'0'
	JR	Z,NOBLD1
	LD	A,D
	OR	A
	JR	Z,NOBLD2
	CALL	PASHEX		;PRINT THE HIGH ORDER BYTE
	LD	A,E
	CALL	PHEX
NOBLD0:
	LD	A,'H'
NOBLD1:
	CALL	COUT
	OR	A		;CLEAR THE CARRY
	RET	
NOBLD2:
	LD	A,E
PRST:
	CP	0AH
	JR	C,NOBLD3
	CALL	PASHEX
	JR	NOBLD0
NOBLD3:
	ADD	A,'0'
	JR	NOBLD1
;
;  OPCODE TABLES
;
OPC:
	DEFB	0FFH,00AH,0,'ASL A'
	DEFB	0FFH,000H,0,'BRK'
	DEFB	0FFH,018H,0,'CLC'
	DEFB	0FFH,0D8H,0,'CLD'
	DEFB	0FFH,058H,0,'CLI'
	DEFB	0FFH,0B8H,0,'CLV'
	DEFB	0FFH,0CAH,0,'DEX'
	DEFB	0FFH,088H,0,'DEY'
	DEFB	0FFH,0E8H,0,'INX'
	DEFB	0FFH,0C8H,0,'INY'
	DEFB	0FFH,04AH,0,'LSR A'
	DEFB	0FFH,0EAH,0,'NOP'
	DEFB	0FFH,048H,0,'PHA'
	DEFB	0FFH,008H,0,'PHP'
	DEFB	0FFH,068H,0,'PLA'
	DEFB	0FFH,028H,0,'PLP'
	DEFB	0FFH,02AH,0,'ROL A'
	DEFB	0FFH,06AH,0,'ROR A'
	DEFB	0FFH,040H,0,'RTI'
	DEFB	0FFH,060H,0,'RTS'
	DEFB	0FFH,038H,0,'SEC'
	DEFB	0FFH,0F8H,0,'SED'
	DEFB	0FFH,078H,0,'SEI'
	DEFB	0FFH,0AAH,0,'TAX'
	DEFB	0FFH,0A8H,0,'TAY'
	DEFB	0FFH,098H,0,'TYA'
	DEFB	0FFH,0BAH,0,'TSX'
	DEFB	0FFH,08AH,0,'TXA'
	DEFB	0FFH,09AH,0,'TXS'
	DEFB	0FFH,069H,02H,'ADC #'
	DEFB	0FFH,029H,02H,'AND #'
	DEFB	0FFH,0C9H,02H,'CMP #'
	DEFB	0FFH,0E0H,02H,'CPX #'
	DEFB	0FFH,0C0H,02H,'CPY #'
	DEFB	0FFH,049H,02H,'EOR #'
	DEFB	0FFH,0A9H,02H,'LDA #'
	DEFB	0FFH,0A2H,02H,'LDX #'
	DEFB	0FFH,0A0H,02H,'LDY #'
	DEFB	0FFH,009H,02H,'ORA #'
	DEFB	0FFH,0E9H,02H,'SBC #'
	DEFB	0FFH,090H,03H,'BCC '
	DEFB	0FFH,0B0H,03H,'BCS '
	DEFB	0FFH,0F0H,03H,'BEQ '
	DEFB	0FFH,030H,03H,'BMI '
	DEFB	0FFH,0D0H,03H,'BNE '
	DEFB	0FFH,010H,03H,'BPL '
	DEFB	0FFH,050H,03H,'BVC '
	DEFB	0FFH,070H,03H,'BVS '
	DEFB	0FFH,06DH,09H,'ADC '
	DEFB	0FFH,02DH,09H,'AND '
	DEFB	0FFH,00EH,09H,'ASL '
	DEFB	0FFH,02CH,09H,'BIT '
	DEFB	0FFH,0CDH,09H,'CMP '
	DEFB	0FFH,0ECH,09H,'CPX '
	DEFB	0FFH,0CCH,09H,'CPY '
	DEFB	0FFH,0CEH,09H,'DEC '
	DEFB	0FFH,04DH,09H,'EOR '
	DEFB	0FFH,0EEH,09H,'INC '
	DEFB	0FFH,04CH,09H,'JMP '
	DEFB	0FFH,020H,09H,'JSR '
	DEFB	0FFH,0ADH,09H,'LDA '
	DEFB	0FFH,0AEH,09H,'LDX '
	DEFB	0FFH,0ACH,09H,'LDY '
	DEFB	0FFH,04EH,09H,'LSR '
	DEFB	0FFH,00DH,09H,'ORA '
	DEFB	0FFH,02EH,09H,'ROL '
	DEFB	0FFH,06EH,09H,'ROR '
	DEFB	0FFH,0EDH,09H,'SBC '
	DEFB	0FFH,08DH,09H,'STA '
	DEFB	0FFH,08EH,09H,'STX '
	DEFB	0FFH,08CH,09H,'STY '
	DEFB	0FFH,065H,08H,'ADC '
	DEFB	0FFH,025H,08H,'AND '
	DEFB	0FFH,006H,08H,'ASL '
	DEFB	0FFH,024H,08H,'BIT '
	DEFB	0FFH,0C5H,08H,'CMP '
	DEFB	0FFH,0E4H,08H,'CPX '
	DEFB	0FFH,0C4H,08H,'CPY '
	DEFB	0FFH,0C6H,08H,'DEC '
	DEFB	0FFH,045H,08H,'EOR '
	DEFB	0FFH,0E6H,08H,'INC '
	DEFB	0FFH,0A5H,08H,'LDA '
	DEFB	0FFH,0A6H,08H,'LDX '
	DEFB	0FFH,0A4H,08H,'LDY '
	DEFB	0FFH,046H,08H,'LSR '
	DEFB	0FFH,005H,08H,'ORA '
	DEFB	0FFH,026H,08H,'ROL '
	DEFB	0FFH,066H,08H,'ROR '
	DEFB	0FFH,0E5H,08H,'SBC '
	DEFB	0FFH,085H,08H,'STA '
	DEFB	0FFH,086H,08H,'STX '
	DEFB	0FFH,084H,08H,'STY '
	DEFB	0FFH,075H,04H,'ADC '
	DEFB	0FFH,07DH,0AH,'ADC '
	DEFB	0FFH,079H,0BH,'ADC '
	DEFB	0FFH,061H,05H,'ADC '
	DEFB	0FFH,071H,06H,'ADC '
	DEFB	0FFH,035H,04H,'AND '
	DEFB	0FFH,03DH,0AH,'AND '
	DEFB	0FFH,039H,0BH,'AND '
	DEFB	0FFH,021H,05H,'AND '
	DEFB	0FFH,031H,06H,'AND '
	DEFB	0FFH,0D5H,04H,'CMP '
	DEFB	0FFH,0DDH,0AH,'CMP '
	DEFB	0FFH,0D9H,0BH,'CMP '
	DEFB	0FFH,0C1H,05H,'CMP '
	DEFB	0FFH,0D1H,06H,'CMP '
	DEFB	0FFH,055H,04H,'EOR '
	DEFB	0FFH,05DH,0AH,'EOR '
	DEFB	0FFH,059H,0BH,'EOR '
	DEFB	0FFH,041H,05H,'EOR '
	DEFB	0FFH,051H,06H,'EOR '
	DEFB	0FFH,0B5H,04H,'LDA '
	DEFB	0FFH,0BDH,0AH,'LDA '
	DEFB	0FFH,0B9H,0BH,'LDA '
	DEFB	0FFH,0A1H,05H,'LDA '
	DEFB	0FFH,0B1H,06H,'LDA '
	DEFB	0FFH,015H,04H,'ORA '
	DEFB	0FFH,01DH,0AH,'ORA '
	DEFB	0FFH,019H,0BH,'ORA '
	DEFB	0FFH,001H,05H,'ORA '
	DEFB	0FFH,011H,06H,'ORA '
	DEFB	0FFH,0F5H,04H,'SBC '
	DEFB	0FFH,0FDH,0AH,'SBC '
	DEFB	0FFH,0F9H,0BH,'SBC '
	DEFB	0FFH,0E1H,05H,'SBC '
	DEFB	0FFH,0F1H,06H,'SBC '
	DEFB	0FFH,095H,04H,'STA '
	DEFB	0FFH,09DH,0AH,'STA '
	DEFB	0FFH,099H,0BH,'STA '
	DEFB	0FFH,081H,05H,'STA '
	DEFB	0FFH,091H,06H,'STA '
	DEFB	0FFH,016H,04H,'ASL '
	DEFB	0FFH,01EH,0AH,'ASL '
	DEFB	0FFH,0D6H,04H,'DEC '
	DEFB	0FFH,0DEH,0AH,'DEC '
	DEFB	0FFH,0F6H,04H,'INC '
	DEFB	0FFH,0FEH,0AH,'INC '
	DEFB	0FFH,0B6H,04H,'LDX '
	DEFB	0FFH,0BEH,0AH,'LDX '
	DEFB	0FFH,0B4H,04H,'LDY '
	DEFB	0FFH,0BCH,0AH,'LDY '
	DEFB	0FFH,056H,04H,'LSR '
	DEFB	0FFH,05EH,0AH,'LSR '
	DEFB	0FFH,036H,04H,'ROL '
	DEFB	0FFH,03EH,0AH,'ROL '
	DEFB	0FFH,076H,04H,'ROR '
	DEFB	0FFH,07EH,0AH,'ROR '
	DEFB	0FFH,096H,07H,'STX '
	DEFB	0FFH,094H,04H,'STY '
	DEFB	0FFH,06CH,0CH,'JMP '
	DEFB	080H,000H,01H,0,0
	DEFB	080H,080H,01H,0,0
;
;  END OF OPCODE TABLE
;
KSTG
	RET	
;
;  PRINT HEADERS
;
START:
	LD	SP,OLDST	;SET STACK
	CALL	PSTRNG
	DEFB	0DH,0AH,'DASM, Version '
	DEFB	VERS/10+'0','.',(VERS.MOD.10)+'0',0DH,0AH,0
;
;  PERFORM REENTRANT INITIALIZATION
;
	CALL	INIT0		;INITIALIZE BUFFERS SO DASM IS REENTRANT
	CALL	INIT		;CLEANUP INITIALIZATION
;
;  READ IN ALL FILES IF A FILE WAS SPECIFIED
;
	LD	A,(FCB+1)	;GET FIRST LETTER OF FILE NAME
	CP	' '+1		;VALID CHAR?
	JR	C,SIGNON	;SKIP READ IF NOT VALID CHAR
	CALL	PSTRNG
	DEFB	0DH,0AH,'Reading in All Files for ',0
	LD	HL,FCB+1	;PT TO FILE NAME
	LD	B,8		;8 CHARS
ARDNAME:
	LD	A,(HL)		;GET CHAR
	CALL	COUT		;PRINT IT
	INC	HL		;PT TO NEXT
	DJNZ	ARDNAME
	CALL	ALLRD		;READ IN ALL FILES
	CALL	PSTRNG
	DEFB	0DH,0AH,'-- Read Complete --',0DH,0AH,0
;
;  PRINT REST OF SIGNON MESSAGE
;
SIGNON:
	LD	DE,HEADER	;PRINT HEADER FROM INCLUDE FILE
	LD	C,9
	CALL	BDOS
	CALL	PSTRNG		;PRINT INITIAL INFO
	DEFB	0DH,0AH,'Type H for Help, ? for Stats',0DH,0AH,0
	JR	GETCMD		;PERFORM COMMAND PROCESSING
;
;  CLEAN UP DASM AND COMPLETELY REINITIALIZE
;
CLEAN:
	CALL	INIT		;DO INITIALIZATION
;
;  MAIN COMMAND PROCESSING LOOP
;
GETCMD:
	XOR	A		;A=0
	LD	(WRTENAB),A	;DISABLE OUTPUT TO FILE
	LD	(HUSH),A	;SET NOT QUIET
	LD	(XCPTR),A
	LD	(XCPTR+1),A
	LD	SP,OLDST	;RESET STACK
;
;  INPUT COMMAND LINE AND CAPITALIZE
;
	CALL	PROMPT		;INPUT COMMAND LINE VIA BDOS
;
;  PROCESS COMMAND LINE
;
PRCEDE:
	LD	A,(INBUF+2)	;PT TO FIRST CHAR OF COMMAND LINE
	LD	B,A		;GET IT
	LD	DE,CMDTABL	;PT TO COMMAND TABLE
PRCLOOP:
	LD	A,(DE)		;GET COMMAND FROM COMMAND TABLE
	OR	A		;END OF TABLE IF 0
	JR	Z,WHAT		;TELL USER THAT COMMAND WAS INVALID
	INC	DE		;PREP FOR NO MATCH
	INC	DE		;...PT TO NEXT COMMAND
	INC	DE
	CP	B		;MATCH?
	JR	NZ,PRCLOOP	;CONTINUE LOOPING IF NOT
	DEC	DE		;PT TO ADDRESS
	LD	A,(DE)		;GET ADR HIGH
	LD	B,A		;... IN B
	DEC	DE		;PT TO LOW
	LD	A,(DE)		;GET ADR LOW
	LD	C,A		;... IN C
	PUSH	BC		;ADDRESS ON STACK
	RET			;"JUMP TO" COMMAND
;
;  GENERAL ERROR
;
WHAT:
	XOR	A
	LD	(WRTENAB),A
	LD	(HUSH),A
	CALL	PSTRNG
	DEFB	0DH,0AH,'** Command Error **',0DH,0AH,0
	JR	GETCMD
;
;  COMMAND TABLE -- CONTAINS COMMAND LETTER FOLLOWED BY ADDRESS OF ROUTINE
;    AND ENDS IN 0 AS THE NEXT COMMAND LETTER
;
CMDTABL:
	DEFB	0DH	;EMPTY LINE
	DEFW	GETCMD
	DEFB	';'	;COMMENTS
	DEFW	CMNT
	DEFB	'A'	;BUILD ASCII
	DEFW	ASCASM
	DEFB	'B'	;BUILD LABELS
	DEFW	BLDASM
	DEFB	'C'	;CONTROL TABLE
	DEFW	CTL
	DEFB	'D'	;MEMORY DUMP
	DEFW	DUMP
	DEFB	'E'	;ENTER SYMBOL
	DEFW	ENTER
	DEFB	'F'	;FIND LABEL
	DEFW	FIND
	DEFB	'H'	;HELP
	DEFW	HELP
	DEFB	'I'	;INCREMENT SYMBOL VALUES
	DEFW	INCMNT
	DEFB	'K'	;KILL SYMBOL
	DEFW	KILL
	DEFB	'L'	;LIST CODE
	DEFW	LIST
	DEFB	'O'	;SET OFFSET
	DEFW	SETOS
	DEFB	'P'	;GENERATE PROLOG
	DEFW	PROLOG
	DEFB	'Q'	;QUIET MODE
	DEFW	QUIET
	DEFB	'R'	;READ FILES
	DEFW	READ
	DEFB	'S'	;SAVE FILES
	DEFW	SAVE
	DEFB	'U'	;SET COMMENTS
	DEFW	UAREA
	DEFB	'X'	;PURGE SYMBOLS AND CONTROL
	DEFW	PURGE
	DEFB	'Z'	;CLOSE ASM FILE
	DEFW	CLOSE
	DEFB	'?'	;STATISTICS DISPLAY
	DEFW	STAT
	DEFB	0	;END OF COMMAND TABLE
;
;COMMAND:  H
;  PRINT HELP INFORMATION
;
HELP:
	CALL	PSTRNG	;JUST ONE BIG PRINT
;LINE  1
	DEFB	0DH,0AH,'                    HELP on DASM -- Command Summary'
;LINE  2
	DEFB	0DH,0AH,';addr,comment  Enter Comment at addr   '
	DEFB	';addr          List comment at addr'
;LINE  3
	DEFB	0DH,0AH,';              List Comments Table     '
	DEFB	';addr,         Delete Comment'
;LINE  4
	DEFB	0DH,0AH,'A (see L)      Attempt to find DB''s   '
	DEFB	'B (see L)      Build Symbol Table'
;LINE  5
	DEFB	0DH,0AH,'C              Dump Control Table      '
	DEFB	'Cnnnn          Dump Ctrl Table at nnnn'
;LINE  6
	DEFB	0DH,0AH,'Cnnnn,x                Set Ctrl (x=BEHISW)     '
	DEFB	'Dnnnn          Dump from nnnn on'
;LINE  7
	DEFB	0DH,0AH,'Daaaa,bbbb     Dump over range         '
	DEFB	'D,bbbb         Dump thru bbbb'
;LINE  8
	DEFB	0DH,0AH,'D              Dump 80H more           '
	DEFB	'D=nn           Set Dump Size Default'
;LINE  9
	DEFB	0DH,0AH,'DS             Dump the Symbol Table   '
	DEFB	'DS.symbol      Dump starting at symbol'
;LINE 10
	DEFB	0DH,0AH,'Ennnn,.symbol  Enter symbol into table '
	DEFB	'Fnnnn,ssss     Find nnnn after ssss'
;LINE 11
	DEFB	0DH,0AH,'F or Fnnnn     Cont Find or Find nnnn  '
	DEFB	'Issss,oooo     Inc addrs>=ssss by oooo'
;LINE 12
	DEFB	0DH,0AH,'K.symbol       Kill symbol from table  '
	DEFB	'L              List next '
	DEFB	(INITLCNT/10)+'0',(INITLCNT.MOD.10)+'0'
	DEFB	' lines'
;LINE 13
	DEFB	0DH,0AH,'Lssss,eeee     List over range         '
	DEFB	'L,eeee         List to eeee'
;LINE 14
	DEFB	0DH,0AH,'Lssss          List '
	DEFB	(INITLCNT/10)+'0',(INITLCNT.MOD.10)+'0'
	DEFB	' lines from ssss       '
	DEFB	'L=nn[,others]  Set list default'
;LINE 15
	DEFB	0DH,0AH,'O              Print current offset    '
	DEFB	'Onnnn          Set new offset'
;LINE 16
	DEFB	0DH,0AH,'Pssss,eeee     Generate program prolog '
	DEFB	'Q              Quiet prefix'
;LINE 17
	DEFB	0DH,0AH,'Rfilename.COM  Read file @ offset+100H '
	DEFB	'Rfilename.CTL  Read Control Table'
;LINE 18
	DEFB	0DH,0AH,'Rfilename.SYM  Read Symbol Table       '
	DEFB	'Rfilename.DOC  Read Comments Table'
;LINE 19
	DEFB	0DH,0AH,'Rfilename.ALL  Read CTL, SYM, DOC, COM '
	DEFB	'Sfilename.ASM  Save ASM File'
;LINE 20
	DEFB	0DH,0AH,'Sfilename.CTL  Save CTL File           '
	DEFB	'Sfilename.SYM  Save SYM File'
;LINE 21
	DEFB	0DH,0AH,'Sfilename.DOC  Save DOC File           '
	DEFB	'Sfilename.ALL  CTL, SYM, DOC, ASM'
;LINE 22
	DEFB	0DH,0AH,'Unnnn          Set Comment Table addr  '
	DEFB	'X              Restart DASM'
;LINE 23
	DEFB	0DH,0AH,'Z              Write EOF to ASM File   '
	DEFB	'?              Print Statistics'
;LINE 24
	DEFB	0DH,0AH,0
	JP	GETCMD
;
;COMMAND:  X
;  PURGE ALL SYMBOLS AND CONTROL
;
PURGE:
	CALL	PSTRNG	;PROMPT USER
	DEFB	'Restart DASM (Y/N)? ',0
	CALL	CHIN	;GET SINGLE CHAR AND CAP
	CP	'Y'
	JP	NZ,GETCMD
	CALL	PSTRNG	;PRINT FUNCTION
	DEFB	'Restarting DASM',0DH,0AH,0
	JP	CLEAN	;RESTART DASM AT INIT
;
;  INPUT A SINGLE CHAR IN A VIA THE BDOS AND CAPITALIZE IT; FOLLOW WITH <CRLF>
;
CHIN:
	LD	C,1	;GET CHAR FROM CON:
	CALL	BDOS
	AND	5FH	;CAPITALIZE
	PUSH	AF
	CALL	CRLF
	POP	AF
	RET
;
;COMMAND:  P
;  ENTER PROLOG INTO ASSEMBLY LANGUAGE PROGRAM
;
PROLOG:
	LD	HL,INBUF+3	;PT TO STARTING ADDRESS
	LD	A,(HL)		;NO ADDRESS SPECIFIED?
	CP	0DH		;ERROR IF SO
	JP	Z,WHAT
	CALL	CNVRT		;CONVERT ADDRESS VALUE TO BINARY IN DE
	CP	' '		;CHAR AFTER ADDRESS = <SP>?
	JR	Z,PRLG0 	;CONT IF SO
	CP	','		;CHAR AFTER ADDRESS = ','?
	JP	NZ,WHAT 	;ERROR IF NOT ',' OR <SP>
PRLG0:
	INC	HL		;PT TO 2ND ADDRESS
	PUSH	DE		;SAVE FIRST ADDRESS ON STACK
	PUSH	HL		;SAVE PTR TO 2ND ADDRESS
	LD	A,1		;TURN ON DISK OUTPUT
	LD	(WRTENAB),A
	CALL	PSTG		;PRINT NEW ORG
	DEFB	9,'ORG',9,0
	POP	HL
	POP	DE
	LD	A,D		;ORG AT FIRST ADDRESS
	CALL	PASHEX		;PRINT AS 'nnH'
	LD	A,E
	CALL	PHEX
	LD	A,'H'
	CALL	COUT
	CALL	CRLF
	PUSH	DE		;SAVE FIRST ADDRESS
	CALL	CNVRT		;GET 2ND ADDRESS IN DE
	CP	0DH		;ERROR IF <CR>
	JP	NZ,WHAT
	POP	BC		;BC=START ADDRESS, DE=END ADDRESS
	LD	HL,SYMTAB	;PT TO SYMBOL TABLE
PRLG1:
	INC	HL		;SKIP OVER SYMBOL ADDRESS
	INC	HL
	LD	A,(HL)		;GET 1ST CHAR OF SYMBOL
	OR	A		;END OF SYMBOL TABLE? (CHAR COUNT = 0)
	JP	Z,GETCMD	;DONE IF SO
	DEC	HL		;PT TO SYMBOL ADDRESS
	DEC	HL
	LD	A,(HL)		;COMPARE SYMBOL ADDRESS TO CURRENT ADDRESS
	SUB	C		;... IN BC
	INC	HL
	LD	A,(HL)
	SBC	A,B
	JR	C,GENEQU	;GENERATE EQU IF SYMBOL < START ADDRESS
	DEC	HL		;PT TO SYMBOL LOW-ORDER ADDRESS AGAIN
	LD	A,(HL)		;COMPARE SYMBOL ADDRESS TO END ADDRESS
	SUB	E
	INC	HL
	LD	A,(HL)
	SBC	A,D
	JP	C,WITHIN	;PROCESS NORMALLY IF START <= SYMBOL <= END
;
;  SYMBOL IS NOT IN RANGE OF:
;    START ADDRESS <= SYMBOL <= END ADDRESS
;  GENERATE EQUATE FOR IT
;
GENEQU:
	PUSH	HL	;SAVE PTR TO SYMBOL
	PUSH	BC	;SAVE START ADDRESS
	INC	HL	;PT TO SYMBOL CHAR COUNT
	LD	B,(HL)	;B=CHAR COUNT
	PUSH	HL	;SAVE PTR TO CHAR COUNT
	INC	HL	;PT TO FIRST LETTER OF SYMBOL
	LD	A,(HL)	;GET IT
	DEC	HL	;PT BACK TO CHAR COUNT
	CP	'A'	;IF FIRST LETTER IS LESS THAN A, DON'T GENERATE 'EQU'
	JR	C,PRLG3
;
;  SCAN SYMBOL FOR '+' OR '-' AND DON'T GENERATE 'EQU' IF IT CONTAINS ONE
;
PRLG2:
	INC	HL	;PT TO NEXT CHAR
	LD	A,(HL)	;GET IT
	CP	'+'	;CHECK
	JR	Z,PRLG3
	CP	'-'	;CHECK
	JR	Z,PRLG3
	DJNZ	PRLG2	;LOOP
	POP	HL	;GET PTR TO SYMBOL CHAR COUNT
	LD	B,(HL)	;B=CHAR COUNT
	LD	A,1	;ENABLE DISK OUTPUT
	LD	(WRTENAB),A
;
;  PRINT SYMBOL EQUATE; HL PTS TO BYTE BEFORE SYMBOL AND B=NUMBER OF CHARS
;
LOOPB:
	INC	HL	;PT TO NEXT CHAR
	LD	A,(HL)	;GET IT
	CALL	COUT	;PRINT IT
	DJNZ	LOOPB	;LOOP FOR NUMBER OF CHARS IN B
	CALL	PSTG
	DB	9,'EQU',9,0
	POP	BC	;GET START ADR
	POP	HL	;PT TO CHAR COUNT OF CURRENT SYMBOL
	LD	A,(HL)	;CHECK FOR HIGH-ORDER VALUE
	OR	A	;DON'T PRINT SIGNIFICANT ZERO
	CALL	NZ,PASHEX
	DEC	HL	;PT TO LOW-ORDER VALUE
	LD	A,(HL)	;GET IT
	CALL	PHEX	;PRINT IT
	LD	A,'H'	;FOLLOWING 'H' FOR 'nnH' AND NEW LINE
	CALL	COUT
	CALL	CRLF
	XOR	A	;DISABLE WRITE TO DISK
	LD	(WRTENAB),A
	INC	HL	;PT TO HIGH-ORDER VALUE OF SYMBOL
;
;  SYMBOL IS WITHIN THE DESIRED RANGE (START <= SYMBOL <= END)
;
WITHIN:
	INC	HL	;PT TO CHAR COUNT OF SYMBOL
	LD	A,(HL)	;GET IT
	CALL	SKIP	;SKIP TO NEXT SYMBOL
	INC	HL	;PT TO ITS ADDRESS
	CALL	BRKCHK	;CHECK FOR BREAK
	JP	PRLG1	;CONTINUE GENERATING PROLOG
;
;  SKIP CURRENT SYMBOL FOR ONE REASON OR ANOTHER
;
PRLG3:
	POP	HL	;RESTORE REGS AND CONTINUE
	POP	BC
	POP	HL
	JR	WITHIN
;
;COMMAND:  Q PREFIX
;  EXECUTE THE COMMAND IN THE QUIET MODE
;
QUIET:
	LD	A,1		;TURN ON QUIET MODE
	LD	(HUSH),A
	LD	DE,INBUF+2	;COPY COMMAND LINE LEFT 1 CHARACTER
	LD	HL,INBUF+3
SHFTBF:
	LD	A,(HL)		;COPY IN ORDER TO CONTINUE PROCESSING
	LD	(DE),A		;... NORMALLY
	INC	HL
	INC	DE
	CP	0DH
	JR	NZ,SHFTBF
	JP	PRCEDE		;RETURN TO MAIN COMMAND PROCESSOR
;
;COMMAND:  D
;  DUMP THE MEMORY, SYMBOL TABLE, OR SET THE DEFAULT DUMP LENGTH
;
DUMP:
	LD	HL,(DMPSTRT)	;GET PTR TO STARTING ADR FOR DUMP
	PUSH	HL
	EX	DE,HL		;... IN DE
	LD	HL,(DMPLEN)	;GET DEFAULT LENGTH OF DUMP
	ADD	HL,DE		;CALCULATE END ADDRESS OF DUMP
	LD	(DMPEND),HL	;SAVE IT
	POP	DE
	LD	HL,INBUF+3	;LOOK AT COMMAND LINE
	LD	A,(HL)		;GET CHAR AFTER THE 'D'
	CP	0DH		;IF <CR>, THEN DUMP FROM DMPSTRT TO DMPEND
	JP	Z,DMPHDR
	CP	'S'		;IF S, THEN DUMP THE SYMBOL TABLE
	JP	Z,DMPSYM
	CP	'='		;IF =, THEN SET THE DEFAULT DUMP LENGTH
	JP	Z,DUMP5
	CP	','		;IF ',', THEN DUMP FROM CURRENT TO END SPEC
	JP	Z,DUMP1
;
;  NUMBER SHOULD FOLLOW THE D -- PROCESS IT
;
DUMP0:
	CALL	CNVRT		;GET VALUE
	PUSH	HL		;SAVE IT
	LD	HL,(DMPLEN)	;GET DEFAULT LENGTH
	ADD	HL,DE		;COMPUTE END OF DUMP
	LD	(DMPEND),HL	;SAVE IT
	POP	HL		;GET START ADDRESS OF DUMP
;
;  CHECK FOR DELIMITER AFTER FIRST NUMBER
;
DUMP1:
	CP	0DH		;IF <CR>, DUMP FOR THE DEFAULT LENGTH
	JR	Z,DUMP3
	CP	' '		;IF <SP>, GET 2ND NUMBER
	JR	Z,DUMP2
	CP	','		;IF ',', GET 2ND NUMBER
	JP	NZ,WHAT 	;ERROR IF NOT
;
;  EXTRACT 2ND NUMBER FROM DUMP COMMAND
;
DUMP2:
	INC	HL		;PT TO NUMBER
	PUSH	DE
	CALL	CNVRT		;RETURN IT IN DE
	EX	DE,HL
	LD	(DMPEND),HL	;SET END ADDRESS OF DUMP
	POP	DE		;GET START ADDRESS OF DUMP IN DE
;
;  ADD OFFSET TO BEGINNING AND ENDING DUMP ADDRESSES
;    ON INPUT, DE=START OF DUMP ADDRESS
;
DUMP3:
	LD	HL,(OFFSET)	;GET OFFSET
	PUSH	HL		;SAVE IT
	ADD	HL,DE		;ADD TO BEGINNING DUMP ADDRESS
	LD	(DMPSTRT),HL	;SET PTR
	LD	HL,(DMPEND)	;GET END ADDRESS OF DUMP
	POP	DE		;GET OFFSET IN DE
	ADD	HL,DE		;ADD OFFSET TO END ADDRESS OF DUMP
	LD	(DMPEND),HL	;NEW END ADDRESS OF DUMP
	CP	0DH		;MAKE SURE <CR> AFTER DUMP COMMAND
	JP	NZ,WHAT 	;ERROR IF NOT
;
;  PRINT HEADER FOR DUMP AND THEN PERFORM DUMP
;
DMPHDR:
	CALL	PSTRNG		;PRINT A HEADER FOR THE DUMP
	DEFB	'Addr  +0   +2    +4   +6     +8   +A    +C   +E      ASCII'
	DEFB	0DH,0AH,0
;
;  MAIN DUMP LOOP
;
CNTDMP:
	LD	HL,(DMPSTRT)	;GET START ADDRESS OF DUMP
DUMP4:
	CALL	BRKCHK		;CHECK FOR BREAK
	PUSH	HL		;SAVE PTR TO NEXT BYTE
	CALL	TWOS		;MAKE HL CONTAIN RELATIVE VALUE
	CALL	PVALUE		;... BY SUBTRACTING OFFSET; THEN PRINT IT
	POP	HL		;GET PTR
	PUSH	HL		;SAVE PTR
	CALL	SPACE		;PRINT A SPACE
;
;  DUMP AS HEX
;
DMPLN:
	LD	A,(HL)		;GET BYTE
	CALL	PHEX		;PRINT AS HEX
	INC	HL		;PT TO NEXT
	LD	A,L		;PRINT ONE SPACE FOR EVERY 2 VALUES
	AND	1
	CALL	Z,SPACE
	LD	A,L		;PRINT TWO SPACES EVERY 4
	AND	3
	CALL	Z,SPACE
	LD	A,L		;PRINT THREE SPACES EVERY 8
	AND	7
	CALL	Z,SPACE
	LD	A,L		;CHECK FOR END OF DUMP LINE (EVERY 16)
	AND	0FH
	JR	NZ,DMPLN
	LD	A,'!'		;PRINT BEGINNING '!'
	CALL	COUT
	POP	HL		;GET PTR TO FIRST BYTE
;
;  DUMP AS ASCII
;
DMPASC:
	LD	A,(HL)		;GET CHAR
	CP	' '		;PRINT . IF LESS THAN <SP>
	JR	C,PERIOD
	CP	7FH		;PRINT . IF GREATER THAN <DEL>
	JR	C,CHRCTR
;
;  PRINT '.'
;
PERIOD:
	LD	A,'.'
;
;  PRINT CHAR IN A AND ADVANCE FOR UP TO 16 CHARS
;
CHRCTR:
	CALL	COUT	;PRINT CHAR
	INC	HL	;PT TO NEXT
	LD	A,L	;END OF LINE?
	AND	0FH	;EVERY 16
	JR	Z,LCMPLT	;DONE IF SO
	AND	7	;EXTRA SPACE FOR EVERY 8
	CALL	Z,SPACE
	JR	DMPASC	;CONTINUE ASCII DUMP
;
;  TIDY UP THE LINE
;
LCMPLT:
	LD	A,'!'	;PRINT ENDING '!'
	CALL	COUT
	CALL	CRLF	;NEW LINE
	LD	(DMPSTRT),HL	;COMPARE CURRENT START ADDRESS TO END ADDRESS
	LD	A,(DMPEND)
	SUB	L
	LD	A,(DMPEND+1)
	SBC	A,H
	JR	NC,DUMP4	;CONTINUE IF CURRENT START <= END
	JP	GETCMD		;RETURN TO COMMAND PROCESSING OTHERWISE
;
;  SET THE DEFAULT NUMBER OF BYTES TO DUMP
;
DUMP5:
	INC	HL	;PT TO VALUE
	CALL	CNVRT	;RETURN VALUE IN DE
	INC	HL
	DEC	DE
	EX	DE,HL
	LD	(DMPLEN),HL	;SAVE VALUE
	EX	DE,HL
	CP	','
	JP	Z,DUMP0
	CP	' '
	JP	Z,DUMP0
	CP	0DH
	JP	Z,GETCMD
	JP	WHAT
;
;  DS -- DUMP THE SYMBOL TABLE
;
DMPSYM:
	CALL	IECNT		;INIT ECNT
	LD	HL,INBUF+4	;PT TO CHAR AFTER 'DS'
	LD	A,(HL)		;GET IT
	CP	'.'		;SYMBOL SPECIFIED?
	JR	NZ,FRMBGN	;NO, SO DUMP FROM BEGINNING OF TABLE
	CALL	LNGTH		;COMPUTE LENGTH OF GIVEN SYMBOL
	CALL	PLCSYM		;RETURN PTR TO THIS SYMBOL IN HL
	JR	NC,FRMSYM	;PROCESS NORMALLY IF FOUND
	LD	HL,(SYMRKR)
	JR	FRMSYM
FRMBGN:
	LD	HL,SYMTAB	;PT TO TABLE
FRMSYM:
	LD	E,(HL)		;GET ADDRESS OF SYMBOL IN DE
	INC	HL
	LD	D,(HL)
	INC	HL
	LD	A,(HL)		;GET LENGTH OF SYMBOL IN A
	OR	A		;DONE IF LENGTH = 0
	JP	Z,SPITCR
	EX	DE,HL		;PRINT VALUE OF SYMBOL
	CALL	PVALUE
	EX	DE,HL
	LD	A,'='	;PRINT =
	CALL	COUT
	LD	B,(HL)		;GET LENGTH OF SYMBOL IN B
	LD	A,SYMMAX+1	;COMPUTE DIFF FROM MAX
	SUB	B
	LD	C,A		;DIFFERENCE IN C (NUMBER OF SPACES AFTER SYM)
	INC	HL
;
;  PRINT THE SYMBOL PTED TO BY HL; B=NUMBER OF BYTES LONG THE SYMBOL IS
;
SPIT:
	LD	A,(HL)		;GET SYMBOL CHAR
	CALL	COUT		;PRINT IT
	INC	HL		;PT TO NEXT
	DJNZ	SPIT		;UNTIL DONE
;
;  PRINT TRAILING SPACES AFTER SYMBOL
;
	LD	B,C	;SP COUNT IN B
SPIT1:
	CALL	SPACE
	DJNZ	SPIT1
	CALL	SPCRLF	;NEW LINE
	CALL	BRKCHK	;CHECK FOR BREAK
	JR	FRMSYM	;CONTINUE
;
;  PRINT <CRLF> AND EXIT
;
SPITCR:
	CALL	CRLF	;NEW LINE
	JP	GETCMD
;
;  COUNT DOWN ECNT AND OUTPUT <CRLF> ON ZERO
;
SPCRLF:
	LD	A,(ECNT)	;GET COUNT
	DEC	A
	LD	(ECNT),A
	RET	NZ
	CALL	CRLF	;NEW LINE
;
;  INIT ECNT
;
IECNT:
	LD	A,4	;SET 4 ENTRIES
	LD	(ECNT),A
	RET
;
;   PRINT THE VALUE OF THE OFFSET.
;
PRNTOS:
	CALL	PSTRNG
	DB	'Offset = ',0
	LD	HL,(OFFSET)	;GET IT AND PRINT IT
	CALL	PVALUE
	CALL	CRLF		;NEW LINE
	JP	GETCMD
;
;COMMAND:  O
;  SET OR PRINT OFFSET ADDRESS
;
SETOS:
	LD	HL,INBUF+3	;FORMAT: O C/R
	LD	A,(HL)		;.. OR	 OXXXX C/R
	CP	0DH		;IF JUST O, DO IT VIA PRNTOS
	JR	Z,PRNTOS
	CALL	CNVRT		;GET VALUE IN DE
	CP	0DH		;ERROR?
	JP	NZ,WHAT
	EX	DE,HL		;SAVE AS OFFSET
	LD	(OFFSET),HL
	CALL	CRLF		;NEW LINE AND PRINT NEW VALUE
	JR	PRNTOS
;
;  SET UP THE FILE CONTROL BLOCK.
;
SETFCB:
	LD	A,(FOPEN)	;FILE OPEN?
	OR	A		;0 IF NOT
	JP	NZ,CANT
	LD	(FCB),A 	;SET DEFAULT DRIVE
	LD	(FCB+12),A	;SET EXTENT NUMBER TO ZERO
	LD	HL,INBUF+3	;PT TO FIRST LETTER OF POSSIBLE FILE NAME
	LD	A,(INBUF+4)	;GET SECOND LETTER
	CP	' '		;ERROR IF JUST <SP>
	JP	Z,WHAT
	CP	':'		;GET AND SET DRIVE IF ':'
	JR	NZ,SMDRV
	LD	A,(HL)		;GET SPECIFIED DRIVE
	SUB	'@'		;CONVERT IT TO BINARY
	LD	(FCB),A 	;SET DRIVE NUMBER IN FCB
	INC	HL
	INC	HL
;
;  WRITE FILE NAME AND TYPE INTO FCB
;
SMDRV:
	LD	DE,FCB+1	;PT TO FILE NAME FIELD OF FCB
	LD	B,8
	CALL	SLIDE		;PUT FILE NAME
	LD	B,3
	CALL	SLIDE		;PUT FILE TYPE
	RET	
;
;  WRITE CHARS PTED TO BY HL INTO BUFFER PTED TO BY DE; WRITE AT MOST B
;    CHARS, AND <SP> FILL THE BUFFER PTED TO BY DE
;
SLIDE:
	LD	A,(HL)	;GET NEXT CHAR
	CP	0DH	;DONE?
	JR	Z,BLANK ;BLANK FILL IF SO
	INC	HL	;PT TO NEXT
	CP	'.'	;FILE TYPE FOLLOWS?
	JR	Z,BLANK ;BLANK FILL IF SO
	LD	(DE),A	;PUT CHAR
	INC	DE	;PT TO NEXT
	DJNZ	SLIDE	;COUNT DOWN
;
;  CHECK FOR ERROR IF AFTER 8 CHARACTERS IN THE FILENAME
;
AFTR8:
	LD	A,(HL)	;GET NEXT CHAR
	CP	0DH	;OK IF <CR>
	RET	Z
	CP	'.'	;OK IF '.'
	INC	HL	;PT TO NEXT AFTER '.'
	RET	Z
	JR	AFTR8
;
;  BLANK FILL FOR THE REMAINDER OF THE NAME
;
BLANK:
	LD	A,' '	;GET <SP>
	LD	(DE),A	;PUT IT
	INC	DE	;PT TO NEXT
	DJNZ	BLANK	;COUNT DOWN
	RET	
;
;COMMAND:  A
;  BUILD ASCII STRINGS USING DB'S
;
ASCASM:
	LD	A,1	;SET FLAG
	LD	(ASCBLD),A
	XOR	A	;TURN OFF BUILD BY B COMMAND
	LD	(BUILD),A
	JR	LIST1	;PERFORM LIST
;
;COMMAND:  B
;  BUILD LABELS
;
BLDASM:
	LD	A,1	;TURN ON BUILD BY B COMMAND
	LD	(BUILD),A
	XOR	A	;TURN OFF BUILD BY A COMMAND
	LD	(ASCBLD),A
	JR	LIST1
;
;COMMAND:  L
;  DISASSEMBLE WITH THE 'L' OPTION
;
LIST:
	XOR	A	;TURN OFF A AND B FLAGS
	LD	(BUILD),A
	LD	(ASCBLD),A
LIST1:
	XOR	A	;DISABLE OUTPUT TO DISK
	LD	(WRTENAB),A
	LD	A,(NLINES)	;SET LINE COUNT
	LD	(LCTR),A
	LD	(CNTENAB),A	;ENABLE LINE COUNT
	LD	HL,INBUF+3	;PT TO CHAR AFTER L, A, OR B COMMAND
	LD	A,(HL)		;GET IT
	CP	0DH		;DO DEFAULT NUMBER IF EOL
	JR	Z,TENL
	CP	','		;USE CURRENT POSITION FOR FIRST ARG IF ','
	JR	Z,LIST3
	CP	' '		;SAME AS ','
	JR	Z,LIST3
	CP	'='		;SET DEFAULT NUMBER OF LINES IF '='
	JR	NZ,LIST2
;
;  SET DEFAULT NUMBER OF LINES FOR LIST
;
NWLNCT:
	INC	HL	;PT TO ARG
	CALL	CNVRT	;GET IT IN DE
	LD	A,E	;ERROR IF ZERO
	OR	A
	JP	Z,WHAT
	LD	(NLINES),A	;SET COUNTS
	LD	(LCTR),A
	LD	A,(HL)	;GET NEXT CHAR
	INC	HL
	CP	','	;CONTINUE IF COMMA OR SPACE
	JR	Z,LIST2
	CP	' '
	JR	Z,LIST2
	CP	0DH	;DONE IF <CR>
	JP	Z,GETCMD
	JP	WHAT	;ERROR OTHERWISE
;
;  GET FIRST ARG FOR L, A, OR B FROM COMMAND LINE
;
LIST2:
	CALL	CNVRT	;GET VALUE IN DE
	EX	DE,HL
	LD	(PC),HL ;SET PC TO IT
	EX	DE,HL
	CP	0DH	;DONE?
	JR	Z,TENL	;DO DEFAULT NUMBER IF SO
	CP	' '	;GET 2ND ARG IF <SP>
	JR	Z,LIST3
	CP	','	;SAME IF ','
	JP	NZ,WHAT ;ERROR OTHERWISE
;
;  GET 2ND ARG FOR L, A, OR B COMMAND
;
LIST3:
	INC	HL	;PT TO FIRST CHAR OF 2ND ARG
	CALL	CNVRT	;GET ITS VALUE IN DE
	EX	DE,HL
	LD	(ENDLST),HL	;SET END OF LISTING TO IT
	XOR	A	;TURN OFF LINE COUNTING
	LD	(CNTENAB),A
;
;  MAIN PROCESSING LOOP FOR L, A, AND B COMMANDS
;
TENL:
	CALL	BRKCHK	;CHECK FOR BREAK
	LD	A,(CNTENAB)	;CHECK FOR LINE COUNTING IN PROGRESS
	OR	A	;0 = NO
	JR	Z,CONTL ;CONTINUE IF NOT
	LD	A,(LCTR)	;GET COUNT
	DEC	A	;COUNT DOWN
	JP	M,GETCMD	;RETURN TO COMMAND PROCESSING IF DONE
	JR	FLAGA
;
;  COMPARE ENDLST WITH PC
;
CONTL:
	LD	HL,(ENDLST)	;DONE WITH DISPLAY?
	LD	A,(PC)
	SUB	L
	LD	A,(PC+1)
	SBC	A,H
	JP	NC,GETCMD
;
;  CHECK FOR A OR B COMMANDS
;
FLAGA:
	LD	A,(ASCBLD)	;A COMMAND IF ASCBLD NOT ZERO
	OR	A
	JR	Z,MOREL
;
;  THIS IS THE MAJOR FUNCTION TO BUILD ASCII DB'S
;
BUILDA:
	LD	HL,(PC) ;HL PTS TO NEXT BYTE (RELATIVE)
	EX	DE,HL	;PTR IN DE
	LD	HL,(OFFSET)	;HL CONTAINS OFFSET
	ADD	HL,DE	;HL PTS TO NEXT BYTE ABSOLUTE
	LD	B,8	;LOOK FOR 8 ASCII CHARS IN A ROW
LOOP8:
	LD	A,(HL)	;CHECK FOR ASCII CHAR
	CALL	ISITASC ;IS IT ASCII?
	JR	C,MOREL ;NO, SKIP TO NEXT BYTE
	INC	HL	;YES, PT TO NEXT
	DJNZ	LOOP8
;
;  FIND END OF THIS ASCII STRING
;
FOLLOW:
	LD	A,(HL)	;LOOK UNTIL NON-ASCII
	INC	HL	;PT TO NEXT
	CALL	ISITASC
	JR	NC,FOLLOW
	DEC	HL	;PT TO NON-ASCII CHAR
	CALL	TWOS	;SUBTRACT OFFSET FROM LOCATION
	EX	DE,HL	;RESULT IN DE
	PUSH	DE	;SAVE PTR TO BYTE AFTER DB STRING FOR 'I' CONTROL
	LD	HL,(PC) ;GET VALUE OF BEGINNING OF ASCII STRING
	EX	DE,HL	;... IN DE
	LD	A,'B'	;SET B CONTROL POINT
	CALL	FTCTL0	;A='B', DE=ADDRESS
	POP	HL
	LD	(PC),HL ;SET NEW ADDRESS TO CONTINUE FROM
	EX	DE,HL
	LD	A,'I'	;A='I', DE=ADDRESS FOR INSTR CONTROL
	CALL	FTCTL0
;
;  NOW LOOK FOR ANY COMMENTS AT THIS ADDRESS
;
MOREL:
	LD	HL,(COMST)	;COMMENT TABLE IN USE?
	LD	A,H	;ADDRESS IS ZERO IF NOT
	OR	L
	JR	Z,NCMT
	LD	HL,(PC) ;HL PTS TO PC
	EX	DE,HL	;DE PTS TO PC
	CALL	CMCHK	;CHECK COMMENT TABLE FOR MATCH
	JR	C,NCMT	;NO MATCH
	INC	HL	;PT TO CHAR COUNT OF COMMENT
	INC	HL
	LD	B,(HL)	;B=NUMBER OF CHARS IN COMMENT
	INC	HL	;PT TO FIRST CHARACTER
	LD	A,(HL)	;A=FIRST CHAR OF COMMENT
	CP	';'	;A ';' COMMENT IS LISTED AFTER THE OPCODE
	DEC	HL	;PT BACK TO CHAR COUNT
	JR	NZ,MOREL1	;CONTINUE IF NO ';'
	LD	(XCPTR),HL	;SAVE THE COMMENT ADDRESS
	JR	NCMT
;
;  THIS ROUTINE WILL
;  PRINT COMMENTS
;  LIKE THIS
;
NWLN:
	SCF	
NWLN0:
	LD	A,1	;ENABLE WRITING
	LD	(WRTENAB),A
	CALL	C,SEMI	;OUTPUT SEMI BEFORE NEW COMMENT
	XOR	A
	OR	B	;CHECK CHAR COUNT FOR DONE
	RET	Z	;DONE IF ZERO CHARS LEFT
CNTCMT:
	INC	HL	;PT TO NEXT CHAR
	LD	A,(HL)	;GET IT
	CP	'\'	;NEW LINE?
	JR	NZ,NTBKSL
	CALL	CRLF	;NEW LINE
	DEC	B	;DEC CHAR COUNT
	JR	NWLN	;CONT
NTBKSL:
	CALL	COUT	;PRINT CHAR
	DEC	B	;DECREMENT COUNT
	JR	NZ,CNTCMT
	RET	
MOREL1:
	CP	'*'		; A '*' COMMENT REPLACES THE ENTIRE LINE
	JR	NZ,MOREL2
	LD	(RPLPTR),HL
	JR	NCMT
;
;  PRINT COMMENT PTED TO BY HL AND THEN NEW LINE
;
MOREL2:
	CALL	NWLN	;PRINT COMMENT
	CALL	CRLF
;
;  NOW PROCESS THE BYTE AS AN INSTRUCTION IF IT IS
;
NCMT:
	LD	HL,(PC) ;PT TO PC
	EX	DE,HL	;... IN DE
	CALL	SCHCTL	;CHECK CONTROL TABLE
	DEC	HL	;PT TO CONTROL MODE OF PREVIOUS ENTRY
	JR	C,RDCTL ;IF NO MATCH, CONTROL MODE OF PREVIOUS ENTRY IS IT
	INC	HL	;SINCE MATCH, PT TO CONTROL MODE OF MATCHED ENTRY
	INC	HL
	INC	HL
;
;  CHECK CONTROL MODE
;
RDCTL:
	LD	A,(HL)	;GET CONTROL MODE
	CP	'I'	;IS IT INSTRUCTION?
	JR	Z,ICTL	;PROCESS IF SO
	CP	'E'	;END OF PROGRAM?
	JP	Z,CLOSE ;DONE IF SO
	PUSH	AF	;ELSE SAVE CONTROL MODE
	INC	HL	;PT TO ADDRESS OF NEXT CONTROL MODE
	LD	E,(HL)	;ADDRESS IN DE
	INC	HL
	LD	D,(HL)
	PUSH	DE	;SAVE ADDRESS OF NEXT CONTROL ENTRY
	LD	HL,(PC) ;PT TO PC
	EX	DE,HL	;... IN DE
	CALL	HSYM	;PRINT SYMBOL IF THERE
	POP	HL	;HL IS ADDRESS OF NEXT CONTROL ENTRY
	LD	(NXTCTL),HL	;SAVE IT
	EX	DE,HL	;... IN DE ALSO
	XOR	A	;DISABLE WRITE
	LD	(WRTENAB),A
	POP	AF	;GET CONTROL MODE
	CP	'S'	;DS?
	JP	Z,DSMODE
	CP	'B'	;DB?
	JP	Z,BMODE
	CP	'H'	;DB HEX?
	JP	Z,HMODE
	CP	'W'	;DW?
	JP	Z,WMODE
	CALL	COUT	;ELSE PRINT AS ERROR
	CALL	PSTRNG
	DEFB	': Invalid CTL Entry',0DH,0AH,0
	JP	GETCMD
;
;  EXECUTE HERE IF THE 'I' CTL IS IN EFFECT -- INTERPRET AS INSTRUCTION
;    DE PTS TO BYTE WHICH IS BEING PROCESSED
;
ICTL:
	CALL	DASM	;INVOKE DISASSEMBLER
	XOR	A	;DISABLE WRITE
	LD	(WRTENAB),A
	JP	TENL
;
;  DS CTL -- DE CONTAIN NEXT CTL ADDRESS
;
DSMODE:
	PUSH	DE	;SAVE NEXT CONTROL
	LD	A,(PC)	;COMPUTE -PC IN HL
	CPL	
	LD	L,A
	LD	A,(PC+1)
	CPL	
	LD	H,A
	INC	HL
	ADD	HL,DE	;HL = LENGTH OF SPACE DEFINED
	LD	A,1	;ENABLE WRITING
	LD	(WRTENAB),A
	CALL	PSTG	;PRINT 'DS'
	DEFB	'DS',9,0
	LD	A,H	;PRINT SIZE OF AREA
	CALL	PASHEX
	LD	A,L
	CALL	PHEX
	LD	A,'H'
	CALL	COUT
	CALL	CRLF
	POP	HL	;GET PTR TO NEXT CONTROL ENTRY
	LD	(PC),HL ;SET PC TO IT
	JP	TENL	;CONTINUE
;
;  DW CTL -- PROCESS DW AND LOOK FOR LABELS
;
WMODE:
	LD	A,1	;ENABLE WRITING
	LD	(WRTENAB),A
	CALL	PSTG	;PRINT 'DW'
	DEFB	'DW',9,0
	LD	HL,(PC) ;GET PC
	EX	DE,HL	;... IN DE
	LD	HL,(OFFSET)	;GET OFFSET
	ADD	HL,DE	;HL PTS TO ACTUAL BYTE PAIR
	LD	E,(HL)	;SET DE TO DW VALUE
	INC	HL
	LD	D,(HL)
	CALL	PRNTDE	;PRINT DW VALUE
	CALL	CRLF
	LD	HL,(PC) ;ADVANCE PC TO BYTE AFTER DW VALUE
	INC	HL
	INC	HL
	LD	(PC),HL
	JP	TENL	;CONTINUE PROCESSING
;
;  NEW LINE AND CONTINUE
;
STPLN:
	CALL	CRLF
	JP	TENL
;
;  DB HEX MODE -- BUILD HEX DB'S
;
HMODE:
	XOR	A	;SET FLAG
	LD	(ADB),A
	JR	BMODE1
;
;  DB MODE -- BUILD ASCII STRINGS LONGER THAN 8 CHARACTERS
;
BMODE:
	LD	A,0FFH	;SET FLAG FOR ASCII
	LD	(ADB),A
BMODE1:
	XOR	A	;INIT LENGTH TO ZERO
	LD	(BLNGTH),A
	INC	A	;ENABLE WRITING
	LD	(WRTENAB),A
	CALL	PSTG	;PRINT 'DB'
	DEFB	'DB',9,0
;
;  PROCESS BYTES OF DB
;
MOREB:
	LD	HL,(PC) ;GET RELATIVE ADDRESS
	EX	DE,HL	;... IN DE
	LD	HL,(OFFSET)	;GET OFFSET
	ADD	HL,DE	;PT TO ACTUAL BYTE
	LD	A,(ADB) ;CHECK FOR ASCII BUILD
	OR	A	;0=NO
	LD	A,(HL)	;GET BYTE OF DB
	JR	Z,LTSPC ;XXH BUILD
	CP	0AH	;<LF>?
	JR	C,LTLF	;PROCESS IF LESS THAN
	CP	' '	;<SP>
	JR	C,LTSPC ;PROCESS IF LESS THAN <SP>
	CP	7FH	;<DEL>?
	JP	C,LTRUB ;PROCESS IF GREATER THAN
;
;  PRINT BYTE AS HEX NUMBER
;
LTSPC:
	CALL	PASHEX	;PRINT BYTE IN A AS HEX
	LD	A,'H'
	CALL	COUT
	LD	A,(BLNGTH)	;INCREASE LENGTH BY 2
	ADD	A,2
	LD	(BLNGTH),A
	JR	MVUP
;
;  CHAR IS LESS THAN <LF> -- MAKE IT SINGLE DIGIT (LIKE 9 FOR TAB)
;
LTLF:
	OR	'0'	;MASK FOR ASCII
	CALL	COUT	;PRINT DIGIT
;
;  ADVANCE TO NEXT BYTE
;
MVUP:
	INC	HL	;PT TO NEXT BYTE
	EX	DE,HL	;... IN DE
	LD	HL,(PC) ;PT TO PC
	INC	HL	;ADVANCE PC
	LD	(PC),HL
	EX	DE,HL	;DE PTS TO PC, HL PTS TO NEXT BYTE
;
;  CHECK TO SEE IF THE NEXT CONTROL POINT BEEN REACHED
;
CNXCTL:
	LD	A,(NXTCTL)	;COMPARE AGAINST PC
	CP	E
	JR	NZ,TRYSYM
	LD	A,(NXTCTL+1)
	CP	D
	JP	Z,QTB
;
;  SEE IF WE ARE POINTING TO A SYMBOL'S ADDRESS
;
TRYSYM:
	LD	HL,(PC) ;PC IN DE
	EX	DE,HL
	CALL	SYMSCH	;LOOK FOR SYMBOL
	JP	NC,STPLN	;NEW LINE IF THERE IS A SYMBOL
	LD	A,(BLNGTH)	;INCREASE LINE BY 2
	ADD	A,2
	LD	(BLNGTH),A
	CP	27
	JP	NC,STPLN	;NEW LINE IF STRING EXCEEDS 27 CHARS
	LD	A,','	;SEPARATE BY COMMA OTHERWISE
	CALL	COUT
	JP	MOREB
;
;  VALID CHAR ... BEGIN PROCESSING AS QUOTED STRING
;
LTRUB:
	LD	A,''''	;OUTPUT QUOTE
	CALL	COUT
	LD	A,(BLNGTH)	;INC LENGTH
	INC	A
	LD	(BLNGTH),A
	LD	A,(HL)	;GET CHAR
;
;  OUTPUT AS ASCII CHARS
;
MORASC:
	CALL	COUT	;PRINT CHAR
	LD	A,(HL)	;CHECK FOR QUOTE
	CP	''''	;COMPARE
	CALL	Z,COUT	;DOUBLE QUOTE
	INC	HL	;PT TO NEXT CHAR
	EX	DE,HL	;... IN DE
	LD	HL,(PC) ;INCR PC
	INC	HL
	LD	(PC),HL
	EX	DE,HL	;DE=NEXT PC
	LD	A,(NXTCTL)	;CHECK FOR CONTROL
	CP	E
	JR	NZ,YET
	LD	A,(NXTCTL+1)
	CP	D
	JR	Z,FNLQT
;
;  CHECK FOR SYMBOL HERE
;
YET:
	PUSH	HL
	LD	HL,(PC)
	EX	DE,HL
	CALL	SYMSCH
	POP	HL
	JR	NC,FNLQT	;OUTPUT ENDING QUOTE AND NEW LINE FOR SYMBOL
	LD	A,(BLNGTH)	;  BREAK
	INC	A	;INCR LINE LENGTH
;
;  KEEP THE LINES LESS THAN 27 LONG
;
	LD	(BLNGTH),A
	CP	35
	JR	NC,LASTQT
	CP	27
	JR	C,STILL
;
;  OVER 17H CHARACTERS HAVE BEEN QUOTED
;
	DEC	HL
	LD	A,(HL)
	INC	HL
	CP	' '
	JR	Z,FNLQT
STILL:
	LD	A,(HL)
	CP	' '
	JR	C,LASTQT
	CP	7FH
	JP	C,MORASC
;
;  PRINT A TRAILING QUOTE
;
LASTQT:
	LD	A,''''	;PRINT QUOTE
	CALL	COUT
	JP	CNXCTL
;
;  PRINT ENDING QUOTE AND NEW LINE
;
FNLQT:
	LD	A,''''
	CALL	COUT
QTB:
	CALL	CRLF
	JP	TENL
;
;COMMAND:  I<ADDRESS>,<OFFSET>
;  INCREMENT SYMBOL TABLE ADDRESSES AFTER AND ON <ADDRESS> BY <OFFSET>
;  FOR DISASSEMBLY OF NEW VERSIONS OF PROGRAMS
;
INCMNT:
	LD	HL,INBUF+3	;LOOK AT COMMAND LINE
	LD	A,(HL)		;GET CHAR AFTER 'I'
	CP	0DH		;ERROR IF EOL
	JP	Z,WHAT
	CALL	CNVRT		;GET FIRST VALUE IN DE
	PUSH	DE		;SAVE STARTING ADDRESS ON STACK
	CP	' '		;CHECK FOR VALID DELIMITER
	JR	Z,INCM1
	CP	','		;' ' OR ',' DELIMITER
	JP	NZ,WHAT
INCM1:
	INC	HL		;PT TO FIRST CHAR AFTER DELIMITER
	CALL	CNVRT		;GET OFFSET IN DE
	CP	0DH		;MUST BE EOL NOW
	JP	NZ,WHAT
	LD	B,D		;BC=OFFSET
	LD	C,E
	POP	DE		;DE=START ADDRESS
	LD	HL,SYMTAB	;PT TO TABLE
;  MAJOR LOOP FOR SCANNING SYMBOL TABLE -- HL PTS TO LOW SYM ADDRESS BYTE
INCM2:
	INC	HL		;PT TO HI SYM ADDRESS
	LD	A,(HL)		;GET HI
	DEC	HL		;PT TO LOW SYM ADDRESS
	CP	D		;COMPARE
	JR	C,INCM4 	;SKIP SYMBOL ENTRY
	JR	NZ,INCM3	;SYMBOL IS GREATER SO ADD OFFSET TO IT
	LD	A,(HL)		;GET LOW
	CP	E		;COMPARE
	JR	C,INCM4 	;SKIP SYMBOL ENTRY
;  ADD OFFSET TO SYMBOL ADDRESS PTED TO BY HL
INCM3:
	LD	A,(HL)		;GET LOW ADDRESS BYTE
	ADD	A,C		;ADD LOW OFFSET BYTE
	LD	(HL),A		;PUT LOW ADDRESS BYTE
	INC	HL		;PT TO HI ADDRESS BYTE
	LD	A,(HL)		;GET HIGH ADDRESS BYTE
	ADC	A,B		;ADD HI OFFSET BYTE
	LD	(HL),A		;PUT HI ADDRESS BYTE
	DEC	HL		;PT TO LOW ADDRESS BYTE
;  SKIP TO NEXT SYMBOL -- HL PTS TO LOW ADDRESS BYTE
INCM4:
	INC	HL		;PT TO HI ADDRESS
	INC	HL		;PT TO CHAR COUNT
	LD	A,(HL)		;GET CHAR COUNT
	OR	A		;DONE IF ZERO
	JP	Z,GETCMD
	INC	HL		;PT TO FIRST CHAR OF SYMBOL
	ADD	A,L		;ADD SYMBOL LENGTH TO HL
	LD	L,A
	LD	A,0		;ADD IN HI NOW
	ADC	A,H
	LD	H,A		;HL PTS TO FIRST BYTE OF NEXT SYMBOL
	JR	INCM2		;CONTINUE PROCESSING
;
;COMMAND:  ?
;  STATISTIC OUTPUT
;
STAT:
	CALL	PSTRNG	;THIS IS RATHER STRAIGHT-FORWARD, SO FEW COMMENTS
	DEFB	'Scratch Area Start = ',0
	LD	HL,ENDALL
	CALL	PVALUE	;PRINT VALUE
	CALL	PSTRNG
	DEFB	0DH,0AH
	DEFB	'Scratch Area End   = ',0
	LD	HL,(6)
	LD	L,0
	CALL	PVALUE		;PRINT THE BEGINNING OF BDOS (NOT CCP)
	CALL	PSTRNG
	DEFB	0DH,0AH,0AH
	DEFB	'COM Start = 0100',0DH,0AH
	DEFB	'COM End   = ',0
	LD	HL,(RELEND)	;GET END ADDRESS
	CALL	PVALUE
	CALL	PSTRNG
	DEFB	0DH,0AH,0AH
	DEFB	'SYMTBL = ',0
	LD	HL,SYMTAB
	CALL	PVALUE
	LD	HL,(SYMEND)
	CALL	PVALUE
	CALL	CRLF
	CALL	PSTRNG
	DEFB	'PC     = ',0
	LD	HL,(PC)
	CALL	PVALUE
	CALL	CRLF
	CALL	PSTRNG
	DEFB	'OFFSET = ',0
	LD	HL,(OFFSET)
	CALL	PVALUE
	CALL	CRLF
	LD	HL,(COMST)
	LD	A,H
	OR	L
	JR	Z,CTLSTT
	CALL	PSTRNG
	DEFB	'COMNTS = ',0
	LD	HL,(COMST)
	CALL	PVALUE
	LD	HL,(COMEND)
	CALL	PVALUE
	CALL	CRLF
CTLSTT:
	CALL	CTLST
	CALL	CMNTST
	JP	GETCMD
;
;  PRINT PARAMETERS OF CONTROL TABLE
;
CTLST:
	CALL	PSTRNG		;PRINT THE START AND END OF CONTROL TABLE
	DEFB	'CTLTBL = ',0
	LD	HL,CTLTBL
	CALL	PVALUE
;
;  FIND THE END OF THE CTLTBL (FF,FF)
;
FNDEND:
	LD	A,(HL)	;GET FIRST BYTE
	INC	HL	;PT TO NEXT
	AND	(HL)	;AND IT IN ... IF BOTH ARE 0FFH, RESULT IS 0FFH
	INC	HL	;PT TO CTL LETTER
	INC	HL	;PT TO NEXT BYTE OF ADDRESS
	INC	A	;IF RESULT WAS 0FFH, A NOW EQUALS 0
	JR	NZ,FNDEND	;CONTINUE UNTIL A=0
	DEC	HL	;BACK UP TO PREVIOUS ENTRY (END OF TABLE)
	DEC	HL
	DEC	HL
	CALL	PVALUE	;PRINT THE VALUE 0FFFFH
	JP	CRLF
;
;  PRINT THE STATUS MESSAGE OF THE SYMBOL COMMENTS FACILITY
;
CMNTST:
	CALL	PSTRNG		;PRINT THE STATUS OF SYMBOL COMMENTS
	DEFB	'Symbol Comments are O',0
	LD	A,(XCSW)
	OR	A
	LD	A,'N'
	JR	NZ,CMTST1
	LD	A,'F'
	CALL	COUT
CMTST1:
	CALL	COUT
	JP	CRLF
;
;COMMAND:  F
;  FIND THE OCCURRENCE OF ADDRESSES
;
FIND:
	LD	HL,INBUF+3
	LD	A,(HL)
	CP	0DH	;CHECK FOR NO FURTHER ARGS
	JR	Z,PREVF
	CALL	CNVRT	;GET ARG IN DE
	EX	DE,HL	; ... IN HL
	LD	(FNDADD),HL	;ADDRESS TO LOOK FOR
	LD	HL,(OFFSET)	;GET OFFSET
	LD	(FNDPC),HL	;SET START OF SEARCH ADDRESS
	EX	DE,HL	;RESTORE HL TO PT TO CHAR IN COMMAND LINE
	CP	0DH	;DONE?
	JR	Z,PREVF
	CP	' '	;<SP> OR ',' MEAN TO CONTINUE
	JR	Z,FIND0
	CP	','
	JP	NZ,WHAT
FIND0:
	INC	HL
	CALL	CNVRT	;GET 2ND ARG FOR FIND
	CP	0DH
	JP	NZ,WHAT
	LD	HL,(OFFSET)	;SET THIS AS STARTING ADDRESS
	ADD	HL,DE	;WITH PROPER OFFSET
	LD	(FNDPC),HL	;START LOOKING FROM HERE
;
;  CONTINUE THE PREVIOUS 'F' COMMAND
;
PREVF:
	LD	HL,(FNDADD)	;GET ADDRESS WE ARE LOOKING FOR
	EX	DE,HL		;... IN DE
NYET:
	CALL	BRKCHK	;CHECK FOR BREAK
	LD	HL,(FNDPC)	;PT TO PC
	LD	A,(HL)		;GET BYTE AT PC
	INC	HL		;PT TO NEXT
	LD	(FNDPC),HL
	CP	E		;COMPARE BYTE WITH ADDRESS WE ARE LOOKING FOR
	JR	NZ,NYET
	LD	A,(HL)		;PARTIAL MATCH -- TRY HIGH BYTE
	CP	D
	JR	NZ,NYET
;
;  WE FOUND ADDRESS IN MEMORY -- PRINT DATA
;
	PUSH	HL
	PUSH	DE
	CALL	TWOS
	DEC	HL
	CALL	PVALUE	;PRINT LOCATION OF FOUND ADDRESS (RELATIVE)
	POP	DE
	POP	HL
	CALL	SPACE	;PRINT <SP>
	JR	NYET
;
;  HL=HL-OFFSET
;   TAKE 2'S COMPLEMENT OF OFFSET AND ADD TO H & L.
;
TWOS:
	LD	A,(OFFSET)	;GET 2'S COMP OF OFFSET IN DE
	CPL	
	LD	E,A
	LD	A,(OFFSET+1)
	CPL	
	LD	D,A
	INC	DE
	ADD	HL,DE		;HL=HL+DE
	RET	
;
;COMMAND:  Z
;   CLOSE THE FILE
;
CLOSE:
	CALL	HSYM
	LD	A,1	;ENABLE WRITING TO DISK FILE
	LD	(WRTENAB),A
	CALL	PSTG	;WRITE END STATEMENT
	DEFB	'END',0DH,0AH,0
	XOR	A	;DISABLE WRITING TO FILE
	LD	(WRTENAB),A
	LD	A,(FOPEN)	;CHECK IF FILE WAS OPEN
	OR	A
	JP	Z,GETCMD
	LD	A,1AH	;FILL WITH ^Z
	CALL	WRTFILE
	CALL	NXTRCRD
	XOR	A	;CLOSE FILE
	LD	(FOPEN),A
	CALL	PSTRNG	;PRINT MESSAGE
	DEFB	'++ ASM File Closed ++',0DH,0AH,0
	JP	GETCMD
;
;COMMAND:  R
;   READ A FILE OR FILES
;
READ:
	CALL	SETFCB	;LOAD THE FCB WITH THE PROPER FILE NAME AND TYPE
	LD	A,(FOPEN)	;CHECK TO SEE IF A FILE IS ALREADY OPENED
	OR	A
	JP	NZ,CANT ;ABORT IF SO
	LD	HL,FCBTYPE	;CHECK FILE TYPE
	LD	DE,TPALL	;IS IT 'ALL'?
	LD	C,3
	CALL	CHKSTG
	JP	NZ,NOTALL	;PROCEED IF NOT
;
;  READ IN DOC, SYM, CTL FILES
;
	CALL	ALLRD		;READ IN ALL FILES
	JP	STAT		;PRINT STATISTICS
;
;  READ IN ALL FILES -- COMMON ROUTINE
;
ALLRD:
	LD	HL,TPDOC	;SET FILE TYPE TO DOC
	CALL	FIXTYP
	CALL	PSTRNG		;TELL USER WHAT IS HAPPENING
	DEFB	0DH,0AH
	DEFB	'Reading DOC file...',0DH,0AH,0
	CALL	DOCRD		;READ FILE IN
	LD	HL,TPSYM	;SET FILE TYPE TO SYM
	CALL	FIXTYP
	CALL	PSTRNG		;TELL USER WHAT IS HAPPENING
	DEFB	'Reading SYM file...',0DH,0AH,0
	CALL	SYMRD		;READ FILE IN
	LD	HL,TPCTL	;SET FILE TYPE TO CTL
	CALL	FIXTYP
	CALL	PSTRNG		;TELL USER WHAT IS HAPPENING
	DEFB	'Reading CTL file...',0DH,0AH,0
	CALL	CTLRD		;READ FILE IN

	IFTRUE	RDCOMQ		;ENABLE QUESTION OF COM FILE READ?
	CALL	PSTRNG
	DEFB	'Read in COM File (Y/N)? ',0
	CALL	CHIN		;GET RESPONSE
	CP	'Y'
	JP	NZ,STAT 	;PRINT STATISTICS
	ENDIF
	
	LD	HL,TPCOM	;SET FILE TYPE TO COM
	CALL	FIXTYP
	CALL	PSTRNG		;TELL USER WHAT IS HAPPENING
	DEFB	'Reading COM file...',0DH,0AH,0
	CALL	COMRD		;READ FILE IN
	RET
;
;  SET THE FILE TYPE TO THAT PTED TO BY HL
;
FIXTYP:
	LD	DE,FCBTYPE
	LD	B,3
	XOR	A
	LD	(FCB+0CH),A	;ZERO THE EXTENT BYTE
	JP	SLIDE
;
;  FILE TYPE WAS NOT 'ALL', SO CHECK TO SEE WHAT TYPE IT WAS AND PROCESS
;
NOTALL:
	LD	HL,FCBTYPE	;CHECK FOR SYM
	LD	DE,TPSYM
	LD	C,3
	CALL	CHKSTG
	JR	NZ,NOTSYM
	CALL	SYMRD		;READ SYM FILE
	JP	STAT		;PRINT STATS
NOTSYM:
	LD	HL,FCBTYPE	;CHECK FOR COM
	LD	DE,TPCOM
	LD	C,3
	CALL	CHKSTG
	JP	NZ,NOTCOM
	CALL	COMRD		;READ IN A COM FILE
	JP	GETCMD		;CONTINUE COMMAND LINE PROCESSING
;
;  READ IN COM FILE
;
COMRD:
	CALL	RDOPEN		;OPEN COM FILE FOR READ
	LD	HL,(OFFSET)	;HL=OFFSET
	LD	A,H
	CP	(SYMTAB+600H).SHR.8	;CHECK FOR NO OVERWRITE OF SYMTABLE
	JP	C,OSERR
	LD	DE,0100H	;SET DMA ADDRESS TO OFFSET PLUS 100H
	ADD	HL,DE
SETDMA:
	PUSH	HL	;SET THE DMA ADDRESS.
	EX	DE,HL
	LD	C,1AH
	CALL	BDOS
	LD	DE,FCB	;READ A RECORD.
	LD	C,14H
	CALL	BDOS
	OR	A	;DONE?
	JR	NZ,RDCMPLT
	POP	HL
	LD	DE,RECLEN	;PT TO NEXT BLOCK FOR READ
	ADD	HL,DE
	JP	SETDMA	;CONTINUE
;
;  DONE WITH LOAD OF COM FILE
;
RDCMPLT:
	POP	HL	;GET DMA ADDRESS OF LAST READ
	CALL	PSTRNG
	DEFB	'Last Block Read into Memory at ',0
	CALL	PVALUE
	CALL	PSTRNG
	DEFB	0DH,0AH
	DEFB	'Last Block Ends at Relative ',0
	CALL	TWOS
	LD	(RELEND),HL	;SAVE RELATIVE END ADDRESS
	CALL	PVALUE
	CALL	CRLF
	LD	DE,RECLEN	;RESET THE DMA ADDRESS TO 80H
	LD	C,1AH
	CALL	BDOS
	RET
;
;  THE READ IS NOT A .SYM OR A .COM FILE
;
NOTCOM:
	LD	HL,FCBTYPE	;CHECK FOR CTL FILE
	LD	DE,TPCTL
	LD	C,3
	CALL	CHKSTG
	JR	NZ,NOTCTL
	JP	ISCTL		;READ IN CTL FILE
NOTCTL:
	LD	HL,FCBTYPE	;CHECK FOR DOC FILE
	LD	DE,TPDOC
	LD	C,3
	CALL	CHKSTG
	JP	NZ,WHAT 	;ERROR IF NOT COM, SYM, CTL, OR DOC
	CALL	DOCRD		;READ IN DOC FILE
	JP	STAT
;
;  ERROR -- ATTEMPT TO OVERLAY THE SYMBOL TABLE OR DISASSEMBLER
;
OSERR:
	CALL	PSTRNG
	DEFB	'++ NO, that would overlay '
	DEFB	'the Disassembler',0DH,0AH
	DEFB	'because the Offset is too small: '
	DEFB	0
	CALL	PRNTOS
	CALL	PSTRNG
	DEFB	' ++',0DH,0AH,0
	RET
;
;  READ THE SYMBOL TABLE FROM DISK
;
SYMRD:
	LD	HL,SYMTAB	;PT TO SYMBOL TABLE
	CALL	READFILE	;READ FILE INTO IT
	LD	(SYMEND),HL	;SET END ADDRESS OF SYMBOL TABL
	INC	HL		;PT TO NEXT SYMBOL CHAR COUNT
	INC	HL
	LD	(HL),0		;SET CHAR COUNT TO ZERO
	RET	
;
;  READ THE DOC (COMMENTS) FILE FROM DISK
;
DOCRD:
	CALL	AREACK		;MAKE SURE COMMENTS AREA DEFINED
	LD	HL,(COMST)	;PT TO START OF COMMENTS AREA
	CALL	READFILE	;READ FILE IN
	LD	(COMEND),HL	;SET END OF COMMENTS AREA
	LD	(HL),0FFH	;STORE 0FFFFH AS ADDRESS OF NEXT COMMENT
	INC	HL
	LD	(HL),0FFH
	RET	
;
;  READ FILE SET IN FCB INTO MEMORY PTED TO BY HL
;
READFILE:
	CALL	RDOPEN	;OPEN FILE
RDFL1:
	CALL	READMA	;READ NEXT BYTE (RETURNED IN A)
	CP	1AH	;RETURN IF EOF EACHED
	RET	Z
	CP	9	;IGNORE <TAB>, <CR>, <LF>
	JR	Z,RDFL1
	CP	0DH
	JR	Z,RDFL1
	CP	0AH
	JR	Z,RDFL1
	CALL	NUM1	;CONVERT FROM HEX CHARS TO VALUE IN DE
	LD	(HL),E	;SAVE THE ADDRESS
	INC	HL
	LD	(HL),D
	INC	HL
	PUSH	HL
	INC	HL
	LD	B,0	;COUNT CHARS IN SYMBOL
SYMLUP:
	CALL	READMA	;GET NEXT BYTE
	CP	9	;DONE IF <TAB> OR <CR>
	JR	Z,SYMTERM
	CP	0DH
	JR	Z,SYMTERM
	LD	(HL),A	;STORE BYTE
	INC	HL	;PT TO NEXT
	INC	B	;INCR CHAR COUNT
	JR	SYMLUP
SYMTERM:
	EX	(SP),HL
	LD	(HL),B
	POP	HL
	JP	RDFL1
;
;  READ NUMBER FROM DISK FILE (1ST HEX DIGIT IN A ON ENTRY)
;    VALUE RETURNED IN DE
;
NUM1:
	LD	DE,0	;INIT NUMBER TO ZERO
LUP1:
	CP	' '	;DONE IF <SP>
	RET	Z
	CP	1AH	;ERROR IF EOF
	JP	Z,ERROR1
	CP	'9'+1	;WITHIN DIGIT RANGE?
	JR	C,NUMER1	;IS A DIGIT
	SUB	7	;CONVERT 'A' TO 'F' TO '9'+1 TO 'E'+1
NUMER1:
	SUB	'0'	;CONVERT TO BINARY IN A
	EX	DE,HL	;OLD VALUE IN HL
	ADD	HL,HL	;*2
	ADD	HL,HL	;*4
	ADD	HL,HL	;*8
	ADD	HL,HL	;*16
	ADD	A,L	;+A
	LD	L,A	;ONLY CHANGES LOW-ORDER BYTE
	EX	DE,HL	;VALUE BACK IN DE
	CALL	READMA
	CP	1AH
	JP	Z,ERROR1
	JR	LUP1
;
;COMMAND:  S
;  SAVE THE FILES
;
SAVE:
	CALL	SETFCB		;LOAD THE FCB FROM THE COMMAND LINE
	LD	A,(FOPEN)	;CHECK FOR FILE ALREADY OPEN
	OR	A		;ABORT IF SO
	JP	NZ,CANT
	LD	HL,FCBTYPE	;CHECK FOR TYPE OF 'ALL'
	LD	DE,TPALL
	LD	C,3
	CALL	CHKSTG
	JP	NZ,NTALL	;CHECK FOR SPECIFIC TYPE IF NOT ALL
	LD	HL,TPDOC	;SAVE DOC FILE
	CALL	FIXTYP
	CALL	PSTRNG
	DEFB	0DH,0AH
	DEFB	'Saving .DOC file...',0DH,0AH,0
	CALL	DOCSV
	LD	HL,TPSYM	;SAVE SYM FILE
	CALL	FIXTYP
	CALL	PSTRNG
	DEFB	'Saving .SYM file...',0DH,0AH,00
	CALL	SYMSV
	LD	HL,TPCTL	;SAVE CTL FILE
	CALL	FIXTYP
	CALL	PSTRNG
	DEFB	'Saving .CTL file...',0DH,0AH,0
	CALL	SVCTL0
	CALL	PSTRNG		;OPTIONALLY SAVE ASM FILE
	DEFB	'Create a New .ASM File (Y/N)? ',0
	CALL	CHIN	;GET CHAR
	CP	'Y'
	JP	NZ,GETCMD
	LD	HL,TPASM	;SAVE ASM FILE
	CALL	FIXTYP
;
;  SAVE THE ASM FILE
;
SVASM:
	LD	A,1	;MARK FILE AS OPEN
	LD	(FOPEN),A
	XOR	A	;DISABLE WRITING AT THIS TIME
	LD	(WRTENAB),A
	CALL	OPEN	;OPEN FILE FOR OUTPUT
	CALL	PSTRNG	;PRINT MESSAGE
	DEFB	'++ Writing ASM Enabled'
	DEFB	0DH,0AH,'Use Z Command or '
	DEFB	'E Control to Close File ++'
	DEFB	0DH,0AH,0
	JP	GETCMD	;NOW PROCESS USER'S NEXT COMMANDS
;
;  TYPE WAS NOT ALL, SO CHECK FOR SPECIFIC FILE TYPES
;
NTALL:
	LD	HL,FCBTYPE	;CHECK FOR SYM
	LD	DE,TPSYM
	LD	C,3
	CALL	CHKSTG
	JP	NZ,NTSYM
	CALL	SYMSV
	JP	GETCMD
;
;  ROUTINE TO SAVE THE SYMBOL TABLE
;
SYMSV:
	LD	HL,SYMTAB	;PT TO SYMBOL TABLE
SVFL:
	CALL	OPEN	;OPEN THE FILE
LUP2:
	LD	E,(HL)	;GET ADDRESS OF SYMBOL IN DE
	INC	HL
	LD	D,(HL)
	INC	HL
	LD	A,(HL)	;GET LENGTH OF SYMBOL IN A
	INC	HL
	LD	B,A	;... AND B
	OR	A	;DONE IF LENGTH IS ZERO
	JP	Z,WRTEOF	;WRITE EOF TO FILE IF DONE
	CALL	EXPND	;WRITE ADDRESS IN DE AS ASCII CHARS ON DISK
	LD	A,' '	;OUTPUT <SP>
	CALL	WRTFILE
WRTSYM:
	LD	A,(HL)	;GET NEXT CHAR OF SYMBOL
	CALL	WRTFILE ;WRITE TO DISK
	INC	HL	;PT TO NEXT
	DJNZ	WRTSYM	;COUNT DOWN SIZE OF SYMBOL
	LD	A,0DH	;WRITE NEW LINE CHARS
	CALL	WRTFILE
	LD	A,0AH
	CALL	WRTFILE
	JR	LUP2
;
;  WRITE AN EOF
;
WRTEOF:
	LD	A,1AH	;WRITE EOF
	CALL	WRTFILE
	CALL	NXTRCRD
	RET	
;
;  EXPAND AN ADDRESS IN DE TO ASCII CHARS AND SAVE ON DISK
;
EXPND:
	LD	A,D	;OUTPUT HIGH NYBBLE OF HIGH-ORDER BYTE
	CALL	HINIB	;ROUTINE TO DO THIS
	CALL	WRTFILE ;WRITE ASCII CHAR IN A TO DISK
	LD	A,D	;OUTPUT LOW NYBBLE
	CALL	LONIB
	CALL	WRTFILE
	LD	A,E	;HIGH OF LOW-ORDER BYTE
	CALL	HINIB
	CALL	WRTFILE
	LD	A,E	;LOW OF LOW-ORDER BYTE
	CALL	LONIB
	JP	WRTFILE
;
;  NOT OF TYPE SYM -- CHECK FOR CTL
;
NTSYM:
	LD	HL,FCBTYPE	;CHECK FOR CTL TYPE
	LD	DE,TPCTL
	LD	C,3
	CALL	CHKSTG
	JP	Z,SVCTL 	;YES, SO SAVE CTL FILE
	LD	HL,FCBTYPE	;CHECK FOR DOC TYPE
	LD	DE,TPDOC
	LD	C,3
	CALL	CHKSTG
	JR	Z,SVDOC 	;YES, SO SAVE DOC FILE
	LD	HL,FCBTYPE	;CHECK FOR ASM TYPE
	LD	DE,TPASM
	LD	C,3
	CALL	CHKSTG
	JP	NZ,WHAT 	;ERROR IF NOT ASM AT THIS POINT
	JP	SVASM		;SAVE ASSEMBLY LANGUAGE (TYPE ALREADY ASM)
;
;  SAVE THE COMMENT TABLE
;
SVDOC:
	CALL	DOCSV
	JP	GETCMD	
;
;  SAVE COMMENTS
;
DOCSV:
	CALL	AREACK	;FIND END OF COMMENTS
	LD	HL,(COMEND)	;GET PTR IN HL
	INC	HL
	INC	HL
	LD	(HL),0	;SET NULL FINAL COMMENT
	LD	HL,(COMST)	;PT TO START OF TABLE
	JP	SVFL	;PERFORM STRAIGHT SAVE
;
;  ATTEMPT TO OPEN ANOTHER FILE WHILE ASM FILE ALREADY OPENED
;
CANT:
	CALL	PSTRNG
	DEFB	'++ No File Accessed Permitted '
	DEFB	'until ASM Closed ++',0DH,0AH
	DEFB	0
	JP	GETCMD
;
;  EOF ENCOUNTERED TOO SOON
;
ERROR1:
	CALL	PSTRNG
	DEFB	'++ Unexpected EOF ++',0DH,0AH
	DEFB	0
	JP	GETCMD
;
;COMMAND:  C
;  CONTROL TABLE ENTRIES ARE MADE HERE
;
CTL:
	CALL	IECNT	;INIT ECNT
	LD	HL,INBUF+3
	LD	A,(HL)
	CP	0DH	;DUMP CONTROL TABLE IF JUST A 'C' COMMAND
	JP	Z,CDUMP1
	CALL	CNVRT	;GET ADDRESS
	CP	0DH	;ERROR?
	JP	Z,CDUMP ;DUMP IF SO
	CP	' '	;DELIMITER?
	JR	Z,CTL0	;PROCESS 2ND OPERAND IF SO
	CP	','	;SAME
	JP	NZ,WHAT ;ERROR OTHERWISE
CTL0:
	INC	HL	;PT TO 2ND OPERAND
	LD	A,(HL)	;GET IT (CONTROL TYPE)
	CALL	FTCTL	;PROCESS ENTRY WITH CONTROL TABLE
	JP	GETCMD
;
;  PLACE A NEW ENTRY INTO THE CONTROL TABLE
;    A=TYPE OF ENTRY (B, E, I, K, S, W) AND DE=ADDRESS
;
FTCTL0:
	PUSH	HL	;SAVE REGS
	PUSH	DE	;NEW ADDRESS
	PUSH	AF	;NEW TYPE
	CALL	SCHCTL	;FIND ENTRY IN CONTROL TABLE
	DEC	HL	;PT TO TYPE OF PREVIOUS CONTROL ENTRY
	JR	C,FTCTL1	;IF CARRY, WE DIDN'T MATCH
	INC	HL	;PT TO TYPE OF CURRENT ENTRY WHICH MATCHES
	INC	HL
	INC	HL
FTCTL1:
	POP	AF	;GET NEW TYPE AND
	POP	DE	;... ADDRESS
	CP	(HL)	;DO OUR TYPES MATCH?
	POP	HL	;RESTORE HL
	RET	Z	;NO CHANGE IF THEY DO
;
;  PLACE A NEW ENTRY INTO THE CONTROL TABLE
;
FTCTL:
	LD	(OPCTP),A	;SAVE TYPE OF ENTRY
	CALL	SCHCTL	;SCAN FOR A MATCH
	JP	C,PLACE ;NO MATCH, SO ENTRY MUST BE ADDED
;
;  MATCH OF ADDRESS, SO SIMPLY CHANGE CONTROL MODE AT THAT POINT
;
	LD	A,(OPCTP)	;GET TYPE OF ENTRY
	CP	'I'	;INSTRUCTION?
	JR	Z,RNCTL
	CP	'W'	;DW?
	JR	Z,RNCTL
	CP	'H'	;DB HEX?
	JR	Z,RNCTL
	CP	'B'	;DB?
	JR	Z,RNCTL
	CP	'S'	;DS?
	JR	Z,RNCTL
	CP	'E'	;END OF PROGRAM?
	JR	Z,RNCTL
	CP	'K'	;KILL SYMBOL?
	JR	Z,DELCTL
	JP	WHAT	;ERROR IF NONE OF THESE
;
;  READ A NEW CONTROL MODE
;    ENTRY FORM IS:
;	DW ADDRESS
;	DB CONTROL MODE
;
RNCTL:
	INC	HL		;ADDRESS IS SAME
	INC	HL		;PT TO CONTROL MODE
	LD	(HL),A		;ONLY SET NEW CONTROL MODE
	RET	
;
;  DELETE THE ENTRY FROM THE CONTROL TABLE
;
DELCTL:
	EX	DE,HL	;DE PTS TO ENTRY TO DELETE
	LD	HL,3
	ADD	HL,DE	;HL PTS TO NEXT ENTRY
	EX	DE,HL	;DE PTS TO NEXT ENTRY, HL PTS TO ENTRY TO DELETE
;
;  COPY CONTROL TABLE DOWN
;
CMPCT:
	LD	A,(HL)	;CHECK FOR END OF CONTROL TABLE
	INC	HL
	AND	(HL)	;ADDRESS IS 0FFFFH IF END
	DEC	HL
	INC	A	;A=0 MEANS ADDRESS IS 0FFFFH
	JR	Z,PNTHLL
	LD	BC,3	;NOT AT END -- COPY 3 BYTES DOWN AND CONTINUE
	EX	DE,HL	;HL PTS TO SOURCE, DE TO DEST
	LDIR		;COPY THE 3 BYTES
	EX	DE,HL	;DE PTS TO NEXT ENTRY, HL PTS TO ENTRY TO DELETE
	JR	CMPCT	;CONTINUE COPY OPERATION
;
;  COPY COMPLETE
;
PNTHLL:
	CALL	CTLST	;PRINT CONTROL TABLE INFORMATION
	JP	GETCMD
;
;  PLACE AN ENTRY INTO THE CONTROL TABLE
;    ON ENTRY, HL PTS TO ENTRY TO INSERT BEFORE
;
PLACE:
	LD	A,(OPCTP)	;GET TYPE OF COMMAND
	CP	'K'		;ERROR IF KILL
	JP	Z,WHAT
	CP	'E'		;SET END OF PROGRAM AREA
	JR	Z,LGLCTL
	CP	'H'		;DB HEX
	JR	Z,LGLCTL
	CP	'B'		;DB
	JR	Z,LGLCTL
	CP	'W'		;DW
	JR	Z,LGLCTL
	CP	'I'		;INSTRUCTION
	JR	Z,LGLCTL
	CP	'S'		;DS
	JP	NZ,WHAT 	;ERROR IF NONE OF THESE
;
;  PLACE ENTRY INTO CONTROL TABLE; A=TYPE, DE=ADDRESS, HL=ADDR OF ENTRY
;    TO INSERT BEFORE
;
LGLCTL:
	PUSH	DE		;SAVE ADDRESS
	PUSH	HL		;SAVE ADDRESS OF ENTRY TO INSERT BEFORE
	LD	HL,CTLTBL	;PT TO FRONT OF TABLE
;
;  LOOP TO THE END OF THE TABLE
;
LP2END:
	LD	A,(HL)		;CHECK FOR 0FFFFH AT END OF TABLE
	INC	HL
	AND	(HL)		;A=0FFH IF SO
	INC	HL		;PT TO CURR CONTROL TYPE
	INC	HL		;PT TO NEXT CONTROL ADDRESS
	INC	A		;A=0 AND ZERO FLAG SET IF AT END
	JR	NZ,LP2END	;CONTINUE UNTIL AT END OF TABLE
	LD	D,H		;DE=HL=PTR TO NEW LAST TABLE ENTRY LOC
	LD	E,L
	INC	HL		;PT TO ENTRY AFTER LAST ENTRY IN TABLE
	INC	HL
	INC	HL		;HL PTS TO NEW LAST TABLE ENTRY LOCATION
	EX	DE,HL		;DE PTS TO NEW, HL PTS TO OLD
	POP	BC		;BC=ADDRESS OF ENTRY TO INSERT BEFORE
;
;  EXPAND THE TABLE BY 3 PLACES UNTIL THE PROPER PLACE IS REACHED
;
EXPTBL:
	DEC	HL		;BACK UP
	DEC	DE
	LD	A,(HL)		;COPY PREVIOUS BYTE INTO NEW TABLE LOCATION
	LD	(DE),A
	LD	A,L		;ARE WE AT ENTRY TO INSERT BEFORE?
	CP	C
	JR	NZ,EXPTBL	;CONTINUE IF NOT
	LD	A,H		;CHECK HIGH BYTES
	CP	B
	JR	NZ,EXPTBL
	POP	DE		;DE=NEW ENTRY ADDRESS, HL=ADDRESS TO INSERT AT
	LD	(HL),E		;PLACE NEW ENTRY ADDRESS INTO TABLE
	INC	HL
	LD	(HL),D
	INC	HL
	LD	A,(OPCTP)	;PLACE NEW ENTRY TYPE INTO TABLE
	LD	(HL),A
	RET	
;
;  SEARCH CTL TBL FOR AN ENTRY FOR (DE)
;    ON EXIT, HL PTS TO LOW-ORDER BYTE OF CONTROL TABLE ENTRY IF MATCHED
;      OR LESS THAN
;    MATCH: C=0
;    NO MATCH:	C=1
;
SCHCTL:
	LD	HL,CTLTBL	;PT TO TABLE
;
;  IF NO MATCH THEN CARRY IS SET
;
SMORE:
	LD	A,(HL)	;GET LOW ADDRESS
	INC	HL	;PT TO HIGH
	AND	(HL)	;AND IN HIGH ADDRESS; IF ADDR=0FFFFH, THEN A=0FFH
	DEC	HL	;PT TO LOW ADDRESS
	INC	A	;IF A=0FFH BEFORE, NOW A=0
	SCF		;SET CARRY FLAG FOR ERROR RETURN
	RET	Z	;RETURN IF A=0 (WE ARE AT END OF TABLE)
	INC	HL	;PT TO HIGH ADDRESS
	LD	A,D	;GET ADDRESS TO COMPARE AGAINST
	CP	(HL)	;DO COMPARE
	DEC	HL	;PT TO LOW ADDRESS
	RET	C	;RETURN IF ADDRESS IS LESS THAN TABLE ENTRY
	JR	NZ,NXTRY	;CONTINUE IF NOT THE SAME
	LD	A,E	;GET LOW ADDRESS
	CP	(HL)	;COMPARE TO LOW ADDRESS
	RET	Z	;CARRY IS OFF AND ZERO IS SET IF COMPLETE MATCH
	RET	C	;CARRY IS ON AND ZERO IS NOT SET IF TARGET IS LESS
;
;  ADVANCE TO THE NEXT TABLE ENTRY
;
NXTRY:
	INC	HL	;PT TO HIGH ADDRESS
	INC	HL	;PT TO TYPE OF NEXT CONTROL ENTRY
	INC	HL	;PT TO LOW ADDRESS OF NEXT ENTRY IN TABLE
	JR	SMORE	;CONTINUE
;
;  DUMP CONTROL TABLE FROM ADDRESS IN DE
;
CDUMP:
	CALL	SCHCTL	;FIND ENTRY IN CONTROL TABLE >= ADDRESS IN DE
	JR	CDUMP2
;
;  DUMP ENTIRE CONTROL TABLE
;
CDUMP1:
	LD	HL,CTLTBL	;PT TO FIRST ENTRY IN CONTROL TABLE
CDUMP2:
	CALL	BRKCHK	;CHECK FOR ABORT
	LD	E,(HL)	;GET ADDRESS OF CONTROL ENTRY IN DE
	INC	HL
	LD	D,(HL)
	INC	HL
	LD	A,D	;CHECK FOR END OF TABLE
	AND	E	;END IF DE=0FFFFH
	INC	A	;SET A TO 0 IF SO
	JR	NZ,MOREDMP
	CALL	CRLF	;DONE, SO OUTPUT NEW LINE AND PRINT CONTROL INFO
	CALL	CTLST
	JP	GETCMD
;
;  DUMP CONTROL TABLE ENTRY TO USER
;
MOREDMP:
	PUSH	DE
	PUSH	HL
	CALL	SYMSCH	;SEARCH FOR A SYMBOL WHOSE VALUE = ADDRESS IN DE
	JR	C,AHEAD ;SKIP IF NOT FOUND
;
;   PRINT A SYMBOL SINCE IT WAS FOUND; SYMBOL PTED TO BY HL
;
	CALL	IECNT	;INIT ECNT
	CALL	CRLF	;NEW LINE
PRNTSYM:
	LD	A,(HL)	;OUTPUT CHARS OF SYMBOL
	CALL	COUT	;... COUNT IN B FROM SYMSCH
	INC	HL
	DJNZ	PRNTSYM
	LD	A,':'	;OUTPUT COLON AFTER SYMBOL
	CALL	COUT
;
;  OUTPUT CONTROL TABLE ENTRY
;
AHEAD:
	POP	HL	;GET PTR TO CONTROL MODE
	POP	DE	;GET ADDRESS OF ENTRY
	CALL	SPACE	;2 <SP>S
	CALL	SPACE
	EX	DE,HL	;ADDRESS IN HL
	CALL	PVALUE	;PRINT VALUE OF ADDRESS
	LD	A,'='	;PRINT DELIMITERS
	CALL	COUT
	LD	A,' '
	CALL	COUT
	EX	DE,HL	;RESTORE HL AS PTR TO CONTROL MODE
	LD	A,(HL)	;GET CONTROL MODE LETTER
	CALL	COUT	;PRINT IT
	CALL	SPACE	;<SP> OUT
	CALL	SPACE
	CALL	SPCRLF	;OUTPUT NEW LINE OCCASIONALLY
	INC	HL	;PT TO NEXT CONTROL TABLE ENTRY
	JR	CDUMP2
;
;  SAVE THE CONTROL TABLE ON DISK
;
SVCTL:
	CALL	SVCTL0	;USE ROUTINE
	JP	GETCMD
;
;  ROUTINE TO SAVE THE CONTROL TABLE ON DISK
;
SVCTL0:
	CALL	OPEN	;OPEN FILE
	LD	HL,CTLTBL	;PT TO TABLE
SVCTL1:
	LD	E,(HL)	;GET ADDRESS IN DE
	INC	HL
	LD	D,(HL)
	INC	HL
	LD	A,D	;CHECK FOR END (0FFFFH)
	AND	E
	INC	A	;A=0 IF SO
	JR	Z,CTLSVED
	CALL	EXPND	;OUTPUT ADDRESS IN DE AS 4 HEX CHARS
	LD	A,','	;OUTPUT COMMA
	CALL	WRTFILE
	LD	A,(HL)	;OUTPUT CONTROL MODE CHAR
	CALL	WRTFILE
	LD	A,0DH	;OUTPUT NEW LINE
	CALL	WRTFILE
	LD	A,0AH
	CALL	WRTFILE
	INC	HL	;PT TO NEXT CONTROL TABLE ENTRY
	JR	SVCTL1
;
;  THE CONTROL TABLE HAS BEEN SAVED
;
CTLSVED:
	LD	A,1AH	;WRITE EOF
	CALL	WRTFILE
	CALL	NXTRCRD
	RET
;
;  READ IN A CONTROL TABLE
;
ISCTL:
	CALL	CTLRD	;READ CONTROL FILE
	JP	STAT	;PRINT STATISTICS
;
;  ROUTINE TO READ IN A CONTROL TABLE
;
CTLRD:
	CALL	RDOPEN	;OPEN FILE FOR READING
	LD	HL,CTLTBL	;PT TO CONTROL TABLE
LUP:
	CALL	READMA	;READ NEXT CHAR
	LD	DE,0	;SET VALUE = 0
NUMLUP:
	CP	1AH	;ERROR IF EOF ENCOUNTERED
	JR	Z,TERMF
	CP	','	;DONE WITH NUMBER IF COMMA FOUND
	JR	Z,STRDE
	CP	'9'+1	;CHECK FOR DIGIT
	JR	C,NUM	;PROCESS IF SO
	SUB	7	;ADJUST FOR 'A'-'F'
NUM:
	SUB	'0'	;CONVERT HEX ASCII TO BINARY
	EX	DE,HL	;VALUE IN HL
	ADD	HL,HL	;*2
	ADD	HL,HL	;*4
	ADD	HL,HL	;*8
	ADD	HL,HL	;*16
	ADD	A,L	;ADD IN NEW VALUE
	LD	L,A
	EX	DE,HL	;VALUE BACK IN DE
	CALL	READMA	;READ NEXT CHAR
	JR	NUMLUP	;CONTINUE
;
;  STORE THE ADDRESS ACCUMULATED IN DE INTO THE CONTROL TABLE
;
STRDE:
	LD	(HL),E	;STORE ADDRESS
	INC	HL
	LD	(HL),D
	INC	HL
	CALL	READMA	;READ CONTROL MODE CHAR
	LD	(HL),A	;STORE IT
	INC	HL	;PT TO NEXT CONTROL TABLE ENTRY
	JR	LUP
;
;  STORE ENDING 0FFFFH IN CONTROL TABLE
;
TERMF:
	LD	(HL),0FFH
	INC	HL
	LD	(HL),0FFH
	RET
;
;COMMAND:  ;
;  COMMENT ROUTINE.  IT ADDS OR LISTS COMMENTS
;
CMNT:
	CALL	AREACK	;VERIFY THAT COMMENT TABLE EXISTS
	LD	HL,INBUF+3	;PT TO CHAR AFTER COMMAND
	LD	A,(HL)	;GET IT
	CP	0DH	;DONE?
	JP	Z,LSTCMT	;YES, SO LIST COMMENTS
	CP	'O'		;LOOK FOR 'ON/OFF' SWITCH
	JR	NZ,CMNT1
	INC	HL
	LD	A,(HL)		;SECOND CHARACTER OF THE COMMENT
	SBC	A,'F'		;CREATE A 0 FOR 'OFF'
	JR	Z,CMNT2
	CP	'N'-'F' 	;LOOK FOR AN 'N' (FOR 'ON')
	JP	NZ,WHAT
CMNT2:
	LD	(XCSW),A	;TURN OFF COMMENTS
	JP	GETCMD
;
;  PROCESS NEW COMMENT ENTRY
;
CMNT1:
	CALL	CNVRT	;GET ADDRESS IN DE
	INC	HL	;PT TO NEXT CHAR
	CP	0DH	;IF DONE, WE DELETE COMMENT
	JP	Z,ONECMT
	CP	' '	;<SP> OR ',' SAYS TEXT FOLLOWS
	JR	Z,CMNT0
	CP	','
	JP	NZ,WHAT ;ERROR IF NOT <CR>, <SP>, OR ','
CMNT0:
	PUSH	HL	;SAVE PTR TO NEXT CHAR
	CALL	CMCHK	;CHECK FOR COMMENT ALREADY AT ADDRESS IN DE
	JR	C,ADDCMT	;IF NOT, JUST ADD COMMENT
	CALL	DELCMT	;IF SO, FIRST DELETE EXISTING COMMENT
;
;  ADD COMMENT TO COMMENT TABLE
;
ADDCMT:
	POP	HL	;GET PTR
	PUSH	HL
	LD	A,(HL)	;CHECK FOR ANY TEXT
	CP	0DH	;IF NONE, OLD COMMENT IS JUST DELETED
	JP	Z,GETCMD
	LD	HL,(COMEND)	;PT TO END OF COMMENT TABLE
	LD	(HL),E	;SAVE NEW ADDRESS OF COMMENT
	INC	HL
	LD	(HL),D
	INC	HL
	POP	DE	;PT TO FIRST CHAR OF COMMENT
	LD	B,0	;INIT CHAR COUNT TO ZERO
	PUSH	HL	;SAVE ADDRESS TO CHAR COUNT OF COMMENT
;
;  SAVE TEXT OF COMMENT
;
STRTXT:
	INC	HL	;PT TO POSITION TO STORE AT
	LD	A,(DE)	;GET COMMENT TEXT
	LD	(HL),A	;STORE IT
	INC	DE	;PT TO NEXT
	INC	B	;INCR CHAR COUNT
	LD	A,(DE)	;CHECK FOR DONE
	CP	0DH	;DONE IF <CR>
	JR	NZ,STRTXT	;CONTINUE IF NOT <CR>
	INC	HL	;PT TO ADDRESS AFTER <CR>
	LD	(COMEND),HL	;SET PTR TO END OF COMMENT TABLE
	LD	(HL),0FFH	;STORE 0FFFFH AS NEXT ENTRY
	INC	HL
	LD	(HL),0FFH
	POP	HL	;GET PTR TO COMMENT CHAR COUNT
	LD	(HL),B	;SAVE CHAR COUNT
	JP	GETCMD
;
;  CHECK FOR A COMMENT AT THE ADDRESS IN DE
;   MATCH: CARRY IS OFF (NC CONDITION)
;
CMCHK:
	LD	HL,(COMST)	;PT TO START OF COMMENT TABLE
CMCHK1:
	LD	A,(HL)	;CHECK ADDRESS FOR 0FFFFH
	INC	HL
	AND	(HL)
	DEC	HL
	INC	A	;A=0 IF SO
	SCF		;PREP FOR ERROR RETURN
	RET	Z	;NOT FOUND IF A=0
	INC	HL	;PT TO ADDRESS HIGH
	LD	A,D	;GET TARGET ADDRESS IN DE
	CP	(HL)	;COMPARE AGAINST THAT STORED
	DEC	HL	;PT TO ADDRESS LOW
	JR	NZ,NXTC ;IF NOT A MATCH, CONTINUE
	LD	A,E	;COMPARE LOW BYTES
	CP	(HL)
	RET	Z	;THERE IS A COMMENT AT THIS ADDRESS, SO CARRY=1
NXTC:
	INC	HL	;PT TO CHAR COUNT
	INC	HL
	LD	A,(HL)	;GET CHAR COUNT
	CALL	SKIP	;SKIP TO NEXT COMMENT
	INC	HL	;PT TO LOW BYTE OF NEXT COMMENT
	JP	CMCHK1
;
;  DUMP COMMENT TABLE FROM A GIVEN ADDRESS FORWARD
;
ONECMT:
	CALL	CMCHK	;FIND COMMENT REFD IN DE
	JR	LSTAGN
;
;  DUMP ENTIRE COMMENT TABLE
;
LSTCMT:
	LD	HL,(COMST)	;PT TO FIRST COMMENT
LSTAGN:
	CALL	BRKCHK	;CHECK FOR ABORT
	LD	E,(HL)	;GET ADDRESS OF COMMENT IN DE
	INC	HL
	LD	D,(HL)
	INC	HL
	LD	A,D	;CHECK FOR 0FFFFH AS END OF TABLE
	AND	E
	INC	A	;A=0 IF SO
	JP	Z,GETCMD	;DONE IF SO
	EX	DE,HL	;VALUE IN HL
	CALL	PVALUE	;PRINT IT
	EX	DE,HL	;VALUE IN DE, PTR TO COMMENT CHAR COUNT IN HL
	LD	A,';'	;PRINT SEMICOLON BEFORE COMMENT
	CALL	COUT
	LD	B,(HL)	;GET CHAR COUNT IN B
TEXT:
	INC	HL	;PT TO COMMENT CHAR
	LD	A,(HL)	;GET AND PRINT IT
	CALL	COUT
	DJNZ	TEXT	;CONTINUE UNTIL DONE
	CALL	CRLF	;NEW LINE
	INC	HL	;PT TO ADDRESS OF NEXT COMMENT
	JR	LSTAGN	;CONTINUE
;
;  DELETE AN EXISTING COMMENT WHOSE ADDRESS IS IN DE; HL PTS TO CMT TABLE
;
DELCMT:
	LD	A,(HL)	;CHECK FOR END OF COMMENT TABLE
	INC	HL
	AND	(HL)
	INC	A	;A=0 IF AT END
	RET	Z
	DEC	HL	;PT TO ADDRESS IN CURRENT COMMENT
	PUSH	DE	;SAVE ADDRESS TO DELETE
	LD	D,H	;SAVE ADDRESS OF CURRENT COMMENT IN DE
	LD	E,L
	INC	HL	;PT TO CHAR COUNT OF CURRENT COMMENT
	INC	HL
	LD	A,(HL)	;GET IT IN A
	CALL	SKIP	;SKIP TO NEXT COMMENT
	INC	HL	;PT TO ITS ADDRESS
	LD	B,0	;INIT TO NOT DONE FOR LOOP
;
;  COPY (HL) TO (DE) UNTIL FFFFH IS ENCOUNTERED
;
SHFTCT:
	LD	A,(HL)	;GET CHAR
	LD	(DE),A	;PUT CHAR
	INC	HL	;PT TO NEXT
	INC	DE
	LD	C,A	;DONE IF BC=0FFFFH
	AND	B
	INC	A	;A=0 IF DONE
	LD	B,C
	JR	NZ,SHFTCT	;CONTINUE UNTIL TWO SUCCESSIVE FF'S FOUND
	EX	DE,HL	;SET END OF COMMENT TABLE
	DEC	HL
	DEC	HL
	LD	(COMEND),HL
	POP	DE
	RET	
;
;  CHECK TO SEE THAT AREA FOR COMMENTS WAS DEFINED (START <> 0) AND
;    ABORT WITH ERROR MESSAGE IF NOT
;
AREACK:
	LD	HL,(COMST)	;HL=START ADDRESS
	LD	A,H
	OR	L
	RET	NZ		;ERROR IF ZERO
	CALL	PSTRNG
	DEFB	'++ COMMAND IGNORED ++',0DH
	DEFB	0AH,'++ Issue ''UNNNN'' to tell '
	DEFB	'DASM to use address '
	DEFB	'NNNN',0DH,0AH,'as the start '
	DEFB	'of the comments table ++',0DH
	DEFB	0AH,0
	JP	GETCMD
;
;COMMAND:  U
;  DEFINE THE COMMENTS AREA
;
UAREA:
	LD	HL,INBUF+3	;CHECK ARGS
	LD	A,(HL)
	CP	0DH	;ERROR IF JUST <CR>
	JP	Z,WHAT
	CP	'.'	;ERROR IF SYMBOL
	JP	Z,WHAT
	CALL	CNVRT	;CONVERT TO NUMBER IN DE
	EX	DE,HL	;... IN HL
	LD	A,H	;CHECK FOR WITHIN RANGE
	CP	(SYMTAB+600H).SHR.8	;THIS ALLOWS 600H BYTES FOR SYM TBL
	JR	C,UAREA0	;ERROR IF LESS
	LD	(COMST),HL	;SET START AND END OF TABLE
	LD	(COMEND),HL
	LD	(HL),0FFH	;SET ENDING 0FFFFH IN TABLE
	INC	HL
	LD	(HL),0FFH
	JP	GETCMD
UAREA0:
	CALL	PSTRNG	;PRINT ERROR MESSAGE
	DEFB	'NO!! Address is less than '
	DEFB	0
	LD	HL,SYMTAB+600H
	LD	L,0
	CALL	PVALUE
	CALL	CRLF
	JP	GETCMD
;
;  HANDLE SYMBOLS FOR THE DISASSEMBLER; ADDRESS IN PC
;    IF A SYMBOL EXISTS AT THIS ADDRESS, PRINT IT
;
HSYM:
	PUSH	DE
	PUSH	HL
	LD	A,1	;ENABLE DISK OUTPUT
	LD	(WRTENAB),A
	LD	HL,(PC) ;GET ADDRESS OF PC
	EX	DE,HL	;... IN DE
	CALL	SYMSCH	;LOOK FOR SYMBOL
	JP	C,RESUME	;GOTO RESUME IF NO SYMBOL
	LD	C,B	;GET CHAR COUNT OF SYMBOL INTO C
	PUSH	HL	;SAVE PTR TO IT
;
;  CHECK TO SEE THAT SYMBOL CONTAINS NO + OR -; DON'T PRINT IF IT DOES
;
HSYM0:
	LD	A,(HL)	;GET CHAR
	CP	'+'	;CHECK IT
	JR	Z,HSYM1
	CP	'-'
	JR	Z,HSYM1
	INC	HL	;PT TO NEXT
	DEC	C	;CONTINUE TO END OF SYMBOL
	JR	NZ,HSYM0
	POP	HL	;PT TO SYMBOL
	CALL	PRNT		;PRINT THE SYMBOL
	LD	A,':'		;.. AND A FOLLOWING COLON
	CALL	COUT
	CALL	TAB	;PRINT THE TAB
	CALL	PDERTN	;PRINT THE ADDRESS AS A COMMENT (ADR IN DE)
	CALL	CRLF	;NEW LINE
	JR	RESUME	;CONTINUE
HSYM1:
	POP	HL
RESUME:
	XOR	A		;PRINT ADDRESS OF PC ON CRT
	LD	(WRTENAB),A	;.. BUT NOT INTO THE FILE
	CALL	SPACE		;<SP> OVER
	CALL	SPACE
	LD	HL,(PC) 	;PRINT PC VALUE
	CALL	PVALUE
	LD	A,1		;REENABLE WRITE OF MNEMONIC
	LD	(WRTENAB),A
	CALL	TAB		;TAB FOR FOLLOWING MNEMONIC
	POP	HL
	POP	DE
	RET	
;
;   BUILD A SYMBOL IN INBUF FOR THE VALUE IN DE
;
BLDSYM:
	LD	HL,INBUF	;PT TO INBUF
	LD	(HL),'L'	;STORE LEADING L
	INC	HL		;PT TO NEXT CHAR
	LD	A,D		;GET VALUE IN DE
	CALL	ACCTOASC	;STORE AS ASCII CHARS IN BUFFER
	LD	A,E
	CALL	ACCTOASC
	LD	HL,INBUF	;PT TO SYMBOL
	LD	B,5		;SYMBOL IS 5 CHARS LONG
;
;  INSERT A SYMBOL ALPHABETICALLY INTO TABLE
;
INSERT:
	CALL	PLCSYM	;FIND SYMBOL
	JR	C,NEWSYM	;PROCESS AS NEW IF NOT FOUND
	LD	(HL),E	;IF FOUND, SET NEW ADDRESS FOR IT
	INC	HL
	LD	(HL),D
	RET	
;
;  INSERT NEW SYMBOL INTO TABLE; LOCATION TO INSERT AT PTED TO BY HL
;
NEWSYM:
	PUSH	HL
	PUSH	DE
	PUSH	BC
	LD	HL,(SYMEND)	;MOVE THE TABLE BY LENGTH+3
	LD	D,H	;DE PTS TO END OF SYMBOL TABLE
	LD	E,L
	LD	A,B	;LENGTH OF SYMBOL IN A
	ADD	A,3	;LENGTH OF SYMBOL + 3
	ADD	A,L	;PT TO NEW END OF TABLE
	LD	L,A
	LD	A,H
	ADC	A,0
	LD	H,A
	LD	(SYMEND),HL	;NEW END OF SYMBOL TABLE
	INC	HL	;PT TO LENGTH OF SYMBOL AFTER LAST ONE
	INC	HL
	LD	(HL),0	;SET THIS TO ZERO TO MARK END OF TABLE
	DEC	HL
	DEC	HL
	LD	B,H	;ADDRESS OF LAST BYTE IN BC
	LD	C,L
	LD	HL,(SYMRKR)	;ADDRESS OF REV DEST TO MOVE TO IN HL
;
;  EXPAND THE TABLE UNTIL SPACE IS MADE AT THE NEW SPOT
;
LUP3:
	LD	A,E	;AT DESTINATION?
	CP	L
	JR	NZ,AHD
	LD	A,D
	CP	H
	JR	Z,STICKAD	;DONE IF SO
AHD:
	DEC	DE	;COPY BACKWARDS (DE) TO (BC)
	DEC	BC
	LD	A,(DE)
	LD	(BC),A
	JR	LUP3
;
;  ENTER THE ADDRESS AND LENGTH
;
STICKAD:
	POP	BC
	POP	DE
	LD	(HL),E	;STORE ADDRESS OF SYMBOL
	INC	HL
	LD	(HL),D
	INC	HL
	LD	(HL),B	;STORE LENGTH OF SYMBOL
	POP	DE
;
;  STORE THE SYMBOL STRING
;
STICKSM:
	INC	HL
	LD	A,(DE)
	LD	(HL),A
	INC	DE
	DJNZ	STICKSM
	RET	
;
;  FIND SPOT FOR NEW SYMBOL PTED TO BY HL, VALUE IN DE, B=LENGTH OF SYMBOL
;    RETURN: C=0 FOR MTCH, HL=SYMBOL
;
PLCSYM:
	PUSH	DE	;SAVE VALUE
	PUSH	HL	;SAVE ADDRESS OF SYMBOL
	LD	HL,SYMTAB	;PT TO SYMBOL TABLE
ANTHR:
	POP	DE	;GET SYMBOL ADDRESS IN DE
	PUSH	DE
	INC	HL	;PT TO SYMBOL CHAR COUNT
	INC	HL
	PUSH	HL
	LD	A,(HL)	;GET CHAR COUNT
	INC	HL	;PT TO FIRST CHAR
	OR	A	;CHECK FOR END OF SYMBOL TABLE
	JR	Z,NONE	;GOTO NONE IF AT END OF TABLE
	CP	B	;COMPARE SYMBOL LENGTHS
	JR	C,LESS	;NO MATCH IF NOT SAME LENGTH
	JR	NZ,NTLESS
	LD	C,A	;SYMBOL LENGTH IN C
	CALL	CHKSTG	;COMPARE (DE) TO (HL)
	JR	Z,FOUND
	JR	C,NONE
;
;  TARGET SYMBOL GOES BEHIND CURRENT SYMBOL
;
LATER:
	POP	HL	;GET ADDRESS OF SYMBOL TABLE SYMBOL
	LD	A,(HL)
	INC	HL
	CALL	SKIP	;SKIP TO NEXT
	JR	ANTHR
;
;  MATCH OF SYMBOLS
;
FOUND:
	POP	HL
	DEC	HL
	DEC	HL
	POP	DE
	POP	DE
	OR	A	;RET WITH CARRY CLEAR FOR MATCH
	RET	
;
;  CHECK SHORTER STRING FOR PARTIAL MATCH
;
LESS:
	LD	C,A
	CALL	CHKSTG
	JR	NC,LATER
	JR	NONE
NTLESS:
	LD	C,B
	CALL	CHKSTG
	JR	Z,NONE
	JR	NC,LATER
;
;  THERE IS NO SYMBOL FOR THIS VALUE, SO THIS VALUE SHOULD GO AT HL
;
NONE:
	POP	HL
	DEC	HL
	DEC	HL
	LD	(SYMRKR),HL	;SET MARKER
	POP	HL
	POP	DE
	SCF			;SET CARRY FOR NO MATCH
	RET	
;
;  SEARCH THE SYMBOL TABLE FOR AN ENTRY WHOSE VALUE IS DE
;    MATCH: C=0
;
SYMSCH:
	LD	HL,SYMTAB	;PT TO SYMBOL TABLE
;
;  (HL) IS START OF SYMBOL; (B) IS LENGTH
;
MORE:
	LD	A,(HL)	;GET AND COMPARE SYMBOL TABLE VALUES
	INC	HL
	CP	E
	JR	NZ,SKPOVR
	LD	A,(HL)
	CP	D
	JR	Z,FNDSYM
;
;  GOTO NEXT SYMBOL
;
SKPOVR:
	INC	HL	;CHECK CHAR COUNT FOR DONE
	LD	A,(HL)	;0 IF DONE
	OR	A
	SCF		;SET CARRY FOR NO MATCH IF SO
	RET	Z
	INC	HL	;PT TO NEXT SYMBOL
	ADD	A,L
	LD	L,A
	JR	NC,MORE
	INC	H
	JR	MORE
;
;  RETURN WITH NO CARRY AND LENGTH IN B IF MATCHED
;
FNDSYM:
	INC	HL
	LD	A,(HL)
	INC	HL
	LD	B,A
	OR	A	;MATCH
	RET	NZ
	SCF		;NO MATCH
	RET	
;
;COMMAND:  E
;  PLACE A SYMBOL IN THE SYMBOL TABLE
;
ENTER:
	LD	HL,INBUF+3	;CHECK FOR CHARS AFTER THE E
	CALL	CNVRT		;GET VALUE
	LD	A,(HL)	;CHECK FOR ERROR
	CP	' '	;MUST BE FOLLOWED BY <SP> OR ','
	JR	Z,ENTER0
	CP	','
	JP	NZ,WHAT
;
;  GET SYMBOL
;
ENTER0:
	INC	HL	;PT TO SYMBOL
	LD	A,(HL)	;GET '.'
	CP	'.'	;MUST BE '.'
	JP	NZ,WHAT
	PUSH	DE		;SAVE THE SYMBOL'S VALUE
	PUSH	HL		;SAVE THE BUFFER PTR
	CALL	SYMSCH		;RETURN WITH C=0 FOR MATCH
				;.. B=LENGTH   HL=START OF STRING
	JR	C,ENTER1		;NOTHING TO DELETE
	PUSH	HL
	CALL	CRLF		;PRINT MESSAGE THAT SYMBOL WAS KILLED
	CALL	PRNT
	CALL	PSTRNG
	DEFB	' was Killed',0DH,0AH,0
	POP	HL
	DEC	HL
	DEC	HL
	DEC	HL
	CALL	KILL0	;KILL SYMBOL
ENTER1:
	POP	HL
	PUSH	HL
	CALL	LNGTH	;COMPUTE LENGTH OF SYMBOL IN B
	POP	DE
	LD	A,B	;CHECK FOR SYMBOL TOO LONG
	CP	SYMMAX+1
	JR	C,ENTER2
	PUSH	HL
	LD	BC,SYMMAX	;SET TO MAX LENGTH
	LD	H,D	;HL=DE
	LD	L,E
	INC	HL	;ADD 1 FOR 1ST CHAR
	ADD	HL,BC
	LD	(HL),0	;TERMINATE SYMBOL
	LD	B,C	;B=SYMMAX
	POP	HL
ENTER2:
	POP	DE
	CALL	INSERT	;INSERT SYMBOL INTO SYMBOL TABLE
	JP	GETCMD
;
;COMMAND:  K
;   DELETE A SYMBOL FROM THE TABLE
;
KILL:
	LD	HL,INBUF+3	;CHECK FOR SYMBOL SPECIFIED
	LD	A,(HL)		;MUST BE '.'
	CP	'.'
	JP	NZ,WHAT
	CALL	LNGTH	;GET LENGTH IN B
	CALL	PLCSYM	;FIND SYMBOL PTED TO BY HL
	JP	C,WHAT	;ERROR IF NOT FOUND
	CALL	KILL0	;KILL IT
	JP	GETCMD
;
;  KILL THE SYMBOL WHOSE VALUE IS PTED TO BY HL
;
KILL0:
	LD	B,H	;SAVE PTR IN BC
	LD	C,L
	INC	HL
	INC	HL
	LD	A,(HL)	;GET THE LENGTH OF THE SYMBOL
	INC	HL
	CALL	SKIP	;SKIP TO NEXT
	EX	DE,HL	;DE PTS TO NEXT SYMBOL
	LD	HL,(SYMEND)	;SHIFT THE SYMBOL TABLE DOWN TO DELETE SYM
LUP4:
	LD	A,E	;SHIFT COMPLETE?
	CP	L
	JR	NZ,AHD1
	LD	A,D
	CP	H
	JR	Z,DEAD
AHD1:
	LD	A,(DE)	;COPY DOWN
	LD	(BC),A
	INC	BC
	INC	DE
	JR	LUP4
;
;  THE SYMBOL IS DEAD -- SET NEW END OF SYMBOL TABLE
;
DEAD:
	LD	H,B
	LD	L,C
	LD	(SYMEND),HL	;SET END
	INC	HL
	INC	HL
	LD	(HL),0	;SET END OF TABLE MARKER
	RET	
;
;  SCAN SYMBOL STARTING AT (HL) AND RETURN WITH LENGTH IN B, PTR TO FIRST
;    CHAR OF SYMBOL IN HL, AND PTR TO CHAR AFTER LAST CHAR IN SYMBOL IN DE
;
LNGTH:
	INC	HL	;PT TO FIRST CHAR
	LD	B,0	;INIT LENGTH
	PUSH	HL
CHAROK:
	LD	A,(HL)	;GET CHAR
	INC	HL	;PT TO NEXT
	INC	B	;INCR LENGTH
	CP	'+'	;CHECK FOR END OF SYMBOL MARK
	JR	Z,CHAROK
	CP	'-'
	JR	Z,CHAROK
	CP	'0'
	JR	C,ILLSYM
	CP	'9'+1
	JR	C,CHAROK
	CP	'A'
	JR	C,ILLSYM
	CP	'Z'+1
	JR	C,CHAROK
;
;  AN ILLEGAL CHARACTER FOUND IN A SYMBOL SCAN, SO SCAN IS DONE
;
ILLSYM:
	DEC	B	;COMPENSATE FOR COUNT
	JP	Z,WHAT	;ERROR IF NO SYMBOL CHARS
	DEC	HL	;BACK UP
	EX	DE,HL	;PTR TO NEXT CHAR IN DE
	POP	HL	;PT TO FIRST CHAR IN HL
	RET	
;
;  CONVERT THE ACCUMULATOR TO HEX ASCII IN MEMORY PTED TO BY HL (2 BYTES)
;
ACCTOASC:
	PUSH	AF
	CALL	HINIB	;CONVERT HIGH NYBBLE
	LD	(HL),A	;STORE IT
	INC	HL	;PT TO NEXT
	POP	AF
	CALL	LONIB	;CONVERT LOW NYBBLE
	LD	(HL),A	;STORE IT
	INC	HL	;PT TO NEXT
	RET	
;
;  CONVERT THE HIGH NIBBLE OF A TO ASCII CHAR
;
HINIB:
	RRA	;ROTATE HIGH NYBBLE TO LOW NYBBLE
	RRA
	RRA
	RRA
;
;  CONVERT THE LOW NYBBLE OF A TO ASCII CHAR
;
LONIB:
	AND	0FH	;MASK OUT NEW HIGH NYBBLE
	CP	10	;CHECK FOR DIGIT
	JR	C,AHD2	;SKIP IF SO
	ADD	A,7	;ADD OFFSET OF 7 FOR '9' TO 'A'
AHD2:
	ADD	A,'0'	;CONVERT TO ASCII IN A
	RET	
;
;  PRINT THE HEX CHARACTERS FOR THE VALUE IN A
;
PHEX:
	PUSH	AF
	CALL	HINIB	;PRINT HIGH NYBBLE
	CALL	COUT
	POP	AF
	CALL	LONIB	;PRINT LOW NYBBLE
	JP	COUT
;
;  PRINT THE 4 HEX CHARACTERS FOR CONTENTS OF HL
;
PVALUE:
	LD	A,H	;PRINT HIGH BYTE
	CALL	PHEX
	LD	A,L	;PRINT LOW BYTE
	CALL	PHEX
;
;  PRINT A <SP>
;
SPACE:
	LD	A,' '	;PRINT <SP>
	JP	COUT
;
;  READ HEX ASCII FROM COMMAND LINE AND CONVERT AND PLACE IN (DE)
;
CNVRT:
	LD	A,(HL)	;GET FIRST CHAR
	CP	'.'	;IT IS A SYMBOL IF '.'
	JR	Z,ITSASYM
	LD	DE,0	;INIT VALUE TO ZERO
AGAIN:
	LD	A,(HL)	;GET CHAR
	CP	'0'	;IN RANGE?
	RET	C	;DONE IF NOT
	CP	'9'+1	;RANGE?
	JR	C,NUMER ;OK IF SO
	CP	'A'	;RANGE?
	RET	C	;DONE IF NOT
	CP	'F'+1	;RANGE?
	RET	NC	;DONE IF NOT
	SUB	7	;CONVERT FOR 'A'-'F'
NUMER:
	SUB	'0'	;CONVERT FROM ASCII TO BINARY
	EX	DE,HL	;HL=VALUE
	ADD	HL,HL	;*2
	ADD	HL,HL	;*4
	ADD	HL,HL	;*8
	ADD	HL,HL	;*16
	ADD	A,L	;ADD IN NEW NYBBLE
	LD	L,A
	EX	DE,HL	;DE=VALUE
	INC	HL	;PT TO NEXT CHAR
	JR	AGAIN	;CONTINUE
;
;  EVALUATE THE SYMBOL IN MEMORY AND RETURN WITH VALUE IN DE
;
ITSASYM:
	CALL	LNGTH	;DETERMINE LENGTH OF SYMBOL
	PUSH	DE
	CALL	PLCSYM	;FIND IT IN TABLE
	JP	C,WHAT	;ERROR IF NOT FOUND
	LD	E,(HL)	;PUT ITS VALUE IN DE
	INC	HL
	LD	D,(HL)
	POP	HL
	LD	A,(HL)
	RET	
;
;  OPEN A FILE FOR READING
;
RDOPEN:
	PUSH	HL
	LD	HL,0100H	;SET DMA TO 100H
	LD	(DMAPTR),HL
	XOR	A		;SET NEXT RECORD FIELD TO 0
	LD	(FCBNR),A
	LD	DE,FCB		;PT TO FCB
	LD	C,0FH		;OPEN THE FILE
	CALL	BDOS
	POP	HL
	INC	A		;FILE FOUND?
	RET	NZ		;RET IF SO
	CALL	PSTRNG		;ERROR IF NOT
	DEFB	'  File Not Found',0DH,0AH,0
	EX	(SP),HL 	;SAVE HL ON STACK
	POP	HL		;RESTORE HL
	RET
;	JP	GETCMD	;OLD ERROR RETURN
;
;  READ NEXT BYTE FROM DMA BUFFER AND RETURN IT IN A
;
READMA:
	PUSH	HL	;SAVE HL
	LD	HL,(DMAPTR)	;PT TO NEXT BYTE
	LD	A,H	;BEYOND END OF BUFFER?
	CP	1	;1 IF SO
	JR	NZ,NOTREAD	;IF NOT, THEN GET THE BYTE
	PUSH	BC	;SAVE BC, DE
	PUSH	DE
	LD	DE,FCB	;PT TO FCB
	LD	C,14H	;READ RECORD INTO DMA ADDRESS
	CALL	BDOS
	OR	A	;SET FLAG FOR ERROR
	POP	DE	;RESTORE REGS
	POP	BC
	LD	HL,RECLEN	;PT TO FIRST BYTE OF BUFFER
	JR	NZ,ERROR	;ERROR IF EOF ENCOUNTERED
NOTREAD:
	LD	A,(HL)	;GET NEXT CHAR IN A
	INC	HL	;PT TO CHAR AFTER
	LD	(DMAPTR),HL	;SET PTR FOR LATER USE
	POP	HL	;RESTORE HL
	RET	
ERROR:
	CP	3
	JR	C,RDDMA0
	CALL	PSTRNG
	DEFB	'++ Unexpected EOF ++',0DH,0AH
	DEFB	0
	JP	GETCMD
;
;  AT EOF ... SET ^Z AS RESPONSE CHAR FROM READ
;
RDDMA0:
	LD	A,1AH
	LD	(HL),A
	JR	NOTREAD
;
;  OPEN FILE PTED TO BY FCB FOR OUTPUT
;
OPEN:
	PUSH	HL
	LD	DE,FCB	;ERASE IT FIRST
	LD	C,13H
	CALL	BDOS
	LD	DE,FCB	;NOW CREATE IT
	LD	C,16H
	CALL	BDOS
	INC	A	;ERROR IN CREATING IT?
	JP	Z,WHAT	;SAY SO (NO ROOM IN DIR)
	XOR	A	;SET RECORD FIELD TO ZERO
	LD	(FCBNR),A
	LD	HL,RECLEN	;SET DMA ADDRESS
	LD	(DMAPTR),HL
	POP	HL
	RET	
;
;  WRITE THE NEXT RECORD TO OPEN FILE
;
NXTRCRD:
	LD	DE,FCB	;WRITE IT
	LD	C,15H
	CALL	BDOS
	OR	A	;ERROR?
	JR	NZ,WRTERR
	LD	DE,FCB	;CLOSE THE FILE
	LD	C,10H
	CALL	BDOS
	INC	A	;ERROR IN CLOSING?
	RET	NZ
	CALL	PSTRNG	;SAY SO IF SO
	DEFB	'++ Close Error ++',0DH,0AH,0
	JP	GETCMD
;
;  AN ERROR OCCURRED DURING A WRITE RECORD ATTEMPT
;
WRTERR:
	CALL	PSTRNG
	DEFB	'++ Write Error ++',0DH,0AH,0
;
;  WRITE INTO THE DMA BUFFER AND WRITE TO DISK WHEN IT FILLS
;    CHAR TO WRITE PASSED IN A
;
WRTFILE:
	PUSH	HL
	LD	HL,(DMAPTR)	;GET PTR
	LD	(HL),A	;STORE NEXT CHAR
	INC	L	;PT TO NEXT
	LD	(DMAPTR),HL	;SET NEXT DMA
	POP	HL
	RET	NZ	;IF L REACHED ZERO, BUFFER WAS FULL; RET IF NZ
	PUSH	BC	;WRITE RECORD TO DISK AND REINIT DMA PTR
	PUSH	DE
	PUSH	HL
	LD	DE,FCB	;DO THE WRITE
	LD	C,15H
	CALL	BDOS
	OR	A	;ERROR?
	JR	NZ,WRTERR
	LD	HL,RECLEN	;RESET DMA PTR
	LD	(DMAPTR),HL
	POP	HL
	POP	DE
	POP	BC
	RET	
;
;  PRINT COMMENT IF PTED TO BY XCPTR
;
DCRLF:
	LD	HL,(XCPTR)
	LD	A,H
	OR	L	;LOOK FOR A COMMENT ADDRESS
	JR	Z,DCRLF3
	CALL	TAB	;TABULATE COMMENT
	LD	B,(HL)	;GET CHAR COUNT
	XOR	A	;CHECK FOR NO COMMENT
	OR	B
	JR	Z,DCRLF2
DCRLF1:
	INC	HL	;OUTPUT COMMENT
	LD	A,(HL)
	CALL	COUT
	DJNZ	DCRLF1
DCRLF2:
	LD	HL,0	;SET NO COMMENT NOW
	LD	(XCPTR),HL
DCRLF3:
	LD	(RPLPTR),HL	;SET RPLPTR=0
;
;  OUTPUT <CR> <LF>
;
CRLF:
	LD	A,0DH
	CALL	COUT
	LD	A,0AH
	JP	COUT
;
;  PRINT THE PROMPT
;
PRTSTAR:
	LD	A,'*'
;
;  PRINT THE CHARACTER IN A ON CON: AND/OR DISK
;    THE FOLLOWING FLAGS TAKE EFFECT:
;	HUSH (QUIET MODE) -- IF =0, CON: OUTPUT, ELSE NO CON: OUTPUT
;	FOPEN (FILE OPEN) AND WRTENAB (WRITE ENABLE) -- IF BOTH <>0, DISK
;		OUTPUT
;	CNTENAB (COUNT ENABLE) -- IF <>0, ENABLE <LF> COUNT (LCTR)
;
COUT:
	PUSH	AF	;SAVE REGS
	PUSH	BC
	PUSH	DE
	PUSH	HL
	LD	E,A	;CHAR IN E
	PUSH	DE	;PREP TO PRINT CHAR
	LD	C,2	;USE BDOS OUTPUT
	LD	A,(HUSH)	;QUIET MODE?
	OR	A	;0=YES
	CALL	Z,BDOS	;PRINT THE CHAR IF NOT QUIET MODE
	POP	DE
	LD	A,(FOPEN)	;GET FILE OPEN FLAG
	LD	HL,WRTENAB	;PT TO FILE WRITE ENABLED FLAG
	AND	(HL)		;IF BOTH ENABLED, WRITE CHAR TO DISK ALSO
	LD	A,E		;CHAR IN A, NOT ZERO FLAG = DISK OUTPUT
	CALL	NZ,WRTFILE	;WRITE TO DISK IF OK
	LD	A,E		;CHECK FOR <LF>
	CP	0AH
	JR	NZ,COUT1
	LD	A,(CNTENAB)	;DECREMENT THE LINE COUNT IF A <LF> WAS SENT
	OR	A		;CHECK IF COUNTING ENABLED
	JR	Z,COUT1
	LD	HL,LCTR ;PT TO LINE COUNT
	DEC	(HL)		;DECREMENT IT
COUT1:
	POP	HL		;RESTORE REGS AND EXIT
	POP	DE
	POP	BC
	POP	AF
	RET	
;
;  PROMPT AND READ A COMMAND LINE FROM THE KEYBOARD
;
PROMPT:
	CALL	PRTSTAR ;PRINT PROMPT
	LD	DE,INBUF	;PT TO INPUT LINE BUFFER
	LD	A,80	;SET BUFFER SIZE
	LD	(DE),A
	LD	C,10	;READ INTO BUFFER FCT
	CALL	BDOS
	LD	HL,INBUF+1	;PT TO CHAR COUNT READ
	LD	E,(HL)	;GET IT IN DE
	LD	D,0
	ADD	HL,DE	;PT TO AFTER LAST CHAR IN BUFFER
	INC	HL
	LD	(HL),0DH	;STORE ENDING <CR>
	LD	HL,INBUF+1	;PT TO CHAR COUNT OF BUFFER
;
;  CONVERT TO UPPER CASE
;
UPPR:
	INC	HL	;PT TO NEXT CHAR
	LD	A,(HL)	;GET IT
	CP	0DH	;DONE?
	JP	Z,CRLF
	CP	61H	;SMALL A?
	JR	C,UPPR	;OK IF LESS
	CP	7BH	;SMALL Z + 1?
	JR	NC,UPPR ;OK IF MORE
	AND	5FH	;CAPITALIZE
	LD	(HL),A	;PUT CHAR
	JR	UPPR	;CONTINUE
;
;  PRINT THE STRING: ADDR AT TOP OF STACK, TERMINATED BY 0
;
PSTRNG:
	XOR	A	;DISABLE QUIET MODE AND DISK OUTPUT
	LD	(WRTENAB),A
	LD	(HUSH),A
PSTG:
	EX	(SP),HL ;PT TO STRING IN HL AND SAVE OLD HL
LUP5:
	LD	A,(HL)	;OUTPUT CHARS
	CALL	COUT
	INC	HL	;PT TO NEXT
	LD	A,(HL)	;GET NEXT CHAR
	OR	A	;DONE?
	JR	NZ,LUP5
	INC	HL	;PT TO AFTER STRING
	EX	(SP),HL ;RESTORE HL AND SET NEW RET ADR
	RET	
;
;  INITIALIZE SPECIAL CONSTANTS SO CODE IS REENTRANT
;
INIT0:
	LD	A,IBUFLEN	;SIZE OF INPUT LINE BUFFER
	LD	(INBUF),A
	LD	A,INITDLEN-1	;INITIAL SIZE OF MEMORY DUMP
	LD	(DMPLEN),A
	LD	A,INITLCNT	;INITIAL SIZE OF LIST DISPLAY
	LD	(NLINES),A
	LD	(LCTR),A
	LD	HL,BLNGTH	;INITIAL CTL PTR
	LD	(NXTCTL),HL
	LD	HL,INITPC	;INITIAL VALUE OF PC
	LD	(DMPSTRT),HL
	LD	(DMPEND),HL
	LD	(PC),HL
	LD	HL,INITOFF	;INITIAL OFFSET
	LD	(OFFSET),HL
	LD	HL,INITELST	;INITIAL END OF LISTING VALUE
	LD	(ENDLST),HL
	LD	HL,COMTBL	;INITIAL POSITION OF COMMENTS
	LD	(COMST),HL
	LD	(COMEND),HL
	RET
;
;  INITIALIZE SYMBOL TABLE, CONTROL TABLE, AND COMMENTS TABLE
;  SET EOL
;
INIT:
	XOR	A	;A=0
	LD	(SYMTAB+2),A	;CLEAR SYMBOL TABLE BY SET CHAR COUNT OF
	LD	HL,SYMTAB	;... FIRST ENTRY TO ZERO
	LD	(SYMEND),HL	;SET END ADDRESS OF SYMBOL TABLE
	LD	A,0DH		;SET END OF INPUT LINE
	LD	(INBUF+3),A
	LD	HL,0FFFFH	;SET NO ENTRIES IN CONTROL TABLE
	LD	(CTLTBL),HL
	LD	A,'I'		;SET FOR INSTRUCTION MODE INITIALLY
	LD	(CTLTBL-1),A	;"PREVIOUS" CONTROL TABLE ENTRY IS SET TO 'I'
	LD	HL,COMTBL	;SET ADDRESS OF COMMENT TABLE
	LD	(COMST),HL	;START ADDRESS
	LD	(COMEND),HL	;END ADDRESS
	LD	(HL),0FFH	;CLEAR FIRST ENTRY TO NO COMMENT
	INC	HL
	LD	(HL),0FFH
	RET	
;
;  RETURN WITH ZERO IF STRINGS (DE) AND (HL) MATCH; LENGTH IS (C)
;
CHKSTG:
	LD	A,(DE)	;GET CHAR
	CP	(HL)	;COMPARE
	RET	NZ	;NO MATCH
	INC	DE	;PT TO NEXT
	INC	HL
	DEC	C	;COUNT DOWN
	JR	NZ,CHKSTG
	RET	
;
;  WATCH THE CONSOLE FOR A BREAK KEY AND ABORT IF SO
;
BRKCHK:
	PUSH	BC
	PUSH	DE
	PUSH	HL
	LD	C,0BH	;CHECK FOR KEY PRESS
	CALL	BDOS
	OR	A	;NONE IF ZERO
	JR	Z,AHD3
	LD	C,1	;GET NEW CHAR
	CALL	BDOS
	CP	3	;CHECK FOR ^C
	JR	Z,ABORT ;ABORT IF SO
	CALL	CRLF	;ELSE NEW LINE
	JP	GETCMD
ABORT:
	CALL	PSTRNG	;PROMPT USER
	DEFB	0DH,0AH,'Abort (Y/N)? ',0
	CALL	CHIN
	CP	'Y'
	JP	Z,WBOOT
	JP	GETCMD
AHD3:
	POP	HL
	POP	DE
	POP	BC
	RET	
;
;  CHECK FOR AN ASCII CHARACTER IN A
;    RETURN WITH ZERO TRUE AND NO CARRY FOR <CR>, <LF>
;    RETURN WITH NO CARRY IF PRINTABLE ASCII
;
ISITASC:
	CP	0DH
	RET	Z	;NO CARRY
	CP	0AH
	RET	Z	;NO CARRY
	CP	' '
	RET	C	;CARRY IF < <SP>
	CP	7FH
	CCF		;CARRY IF > 7FH
	RET
;
;  FILE TYPES
;
TPALL:
	DEFB	'ALL'	;FILE TYPE FOR ALL (CTL, SYM, DOC, COM, AND ASM) FILES
TPASM:
	DEFB	'ASM'	;ASM FILE TYPE
TPCOM:
	DEFB	'COM'	;COM FILE TYPE
TPCTL:
	DEFB	'CTL'	;CTL FILE TYPE
TPSYM:
	DEFB	'SYM'	;SYM FILE TYPE
TPDOC:
	DEFB	'DOC'	;DOC FILE TYPE
	DEFB	'.'
;
;  BUFFERS
;
RELEND:
	DEFS	2	;RELATIVE END ADDRESS OF COM FILE
DMPSTRT:
	DEFS	2	;STARTING ADDRESS OF DUMP (CURRENT ADDR ALSO)
DMPEND:
	DEFS	2	;ENDING ADDRESS OF DUMP
DMPLEN:
	DEFS	2	;NUMBER OF BYTES TO DUMP AT ONE TIME - 1
OFFSET:
	DEFS	2	;OFFSET VALUE
SYMEND:
	DEFS	2	;END OF SYMBOL TABLE
PC:
	DEFS	2	;CURRENT VALUE OF PC
ENDLST:
	DEFS	2	;END OF LISTING PTR
BIASED:
	DEFS	2	;BIASED OFFSET
COMST:
	DEFS	2	;START ADDRESS OF COMMENTS
COMEND:
	DEFS	2	;END ADDRESS OF COMMENTS
ADB:
	DEFS	1	;FLAG FOR DB BUILD (0=HEX, <>0=ASCII AND HEX)
FNDPC:
	DEFS	2	;TEMP PC FOR FIND FUNCTION
FNDADD:
	DEFS	2	;TEMP ADDRESS FOR FIND FUNCTION
ECNT:
	DEFS	1	;TEMP LINE COUNTER
NLINES:
	DEFS	1	;NUMBER OF LINES FOR LIST
LCTR:
	DEFS	1	;COUNTER FOR LINES
CNTENAB:
	DEFS	1	;ENABLE LINE COUNT IF <> 0, ELSE DISABLE LINE CNT
WRTENAB:
	DEFS	1	;OUTPUT TO FILE IS ENABLED IF <> 0, NOT IF 0
RPLPTR:
	DEFS	2	;MISC PTR
XCPTR:
	DEFS	2	;MISC PTR
XCSW:
	DEFS	1	;MISC PTR
FOPEN:
	DEFS	1	;FILE IS OPEN IF <> 0, NOT OPEN IF 0
HUSH:
	DEFS	1	;DON'T PRINT COMMAND RESULT (QUIET MODE) IF 0
NXTCTL:
	DEFS	2	;PTR TO NEXT CTL ENTRY
BLNGTH:
	DEFS	1	;BUFFER LENGTH
SYMRKR:
	DEFS	2	;SYMBOL MARKER
DMAPTR:
	DEFS	2	;PT TO DMA ADDRESS
ASCBLD:
	DEFS	1	;FLAG FOR A COMMAND (0=NOT A)
BUILD:
	DEFS	1	;FLAG FOR B COMMAND (0=NOT B)
OPCTP:
	DEFS	3
;
;  INPUT LINE BUFFER
;
INBUF:
	DEFS	1		;SIZE OF BUFFER
	DEFS	IBUFLEN+1	;SIZE OF INPUT LINE AND BUFFER CONTENTS
;
;  STACK AREA
;
	DEFS	40		;STACK SPACE
OLDST:
	DEFS	2		;OLD STACK PTR
;
	DEFS	1		;1 BYTE FOR INITIAL 'I' IN CONTROL TABLE
;
;  NEXT PAGE AFTER PROGRAM MARKS BEGINNING OF BUFFER AREAS
;
	ORG	$/100H*100H+100H
ENDALL		EQU	$
CTLTBL		EQU	ENDALL		;BEGINNING OF CONTROL TABLE
SYMTAB		EQU	CTLTBL+600H	;BEGINNING OF SYMBOL TABLE
INITOFF 	EQU	SYMTAB+2000H	;INITIAL OFFSET VALUE
COMTBL		EQU	INITOFF+4000H	;BEGINNING OF COMMENTS

	END	
G OF SYMBOL T