;___ROM_MONITOR_PROGRAM_______________________________________________________
;
;  ORIGINAL CODE BY:	ANDREW LYNCH (LYNCHAJ@YAHOO COM)	13 FEB 2007
;
;  MODIFIED BY : 	DAN WERNER 03 09.2009
;
;__REFERENCES_________________________________________________________________
; THOMAS SCHERRER BASIC HARDWARE TEST ASSEMBLER SOURCES FROM THE Z80 INFO PAGE
; INCLUDING ORIGINAL SCHEMATIC CONCEPT
; HTTP://Z80.INFO/Z80SOURC.TXT
; CODE SAMPLES FROM BRUCE JONES PUBLIC DOMAIN ROM MONITOR FOR THE SBC-200C
; HTTP://WWW.RETROTECHNOLOGY.COM/HERBS_STUFF/SD_BRUCE_CODE.ZIP
; INSPIRATION FROM JOEL OWENS "Z-80 SPACE-TIME PRODUCTIONS SINGLE BOARD COMPUTER"
; HTTP://WWW.JOELOWENS.ORG/Z80/Z80INDEX.HTML
; GREAT HELP AND TECHNICAL ADVICE FROM ALLISON AT ALPACA_DESIGNERS
; HTTP://GROUPS.YAHOO.COM/GROUP/ALPACA_DESIGNERS
; INTEL SDK-85 ROM DEBUG MONITOR
;_____________________________________________________________________________
;
#INCLUDE "std.asm"
;
BUFLEN	.EQU	40			; INPUT LINE LENGTH
;
;__MAIN_PROGRAM_______________________________________________________________
;
;	ORG	00100h			; FOR DEBUG IN CP/M (AS .COM)
	.ORG	MON_LOC
;
;__ENTRY JUMP TABLE___________________________________________________________
;
	JP	DSKY_ENTRY
	JP	UART_ENTRY
;
ENA_XM		.EQU	TRUE		; INCLUDE XMODEM
;
ENA_MBC6502	.EQU	FALSE		; ENABLE OR DISABLE MBC6502 OPTION
;
;__UART_ENTRY_________________________________________________________________
;
;	SERIAL MONITOR STARTUP
;_____________________________________________________________________________
;
UART_ENTRY:
	LD	SP,MON_STACK		; SET THE STACK POINTER
	;EI				; INTS OK NOW
	LD	HL,UART_ENTRY		; RESTART ADDRESS
	CALL	INITIALIZE		; INITIALIZE SYSTEM

	LD	HL,TXT_READY		; POINT AT TEXT
	CALL	PRTSTRH			; SHOW WE'RE HERE
;
;__SERIAL_MONITOR_COMMANDS____________________________________________________
;
; B			- BOOT SYSTEM
; D XXXX YYYY		- DUMP MEMORY IN RANGE XXXX-YYYY
; F XXXX YYYY ZZ	- FILL MEMORY IN RANGE XXXX-YYYY WITH ZZ
; H			- HALT SYSTEM
; I XXXX		- SHOW VALUE AT PORT XXXX
; K			- ECHO KEYBOARD INPUT
; L			- LOAD INTEL HEX FORMAT DATA
; M XXXX YYYY ZZZZ	- MOVE MEMORY BLOCK XXXX-YYYY TO ZZZZ
; O XXXX YY		- OUTPUT VALUE YY TO PORT XX
; P XXXX		- PROGRAM RAM STARTING AT XXXX, PROMPT FOR VALUES
; R XXXX		- RUN A PROGRAM AT ADDRESS XXXX
; S XX			- SET ACTIVE BANK TO XX
; T XXXX 		- X-MODEM TRANSFER TO MEMORY LOCATION XXXX
; U 			- SET BANK TO PREVIOUS BANK
; 6 XX                  - TRANSFER CONTROL TO MBC6502 UNIT XX
; X			- EXIT MONITOR
;
;__COMMAND_PARSE______________________________________________________________
;
;	PROMPT USER FOR COMMANDS, THEN PARSE THEM
;_____________________________________________________________________________
;
SERIALCMDLOOP:
	LD	SP,MON_STACK		; RESET STACK
	CALL	NEWLINE
#IF (BIOS == BIOS_WBW)
	LD	A,($FFE0)		; DISPLAY CURRENTLY ACTIVE
	CALL	PRTHEXBYTE		; BANK IN LOW MEMORY
#ENDIF
	LD	A,'>'
	CALL	COUT

	LD	HL,KEYBUF		; SET POINTER TO KEYBUF AREA
	CALL 	GETLN			; GET A LINE OF INPUT FROM THE USER
	LD	HL,KEYBUF		; RESET POINTER TO START OF KEYBUF
	LD	A,C			; GET LINE LENGTH ENTERED
	OR	A			; ZERO?
	JR	Z,SERIALCMDLOOP		; NOTHING ENTERED, LOOP
	LD	A,(HL)			; LOAD FIRST CHAR INTO A (THIS SHOULD BE THE COMMAND)
	INC	HL			; INC POINTER

	CP	'B'			; IS IT "B" (Y/N)
	JP	Z,BOOT			; IF YES BOOT
	CP	'R'			; IS IT "R" (Y/N)
	JP	Z,RUN			; IF YES GO RUN ROUTINE
	CP	'P'			; IS IT "P" (Y/N)
	JP	Z,PROGRM		; IF YES GO PROGRAM ROUTINE
	CP	'O'			; IS IT AN "O" (Y/N)
	JP	Z,POUT			; PORT OUTPUT
#IF (ENA_XM)
	CP	'T'			; IS IT A "T" (Y/N)
	JP	Z,XMLOAD		; XMODEM TRANSFER
#ENDIF
	CP	'L'			; IS IT A "L" (Y/N)
	JP	Z,HXLOAD		; INTEL HEX FORMAT LOAD DATA
	CP	'I'			; IS IT AN "I" (Y/N)
	JP	Z,PIN			; PORT INPUT
	CP	'D'			; IS IT A "D" (Y/N)
	JP	Z,DUMPMEM		; DUMP MEMORY
	CP	'K'			; IS IT A "K" (Y/N)
	JP	Z,KLOP			; LOOP ON KEYBOARD
	CP	'M'			; IS IT A "M" (Y/N)
	JP	Z,MOVEMEM		; MOVE MEMORY COMMAND
	CP	'F'			; IS IT A "F" (Y/N)
	JP	Z,FILLMEM		; FILL MEMORY COMMAND
	CP	'?'			; IS IT A "?" (Y/N)
	JP	Z,HELP			; HELP COMMAND
	CP	'H'			; IS IT A "H" (Y/N)
	JP	Z,HALT			; HALT COMMAND
#IF (BIOS == BIOS_WBW)
	CP	'S'			; IS IT A "S" (Y/N)
	JP	Z,SETBNK		; SET BANK COMMAND
	CP	'U'			; IS IT A "U" (Y/N)
	JP	Z,UNSETBNK		; UNSET (REVERT) BANK COMMAND		
  #IF ((PLATFORM = PLT_MBC) & ENA_MBC6502)
	CP	'6'			; IS IT A "6" (Y/N)
	JP	Z,MBC6502		; TRANSFER TO MBC6502 COMMAND
  #ENDIF
#ENDIF
	CP	'X'			; IS IT A "X" (Y/N)
	JP	Z,EXIT			; EXIT COMMAND
	LD	HL,TXT_COMMAND		; POINT AT ERROR TEXT
	CALL	PRTSTRH			; PRINT COMMAND LABEL

	JR	SERIALCMDLOOP
;
;__INITIALIZE_________________________________________________________________
;
;	INITIALIZE SYSTEM
;	AT ENTRY, HL SHOULD HAVE ADDRESS OF DESIRED RESTART ADDRESS
;_____________________________________________________________________________
;
INITIALIZE:
;
#IF (BIOS == BIOS_UNA)
	; INSTALL UNA INVOCATION VECTOR FOR RST 08
	LD	A,$C3		; JP INSTRUCTION
	LD	(8),A		; STORE AT 0x0008
	LD	HL,($FFFE)	; UNA ENTRY VECTOR
	LD	(9),HL		; STORE AT 0x0009
#ENDIF
;
	RET
;
;__BOOT_______________________________________________________________________
;
;	PERFORM BOOT ACTION
;_____________________________________________________________________________
;
BOOT:
#IF (BIOS == BIOS_UNA)
	LD	BC,$01FB		; UNA FUNC = SET BANK
	LD	DE,0			; ROM BANK 0
	CALL	$FFFD			; DO IT (RST 08 NOT SAFE HERE)
	JP	0			; JUMP TO RESTART ADDRESS
#ELSE
	;LD	A,BID_BOOT		; BOOT BANK
	;LD	HL,0			; ADDRESS ZERO
	;CALL	HB_BNKCALL		; DOES NOT RETURN
	LD	B,BF_SYSRESET		; SYSTEM RESTART
	LD	C,BF_SYSRES_COLD	; COLD START
	CALL	$FFF0			; CALL HBIOS
#ENDIF
;
;__EXIT_______________________________________________________________________
;
;	PERFORM EXIT ACTION
;_____________________________________________________________________________
;
EXIT:
#IF (BIOS == BIOS_UNA)
	JR	BOOT
#ELSE
	LD	B,BF_SYSRESET		; SYSTEM RESTART
	LD	C,BF_SYSRES_WARM	; WARM START
	CALL	$FFF0			; CALL HBIOS
#ENDIF
;
;__HALT_______________________________________________________________________
;
;	PERFORM HALT ACTION
;_____________________________________________________________________________
;
HALT:
	DI
	HALT
;
;__SETBNK_____________________________________________________________________
;
;	PERFORM SET BANK ACTION
;_____________________________________________________________________________
;
#IF (BIOS == BIOS_WBW)
;
SETBNK:
#IF (INTMODE == 1)
	LD	HL,TXT_IMERR
	CALL	PRTSTR
