
; Definitions
CRTRAM:	EQU	2000H			;CRT RAM ADDRESS
CUR:	EQU	05FH			;UNDERLINE CHARACTER FOR CURSOR
BL:	EQU	' '			;SPACE
FF:	EQU	01EH			;CLEAR SCREEN
CR:	EQU	01FH			;RETURN
BS:	EQU	01DH			;BACKSPACE
CURLIN	EQU	CRTRAM + 10 + (14 * 64) ;CURRENT CRT LINE
LINE:	EQU	CURLIN - 64		;PREVIOUS LINE

		ORG	0

START:
	LD	SP,STACK		;INITIAL STACK
	LD	HL,RAMZ			;FIRST LOCATION OF WORK AREA
	LD	B,RAME - RAMZ		;NUMBER TO CLEAR
START1:
	LD	(HL),0			;CLEAR LOCATION IN WORK AREA
	INC	HL
	DJNZ	START1			;B LOCATIONS
	LD	HL,INITT		;SET UP REFLECTION IN RAM
	LD	DE,INITR
	LD	BC,INITE - INITT
	LDIR
	LD	A,FF			;CLEAR SCREEN
	CALL	CRT
	JP	STRT0			;START OF MONITOR

;++++++++++++++++++++++++BREAKPOINT ENTRY

	PUSH	AF			;SAVE REGISTER
	PUSH	HL
	PUSH	DE
	JP	BPT1			;BREAKPOINT 
	NOP
	NOP

;++++++++++++++++++++++++PRINT STRING LOCATION IN SP

PRS:
	EX	(SP),HL			;PREPARE POINTERS
PRS1:
	LD	A,(HL)			;FETCH CHARACTER
	INC	HL			;ADVANCE POINTER
	OR	A
	JR	Z,PRS2			;EXIT IF NULL END MARKER FOUND
	CALL	@CRT			;LOAD TO SCREEN AT CURSOR POSITION
	JR	PSR1
PSR2:
	EX	(SP),HL			;AT END RESTORE POINTER AND EXIT
	RET

;+++++++++++++++++++++++KEYBOARD DELAY TIMER

KDEL:
	XOR	A			;LOOP 256 TIMES
KDEL1:
	PUSH	AF
	POP	AF
	PUSH	AF
	POP	AF
	DEC	A
	JR	NZ,KDEL1
	RET

;+++++++++++++++++++++++ROUTINE TO INPUT KEYBOARD OR UART CHARACTER

CHIN:
	CALL	@KBD			;SEE IF CHARACTER AVAILABLE
	RET	C			;RETURN CHARACTER
	IN	A,02			;CHECK UART
	RLA
	JR	NC,CHIN			;LOOP IF NO CHARACTER
	IN	A,01			;GET CHARACTER
	RET

;++++++++++++++++++++++ROUTINE TO PULE BITS OF PORT 0 AS SET IN A

FPFLP:
	PUSH	AF
	CALL	FLIP			;ONE WAY
	POP	AF
	JR	FLIP			;THEN BACK AND EXIT

;++++++++++++++++++++++TOGGLE MOTOR ON BIT FOR CASSETTE

MOTFLP:
	LD	A,10H			;BIT 4

;++++++++++++++++++++++TOGGLE SELECTED BIT OF PORT 0

FLIP:
	PUSH	HL
	LD	HL,PORT0		;RECOVER LAST STATE OF PORT 0
	XOR 	(HL)			;TOGGLE SELECTED BIT
	OUT	0,A			;OUTPUT NEW STATE
	LD	(HL),A			;NOTE NEW VALUE FOR NEXT TIME
	POP	HL
	RET

;+++++++++++++++++++++LOAD CHARACTER TO UART

SRLOUT:
	OUT	1,A			;OUTPUT CHARACTER
SRL1:
	IN	A,2
	ADD	A,A
	RET	M			;RETURN WENN CHAR SENT
	NOP

;+++++++++++++++++++++VECTORED JUMP

NMIVEC:
	JP	@NMI

;+++++++++++++++++++++keyboard routine