#ELSE
	LD	A,($FFE0)		; GET AND SAVE
	LD	(BNKSAV),A		; CURRENT BANK
	CALL	BYTEPARM		; GET BANK NUMBER
	JP	C,ERR			; HANDLE DATA ENTRY ERROR
	LD	C,A			; PUT IN C FOR FOR FUNC CALL
	LD	B,BF_SYSSETBNK		; SET BANK FUNCTION
	CALL	$FFF0			; C HAS BANK, DO IT
#ENDIF
	JP	SERIALCMDLOOP		; NEXT COMMAND
;
;__UNSETBNK___________________________________________________________________
;
;	PERFORM UNSET BANK ACTION - REVERT TO BANK BEFORE PREVIOUS SET
;_____________________________________________________________________________
;
UNSETBNK:
#IF (INTMODE == 1)
	LD	HL,TXT_IMERR
	CALL	PRTSTR
#ELSE
	LD	A,(BNKSAV)
	LD	C,A			; PUT IN C FOR FOR FUNC CALL
	LD	B,BF_SYSSETBNK		; SET BANK FUNCTION
	CALL	$FFF0			; C HAS BANK, DO IT
#ENDIF
	JP	SERIALCMDLOOP		; NEXT COMMAND
;
BNKSAV	.DB	00H			; OLD BANK FROM BEFORE SET
;
#ENDIF
;
;__RUN________________________________________________________________________
;
;	TRANSFER OUT OF MONITOR, USER OPTION "R"
;	SYNTAX: R <ADDR> [<A-VALUE> [<BC-VALUE>]]
;_____________________________________________________________________________
;
RUN:
	CALL	WORDPARM		; GET START ADDRESS
	JP	C,ERR			; HANDLE ERRORS
	PUSH	DE			; SAVE VALUE
	CALL	BYTEPARM		; GET OPTIONAL
	PUSH	AF			; A REGISTER VALUE
	CALL	WORDPARM		; GET OPTIONAL
	PUSH	DE			; BC REGISTER VALUE
	CALL	NONBLANK		; LOOK FOR EXTRANEOUS PARAMETERS
	CP	0			; TEST FOR TERMINATING NULL
	JP	NZ,ERR			; ERROR IF NOT TERMINATING NULL
	POP	BC			; RECOVER BC REGISTER VALUE TO PASS
	POP	AF			; RECOVER A REGISTER VALUE TO PASS
	POP	HL			; RECOVER START ADDRESS
;
	LD	DE,PREG1		; SETUP A RETURN
	PUSH	DE			; ADDRESS
;
	JP	(HL)			; GO
;
PREG1:	PUSH	BC			; SAVE
	PUSH	DE			; REGISTERS
	PUSH	HL			; FOR DISPLAY
;
	CALL	NEWLINE
	CALL	PRTHEXBYTE		; DISPLAY A
	CALL	PC_SPACE		; REGISTER
;
	LD	B,3
PREG2:	POP	HL			; DISPLAY
	CALL	PHL			; HL DE BC
	CALL	PC_SPACE		; REGISTER
	DJNZ	PREG2
	JP	SERIALCMDLOOP
;
;__PROGRM_____________________________________________________________________
;
;	PROGRAM RAM LOCATIONS, USER OPTION "P"
;_____________________________________________________________________________
;
PROGRM:
	CALL	WORDPARM		; GET STARTING LOCATION
	JP	C,ERR			; HANDLE SYNTAX ERRORS
	PUSH	DE			; SAVE VALUE
	CALL	NONBLANK		; LOOK FOR EXTRANEOUS PARAMETERS
	CP	0			; TEST FOR TERMINATING NULL
	JP	NZ,ERR			; ERROR IF NOT TERMINATING NULL
PROGRM1:
	CALL	NEWLINE
	POP	HL
	PUSH	HL
	CALL	PHL
	CALL	PC_COLON		; DISPLAY
	CALL	PC_SPACE		; CURRENT
	POP	HL			; VALUE
	PUSH	HL
	LD	A,(HL)
	CALL	PRTHEXBYTE
	CALL	PC_SPACE
	LD	HL,KEYBUF		; GET AND
	CALL	GETLN			; SAVE NEW
	LD	HL,KEYBUF		; VALUE
	CALL	NONBLANK
	CP	0
	JP	Z,SERIALCMDLOOP
	CALL	BYTEPARM
	JR	C,PROGRM2		; SYNTAX ERROR
	POP	DE
	LD	(DE),A
	INC	DE
	PUSH	DE
	JR	PROGRM1
PROGRM2:
	LD	HL,TXT_BADNUM
	CALL	PRTSTR
	JR	PROGRM1
;
;__KLOP_______________________________________________________________________
;
;	READ FROM THE SERIAL PORT AND ECHO, MONITOR COMMAND "K"
;_____________________________________________________________________________
;
KLOP:
	CALL	NEWLINE			;
KLOP1:
	CALL	KIN			; GET A KEY
	CP	CHR_ESC			; IS <ESC>?
	JP	Z,SERIALCMDLOOP		; IF SO, ALL DONE
	CALL	COUT			; OUTPUT KEY TO SCREEN
	JR	KLOP1			; LOOP
;
#IF (ENA_XM)
;
;__XMLOAD_____________________________________________________________________
;
;	LOAD A FILE INTO MEMORY FROM THE SERIAL PORT USING X-MODEM PROTOCOL
;
SOH:	.EQU	'A'-40h			; ^A CTRL-A
EOT:	.EQU	'D'-40h			; ^D = End of Transmission
ACK:	.EQU	'F'-40h			; ^F = Positive Acknowledgement
NAK:	.EQU	'U'-40h			; ^U = Negative Acknowledgement
CAN:	.EQU	'X'-40h			; ^X = Cancel
;
CPKTN	.DB	0			; CALCULATED PACKET NUMBER
CPKTN1C	.DB	0			; CALCULATED PACKET NUMBER COMPLEMENT
RETRYC	.DB	0			; RETRY COUNT
RPKTN:	.DB	0			; RECEIVED PACKET NUMBER
RPKTN1C:.DB	0			; RECEIVED PACKET NUMBER COMPLEMENT
PKTCS	.DB	0 			; CHECKSUM
;
PSADDR:	.DW	0			; START OF PACKET ADDR
;
XMLOAD:	CALL	WORDPARM		; GET STARTING LOCATION
	JP	C,ERR			; HANDLE SYNTAX ERRORS
	PUSH	DE			; SAVE VALUE
	CALL	NONBLANK		; LOOK FOR EXTRANEOUS PARAMETERS
	CP	0			; TEST FOR TERMINATING NULL
	JP	NZ,ERR			; ERROR IF NOT TERMINATING NULL
;
	LD	HL,TXT_READY		; READY FOR
	CALL	PRTSTR			; TRANSFER
	CALL	NEWLINE
;
	LD	BC,$F8F0		; GET CPU SPEED
	CALL	$FFF0			; CALL HBIOS
;	RST	08			; AND MULTIPLY
	LD	A,L			; BY 4
	PUSH	AF
	ADD	A,A			; TO CREATE
	ADD	A,A			; TIMEOUT DELAY
	LD	(TMOFCT),A		; FACTOR 
	POP	AF
;
	LD	BC,$FE01		; SET FIRST NUMBER TO 1
	LD	(CPKTN),BC		; ALSO STORE THE 1-COMPLEMENT
;
	POP	DE			; POINT TO WHERE TO SAVE THE PACKET
	LD	(PSADDR),DE		; SAVE IF FOR THE CHECKSUM CALCULATION
;
GETNP:	LD	HL,RETRYC		; WE RETRY 20 TIMES BEFORE GIVING UP
	LD 	(HL),20
;
NPLOOP:	LD 	B,6			; 6 SECONDS OF TIMEOUT BEFORE EACH NEW BLOCK
	CALL	GCTO
	JP 	NC,NOTOUT		; NO TIMEOUT ?
;
	DEC 	(HL)			; REACHED MAX NUMBER OF RETRIES?
	JP 	Z,FAILRT		; YES, PRINT MESSAGE AND EXIT
;
	LD 	A,NAK			; SEND A NAK TO THE UPLOADER
	CALL	COUT
	JR 	NPLOOP			; LOOP UNTIL WE GET A GET A CHARACTOR OR TIMEOUT
;
NOTOUT:	CP	EOT			; DID UPLOADER SAY WE'RE FINISHED?
	JP	Z,XMDONE		; YES, THEN WE'RE DONE
	CP 	CAN			; UPLOADER WANTS TO FAIL TRANSFER?
	JP 	Z,FAILCN		; YES, THEN WE'RE ALSO DONE
	CP	SOH			; DID WE GET A START-OF-NEW-PACKET?
	JR	NZ,NPLOOP		; NO, GO BACK AND TRY AGAIN
;
	LD	HL,RPKTN		; WE SAVE PACKET NUMBER HERE
;
	CALL	GCTO1			; WAIT ONE SECOND FOR A CHARACTER
	LD	(HL),A                  ; SHOULD BE PACKET NUMBER
	INC 	HL
	JR	C,FAILTO		; TIMOUT ERROR?
;
	CALL	GCTO1			; WAIT ONE SECOND FOR A CHARACTER
	LD	(HL),A			; SHOULD BE PACKET NUMBER COMPLEMENT
	JR	C,FAILTO		; TIMOUT ERROR?

	LD 	C,128			; GET 128 MORE CHARACTERS FOR A FULL PACKET
PCKRCV:	CALL	GCTO1			; WAIT ONE SECOND FOR A CHARACTER
	JR	C,FAILTO		; TIMOUT ERROR?
	LD	(DE),A         		; SAVE THE RECEIVED CHAR
	INC	DE
	DEC	C	
	JP	NZ,PCKRCV
;
	CALL	GCTO1			; WAIT ONE SECOND FOR A CHARACTER
	JR	C,FAILTO		; TIMOUT ERROR?
	LD	(PKTCS),A		; SHOULD BE CHECKSUM
;
	LD	HL,(PSADDR)		; CALCULATE CHECKSUM FROM 128 BYTES OF DATA
	LD	B,128
	XOR	A
CSLOOP:	ADD	A,(HL)			; JUST ADD UP THE BYTES
	INC	HL
	DJNZ	CSLOOP
;
	LD	(PSADDR),DE		; SAVE THE NEW PACKET START ADDRESS
;
	LD	HL,PKTCS
	XOR	(HL)			; HL POINTS TO THE RECEIVED CHECKSUM SO
	JR	NZ,FAILCS		; BY XORING IT TO OUR SUM WE CHECK FOR EQUALITY
;
	LD	HL,(CPKTN)		; CHECK
	LD	BC,(RPKTN)		; AGREEMENT
;	XOR	A                       ; PACKET
	SBC	HL,BC                   ; NUMBERS
	JR	NZ,FAILPN
;
	LD	HL,CPKTN		; UPDATE THE PACKET COUNTERS
	INC 	(HL)
	INC	HL
	DEC	(HL)
;
	LD 	A,ACK			; TELL UPLOADER THAT WE'RE HAPPY WITH WITH
	CALL	COUT			; PACKET AND GO BACK AND FETCH SOME MORE
	JP	GETNP
;
FAILRT:	LD	HL,TXT_RETRYERR		; FAILED ON RETRY
	JR	XMERR
FAILCN:	LD	HL,TXT_CANCLERR		; TRANSFER CANCELLED
	JR	XMERR
FAILCS:	LD	HL,TXT_CKSUMERR		; CHECKSUM ERROR 
	JR	XMERR
FAILPN:	LD	HL,TXT_PKNUMERR		; PACKET NUMBER ERROR
	JR	XMERR
FAILTO:	LD	HL,TXT_TMOUTERR		; TIMEOUT ERROR
	JR	XMERR
;
XMDONE:	LD	A,ACK			; TELL REMOTE 
	CALL	COUT			; WE'RE DONE
	LD 	HL,TXT_LOADED		; TELL USER
XMERR:	CALL	PRTSTR			; WE'RE DONE
	JP	SERIALCMDLOOP		; BACK TO MENU
;
; WAITS FOR UP TO B SECONDS FOR A CHARACTER TO BECOME AVAILABLE AND
; RETURNS IT IN A WITHOUT ECHO AND CARRY CLEAR. IF TIMEOUT THEN CARRY
; IT SET.
;
; 4MHZ  20 SECONDS TMOFCT = 16
; 10MHZ 20 SECONDS TMOFCT = 39
;
GCTO1:	LD	B,1			; WAIT 1 SECOND FOR SERIAL INPUT
GCTO:	CALL	CST			; IF THERE IS A 
	OR	A			; CHARACTER AVAILABLE
	JR 	NZ,GETCHRX		; EXIT NOW OTHERWISE POLL
GCTOA:	PUSH	BC
	LD	BC,255			; C=CONSTANT (255) FOR INNER TIMING LOOP
TMOFCT:	.EQU	$-1			; B=SPEED FACTOR WHICH GETS UPDATED AT START
GCTOB:	PUSH	BC
	LD	B,C
GCTOC:	PUSH	BC
	CALL	CST
	OR	A			; A CHAR AVAILABLE?
	JR 	NZ,GETCHR		; YES, GET OUT OF LOOP
	POP	BC
	DJNZ	GCTOC
	POP	BC
	DJNZ	GCTOB
	POP	BC
	DJNZ	GCTO
	SCF 				; SET CARRY SIGNALS 
	RET				; TIMEOUT OCCURRED
GETCHR:	POP	BC
	POP	BC
	POP	BC
GETCHRX:CALL	CIN			; GET THE CHARACTER
	OR	A 			; CLEAR CARRY
	RET				; SIGNALS SUCCESS

TXT_PKNUMERR	.TEXT	"\r\nPacket Number Error$"
TXT_TMOUTERR	.TEXT	"\r\nTimeout Error$"
TXT_RETRYERR	.TEXT	"\r\nRetry Error$"
TXT_CANCLERR	.TEXT	"\r\nTransfer Cancelled$"
#ENDIF
;
;__HXLOAD_____________________________________________________________________
;
;	LOAD INTEL HEX FORMAT FILE FROM THE SERIAL PORT, USER OPTION "H"
;
;	 [INTEL HEX FORMAT IS:
;	 1) COLON (FRAME 0)
;	 2) RECORD LENGTH FIELD (FRAMES 1 AND 2)
;	 3) LOAD ADDRESS FIELD (FRAMES 3,4,5,6)
;	 4) RECORD TYPE FIELD (FRAMES 7 AND 8)
;	 5) DATA FIELD (FRAMES 9 TO 9+2*(RECORD LENGTH)-1
;	 6) CHECKSUM FIELD - SUM OF ALL BYTE VALUES FROM RECORD LENGTH TO AND
;	   INCLUDING CHECKSUM FIELD = 0 ]
;
; EXAMPLE OF INTEL HEX FORMAT FILE
; EACH LINE CONTAINS A CARRIAGE RETURN AS THE LAST CHARACTER
; :18F900002048454C4C4F20574F524C4420FF0D0AFF0D0A3EFF0D0A54BF
; :18F918006573742050726F746F7479706520524F4D204D6F6E69746FF1
; :18F9300072205265616479200D0AFF0D0A434F4D4D414E4420524543F2
; :18F948004549564544203AFF0D0A434845434B53554D204552524F52CD
; :16F96000FF0A0D20202D454E442D4F462D46494C452D20200A0DA4
; :00000001FF
;_____________________________________________________________________________
;
HXLOAD:
	CALL	NEWLINE			; SHOW READY
HXLOADLINE:
	CALL	CIN			; GET THE FIRST CHARACTER, EXPECTING A ':'
	CP	':'			; IS IT COLON ':'? WAIT FOR START OF NEXT LINE OF INTEL HEX FILE
	JR	NZ,HXLOADLINE		; IF NOT, GO BACK TO WAIT
	LD	E,0			; RESET THE CHECKSUM BYTE <E>
	CALL	HEXINS			; FIRST TWO CHARACTERS IS THE RECORD LENGTH FIELD <D>
	LD	D,A			; LOAD RECORD LENGTH COUNT INTO D
	CALL	HEXINS			; GET NEXT TWO CHARACTERS, MEMORY LOAD ADDRESS <H>
	LD	H,A			; PUT VALUE IN H REGISTER
	CALL	HEXINS			; GET NEXT TWO CHARACTERS, MEMORY LOAD ADDRESS <L>
	LD	L,A			; PUT VALUE IN L REGISTER
	CALL	HEXINS			; GET NEXT TWO CHARACTERS, RECORD FIELD TYPE
	DEC A				; RECORD FIELD TYPE 01 IS END OF FILE
	JR	Z,HXLOADEXIT		; MUST BE THE END OF THAT FILE
	INC A				; RECORD FIELD TYPE 00 IS DATA
	JR	NZ,HXLOADTYPERR		; RECORD TYPE IS INCORRECT, ERROR OUT
HXLOADDATA:
	CALL	HEXINS			; GET NEXT TWO CHARACTERS, ASSEMBLE INTO BYTE
	LD	(HL),A			; MOVE CONVERTED BYTE IN A TO MEMORY LOCATION
	INC	HL			; INCREMENT POINTER TO NEXT MEMORY LOCATION
	DEC	D			; DECREMENT LINE CHARACTER COUNTER
	JR	NZ,HXLOADDATA		; AND KEEP LOADING INTO MEMORY UNTIL LINE IS COMPLETE
	CALL	HEXINS			; GET NEXT TWO CHARACTERS, ASSEMBLE INTO CHECKSUM BYTE
	LD	A,E			; RECALL THE CHECKSUM BYTE
	OR	A			; IT SHOULD BE ZERO
	JR	Z,HXLOADLINE		; ZERO, SO WE HAVE NO ERROR, GO GET ANOTHER LINE
HXLOADCHKERR:
	LD	HL,TXT_CKSUMERR		; GET "CHECKSUM ERROR" MESSAGE
	CALL	PRTSTR			; PRINT MESSAGE FROM (HL) AND TERMINATE THE LOAD
	JP	SERIALCMDLOOP		; RETURN TO PROMPT
HXLOADTYPERR:
	LD	HL,TXT_RECORDERR	; GET "RECORD TYPE ERROR" MESSAGE
	CALL	PRTSTR			; PRINT MESSAGE FROM (HL) AND TERMINATE THE LOAD
	JP	SERIALCMDLOOP		; RETURN TO PROMPT
HXLOADEXIT:
	CALL	HEXINS			; GET LAST TWO CHARACTERS, ASSEMBLE INTO CHECKSUM BYTE
	LD	A,E			; RECALL THE CHECKSUM BYTE
	OR	A		    	; IT SHOULD BE ZERO
	JR	NZ,HXLOADCHKERR		; CHECKUM IS INCORRECT, ERROR OUT
	LD	HL,TXT_LOADED		; GET "LOADED" MESSAGE
	CALL	PRTSTR			; PRINT MESSAGE FROM (HL)
	JP	SERIALCMDLOOP		; RETURN TO PROMPT
;
;__POUT_______________________________________________________________________
;
;	OUTPUT TO AN I/O PORT, MONITOR COMMAND "O"
;	SYNTAX: O <PORT> <VALUE>
;	NOTE: A WORD VALUE IS USED FOR THE PORT NUMBER BECAUSE THE
;             Z80 WILL ACTUALLY PLACE 16 BITS ON THE BUS USING
;             THE B AND C REGISTERS WITH AN "OUT (C),A" INSTRUCTION
;_____________________________________________________________________________
;
POUT:
	CALL	WORDPARM		; GET PORT NUMBER
	JP	C,ERR			; HANDLE ERRORS
	PUSH	DE			; SAVE IT FOR NOW
	CALL	BYTEPARM		; GET VALUE TO WRITE
	JP	C,ERR			; HANDLE ERRORS
	POP	BC			; RESTORE PORT NUMBER TO BC
	OUT	(C),A			; SEND VALUE TO PORT
	JP	SERIALCMDLOOP		; DONE, BACK TO COMMAND LOOP