KBD:
	PUSH	BC			;SAVE REGISTER
	PUSH	DE
	PUSH	HL
	LD	A,2			;PULSE BIT 1 OF PORT 0 TO RESET COUNTER
	CALL	FLPFLP
	LD	HL,KMAP
	IN	A,0			;READ ROW 0
	CPL
	LD	(HL),A			;SAVE SHIFT INFORMATION
	LD	B,8			;
KSC1:
	LD	A,1			;
	CALL	FLPFLP			;PULE BIT 0 OF POTRT 0 TO CLOCK COUNTER
	INC	HL			;INCREMENT KMAP POINTER
	IN	A,0			;INPUT ROW CONTENS
	CPL
	LD	D,A			;SAVE IT FOR LATER
	XOR	(HL)
	JR	NZ,KSC2			;IF CHANGE DTECTED
KSC1A:
	DJNZ	KSC1			;LOOP UNTIL 8TE ROW
KSC8:
	OR	A			;NO KEY DETECTED
KSC9:
	POP	HL			;EXIT FROM ROUTINE
	POP	DE
	POP	BC
	RET
KSC2:
	CALL	KDEL			;DELAY 7MS
	IN	A,0			;READ IN ROW AGAIN
	CPL
	LD	E,A
	LD	A,D			;RECOVER LAST STATE
	XOR	(HL)
	LD	C,0FFH
	LD	D,0
	SCF
KSC4:
	RL	D			;CONSTRUCT BIT MASK IN D
	INC	C			;COLUMN BIT IN C
	RRA
	JR	NC,KSC4
	LD	A,D			;RECOVER LAST STATE
	AND	E
	LD	E,A
	LD	A,(HL)			;CHECK TO SEE IF FALSE READING
	AND	D
	CP	E
	JR	Z,KSC1A			;FALSE READING CHECK NEXT COLUMN
	LD	A,(HL)
	XOR	D
	LD	(HL),A			;FURTHER VALIDATE CHECK
	LD	A,E
	OR	A			;
	JR	Z,KSC1A			;GO ON CHECKING STILL A FALSE READING
	LD	A,(KMAP)		;SAVE IN KMAP FOR NEXT TIME
	AND	10H			;CONSTRUCT THE ASCII VALUE
	OR	B
	ADD	A,A
	ADD	A,A
	ADD	A,A
	OR	C
	LD	BC,(@KTABL)		;USING THE LOOK UP TABLE
	LD	HL,(@KTAB)
	CPIR
	JR	Z,KSC5			;AND SHIFT INFORMATION
	LD	HL,(@KTAB)		;IF APPROPRIATE
	LD	BC,(@KTABL)
	AND	7FH
	CPIR
	JR	NZ,KSC8			;CHARACTER NOT FOUND IN TABLE
KSC5:
	LD	BC,(@KTAB)
	SCF
	SBC	HL,BC
	LD	BC,(@KTAB0)
	ADD	HL,BC
	LD	A,L			;RECOVER ACTUAL CHARACTER
KSC3:
	SCF				;SET CARRY FLAG TO INDICATE ASCII AVAIL
	JR	KSC9			;AND FINISH OFF ROUTINE
;+++++++++++++++++++++++++++SET BREAK POINT

BREAK:
	LD	HL,(ARG1)		;BREAKPOINT REQUESTED
	LD	(BRKADR),HL		;NOT IT FOR WHEN BREAK OCCURS
	RET
;+++++++++++++++++++++++++++KEYBOARD LOOKUP TABLE