;
;__PIN________________________________________________________________________
;
;	INPUT FROM AN I/O PORT, MONITOR COMMAND "I"
;	SYNTAX: I <PORT>
;       NOTE: A WORD VALUE IS USED FOR THE PORT NUMBER BECAUSE THE
;             Z80 WILL ACTUALLY PLACE 16 BITS ON THE BUS USING
;             THE B AND C REGISTERS WITH AN "IN A,(C)" INSTRUCTION
;_____________________________________________________________________________
;
PIN:
	CALL	WORDPARM		; GET PORT NUMBER
	JP	C,ERR			; HANDLE ERRORS
	PUSH	DE			; SAVE IT
	CALL	NEWLINE			;
	POP	BC			; RESTORE TO BC
	IN	A,(C)			; GET PORT VALUE
	CALL	PRTHEXBYTE		; DISPLAY IT
	JP	SERIALCMDLOOP		; DONE, BACK TO COMMAND LOOP
;
;__DUMPMEM____________________________________________________________________
;
;	PRINT A MEMORY DUMP, USER OPTION "D"
;	SYNTAX: D <START ADR> [END ADR]
;	IF NO END ADDRESS, DUMP 100H BYTES
;_____________________________________________________________________________
;
DUMPMEM:
	CALL	WORDPARM		; GET START ADDRESS
	JP	C,ERR			; HANDLE ERRORS
	PUSH	DE			; SAVE IT
	CALL	WORDPARM		; GET END ADDRESS
	POP	HL			; RECOVER START
	JR	NC,GDATA		; 
;
	LD	D,H			; DEFAULT TO 100H
	LD	E,L			; BYTES IF NO
	INC	D			; END ADDRESS
	DEC	DE			; IS GIVEN
;
GDATA:
	INC	DE			; BUMP DE FOR LATER COMPARE
	CALL	NEWLINE			;
BLKRD:
	CALL	PHL			; PRINT START LOCATION
	CALL	PC_COLON
	CALL	PC_SPACE
	LD	C,16			; SET FOR 16 LOCS
	PUSH	HL			; SAVE STARTING HL
NXTONE:
	EXX				;
	LD	C,E			;
	IN	A,(C)			;
	EXX				;
	AND	7FH			;
	CP	CHR_ESC			;
	JP	Z,SERIALCMDLOOP		;
	CP	19			;
	JR	Z,NXTONE		;
	LD 	A,(HL)			; GET BYTE
	CALL	PRTHEXBYTE		; DISPLAY IT
	CALL	PC_SPACE		;
UPDH:
	INC	HL			; POINT NEXT
	DEC	C			; DEC  LOC COUNT
	JR	NZ,NXTONE		; IF LINE NOT DONE
					; NOW PRINT 'DECODED' DATA TO RIGHT OF DUMP
PCRLF:
	CALL	PC_SPACE		; SPACE IT
	LD	C,16			; SET FOR 16 CHARS
	POP	HL			; GET BACK START
PCRLF0:
	LD	A,(HL)			; GET BYTE TO PRINT
	CP	$20			; CONTROL CHAR (UNPRINTABLE)?
	JR	C,PDOT			; IF SO, PRINT A DOT
	CP	$7F			; 127 OR MORE (UNPRINTABLE)?
	JR	NC,PDOT			; IF SO, PRINT A DOT
	JR	PCHAR			; PRINT ACTUAL CHAR
PDOT:
	LD	A,2EH			; OTHERWISE SUBSTITUTE A DOT
PCHAR:
	CALL	COUT			; PRINT IT
	INC	HL			;
	LD	A,D			;
	CP	H			;
	JR	NZ,UPDH1		;
	LD	A,E			;
	CP	L			;
	JP	Z,SERIALCMDLOOP		;
;
;IF BLOCK NOT DUMPED, DO NEXT CHARACTER OR LINE
UPDH1:
	DEC	C			; DEC  CHAR COUNT
	JR	NZ,PCRLF0		; DO NEXT
CONTD:
	CALL	NEWLINE			;
	JR	BLKRD			;
;
;__MOVEMEM____________________________________________________________________
;
;	MOVE MEMORY, USER OPTION "M"
;	SYNTAX: M <SRC-START> <SRC-END> <TGT>
;_____________________________________________________________________________
;
MOVEMEM:
	CALL	WORDPARM		; GET WORD VALUE INTO DE (MOVE SRC START ADR)
	JP	C,ERR			; SYNTAX ERROR IF HEXWORD FAILED
	PUSH	DE			; SAVE IT
	CALL	WORDPARM		; GET WORD VALUE INTO DE (MOVE SRC END ADR)
	JP	C,ERR			; SYNTAX ERROR IF HEXWORD FAILED
	PUSH	DE			; SAVE IT
	CALL	WORDPARM		; GET WORD VALUE INTO DE (MOVE TGT ADR)
	JP	C,ERR			; SYNTAX ERROR IF HEXBYTE FAILED
	PUSH	DE			; SAVE IT
	CALL	NONBLANK		; LOOK FOR EXTRANEOUS PARAMETERS
	CP	0			; TEST FOR TERMINATING NULL
	JP	NZ,ERR			; ERROR IF NOT TERMINATING NULL

	POP	DE			; TGT ADR TO DE
	POP	BC			; SRC END ADR TO BC
	POP	HL			; SRC START ADR TO HL
	DEC	HL			; PRE-DECREMENT
	DEC	DE			; PRE-DECREMENT
MOVEMEM1:
	INC	HL			; BUMP CUR SRC ADR
	INC	DE			; BUMP CUR TGT ADR
	LD	A,(HL)			; GET SOURCE VAUEE
	LD	(DE),A			; WRITE TO TARGET LOC
	LD	A,H			; CHECK MSB OF END ADR
	CP	B			;
	JR	NZ,MOVEMEM1		; NO MATCH, LOOP
	LD	A,L			; CHECK LSB OF END ADR
	CP	C			;
	JR	NZ,MOVEMEM1		; NO MATCH, LOOP
	JP	SERIALCMDLOOP		; LSB AND MSB MATCH, ALL DONE
;
;__FILLMEM____________________________________________________________________
;
;	FILL MEMORY, USER OPTION "M"
;	SYNTAX: F <START> <END> <VALUE>
;_____________________________________________________________________________
;
FILLMEM:
	CALL	WORDPARM		; GET WORD VALUE INTO DE (FILL START ADR)
	JP	C,ERR			; SYNTAX ERROR IF HEXWORD FAILED
	PUSH	DE			; SAVE IT
	CALL	WORDPARM		; GET WORD VALUE INTO DE (FILL END ADR)
	JP	C,ERR			; SYNTAX ERROR IF HEXWORD FAILED
	PUSH	DE			; SAVE IT
	CALL	BYTEPARM		; GET BYTE VALUE (FILL VALUE) INTO A
	JP	C,ERR			; SYNTAX ERROR IF HEXBYTE FAILED
	LD	C,A			; FILL VALUE TO C
	CALL	NONBLANK		; LOOK FOR EXTRANEOUS PARAMETERS
	CP	0			; TEST FOR TERMINATING NULL
	JP	NZ,ERR			; ERROR IF NOT TERMINATING NULL

	POP	DE			; END ADR TO DE
	POP	HL			; START ADR TO HL
	DEC	HL			; PRE-DECREMENT
FILLMEM1:
	INC	HL			; BUMP CUR ADR
	LD	A,C			; FILL VALUE TO A
	LD	(HL),A			; WRITE FILL VALUE TO CUR ADR (HL)
	LD	A,H			; CHECK MSB OF END ADR
	CP	D			;
	JR	NZ,FILLMEM1		; NO MATCH, LOOP
	LD	A,L			; CHECK LSB OF END ADR
	CP	E			;
	JR	NZ,FILLMEM1		; NO MATCH, LOOP
	JP	SERIALCMDLOOP		; LSB AND MSB MATCH, ALL DONE
;
;__HELP_______________________________________________________________________
;
;	SYNTAX HELP, USER OPTION "H"
;_____________________________________________________________________________
;
HELP:
	LD	HL,TXT_HELP		; POINT AT SYNTAX HELP TEXT
	CALL	PRTSTR			; DISPLAY IT
	JP	SERIALCMDLOOP		; AND BACK TO COMMAND LOOP
;
;__MBC6502____________________________________________________________________
;
;	TRANSFER CONTROL TO MBC6502
;_____________________________________________________________________________
;
;
#IF (BIOS == BIOS_WBW)
  #IF ((PLATFORM = PLT_MBC) & ENA_MBC6502)
MBC6502:
	CALL	BYTEPARM		; GET BYTE VALUE (FILL VALUE) INTO A
	CPL				; UNIT 0 = FFH, 1 = FEH ETC
	LD	C,A
;
	IN	A,(C)			; EXECUTE
	NOP				; TRANSFER
;
	LD	A,($FFE0)		; GET PREVIOUS BANK
	OUT	(MPCL_RAM),A		; SET RAM PAGE SELECTOR
	OUT	(MPCL_ROM),A		; SET ROM PAGE SELECTOR
;
	JP	SERIALCMDLOOP		; AND BACK TO COMMAND LOOP
  #ENDIF
#ENDIF
;
;__ERR________________________________________________________________________
;
;	SYNTAX ERROR
;_____________________________________________________________________________
;
ERR:
	LD	HL,TXT_ERR		; POINT AT ERROR TEXT
	CALL	PRTSTRH			; DISPLAY IT
	JP	SERIALCMDLOOP		; AND BACK TO COMMAND LOOP