KTAB:
	DB	08H,88H,09H				;BS,FF,CR
	DB	014H,09CH,09BH,0A3H,092H,0C2H,0BAH,0B2H ;SP TO '
	DB	0AAH,0A2H,098H,0A0H,029H,00AH,021H,019H ;(  TO /
	DB	01AH,01CH,01BH,023H,012H,042H,03AH,032H ;0  TO 7
	DB	02AH,022H,018H,020H,0B1H,08AH,0B9H,099H ;8  TO ?
	DB	00DH,02CH,041H,013H,03BH,033H,043H,010H ;@  TO G
	DB	040H,02DH,038H,030H,028H,031H,039H,025H ;H  TO O
	DB	01DH,024H,015H,034H,045H,035H,011H,02BH ;P  TO W
	DB	044H,03DH,03CH				;X,Y,Z  

;++++++++++++++++++++++++++++RAM IMAGE MAP

INITT:
	DW	1000H			;END OF RAM
	DW	64 + 3 - 5		;@KTABL
	DW	32 - 3			;@KTABO
	DW	KTAB
	DW	CTAB
	JP	TRAP
	JP	CRT
	JP	KBD
INITE:

;++++++++++++++++++++++++++++SCREEN HANDLER

CRT:
	OR	A
	RET	Z			;IGNOR NULLS
	PUSH	AF
	PUSH	BC
	PUSH	DE
	PUSH	HL
	CP	FF
	JR	NZ,CRT2A		;NOT CLEAR SCREEN
	LD	HL,CRTRAM + 9
	LD	(HL),-1			;MARKER START OF SCRREN MEMORY
	INC	HL
	LD	B,48
CRT01:
	LD	(HL),BL			;LOAD 48 SPACES TO FIRST SCREEN LINE
	INC	HL
	DJNZ	CRT01
	LD	B,16
CRT02:
	LD	(HL),0			;FILL NON DISPLAYED POSITIONS
	INC	HL
	DJNZ	CRT02
	EX	DE,HL			;NOTE POSITION FOR LATER
	LD 	HL,CRTRAM + 10
	LD	BC,15 * 64 - 16
	LDIR				;COPY FIRST LINE TO REMAINIGN LINES
	LD	A,-1			;MARKER END OF SCREEN MEMORY
	LD	(CRTRAM + (14 * 64) + 58,A
CRT0:
	LD	HL,CURLIN		;SET CURSOR TO START OF BOTTOM LINE
CRT1:
	LD	(HL),CUR
	LD	(CURSOR),HL
CRT2:
	POP	HL
	POP	DE
	POP	BC
	POP	AF
	RET
CRT2A:
	LD	HL,(CURSOR)		;REPLACE CURSOR WITH SPACE
	LD	(HL),BL
	CP	BS
	JR	NZ,CRT2C		;NOT CURSOR BACKSPACE
CRT2B:
	DEC	HL			;MOVE CURSOR BACK
	LD	A,(HL)
	OR	A
	JR	Z,CRT2B			;SKIP OVER ON DISPLAYED AREA
	INC	A
	JR	NZ,CRT1			;DISPLAY CURSOR IN NEW POSITION
	INC	HL
	JR	CRT1			;BUT IF OFF SCREEN PUT BACK ON
CRT2C:
	CP	CR
	JR	Z,CRT3			;CR
	LD	(HL),A
CRT2D:
	INC	HL			;ADVANCE CURSOR TO NEXT POSITION
	LD	A,(HL)
	OR	A
	JR	Z,CRT2D			;SKIP OVER NON DISPLAYED AREA
	INC	A
	JR	NZ,CRT1			;DISPLAY CURSOR UNLESS OFF SCREEN
CRT3:
	LD	DE,CRTRAM + 10		;SCROLL SCREEN UP ONE LINE
	LD	HL,CRTRAM + 10 + 64
	LD	BC,14 * 64 - 16
	LDIR
	LD	HL,16
	ADD	HL,DE
	LD	B,48
CRT3A:
	LD	(HL),BL			;LOAD SPACES TO BOTTOM LINE				 
	INC	HL
	DJNZ	CRT3A
	JR	CRT0			;SET CURSOR TO START FIRST LINE & EXIT

;++++++++++++++++++++++++++++DISPLAY & MODIFY RAM

MODIFY:
	LD	HL,(ARG1)		;ADDRESS TO BE DISPLAYED
MOD1:
	CALL	TBCD3			;DISPLAY THE ADDRESS
	LD	A,(HL)
	CALL	B2HEX			;DISPLAY CONTENS OF THE ADRESS
	CALL	INLINE			;PUT UP PROMPT AND GET NEW INFORMATION
	LD	DE,LINE + 8
	LD	B,0			;ZERO TALLY COUNTER
MOD2:
	PUSH	HL
	CALL	NEXNUM			;READ IN NEXT VALUE
	LD	A,(HL)
	OR	A
	JR	Z,MOD3			;NUMBER NOT VALID
	INC	HL
	LD	A,(HL)
	POP	HL
	LD	(HL),A			;SAVE NEW VALUE IN LOCATION
	INC	B
	INC	HL
	JR	MOD2
MOD3:
	POP	HL
	LD	A,(DE)			;GET NEXT CHARACTER
	CP	'.'
	RET	Z			;RETURN TO COMMAND MODE IF . KEYED
	LD	A,B
	OR	A
	JR	NZ,MOD4			;FINISH LINE GET NEXT BYTE
	INC	HL
MOD4:
	JR	MOD1

;++++++++++++++++++++++++++++READ A LINE

INLINE:
	RST	28H
	DB	3EH,00H			;DISPLAY PROMPT SEQUENCE
INL0:
	CALL	CHIN			;GET A CHARACTER
	CP	BS
	JR	Z,INL2			;BACKSPACE
	CP	CR
	JR	Z,CRLF
INL1:
	CALL	@CRT			;DISPLAY CHARACTER
	JR	INL0			;GET NEXT
INL2:
	LD	DE,(CURSOR)		;BACKSPACE CURSOR
	DEC	DE
	LD	A,(DE)
	CP	03EH
	JR	Z,INL0			;BUT NOT OVER PROMPT
	LD	A,BS
	JR	INL1			;DO BACKSPACE CURSOR

;++++++++++++++++++++++++++++DISPLAY CONTENS OF MEMORY N.B. IN BLOCKS OF 8

TABCDE:
	LD	HL,(ARG1)		;SET UP START ADDRESS
TABCD1:
	LD	DE,(ARG2)		;TEST FOR COMPLETION
	PUSH	HL
	OR	A
	SBC	HL,DE
	POP	HL
	JR	CTBCD10			;NOT COMPLETED
	RST	28H			;FINISH DISPLAY DATA NOW PROMPT
	DB	'.',CR,0
	RET				;RETURN TO COMMAND MODE
TBCD10:
	LD	C,0			;DISPLAY ADDRESS
	CALL	TBCD3
	LD	B,8H			;8 LOCATIONS TO BE DISPLAYED INA LINE
TBCD1A:
	LD	A,(HL)
	CALL	TBCD2			;DISPLAY LOCATION CONTENT
	INC	HL			;NEXT LOCATION
	CALL	SPACE			;SPACE TO SEPARATE VALUES DISPLAYED
	DJNZ	TBCD1A			;8 LOCATIONS
	LD	A,C			;
	CALL	B2HEX			;DISPLAY CHECKSUM
	RST	28H
	DB	BS,BS,CR,00H
	JR	TBCD1			;SEE IF FINISHED

; DISPLAY HEX VALUES ACCUMULATING CHECKSUM

TBCD2:
	LD	D,A
	ADD	A,C
	LD	C,A			;NEW CHECKSUM
	LD	A,D
	JP	B2HEX			;DISPLAY VALUE IN HEX

; DISPLAY ADDRESS IN HEX

TBCD3:
	LD	A,H
	CALL	TBCD2			;HIGH ORDER ADDRESS
	LD	A,L
	CALL	TBCD2			;LOW ODERE ADDRESS
	JR	SPACE
 
; DISPLAY A SPACE

SPACE:
	LD	A,BL
	JR	JCRT			;GO TO CRT ROUTINE TO DISP A SPACE

; CARRIGE RETURN LINE FEED

CRLF:
	LD	A,CR
	JR	JCRT

; BINARY TO HEX DISPLAY

B2HEX:
	PUSH	AF
	RRA
	RRA
	RRA
	RRA
	CALL	B2HEX1			;DISPLAY EFT NIBBLE
	POP	AF			;RIGHT HAND NIBBLE
B2HEX1:
	AND	0FH			;MASK TO BINARY VALUE
	ADD	A,'0'			;CONVERT TO ASCII NUMBER
	CP	'9'+1
	JR	C,JCRT
	ADD	A,7
JCRT:
	JP	@CRT

;++++++++++++++++++++++++++++SUBROUTIE TO READ HEX NUMBER OF SCREEN

NEXNUM:
	LD	A,(DE)			;LINE POSITION IN DE
	CP	BL
	INC	DE
	JR	Z,NEXNUM		;SKIP OVER SPACES
	DEC	DE
	XOR	A
	LD	HL,NUM			;NUM IS NO. DIGITS IN NO.
	LD	(HL),A			;RESET NUM TO NULL
	INC	HL
	LD	(HL),A
NN1:
	LD	A,(DE)			;READ DIGIT
	DEC	HL
	DEC	HL
	SUB	A,'0'
	RET	M			;OUT OF RANGE
	CP	10
	JR	C,NN2			;IN RANGE SAVE IT
	SUB	A,7
	CP	10
	RET	M			;OUT OF RANGE
	CP	16
	RET	P			;OUT OF RANGE
NN2:
	INC	DE			;NEXT DIGIT
	INC	(HL)			;DIGIT COUNT + 1
	INC	HL
	RLD
	INC	HL
	RLD
	JR	NN1

;++++++++++++++++++++++++++++ LINE INTERPRETER

PARSE:
	CALL	INLINE			;PROMPT AND READ RESPONSE LINE
	LD	DE,LINE + 1
	LD	BC,ARGS
	LD	A,(DE)
	CP	BL
	JR	NZ,PARSE1		;NOT SPACE
	LD	A,(BC)
	CP	'S'
	JR	NZ,PARSE		;NOT IN SINGLE STEP MODE
PARSE1:
	LD	(BC),A			;SAVE COMMAND CHAR AT ARGS
	INC	BC
	INC	DE
	XOR	A
	LD	(BC),A			;SET NO. ARGS TO 0
PLOOP:
	INC	BC
	CALL	NEXNUM			;GET ARGUMENT
	LD	A,(HL)
	OR	A
	JR	Z,PEND			;NO MORE ARGUMENTS
	INC	HL
	LD	A,(HL)
	LD	(BC),A			;SAVE ARGUMENT IN ARG1/2/3 1ST PART
	INC	HL
	INC	BC
	LD	A,(HL)
	LD	(BC),A			;SECOND PART
	LD	HL,ARGS + 1
	INC	(HL)			;INCR. NO. ARGUMENTS COUNT
	JR	PLOOP			;SEE IF FURTHER ARGUMENTS
PEND:
	LD	BC,(ARGS)		;COMMAND TYPE COMPARE WITH THOSE IN
	LD	HL,(@CTAB)		;   COMMAND LOOKUP TABLE
PEND1:
	LD	A,(HL)
	OR	A
	JR	PARSE			;INVALID COMMAND IGNORE IT
	INC	HL
	CP	C
	JR	Z,PEND2			;COMMAND RECOGNISED
	NOP
	INC	HL			;BYPASS ADDRESS IN TABLE
	INC	HL
	JR	PEND1			;LOOP TILL COMMAND OR TABE END FOUND
PEND2:
	LD	E,(HL)			;GET LOW ORDER ADDRESS OR ROUTINE START
	INC	HL
	LD	D,(HL)			;HIGH ADDRESS
	LD	HL,PARSE
	PUSH	HL			;FORCE RETURN ADDRESS TO PARSE ON STACK
	EX	DE,HL
	JP	(HL)			;PSEUDO CALL TO SELECTED ROUTINE

;++++++++++++++++++++++++++++ EXECUTE PROGRAM

EXEC:
	LD	A,-1
	LD	(CONFLG),A		;SET CONFLG TO INDICATE NOT SINGLE STEP
EXEC1:
	LD	HL,TRAP			;INIT NMI REFLECTION
	LD	(@NMI + 1),HL
	POP	HL			;REMOVE RETURN TO PARSE
	LD	A,(ARGS + 1)
	OR	A
	JR	Z,EXEC2			;NO ARGUMENTS