;
;__BYTEPARM___________________________________________________________________
;
;	ATTEMPT TO GET A BYTE PARM, VALUE RETURNED IN A
;       CF SET ON ERROR
;_____________________________________________________________________________
;
BYTEPARM:
	CALL	NONBLANK		; SKIP LEADING BLANKS
	JP	Z,ERR			; SYNTAX ERROR IF PARM NOT FOUND
	CALL	ISHEX			; HEX CHAR?
	JR	NZ,BYTEPARM1		; IF NOT, ERR
	JP	HEXBYTE			; RETURN VIA HEXBYTE
BYTEPARM1:
	SCF				; SIGNAL ERROR
	RET				; RETURN
;
;__WORDPARM___________________________________________________________________
;
;	ATTEMPT TO GET A WORD PARM, VALUE RETURNED IN DE
;       CF SET ON ERROR
;_____________________________________________________________________________
;
WORDPARM:
	CALL	NONBLANK		; SKIP LEADING BLANKS
	JP	Z,ERR			; SYNTAX ERROR IF PARM NOT FOUND
	CALL	ISHEX			; HEX CHAR?
	JR	NZ,BYTEPARM1		; IF NOT, ERR
	JP	HEXWORD			; RETURN VIA HEXWORD
;
;__GETLN______________________________________________________________________
;
;	READ A LINE OF TEXT FROM THE SERIAL PORT, HANDLE <BS>, TERM ON <CR>
;       EXIT IF TOO MANY CHARS    STORE RESULT IN HL.  CHAR COUNT IN C.
;_____________________________________________________________________________
;
GETLN:
	LD	C,0			; ZERO CHAR COUNTER
	PUSH	DE			; SAVE DE
GETLNLOP:
	; ENTRY LOOP
	CALL	KIN			; GET A KEY
	CP	CHR_CR			; IS <CR>?
	JR	Z,GETLNDONE		; YES, EXIT
	CP	CHR_BS			; IS <BS>?
	JR	Z,GETLNBS		; IF SO, HANDLE IT
	CP	CHR_DEL			; IS <DEL>?
	JR	Z,GETLNBS		; IF SO, HANDLE AS <BS>
	CP	' '			; UNEXPECTED CONTROL CHAR?
	JR	C,GETLNLOP		; IF SO, IGNORE IT AND GET NEXT
	LD	B,A			; SAVE CHAR IN B FOR NOW
	LD	A,C			; GET COUNTER
	CP	BUFLEN - 1		; MAX OF BUFLEN CHARS LESS SPACE FOR TERM NULL
	JR	Z,GETLNOVF		; IF AT MAX, HANDLE OVERFLOW
	LD	A,B			; GET INPUT CHAR BACK
	CALL	COUT			; OUTPUT KEY TO SCREEN
	LD	(HL),A			; STORE CHAR IN BUFFER
	INC	HL			; INC POINTER
	INC	C			; INC CHAR COUNTER
	JR	GETLNLOP		; GET NEXT CHAR
GETLNOVF:
	; OVERFLOW
	LD	A,CHR_BEL		; BELL CHARACTER
	CALL	COUT			; SEND IT TO CONSOLE
	JR	GETLNLOP		; LOOP
GETLNBS:
	; BACKSPACE
	LD	A,C			; A=C
	OR	A			; ZERO?
	JR	Z,GETLNLOP		; IF EMPTY LINE, IGNORE BS & LOOP
	DEC	HL			; BACKUP BUF PTR 1 CHAR
	DEC	C			; DECREMENT CHAR COUNTER
	LD	A,CHR_BS		; BACKSPACE
	CALL	COUT			; TO CONSOLE
	LD	A,20H			; BLANK OUT CHAR ON TERM
	CALL	COUT			; TO CONSOLE
	LD	A,CHR_BS		; BACKSPACE
	CALL	COUT			; TO CONSOLE
	JR	GETLNLOP		; GET NEXT KEY
	; DONE
GETLNDONE:
	LD	(HL),00H		; STORE NULL IN BUFFER
	POP	DE			; RESTORE DE
	RET				;
;
;__KIN________________________________________________________________________
;
;	READ FROM THE SERIAL PORT AND ECHO & CONVERT INPUT TO UCASE
;_____________________________________________________________________________
;
KIN:
	CALL	CIN
	AND	7FH			; STRIP HI BIT
	CP	'A'			; KEEP NUMBERS, CONTROLS
	RET	C			; AND UPPER CASE
	CP	7BH			; SEE IF NOT LOWER CASE
	RET	NC
	AND	5FH			; MAKE UPPER CASE
	RET
;
;__NONBLANK___________________________________________________________________
;
;	FIND NEXT NONBLANK CHARACTER IN BUFFER AT (HL)
;_____________________________________________________________________________
;
NONBLANK:
	LD	A,(HL)			; GET NEXT CHAR
	CP	' '			; COMPARE TO BLANK
	RET	NZ			; DONE IF NOT BLANK
	INC	HL			; BUMP TO NEXT CHAR
	JR	NONBLANK		; AND LOOP
;
;__ISHEX______________________________________________________________________
;
;	CHECK BYTE AT (HL) FOR HEX CHAR, RET Z IF SO, ELSE NZ
;_____________________________________________________________________________
;
ISHEX:
	LD	A,(HL)			; CHAR TO AS
	CP	'0'			; < '0'?
	JR	C,ISHEX1		; YES, NOT 0-9, CHECK A-F
	CP	'9' + 1			; > '9'
	JR	NC,ISHEX1		; YES, NOT 0-9, CHECK A-F
	XOR	A			; MUST BE 0-9, SET ZF
	RET				; AND DONE
ISHEX1:
	CP	'A'			; < 'A'?
	JR	C,ISHEX2		; YES, NOT A-F, FAIL
	CP	'F' + 1			; > 'F'
	JR	NC,ISHEX2		; YES, NOT A-F, FAIL
	XOR	A			; MUST BE A-F, SET ZF
	RET				; AND DONE
ISHEX2:
	OR	$FF			; CLEAR ZF
	RET				; AND DONE
;
;__HEXBYTE____________________________________________________________________
;
;	GET ONE BYTE OF HEX DATA FROM BUFFER IN HL, RETURN IN A
;_____________________________________________________________________________
;
HEXBYTE:
	LD	C,0			; INIT WORKING VALUE
HEXBYTE1:
	CALL	ISHEX			; DO WE HAVE A HEX CHAR?
	JR	NZ,HEXBYTE3		; IF NOT, WE ARE DONE
	LD	B,4			; SHIFT WORKING VALUE (C := C * 16)
HEXBYTE2:
	SLA	C			; SHIFT ONE BIT
	RET	C			; RETURN W/ CF SET INDICATING OVERFLOW ERROR
	DJNZ	HEXBYTE2		; LOOP FOR 4 BITS
	CALL	NIBL			; CONVERT HEX CHAR TO BINARY VALUE IN A & INC HL
	OR	C			; COMBINE WITH WORKING VALUE
	LD	C,A			; AND PUT BACK IN WORKING VALUE
	JR	HEXBYTE1		; DO ANOTHER CHARACTER
HEXBYTE3:
	LD	A,C			; WORKING VALUE TO A
	OR	A			; CLEAR CARRY
	RET				; AND DONE
;
;__HEXWORD____________________________________________________________________
;
;	GET ONE WORD OF HEX DATA FROM BUFFER IN HL, RETURN IN DE
;_____________________________________________________________________________
;
HEXWORD:
	LD	DE,0			; INIT WORKING VALUE
HEXWORD1:
	CALL	ISHEX			; DO WE HAVE A HEX CHAR?
	JR	NZ,HEXWORD3		; IF NOT, WE ARE DONE
	LD	B,4			; SHIFT WORKING VALUE (DE := DE * 16)
HEXWORD2:
	SLA	E			; SHIFT LSB ONE BIT
	RL	D			; SHIFT MSB ONE BIT
	RET	C			; RETURN W/ CF SET INDICATING OVERFLOW ERROR
	DJNZ	HEXWORD2		; LOOP FOR 4 BITS
	CALL	NIBL			; CONVERT HEX CHAR TO BINARY VALUE IN A & INC HL
	OR	E			; COMBINE WITH LSB
	LD	E,A			; AND PUT BACK IN WROKING VALUE
	JR	HEXWORD1		; DO ANOTHER CHARACTER
HEXWORD3:
	OR	A			; CLEAR CARRY
	RET				; AND DONE
;
;__NIBL_______________________________________________________________________
;
;	GET ONE BYTE OF HEX DATA FROM BUFFER IN HL, RETURN IN A
;_____________________________________________________________________________
;
NIBL:
	LD	A,(HL)			; GET K B. DATA
	INC	HL			; INC KB POINTER
	CP	40H			; TEST FOR ALPHA
	JR	NC,ALPH
	AND	0FH			; GET THE BITS
	RET
ALPH:
	AND	0FH			; GET THE BITS
	ADD	A,09H			; MAKE IT HEX A-F
	RET
;
;__HEXINS_____________________________________________________________________
;
;	GET ONE BYTE OF HEX DATA FROM SERIAL PORT, CHECKSUM IN E, RETURN IN A
;_____________________________________________________________________________
;
HEXINS:
	CALL	NIBLS			; DO A NIBBLE
	RLCA				; MOVE FIRST BYTE UPPER NIBBLE
	RLCA				;
	RLCA				;
	RLCA				;
	LD	B,A			; SAVE ROTATED NIBBLE
	CALL	NIBLS			; DO NEXT NIBBLE
	OR	B			; COMBINE NIBBLES IN ACC TO BYTE
	LD	B,A			; SAVE BYTE
	ADD	A,E			; ADD TO CHECKSUM
	LD	E,A			; SAVE CHECKSUM
	LD	A,B			; RECOVER BYTE
	RET				; DONE
NIBLS:
	CALL	CIN			; GET K B. DATA
	SUB	'0'
	CP	10	 		; TEST FOR ALPHA
	RET	C			; IF A<10 JUST RETURN
	SUB	7			; ELSE SUBTRACT 'A'-'0' (17) AND ADD 10
	RET
;
;__PHL________________________________________________________________________
;
;	PRINT THE HL REG ON THE SERIAL PORT
;_____________________________________________________________________________
;
PHL:
	LD	A,H			; GET HI BYTE
	CALL	PRTHEXBYTE		; DISPLAY IT
	LD	A,L			; GET LOW BYTE
	CALL	PRTHEXBYTE		; DISPLAY IT
	RET				; DONE
;
;__PRTSTRH____________________________________________________________________
;
;	PRINT STRING AT HL W/ MINI HELP SUFFIX
;_____________________________________________________________________________
;
PRTSTRH:
	CALL	PRTSTR
	LD	HL,TXT_MINIHELP
	JP	PRTSTR
;
#IF (BIOS == BIOS_UNA)
;
;__COUT_______________________________________________________________________
;
;	OUTPUT CHARACTER FROM A
;_____________________________________________________________________________
;
COUT:
	; SAVE ALL INCOMING REGISTERS
	PUSH	AF
	PUSH	BC
	PUSH	DE
	PUSH	HL
;
	; OUTPUT CHARACTER TO CONSOLE VIA UBIOS
	LD	E,A
	LD	BC,$12
	CALL	$FFFD
;
	; RESTORE ALL REGISTERS
	POP	HL
	POP	DE
	POP	BC
	POP	AF
	RET
;
;__CIN________________________________________________________________________
;
;	INPUT CHARACTER TO A
;_____________________________________________________________________________
;
CIN:
	; SAVE INCOMING REGISTERS (AF IS OUTPUT)
	PUSH	BC
	PUSH	DE
	PUSH	HL
;
	; INPUT CHARACTER FROM CONSOLE VIA UBIOS
	LD	BC,$11
	CALL	$FFFD
	LD	A,E
;
	; RESTORE REGISTERS (AF IS OUTPUT)
	POP	HL
	POP	DE
	POP	BC
	RET
;
;__CST________________________________________________________________________
;
;	RETURN INPUT STATUS IN A (0 = NO CHAR, !=0 CHAR WAITING)
;_____________________________________________________________________________
;
CST:
	; SAVE INCOMING REGISTERS (AF IS OUTPUT)
	PUSH	BC
	PUSH	DE
	PUSH	HL
;
	; GET CONSOLE INPUT STATUS VIA UBIOS
	LD	BC,$13
	CALL	$FFFD
	LD	A,E
;
	; RESTORE REGISTERS (AF IS OUTPUT)
	POP	HL
	POP	DE
	POP	BC
	RET
;
#ELSE
;
;__COUT_______________________________________________________________________
;
;	OUTPUT CHARACTER FROM A
;_____________________________________________________________________________
;
COUT:
	; SAVE ALL INCOMING REGISTERS
	PUSH	AF
	PUSH	BC
	PUSH	DE
	PUSH	HL
;
	; OUTPUT CHARACTER TO CONSOLE VIA HBIOS
	LD	E,A			; OUTPUT CHAR TO E
	LD	C,CIO_CONSOLE		; CONSOLE UNIT TO C
	LD	B,BF_CIOOUT		; HBIOS FUNC: OUTPUT CHAR
	CALL	$FFF0			; HBIOS OUTPUTS CHARACTER
;
	; RESTORE ALL REGISTERS
	POP	HL
	POP	DE
	POP	BC
	POP	AF
	RET
;
;__CIN________________________________________________________________________
;
;	INPUT CHARACTER TO A
;_____________________________________________________________________________
;
CIN:
	; SAVE INCOMING REGISTERS (AF IS OUTPUT)
	PUSH	BC
	PUSH	DE
	PUSH	HL
;
	; INPUT CHARACTER FROM CONSOLE VIA HBIOS
	LD	C,CIO_CONSOLE		; CONSOLE UNIT TO C
	LD	B,BF_CIOIN		; HBIOS FUNC: INPUT CHAR
	CALL	$FFF0			; HBIOS READS CHARACTER
	LD	A,E			; MOVE CHARACTER TO A FOR RETURN
;
	; RESTORE REGISTERS (AF IS OUTPUT)
	POP	HL
	POP	DE
	POP	BC
	RET
;
;__CST________________________________________________________________________
;
;	RETURN INPUT STATUS IN A (0 = NO CHAR, !=0 CHAR WAITING)
;_____________________________________________________________________________
;
CST:
	; SAVE INCOMING REGISTERS (AF IS OUTPUT)
	PUSH	BC
	PUSH	DE
	PUSH	HL
;
	; GET CONSOLE INPUT STATUS VIA HBIOS
	LD	C,CIO_CONSOLE		; CONSOLE UNIT TO C
	LD	B,BF_CIOIST		; HBIOS FUNC: INPUT STATUS
	CALL	$FFF0			; HBIOS RETURNS STATUS IN A
;
	; RESTORE REGISTERS (AF IS OUTPUT)
	POP	HL
	POP	DE
	POP	BC
	RET
;
#ENDIF
;
;__WORK_AREA__________________________________________________________________
;
;	RESERVED RAM FOR MONITOR WORKING AREA
;_____________________________________________________________________________
;
KEYBUF:  	.FILL	BUFLEN,0
;
;__TEXT_STRINGS_______________________________________________________________
;
;	SYSTEM TEXT STRINGS
;_____________________________________________________________________________
;
;TXT_PROMPT	.TEXT	"\r\n>$"
TXT_READY	.TEXT	"\r\n\r\nMonitor Ready$"
TXT_COMMAND	.TEXT	"\r\nUnknown Command$"
TXT_ERR		.TEXT	"\r\nSyntax Error$"
TXT_IMERR	.TEXT	"\r\nCommand not available under interrupt mode 1$"
TXT_CKSUMERR	.TEXT	"\r\nChecksum Error$"
TXT_RECORDERR	.TEXT	"\r\nRecord Type Error$"
TXT_LOADED	.TEXT	"\r\nLoaded$"
TXT_BADNUM	.TEXT	" *Invalid Hex Byte Value*$"
TXT_MINIHELP	.TEXT	" (? for Help)$"
TXT_HELP	.TEXT	"\r\nMonitor Commands (all values in hex):"
		.TEXT	"\r\nB                - Boot system"
		.TEXT	"\r\nD xxxx [yyyy]    - Dump memory from xxxx to yyyy"
		.TEXT	"\r\nF xxxx yyyy zz   - Fill memory from xxxx to yyyy with zz"
		.TEXT	"\r\nH                - Halt system"
		.TEXT	"\r\nI xxxx           - Input from port xxxx"
		.TEXT	"\r\nK                - Keyboard echo"
		.TEXT	"\r\nL                - Load Intel hex data"
		.TEXT	"\r\nM xxxx yyyy zzzz - Move memory block xxxx-yyyy to zzzz"
		.TEXT	"\r\nO xxxx yy        - Output value yy to port xxxx"
		.TEXT	"\r\nP xxxx           - Program RAM at address xxxx"
		.TEXT	"\r\nR xxxx [[yy] [zzzz]]  - Run code at address xxxx"
		.TEXT	"\r\n                        Pass yy and zzzz to register A and BC"
#IF (BIOS == BIOS_WBW)
		.TEXT	"\r\nS xx             - Set bank to xx"
		.TEXT	"\r\nU                - Set bank to previous bank"
#ENDIF
#IF (ENA_XM)
		.TEXT	"\r\nT xxxx           - X-modem transfer to memory location xxxx"
#ENDIF
#IF (BIOS == BIOS_WBW)
  #IF ((PLATFORM == PLT_MBC) & ENA_MBC6502)
		.TEXT	"\r\n6 xx             - Transfer control to MBC6502 unit xx"
  #ENDIF
#ENDIF
		.TEXT	"\r\nX                - Exit monitor"
		.TEXT	"$"
;
#IF DSKYENABLE
;
KY_PR	.EQU	KY_FW		; USE [FW] FOR [PR] (PORT READ)
KY_PW	.EQU	KY_BK		; USE [BW] FOR [PW] (PORT WRITE)
;
;__DSKY_ENTRY_________________________________________________________________
;
;	DSKY FRONT PANEL STARTUP
;_____________________________________________________________________________
;
DSKY_ENTRY:
	; SHOULD WE DO SOMETHING HERE TO CONFIRM THAT A DSKY
	; IS ACTUALLY OPERATING???
	LD	SP,MON_STACK		; SET THE STACK POINTER
	LD	HL,DSKY_ENTRY		; RESTART ADDRESS
	CALL	INITIALIZE
;
;__FRONT_PANEL_STARTUP________________________________________________________
;
;	START UP THE SYSTEM WITH THE FRONT PANEL INTERFACE
;_____________________________________________________________________________
;
	CALL 	DSKY_BEEP
;
;__COMMAND_PARSE______________________________________________________________
;
;	PROMPT USER FOR COMMANDS, THEN PARSE THEM
;_____________________________________________________________________________
;
FRONTPANELLOOP:
	LD	C,DSKY_MSG_MON_RDY
	CALL	DSKY_MSG
	CALL 	DSKY_HIGHLIGHTCMDKEYS
	CALL 	DSKY_L1ON
	CALL	KB_GET			; GET KEY FROM DSKY
	PUSH	AF
	CALL 	DSKY_L1OFF
	POP	AF

FRONTPANELLOOP1:
	CP	KY_PR			; IS PORT READ?
	JP	Z,DOPORTREAD		; YES, JUMP
	CP	KY_PW			; IS PORT WRITE?
	JP	Z,DOPORTWRITE		; YES, JUMP
	CP	KY_DE			; IS DEPOSIT?
	JP	Z,DODEPOSIT		; YES, JUMP
	CP	KY_EX			; IS EXAMINE?
	JP	Z,DOEXAMINE		; YES, JUMP
	CP	KY_GO			; IS GO?
	JP	Z,DOGO			; YES, JUMP
	CP	KY_BO			; IS BOOT?
	JP	Z,DOBOOT		; YES, JUMP

	JR	FRONTPANELLOOP		; LOOP
;
;__DOBOOT_____________________________________________________________________
;
;	PERFORM BOOT FRONT PANEL ACTION
;_____________________________________________________________________________
;
DOBOOT:
	LD	C,DSKY_MSG_MON_BOOT
	CALL	DSKY_MSG
	JP	BOOT			; DO BOOT
;
;__DOPORTREAD_________________________________________________________________
;
;	PERFORM PORT READ FRONT PANEL ACTION
;       PANEL TEMPLATE "Po88  88"
;                  POS  01234567
;_____________________________________________________________________________
;
DOPORTREAD:
	CALL 	DSKY_HIGHLIGHTNUMKEYS
	CALL 	GETPORT			; GET PORT INTO A
PORTREADLOOP:
	LD	C,A			; STORE PORT IN "C"
	LD	DE,DISPLAYBUF+2		; POINT TO POS 2 IN BUF
	CALL	PUTVALUE		; DISPLAY PORT NUM
	IN 	A,(C)			; GET PORT VALUE FROM PORT IN "C"
	INC	DE			; ADVANCE BUF PTR
	INC	DE			; ... TO LAST TWO POSITIONS
	CALL	PUTVALUE		; DISPLAY PORT VALUE
	CALL	DISPLAY			; DISPLAY BUFFER CONTENTS
PORTREADGETKEY:
	CALL	KB_GET			; GET KEY FROM KB
	JR	PORTREADGETKEY		; NO VALID KEY, LOOP
;
;__DOPORTWRITE________________________________________________________________
;
;	PERFORM PORT WRITE FRONT PANEL ACTION
;       PANEL TEMPLATE "Po88  88"
;                  POS  01234567
;_____________________________________________________________________________
;
DOPORTWRITE:
	CALL 	DSKY_HIGHLIGHTNUMKEYS
	CALL 	GETPORT			; GET PORT INTO A
PORTWRITELOOP:
	LD	L,A			; SAVE PORT NUM
	LD	DE,DISPLAYBUF+2		; POINT TO POS 2 IN BUF
	CALL	PUTVALUE		; DISPLAY PORT NUM
	CALL	GETVALUE		; INPUT A BYTE VALUE, RETURN IN "A"
	LD	C,L			; RESTORE PORT NUM
	OUT	(C),A			; OUTPUT VALUE TO PORT STORED IN "C"
	LD	DE,DISPLAYBUF+6		; DISPLAY WRITTEN PORT VALUE
	CALL	PUTVALUE		; ... WITHOUT DP'S
	CALL	DISPLAY			; DISPLAY BUFFER CONTENTS
PORTWRITEGETKEY:
	CALL	KB_GET			; GET KEY FROM KB
	JR	PORTWRITEGETKEY		; NO VALID KEY, LOOP
;
;__DOGO_______________________________________________________________________
;
;	PERFORM GO FRONT PANEL ACTION
;_____________________________________________________________________________
;
DOGO:
	CALL 	DSKY_HIGHLIGHTNUMKEYS
	LD	HL,GOTO			; POINT TO "GO" MSG
	CALL	INITBUF
	CALL	GETVALW			; GET ADDRESS TO JUMP TO
	PUSH	HL
	CALL 	DSKY_HIGHLIGHTKEYSOFF
	POP	HL
	LD	DE,DISPLAYBUF+4
	LD	A,H
	CALL	PUTVALUE
	LD	A,L
	CALL	PUTVALUE
	CALL	DISPLAY			; DISPLAY
	JP	(HL)			; AND RUN
;
;__DOEXAMINE__________________________________________________________________
;
;	PERFORM EXAMINE FRONT PANEL ACTION
;       PANEL TEMPLATE "8888  88"
;                  POS  01234567
;_____________________________________________________________________________
;
DOEXAMINE:
	CALL 	DSKY_HIGHLIGHTNUMKEYS
	CALL 	GETADDR			; GET ADDRESS INTO HL
EXAMINELOOP:
	LD	DE,DISPLAYBUF+0
	LD	A,H
	CALL	PUTVALUE
	LD	A,L
	CALL	PUTVALUE
	LD	A,$10
	LD	(DE),A
	INC	DE
	LD	(DE),A
	INC	DE
	LD	A,(HL)			; GET VALUE FROM ADDRESS IN HL
	CALL	PUTVALUE
	CALL	DISPLAY			; DISPLAY BUFFER ON DISPLAYS
	CALL 	DSKY_HIGHLIGHTFWDKEYS
EXAMINEGETKEY:
	CALL	KB_GET			; GET KEY FROM KB
	CP	KY_EN			; [EN] PRESSED, INC ADDRESS AND LOOP
	JR	Z,EXAMINEFW		;
	JR	EXAMINEGETKEY		; NO VALID KEY, LOOP
EXAMINEFW:
	INC	HL			; HL++
	JR 	EXAMINELOOP		;
;
;__DODEPOSIT__________________________________________________________________
;
;	PERFORM DEPOSIT FRONT PANEL ACTION
;       PANEL TEMPLATE "8888  88"
;                  POS  01234567
;_____________________________________________________________________________
;
DODEPOSIT:
	CALL 	DSKY_HIGHLIGHTNUMKEYS
	CALL 	GETADDR			; GET ADDRESS INTO HL
DEPOSITLOOP:
	LD	DE,DISPLAYBUF+0
	LD	A,H
	CALL	PUTVALUE
	LD	A,L
	CALL	PUTVALUE
	LD	A,$10
	LD	(DE),A
	INC	DE
	LD	(DE),A
	CALL	GETVALUE		;
	LD	(HL),A			;
	LD	DE,DISPLAYBUF+6		; DISPLAY WRITTEN MEM VALUE
	CALL	PUTVALUE		; ... WITHOUT DP'S
	CALL	DISPLAY			; DISPLAY BUFFER CONTENTS
	CALL 	DSKY_HIGHLIGHTFWDKEYS
DEPOSITGETKEY:
	CALL	KB_GET			; GET KEY FROM KB
	CP	KY_EN			; [EN] PRESSED, INC ADDRESS AND LOOP
	JR	Z,DEPOSITFW		;
	JR	DEPOSITGETKEY		; NO VALID KEY, LOOP
DEPOSITFW:
	INC	HL			;
	JR 	DEPOSITLOOP		;
;
;__GETADDR____________________________________________________________________
;
;	GET ADDRESS FROM FRONT PANEL
;       PANEL TEMPLATE "Adr 8888"
;                  POS  01234567
;_____________________________________________________________________________
;
GETADDR:
	LD	HL,ADDR			; INITIALIZE DISPLAYBUF
	CALL	INITBUF
	JR	GETVALW
;
;__GETVAL16___________________________________________________________________
;
;	GET 16 BIT VALUE FROM FRONT PANEL
;       PANEL TEMPLATE "????8888"
;                  POS  01234567
;_____________________________________________________________________________
;
GETVALW:
	LD	A,$80			;
	LD	(DISPLAYBUF+4),A	;
	LD	(DISPLAYBUF+5),A	;
	LD	(DISPLAYBUF+6),A	;
	LD	(DISPLAYBUF+7),A	;
GETVALW1:
	CALL	DISPLAY			;
GETVALWLOOP:
	CALL	KB_GET			;
	CP	$10			;
	JP	M,GETVALWNUM		; NUMBER PRESSED, STORE IT
	CP	KY_EN			; [EN] PRESSED, DONE
	JR	Z,GETVALWDONE		;
	JR	GETVALWLOOP		; INVALID KEY, LOOP
GETVALWNUM:
	OR	$80			; SET DP
	LD	C,A			;
	LD	A,(DISPLAYBUF+5)	; SHIFT BYTES IN DISPLAY BUF TO THE LEFT
	LD      (DISPLAYBUF+4),A	;
	LD	A,(DISPLAYBUF+6)	;
	LD	(DISPLAYBUF+5),A	;
	LD	A,(DISPLAYBUF+7)	;
	LD	(DISPLAYBUF+6),A	;
	LD	A,C			; DISPLAY KEYSTROKE IN RIGHT MOST DISPLAY (0)
	LD	(DISPLAYBUF+7),A	;
	JR	GETVALW1		;
GETVALWDONE:
	LD	A,(DISPLAYBUF+6)	; GET DIGIT IN DISPLAY 6
	AND	$0F
	SLA	A			; ROTATE IT TO HIGH NIBBLE
	SLA	A			;
	SLA	A			;
	SLA	A			;
	LD	C,A			; STORE IT IN "C"
	LD	A,(DISPLAYBUF+7)	; GET DIGIT IN DISPLAY 7
	AND	$0F
	OR	C			; ADD IN NIBBLE STORED IN C
	LD	L,A			; STORE IT IN LOW BYTE OF ADDRESS POINTER
	LD	A,(DISPLAYBUF+4)	; GET DIGIT IN DISPLAY 4
	AND	$0F
	SLA	A			; ROTATE IT TO HIGH NIBBLE
	SLA	A			;
	SLA	A			;
	SLA	A			;
	LD	C,A			; STORE IT IN "C"
	LD	A,(DISPLAYBUF+5)	; GET DIGIT IN DISPLAY 5
	AND	$0F
	OR	C			; ADD IN NIBBLE STORED IN "C"
	LD	H,A			; STORE BYTE IN HIGH BYTE OF ADDRESS POINTER
	RET
;
;__GETPORT____________________________________________________________________
;
;	GET PORT FROM FRONT PANEL
;       PANEL TEMPLATE "Port  88"
;                  POS  01234567
;_____________________________________________________________________________
;
GETPORT:
	LD	HL,PORT			; INITIALIZE DISPLAYBUF
	CALL	INITBUF
	JR	GETVALUE
;
;__GETVALUE___________________________________________________________________
;
;	GET 8 BIT VALUE FROM FRONT PANEL
;       PANEL TEMPLATE "??????88"
;                  POS  01234567
;_____________________________________________________________________________
;
GETVALUE:
	LD	A,$80			;
	LD	(DISPLAYBUF+6),A	;
	LD	(DISPLAYBUF+7),A	;
GETVALUE1:
	CALL	DISPLAY			;
GETVALUELOOP:
	CALL	KB_GET			;
	CP	$10			;
	JP	M,GETVALUENUM		; NUMBER PRESSED, STORE IT
	CP	KY_EN			; [EN] PRESSED, DONE
	JR	Z,GETVALUEDONE		;
	JR	GETVALUELOOP		; INVALID KEY, LOOP
GETVALUENUM:
	OR	$80			; SET DP
	LD	C,A			;
	LD	A,(DISPLAYBUF+7)	;
	LD	(DISPLAYBUF+6),A	;
	LD	A,C			;
	LD	(DISPLAYBUF+7),A	;
	JR	GETVALUE1		;
GETVALUEDONE:
	LD	A,(DISPLAYBUF+6)	;
	AND	$0F
	RLCA				;
	RLCA				;
	RLCA				;
	RLCA				;
	LD	C,A			;
	LD	A,(DISPLAYBUF+7)	;
	AND	$0F
	OR	C			;
	RET
;
;__PUTVALUE___________________________________________________________________
;
;  INSERT HEX DIGITS OF A INTO AN ENCODED DSKY DISPLAY BUFFER
;  AT POSTION SPECIFIED BY DE.  ON RETURN, DE POINTS TO NEXT
;  POSITION IN DISPLAY BUFFER.
;_____________________________________________________________________________
;
PUTVALUE:
	PUSH	AF			; SAVE INCOMING VALUE
	RLCA				; HIGH NIBBLE -> LOW NIBBLE
	RLCA				; ...
	RLCA				; ...
	RLCA				; ...
	AND	$0F			; ISOLATE LOW NIBBLE
	LD	(DE),A			; PLACE DIGIT VALUE IN BUFFER
	INC	DE			; NEXT BUFFER POSITION
	POP	AF			; RECOVER ORIGINAL VALUE
	AND	$0F			; ISOLATE LOW NIBBLE
	LD	(DE),A			; PLACE DIGIT VALUE IN BUFFER
	INC	DE			; NEXT BUFFER POSITION
	RET				; DONE
;
;__KB_GET_____________________________________________________________________
;
;  GET A SINGLE KEY AND DECODE
;
;_____________________________________________________________________________
;
KB_GET:
	PUSH	BC
	PUSH	DE
	PUSH 	HL			; SAVE HL
	CALL	DSKY_GETKEY		; GET A KEY
	LD	A,E			; PUT KEY CODE IN A
	CP	KY_EN			; ENTER?
	JR	Z,KB_GET1		; IF YES, RET TO CALLER
	CP	$10			; HEX DIGIT?
	JR	C,KB_GET1		; IF YES, RET TO CALLER
	; NOT A DIGIT OR [EN], BAIL OUT TO MAIN LOOP TO HANDLE IT
	LD	SP,MON_STACK		; CLEAR STACK
	JP	FRONTPANELLOOP1		; RESTART AT MAIN LOOP
KB_GET1:
	POP	HL			; RESTORE HL
	POP	DE
	POP	BC
	RET
;
;__INITBUF____________________________________________________________________
;
;  INITIALIZE DISPLAY BUFFER FROM VALUE AT ADDRESS IN HL
;_____________________________________________________________________________
;
INITBUF:
	LD	DE,DISPLAYBUF
	LD	BC,8
	LDIR
	RET
;
;__DISPLAY   _________________________________________________________________
;
;  DISPLAY CONTENTS OF DISPLAYBUF
;_____________________________________________________________________________
;
DISPLAY:
	PUSH	AF
	PUSH	BC
	PUSH	DE
	PUSH	HL
	LD	HL,DISPLAYBUF
	CALL	DSKY_SHOW
	POP	HL
	POP	DE
	POP	BC
	POP	AF
	RET
;
;_____________________________________________________________________________
;
;  DSKY INTERFACE ROUTINES
;_____________________________________________________________________________
;
DSKY_GETKEY:
	LD	B,BF_DSKYGETKEY
	RST	08
	RET
;
DSKY_SHOW:
	LD	B,BF_DSKYSHOWSEG
	RST	08
	RET
;
DSKY_BEEP:
	LD	B,BF_DSKYBEEP
	RST	08
	RET
;
DSKY_L1ON:
	LD	E,1
	JR	DSKY_STATLED
DSKY_L1OFF:
	LD	E,0
DSKY_STATLED:
	LD	B,BF_DSKYSTATLED
	LD	D,0
	RST	08
	RET
;
DSKY_PUTLED:
	LD	B,BF_DSKYKEYLEDS
	RST	08
	RET
;
DSKY_HIGHLIGHTFWDKEYS:
	LD	DE,DSKY_HIGHLIGHTFWDKEYLEDS
	JR 	DSKY_HIGHLIGHT
;
DSKY_HIGHLIGHTCMDKEYS:
	LD	DE,DSKY_HIGHLIGHTCMDKEYLEDS
	JR 	DSKY_HIGHLIGHT
;
DSKY_HIGHLIGHTNUMKEYS:
	LD	DE,DSKY_HIGHLIGHTNUMKEYLEDS
	JR 	DSKY_HIGHLIGHT
;
DSKY_HIGHLIGHTKEYSOFF:
	LD	DE,DSKY_HIGHLIGHTKEYLEDSOFF
	JR 	DSKY_HIGHLIGHT
;
DSKY_HIGHLIGHT:
	PUSH	HL
	EX	DE,HL
	CALL	DSKY_PUTLED
	POP	HL
	RET
;
DSKY_MSG:
	LD	B,BF_DSKYMESSAGE
	RST	08
	RET

DSKY_HIGHLIGHTFWDKEYLEDS	.DB 	$00,$00,$00,$30,$00,$00,$00,$00
DSKY_HIGHLIGHTCMDKEYLEDS	.DB 	$20,$00,$20,$3F,$00,$00,$00,$00
DSKY_HIGHLIGHTNUMKEYLEDS	.DB 	$1F,$3F,$1F,$30,$00,$00,$00,$00
DSKY_HIGHLIGHTKEYLEDSOFF	.DB 	$00,$00,$00,$00,$00,$00,$00,$00
;
ADDR	.DB	$17,$18,$19,$10,$00,$00,$00,$00	; "Adr 0000" (ENCODED FOR SHOWSEG)
PORT	.DB	$13,$14,$15,$16,$10,$10,$00,$00	; "Port  00" (ENCODED FOR SHOWSEG)
GOTO	.DB	$1A,$14,$10,$10,$00,$00,$00,$00	; "Go  0000" (ENCODED FOR SHOWSEG)
;
DISPLAYBUF:	.FILL	8,0
;
#ELSE
;
DSKY_ENTRY:
	JP	EXIT
;
#ENDIF
;
;==================================================================================================
; UTILITY FUNCTIONS
;==================================================================================================
;
CHR_BEL		.EQU	07H
CHR_CR		.EQU	0DH
CHR_LF		.EQU	0AH
CHR_BS		.EQU	08H
CHR_ESC		.EQU	1BH
CHR_DEL		.EQU	7FH
;
;__________________________________________________________________________________________________
;
; UTILITY PROCS TO PRINT SINGLE CHARACTERS WITHOUT TRASHING ANY REGISTERS
;
PC_SPACE:
	PUSH	AF
	LD	A,' '
	JR	PC_PRTCHR
PC_COLON:
	PUSH	AF
	LD	A,':'
	JR	PC_PRTCHR
PC_CR:
	PUSH	AF
	LD	A,CHR_CR
	JR	PC_PRTCHR

PC_LF:
	PUSH	AF
	LD	A,CHR_LF
	JR	PC_PRTCHR

PC_PRTCHR:
	CALL	COUT
	POP	AF
	RET

NEWLINE2:
	CALL	NEWLINE
NEWLINE:
	CALL	PC_CR
	CALL	PC_LF
	RET
PRTSTR:
	LD	A,(HL)
	INC	HL
	CP	'$'
	RET	Z
	CALL	COUT
	JR	PRTSTR
;
; PRINT THE HEX BYTE VALUE IN A
;
PRTHEXBYTE:
	PUSH	AF
	PUSH	DE
	CALL	HEXASCII
	LD	A,D
	CALL	COUT
	LD	A,E
	CALL	COUT
	POP	DE
	POP	AF
	RET
;
; CONVERT BINARY VALUE IN A TO ASCII HEX CHARACTERS IN DE
;
HEXASCII:
	LD	D,A
	CALL	HEXCONV
	LD	E,A
	LD	A,D
	RLCA
	RLCA
	RLCA
	RLCA
	CALL	HEXCONV
	LD	D,A
	RET
;
; CONVERT LOW NIBBLE OF A TO ASCII HEX
;
HEXCONV:
	AND	0FH	     ;LOW NIBBLE ONLY
	ADD	A,90H
	DAA
	ADC	A,40H
	DAA
	RET
;
; ADD HL,A
;
;   A REGISTER IS DESTROYED!
;
ADDHLA:
	ADD	A,L
	LD	L,A
	RET	NC
	INC	H
	RET
;
;
;
		.FILL	16,0		; SET MINIMUM STACK DEPTH
SLACK		.EQU	(MON_END - $)
		.FILL	SLACK,00H
;
MON_STACK	.EQU	$
;
		.ECHO	"DBGMON space remaining: "
		.ECHO	SLACK
		.ECHO	" bytes.\n"
;
		.END
