;##########################################################################
;# BSrom140 - Modified ZX Spectrum ROM - (c) Busy soft - Release 22.04.97 #
;#                   with enhancements needed for BSDOS                   #
;##########################################################################
;                         Original rom: (c) Amstrad



		OUTPUT	"bsrom140mb02.bin"

VERZIA:		EQU	140

VERA:		EQU	VERZIA/100
VERB:		EQU	VERA*100
VERC:		EQU	VERZIA-VERB
VERD:		EQU	VERC/10
VERE:		EQU	VERD*10
VERF:		EQU	VERC-VERE

VER1:		EQU	'0'+VERA
VER2:		EQU	'0'+VERD
VER3:		EQU	'0'+VERF

; BSDOS services
EM562:		EQU	#20
EM4C6:		EQU	#21
BASICM:		EQU	#31
FUNKC:		EQU	#32

		ORG	#0000

; RST #00
START:		DI
		XOR	A
		LD	DE,#FFFF
		JP	NMI_MENU		; BSROM - jumps to NMI menu instead of START_NEW

; Error restart
; RST #08
ERROR_1:	LD	HL,(#5C5D)
		CALL	TOERR			; BSROM - cursor jumps to error
		JR	ERROR_2

; Print a character
; RST #10
PRINT_A:	JP	PRINT_A_2

; Unused bytes
		DW	#FFFF
		DW	#FFFF
		DB	#FF

; Collect a character
; RST #18
GET_CHAR:	LD	HL,(#5C5D)
		LD	A,(HL)
TEST_CHAR:	CALL	SKIP_OVER
		RET	NC
NEXT_CHAR:	CALL	CH_ADD_1
		JR	TEST_CHAR

; Unused bytes
		DW	#FFFF
		DB	#FF

; Calculator restart
; RST #28
		JP	CALCULATE

; Unused bytes
		DW	#FFFF
		DW	#FFFF
		DB	#FF

; Create free locations in work space
; RST #30
BC_SPACES:	PUSH	BC
		LD	HL,(#5C61)
		PUSH	HL
		JP	RESERVE

; Maskable interrupt routine
; RST #38
MASK_INT:	PUSH	AF
		PUSH	HL
		LD	HL,(#5C78)
		INC	HL
		LD	(#5C78),HL
		LD	A,H
		OR	L
		JR	NZ,KEY_INT
		INC	(IY+#40)
KEY_INT:	PUSH	BC
		PUSH	DE
		CALL	KEYBOARD
		POP	DE
		POP	BC
		POP	HL
		POP	AF
		EI
		RET

; A continuation of the code at #0008
ERROR_2:	POP	HL
		LD	L,(HL)
ERROR_3:	LD	(IY+#00),L
		LD	SP,(#5C3D)
		JP	SET_STK

; Unused bytes
		DW	#FFFF
		DW	#FFFF
		DW	#FFFF
		DB	#FF

; Non-maskable interrupt routine
; RST #66
RESET:		JP	NMI_MENU		; BSROM - jumps to NMI menu

		DB	#B0			; Looks like this is unused torso 
		DB	#5C			; of the original RESET routine.
		DB	#7C			;
		DB	#B5			;
		DB	#20, #01		;
		DB	#E9			;
		DB	#E1			;
		DB	#F1			;
		DB	#ED, #45		; End of unused bytes.

; Fetch the next immediate character following the current valid character address
; and update the associated system variable.
CH_ADD_1:	LD	HL,(#5C5D)
TEMP_PTR1:	INC	HL
TEMP_PTR2:	LD	(#5C5D),HL
		LD	A,(HL)
		RET

; Skip over white-space and other characters irrelevant to the parsing of a basic line
SKIP_OVER:	CP	#21
		RET	NC
		CP	#0D
		RET	Z
		CP	#10
		RET	C
		CP	#18
		CCF
		RET	C
		INC	HL
		CP	#16
		JR	C,SKIPS
		INC	HL
SKIPS:		SCF
		LD	(#5C5D),HL
		RET

; Six look-up tables for keyboard reading routine to decode the key values.
; Table for tokenized characters (134d-255d).
; Begins with function type words without a leading space.
; The last byte of a token is inverted to denote the end of the word.
TKN_TABLE:	DC	"?"				
		DC	"RND"
		DC	"INKEY$"
		DC	"PI"
		DC	"FN"
		DC	"POINT"
		DC	"SCREEN$"
		DC	"ATTR"
		DC	"AT"
		DC	"TAB"
		DC	"VAL$"
		DC	"CODE"
		DC	"VAL"
		DC	"LEN"
		DC	"SIN"
		DC	"COS"
		DC	"TAN"
		DC	"ASN"
		DC	"ACS"
		DC	"ATN"
		DC	"LN"
		DC	"EXP"
		DC	"INT"
		DC	"SQR"
		DC	"SGN"
		DC	"ABS"
		DC	"PEEK"
		DC	"IN"
		DC	"USR"
		DC	"STR$"
		DC	"CHR$"
		DC	"NOT"
		DC	"BIN"
		
; Function type words with a leading space
; if they begin with a letter.	
		DC	"OR"			
		DC	"AND"
		DC	"<="
		DC	">="
		DC	"<>"
		DC	"LINE"
		DC	"THEN"
		DC	"TO"
		DC	"STEP"
		DC	"DEF FN"
		DC	"CAT"
		DC	"FORMAT"
		DC	"MOVE"
		DC	"ERASE"
		DC	"OPEN #"
		DC	"CLOSE #"
		DC	"MERGE"
		DC	"VERIFY"
		DC	"BEEP"
		DC	"CIRCLE"
		DC	"INK"
		DC	"PAPER"
		DC	"FLASH"
		DC	"BRIGHT"
		DC	"INVERSE"
		DC	"OVER"
		DC	"OUT"
		DC	"LPRINT"
		DC	"LLIST"
		DC	"STOP"
		DC	"READ"
		DC	"DATA"
		DC	"RESTORE"
		DC	"NEW"
		DC	"BORDER"
		DC	"CONTINUE"
		DC	"DIM"
		DC	"REM"
		DC	"FOR"
		DC	"GO TO"
		DC	"GO SUB"
		DC	"INPUT"
		DC	"LOAD"
		DC	"LIST"
		DC	"LET"
		DC	"PAUSE"
		DC	"NEXT"
		DC	"POKE"
		DC	"PRINT"
		DC	"PLOT"
		DC	"RUN"
		DC	"SAVE"
		DC	"RANDOMIZE"
		DC	"IF"
		DC	"CLS"
		DC	"DRAW"
		DC	"CLEAR"
		DC	"RETURN"
		DC	"COPY"

; maps for the standard 40-key ZX Spectrum keyboard
; SHIFT (#27) is read directly.
MAIN_KEYS:	DB	#42			;B
		DB	#48			;H
		DB	#59			;Y
		DB	#36			;6
		DB	#35			;5
		DB	#54			;T
		DB	#47			;G
		DB	#56			;V
		DB	#4E			;N
		DB	#4A			;J
		DB	#55			;U
		DB	#37			;7
		DB	#34			;4
		DB	#52			;R
		DB	#46			;F
		DB	#43			;C
		DB	#4D			;M
		DB	#4B			;K
		DB	#49			;I
		DB	#38			;8
		DB	#33			;3
		DB	#45			;E
		DB	#44			;D
		DB	#58			;X
		DB	#0E			;Symbol shift
		DB	#4C			;L
		DB	#4F			;O
		DB	#39			;9
		DB	#32			;2
		DB	#57			;W
		DB	#53			;S
		DB	#5A			;Z
		DB	#20			;Space
		DB	#0D			;Enter
		DB	#50			;P
		DB	#30			;0
		DB	#31			;1
		DB	#51			;Q
		DB	#41			;A

; Unshifted extended mode keys.
; The green keywords on the original keyboard.
E_UNSHIFT:	DB	#E3			;READ
		DB	#C4			;BIN
		DB	#E0			;LPRINT
		DB	#E4			;DATA
		DB	#B4			;TAN
		DB	#BC			;SGN
		DB	#BD			;ABS
		DB	#BB			;SQR
		DB	#AF			;CODE
		DB	#B0			;VAL
		DB	#B1			;LEN
		DB	#C0			;USR
		DB	#A7			;PI
		DB	#A6			;INKEY$
		DB	#BE			;PEEK
		DB	#AD			;TAB
		DB	#B2			;SIN
		DB	#BA			;INT
		DB	#E5			;RESTORE
		DB	#A5			;RND
		DB	#C2			;CHR$
		DB	#E1			;LLIST
		DB	#B3			;COS
		DB	#B9			;EXP
		DB	#C1			;STR$
		DB	#B8			;LN

; Shifted extended mode keys.
; The red keywords below keys on the original keyboard.
EXT_SHIFT:	DB	#7E			;~
		DB	#DC			;BRIGHT
		DB	#DA			;PAPER
		DB	#5C			;\
		DB	#B7			;ATN
		DB	#7B			;{
		DB	#7D			;}
		DB	#D8			;CIRCLE
		DB	#BF			;IN
		DB	#AE			;VAL$
		DB	#AA			;SCREEN$
		DB	#AB			;ATTR
		DB	#DD			;INVERSE
		DB	#DE			;OVER
		DB	#DF			;OUT
		DB	#7F			;(c)
		DB	#B5			;ASN
		DB	#D6			;VERIFY
		DB	#7C			;|
		DB	#D5			;MERGE
		DB	#5D			;]
		DB	#DB			;FLASH
		DB	#B6			;ACS
		DB	#D9			;INK
		DB	#5B			;[
		DB	#D7			;BEEP

; Shift key control codes assigned to the digits.
; White labels above the number characters on the digits keys on the orig. keyboard.
CTL_CODES:	DB	#0C			;DELETE
		DB	#07			;EDIT
		DB	#06			;Caps lock
		DB	#04			;True video
		DB	#05			;Inverse video
		DB	#08			;Cursor left
		DB	#0A			;Cursor down
		DB	#0B			;Cursor up
		DB	#09			;Cursor right
		DB	#0F			;GRAPH

; Keys shifted with Symbol shift.
; Red symbols on the alphabetic characters on the original keyboard.
SYM_CODES:	DB	#E2			;STOP
		DB	#2A			;*
		DB	#3F			;?
		DB	#CD			;STEP
		DB	#C8			;>=
		DB	#CC			;TO
		DB	#CB			;THEN
		DB	#5E			;^
		DB	#AC			;AT
		DB	#2D			;-
		DB	#2B			;+
		DB	#3D			;=
		DB	#2E			;.
		DB	#2C			;,
		DB	#3B			;;
		DB	#22			;"
		DB	#C7			;<=
		DB	#3C			;<
		DB	#C3			;NOT
		DB	#3E			;>
		DB	#C5			;OR
		DB	#2F			;/
		DB	#C9			;<>
		DB	#60			;£
		DB	#C6			;AND
		DB	#3A			;:

; Keywords assigned to the digits in extended mode.
; On the original keyboard those are remaining red keywords below the keys.
E_DIGITS:	DB	#D0			;FORMAT
		DB	#CE			;DEF FN
		DB	#A8			;FN
		DB	#CA			;LINE
		DB	#D3			;OPEN #
		DB	#D4			;CLOSE #
		DB	#D1			;MOVE
		DB	#D2			;ERASE
		DB	#A9			;POINT
		DB	#CF			;CAT

; Keyboard scanning
; returns 1 or 2 keys in DE
KEY_SCAN:	LD	L,#2F
		LD	DE,#FFFF
		LD	BC,#FEFE
KEY_LINE:	IN	A,(C)
		CPL
		AND	#1F
		JR	Z,KEY_DONE
		LD	H,A
		LD	A,L
KEY_3KEYS:	INC	D
		RET	NZ
KEY_BITS:	SUB	#08
		SRL	H
		JR	NC,KEY_BITS
		LD	D,E
		LD	E,A
		JR	NZ,KEY_3KEYS
KEY_DONE:	DEC	L
		RLC	B
		JR	C,KEY_LINE
		LD	A,D
		INC	A
		RET	Z
		CP	#28
		RET	Z
		CP	#19
		RET	Z
		LD	A,E
		LD	E,D
		LD	D,A
		CP	#18
		RET

; Scan keyboard and decode value
KEYBOARD:	CALL	KEY_SCAN
		RET	NZ
		LD	HL,#5C00
K_ST_LOOP:	BIT	7,(HL)
		JR	NZ,K_CH_SET
		INC	HL
		DEC	(HL)
		DEC	HL
		JR	NZ,K_CH_SET
		LD	(HL),#FF
K_CH_SET:	LD	A,L
		LD	HL,#5C04
		CP	L
		JR	NZ,K_ST_LOOP
		CALL	K_TEST
		RET	NC
		LD	HL,#5C00
		CP	(HL)
		JR	Z,K_REPEAT
		EX	DE,HL
		LD	HL,#5C04
		CP	(HL)
		JR	Z,K_REPEAT
		BIT	7,(HL)
		JR	NZ,K_NEW
		EX	DE,HL
		BIT	7,(HL)
		RET	Z
K_NEW:		LD	E,A
		LD	(HL),A
		INC	HL
		LD	(HL),#05
		INC	HL
		LD	A,(#5C09)
		LD	(HL),A
		INC	HL
		LD	C,(IY+#07)
		LD	D,(IY+#01)
		PUSH	HL
		CALL	K_DECODE
		POP	HL
		LD	(HL),A
K_END:		LD	(#5C08),A
		SET	5,(IY+#01)
		RET

; Repeat key routine
K_REPEAT:	INC	HL
		LD	(HL),#05
		INC	HL
		DEC	(HL)
		RET	NZ
		LD	A,(#5C0A)
		LD	(HL),A
		INC	HL
		LD	A,(HL)
		JR	K_END

; Test key value
K_TEST:		LD	B,D
		LD	D,#00
		LD	A,E
		CP	#27
		RET	NC
		CP	#18
		JR	NZ,K_MAIN
		BIT	7,B
		RET	NZ
K_MAIN:		LD	HL,MAIN_KEYS
		ADD	HL,DE
		LD	A,(HL)
		SCF
		RET

; Keyboard decoding
K_DECODE:	LD	A,E
		CP	#3A
		JR	C,K_DIGIT
		DEC	C
		JP	M,K_KLC_LET
		JR	Z,K_E_LET
		ADD	A,#4F
		RET

; Test if B is empty (i.e. not a shift)
; forward to K_LOOK_UP if neither shift
K_E_LET:	LD	HL,#01EB		;E_UNSHIFT-#41
		INC	B
		JR	Z,K_LOOK_UP
		LD	HL,#0205		;EXT_SHIFT-#41

; Prepare to index
K_LOOK_UP:	LD	D,#00
		ADD	HL,DE
		LD	A,(HL)
		RET

; Prepare base of SYM_CODES
K_KLC_LET:	LD	HL,#0229		;SYM_CODES-#41
		BIT	0,B
		JR	Z,K_LOOK_UP
		BIT	3,D
		JR	Z,K_TOKENS
		BIT	3,(IY+#30)
		RET	NZ
		INC	B
		RET	NZ
		ADD	A,#20
		RET
; Add offset to main code to get tokens
K_TOKENS:	ADD	A,#A5
		RET

; Digits, space, enter and symbol shift decoding
K_DIGIT:	CP	#30
		RET	C
		DEC	C
		JP	M,K_KLC_DGT
		JR	NZ,K_GRA_DGT
		LD	HL,#0254		;E_DIGITS-#30
		BIT	5,B
		JR	Z,K_LOOK_UP
		CP	#38
		JR	NC,K_8_AND_9
		SUB	#20
		INC	B
		RET	Z
		ADD	A,#08
		RET

; Digits 8 and 9 decoding
K_8_AND_9:	SUB	#36
		INC	B
		RET	Z
		ADD	A,#FE
		RET

; Graphics mode with digits
K_GRA_DGT:	LD	HL,#0230		;CTL_CODES-#30
		CP	#39
		JR	Z,K_LOOK_UP
		CP	#30
		JR	Z,K_LOOK_UP
		AND	#07
		ADD	A,#80
		INC	B
		RET	Z
		XOR	#0F
		RET

; Digits in 'KLC' mode
K_KLC_DGT:	INC	B
		RET	Z
		BIT	5,B
		LD	HL,#0230		;CTL_CODES-#30
		JR	NZ,K_LOOK_UP
		SUB	#10
		CP	#22
		JR	Z,K_AT_CHAR
		CP	#20
		RET	NZ
		LD	A,#5F
		RET

; Substitute ascii '@'
K_AT_CHAR:	LD	A,#40
		RET

; Routine to control loudspeaker
BEEPER:		DI
		LD	A,L
		SRL	L
		SRL	L
		CPL
		AND	#03
		LD	C,A
		LD	B,#00
		LD	IX,BE_IX_3
		ADD	IX,BC
		LD	A,(#5C48)
		AND	#38
		RRCA
		RRCA
		RRCA
		OR	#08
BE_IX_3:	NOP
		NOP
		NOP
		INC	B
		INC	C
BE_HL_LP:	DEC	C
		JR	NZ,BE_HL_LP
		LD	C,#3F
		DEC	B
		JP	NZ,BE_HL_LP
		XOR	#10
		OUT	(#FE),A
		LD	B,H
		LD	C,A
		BIT	4,A
		JR	NZ,BE_AGAIN
		LD	A,D
		OR	E
		JR	Z,BE_END
		LD	A,C
		LD	C,L
		DEC	DE
L_03F0:		JP	(IX)
BE_AGAIN:	LD	C,L
		INC	C
		JP	(IX)
BE_END:		EI
		RET

; Handle BEEP command
BEEP:		RST	#28			;FP_CALC
		DB	#31			;DUPLICATE - duplicate pitch
		DB	#27			;INT - convert to integer
		DB	#C0			;ST_MEM_0 - store integer pitch to memory 0
		DB	#03			;SUBTRACT - calculate fractional part of pitch = fp_pitch - int_pitch
		DB	#34			;STK_DATA - push constant
		DB	#EC			;Exponent: #7C, Bytes: 4 - constant = 0.05762265
		DB	#6C,#98,#1F,#F5 	;(#6C,#98,#1F,#F5)
		DB	#04			;MULTIPLY - compute:
		DB	#A1			;STK_ONE - 1 + 0.05762265 * fraction_part(pitch)
		DB	#0F			;ADDITION
		DB	#38			;END_CALC - leave on calc stack

		LD	HL,#5C92
		LD	A,(HL)
		AND	A
		JR	NZ,REPORT_B
		INC	HL
		LD	C,(HL)
		INC	HL
		LD	B,(HL)
		LD	A,B
		RLA
		SBC	A,A
		CP	C
		JR	NZ,REPORT_B
		INC	HL
		CP	(HL)
		JR	NZ,REPORT_B
		LD	A,B
		ADD	A,#3C
		JP	P,BE_I_OK
		JP	PO,REPORT_B
BE_I_OK:	LD	B,#FA
BE_OCTAVE:	INC	B
		SUB	#0C
		JR	NC,BE_OCTAVE
		ADD	A,#0C
		PUSH	BC
		LD	HL,SEMI_TONE
		CALL	LOC_MEM
		CALL	STACK_NUM

		RST	#28			;FP_CALC
		DB	#04			;MULTIPLY
		DB	#38			;END_CALC

		POP	AF
		ADD	A,(HL)
		LD	(HL),A

		RST	#28			;FP_CALC
		DB	#C0			;ST_MEM_0
		DB	#02			;DELETE
		DB	#31			;DUPLICATE
		DB	#38			;END_CALC

		CALL	FIND_INT1
		CP	#0B
		JR	NC,REPORT_B

		RST	#28			;FP_CALC
		DB	#E0			;GET_MEM_0
		DB	#04			;MULTIPLY
		DB	#E0			;GET_MEM_0
		DB	#34			;STK_DATA
		DB	#80			;Exponent #93, Bytes: 3
		DB	#43, #55, #9F, #80
		DB	#01			;EXCHANGE
		DB	#05			;DIVISION
		DB	#34			;STK_DATA
		DB	#35			;Exponent: #85, Bytes: 1
		DB	#71
		DB	#03			;SUBTRACT
		DB	#38			;END_CALC

		CALL	FIND_INT2
		PUSH	BC
		CALL	FIND_INT2
		POP	HL
		LD	D,B
		LD	E,C
		LD	A,D
		OR	E
		RET	Z
		DEC	DE
		JP	BEEPER

REPORT_B:	RST	#08			; Error report
		DB	#0A			; Integer out of range

; Semi-tone table.
; Holds frequencies corresponding to semitones in middle octave.
SEMI_TONE:	DB	#89, #02, #D0, #12, #86
		DB	#89, #0A, #97, #60, #75
		DB	#89, #12, #D5, #17, #1F
		DB	#89, #1B, #90, #41, #02
		DB	#89, #24, #D0, #53, #CA
		DB	#89, #2E, #9D, #36, #B1
		DB	#89, #38, #FF, #49, #3E
		DB	#89, #43, #FF, #6A, #73
		DB	#89, #4F, #A7, #00, #54
		DB	#89, #5C, #00, #00, #00
		DB	#89, #69, #14, #F6, #24
		DB	#89, #76, #F1, #10, #05

; BSROM for MB02+
; reserved for future patches
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000

; Save header and program or data
SA_BYTES:	LD	HL,SA_LD_RET
		PUSH	HL
SA_BYTES1:	CALL	TSTSAV			;BSROM for MB02+ - modified tape save (tape emulator)
		BIT	7,A
		JR	Z,SA_FLAG
		LD	HL,#0C98
SA_FLAG:	EX	AF,AF'
		INC	DE
		DEC	IX
		DI
		LD	A,#02
		LD	B,A
SA_LEADER:	DJNZ	SA_LEADER
		OUT	(#FE),A
		XOR	#0F
		LD	B,#A4
		DEC	L
		JR	NZ,SA_LEADER
		DEC	B
		DEC	H
		JP	P,SA_LEADER
		LD	B,#2F
SA_SYNC_1:	DJNZ	SA_SYNC_1
		OUT	(#FE),A
		LD	A,#0D
		LD	B,#37
SA_SYNC_2:	DJNZ	SA_SYNC_2
		OUT	(#FE),A
		LD	BC,#3B0E		; B=#3B time; C=#0E YELLOW, MIC OFF.
		EX	AF,AF'
		LD	L,A
		JP	SA_START

SA_LOOP:	LD	A,D
		OR	E
		JR	Z,SA_PARITY
		LD	L,(IX+#00)
SA_LOOP_P:	LD	A,H
		XOR	L
SA_START:	LD	H,A
		LD	A,#01
		SCF
		JP	SA_8_BITS

SA_PARITY:	LD	L,H
		JR	SA_LOOP_P

SA_BIT_2:	LD	A,C
		BIT	7,B
SA_BIT_1:	DJNZ	SA_BIT_1
		JR	NC,SA_OUT
		LD	B,#42
SA_SET:		DJNZ	SA_SET
SA_OUT:		OUT	(#FE),A
		LD	B,#3E
		JR	NZ,SA_BIT_2
		DEC	B
		XOR	A
		INC	A
SA_8_BITS:	RL	L
		JP	NZ,SA_BIT_1
		DEC	DE
		INC	IX
		LD	B,#31
		LD	A,#7F
		IN	A,(#FE)
		RRA
		RET	NC
		LD	A,D
		INC	A
		JP	NZ,SA_LOOP
		LD	B,#3B
SA_DELAY:	DJNZ	SA_DELAY
		RET

; Reset border nad check BREAK for LOAD and SAVE
SA_LD_RET:	PUSH	AF
		LD	A,(#5C48)
		AND	#38
		RRCA
		RRCA
		RRCA
		OUT	(#FE),A
		LD	A,#7F
		IN	A,(#FE)
		RRA
		EI
		JR	C,SA_LD_END
REPORT_DA:	RST	#08			; Error report
		DB	#0C			; BREAK - CONT repeats
SA_LD_END:	POP	AF
		RET

; Load header or data
LD_BYTES:	INC	D
		EX	AF,AF'
		DEC	D
		NOP				; BSROM for MB02+ - don't disable interrupt
		LD	A,#0F
		LD	A,#FE			; BSROM for MB02+ - don't change border
		LD	HL,SA_LD_RET
		PUSH	HL
		CALL	TSTLOA			; BSROM for MB02+ - modified tape load (tape emulator)
LD_BYTES1:	AND	#20
		OR	#02
		LD	C,A
		CP	A
LD_BREAK:	RET	NZ
LD_START:	CALL	LD_EDGE_1
		JR	NC,LD_BREAK
		LD	HL,#0115		; BSROM - short delay (was #0415 in orig. ROM)
LD_WAIT:	DJNZ	LD_WAIT
		DEC	HL
		LD	A,H
		OR	L
		JR	NZ,LD_WAIT
		CALL	LD_EDGE_2
		JR	NC,LD_BREAK
LD_LEADER:	LD	B,#9C
		CALL	LD_EDGE_2
		JR	NC,LD_BREAK
		LD	A,#C6
		CP	B
		JR	NC,LD_START
		INC	H
		JR	NZ,LD_LEADER
LD_SYNC:	LD	B,#C9
		CALL	LD_EDGE_1
		JR	NC,LD_BREAK
		LD	A,B
		CP	#D4
		JR	NC,LD_SYNC
		CALL	LD_EDGE_1
		RET	NC
		LD	A,C
		XOR	#03
		LD	C,A
		LD	H,#00
		LD	B,#B0
		JR	LD_MARKER

LD_LOOP:	EX	AF,AF'
		JR	NZ,LD_FLAG
		JR	NC,LD_VERIFY
		LD	(IX+#00),L
		JR	LD_NEXT

LD_FLAG:	RL	C
		XOR	L
		RET	NZ
		LD	A,C
		RRA
		LD	C,A
		INC	DE
		JR	LD_DEC

LD_VERIFY:	LD	A,(IX+#00)
		XOR	L
		RET	NZ
LD_NEXT:	INC	IX
LD_DEC:		DEC	DE
		EX	AF,AF'
		LD	B,#B2
LD_MARKER:	LD	L,#01
LD_8_BITS:	CALL	LD_EDGE_2
		RET	NC
		LD	A,#CB
		CP	B
		RL	L
		LD	B,#B0
		JP	NC,LD_8_BITS
		LD	A,H
		XOR	L
		LD	H,A
		LD	A,D
		OR	E
		JR	NZ,LD_LOOP
		LD	A,H
		CP	#01
		RET

; Check signal being loaded
LD_EDGE_2:	CALL	LD_EDGE_1
		RET	NC
LD_EDGE_1:	LD	A,#16
LD_DELAY:	DEC	A
		JR	NZ,LD_DELAY
		AND	A
LD_SAMPLE:	INC	B
		RET	Z
		LD	A,#7F
		IN	A,(#FE)
		RRA
		RET	NC
		XOR	C
		AND	#20
		JR	Z,LD_SAMPLE
		LD	A,C
		CPL
		LD	C,A
		AND	#07
		OR	#08
		OUT	(#FE),A
		SCF
		RET

; Entry point for tape commands
SAVE_ETC:	POP	AF
		LD	A,(#5C74)
		SUB	#E0
		LD	(#5C74),A
		NOP			; BSROM for MB02+ - filename handling provided by BSDOS
		NOP
		NOP
		CALL	SYNTAX_Z
		JR	Z,SA_DATA
		LD	BC,#0011
		LD	A,(#5C74)
		AND	A
		JR	Z,SA_SPACE
		LD	C,#22
SA_SPACE:	RST	#30
		PUSH	DE
		POP	IX
		LD	B,#0B
		LD	A,#20
SA_BLANK:	LD	(DE),A
		INC	DE
		DJNZ	SA_BLANK
		LD	(IX+#01),#FF
		CALL	STK_FETCH
		LD	HL,#FFF6
		DEC	BC
		ADD	HL,BC
		INC	BC
		JR	NC,SA_NAME
		LD	A,(#5C74)
		AND	A
		JR	NZ,SA_NULL
REPORT_FA:	RST	#08			; Error report
		DB	#0E			; Invalid file name
SA_NULL:	LD	A,B
		OR	C
		JR	Z,SA_DATA
		LD	BC,#000A
SA_NAME:	PUSH	IX
		POP	HL
		INC	HL
		EX	DE,HL
		LDIR
SA_DATA:	RST	#18
		CP	#E4
		JR	NZ,SA_SCR
		LD	A,(#5C74)
		CP	#03
		JP	Z,REPORT_C
		RST	#20
		CALL	LOOK_VARS
		SET	7,C
		JR	NC,SA_V_OLD
		LD	HL,#0000
		LD	A,(#5C74)
		DEC	A
		JR	Z,SA_V_NEW
REPORT_2A:	RST	#08			; Error report
		DB	#01			; Variable not found
SA_V_OLD:	JP	NZ,REPORT_C
		CALL	SYNTAX_Z
		JR	Z,SA_DATA_1
		INC	HL
		LD	A,(HL)
		LD	(IX+#0B),A
		INC	HL
		LD	A,(HL)
		LD	(IX+#0C),A
		INC	HL
SA_V_NEW:	LD	(IX+#0E),C
		LD	A,#01
		BIT	6,C
		JR	Z,SA_V_TYPE
		INC	A
SA_V_TYPE:	LD	(IX+#00),A
SA_DATA_1:	EX	DE,HL
		RST	#20
		CP	#29
		JR	NZ,SA_V_OLD
		RST	#20
		CALL	CHECK_END
		EX	DE,HL
		JP	SA_ALL

SA_SCR:		CP	#AA
		JR	NZ,SA_CODE
		LD	A,(#5C74)
		CP	#03
		JP	Z,REPORT_C
		RST	#20
		CALL	CHECK_END
		LD	(IX+#0B),#00
		LD	(IX+#0C),#1B
		LD	HL,#4000
		LD	(IX+#0D),L
		LD	(IX+#0E),H
		JR	SA_TYPE_3

SA_CODE:	CP	#AF
		JR	NZ,SA_LINE
		LD	A,(#5C74)
		CP	#03
		JP	Z,REPORT_C
		RST	#20
		CALL	PR_ST_END
		JR	NZ,SA_CODE_1
		LD	A,(#5C74)
		AND	A
		JP	Z,REPORT_C
		CALL	USE_ZERO
		JR	SA_CODE_2

SA_CODE_1:	CALL	EXPT_1NUM
		RST	#18
		CP	#2C
		JR	Z,SA_CODE_3
		LD	A,(#5C74)
		AND	A
		JP	Z,REPORT_C
SA_CODE_2:	CALL	USE_ZERO
		JR	SA_CODE_4

SA_CODE_3:	RST	#20
		CALL	EXPT_1NUM
SA_CODE_4:	CALL	CHECK_END
		CALL	FIND_INT2
		LD	(IX+#0B),C
		LD	(IX+#0C),B
		CALL	FIND_INT2
		LD	(IX+#0D),C
		LD	(IX+#0E),B
		LD	H,B
		LD	L,C
SA_TYPE_3:	LD	(IX+#00),#03
		JR	SA_ALL

SA_LINE:	CP	#CA
		JR	Z,SA_LINE_1
		CALL	CHECK_END
		LD	(IX+#0E),#80
		JR	SA_TYPE_0

SA_LINE_1:	LD	A,(#5C74)
		AND	A
		JP	NZ,REPORT_C
		RST	#20
		CALL	EXPT_1NUM
		CALL	CHECK_END
		CALL	FIND_INT2
		LD	(IX+#0D),C
		LD	(IX+#0E),B
SA_TYPE_0:	LD	(IX+#00),#00
		LD	HL,(#5C59)
		LD	DE,(#5C53)
		SCF
		SBC	HL,DE
		LD	(IX+#0B),L
		LD	(IX+#0C),H
		LD	HL,(#5C4B)
		SBC	HL,DE
		LD	(IX+#0F),L
		LD	(IX+#10),H
		EX	DE,HL
SA_ALL:		LD	A,(#5C74)
		AND	A
		JP	Z,SA_CONTRL
		PUSH	HL
		LD	BC,#0011
		ADD	IX,BC
LD_LOOK_H:	PUSH	IX
		LD	DE,#0011
		XOR	A
		SCF
		CALL	LD_BYTES
		POP	IX
		JR	NC,LD_LOOK_H
		LD	A,#FE
		CALL	CHAN_OPEN
		LD	(IY+#52),#FF		; BSROM - fixed "scroll?" troubles when tape header is shown, was LD (IY+$52),$03
		LD	C,#80
		LD	A,(IX+#00)
		CP	(IX-#11)
		JR	NZ,LD_TYPE
		LD	C,#F6
LD_TYPE:	CP	#04
		JR	NC,LD_LOOK_H
		LD	DE,TAPE_MSGS2
		PUSH	BC
		CALL	PO_MSG
		POP	BC
		PUSH	IX
		POP	DE
		LD	HL,#FFF0
		ADD	HL,DE
		LD	B,#0A
		LD	A,(HL)
		INC	A
		JR	NZ,LD_NAME
		LD	A,C
		ADD	A,B
		LD	C,A
LD_NAME:	INC	DE
		LD	A,(DE)
		CP	(HL)
		INC	HL
		JR	NZ,LD_CH_PR
		INC	C
LD_CH_PR:	RST	#10
		DJNZ	LD_NAME
		BIT	7,C
		JR	NZ,LD_LOOK_H
		LD	A,#0D
		RST	#10
		POP	HL
		LD	A,(IX+#00)
		CP	#03
		JR	Z,VR_CONTROL
		LD	A,(#5C74)
		DEC	A
		JP	Z,LD_CONTRL
		CP	#02
		JP	Z,ME_CONTRL
VR_CONTROL:	PUSH	HL			; Handle VERIFY control
		LD	L,(IX-#06)
		LD	H,(IX-#05)
		LD	E,(IX+#0B)
		LD	D,(IX+#0C)
		LD	A,H
		OR	L
		JR	Z,VR_CONT_1
		SBC	HL,DE
		JR	C,REPORT_R
		JR	Z,VR_CONT_1
		LD	A,(IX+#00)
		CP	#03
		JR	NZ,REPORT_R
VR_CONT_1:	POP	HL
		LD	A,H
		OR	L
		JR	NZ,VR_CONT_2
		LD	L,(IX+#0D)
		LD	H,(IX+#0E)
VR_CONT_2:	PUSH	HL
		POP	IX
		LD	A,(#5C74)
		CP	#02
		SCF
		JR	NZ,VR_CONT_3
		AND	A
VR_CONT_3:	LD	A,#FF
LD_BLOCK:	CALL	LD_BYTES		; Load a block of data
		RET	C
REPORT_R:	RST	#08			; Error report
		DB	#1A			; Tape loading error
LD_CONTRL:	LD	E,(IX+#0B)		; Handle LOAD control
		LD	D,(IX+#0C)
		PUSH	HL
		LD	A,H
		OR	L
		JR	NZ,LD_CONT_1
		INC	DE
		INC	DE
		INC	DE
		EX	DE,HL
		JR	LD_CONT_2

LD_CONT_1:	LD	L,(IX-#06)
		LD	H,(IX-#05)
		EX	DE,HL
		SCF
		SBC	HL,DE
		JR	C,LD_DATA
LD_CONT_2:	LD	DE,#0005
		ADD	HL,DE
		LD	B,H
		LD	C,L
		CALL	TEST_ROOM
LD_DATA:	POP	HL
		LD	A,(IX+#00)
		AND	A
		JR	Z,LD_PROG
		LD	A,H
		OR	L
		JR	Z,LD_DATA_1
		DEC	HL
		LD	B,(HL)
		DEC	HL
		LD	C,(HL)
		DEC	HL
		INC	BC
		INC	BC
		INC	BC
		LD	(#5C5F),IX
		CALL	RECLAIM_2
		LD	IX,(#5C5F)
LD_DATA_1:	LD	HL,(#5C59)
		DEC	HL
		LD	C,(IX+#0B)
		LD	B,(IX+#0C)
		PUSH	BC
		INC	BC
		INC	BC
		INC	BC
		LD	A,(IX-#03)
		PUSH	AF
		CALL	MAKE_ROOM
		INC	HL
		POP	AF
		LD	(HL),A
		POP	DE
		INC	HL
		LD	(HL),E
		INC	HL
		LD	(HL),D
		INC	HL
		PUSH	HL
		POP	IX
		SCF
		LD	A,#FF
		JP	LD_BLOCK

LD_PROG:	EX	DE,HL
		LD	HL,(#5C59)
		DEC	HL
		LD	(#5C5F),IX
		LD	C,(IX+#0B)
		LD	B,(IX+#0C)
		PUSH	BC
		CALL	RECLAIM_1
		POP	BC
		PUSH	HL
		PUSH	BC
		CALL	MAKE_ROOM
		LD	IX,(#5C5F)
		INC	HL
		LD	C,(IX+#0F)
		LD	B,(IX+#10)
		ADD	HL,BC
		LD	(#5C4B),HL
		LD	H,(IX+#0E)
		LD	A,H
		AND	#C0
		JR	NZ,LD_PROG_1
		LD	L,(IX+#0D)
		LD	(#5C42),HL
		LD	(IY+#0A),#00
LD_PROG_1:	POP	DE
		POP	IX
		SCF
		LD	A,#FF
		JP	LD_BLOCK

; Handle MERGE control
ME_CONTRL:	LD	C,(IX+#0B)
		LD	B,(IX+#0C)
		PUSH	BC
		INC	BC
		RST	#30
		LD	(HL),#80
		EX	DE,HL
		POP	DE
		PUSH	HL
		PUSH	HL
		POP	IX
		SCF
		LD	A,#FF
		CALL	LD_BLOCK
		POP	HL
		LD	DE,(#5C53)
ME_NEW_LP:	LD	A,(HL)
		AND	#C0
		JR	NZ,ME_VAR_LP
ME_OLD_LP:	LD	A,(DE)
		INC	DE
		CP	(HL)
		INC	HL
		JR	NZ,ME_OLD_L1
		LD	A,(DE)
		CP	(HL)
ME_OLD_L1:	DEC	DE
		DEC	HL
		JR	NC,ME_NEW_L2
		PUSH	HL
		EX	DE,HL
		CALL	NEXT_ONE
		POP	HL
		JR	ME_OLD_LP

ME_NEW_L2:	CALL	ME_ENTER
		JR	ME_NEW_LP

ME_VAR_LP:	LD	A,(HL)
		LD	C,A
		CP	#80
		RET	Z
		PUSH	HL
		LD	HL,(#5C4B)
ME_OLD_VP:	LD	A,(HL)
		CP	#80
		JR	Z,ME_VAR_L2
		CP	C
		JR	Z,ME_OLD_V2
ME_OLD_V1:	PUSH	BC
		CALL	NEXT_ONE
		POP	BC
		EX	DE,HL
		JR	ME_OLD_VP

ME_OLD_V2:	AND	#E0
		CP	#A0
		JR	NZ,ME_VAR_L1
		POP	DE
		PUSH	DE
		PUSH	HL
ME_OLD_V3:	INC	HL
		INC	DE
		LD	A,(DE)
		CP	(HL)
		JR	NZ,ME_OLD_V4
		RLA
		JR	NC,ME_OLD_V3
		POP	HL
		JR	ME_VAR_L1

ME_OLD_V4:	POP	HL
		JR	ME_OLD_V1

ME_VAR_L1:	LD	A,#FF
ME_VAR_L2:	POP	DE
		EX	DE,HL
		INC	A
		SCF
		CALL	ME_ENTER
		JR	ME_VAR_LP

; Merge a line or variable
ME_ENTER:	JR	NZ,ME_ENT_1
		EX	AF,AF'
		LD	(#5C5F),HL
		EX	DE,HL
		CALL	NEXT_ONE
		CALL	RECLAIM_2
		EX	DE,HL
		LD	HL,(#5C5F)
		EX	AF,AF'
ME_ENT_1:	EX	AF,AF'
		PUSH	DE
		CALL	NEXT_ONE
		LD	(#5C5F),HL
		LD	HL,(#5C53)
		EX	(SP),HL
		PUSH	BC
		EX	AF,AF'
		JR	C,ME_ENT_2
		DEC	HL
		CALL	MAKE_ROOM
		INC	HL
		JR	ME_ENT_3

ME_ENT_2:	CALL	MAKE_ROOM
ME_ENT_3:	INC	HL
		POP	BC
		POP	DE
		LD	(#5C53),DE
		LD	DE,(#5C5F)
		PUSH	BC
		PUSH	DE
		EX	DE,HL
		LDIR
		POP	HL
		POP	BC
		PUSH	DE
		CALL	RECLAIM_2
		POP	DE
		RET

; Handle SAVE control
SA_CONTRL:	PUSH	HL
		LD	A,#FD
		CALL	CHAN_OPEN
		XOR	A
		LD	DE,TAPE_MSGS
		CALL	PO_MSG
		SET	5,(IY+#02)
		CALL	WAIT_KEY
		PUSH	IX
		LD	DE,#0011
		XOR	A
		CALL	SA_BYTES
		POP	IX
		LD	B,#02			; BSROM for MB02+ - wait only 2/50 sec
SA_1_SEC:	HALT
		DJNZ	SA_1_SEC
		LD	E,(IX+#0B)
		LD	D,(IX+#0C)
		POP	IX			; BSROM - LD A,#FF and POP IX swapped
		LD	A,#FF
		JP	SA_BYTES

; Tape mesages
TAPE_MSGS:	DB	#80
		DC	"Press REC & PLAY, then any key."
TAPE_MSGS2:	EQU	$-1
		DB	#0D
		DC	"Program: "
		DB	#0D
		DC	"Number array: "
		DB	#0D
		DC	"Character array: "
		DB	#0D
		DC	"Bytes: "

; Genereal PRINT routine
PRINT_OUT:	CALL	DISPL			; BSROM - disabled autolist of control codes
		CP	#1E
		JP	NC,PO_ABLE
		CP	#06
		JR	C,PO_QUEST
		CP	#18
		JR	NC,PO_QUEST
		LD	HL,CTLCHRTAB-6
		LD	E,A
		LD	D,#00
		ADD	HL,DE
		LD	E,(HL)
		ADD	HL,DE
		PUSH	HL
		JP	PO_FETCH

;Control character table
CTLCHRTAB:	DB	#4E			; PO_COMMA
		DB	#57			; PO_QUEST
		DB	#10			; PO_BACK_1
		DB	#29			; PO_RIGHT
		DB	#54			; PO_QUEST
		DB	#53			; PO_QUEST
		DB	#52			; PO_QUEST
		DB	#37			; PO_ENTER
		DB	#50			; PO_QUEST
		DB	#4F			; PO_QUEST
		DB	#5F			; PO_1_OPER
		DB	#5E			; PO_1_OPER
		DB	#5D			; PO_1_OPER
		DB	#5C			; PO_1_OPER
		DB	#5B			; PO_1_OPER
		DB	#5A			; PO_1_OPER
		DB	#54			; PO_2_OPER
		DB	#53			; PO_2_OPER

; Cursor left routine
PO_BACK_1:	INC	C
		LD	A,#22
		CP	C
		JR	NZ,PO_BACK_3
		BIT	1,(IY+#01)
		JR	NZ,PO_BACK_2
		INC	B
		LD	C,#02
		LD	A,#19			; BSROM - bugfix - was LD A,#18
		CP	B
		JR	NZ,PO_BACK_3
		DEC	B
PO_BACK_2:	LD	C,#21
PO_BACK_3:	JP	CL_SET

; Cursor right routine
PO_RIGHT:	LD	A,(#5C91)
		PUSH	AF
		LD	(IY+#57),#01
		LD	A,#20
		CALL	PO_ABLE			; BSROM - bugfix - was CALL PO_BACK
		POP	AF
		LD	(#5C91),A
		RET

; Carriage return / Enter
PO_ENTER:	BIT	1,(IY+#01)
		RET	NZ			; BSROM for MB02+ - don't use ZX Printer
		NOP
		NOP
		LD	C,#21
		CALL	PO_SCR
		DEC	B
		JP	CL_SET

; Print comma
PO_COMMA:	CALL	PO_FETCH
		LD	A,C
		DEC	A
		DEC	A
		AND	#10
		JR	PO_FILL

; Print question mark
PO_QUEST:	LD	A,#3F
		JR	PO_ABLE

; Control characters with operands
PO_TV_2:	LD	DE,PO_CONT
		LD	(#5C0F),A
		JR	PO_CHANGE

PO_2_OPER:	LD	DE,PO_TV_2
		JR	PO_TV_1

PO_1_OPER:	LD	DE,PO_CONT
PO_TV_1:	LD	(#5C0E),A
PO_CHANGE:	LD	HL,(#5C51)
		LD	(HL),E
		INC	HL
		LD	(HL),D
		RET

PO_CONT:	LD	DE,PRINT_OUT
		CALL	PO_CHANGE
		LD	HL,(#5C0E)
		LD	D,A
		LD	A,L
		CP	#16
		JP	C,CO_TEMP_5
		JR	NZ,PO_TAB
		LD	B,H
		LD	C,D
		LD	A,#1F
		SUB	C
		JR	C,PO_AT_ERR
		ADD	A,#02
		LD	C,A
		BIT	1,(IY+#01)
		JR	NZ,PO_AT_SET
		LD	A,#16
		SUB	B
PO_AT_ERR:	JP	C,REPORT_BB
		INC	A
		LD	B,A
		INC	B
		BIT	0,(IY+#02)
		JP	NZ,PO_SCR
		CP	(IY+#31)
		JP	C,REPORT_5
PO_AT_SET:	JP	CL_SET

PO_TAB:		LD	A,H
PO_FILL:	CALL	PO_FETCH
		ADD	A,C
		DEC	A
		AND	#1F
		RET	Z
		LD	D,A
		SET	0,(IY+#01)
PO_SPACE:	LD	A,#20
		CALL	PO_SAVE
		DEC	D
		JR	NZ,PO_SPACE
		RET

; Print printable character(s)
PO_ABLE:	CALL	PO_ANY

; Store line, column and pixel address
PO_STORE:	BIT	1,(IY+#01)
		JR	NZ,PO_ST_PR
		BIT	0,(IY+#02)
		JR	NZ,PO_ST_E
		LD	(#5C88),BC
		LD	(#5C84),HL
		RET

PO_ST_E:	LD	(#5C8A),BC
		LD	(#5C82),BC
		LD	(#5C86),HL
		RET

PO_ST_PR:	LD	(IY+#45),C
		LD	(#5C80),HL
		RET

; Fetch position parameters
PO_FETCH:	BIT	1,(IY+#01)
		JR	NZ,PO_F_FR
		LD	BC,(#5C88)
		LD	HL,(#5C84)
		BIT	0,(IY+#02)
		RET	Z
		LD	BC,(#5C8A)
		LD	HL,(#5C86)
		RET

PO_F_FR:	LD	C,(IY+#45)
		LD	HL,(#5C80)
		RET

; Print any character
PO_ANY:		CP	#80
		JR	C,PO_CHAR
		CP	#90
		JR	NC,PO_T_UDG
		LD	B,A
		CALL	PO_GR_1
		CALL	PO_FETCH
		LD	DE,#5C92
		JR	PR_ALL

PO_GR_1:	LD	HL,#5C92
		CALL	PO_GR_2
PO_GR_2:	RR	B
		SBC	A,A
		AND	#0F
		LD	C,A
		RR	B
		SBC	A,A
		AND	#F0
		OR	C
		LD	C,#04
PO_GR_3:	LD	(HL),A
		INC	HL
		DEC	C
		JR	NZ,PO_GR_3
		RET

PO_T_UDG:	SUB	#A5
		JR	NC,PO_T
		ADD	A,#15
		PUSH	BC
		LD	BC,(#5C7B)
		JR	PO_CHAR_2

PO_T:		CALL	PO_TOKENS
		JP	PO_FETCH

PO_CHAR:	PUSH	BC
		LD	BC,(#5C36)
PO_CHAR_2:	EX	DE,HL
		LD	HL,#5C3B
		RES	0,(HL)
		CP	#20
		JR	NZ,PO_CHAR_3
		SET	0,(HL)
PO_CHAR_3:	LD	H,#00
		LD	L,A
		ADD	HL,HL
		ADD	HL,HL
		ADD	HL,HL
		ADD	HL,BC
		POP	BC
		EX	DE,HL
PR_ALL:		LD	A,C			; Print all characters
		DEC	A
		LD	A,#21
		JR	NZ,PR_ALL_1
		DEC	B
		LD	C,A
		BIT	1,(IY+#01)
		JR	Z,PR_ALL_1
		PUSH	DE
		LD	DE,#0ECD		; BSROM for MB02+ - don't use ZX Printer
		POP	DE
		LD	A,C
PR_ALL_1:	CP	C
		PUSH	DE
		CALL	Z,PO_SCR
		POP	DE
		PUSH	BC
		PUSH	HL
		LD	A,(#5C91)
		LD	B,#FF
		RRA
		JR	C,PR_ALL_2
		INC	B
PR_ALL_2:	RRA
		RRA
		SBC	A,A
		LD	C,A
		LD	A,#08
		AND	A
		BIT	1,(IY+#01)
		JR	Z,PR_ALL_3
		SET	1,(IY+#30)
		SCF
PR_ALL_3:	EX	DE,HL
PR_ALL_4:	EX	AF,AF'
		LD	A,(DE)
		AND	B
		XOR	(HL)
		XOR	C
		LD	(DE),A
		EX	AF,AF'
		JR	C,PR_ALL_6
		INC	D
PR_ALL_5:	INC	HL
		DEC	A
		JR	NZ,PR_ALL_4
		EX	DE,HL
		DEC	H
		BIT	1,(IY+#01)
		CALL	Z,PO_ATTR
		POP	HL
		POP	BC
		DEC	C
		INC	HL
		RET

PR_ALL_6:	EX	AF,AF'
		LD	A,#20
		ADD	A,E
		LD	E,A
		EX	AF,AF'
		JR	PR_ALL_5

; Set attribute
PO_ATTR:	LD	A,H
		RRCA
		RRCA
		RRCA
		AND	#03
		OR	#58
		LD	H,A
		LD	DE,(#5C8F)
		LD	A,(HL)
		XOR	E
		AND	D
		XOR	E
		BIT	6,(IY+#57)
		JR	Z,PO_ATTR_1
		AND	#C7
		BIT	2,A
		JR	NZ,PO_ATTR_1
		XOR	#38
PO_ATTR_1:	BIT	4,(IY+#57)
		JR	Z,PO_ATTR_2
		AND	#F8
		BIT	5,A
		JR	NZ,PO_ATTR_2
		XOR	#07
PO_ATTR_2:	LD	(HL),A
		RET

; Message printing (boot-up, tape, scroll, error reports)
PO_MSG:		PUSH	HL
		LD	H,#00
		EX	(SP),HL
		JR	PO_TABLE

PO_TOKENS:	LD	DE,TKN_TABLE
PO_TOKENS1:	PUSH	AF
PO_TABLE:	CALL	PO_SEARCH
		JR	C,PO_EACH
		LD	A,#20
		BIT	0,(IY+#01)
		CALL	Z,PO_SAVE
PO_EACH:	LD	A,(DE)
		AND	#7F
		CALL	PO_SAVE
		LD	A,(DE)
		INC	DE
		ADD	A,A
		JR	NC,PO_EACH
		POP	DE
		CP	#48
		JR	Z,PO_TR_SP
		CP	#82
		RET	C
PO_TR_SP:	LD	A,D
		CP	#03
		RET	C
		LD	A,#20
PO_SAVE:	PUSH	DE			; Handle recursive printing
		EXX
		RST	#10
		EXX
		POP	DE
		RET

; Token table search
PO_SEARCH:	PUSH	AF
		EX	DE,HL
		INC	A
PO_STEP:	BIT	7,(HL)
		INC	HL
		JR	Z,PO_STEP
		DEC	A
		JR	NZ,PO_STEP
		EX	DE,HL
		POP	AF
		CP	#20
		RET	C
		LD	A,(DE)
		SUB	#41
		RET

; Test for scroll
PO_SCR:		BIT	1,(IY+#01)
		RET	NZ
		LD	DE,CL_SET
		PUSH	DE
		LD	A,B
		BIT	0,(IY+#02)
		JP	NZ,PO_SCR_4
		CP	(IY+#31)
		JR	C,REPORT_5
		RET	NZ
		BIT	4,(IY+#02)
		JR	Z,PO_SCR_2
		LD	E,(IY+#2D)
		DEC	E
		JR	Z,PO_SCR_3
		LD	A,#00
		CALL	CHAN_OPEN
		LD	SP,(#5C3F)
		RES	4,(IY+#02)
		RET

REPORT_5:	RST	#08			; Error report
		DB	#04			; Out of screen
PO_SCR_2:	DEC	(IY+#52)
		JR	NZ,PO_SCR_3
		LD	A,#18
		SUB	B
		LD	(#5C8C),A
		LD	HL,(#5C8F)
		PUSH	HL
		LD	A,(#5C91)
		PUSH	AF
		LD	A,#FD
		CALL	CHAN_OPEN
		XOR	A
		LD	DE,SCRL_MSG
		CALL	PO_MSG
		SET	5,(IY+#02)
		LD	HL,#5C3B
		SET	3,(HL)
		RES	5,(HL)
		EXX
		CALL	WAIT_KEY
		EXX
		CP	#20
		JR	Z,REPORT_D
		CP	#E2
		JR	Z,REPORT_D
		OR	#20
		CP	#6E
		JR	Z,REPORT_D
		LD	A,#FE
		CALL	CHAN_OPEN
		POP	AF
		LD	(#5C91),A
		POP	HL
		LD	(#5C8F),HL
PO_SCR_3:	CALL	CL_SC_ALL
		LD	B,(IY+#31)
		INC	B
		LD	C,#21
		PUSH	BC
		CALL	CL_ADDR
		LD	A,H
		RRCA
		RRCA
		RRCA
		AND	#03
		OR	#58
		LD	H,A
		LD	DE,#5AE0
		LD	A,(DE)
		LD	C,(HL)
		LD	B,#20
		EX	DE,HL
PO_SCR_3A:	LD	(DE),A
		LD	(HL),C
		INC	DE
		INC	HL
		DJNZ	PO_SCR_3A
		POP	BC
		RET

SCRL_MSG:	DB	#80
		DC	"scroll?"

REPORT_D:	RST	#08			; Error report
		DB	#0C			; BREAK - CONT repeats
PO_SCR_4:	CP	#02
		JR	C,REPORT_5
		ADD	A,(IY+#31)
		SUB	#19
		RET	NC
		NEG
		PUSH	BC
		LD	B,A
		LD	HL,(#5C8F)
		PUSH	HL
		LD	HL,(#5C91)
		PUSH	HL
		CALL	TEMPS
		LD	A,B
PO_SCR_4A:	PUSH	AF
		LD	HL,#5C6B
		LD	B,(HL)
		LD	A,B
		INC	A
		LD	(HL),A
		LD	HL,#5C89
		CP	(HL)
		JR	C,PO_SCR_4B
		INC	(HL)
		LD	B,#18
PO_SCR_4B:	CALL	CL_SCROLL
		POP	AF
		DEC	A
		JR	NZ,PO_SCR_4A
		POP	HL
		LD	(IY+#57),L
		POP	HL
		LD	(#5C8F),HL
		LD	BC,(#5C88)
		RES	0,(IY+#02)
		CALL	CL_SET
		SET	0,(IY+#02)
		POP	BC
		RET

; Copy temporary items
TEMPS:		XOR	A
		LD	HL,(#5C8D)
		BIT	0,(IY+#02)
		JR	Z,TEMPS_1
		LD	H,A
		LD	L,(IY+#0E)
TEMPS_1:	LD	(#5C8F),HL
		LD	HL,#5C91
		JR	NZ,TEMPS_2
		LD	A,(HL)
		RRCA
TEMPS_2:	XOR	(HL)
		AND	#55
		XOR	(HL)
		LD	(HL),A
		RET

; Handle CLS command
CLS:		CALL	CL_ALL
CLS_LOWER:	LD	HL,#5C3C
		RES	5,(HL)
		SET	0,(HL)
		CALL	TEMPS
		LD	B,(IY+#31)
		CALL	CL_LINE
		LD	HL,#5AC0
		LD	A,(#5C8D)
		DEC	B
		JR	CLS_3

CLS_1:		LD	C,#20
CLS_2:		DEC	HL
		LD	(HL),A
		DEC	C
		JR	NZ,CLS_2
CLS_3:		DJNZ	CLS_1
		LD	(IY+#31),#02
CL_CHAN:	LD	A,#FD
		CALL	CHAN_OPEN
		LD	HL,(#5C51)
		LD	DE,PRINT_OUT
		AND	A
CL_CHAN_A:	LD	(HL),E
		INC	HL
		LD	(HL),D
		INC	HL
		LD	DE,KEY_INPUT
		CCF
		JR	C,CL_CHAN_A
		LD	BC,#1721
		JR	CL_SET

; Clear display area
CL_ALL:		LD	HL,#0000
		LD	(#5C7D),HL
		RES	0,(IY+#30)
		CALL	CL_CHAN
		LD	A,#FE
		CALL	CHAN_OPEN
		CALL	TEMPS
		LD	B,#18
		CALL	CL_LINE
		LD	HL,(#5C51)
		LD	DE,PRINT_OUT
		LD	(HL),E
		INC	HL
		LD	(HL),D
		LD	(IY+#52),#01
		LD	BC,#1821
CL_SET:		LD	HL,#5B00		; Set line and column numbers
		BIT	1,(IY+#01)
		JR	NZ,CL_SET_2
		LD	A,B
		BIT	0,(IY+#02)
		JR	Z,CL_SET_1
		ADD	A,(IY+#31)
		SUB	#18
CL_SET_1:	PUSH	BC
		LD	B,A
		CALL	CL_ADDR
		POP	BC
CL_SET_2:	LD	A,#21
		SUB	C
		LD	E,A
		LD	D,#00
		ADD	HL,DE
		JP	PO_STORE

; Scroll part or whole display
CL_SC_ALL:	LD	B,#17
CL_SCROLL:	CALL	CL_ADDR
		LD	C,#08
CL_SCR_1:	PUSH	BC
		PUSH	HL
		LD	A,B
		AND	#07
		LD	A,B
		JR	NZ,CL_SCR_3
CL_SCR_2:	EX	DE,HL
		LD	HL,#F8E0
		ADD	HL,DE
		EX	DE,HL
		LD	BC,#0020
		DEC	A
		LDIR
CL_SCR_3:	EX	DE,HL
		LD	HL,#FFE0
		ADD	HL,DE
		EX	DE,HL
		LD	B,A
		AND	#07
		RRCA
		RRCA
		RRCA
		LD	C,A
		LD	A,B
		LD	B,#00
		LDIR
		LD	B,#07
		ADD	HL,BC
		AND	#F8
		JR	NZ,CL_SCR_2
		POP	HL
		INC	H
		POP	BC
		DEC	C
		JR	NZ,CL_SCR_1
		CALL	CL_ATTR
		LD	HL,#FFE0
		ADD	HL,DE
		EX	DE,HL
		LDIR
		LD	B,#01
CL_LINE:	PUSH	BC			; Clear text lines at the bottom of display
		CALL	CL_ADDR
		LD	C,#08
CL_LINE_1:	PUSH	BC
		PUSH	HL
		LD	A,B
CL_LINE_2:	AND	#07
		RRCA
		RRCA
		RRCA
		LD	C,A
		LD	A,B
		LD	B,#00
		DEC	C
		LD	D,H
		LD	E,L
		LD	(HL),#00
		INC	DE
		LDIR
		LD	DE,#0701
		ADD	HL,DE
		DEC	A
		AND	#F8
		LD	B,A
		JR	NZ,CL_LINE_2
		POP	HL
		INC	H
		POP	BC
		DEC	C
		JR	NZ,CL_LINE_1
		CALL	CL_ATTR
		LD	H,D
		LD	L,E
		INC	DE
		LD	A,(#5C8D)
		BIT	0,(IY+#02)
		JR	Z,CL_LINE_3
		LD	A,(#5C48)
CL_LINE_3:	LD	(HL),A
		DEC	BC
		LDIR
		POP	BC
		LD	C,#21
		RET

; Attribute handling
CL_ATTR:	LD	A,H
		RRCA
		RRCA
		RRCA
		DEC	A
		OR	#50
		LD	H,A
		EX	DE,HL
		LD	H,C
		LD	L,B
		ADD	HL,HL
		ADD	HL,HL
		ADD	HL,HL
		ADD	HL,HL
		ADD	HL,HL
		LD	B,H
		LD	C,L
		RET

; Handle display with line number
CL_ADDR:	LD	A,#18
		SUB	B
		LD	D,A
		RRCA
		RRCA
		RRCA
		AND	#E0
		LD	L,A
		LD	A,D
		AND	#18
		OR	#40
		LD	H,A
		RET

; BSROM for MB02+ - here was ZX Printer handling.
; Replaced with BSDOS patches
COPY:		RET

STKDUP:		RST	#28			;FP_CALC
		DB	#31			;DUPLICATE
		DB	#38			;END_CALC
		RET

ZNKCMD:		DB	'.', '@', '$', '`'	; new commands

NEWCMD:		LD	HL,ZNKCMD		; extended BASIC interpreter
		LD	BC,#0004
		CPIR
		JP	NZ,COMM
		LD	(#5C74),A
		DB	#3E
CMDMGF:		POP	AF
CMDEXE:		LD	(#5C3F),SP
		LD	A,BASICM
		JR	DOSCAL

TSTSAV:		LD	HL,TAPDSK
		BIT	0,(HL)
		LD	HL,#1F80
		RET	Z
		LD	L,A
		LD	A,EM4C6
		JR	LOASAV

TSTLOA:		LD	A,(TAPDSK)
		RRCA
		JR	C,LOADOS
		DI
		LD	A,#0E
		OUT	(#FE),A
		IN	A,(#FE)
		RRA
		RET

LOADOS:		LD	A,EM562
LOASAV:		POP	BC
DOSCAL:		CALL	BNKCAL
		DW	#0020
		RET

NEWFNC:		LD	A,FUNKC
		CALL	DOSCAL
		JP	Z,S_CONT_2
		RST	#18
		CALL	SYNTAX_Z
		JP	Z,S_FN_SBRN1
		JP	SF_RUN1

; BSROM for MB02+
; Reserved for future BSDOS patches

		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000

		RET

; The editor routine - prepare or edit BASIC line, or handle INPUT expression
EDITOR:		LD	HL,(#5C3D)
		PUSH	HL
ED_AGAIN:	LD	HL,ED_ERROR
		PUSH	HL
		LD	(#5C3D),SP
ED_LOOP:	CALL	WAIT_KEY
		PUSH	AF
		LD	D,#00
		LD	E,(IY-#01)
		LD	HL,#00C8
		CALL	BEEPER
		POP	AF
		LD	HL,ED_LOOP
		PUSH	HL
		CP	#18
		JR	NC,ADD_CHAR
		CP	#07
		JR	C,ADD_CHAR
		CP	#10
		JR	C,ED_KEYS
		LD	BC,#0002
		LD	D,A
		CP	#16
		JR	C,ED_CONTR
		INC	BC
		BIT	7,(IY+#37)
		JP	Z,ED_IGNORE
		CALL	WAIT_KEY
		LD	E,A
ED_CONTR:	CALL	WAIT_KEY
		PUSH	DE
		LD	HL,(#5C5B)
		RES	0,(IY+#07)
		CALL	MAKE_ROOM
		POP	BC
		INC	HL
		LD	(HL),B
		INC	HL
		LD	(HL),C
		JR	ADD_CH_1

; Add code to current line
ADD_CHAR:	RES	0,(IY+#07)
		LD	HL,(#5C5B)
		CALL	ONE_SPACE
ADD_CH_1:	LD	(DE),A
		INC	DE
		LD	(#5C5B),DE
		RET

ED_KEYS:	LD	E,A
		LD	D,#00
		LD	HL,ED_KEYS_T-7
		ADD	HL,DE
		LD	E,(HL)
		ADD	HL,DE
		PUSH	HL
		LD	HL,(#5C5B)
		RET

; Editing keys table
ED_KEYS_T:	DB	#09			; ED_EDIT
		DB	#66			; ED_LEFT
		DB	#6A			; ED_RIGHT
		DB	#50			; ED_DOWN
		DB	#B5			; ED_UP
		DB	#70			; ED_DELETE
		DB	#7E			; ED_ENTER
		DB	#CF			; ED_SYMBOL
		DB	#D4			; ED_GRAPH

; Handle EDIT key
ED_EDIT:	LD	HL,(#5C49)
		BIT	5,(IY+#37)
		JP	NZ,CLEAR_SP
		CALL	LINE_ADDR
		CALL	LIN2			; BSROM - modified BASIC program presence test
		AND	#C0
		JP	NZ,CLEAR_SP
		PUSH	HL
		INC	HL
		LD	C,(HL)
		INC	HL
		LD	B,(HL)
		LD	HL,#000A
		ADD	HL,BC
		LD	B,H
		LD	C,L
		CALL	TEST_ROOM
		CALL	CLEAR_SP
		LD	HL,(#5C51)
		EX	(SP),HL
		PUSH	HL
		LD	A,#FF
		CALL	CHAN_OPEN
		POP	HL
		DEC	HL
		CALL	OUT_LINE		;BSROM - cursor placement after EDIT
		LD	DE,#0005
		LD	HL,(#5C59)
		ADD	HL,DE
		LD	(#5C5B),HL
		POP	HL
		JP	CHAN_FLAG

TOERR:		LD	(#5C5F),HL		; BSROM - cursor jumps to error
		LD	(#5C5B),HL
		RET

; Cursor down editing
ED_DOWN:	CALL	DOLE			; BSROM - free cursor moving
		BIT	5,(IY+#37)
		RET	NZ
		NOP
		CALL	LN_FETCH
		JR	ED_LIST

ED_STOP:	LD	(IY+#00),#10
		JR	ED_ENTER

; Cursor left editing
ED_LEFT:	CALL	ED_EDGE
		JR	ED_CUR

; Cursor right editing
ED_RIGHT:	LD	A,(HL)
		CP	#0D
		RET	Z
		INC	HL
ED_CUR:		LD	(#5C5B),HL
		RET

; Handling DELETE
ED_DELETE:	CALL	ED_EDGE
		LD	BC,#0001
		JP	RECLAIM_2

; Ignore next two codes from KEY_INPUT routine
ED_IGNORE:	CALL	WAIT_KEY
		CALL	WAIT_KEY
ED_ENTER:	POP	HL			; Handle ENTER
		POP	HL
ED_END:		POP	HL
		LD	(#5C3D),HL
		BIT	7,(IY+#00)
		RET	NZ
		LD	SP,HL
		RET

; Move cursor left when editing
ED_EDGE:	SCF
		CALL	SET_DE
		SBC	HL,DE
		ADD	HL,DE
		INC	HL
		POP	BC
		RET	C
		PUSH	BC
		LD	B,H
		LD	C,L
ED_EDGE_1:	LD	H,D
		LD	L,E
		INC	HL
		LD	A,(DE)
		AND	#F0
		CP	#10
		JR	NZ,ED_EDGE_2
		INC	HL
		LD	A,(DE)
		SUB	#17
		ADC	A,#00
		JR	NZ,ED_EDGE_2
		INC	HL
ED_EDGE_2:	AND	A
		SBC	HL,BC
		ADD	HL,BC
		EX	DE,HL
		JR	C,ED_EDGE_1
		RET

; Cursor up editing
ED_UP:		CALL	HORE			; BSROM - free cursor moving
		BIT	5,(IY+#37)
		RET	NZ
		CALL	LINE_ADDR
		EX	DE,HL
		CALL	LINE_NO
		LD	HL,#5C4A
		CALL	LN_STORE
ED_LIST:	CALL	AUTO_LIST
ED_LIST_1:	LD	A,#00
		JP	CHAN_OPEN

; Use of symbol and graphic codes
ED_SYMBOL:	BIT	7,(IY+#37)
		JR	Z,ED_ENTER
ED_GRAPH:	JP	ADD_CHAR

; Editor error handling
ED_ERROR:	BIT	4,(IY+#30)
		JR	Z,ED_END
		LD	(IY+#00),#FF
		LD	D,#00
		LD	E,(IY-#02)
		LD	HL,#0190		; BSROM - higher tone of error beep, was LD HL,#1A90
		CALL	BEEPER
		JP	ED_AGAIN

; Clear workspace
CLEAR_SP:	PUSH	HL
		CALL	SET_HL
		DEC	HL
		CALL	RECLAIM_1
		LD	(#5C5B),HL
		LD	(IY+#07),#00
		POP	HL
		RET

; Handle keyboard input
KEY_INPUT:	BIT	3,(IY+#02)
		CALL	NZ,ED_COPY
		AND	A
		BIT	5,(IY+#01)
		RET	Z
		LD	A,(#5C08)
		RES	5,(IY+#01)
		PUSH	AF
		BIT	5,(IY+#02)
		CALL	NZ,CLS_LOWER
		POP	AF
		CP	#20
		JR	NC,KEY_DONE2
		CP	#10
		JR	NC,KEY_CONTR
		CP	#06
		JR	NC,KEY_M_CL
		LD	B,A
		AND	#01
		LD	C,A
		LD	A,B
		RRA
		ADD	A,#12
		JR	KEY_DATA

; Separate caps lock
KEY_M_CL:	JR	NZ,KEY_MODE
		LD	HL,#5C6A
		LD	A,#08
		XOR	(HL)
		LD	(HL),A
		JR	KEY_FLAG

; Mode handling
KEY_MODE:	CP	#0E
		RET	C
		SUB	#0D
		LD	HL,#5C41
		CP	(HL)
		LD	(HL),A
		JR	NZ,KEY_FLAG
		LD	(HL),#00
KEY_FLAG:	SET	3,(IY+#02)
		CP	A
		RET

; Handle colour controls
KEY_CONTR:	LD	B,A
		AND	#07
		LD	C,A
		LD	A,#10
		BIT	3,B
		JR	NZ,KEY_DATA
		INC	A
KEY_DATA:	LD	(IY-#2D),C
		LD	DE,KEY_NEXT
		JR	KEY_CHAN

KEY_NEXT:	LD	A,(#5C0D)
		LD	DE,KEY_INPUT
KEY_CHAN:	LD	HL,(#5C4F)
		INC	HL
		INC	HL
		LD	(HL),E
		INC	HL
		LD	(HL),D
KEY_DONE2:	SCF
		RET

; Print lower screen workspace
ED_COPY:	CALL	TEMPS
		RES	3,(IY+#02)
		RES	5,(IY+#02)
		LD	HL,(#5C8A)
		PUSH	HL
		LD	HL,(#5C3D)
		PUSH	HL
		LD	HL,ED_FULL
		PUSH	HL
		LD	(#5C3D),SP
		LD	HL,(#5C82)
		PUSH	HL
		SCF
		CALL	SET_DE
		EX	DE,HL
		CALL	OUT_LINE2
		EX	DE,HL
		CALL	OUT_CURS
		LD	HL,(#5C8A)
		EX	(SP),HL
		EX	DE,HL
		CALL	TEMPS
ED_BLANK:	LD	A,(#5C8B)
		SUB	D
		JR	C,ED_C_DONE
		JR	NZ,ED_SPACES
		LD	A,E
		SUB	(IY+#50)
		JR	NC,ED_C_DONE
ED_SPACES:	LD	A,#20
		PUSH	DE
		CALL	PRINT_OUT
		POP	DE
		JR	ED_BLANK

; Error handling
ED_FULL:	LD	D,#00
		LD	E,(IY-#02)
		LD	HL,#0190		; BSROM - higher tone of error beep, was LD HL,#1A90
		CALL	BEEPER
		LD	(IY+#00),#FF
		LD	DE,(#5C8A)
		JR	ED_C_END

ED_C_DONE:	POP	DE
		POP	HL
ED_C_END:	POP	HL
		LD	(#5C3D),HL
		POP	BC
		PUSH	DE
		CALL	CL_SET
		POP	HL
		LD	(#5C82),HL
		LD	(IY+#26),#00
		RET

; Ensure that the proper pointers are selected for workspace
SET_HL:		LD	HL,(#5C61)
		DEC	HL
		AND	A
SET_DE:		LD	DE,(#5C59)
		BIT	5,(IY+#37)
		RET	Z
		LD	DE,(#5C61)
		RET	C
		LD	HL,(#5C63)
		RET

; Remove floating point from line
REMOVE_FP:	LD	A,(HL)
		CP	#0E
		LD	BC,#0006
		CALL	Z,RECLAIM_2
		LD	A,(HL)
		INC	HL
		CP	#0D
		JR	NZ,REMOVE_FP
		RET

; Handle NEW command
NEW:		DI
		LD	A,#FF
		LD	DE,(#5CB2)
NEW_1:		EXX
		LD	BC,(#5CB4)
		LD	DE,(#5C38)
		LD	HL,(#5C7B)
		EXX
START_NEW:	LD	B,A
		XOR	A			; BSROM - faster RAM clear, RAM is not tested for errors
		LD	I,A
		LD	C,A
		LD	H,D
		LD	L,E
		LD	A,B
		LD	B,C
		LD	SP,HL
CLSUJ:		PUSH	BC
		PUSH	BC
		PUSH	BC
		PUSH	BC
		PUSH	BC
		PUSH	BC
		PUSH	BC
		PUSH	BC
		LD	HL,#A7FF
		ADD	HL,SP
		JR	C,CLSUJ
		EX	DE,HL
		JR	RAM_DONE1

; Modified CONTINUE command
NEW_CONT:	CALL	FIND_INT2
		LD	A,B
		OR	C
		JP	Z,CONTINUE
		PUSH	BC
		RET
; Remains of original RAM_DONE routine
RAM_DONE1:	EXX
		LD	(#5CB4),BC
		LD	(#5C38),DE
		LD	(#5C7B),HL
		EXX	
		INC	A			; BSROM - changed for new NEW command, was INC B
		JR	Z,RAM_SET
RAM_DONE2:	LD	(#5CB4),HL
		LD	DE,#3EAF
		LD	BC,#00A8
		EX	DE,HL
		LDDR
		EX	DE,HL
		INC	HL
		LD	(#5C7B),HL
		DEC	HL
		LD	BC,#0040
		LD	(#5C38),BC
RAM_SET:	LD	(#5CB2),HL
		LD	HL,#3C00
		LD	(#5C36),HL
		LD	HL,(#5CB2)
		LD	(HL),#3E
		DEC	HL
		LD	SP,HL
		DEC	HL
		DEC	HL
		LD	(#5C3D),HL
		IM	1
		LD	IY,#5C3A
		EI
		LD	HL,#5CB6
		LD	(#5C4F),HL
		LD	DE,INIT_CHAN
		LD	BC,#0015
		EX	DE,HL
		LDIR
		EX	DE,HL
		DEC	HL
		LD	(#5C57),HL
		INC	HL
		LD	(#5C53),HL
		LD	(#5C4B),HL
		LD	(HL),#80
		INC	HL
		LD	(#5C59),HL
WARM_ST:	LD	(HL),#0D
		INC	HL
		LD	(HL),#80
		INC	HL
		LD	(#5C61),HL
		LD	(#5C63),HL
		LD	(#5C65),HL
		LD	A,#07			; BSROM - changed colors, blue border, black paper, white ink
		LD	(#5C8D),A
		LD	(#5C8F),A
		LD	(#5C48),A
		LD	HL,#0114		; BSROM - REPDEL and REPPER were changed, was #0523
		LD	(#5C09),HL
		DEC	(IY-#3A)
		DEC	(IY-#36)
		LD	HL,INIT_STRM
		LD	DE,#5C10
		LD	BC,#000E
		LDIR
		LD	(IY+#31),#02		; BSROM - printer vars initialization removed
		LD	(IY+#0E),#0F
		CALL	HARD			; reset AY, DMA, FDC
		CALL	SET_MIN
		LD	(IY+#00),#FF
		CALL	INFO			; copyright message replaced with status info
		CALL	SA_LD_RET
		JP	MAIN_4

; Main execution loop
MAIN_EXEC:	LD	(IY+#31),#02
		CALL	AUTO_LIST
MAIN_1:		CALL	SET_MIN
MAIN_2:		LD	A,#00
		CALL	CHAN_OPEN
		CALL	EDITOR
		CALL	LINE_SCAN
		BIT	7,(IY+#00)
		JR	NZ,MAIN_3
		BIT	4,(IY+#30)
		JR	Z,MAIN_4
		LD	HL,(#5C59)
		CALL	REMOVE_FP
		LD	(IY+#00),#FF
		JR	MAIN_2

MAIN_3:		LD	HL,(#5C59)
		LD	(#5C5D),HL
		CALL	LIN3			; BSROM - modified test of number at the begin of BASIC line
		NOP
		NOP
		JP	NC,MAIN_ADD		; BSROM - don't test zero, so line 0 can be used and/or edited
		RST	#18
		CP	#0D
		JR	Z,MAIN_EXEC
		BIT	0,(IY+#30)
		CALL	NZ,CL_ALL
		CALL	CLS_LOWER
		LD	A,#19
		SUB	(IY+#4F)
		LD	(#5C8C),A
		SET	7,(IY+#01)
		LD	(IY+#00),#FF
		LD	(IY+#0A),#01
		CALL	LINE_RUN
MAIN_4:		RST	#38			; BSROM - bugfix - was HALT
		HALT				; BSROM for MB02+ - wait for beam
		NOP				; BSROM for MB02+ - ZX Printer not used anymore hence six NOPs
		NOP
		NOP
		RES	5,(IY+#01) 
		NOP
		NOP
		NOP
		LD	A,(#5C3A)
		INC	A
MAIN_G:		PUSH	AF
		LD	HL,#0000
		LD	(IY+#37),H
		LD	(IY+#26),H
		LD	(#5C0B),HL
		LD	HL,#0001
		LD	(#5C16),HL
		CALL	SET_MIN
		RES	5,(IY+#37)
		CALL	CLS_LOWER
		SET	5,(IY+#02)
		POP	AF
		LD	B,A
		CP	#0A
		JR	C,MAIN_5
		ADD	A,#07
MAIN_5:		CALL	OUT_CODE
		LD	A,#20
		RST	#10
		LD	A,B
		LD	DE,RPT_MESGS
		CALL	PO_MSG
		XOR	A
		LD	DE,COMMA_SP-1
		CALL	PO_MSG
		LD	BC,(#5C45)
		CALL	OUT_NUM_1
		LD	A,#3A
		RST	#10
		LD	C,(IY+#0D)
		LD	B,#00
		CALL	OUT_NUM_1
		CALL	CLEAR_SP
		LD	A,(#5C3A)
		INC	A
		JR	Z,MAIN_9
		CP	#09
		JR	Z,MAIN_6
		CP	#15
		JR	NZ,MAIN_7
MAIN_6:		INC	(IY+#0D)
MAIN_7:		LD	BC,#0003
		LD	DE,#5C70
		LD	HL,#5C44
		BIT	7,(HL)
		JR	Z,MAIN_8
		ADD	HL,BC
MAIN_8:		LDDR
MAIN_9:		LD	(IY+#0A),#FF
		RES	3,(IY+#01)
		JP	MAIN_2

;The error mesages, with last byte inverted.
;The first #80 entry is dummy entry.
RPT_MESGS:	DB	#80
		DC	"OK"
		DC	"NEXT without FOR"
		DC	"Variable not found"
		DC	"Subscript wrong"
		DC	"Out of memory"
		DC	"Out of screen"
		DC	"Number too big"
		DC	"RETURN without GOSUB"
		DC	"End of file"
		DC	"STOP statement"
		DC	"Invalid argument"
		DC	"Integer out of range"
		DC	"Nonsense in BASIC"
		DC	"BREAK - CONT repeats"
		DC	"Out of DATA"
		DC	"Invalid file name"
		DC	"No room for line"
		DC	"STOP in INPUT"
		DC	"FOR without NEXT"
		DC	"Invalid I/O device"
		DC	"Invalid colour"
		DC	"BREAK into program"
		DC	"RAMTOP no good"
		DC	"Statement lost"
		DC	"Invalid stream"
		DC	"FN without DEF"
		DC	"Parameter error"
		DC	"Tape loading error"
COMMA_SP:	DC	", "

; BSROM - here was the copyright message in the original ZX Spectrum ROM.
COPYRIGHT:	DC	"Rom 140"
		DC	"Prog:"
		DB	#16
		DB	#00
		DB	#0B

		DC	"Vars:"
		DB	#16
		DB	#00
		DB	#16

		DC	"Free:"

; Out of memory handling
REPORT_G:	LD	A,#10
		LD	BC,#0000
		JP	MAIN_G

; Handle additon of BASIC line
MAIN_ADD:	LD	(#5C49),BC
		LD	HL,(#5C5D)
		EX	DE,HL
		LD	HL,REPORT_G
		PUSH	HL
		LD	HL,(#5C61)
		SCF
		SBC	HL,DE
		PUSH	HL
		LD	H,B
		LD	L,C
		CALL	LINE_ADDR
		JR	NZ,MAIN_ADD1
		CALL	NEXT_ONE
		CALL	RECLAIM_2
MAIN_ADD1:	POP	BC
		LD	A,C
		DEC	A
		OR	B
		JR	Z,MAIN_ADD2
		PUSH	BC
		INC	BC
		INC	BC
		INC	BC
		INC	BC
		DEC	HL
		LD	DE,(#5C53)
		PUSH	DE
		CALL	MAKE_ROOM
		POP	HL
		LD	(#5C53),HL
		POP	BC
		PUSH	BC
		INC	DE
		LD	HL,(#5C61)
		DEC	HL
		DEC	HL
		LDDR
		LD	HL,(#5C49)
		EX	DE,HL
		POP	BC
		LD	(HL),B
		DEC	HL
		LD	(HL),C
		DEC	HL
		LD	(HL),E
		DEC	HL
		LD	(HL),D
MAIN_ADD2:	POP	AF
		JP	MAIN_EXEC

; Initial channel information
INIT_CHAN:	DW	PRINT_OUT
		DW	KEY_INPUT
		DB	"K"
		DW	PRINT_OUT
		DW	REPORT_J
		DB	"S"
		DW	ADD_CHAR
		DW	REPORT_J
		DB	"R"
		DW	PRINT_OUT
		DW	REPORT_J
		DB	"P"
		DB	#80			; End marker

REPORT_J:	RST	#08			; Error report
		DB	#12			; Invalid I/O device

; Initial stream data
INIT_STRM:	DB	#01, #00		; stream #FD offset to channel 'K'
		DB	#06, #00		; stream #FE offset to channel 'S'
		DB	#0B, #00		; stream #FF offset to channel 'R'
		DB	#01, #00		; stream #00 offset to channel 'K'
		DB	#01, #00		; stream #01 offset to channel 'K'
		DB	#06, #00		; stream #02 offset to channel 'S'
		DB	#10, #00		; stream #03 offset to channel 'P'

; Control for input subroutine
WAIT_KEY:	BIT	5,(IY+#02)
		JR	NZ,WAIT_KEY1
		SET	3,(IY+#02)
WAIT_KEY1:	CALL	INPUT_AD
		RET	C
		JR	Z,WAIT_KEY1
REPORT_8:	RST	#08			; Error report
		DB	#07			; End of file
INPUT_AD:	EXX
		PUSH	HL
		LD	HL,(#5C51)
		INC	HL
		INC	HL
		JR	CALL_SUB

; Print ascii equivalent of a value 0-9
OUT_CODE:	LD	E,#30
		ADD	A,E
PRINT_A_2:	EXX
		PUSH	HL
		LD	HL,(#5C51)
CALL_SUB:	LD	E,(HL)
		INC	HL
		LD	D,(HL)
		EX	DE,HL
		CALL	CALL_JUMP
		POP	HL
		EXX
		RET

; Open a channel 'K', 'S', 'R' or 'P'
CHAN_OPEN:	ADD	A,A
		ADD	A,#16
		LD	L,A
		LD	H,#5C
		LD	E,(HL)
		INC	HL
		LD	D,(HL)
		LD	A,D
		OR	E
		JR	NZ,CHAN_OP_1
REPORT_OA:	RST	#08			; Error report
		DB	#17			; Invalid stream
CHAN_OP_1:	DEC	DE
		LD	HL,(#5C4F)
		ADD	HL,DE
CHAN_FLAG:	LD	(#5C51),HL		; Set channel flags
		RES	4,(IY+#30)
		INC	HL
		INC	HL
		INC	HL
		INC	HL
		LD	C,(HL)
		LD	HL,CH_CD_LU
		CALL	INDEXER
		RET	NC
		LD	D,#00
		LD	E,(HL)
		ADD	HL,DE
CALL_JUMP:	JP	(HL)

; Channel code lookup table
CH_CD_LU:	DB	"K", #06		; CHAN_K
		DB	"S", #12		; CHAN_S
		DB	"P", #1B		; CHAN_P
		DB	#00			; End marker

; Channel K flag
CHAN_K:		SET	0,(IY+#02)
		RES	5,(IY+#01)
		SET	4,(IY+#30)
		JR	CHAN_S_1

; Channel S flag
CHAN_S:		RES	0,(IY+#02)
CHAN_S_1:	RES	1,(IY+#01)
		JP	TEMPS

; Channel P flag
CHAN_P:		SET	1,(IY+#01)
		RET

; Create a single space in workspace by ADD_CHAR
ONE_SPACE:	LD	BC,#0001
MAKE_ROOM:	PUSH	HL		; Create BC spaces in various areas
		CALL	TEST_ROOM
		POP	HL
		CALL	POINTERS
		LD	HL,(#5C65)
		EX	DE,HL
		LDDR
		RET

; Adjust pointers before making or reclaiming room
POINTERS:	PUSH	AF
		PUSH	HL
		LD	HL,#5C4B
		LD	A,#0E
PTR_NEXT:	LD	E,(HL)
		INC	HL
		LD	D,(HL)
		EX	(SP),HL
		AND	A
		SBC	HL,DE
		ADD	HL,DE
		EX	(SP),HL
		JR	NC,PTR_DONE
		PUSH	DE
		EX	DE,HL
		ADD	HL,BC
		EX	DE,HL
		LD	(HL),D
		DEC	HL
		LD	(HL),E
		INC	HL
		POP	DE
PTR_DONE:	INC	HL
		DEC	A
		JR	NZ,PTR_NEXT
		EX	DE,HL
		POP	DE
		POP	AF
		AND	A
		SBC	HL,DE
		LD	B,H
		LD	C,L
		INC	BC
		ADD	HL,DE
		EX	DE,HL
		RET

; Collect line number
LINE_ZERO:	DB	#00, #00		; Dummy line number for direct commands

LINE_NO_A:	EX	DE,HL
		LD	DE,LINE_ZERO
LINE_NO:	LD	A,(HL)
		AND	#C0
		JR	NZ,LINE_NO_A
		LD	D,(HL)
		INC	HL
		LD	E,(HL)
		RET

; Handle reserve room, continuation of the restart BC_SPACES
RESERVE:	LD	HL,(#5C63)
		DEC	HL
		CALL	MAKE_ROOM
		INC	HL
		INC	HL
		POP	BC
		LD	(#5C61),BC
		POP	BC
		EX	DE,HL
		INC	HL
		RET

; Clear editing areas
SET_MIN:	LD	HL,(#5C59)
		LD	(HL),#0D
		LD	(#5C5B),HL
		INC	HL
		LD	(HL),#80
		INC	HL
		LD	(#5C61),HL
SET_WORK:	LD	HL,(#5C61)
		LD	(#5C63),HL
SET_STK:	LD	HL,(#5C63)
		LD	(#5C65),HL
		PUSH	HL
		LD	HL,#5C92
		LD	(#5C68),HL
		POP	HL
		RET

; Not used code, remains of ZX80/ZX81 legacy code
REC_EDIT:	LD	DE,(#5C59)
		JP	RECLAIM_1

; Table indexing routine
INDEXER_1:	INC	HL
INDEXER:	LD	A,(HL)
		AND	A
		RET	Z
		CP	C
		INC	HL
		JR	NZ,INDEXER_1
		SCF
		RET

; Handle CLOSE# command
CLOSE:		CALL	STR_DATA
		CALL	CLOSE_2
		LD	BC,#0000
		LD	DE,#A3E2
		EX	DE,HL
		ADD	HL,DE
		JR	C,CLOSE_1
		LD	BC,INIT_STRM+14
		ADD	HL,BC
		LD	C,(HL)
		INC	HL
		LD	B,(HL)
CLOSE_1:	EX	DE,HL
		LD	(HL),C
		INC	HL
		LD	(HL),B
		RET

CLOSE_2:	PUSH	HL
		LD	HL,(#5C4F)
		ADD	HL,BC
		INC	HL
		INC	HL
		INC	HL
		LD	C,(HL)
		EX	DE,HL
		LD	HL,CL_STR_LU
		CALL	INDEXER
		LD	C,(HL)
		LD	B,#00
		ADD	HL,BC
		JP	(HL)

; Close stream lookup table
CL_STR_LU:	DB	"K", #05
		DB	"S", #03
		DB	"P", #01

CLOSE_STR:	POP	HL
		RET

; Stream data
STR_DATA:	CALL	FIND_INT1
		CP	#10
		JR	C,STR_DATA1
REPORT_OB:	RST	#08			; Error report
		DB	#17			; Invalid stream
STR_DATA1:	ADD	A,#03
		RLCA
		LD	HL,#5C10
		LD	C,A
		LD	B,#00
		ADD	HL,BC
		LD	C,(HL)
		INC	HL
		LD	B,(HL)
		DEC	HL
		RET

; Handle OPEN# command
OPEN:		RST	#28			;FP_CALC
		DB	#01			;EXCHANGE
		DB	#38			;END_CALC
		CALL	STR_DATA
		LD	A,B
		OR	C
		JR	Z,OPEN_1
		EX	DE,HL
		LD	HL,(#5C4F)
		ADD	HL,BC
		INC	HL
		INC	HL
		INC	HL
		LD	A,(HL)
		EX	DE,HL
		CP	#4B
		JR	Z,OPEN_1
		CP	#53
		JR	Z,OPEN_1
		CP	#50
		JR	NZ,REPORT_OB
OPEN_1:		CALL	OPEN_2
		LD	(HL),E
		INC	HL
		LD	(HL),D
		RET

OPEN_2:		PUSH	HL
		CALL	STK_FETCH
		LD	A,B
		OR	C
		JR	NZ,OPEN_3
REPORT_F:	RST	#08			; Error report
		DB	#0E			; Invalid file name
OPEN_3:		PUSH	BC
		LD	A,(DE)
		AND	#DF
		LD	C,A
		LD	HL,OP_STR_LU
		CALL	INDEXER
		JR	NC,REPORT_F
		LD	C,(HL)
		LD	B,#00
		ADD	HL,BC
		POP	BC
		JP	(HL)

; Open stream lookup table
OP_STR_LU:	DB	"K", #06		; OPEN_K
		DB	"S", #08		; OPEN_S
		DB	"P", #0A		; OPEN_P
		DB	#00			; End marker

; Open keyboard stream
OPEN_K:		LD	E,#01
		JR	OPEN_END

; Open Screen stream
OPEN_S:		LD	E,#06
		JR	OPEN_END

; Open printer stream
OPEN_P:		LD	E,#10
OPEN_END:	DEC	BC
		LD	A,B
		OR	C
		JR	NZ,REPORT_F
		LD	D,A
		POP	HL
		RET

; Handle CAT, ERASE, FORMAT and MOVE commands
CAT_ETC:	JR	REPORT_OB

; Automatic listing in the upper screen
AUTO_LIST:	LD	(#5C3F),SP
		LD	(IY+#02),#10
		CALL	CL_ALL
		SET	0,(IY+#02)
		LD	B,(IY+#31)
		CALL	CL_LINE
		RES	0,(IY+#02)
		SET	0,(IY+#30)
		LD	HL,(#5C49)
		LD	DE,(#5C6C)
		AND	A
		SBC	HL,DE
		ADD	HL,DE
		JR	C,AUTO_L_2
		PUSH	DE
		CALL	LINE_ADDR
		LD	DE,#02C0
		EX	DE,HL
		SBC	HL,DE
		EX	(SP),HL
		CALL	LINE_ADDR
		POP	BC
AUTO_L_1:	PUSH	BC
		CALL	NEXT_ONE
		POP	BC
		ADD	HL,BC
		JR	C,AUTO_L_3
		EX	DE,HL
		LD	D,(HL)
		INC	HL
		LD	E,(HL)
		DEC	HL
		LD	(#5C6C),DE
		JR	AUTO_L_1

AUTO_L_2:	LD	(#5C6C),HL
AUTO_L_3:	LD	HL,(#5C6C)
		CALL	LINE_ADDR
		JR	Z,AUTO_L_4
		EX	DE,HL
AUTO_L_4:	CALL	LIST_ALL
		RES	4,(IY+#02)
		RET

; Handle LLIST command
LLIST:		LD	A,#03
		JR	LIST_1

; Handle LIST command
LIST:		LD	A,#02
LIST_1:		LD	(IY+#02),#00
		CALL	SYNTAX_Z
		CALL	NZ,CHAN_OPEN
		RST	#18
		CALL	STR_ALTER
		JR	C,LIST_4
		RST	#18
		CP	#3B
		JR	Z,LIST_2
		CP	#2C
		JR	NZ,LIST_3
LIST_2:		RST	#20
		CALL	EXPT_1NUM
		JR	LIST_5

LIST_3:		CALL	USE_ZERO
		JR	LIST_5

LIST_4:		CALL	FETCH_NUM
LIST_5:		CALL	CHECK_END
		CALL	FIND_INT2
		LD	A,B
		AND	#3F
		LD	H,A
		LD	L,C
		LD	(#5C49),HL
		CALL	LINE_ADDR
LIST_ALL:	LD	E,#01
LIST_ALL_2:	CALL	OUT_LINE
		RST	#10
		BIT	4,(IY+#02)
		JR	Z,LIST_ALL_2
		LD	A,(#5C6B)
		SUB	(IY+#4F)
		JR	NZ,LIST_ALL_2
		XOR	E
		RET	Z
		PUSH	HL
		PUSH	DE
		LD	HL,#5C6C
		CALL	LN_FETCH
		POP	DE
		POP	HL
		JR	LIST_ALL_2

; Print a whole BASIC line
OUT_LINE:	LD	BC,(#5C49)
		CALL	CP_LINES
		LD	D,#2A			; BSROM - line cursor is "*" instead of ">"
		JR	Z,OUT_LINE1
		LD	DE,#2000		; BSROM - " " instead of suppressing line cursor
		RL	E
OUT_LINE1:	LD	(IY+#2D),E
		LD	A,(HL)
		CP	#40
		POP	BC
		RET	NC
		PUSH	BC
		CALL	LIN4			; BSROM - no cursor
		INC	HL
		INC	HL
		INC	HL
		XOR	A
		XOR	D
		JR	Z,OUT_LINE1A
		RST	#10
OUT_LINE1A:	NOP				; remains of old code are replaced with NOPs
		NOP
		NOP
		NOP
OUT_LINE2:	SET	0,(IY+#01)
OUT_LINE3:	PUSH	DE
		EX	DE,HL
		RES	2,(IY+#30)
		LD	HL,#5C3B
		RES	2,(HL)
		BIT	5,(IY+#37)
		JR	Z,OUT_LINE4
		SET	2,(HL)
OUT_LINE4:	LD	HL,(#5C5F)
		AND	A
		SBC	HL,DE
		JR	NZ,OUT_LINE5
		LD	A,#3F
		CALL	OUT_FLASH
OUT_LINE5:	CALL	OUT_CURS
		EX	DE,HL
		LD	A,(HL)
		CALL	NUMBER
		INC	HL
		CP	#0D
		JR	Z,OUT_LINE6
		EX	DE,HL
		CALL	OUT_CHAR
		JR	OUT_LINE4

OUT_LINE6:	POP	DE
		RET

; Check for a number marker
NUMBER:		CP	#0E
		RET	NZ
		INC	HL
		INC	HL
		INC	HL
		INC	HL
		INC	HL
		INC	HL
		LD	A,(HL)
		RET

; Print a flashing character
OUT_FLASH:	EXX
		LD	HL,(#5C8F)
		PUSH	HL
		RES	7,H
		SET	7,L
		LD	(#5C8F),HL
		LD	HL,#5C91
		LD	D,(HL)
		PUSH	DE
		LD	(HL),#00
		CALL	PRINT_OUT
		POP	HL
		LD	(IY+#57),H
		POP	HL
		LD	(#5C8F),HL
		EXX
		RET

; Print the cursor
OUT_CURS:	LD	HL,(#5C5B)
		AND	A
		SBC	HL,DE
		RET	NZ
		LD	A,(#5C41)
		RLC	A
		JR	Z,OUT_C_1
		ADD	A,#43
		JR	OUT_C_2

OUT_C_1:	LD	HL,#5C3B
		RES	3,(HL)
		LD	A,#4B
		BIT	2,(HL)
		JR	Z,OUT_C_2
		SET	3,(HL)
		INC	A
		BIT	3,(IY+#30)
		JR	Z,OUT_C_2
		LD	A,#43
OUT_C_2:	PUSH	DE
		CALL	OUT_FLASH
		POP	DE
		RET

; Get line number of the next line
LN_FETCH:	LD	E,(HL)
		INC	HL
		LD	D,(HL)
		PUSH	HL
		EX	DE,HL
		INC	HL
		CALL	LINE_ADDR
		CALL	LINE_NO
		POP	HL
LN_STORE:	BIT	5,(IY+#37)
		RET	NZ
		LD	(HL),D
		DEC	HL
		LD	(HL),E
		RET

; Outputting numbers at start of BASIC line
OUT_SP_2:	LD	A,E
		AND	A
		RET	M
		JR	OUT_CHAR

OUT_SP_NO:	XOR	A
OUT_SP_1:	ADD	HL,BC
		INC	A
		JR	C,OUT_SP_1
		SBC	HL,BC
		DEC	A
		JR	Z,OUT_SP_2
		JP	OUT_CODE

; Outputting characters in a BASIC line
OUT_CHAR:	CALL	NUMERIC
		JR	NC,OUT_CH_3
		CP	#21
		JR	C,OUT_CH_3
		RES	2,(IY+#01)
		CP	#CB
		JR	Z,OUT_CH_3
		CP	#3A
		JR	NZ,OUT_CH_1
		BIT	5,(IY+#37)
		JR	NZ,OUT_CH_2
		BIT	2,(IY+#30)
		JR	Z,OUT_CH_3
		JR	OUT_CH_2

OUT_CH_1:	CP	#22
		JR	NZ,OUT_CH_2
		PUSH	AF
		LD	A,(#5C6A)
		XOR	#04
		LD	(#5C6A),A
		POP	AF
OUT_CH_2:	SET	2,(IY+#01)
OUT_CH_3:	RST	#10
		RET

; Get starting address of line (or line after)
LINE_ADDR:	PUSH	HL
		LD	HL,(#5C53)
		LD	D,H
		LD	E,L
LINE_AD_1:	POP	BC
		CALL	LIN1			; BSROM - modified line number test
		RET	NC
		PUSH	BC
		CALL	NEXT_ONE
		EX	DE,HL
		JR	LINE_AD_1

; Compare line numbers
CP_LINES:	LD	A,(HL)
		CP	B
		RET	NZ
		INC	HL
		LD	A,(HL)
		DEC	HL
		CP	C
		RET

; Find each statement
		INC	HL			; 3x INC HL not used in this ROM
		INC	HL
		INC	HL
EACH_STMT:	LD	(#5C5D),HL
		LD	C,#00
EACH_S_1:	DEC	D
		RET	Z
		RST	#20
		CP	E
		JR	NZ,EACH_S_3
		AND	A
		RET

EACH_S_2:	INC	HL
		LD	A,(HL)
EACH_S_3:	CALL	NUMBER
		LD	(#5C5D),HL
		CP	#22
		JR	NZ,EACH_S_4
		DEC	C
EACH_S_4:	CP	#3A
		JR	Z,EACH_S_5
		CP	#CB
		JR	NZ,EACH_S_6
EACH_S_5:	BIT	0,C
		JR	Z,EACH_S_1
EACH_S_6:	CP	#0D
		JR	NZ,EACH_S_2
		DEC	D
		SCF
		RET

; Find the address of the next line in the program area,
; or the next variable in the variables area
NEXT_ONE:	PUSH	HL
		LD	A,(HL)
		CP	#40
		JR	C,NEXT_O_3
		BIT	5,A
		JR	Z,NEXT_O_4
		ADD	A,A
		JP	M,NEXT_O_1
		CCF
NEXT_O_1:	LD	BC,#0005
		JR	NC,NEXT_O_2
		LD	C,#12
NEXT_O_2:	RLA
		INC	HL
		LD	A,(HL)
		JR	NC,NEXT_O_2
		JR	NEXT_O_5

NEXT_O_3:	INC	HL
NEXT_O_4:	INC	HL
		LD	C,(HL)
		INC	HL
		LD	B,(HL)
		INC	HL
NEXT_O_5:	ADD	HL,BC
		POP	DE
DIFFER:		AND	A
		SBC	HL,DE
		LD	B,H
		LD	C,L
		ADD	HL,DE
		EX	DE,HL
		RET

; Handle reclaiming space
RECLAIM_1:	CALL	DIFFER
RECLAIM_2:	PUSH	BC
		LD	A,B
		CPL
		LD	B,A
		LD	A,C
		CPL
		LD	C,A
		INC	BC
		CALL	POINTERS
		EX	DE,HL
		POP	HL
		ADD	HL,DE
		PUSH	DE
		LDIR
		POP	HL
		RET
		
; Read line number of line editing area
E_LINE_NO:	LD	HL,(#5C59)
		DEC	HL
		LD	(#5C5D),HL
		RST	#20
		LD	HL,#5C92
		LD	(#5C65),HL
		CALL	INT_TO_FP
		CALL	FP_TO_BC
		JR	C,E_L_1
		LD	HL,#C000		; BSROM - line number can be 0..16383 now, was LD HL,$D8F0 (max 9999 lines)
		ADD	HL,BC
E_L_1:		JP	C,REPORT_C
		JP	SET_STK

; Report and line number outputting
OUT_NUM_1:	PUSH	DE
		PUSH	HL
		XOR	A
		BIT	7,B
		JR	NZ,OUT_NUM_4
		LD	H,B
		LD	E,#FF			;BSROM - lines 0..16383
		JP	NUMCOM

OUT_NUM_2:	PUSH	DE
		LD	D,(HL)
		INC	HL
		LD	E,(HL)
		PUSH	HL
		EX	DE,HL
		LD	E,#20
OUT_NUM_3:	LD	BC,#FC18
		CALL	OUT_SP_NO
		LD	BC,#FF9C
		CALL	OUT_SP_NO
		LD	C,#F6
		CALL	OUT_SP_NO
		LD	A,L
OUT_NUM_4:	CALL	OUT_CODE
		POP	HL
		POP	DE
		RET

; The offset table for command interpretation
OFFST_TBL:	DB	#B1			; P_DEF_FN
		DB	#CB			; P_CAT
		DB	#BC			; P_FORMAT
		DB	#BF			; P_MOVE
		DB	#C4			; P_ERASE
		DB	#AF			; P_OPEN
		DB	#B4			; P_CLOSE
		DB	#93			; P_MERGE
		DB	#91			; P_VERIFY
		DB	#92			; P_BEEP
		DB	#95			; P_CIRCLE
		DB	#98			; P_INK
		DB	#98			; P_PAPER
		DB	#98			; P_FLASH
		DB	#98			; P_BRIGHT
		DB	#98			; P_INVERSE
		DB	#98			; P_OVER
		DB	#98			; P_OUT
		DB	#7F			; P_LPRINT
		DB	#81			; P_LLIST
		DB	#2E			; P_STOP
		DB	#6C			; P_READ
		DB	#6E			; P_DATA
		DB	#70			; P_RESTORE
		DB	#48			; P_NEW
		DB	#94			; P_BORDER
		DB	#56			; P_CONT
		DB	#3F			; P_DIM
		DB	#41			; P_REM
		DB	#2B			; P_FOR
		DB	#17			; P_GO_TO
		DB	#1F			; P_GO_SUB
		DB	#37			; P_INPUT
		DB	#77			; P_LOAD
		DB	#44			; P_LIST
		DB	#0F			; P_LET
		DB	#59			; P_PAUSE
		DB	#2B			; P_NEXT
		DB	#43			; P_POKE
		DB	#2D			; P_PRINT
		DB	#51			; P_PLOT
		DB	#3A			; P_RUN
		DB	#6D			; P_SAVE
		DB	#42			; P_RANDOM
		DB	#0D			; P_IF
		DB	#49			; P_CLS
		DB	#5C			; P_DRAW
		DB	#44			; P_CLEAR
		DB	#15			; P_RETURN
		DB	#5D			; P_COPY

; The parameter table. List of parameters for commands.		
P_LET:		DB	#01
		DB	"="
		DB	#02

P_GO_TO:	DB	#03			; BSROM - enhanced GOTO command, parameter is optional
		DW	GO_TO
		DB	#00

P_IF:		DB	#06
		DB	#CB
		DB	#05
		DW	IF_CMD

P_GO_SUB:	DB	#03			; BSROM - enhanced GOSUB command, parameter is optional
		DW	GO_SUB
		DB	#00
	
P_STOP:		DB	#00
		DW	STOP

P_RETURN:	DB	#00
		DW	RETURN

P_FOR:		DB	#04
		DB	"="
		DB	#06
		DB	#CC
		DB	#06
		DB	#05
		DW	FOR

P_NEXT:		DB	#04
		DB	#00
		DW	NEXT

P_PRINT:	DB	#05
		DW	PRINT

P_INPUT:	DB	#05
		DW	INPUT

P_DIM:		DB	#05
		DW	DIM

P_REM:		DB	#05
		DW	REM

P_NEW:		DB	#05			; BSROM for MB02+ - enhanced NEW command, added numeric parameter
		DW	CMDEXE

P_RUN:		DB	#03
		DW	RUN

P_LIST:		DB	#05
		DW	LIST

P_POKE:		DB	#06			; BSROM - enhanced POKE comand, added more items
		DB	#05
		DW	NEW_POKE

P_RANDOM:	DB	#03
		DW	RANDOMIZE

P_CONT:		DB	#03			; BSROM - enhanced CONTINUE command, added numeric parameter
		DW	NEW_CONT
	
P_CLEAR:	DB	#03
		DW	CLEAR

P_CLS:		DB	#03			; BSROM - enhanced CLS command, added numeric parameter
		DW	NEW_CLS

P_PLOT:		DB	#09
		DB	#00
		DW	PLOT

P_PAUSE:	DB	#03			; BSROM - enhanced PAUSE command, parameter is optional
		DW	PAUSE
		DB	#00

P_READ:		DB	#05
		DW	READ

P_DATA:		DB	#05
		DW	DATA

P_RESTORE:	DB	#03
		DW	RESTORE

P_DRAW:		DB	#09
		DB	#05
		DW	DRAW

P_COPY:		DB	#05			; BSROM for MB02+ - enhanced COPY command, added numeric parameter
		DW	CMDEXE

P_LPRINT:	DB	#05
		DW	LPRINT

P_LLIST:	DB	#05
		DW	LLIST

P_SAVE:		DB	#0B
P_LOAD:		DB	#0B
P_VERIFY:	DB	#0B
P_MERGE:	DB	#0B

P_BEEP:		DB	#08
		DB	#00
		DW	BEEP

P_CIRCLE:	DB	#09
		DB	#05
		DW	CIRCLE

P_INK:		DB	#07
P_PAPER:	DB	#07
P_FLASH:	DB	#07
P_BRIGHT:	DB	#07
P_INVERSE:	DB	#07
P_OVER:		DB	#07

P_OUT:		DB	#08
		DB	#00
		DW	OUT_CMD

P_BORDER:	DB	#03			; BSROM - enhanced BORDER command, parameter s optional
		DW	BORDER
		DB	#00
	
P_DEF_FN:	DB	#05
		DW	DEF_FN

P_OPEN:		DB	#06
		DB	","
		DB	#0A
		DB	#00
		DW	OPEN

P_CLOSE:	DB	#06
		DB	#00
		DW	CLOSE

P_FORMAT:	DB	#0A
		DB	#00
		DW	CAT_ETC

P_MOVE:		DB	#0A
		DB	","
		DB	#0A
		DB	#00
		DW	CAT_ETC

P_ERASE:	DB	#0A
		DB	#00
		DW	CAT_ETC

P_CAT:		DB	#05			; BSROM for MB02+ - enhanced CAT command, added numeric parameter
		DW	CMDEXE

; Main parser of BASIC interpreter
LINE_SCAN:	RES	7,(IY+#01)
		CALL	E_LINE_NO
		XOR	A
		LD	(#5C47),A
		DEC	A
		LD	(#5C3A),A
		JR	STMT_L_1

; Statement loop
STMT_LOOP:	RST	#20
STMT_L_1:	CALL	SET_WORK
		INC	(IY+#0D)
		JP	M,REPORT_C
		RST	#18
		LD	B,#00
		CP	#0D
		JR	Z,LINE_END
		CP	#3A
		JR	Z,STMT_LOOP
		LD	HL,STMT_RET
		PUSH	HL
		CP	#CE
		JP	C,NEWCMD		; BSROM for MB02+ - new BASIC commands
		SUB	#CE
		LD	C,A
		RST	#20
		LD	HL,OFFST_TBL
		ADD	HL,BC
		LD	C,(HL)
		ADD	HL,BC
		JR	GET_PARAM

; The main scanning loop
SCAN_LOOP:	LD	HL,(#5C74)
GET_PARAM:	LD	A,(HL)
		INC	HL
		LD	(#5C74),HL
		LD	BC,SCAN_LOOP
		PUSH	BC
		LD	C,A
		CP	#20
		JR	NC,SEPARATOR
		LD	HL,CLASS_TBL
		LD	B,#00
		ADD	HL,BC
		LD	C,(HL)
		ADD	HL,BC
		PUSH	HL
		RST	#18
		DEC	B
		RET

; Verify that the mandatory separator is present in correct location
SEPARATOR:	RST	#18
		CP	C
		JP	NZ,REPORT_C
		RST	#20
		RET

; Handle BREAK, return, and direct commands
STMT_RET:	CALL	BREAK_KEY
		JR	C,STMT_R_1
REPORT_L:	RST	#08			; Error report
		DB	#14			; BREAK into program
STMT_R_1:	BIT	7,(IY+#0A)
		JR	NZ,STMT_NEXT
		LD	HL,(#5C42)
		BIT	7,H
		JR	Z,LINE_NEW
LINE_RUN:	LD	HL,#FFFE
		LD	(#5C45),HL
		LD	HL,(#5C61)
		DEC	HL
		LD	DE,(#5C59)
		DEC	DE
		LD	A,(#5C44)
		JR	NEXT_LINE

; Find start address of a new line
LINE_NEW:	CALL	LINE_ADDR
		LD	A,(#5C44)
		JR	Z,LINE_USE
		AND	A
		JR	NZ,REPORT_N
		LD	B,A
		LD	A,(HL)
		AND	#C0
		LD	A,B
		JR	Z,LINE_USE
REPORT_0:	RST	#08			; Error report
		DB	#FF			; OK

; REM command
REM:		POP	BC

; End of line test
LINE_END:	CALL	SYNTAX_Z
		RET	Z
		LD	HL,(#5C55)
		LD	A,#C0
		AND	(HL)
		RET	NZ
		XOR	A
LINE_USE:	CP	#01			; General line checking
		ADC	A,#00
		LD	D,(HL)
		INC	HL
		LD	E,(HL)
		LD	(#5C45),DE
		INC	HL
		LD	E,(HL)
		INC	HL
		LD	D,(HL)
		EX	DE,HL
		ADD	HL,DE
		INC	HL
NEXT_LINE:	LD	(#5C55),HL
		EX	DE,HL
		LD	(#5C5D),HL
		LD	D,A
		LD	E,#00
		LD	(IY+#0A),#FF
		DEC	D
		LD	(IY+#0D),D
		JP	Z,STMT_LOOP
		INC	D
		CALL	EACH_STMT
		JR	Z,STMT_NEXT
REPORT_N:	RST	#08			; Error report
		DB	#16			; Statement lost

; End of statements
CHECK_END:	CALL	SYNTAX_Z
		RET	NZ
		POP	BC
		POP	BC
STMT_NEXT:	RST	#18			; Go to next statement
		CP	#0D
		JR	Z,LINE_END
		CP	#3A
		JP	Z,STMT_LOOP
		JP	REPORT_C

; Command class table
CLASS_TBL:	DB	#0F			; CLASS_00
		DB	#1D			; CLASS_01
		DB	#4B			; CLASS_02
		DB	#09			; CLASS_03
		DB	#67			; CLASS_04
		DB	#0B			; CLASS_05
		DB	#7B			; CLASS_06
		DB	#8E			; CLASS_07
		DB	#71			; CLASS_08
		DB	#B4			; CLASS_09
		DB	#81			; CLASS_0A
		DB	#CF			; CLASS_0B

; Command classes 00 - no operand, 03 - optional operand, 05 - variable syntax checked by routine
CLASS_03:	CALL	FETCH_NUM
CLASS_00:	CP	A
CLASS_05:	POP	BC
		CALL	Z,CHECK_END
		EX	DE,HL
		LD	HL,(#5C74)
		LD	C,(HL)
		INC	HL
		LD	B,(HL)
		EX	DE,HL
		PUSH	BC
		RET

; Command classes
; 01 - variable is required 
; 02 - expression is required
; 04 - single character variable is required 
CLASS_01:	CALL	LOOK_VARS
VAR_A_1:	LD	(IY+#37),#00
		JR	NC,VAR_A_2
		SET	1,(IY+#37)
		JR	NZ,VAR_A_3
REPORT_2:	RST	#08			; Error report
		DB	#01			; Variable not found;
VAR_A_2:	CALL	Z,STK_VAR
		BIT	6,(IY+#01)
		JR	NZ,VAR_A_3
		XOR	A
		CALL	SYNTAX_Z
		CALL	NZ,STK_FETCH
		LD	HL,#5C71
		OR	(HL)
		LD	(HL),A
		EX	DE,HL
VAR_A_3:	LD	(#5C72),BC
		LD	(#5C4D),HL
		RET

CLASS_02:	POP	BC
		CALL	VAL_FET_1
		CALL	CHECK_END
		RET

; Fetch a value
VAL_FET_1:	LD	A,(#5C3B)
VAL_FET_2:	PUSH	AF
		CALL	SCANNING
		POP	AF
		LD	D,(IY+#01)
		XOR	D
		AND	#40
		JR	NZ,REPORT_C
		BIT	7,D
		JP	NZ,LET
		RET

CLASS_04:	CALL	LOOK_VARS
		PUSH	AF
		LD	A,C
		OR	#9F
		INC	A
		JR	NZ,REPORT_C
		POP	AF
		JR	VAR_A_1

; Command classes
; 06 - numeric expression is expected
; 08 - two numeric expressions separated by comma are expected
; 0A - string expression is expected
NEXT_2NUM:	RST	#20
EXPT_2NUM:	CALL	EXPT_1NUM		; CLASS_08
		CP	#2C
		JR	NZ,REPORT_C
		RST	#20
EXPT_1NUM:	CALL	SCANNING		; CLASS_06
		BIT	6,(IY+#01)
		RET	NZ
REPORT_C:	RST	#08			; Error report
		DB	#0B			; Nonsense in BASIC
EXPT_EXP:	CALL	SCANNING		; CLASS_0A
		BIT	6,(IY+#01)
		RET	Z
		JR	REPORT_C

; Command class 07 - set permanent colors
CLASS_07:	BIT	7,(IY+#01)
		RES	0,(IY+#02)
		CALL	NZ,TEMPS
		POP	AF
		LD	A,(#5C74)
		SUB	#13
		CALL	CO_TEMP_4
		CALL	CHECK_END
		LD	HL,(#5C8F)
		LD	(#5C8D),HL
		LD	HL,#5C91
		LD	A,(HL)
		RLCA
		XOR	(HL)
		AND	#AA
		XOR	(HL)
		LD	(HL),A
		RET

; Command class 09 - two coordinates, could be preceded by embedded color commands
CLASS_09:	CALL	SYNTAX_Z
		JR	Z,CL_09_1
		RES	0,(IY+#02)
		CALL	TEMPS
		LD	HL,#5C90
		LD	A,(HL)
		OR	#F8
		LD	(HL),A
		RES	6,(IY+#57)
		RST	#18
CL_09_1:	CALL	CO_TEMP_2
		JR	EXPT_2NUM

; Command class 09 - four commands handling
		JP	CMDMGF			; BSROM for MB02+ - modified tape commands

; Fetch a number
FETCH_NUM:	CP	#0D
		JR	Z,USE_ZERO
		CP	#3A
		JR	NZ,EXPT_1NUM		
USE_ZERO:	CALL	SYNTAX_Z		; Place 0 on the calculator stack
		RET	Z
		RST	#28			;FP_CALC
		DB	#A0			;STK_ZERO
		DB	#38			;END_CALC
		RET

; Handle STOP command
STOP:		RST	#08			; Error report
		DB	#08			; STOP statement

; Handle IF command
IF_CMD:		POP	BC
		CALL	SYNTAX_Z
		JR	Z,IF_1
		RST	#28			;FP_CALC
		DB	#02			;DELETE
		DB	#38			;END_CALC
		EX	DE,HL
		CALL	TEST_ZERO
		JP	C,LINE_END
IF_1:		JP	STMT_L_1

; Handle FOR command
FOR:		CP	#CD
		JR	NZ,F_USE_1
		RST	#20
		CALL	EXPT_1NUM
		CALL	CHECK_END
		JR	F_REORDER

F_USE_1:	CALL	CHECK_END
		RST	#28			;FP_CALC
		DB	#A1			;STK_ONE
		DB	#38			;END_CALC
F_REORDER:	RST	#28			;FP_CALC
		DB	#C0			;ST_MEM_0
		DB	#02			;DELETE
		DB	#01			;EXCHANGE
		DB	#E0			;GET_MEM_0
		DB	#01			;EXCHANGE
		DB	#38			;END_CALC
		CALL	LET
		LD	(#5C68),HL
		DEC	HL
		LD	A,(HL)
		SET	7,(HL)
		LD	BC,#0006
		ADD	HL,BC
		RLCA
		JR	C,F_L_S
		LD	C,#0D
		CALL	MAKE_ROOM
		INC	HL
F_L_S:		PUSH	HL
		RST	#28			;FP_CALC
		DB	#02			;DELETE
		DB	#02			;DELETE
		DB	#38			;END_CALC
		POP	HL
		EX	DE,HL
		LD	C,#0A
		LDIR
		LD	HL,(#5C45)
		EX	DE,HL
		LD	(HL),E
		INC	HL
		LD	(HL),D
		LD	D,(IY+#0D)
		INC	D
		INC	HL
		LD	(HL),D
		CALL	NEXT_LOOP
		RET	NC
		LD	B,(IY+#38)
		LD	HL,(#5C45)
		LD	(#5C42),HL
		LD	A,(#5C47)
		NEG
		LD	D,A
		LD	HL,(#5C5D)
		LD	E,#F3
F_LOOP:		PUSH	BC
		LD	BC,(#5C55)
		CALL	LOOK_PROG
		LD	(#5C55),BC
		POP	BC
		JR	C,REPORT_I
		RST	#20
		OR	#20
		CP	B
		JR	Z,F_FOUND
		RST	#20
		JR	F_LOOP

F_FOUND:	RST	#20
		LD	A,#01
		SUB	D
		LD	(#5C44),A
		RET

REPORT_I:	RST	#08			; Error report
		DB	#11			; FOR without NEXT

; Search the program area for DATA, DEF FN or NEXT keywords
LOOK_PROG:	LD	A,(HL)
		CP	#3A
		JR	Z,LOOK_P_2
LOOK_P_1:	INC	HL
		LD	A,(HL)
		AND	#C0
		SCF
		RET	NZ
		LD	B,(HL)
		INC	HL
		LD	C,(HL)
		LD	(#5C42),BC
		INC	HL
		LD	C,(HL)
		INC	HL
		LD	B,(HL)
		PUSH	HL
		ADD	HL,BC
		LD	B,H
		LD	C,L
		POP	HL
		LD	D,#00
LOOK_P_2:	PUSH	BC
		CALL	EACH_STMT
		POP	BC
		RET	NC
		JR	LOOK_P_1

; Handle NEXT command
NEXT:		BIT	1,(IY+#37)
		JP	NZ,REPORT_2
		LD	HL,(#5C4D)
		BIT	7,(HL)
		JR	Z,REPORT_1
		INC	HL
		LD	(#5C68),HL
		RST	#28			;FP_CALC
		DB	#E0			;GET_MEM_0
		DB	#E2			;GET_MEM_2
		DB	#0F			;ADDITION
		DB	#C0			;ST_MEM_0
		DB	#02			;DELETE
		DB	#38			;END_CALC
		CALL	NEXT_LOOP
		RET	C
		LD	HL,(#5C68)
		LD	DE,#000F
		ADD	HL,DE
		LD	E,(HL)
		INC	HL
		LD	D,(HL)
		INC	HL
		LD	H,(HL)
		EX	DE,HL
		JP	GO_TO_2

REPORT_1:	RST	#08			; Error report
		DB	#00			; NEXT withou FOR

; Test iterations for FOR command
NEXT_LOOP:	RST	#28			;FP_CALC
		DB	#E1			;GET_MEM_1
		DB	#E0			;GET_MEM_0
		DB	#E2			;GET_MEM_2
		DB	#36			;LESS_0
		DB	#00			;JUMP_TRUE
		DB	#02			;NEXT_1 if step negative
		DB	#01			;EXCHANGE
NEXT_1:		DB	#03			;SUBTRACT
		DB	#37			;GREATER_0
		DB	#00			;JUMP_TRUE
		DB	#04			;NEXT_2 if finished
		DB	#38			;END_CALC
		AND	A
		RET
	
NEXT_2:		DB	#38			;END_CALC
		SCF
		RET

; Handle READ command
READ_3:		RST	#20
READ:		CALL	CLASS_01
		CALL	SYNTAX_Z
		JR	Z,READ_2
		RST	#18
		LD	(#5C5F),HL
		LD	HL,(#5C57)
		LD	A,(HL)
		CP	#2C
		JR	Z,READ_1
		LD	E,#E4
		CALL	LOOK_PROG
		JR	NC,READ_1
REPORT_E:	RST	#08			; Error report
		DB	#0D			; Out of data
READ_1:		CALL	TEMP_PTR1
		CALL	VAL_FET_1
		RST	#18
		LD	(#5C57),HL
		LD	HL,(#5C5F)
		LD	(IY+#26),#00
		CALL	TEMP_PTR2
READ_2:		RST	#18
		CP	#2C
		JR	Z,READ_3
		CALL	CHECK_END
		RET

; Handle DATA command
DATA:		CALL	SYNTAX_Z
		JR	NZ,DATA_2
DATA_1:		CALL	SCANNING
		CP	#2C
		CALL	NZ,CHECK_END
		RST	#20
		JR	DATA_1

DATA_2:		LD	A,#E4
PASS_BY:	LD	B,A
		CPDR
		LD	DE,#0200
		JP	EACH_STMT

; Handle RESTORE command
RESTORE:	CALL	FIND_INT2
REST_RUN:	LD	H,B
		LD	L,C
		CALL	LINE_ADDR
		DEC	HL
		LD	(#5C57),HL
		RET

; Handle RANDOMIZE command
RANDOMIZE:	CALL	FIND_INT2
		LD	A,B
		OR	C
		JR	NZ,RAND_1
		LD	BC,(#5C78)
RAND_1:		LD	(#5C76),BC
		RET

; Handle CONTINUE command
CONTINUE:	LD	HL,(#5C6E)
		LD	D,(IY+#36)
		JR	GO_TO_2

; Handle GOTO command
GO_TO:		CALL	FIND_INT2
		LD	H,B
		LD	L,C
		LD	D,#00
		LD	A,H
		CP	#F0
		JR	NC,REPORT_BB
GO_TO_2:	LD	(#5C42),HL
		LD	(IY+#0A),D
		RET

; Handle OUT command
OUT_CMD:	CALL	TWO_PARAM
		OUT	(C),A
		RET

; BSROM - fix for rewriting first bytes of ROM
; was POKE command handling here originally
NO_RW_AT0:	LD	DE,(#5C65)
		RET

; BSROM - extended command parameters
TWO_PARAM:	CALL	FP_TO_A
		PUSH	AF
		CALL	FIND_INT2
		POP	AF
ROZPAR:		JR	C,REPORT_BB
		JR	Z,ROZPAR_1
		NEG
ROZPAR_1:	RET

; Find integers
FIND_INT1:	CALL	FP_TO_A
		JR	ROZPAR

FIND_INT2:	CALL	FP_TO_BC
		JR	C,REPORT_BB
		RET	Z

REPORT_BB:	RST	#08			; Error report
		DB	#0A			; Integer out of range

; Handle RUN command
RUN:		CALL	GO_TO
		LD	BC,#0000
		CALL	REST_RUN
		JR	CLEAR_RUN

; Handle CLEAR command
CLEAR:		CALL	FIND_INT2
CLEAR_RUN:	LD	A,B
		OR	C
		JR	NZ,CLEAR_1
		LD	BC,(#5CB2)
CLEAR_1:	PUSH	BC
		LD	DE,(#5C4B)
		LD	HL,(#5C59)
		DEC	HL
		CALL	RECLAIM_1
		CALL	CLS
		LD	HL,(#5C65)
		LD	DE,#0032
		ADD	HL,DE
		POP	DE
		SBC	HL,DE
		JR	NC,REPORT_M
		LD	HL,(#5CB4)
		AND	A
		SBC	HL,DE
		JR	NC,CLEAR_2
REPORT_M:	RST	#08			; Error report
		DB	#15			; RAMTOP no good
CLEAR_2:	EX	DE,HL
		LD	(#5CB2),HL
		POP	DE
		POP	BC
		LD	(HL),#3E
		DEC	HL
		LD	SP,HL
		PUSH	BC
		LD	(#5C3D),SP
		EX	DE,HL
		JP	(HL)

; Handle GO SUB command
GO_SUB:		POP	DE
		LD	H,(IY+#0D)
		INC	H
		EX	(SP),HL
		INC	SP
		LD	BC,(#5C45)
		PUSH	BC
		PUSH	HL
		LD	(#5C3D),SP
		PUSH	DE
		CALL	GO_TO
		LD	BC,#0014
TEST_ROOM:	LD	HL,(#5C65)		; Check available memory
		ADD	HL,BC
		JR	C,REPORT_4
		EX	DE,HL
		LD	HL,#0050
		ADD	HL,DE
		JR	C,REPORT_4
		SBC	HL,SP
		RET	C
REPORT_4:	LD	L,#03
		JP	ERROR_3

; Get free memory. Not used in ROM, but can be used by user
FREE_MEM:	LD	BC,#0000
		CALL	TEST_ROOM
		LD	B,H
		LD	C,L
		RET

; Handle RETURN command
RETURN:		POP	BC
		POP	HL
		POP	DE
		LD	A,D
		CP	#3E
		JR	Z,REPORT_7
		DEC	SP
		EX	(SP),HL
		EX	DE,HL
		LD	(#5C3D),SP
		PUSH	BC
		JP	GO_TO_2
REPORT_7:	PUSH	DE
		PUSH	HL
		RST	#08			; Error report
		DB	#06			; RETURN without GOSUB

; Handle PAUSE command
PAUSE:		CALL	FIND_INT2
PAUSE_1:	HALT
		DEC	BC
		LD	A,B
		OR	C
		JR	Z,PAUSE_END
		LD	A,B
		AND	C
		INC	A
		JR	NZ,PAUSE_2
		INC	BC
PAUSE_2:	BIT	5,(IY+#01)
		JR	Z,PAUSE_1
PAUSE_END:	RES	5,(IY+#01)
		RET

; Check for BREAK key
BREAK_KEY:	LD	A,#7F
		IN	A,(#FE)
		RRA
		RET	C
		LD	A,#FE
		IN	A,(#FE)
		RRA
		RET

; Handle DEF FN command
DEF_FN:		CALL	SYNTAX_Z
		JR	Z,DEF_FN_1
		LD	A,#CE
		JP	PASS_BY

DEF_FN_1:	SET	6,(IY+#01)
		CALL	ALPHA
		JR	NC,DEF_FN_4
		RST	#20
		CP	#24
		JR	NZ,DEF_FN_2
		RES	6,(IY+#01)
		RST	#20
DEF_FN_2:	CP	#28
		JR	NZ,DEF_FN_7
		RST	#20
		CP	#29
		JR	Z,DEF_FN_6
DEF_FN_3:	CALL	ALPHA
DEF_FN_4:	JP	NC,REPORT_C
		EX	DE,HL
		RST	#20
		CP	#24
		JR	NZ,DEF_FN_5
		EX	DE,HL
		RST	#20
DEF_FN_5:	EX	DE,HL
		LD	BC,#0006
		CALL	MAKE_ROOM
		INC	HL
		INC	HL
		LD	(HL),#0E
		CP	#2C
		JR	NZ,DEF_FN_6
		RST	#20
		JR	DEF_FN_3

DEF_FN_6:	CP	#29
		JR	NZ,DEF_FN_7
		RST	#20
		CP	#3D
		JR	NZ,DEF_FN_7
		RST	#20
		LD	A,(#5C3B)
		PUSH	AF
		CALL	SCANNING
		POP	AF
		XOR	(IY+#01)
		AND	#40
DEF_FN_7:	JP	NZ,REPORT_C
		CALL	CHECK_END
UNSTACK_Z:	CALL	SYNTAX_Z
		POP	HL
		RET	Z
		JP	(HL)

; Handle LPRINT command
LPRINT:		LD	A,#03
		JR	PRINT_1

; Handle PRINT command
PRINT:		LD	A,#02
PRINT_1:	CALL	SYNTAX_Z
		CALL	NZ,CHAN_OPEN
		CALL	TEMPS
		CALL	PRINT_2
		CALL	CHECK_END
		RET

PRINT_2:	RST	#18
		CALL	PR_END_Z
		JR	Z,PRINT_4
PRINT_3:	CALL	PR_POSN_1
		JR	Z,PRINT_3
		CALL	PR_ITEM_1
		CALL	PR_POSN_1
		JR	Z,PRINT_3
PRINT_4:	CP	#29
		RET	Z
PRINT_CR:	CALL	UNSTACK_Z
PRINT_5:	LD	A,#0D
		RST	#10
		RET

; Print items
PR_ITEM_1:	RST	#18
		CP	#AC
		JR	NZ,PR_ITEM_2
		CALL	NEXT_2NUM
		CALL	UNSTACK_Z
		CALL	STK_TO_BC
		LD	A,#16
		JR	PR_AT_TAB

PR_ITEM_2:	CP	#AD
		JR	NZ,PR_ITEM_3
		RST	#20
		CALL	EXPT_1NUM
		CALL	UNSTACK_Z
		CALL	FIND_INT2
		LD	A,#17
PR_AT_TAB:	RST	#10
		LD	A,C
		RST	#10
		LD	A,B
		RST	#10
		RET

PR_ITEM_3:	CALL	CO_TEMP_3
		RET	NC
		CALL	STR_ALTER
		RET	NC
		CALL	SCANNING
		CALL	UNSTACK_Z
		BIT	6,(IY+#01)
		CALL	Z,STK_FETCH
		JP	NZ,PRINT_FP
PR_STRING:	LD	A,B
		OR	C
		DEC	BC
		RET	Z
		LD	A,(DE)
		INC	DE
		RST	#10
		JR	PR_STRING

; End of printing
PR_END_Z:	CP	#29			; ')'
		RET	Z
PR_ST_END:	CP	#0D			; carriage return
		RET	Z
		CP	#3A			; ':'
		RET

; Consider print position by ';' or ',' or '''
PR_POSN_1:	RST	#18
		CP	#3B
		JR	Z,PR_POSN_3
		CP	#2C
		JR	NZ,PR_POSN_2
		CALL	SYNTAX_Z
		JR	Z,PR_POSN_3
		LD	A,#06
		RST	#10
		JR	PR_POSN_3

PR_POSN_2:	CP	#27
		RET	NZ
		CALL	PRINT_CR
PR_POSN_3:	RST	#20
		CALL	PR_END_Z
		JR	NZ,PR_POSN_4
		POP	BC
PR_POSN_4:	CP	A
		RET

; Alter stream
STR_ALTER:	CP	#23
		SCF
		RET	NZ
		RST	#20
		CALL	EXPT_1NUM
		AND	A
		CALL	UNSTACK_Z
		CALL	FIND_INT1
		CP	#10
		JP	NC,REPORT_OA
		CALL	CHAN_OPEN
		AND	A
		RET

; Handle INPUT command
INPUT:		CALL	SYNTAX_Z
		JR	Z,INPUT_1
		LD	A,#01
		CALL	CHAN_OPEN
		CALL	CLS_LOWER
INPUT_1:	LD	(IY+#02),#01
		CALL	IN_ITEM_1
		CALL	CHECK_END
		LD	BC,(#5C88)
		LD	A,(#5C6B)
		CP	B
		JR	C,INPUT_2
		LD	C,#21
		LD	B,A
INPUT_2:	LD	(#5C88),BC
		LD	A,#19
		SUB	B
		LD	(#5C8C),A
		RES	0,(IY+#02)
		CALL	CL_SET
		JP	CLS_LOWER

; Handle input items from the current input channel
IN_ITEM_1:	CALL	PR_POSN_1
		JR	Z,IN_ITEM_1
		CP	#28
		JR	NZ,IN_ITEM_2
		RST	#20
		CALL	PRINT_2
		RST	#18
		CP	#29
		JP	NZ,REPORT_C
		RST	#20
		JP	IN_NEXT_2

IN_ITEM_2:	CP	#CA
		JR	NZ,IN_ITEM_3
		RST	#20
		CALL	CLASS_01
		SET	7,(IY+#37)
		BIT	6,(IY+#01)
		JP	NZ,REPORT_C
		JR	IN_PROMPT

IN_ITEM_3:	CALL	ALPHA
		JP	NC,IN_NEXT_1
		CALL	CLASS_01
		RES	7,(IY+#37)
IN_PROMPT:	CALL	SYNTAX_Z
		JP	Z,IN_NEXT_2
		CALL	SET_WORK
		LD	HL,#5C71
		RES	6,(HL)
		SET	5,(HL)
		LD	BC,#0001
		BIT	7,(HL)
		JR	NZ,IN_PR_2
		LD	A,(#5C3B)
		AND	#40
		JR	NZ,IN_PR_1
		LD	C,#03
IN_PR_1:	OR	(HL)
		LD	(HL),A
IN_PR_2:	RST	#30
		LD	(HL),#0D
		LD	A,C
		RRCA
		RRCA
		JR	NC,IN_PR_3
		LD	A,#22
		LD	(DE),A
		DEC	HL
		LD	(HL),A
IN_PR_3:	LD	(#5C5B),HL
		BIT	7,(IY+#37)
		JR	NZ,IN_VAR_3
		LD	HL,(#5C5D)
		PUSH	HL
		LD	HL,(#5C3D)
		PUSH	HL
IN_VAR_1:	LD	HL,IN_VAR_1
		PUSH	HL
		BIT	4,(IY+#30)
		JR	Z,IN_VAR_2
		LD	(#5C3D),SP
IN_VAR_2:	LD	HL,(#5C61)
		CALL	REMOVE_FP
		LD	(IY+#00),#FF
		CALL	EDITOR
		RES	7,(IY+#01)
		CALL	IN_ASSIGN
		JR	IN_VAR_4

IN_VAR_3:	CALL	EDITOR
IN_VAR_4:	LD	(IY+#22),#00
		CALL	IN_CHAN_K
		JR	NZ,IN_VAR_5
		CALL	ED_COPY
		LD	BC,(#5C82)
		CALL	CL_SET
IN_VAR_5:	LD	HL,#5C71
		RES	5,(HL)
		BIT	7,(HL)
		RES	7,(HL)
		JR	NZ,IN_VAR_6
		POP	HL
		POP	HL
		LD	(#5C3D),HL
		POP	HL
		LD	(#5C5F),HL
		SET	7,(IY+#01)
		CALL	IN_ASSIGN
		LD	HL,(#5C5F)
		LD	(IY+#26),#00
		LD	(#5C5D),HL
		JR	IN_NEXT_2

IN_VAR_6:	LD	HL,(#5C63)
		LD	DE,(#5C61)
		SCF
		SBC	HL,DE
		LD	B,H
		LD	C,L
		CALL	STK_STO_D
		CALL	LET
		JR	IN_NEXT_2

IN_NEXT_1:	CALL	PR_ITEM_1
IN_NEXT_2:	CALL	PR_POSN_1
		JP	Z,IN_ITEM_1
		RET

; INPUT sytax check and assignment
IN_ASSIGN:	LD	HL,(#5C61)
		LD	(#5C5D),HL
		RST	#18
		CP	#E2			; STOP
		JR	Z,IN_STOP
		LD	A,(#5C71)
		CALL	VAL_FET_2
		RST	#18
		CP	#0D			; carriage return
		RET	Z
REPORT_CB:	RST	#08			; Error report
		DB	#0B			; Nonsense in BASIC
IN_STOP:	CALL	SYNTAX_Z
		RET	Z
REPORT_H:	RST	#08			; Error report
		DB	#10			; STOP in INPUT
IN_CHAN_K:	LD	HL,(#5C51)		; Test for K channel
		INC	HL
		INC	HL
		INC	HL
		INC	HL
		LD	A,(HL)
		CP	#4B
		RET

; Color item routines
CO_TEMP_1:	RST	#20
CO_TEMP_2:	CALL	CO_TEMP_3
		RET	C
		RST	#18
		CP	#2C
		JR	Z,CO_TEMP_1
		CP	#3B
		JR	Z,CO_TEMP_1
		JP	REPORT_C

CO_TEMP_3:	CP	#D9
		RET	C
		CP	#DF
		CCF
		RET	C
		PUSH	AF
		RST	#20
		POP	AF
CO_TEMP_4:	SUB	#C9
		PUSH	AF
		CALL	EXPT_1NUM
		POP	AF
		AND	A
		CALL	UNSTACK_Z
		PUSH	AF
		CALL	FIND_INT1
		LD	D,A
		POP	AF
		RST	#10
		LD	A,D
		RST	#10
		RET

; The color system variable handler
CO_TEMP_5:	SUB	#11
		ADC	A,#00
		JR	Z,CO_TEMP_7
		SUB	#02
		ADC	A,#00
		JR	Z,CO_TEMP_C
		CP	#01
		LD	A,D
		LD	B,#01
		JR	NZ,CO_TEMP_6
		RLCA
		RLCA
		LD	B,#04
CO_TEMP_6:	LD	C,A
		LD	A,D
		CP	#02
		JR	NC,REPORT_K
		LD	A,C
		LD	HL,#5C91
		JR	CO_CHANGE
CO_TEMP_7:	LD	A,D
		LD	B,#07
		JR	C,CO_TEMP_8
		RLCA
		RLCA
		RLCA
		LD	B,#38
CO_TEMP_8:	LD	C,A
		LD	A,D
		CP	#0A
		JR	C,CO_TEMP_9
REPORT_K:	RST	#08			; Error report
		DB	#13			; Invalid colour
CO_TEMP_9:	LD	HL,#5C8F
		CP	#08
		JR	C,CO_TEMP_B
		LD	A,(HL)
		JR	Z,CO_TEMP_A
		OR	B
		CPL
		AND	#24
		JR	Z,CO_TEMP_A
		LD	A,B
CO_TEMP_A:	LD	C,A
CO_TEMP_B:	LD	A,C
		CALL	CO_CHANGE
		LD	A,#07
		CP	D
		SBC	A,A
		CALL	CO_CHANGE
		RLCA
		RLCA
		AND	#50
		LD	B,A
		LD	A,#08
		CP	D
		SBC	A,A

; Handle change of color
CO_CHANGE:	XOR	(HL)
		AND	B
		XOR	(HL)
		LD	(HL),A
		INC	HL
		LD	A,B
		RET

CO_TEMP_C:	SBC	A,A
		LD	A,D
		RRCA
		LD	B,#80
		JR	NZ,CO_TEMP_D
		RRCA
		LD	B,#40
CO_TEMP_D:	LD	C,A
		LD	A,D
		CP	#08
		JR	Z,CO_TEMP_E
		CP	#02
		JR	NC,REPORT_K
CO_TEMP_E:	LD	A,C
		LD	HL,#5C8F
		CALL	CO_CHANGE
		LD	A,C
		RRCA
		RRCA
		RRCA
		JR	CO_CHANGE

; Handle BORDER command
BORDER:		CALL	FIND_INT1
		CP	#08
		JR	NC,REPORT_K
		OUT	(#FE),A
		RLCA
		RLCA
		RLCA
		BIT	5,A
		JR	NZ,BORDER_1
		XOR	#07
BORDER_1:	LD	(#5C48),A
		RET

; Get pixel address
PIXEL_ADD:	LD	A,#AF
		SUB	B
		JP	C,REPORT_BC
		LD	B,A
		AND	A
		RRA
		SCF
		RRA
		AND	A
		RRA
		XOR	B
		AND	#F8
		XOR	B
		LD	H,A
		LD	A,C
		RLCA
		RLCA
		RLCA
		XOR	B
		AND	#C7
		XOR	B
		RLCA
		RLCA
		LD	L,A
		LD	A,C
		AND	#07
		RET

; Point subroutine
POINT_SUB:	CALL	STK_TO_BC
		CALL	PIXEL_ADD
		LD	B,A
		INC	B
		LD	A,(HL)
POINT_LP:	RLCA
		DJNZ	POINT_LP
		AND	#01
		JP	STACK_A

; Handle PLOT command
PLOT:		CALL	STK_TO_BC
		CALL	PLOT_SUB
		JP	TEMPS

PLOT_SUB:	LD	(#5C7D),BC
		CALL	PIXEL_ADD
		LD	B,A
		INC	B
		LD	A,#FE
PLOT_LOOP:	RRCA
		DJNZ	PLOT_LOOP
		LD	B,A
		LD	A,(HL)
		LD	C,(IY+#57)
		BIT	0,C
		JR	NZ,PL_TST_IN
		AND	B
PL_TST_IN:	BIT	2,C
		JR	NZ,PLOT_END
		XOR	B
		CPL
PLOT_END:	LD	(HL),A
		JP	PO_ATTR

; Put two numbers in BC register
STK_TO_BC:	CALL	STK_TO_A
		LD	B,A
		PUSH	BC
		CALL	STK_TO_A
		LD	E,C
		POP	BC
		LD	D,C
		LD	C,A
		RET

; Put the last value on the calc stack into the accumulator
STK_TO_A:	CALL	FP_TO_A
		JP	C,REPORT_BC
		LD	C,#01
		RET	Z
		LD	C,#FF
		RET

; Handle CIRCLE command
CIRCLE:		RST	#18
		CP	#2C
		JP	NZ,REPORT_C
		RST	#20
		CALL	EXPT_1NUM
		CALL	CHECK_END
		RST	#28			;FP_CALC
		DB	#2A			;ABS
		DB	#3D			;RE_STACK
		DB	#38			;END_CALC
		LD	A,(HL)
		CP	#81
		JR	NC,C_R_GRE_1
		RST	#28			;FP_CALC
		DB	#02			;DELETE
		DB	#38			;END_CALC
		JR	PLOT

C_R_GRE_1:	RST	#28			;FP_CALC
		DB	#A3			;STK_PI_2
		DB	#38			;END_CALC
		LD	(HL),#83
		RST	#28			;FP_CALC
		DB	#C5			;ST_MEM_5
		DB	#02			;DELETE
		DB	#38			;END_CALC
		CALL	CD_PRMS1
		PUSH	BC
		RST	#28			;FP_CALC
		DB	#31			;DUPLICATE
		DB	#E1			;GET_MEM_1
		DB	#04			;MULTIPLY
		DB	#38			;END_CALC
		LD	A,(HL)
		CP	#80
		JR	NC,C_ARC_GE1
		RST	#28			;FP_CALC
		DB	#02			;DELETE
		DB	#02			;DELETE
		DB	#38			;END_CALC
		POP	BC
		JP	PLOT

C_ARC_GE1:	RST	#28			;FP_CALC
		DB	#C2			;ST_MEM_2
		DB	#01			;EXCHANGE
		DB	#C0			;ST_MEM_0
		DB	#02			;DELETE
		DB	#03			;SUBTRACT
		DB	#01			;EXCHANGE
		DB	#E0			;GET_MEM_0
		DB	#0F			;ADDITION
		DB	#C0			;ST_MEM_0
		DB	#01			;EXCHANGE
		DB	#31			;DUPLICATE
		DB	#E0			;GET_MEM_0
		DB	#01			;EXCHANGE
		DB	#31			;DUPLICATE
		DB	#E0			;GET_MEM_0
		DB	#A0			;STK_ZERO
		DB	#C1			;ST_MEM_1
		DB	#02			;DELETE
		DB	#38			;END_CALC
		INC	(IY+#62)
		CALL	FIND_INT1
		LD	L,A
		PUSH	HL
		CALL	FIND_INT1
		POP	HL
		LD	H,A
		LD	(#5C7D),HL
		POP	BC
		JP	DRW_STEPS

; Handle DRAW command
DRAW:		RST	#18
		CP	#2C
		JR	Z,DR_3_PRMS
		CALL	CHECK_END
		JP	LINE_DRAW

DR_3_PRMS:	RST	#20
		CALL	EXPT_1NUM
		CALL	CHECK_END
		RST	#28			;FP_CALC
		DB	#C5			;ST_MEM_5
		DB	#A2			;STK_HALF
		DB	#04			;MULTIPLY
		DB	#1F			;SIN
		DB	#31			;DUPLICATE
		DB	#30			;NOT
		DB	#30			;NOT
		DB	#00			;JUMP_TRUE
		DB	#06			;to DR_SIN_NZ
		DB	#02			;DELETE
		DB	#38			;END_CALC
		JP	LINE_DRAW

DR_SIN_NZ:	DB	#C0			;ST_MEM_0
		DB	#02			;DELETE
		DB	#C1			;ST_MEM_1
		DB	#02			;DELETE
		DB	#31			;DUPLICATE
		DB	#2A			;ABS
		DB	#E1			;GET_MEM_1
		DB	#01			;EXCHANGE
		DB	#E1			;GET_MEM_1
		DB	#2A			;ABS
		DB	#0F			;ADDITION
		DB	#E0			;GET_MEM_0
		DB	#05			;DIVISION
		DB	#2A			;ABS
		DB	#E0			;GET_MEM_0
		DB	#01			;EXCHANGE
		DB	#3D			;RE_STACK
		DB	#38			;END_CALC
		LD	A,(HL)
		CP	#81
		JR	NC,DR_PRMS
		RST	#28			;FP_CALC
		DB	#02			;DELETE
		DB	#02			;DELETE
		DB	#38			;END_CALC
		JP	LINE_DRAW

DR_PRMS:	CALL	CD_PRMS1
		PUSH	BC
		RST	#28			;FP_CALC
		DB	#02			;DELETE
		DB	#E1			;GET_MEM_1
		DB	#01			;EXCHANGE
		DB	#05			;DIVISION
		DB	#C1			;ST_MEM_1
		DB	#02			;DELETE
		DB	#01			;EXCHANGE
		DB	#31			;DUPLICATE
		DB	#E1			;GET_MEM_1
		DB	#04			;MULTIPLY
		DB	#C2			;ST_MEM_2
		DB	#02			;DELETE
		DB	#01			;EXCHANGE
		DB	#31			;DUPLICATE
		DB	#E1			;GET_MEM_1
		DB	#04			;MULTIPLY
		DB	#E2			;GET_MEM_2
		DB	#E5			;GET_MEM_5
		DB	#E0			;GET_MEM_0
		DB	#03			;SUBTRACT
		DB	#A2			;STK_HALF
		DB	#04			;MULTIPLY
		DB	#31			;DUPLICATE
		DB	#1F			;SIN
		DB	#C5			;ST_MEM_5
		DB	#02			;DELETE
		DB	#20			;COS
		DB	#C0			;ST_MEM_0
		DB	#02			;DELETE
		DB	#C2			;ST_MEM_2
		DB	#02			;DELETE
		DB	#C1			;ST_MEM_1
		DB	#E5			;GET_MEM_5
		DB	#04			;MULTIPLY
		DB	#E0			;GET_MEM_0
		DB	#E2			;GET_MEM_2
		DB	#04			;MULTIPLY
		DB	#0F			;ADDITION
		DB	#E1			;GET_MEM_1
		DB	#01			;EXCHANGE
		DB	#C1			;ST_MEM_1
		DB	#02			;DELETE
		DB	#E0			;GET_MEM_0
		DB	#04			;MULTIPLY
		DB	#E2			;GET_MEM_2
		DB	#E5			;GET_MEM_5
		DB	#04			;MULTIPLY
		DB	#03			;SUBTRACT
		DB	#C2			;ST_MEM_2
		DB	#2A			;ABS
		DB	#E1			;GET_MEM_1
		DB	#2A			;ABS
		DB	#0F			;ADDITION
		DB	#02			;DELETE
		DB	#38			;END_CALC
		LD	A,(DE)
		CP	#81
		POP	BC
		JP	C,LINE_DRAW
		PUSH	BC
		RST	#28			;FP_CALC
		DB	#01			;EXCHANGE
		DB	#38			;END_CALC
		LD	A,(#5C7D)
		CALL	STACK_A
		RST	#28			;FP_CALC
		DB	#C0			;ST_MEM_0
		DB	#0F			;ADDITION
		DB	#01			;EXCHANGE
		DB	#38			;END_CALC
		LD	A,(#5C7E)
		CALL	STACK_A
		RST	#28			;FP_CALC
		DB	#C5			;ST_MEM_5
		DB	#0F			;ADDITION
		DB	#E0			;GET_MEM_0
		DB	#E5			;GET_MEM_5
		DB	#38			;END_CALC
		POP	BC
DRW_STEPS:	DEC	B
		JR	Z,ARC_END
		JR	ARC_START

ARC_LOOP:	RST	#28			;FP_CALC
		DB	#E1			;GET_MEM_1
		DB	#31			;DUPLICATE
		DB	#E3			;GET_MEM_3
		DB	#04			;MULTIPLY
		DB	#E2			;GET_MEM_2
		DB	#E4			;GET_MEM_4
		DB	#04			;MULTIPLY
		DB	#03			;SUBTRACT
		DB	#C1			;ST_MEM_1
		DB	#02			;DELETE
		DB	#E4			;GET_MEM_4
		DB	#04			;MULTIPLY
		DB	#E2			;GET_MEM_2
		DB	#E3			;GET_MEM_3
		DB	#04			;MULTIPLY
		DB	#0F			;ADDITION
		DB	#C2			;ST_MEM_2
		DB	#02			;DELETE
		DB	#38			;END_CALC
ARC_START:	PUSH	BC
		RST	#28			;FP_CALC
		DB	#C0			;ST_MEM_0
		DB	#02			;DELETE
		DB	#E1			;GET_MEM_1
		DB	#0F			;ADDITION
		DB	#31			;DUPLICATE
		DB	#38			;END_CALC
		LD	A,(#5C7D)
		CALL	STACK_A
		RST	#28			;FP_CALC
		DB	#03			;SUBTRACT
		DB	#E0			;GET_MEM_0
		DB	#E2			;GET_MEM_2
		DB	#0F			;ADDITION
		DB	#C0			;ST_MEM_0
		DB	#01			;EXCHANGE
		DB	#E0			;GET_MEM_0
		DB	#38			;END_CALC
		LD	A,(#5C7E)
		CALL	STACK_A
		RST	#28			;FP_CALC
		DB	#03			;SUBTRACT
		DB	#38			;END_CALC
		CALL	DRAW_LINE
		POP	BC
		DJNZ	ARC_LOOP
ARC_END:	RST	#28			;FP_CALC
		DB	#02			;DELETE
		DB	#02			;DELETE
		DB	#01			;EXCHANGE
		DB	#38			;END_CALC
		LD	A,(#5C7D)
		CALL	STACK_A
		RST	#28			;FP_CALC
		DB	#03			;SUBTRACT
		DB	#01			;EXCHANGE
		DB	#38			;END_CALC
		LD	A,(#5C7E)
		CALL	STACK_A
		RST	#28			;FP_CALC
		DB	#03			;SUBTRACT
		DB	#38			;END_CALC
LINE_DRAW:	CALL	DRAW_LINE
		JP	TEMPS

; Initial parameters
CD_PRMS1:	RST	#28			;FP_CALC
		DB	#31			;DUPLICATE
		DB	#28			;SQR
		DB	#34			;STK_DATA
		DB	#32			;EXPONENT
		DB	#00			;
		DB	#01			;EXCHANGE
		DB	#05			;DIVISION
		DB	#E5			;GET_MEM_5
		DB	#01			;EXCHANGE
		DB	#05			;DIVISION
		DB	#2A			;ABS
		DB	#38			;END_CALC
		CALL	FP_TO_A
		JR	C,USE_252
		AND	#FC
		ADD	A,#04
		JR	NC,DRAW_SAVE
USE_252:	LD	A,#FC
DRAW_SAVE:	PUSH	AF
		CALL	STACK_A
		RST	#28			;FP_CALC
		DB	#E5			;GET_MEM_5
		DB	#01			;EXCHANGE
		DB	#05			;DIVISION
		DB	#31			;DUPLICATE
		DB	#1F			;SIN
		DB	#C4			;ST_MEM_4
		DB	#02			;DELETE
		DB	#31			;DUPLICATE
		DB	#A2			;STK_HALF
		DB	#04			;MULTIPLY
		DB	#1F			;SIN
		DB	#C1			;ST_MEM_1
		DB	#01			;EXCHANGE
		DB	#C0			;ST_MEM_0
		DB	#02			;DELETE
		DB	#31			;DUPLICATE
		DB	#04			;MULTIPLY
		DB	#31			;DUPLICATE
		DB	#0F			;ADDITION
		DB	#A1			;STK_ONE
		DB	#03			;SUBTRACT
		DB	#1B			;NEGATE
		DB	#C3			;ST_MEM_3
		DB	#02			;DELETE
		DB	#38			;END_CALC
		POP	BC
		RET

; Line drawing
DRAW_LINE:	CALL	STK_TO_BC
		LD	A,C
		CP	B
		JR	NC,DL_X_GE_Y
		LD	L,C
		PUSH	DE
		XOR	A
		LD	E,A
		JR	DL_LARGER

DL_X_GE_Y:	OR	C
		RET	Z
		LD	L,B
		LD	B,C
		PUSH	DE
		LD	D,#00
DL_LARGER:	LD	H,B
		LD	A,B
		RRA
D_L_LOOP:	ADD	A,L
		JR	C,D_L_DIAG
		CP	H
		JR	C,D_L_HR_VT
D_L_DIAG:	SUB	H
		LD	C,A
		EXX
		POP	BC
		PUSH	BC
		JR	D_L_STEP

D_L_HR_VT:	LD	C,A
		PUSH	DE
		EXX
		POP	BC
D_L_STEP:	LD	HL,(#5C7D)
		LD	A,B
		ADD	A,H
		LD	B,A
		LD	A,C
		INC	A
		ADD	A,L
		JR	C,D_L_RANGE
		JR	Z,REPORT_BC
D_L_PLOT:	DEC	A
		LD	C,A
		CALL	PLOT_SUB
		EXX
		LD	A,C
		DJNZ	D_L_LOOP
		POP	DE
		RET

D_L_RANGE:	JR	Z,D_L_PLOT
REPORT_BC:	RST	#08			; Error report
		DB	#0A			; Integer out of range

; Scan expression or sub expression
SCANNING:	RST	#18
		LD	B,#00
		PUSH	BC
S_LOOP_1:	LD	C,A
		CALL	HEXA			; BSROM - hexadecimal numbers handling
		CALL	INDEXER
		LD	A,C
		JP	NC,S_ALPHNUM
		LD	B,#00
		LD	C,(HL)
		ADD	HL,BC
		JP	(HL)

S_QUOTE_S:	CALL	CH_ADD_1
		INC	BC
		CP	#0D
		JP	Z,REPORT_C
		CP	#22
		JR	NZ,S_QUOTE_S
		CALL	CH_ADD_1
		CP	#22
		RET

S_2_COORD:	RST	#20
		CP	#28
		JR	NZ,S_RPORT_C
		CALL	NEXT_2NUM
		RST	#18
		CP	#29
S_RPORT_C:	JP	NZ,REPORT_C

; Check syntax
SYNTAX_Z:	BIT	7,(IY+#01)
		RET

; Scanning SCREEN$
S_SCRN_S:	CALL	STK_TO_BC
		LD	HL,(#5C36)
		LD	DE,#0100
		ADD	HL,DE
		LD	A,C
		RRCA
		RRCA
		RRCA
		AND	#E0
		XOR	B
		LD	E,A
		LD	A,C
		AND	#18
		XOR	#40
		LD	D,A
		LD	B,#60
S_SCRN_LP:	PUSH	BC
		PUSH	DE
		PUSH	HL
		LD	A,(DE)
		XOR	(HL)
		JR	Z,S_SC_MTCH
		INC	A
		JR	NZ,S_SCR_NXT
		DEC	A
S_SC_MTCH:	LD	C,A
		LD	B,#07
S_SC_ROWS:	INC	D
		INC	HL
		LD	A,(DE)
		XOR	(HL)
		XOR	C
		JR	NZ,S_SCR_NXT
		DJNZ	S_SC_ROWS
		POP	BC
		POP	BC
		POP	BC
		LD	A,#80
		SUB	B
		LD	BC,#0001
		RST	#30
		LD	(DE),A
		JR	S_SCR_STO

S_SCR_NXT:	POP	HL
		LD	DE,#0008
		ADD	HL,DE
		POP	DE
		POP	BC
		DJNZ	S_SCRN_LP
		LD	C,B
S_SCR_STO:	RET				; BSROM - bugfix - don't store string after SCREEN$
		DB	#B2,#2A			; remains of JP STK_STO_D (#2AB2)

; Scanning attributes
S_ATTR_S:	CALL	STK_TO_BC
		LD	A,C
		RRCA
		RRCA
		RRCA
		LD	C,A
		AND	#E0
		XOR	B
		LD	L,A
		LD	A,C
		AND	#03
		XOR	#58
		LD	H,A
		LD	A,(HL)
		JP	STACK_A

; Scanning function table
SCAN_FUNC:	DB	#22, #1C		; S_QUOTE
		DB	#28, #4F		; S_BRACKET
		DB	#2E, #F2		; S_DECIMAL
		DB	#2B, #12		; S_U_PLUS
		DB	#A8, #56		; S_FN
		DB	#A5, #57		; S_RND
		DB	#A7, #84		; S_PI
		DB	#A6, #8F		; S_INKEY
		DB	#C4, #E6		; S_BIN
		DB	#AA, #BF		; S_SCREEN
		DB	#AB, #C7		; S_ATTR
		DB	#A9, #CE		; S_POINT
		DB	#00			; End marker

; Scanning function routines
S_U_PLUS:	RST	#20
		JP	S_LOOP_1

S_QUOTE:	RST	#18
		INC	HL
		PUSH	HL
		LD	BC,#0000
		CALL	S_QUOTE_S
		JR	NZ,S_Q_PRMS
S_Q_AGAIN:	CALL	S_QUOTE_S
		JR	Z,S_Q_AGAIN
		CALL	SYNTAX_Z
		JR	Z,S_Q_PRMS
		RST	#30
		POP	HL
		PUSH	DE
S_Q_COPY:	LD	A,(HL)
		INC	HL
		LD	(DE),A
		INC	DE
		CP	#22
		JR	NZ,S_Q_COPY
		LD	A,(HL)
		INC	HL
		CP	#22
		JR	Z,S_Q_COPY
S_Q_PRMS:	DEC	BC
		POP	DE
S_STRING:	LD	HL,#5C3B
		RES	6,(HL)
		BIT	7,(HL)
		CALL	NZ,STK_STO_D
		JP	S_CONT_2

S_BRACKET:	RST	#20
		CALL	SCANNING
		CP	#29
		JP	NZ,REPORT_C
		RST	#20
		JP	S_CONT_2

S_FN:		JP	NEWFNC			; BSROM for MB02+ - new functions

S_RND:		CALL	SYNTAX_Z
		JR	Z,S_RND_END
		LD	BC,(#5C76)
		CALL	STACK_BC
		RST	#28			;FP_CALC
		DB	#A1			;STK_ONE
		DB	#0F			;ADDITION
		DB	#34			;STK_DATA
		DB	#37			;Exponent
		DB	#16			;
		DB	#04			;MULTIPLY
		DB	#34			;STK_DATA
		DB	#80			;
		DB	#41			;Exponent
		DB	#00			;
		DB	#00			;
		DB	#80			;
		DB	#32			;N_MOD_M
		DB	#02			;DELETE
		DB	#A1			;STK_ONE
		DB	#03			;SUBTRACT
		DB	#31			;DUPLICATE
		DB	#38			;END_CALC
		CALL	FP_TO_BC
		LD	(#5C76),BC
		LD	A,(HL)
		AND	A
		JR	Z,S_RND_END
		SUB	#10
		LD	(HL),A
S_RND_END:	JR	S_PI_END

S_PI:		CALL	SYNTAX_Z
		JR	Z,S_PI_END
		RST	#28			;FP_CALC
		DB	#A3			;STK_PI_2
		DB	#38			;END_CALC
		INC	(HL)
S_PI_END:	RST	#20
		JP	S_NUMERIC

S_INKEY:	LD	BC,#105A
		RST	#20
		CP	#23
		JP	Z,S_PUSH_PO
		LD	HL,#5C3B
		RES	6,(HL)
		BIT	7,(HL)
		JR	Z,S_INK_EN
		CALL	KEY_SCAN
		LD	C,#00
		JR	NZ,S_IK_STK
		CALL	K_TEST
		JR	NC,S_IK_STK
		DEC	D
		LD	E,A
		CALL	K_DECODE
		PUSH	AF
		LD	BC,#0001
		RST	#30
		POP	AF
		LD	(DE),A
		LD	C,#01
S_IK_STK:	LD	B,#00
		CALL	STK_STO_D
S_INK_EN:	JP	S_CONT_2

S_SCREEN:	CALL	S_2_COORD
		CALL	NZ,S_SCRN_S
		RST	#20
		JP	S_STRING

S_ATTR:		CALL	S_2_COORD
		CALL	NZ,S_ATTR_S
		RST	#20
		JR	S_NUMERIC

S_POINT:	CALL	S_2_COORD
		CALL	NZ,POINT_SUB
		RST	#20
		JR	S_NUMERIC

S_ALPHNUM:	CALL	ALPHANUM
		JR	NC,S_NEGATE
		CP	#41
		JR	NC,S_LETTER
S_DECIMAL:		
S_BIN:		CALL	SYNTAX_Z
		JR	NZ,S_STK_DEC
		CALL	DEC_TO_FP
S_BIN_1:	RST	#18
		LD	BC,#0006
		CALL	MAKE_ROOM
		INC	HL
		LD	(HL),#0E
		INC	HL
		EX	DE,HL
		LD	HL,(#5C65)
		LD	C,#05
		AND	A
		SBC	HL,BC
		LD	(#5C65),HL
		LDIR
		EX	DE,HL
		DEC	HL
		CALL	TEMP_PTR1
		JR	S_NUMERIC

S_STK_DEC:	RST	#18
S_SD_SKIP:	INC	HL
		LD	A,(HL)
		CP	#0E
		JR	NZ,S_SD_SKIP
		INC	HL
		CALL	STACK_NUM
		LD	(#5C5D),HL
S_NUMERIC:	SET	6,(IY+#01)
		JR	S_CONT_1

; Scanning variable routines
S_LETTER:	CALL	LOOK_VARS
		JP	C,REPORT_2
		CALL	Z,STK_VAR
		LD	A,(#5C3B)
		CP	#C0
		JR	C,S_CONT_1
		INC	HL
		CALL	STACK_NUM
S_CONT_1:	JR	S_CONT_2

S_NEGATE:	LD	BC,#09DB
		CP	#2D
		JR	Z,S_PUSH_PO
		LD	BC,#1018
		CP	#AE
		JR	Z,S_PUSH_PO
		SUB	#AF
		JP	C,REPORT_C
		LD	BC,#04F0
		CP	#14
		JR	Z,S_PUSH_PO
		JP	NC,REPORT_C
		LD	B,#10
		ADD	A,#DC
		LD	C,A
		CP	#DF
		JR	NC,S_NO_TO
		RES	6,C
S_NO_TO:	CP	#EE
		JR	C,S_PUSH_PO
		RES	7,C
S_PUSH_PO:	PUSH	BC
		RST	#20
		JP	S_LOOP_1

S_CONT_2:	RST	#18
S_CONT_3:	CP	#28
		JR	NZ,S_OPERTR
		BIT	6,(IY+#01)
		JR	NZ,S_LOOP
		CALL	SLICING
		RST	#20
		JR	S_CONT_3

S_OPERTR:	LD	B,#00
		LD	C,A
		LD	HL,TBL_OF_OPS
		CALL	INDEXER
		JR	NC,S_LOOP
		LD	C,(HL)
		LD	HL,#26ED
		ADD	HL,BC
		LD	B,(HL)

; Scanning main loop
S_LOOP:		POP	DE
		LD	A,D
		CP	B
		JR	C,S_TIGHTER
		AND	A
		JP	Z,GET_CHAR
		PUSH	BC
		LD	HL,#5C3B
		LD	A,E
		CP	#ED
		JR	NZ,S_STK_LST
		BIT	6,(HL)
		JR	NZ,S_STK_LST
		LD	E,#99
S_STK_LST:	PUSH	DE
		CALL	SYNTAX_Z
		JR	Z,S_SYNTEST
		LD	A,E
		AND	#3F
		LD	B,A
		RST	#28			;FP_CALC
		DB	#3B			;FP_CALC_2
		DB	#38			;END_CALC
		JR	S_RUNTEST

S_SYNTEST:	LD	A,E
		CALL	VAL1			; BSROM - enhanced VAL & VAL$
		AND	#40
S_RPORT_C2:	JP	NZ,REPORT_C
S_RUNTEST:	POP	DE
		LD	HL,#5C3B
		SET	6,(HL)
		BIT	7,E
		JR	NZ,S_LOOPEND
		RES	6,(HL)
S_LOOPEND:	POP	BC
		JR	S_LOOP

S_TIGHTER:	PUSH	DE
		LD	A,C
		BIT	6,(IY+#01)
		JR	NZ,S_NEXT
		AND	#3F
		ADD	A,#08
		LD	C,A
		CP	#10
		JR	NZ,S_NOT_AND
		SET	6,C
		JR	S_NEXT

S_NOT_AND:	JR	C,S_RPORT_C2
		CP	#17
		JR	Z,S_NEXT
		SET	7,C
S_NEXT:		PUSH	BC
		RST	#20
		JP	S_LOOP_1

; Table of operators
TBL_OF_OPS:	DB	"+", #CF		; ADDITION
		DB	"-", #C3		; SUBTRACT
		DB	"*", #C4		; MULTIPLY
		DB	"/", #C5		; DIVISION
		DB	"^", #C6		; TO_POWER
		DB	"=", #CE		; NOS_EQL
		DB	">", #CC		; NO_GRTR
		DB	"<", #CD		; NO_LESS
		DB	#C7, #C9		; NO_L_EQL '<='
		DB	#C8, #CA		; NO_GR_EQL '>='
		DB	#C9, #CB		; NOS_NEQL '<>'
		DB	#C5, #C7		; OR
		DB	#C6, #C8		; AND
		DB	#00			; End marker

; Table of priorities
TBL_PRIORS:	DB	#06			; '-'
		DB	#08			; '*'
		DB	#08			; '/'
		DB	#0A			; '^'
		DB	#02			; OR
		DB	#03			; AND
		DB	#05			; '<='
		DB	#05			; '>='
		DB	#05			; '<>'
		DB	#05			; '>'
		DB	#05			; '<'
		DB	#05			; '='
		DB	#06			; '+'

; User defined functions handling
S_FN_SBRN:	CALL	SYNTAX_Z
		JR	NZ,SF_RUN
		RST	#20
S_FN_SBRN1:	CALL	ALPHA
		JP	NC,REPORT_C
		RST	#20
		CP	#24
		PUSH	AF
		JR	NZ,SF_BRKT_1
		RST	#20
SF_BRKT_1:	CP	#28
		JR	NZ,SF_RPRT_C
		RST	#20
		CP	#29
		JR	Z,SF_FLAG_6
SF_ARGMTS:	CALL	SCANNING
		RST	#18
		CP	#2C
		JR	NZ,SF_BRKT_2
		RST	#20
		JR	SF_ARGMTS

SF_BRKT_2:	CP	#29
SF_RPRT_C:	JP	NZ,REPORT_C
SF_FLAG_6:	RST	#20
		LD	HL,#5C3B
		RES	6,(HL)
		POP	AF
		JR	Z,SF_SYN_EN
		SET	6,(HL)
SF_SYN_EN	JP	S_CONT_2

SF_RUN:		RST	#20
SF_RUN1:	AND	#DF
		LD	B,A
		RST	#20
		SUB	#24
		LD	C,A
		JR	NZ,SF_ARGMT1
		RST	#20
SF_ARGMT1:	RST	#20
		PUSH	HL
		LD	HL,(#5C53)
		DEC	HL
SF_FND_DF:	LD	DE,#00CE
		PUSH	BC
		CALL	LOOK_PROG
		POP	BC
		JR	NC,SF_CP_DEF
REPORT_P:	RST	#08			; Error report
		DB	#18			; FN without DEF
SF_CP_DEF:	PUSH	HL
		CALL	FN_SKPOVR
		AND	#DF
		CP	B
		JR	NZ,SF_NOT_FD
		CALL	FN_SKPOVR
		SUB	#24
		CP	C
		JR	Z,SF_VALUES
SF_NOT_FD:	POP	HL
		DEC	HL
		LD	DE,#0200
		PUSH	BC
		CALL	EACH_STMT
		POP	BC
		JR	SF_FND_DF

SF_VALUES:	AND	A
		CALL	Z,FN_SKPOVR
		POP	DE
		POP	DE
		LD	(#5C5D),DE
		CALL	FN_SKPOVR
		PUSH	HL
		CP	#29
		JR	Z,SF_R_BR_2
SF_ARG_LP:	INC	HL
		LD	A,(HL)
		CP	#0E
		LD	D,#40
		JR	Z,SF_ARG_VR
		DEC	HL
		CALL	FN_SKPOVR
		INC	HL
		LD	D,#00
SF_ARG_VR:	INC	HL
		PUSH	HL
		PUSH	DE
		CALL	SCANNING
		POP	AF
		XOR	(IY+#01)
		AND	#40
		JR	NZ,REPORT_Q
		POP	HL
		EX	DE,HL
		LD	HL,(#5C65)
		LD	BC,#0005
		SBC	HL,BC
		LD	(#5C65),HL
		LDIR
		EX	DE,HL
		DEC	HL
		CALL	FN_SKPOVR
		CP	#29
		JR	Z,SF_R_BR_2
		PUSH	HL
		RST	#18
		CP	#2C
		JR	NZ,REPORT_Q
		RST	#20
		POP	HL
		CALL	FN_SKPOVR
		JR	SF_ARG_LP

SF_R_BR_2:	PUSH	HL
		RST	#18
		CP	#29
		JR	Z,SF_VALUE
REPORT_Q:	RST	#08			; Error report
		DB	#19			; Parameter error
SF_VALUE:	POP	DE
		EX	DE,HL
		LD	(#5C5D),HL
		LD	HL,(#5C0B)
		EX	(SP),HL
		LD	(#5C0B),HL
		PUSH	DE
		RST	#20
		RST	#20
		CALL	SCANNING
		POP	HL
		LD	(#5C5D),HL
		POP	HL
		LD	(#5C0B),HL
		RST	#20
		JP	S_CONT_2

; Skip spaces and color control codes in DEF FN
FN_SKPOVR:	INC	HL
		LD	A,(HL)
		CP	#21
		JR	C,FN_SKPOVR
		RET

; Variables lookup
LOOK_VARS:	SET	6,(IY+#01)
		RST	#18
		CALL	ALPHA
		JP	NC,REPORT_C
		PUSH	HL
		AND	#1F
		LD	C,A
		RST	#20
		PUSH	HL
		CP	#28
		JR	Z,V_RUN_SYN
		SET	6,C
		CP	#24
		JR	Z,V_STR_VAR
		SET	5,C
		CALL	ALPHANUM
		JR	NC,V_TEST_FN
V_CHAR:		CALL	ALPHANUM
		JR	NC,V_RUN_SYN
		RES	6,C
		RST	#20
		JR	V_CHAR

V_STR_VAR:	RST	#20
		RES	6,(IY+#01)
V_TEST_FN:	LD	A,(#5C0C)
		AND	A
		JR	Z,V_RUN_SYN
		CALL	SYNTAX_Z
		JP	NZ,STK_F_ARG
V_RUN_SYN:	LD	B,C
		CALL	SYNTAX_Z
		JR	NZ,V_RUN
		LD	A,C
		AND	#E0
		SET	7,A
		LD	C,A
		JR	V_SYNTAX

V_RUN:		LD	HL,(#5C4B)
V_EACH:		LD	A,(HL)
		AND	#7F
		JR	Z,V_80_BYTE
		CP	C
		JR	NZ,V_NEXT
		RLA
		ADD	A,A
		JP	P,V_FOUND_2
		JR	C,V_FOUND_2
		POP	DE
		PUSH	DE
		PUSH	HL
V_MATCHES:	INC	HL
V_SPACES:	LD	A,(DE)
		INC	DE
		CP	#20
		JR	Z,V_SPACES
		OR	#20
		CP	(HL)
		JR	Z,V_MATCHES
		OR	#80
		CP	(HL)
		JR	NZ,V_GET_PTR
		LD	A,(DE)
		CALL	ALPHANUM
		JR	NC,V_FOUND_1
V_GET_PTR:	POP	HL
V_NEXT:		PUSH	BC
		CALL	NEXT_ONE
		EX	DE,HL
		POP	BC
		JR	V_EACH

V_80_BYTE:	SET	7,B
V_SYNTAX:	POP	DE
		RST	#18
		CP	#28
		JR	Z,V_PASS
		SET	5,B
		JR	V_END

V_FOUND_1:	POP	DE
V_FOUND_2:	POP	DE
		POP	DE
		PUSH	HL
		RST	#18
V_PASS:		CALL	ALPHANUM
		JR	NC,V_END
		RST	#20
		JR	V_PASS

V_END:		POP	HL
		RL	B
		BIT	6,B
		RET

; Stack function argument
STK_F_ARG:	LD	HL,(#5C0B)
		LD	A,(HL)
		CP	#29
		JP	Z,V_RUN_SYN
SFA_LOOP:	LD	A,(HL)
		OR	#60
		LD	B,A
		INC	HL
		LD	A,(HL)
		CP	#0E
		JR	Z,SFA_CP_VR
		DEC	HL
		CALL	FN_SKPOVR
		INC	HL
		RES	5,B
SFA_CP_VR:	LD	A,B
		CP	C
		JR	Z,SFA_MATCH
		INC	HL
		INC	HL
		INC	HL
		INC	HL
		INC	HL
		CALL	FN_SKPOVR
		CP	#29
		JP	Z,V_RUN_SYN
		CALL	FN_SKPOVR
		JR	SFA_LOOP

SFA_MATCH:	BIT	5,C
		JR	NZ,SFA_END
		INC	HL
		LD	DE,(#5C65)
		CALL	MOVE_FP
		EX	DE,HL
		LD	(#5C65),HL
SFA_END:	POP	DE
		POP	DE
		XOR	A
		INC	A
		RET

; Stack variable component
STK_VAR:	XOR	A
		LD	B,A
		BIT	7,C
		JR	NZ,SV_COUNT
		BIT	7,(HL)
		JR	NZ,SV_ARRAYS
		INC	A
SV_SIMPLE:	INC	HL
		LD	C,(HL)
		INC	HL
		LD	B,(HL)
		INC	HL
		EX	DE,HL
		CALL	STK_STO_D
		RST	#18
		JP	SV_SLICE_EX

SV_ARRAYS:	INC	HL
		INC	HL
		INC	HL
		LD	B,(HL)
		BIT	6,C
		JR	Z,SV_PTR
		DEC	B
		JR	Z,SV_SIMPLE
		EX	DE,HL
		RST	#18
		CP	#28
		JR	NZ,REPORT_3
		EX	DE,HL
SV_PTR:		EX	DE,HL
		JR	SV_COUNT

SV_COMMA:	PUSH	HL
		RST	#18
		POP	HL
		CP	#2C
		JR	Z,SV_LOOP
		BIT	7,C
		JR	Z,REPORT_3
		BIT	6,C
		JR	NZ,SV_CLOSE
		CP	#29
		JR	NZ,SV_RPT_C
		RST	#20
		RET

SV_CLOSE:	CP	#29
		JR	Z,SV_DIM
		CP	#CC
		JR	NZ,SV_RPT_C
SV_CH_ADD:	RST	#18
		DEC	HL
		LD	(#5C5D),HL
		JR	SV_SLICE

SV_COUNT:	LD	HL,#0000
SV_LOOP:	PUSH	HL
		RST	#20
		POP	HL
		LD	A,C
		CP	#C0
		JR	NZ,SV_MULT
		RST	#18
		CP	#29
		JR	Z,SV_DIM
		CP	#CC
		JR	Z,SV_CH_ADD
SV_MULT:	PUSH	BC
		PUSH	HL
		CALL	DE_DE_1
		EX	(SP),HL
		EX	DE,HL
		CALL	INT_EXP1
		JR	C,REPORT_3
		DEC	BC
		CALL	GET_HL_DE
		ADD	HL,BC
		POP	DE
		POP	BC
		DJNZ	SV_COMMA
		BIT	7,C
SV_RPT_C:	JR	NZ,SL_RPT_C
		PUSH	HL
		BIT	6,C
		JR	NZ,SV_ELEM
		LD	B,D
		LD	C,E
		RST	#18
		CP	#29
		JR	Z,SV_NUMBER
REPORT_3:	RST	#08			; Error report
		DB	#02			; Subscript wrong
SV_NUMBER:	RST	#20
		POP	HL
		LD	DE,#0005
		CALL	GET_HL_DE
		ADD	HL,BC
		RET

SV_ELEM:	CALL	DE_DE_1
		EX	(SP),HL
		CALL	GET_HL_DE
		POP	BC
		ADD	HL,BC
		INC	HL
		LD	B,D
		LD	C,E
		EX	DE,HL
		CALL	STK_ST_0
		RST	#18
		CP	#29
		JR	Z,SV_DIM
		CP	#2C
		JR	NZ,REPORT_3
SV_SLICE:	CALL	SLICING
SV_DIM:		RST	#20
SV_SLICE_EX:	CP	#28
		JR	Z,SV_SLICE
		RES	6,(IY+#01)
		RET

; Handle slicing of strings
SLICING:	CALL	SYNTAX_Z
		CALL	NZ,STK_FETCH
		RST	#20
		CP	#29
		JR	Z,SL_STORE
		PUSH	DE
		XOR	A
		PUSH	AF
		PUSH	BC
		LD	DE,#0001
		RST	#18
		POP	HL
		CP	#CC
		JR	Z,SL_SECOND
		POP	AF
		CALL	INT_EXP2
		PUSH	AF
		LD	D,B
		LD	E,C
		PUSH	HL
		RST	#18
		POP	HL
		CP	#CC
		JR	Z,SL_SECOND
		CP	#29
SL_RPT_C:	JP	NZ,REPORT_C
		LD	H,D
		LD	L,E
		JR	SL_DEFINE

SL_SECOND:	PUSH	HL
		RST	#20
		POP	HL
		CP	#29
		JR	Z,SL_DEFINE
		POP	AF
		CALL	INT_EXP2
		PUSH	AF
		RST	#18
		LD	H,B
		LD	L,C
		CP	#29
		JR	NZ,SL_RPT_C
SL_DEFINE:	POP	AF
		EX	(SP),HL
		ADD	HL,DE
		DEC	HL
		EX	(SP),HL
		AND	A
		SBC	HL,DE
		LD	BC,#0000
		JR	C,SL_OVER
		INC	HL
		AND	A
		JP	M,REPORT_3
		LD	B,H
		LD	C,L
SL_OVER:	POP	DE
SL_OVER1:	RES	6,(IY+#01)
SL_STORE:	CALL	SYNTAX_Z
		RET	Z
STK_ST_0:	XOR	A
STK_STO_D:	RES	6,(IY+#01)
STK_STORE:	PUSH	BC			; Put five registers on the calc stack
		CALL	TEST_5_SP
		POP	BC
		LD	HL,(#5C65)
		LD	(HL),A
		INC	HL
		LD	(HL),E
		INC	HL
		LD	(HL),D
		INC	HL
		LD	(HL),C
		INC	HL
		LD	(HL),B
		INC	HL
		LD	(#5C65),HL
		RET

; Check and evaluate an integer expression
INT_EXP1:	XOR	A
INT_EXP2:	PUSH	DE
		PUSH	HL
		PUSH	AF
		CALL	EXPT_1NUM
		POP	AF
		CALL	SYNTAX_Z
		JR	Z,I_RESTORE
		PUSH	AF
		CALL	FIND_INT2
		POP	DE
		LD	A,B
		OR	C
		SCF
		JR	Z,I_CARRY
		POP	HL
		PUSH	HL
		AND	A
		SBC	HL,BC
I_CARRY:	LD	A,D
		SBC	A,#00
I_RESTORE:	POP	HL
		POP	DE
		RET

; Load DE+1 into DE
DE_DE_1:	EX	DE,HL
		INC	HL
		LD	E,(HL)
		INC	HL
		LD	D,(HL)
		RET

; Multiply HL by DE
GET_HL_DE:	CALL	SYNTAX_Z
		RET	Z
		CALL	HL_HL_DE
		JP	C,REPORT_4
		RET

; Handle LET command
LET:		LD	HL,(#5C4D)
		BIT	1,(IY+#37)
		JR	Z,L_EXISTS
		LD	BC,#0005
L_EACH_CH:	INC	BC
L_NO_SP:	INC	HL
		LD	A,(HL)
		CP	#20
		JR	Z,L_NO_SP
		JR	NC,L_TEST_CH
		CP	#10
		JR	C,L_SPACES
		CP	#16
		JR	NC,L_SPACES
		INC	HL
		JR	L_NO_SP

L_TEST_CH:	CALL	ALPHANUM
		JR	C,L_EACH_CH
		CP	#24
		JP	Z,L_NEW
L_SPACES:	LD	A,C
		LD	HL,(#5C59)
		DEC	HL
		CALL	MAKE_ROOM
		INC	HL
		INC	HL
		EX	DE,HL
		PUSH	DE
		LD	HL,(#5C4D)
		DEC	DE
		SUB	#06
		LD	B,A
		JR	Z,L_SINGLE
L_CHAR:		INC	HL
		LD	A,(HL)
		CP	#21
		JR	C,L_CHAR
		OR	#20
		INC	DE
		LD	(DE),A
		DJNZ	L_CHAR
		OR	#80
		LD	(DE),A
		LD	A,#C0
L_SINGLE:	LD	HL,(#5C4D)
		XOR	(HL)
		OR	#20
		POP	HL
		CALL	L_FIRST
L_NUMERIC:	PUSH	HL
		RST	#28			;FP_CALC
		DB	#02			;DELETE
		DB	#38			;END_CALC
		POP	HL
		LD	BC,#0005
		AND	A
		SBC	HL,BC
		JR	L_ENTER

L_EXISTS:	BIT	6,(IY+#01)
		JR	Z,L_DELETE
		LD	DE,#0006
		ADD	HL,DE
		JR	L_NUMERIC

L_DELETE:	LD	HL,(#5C4D)
		LD	BC,(#5C72)
		BIT	0,(IY+#37)
		JR	NZ,L_ADD
		LD	A,B
		OR	C
		RET	Z
		PUSH	HL
		RST	#30
		PUSH	DE
		PUSH	BC
		LD	D,H
		LD	E,L
		INC	HL
		LD	(HL),#20
		LDDR
		PUSH	HL
		CALL	STK_FETCH
		POP	HL
		EX	(SP),HL
		AND	A
		SBC	HL,BC
		ADD	HL,BC
		JR	NC,L_LENGTH
		LD	B,H
		LD	C,L
L_LENGTH:	EX	(SP),HL
		EX	DE,HL
		LD	A,B
		OR	C
		JR	Z,L_IN_W_S
		LDIR
L_IN_W_S:	POP	BC
		POP	DE
		POP	HL
L_ENTER:	EX	DE,HL
		LD	A,B
		OR	C
		RET	Z
		PUSH	DE
		LDIR
		POP	HL
		RET

L_ADD:		DEC	HL
		DEC	HL
		DEC	HL
		LD	A,(HL)
		PUSH	HL
		PUSH	BC
		CALL	L_STRING
		POP	BC
		POP	HL
		INC	BC
		INC	BC
		INC	BC
		JP	RECLAIM_2

L_NEW:		LD	A,#DF
		LD	HL,(#5C4D)
		AND	(HL)
L_STRING:	PUSH	AF
		CALL	STK_FETCH
		EX	DE,HL
		ADD	HL,BC
		PUSH	BC
		DEC	HL
		LD	(#5C4D),HL
		INC	BC
		INC	BC
		INC	BC
		LD	HL,(#5C59)
		DEC	HL
		CALL	MAKE_ROOM
		LD	HL,(#5C4D)
		POP	BC
		PUSH	BC
		INC	BC
		LDDR
		EX	DE,HL
		INC	HL
		POP	BC
		LD	(HL),B
		DEC	HL
		LD	(HL),C
		POP	AF
L_FIRST:	DEC	HL
		LD	(HL),A
		LD	HL,(#5C59)
		DEC	HL
		RET

; Get last value from the calc stack
STK_FETCH:	LD	HL,(#5C65)
		DEC	HL
		LD	B,(HL)
		DEC	HL
		LD	C,(HL)
		DEC	HL
		LD	D,(HL)
		DEC	HL
		LD	E,(HL)
		DEC	HL
		LD	A,(HL)
		LD	(#5C65),HL
		RET

; Handle DIM command
DIM:		CALL	LOOK_VARS
D_RPORT_C:	JP	NZ,REPORT_C
		CALL	SYNTAX_Z
		JR	NZ,D_RUN
		RES	6,C
		CALL	STK_VAR
		CALL	CHECK_END
D_RUN:		JR	C,D_LETTER
		PUSH	BC
		CALL	NEXT_ONE
		CALL	RECLAIM_2
		POP	BC
D_LETTER:	SET	7,C
		LD	B,#00
		PUSH	BC
		LD	HL,#0001
		BIT	6,C
		JR	NZ,D_SIZE
		LD	L,#05
D_SIZE:		EX	DE,HL
D_NO_LOOP:	RST	#20
		LD	H,#FF
		CALL	INT_EXP1
		JP	C,REPORT_3
		POP	HL
		PUSH	BC
		INC	H
		PUSH	HL
		LD	H,B
		LD	L,C
		CALL	GET_HL_DE
		EX	DE,HL
		RST	#18
		CP	#2C
		JR	Z,D_NO_LOOP
		CP	#29
		JR	NZ,D_RPORT_C
		RST	#20
		POP	BC
		LD	A,C
		LD	L,B
		LD	H,#00
		INC	HL
		INC	HL
		ADD	HL,HL
		ADD	HL,DE
		JP	C,REPORT_4
		PUSH	DE
		PUSH	BC
		PUSH	HL
		LD	B,H
		LD	C,L
		LD	HL,(#5C59)
		DEC	HL
		CALL	MAKE_ROOM
		INC	HL
		LD	(HL),A
		POP	BC
		DEC	BC
		DEC	BC
		DEC	BC
		INC	HL
		LD	(HL),C
		INC	HL
		LD	(HL),B
		POP	BC
		LD	A,B
		INC	HL
		LD	(HL),A
		LD	H,D
		LD	L,E
		DEC	DE
		LD	(HL),#00
		BIT	6,C
		JR	Z,DIM_CLEAR
		LD	(HL),#20
DIM_CLEAR:	POP	BC
		LDDR
DIM_SIZES:	POP	BC
		LD	(HL),B
		DEC	HL
		LD	(HL),C
		DEC	HL
		DEC	A
		JR	NZ,DIM_SIZES
		RET

; Check that the character in A is alphanumeric
ALPHANUM:	CALL	NUMERIC
		CCF
		RET	C
ALPHA:		CP	#41
		CCF
		RET	NC
		CP	#5B
		RET	C
		CP	#61
		CCF
		RET	NC
		CP	#7B
		RET

; Decimal to floating point
DEC_TO_FP:	CP	#C4
		JR	NZ,NOT_BIN
		LD	DE,#0000
BIN_DIGIT:	RST	#20
		SUB	#31
		ADC	A,#00
		JR	NZ,BIN_END
		EX	DE,HL
		CCF
		ADC	HL,HL
		JP	C,REPORT_6
		EX	DE,HL
		JR	BIN_DIGIT

BIN_END:	LD	B,D
		LD	C,E
		JP	STACK_BC

NOT_BIN:	CP	#2E
		JR	Z,DECIMAL
		CALL	INT_TO_FP
		CP	#2E
		JR	NZ,E_FORMAT
		RST	#20
		CALL	NUMERIC
		JR	C,E_FORMAT
		JR	DEC_STO_1

DECIMAL:	RST	#20
		CALL	NUMERIC
DEC_RPT_C:	JP	C,REPORT_C
		RST	#28			;FP_CALC
		DB	#A0			;STK_ZERO
		DB	#38			;END_CALC

DEC_STO_1:	RST	#28			;FP_CALC
		DB	#A1			;STK_ONE
		DB	#C0			;ST_MEM_0
		DB	#02			;DELETE
		DB	#38			;END_CALC

NXT_DGT_1:	RST	#18
		CALL	STK_DIGIT
		JR	C,E_FORMAT
		RST	#28			;FP_CALC
		DB	#E0			;GET_MEM_0
		DB	#A4			;STK_TEN
		DB	#05			;DIVISION
		DB	#C0			;ST_MEM_0
		DB	#04			;MULTIPLY
		DB	#0F			;ADDITION
		DB	#38			;END_CALC
		RST	#20
		JR	NXT_DGT_1

E_FORMAT:	CP	#45
		JR	Z,SIGN_FLAG
		CP	#65
		RET	NZ
SIGN_FLAG:	LD	B,#FF
		RST	#20
		CP	#2B
		JR	Z,SIGN_DONE
		CP	#2D
		JR	NZ,ST_E_PART
		INC	B
SIGN_DONE:	RST	#20
ST_E_PART:	CALL	NUMERIC
		JR	C,DEC_RPT_C
		PUSH	BC
		CALL	INT_TO_FP
		CALL	FP_TO_A
		POP	BC
		JP	C,REPORT_6
		AND	A
		JP	M,REPORT_6
		INC	B
		JR	Z,E_FP_JUMP
		NEG
E_FP_JUMP:	JP	E_TO_FP

; Check for valid digit
NUMERIC:	CP	#30
		RET	C
		CP	#3A
		CCF
		RET

; Stack digit
STK_DIGIT:	CALL	NUMERIC
		RET	C
		SUB	#30
STACK_A:	LD	C,A			;Stack accumulator
		LD	B,#00
STACK_BC:	LD	IY,#5C3A		;Stack BC register pair
		XOR	A
		LD	E,A
		LD	D,C
		LD	C,B
		LD	B,A
		CALL	STK_STORE
		RST	#28			;FP_CALC
		DB	#38			;END_CALC
		AND	A
		RET

; Integer to floating point
INT_TO_FP:	PUSH	AF
		RST	#28			;FP_CALC
		DB	#A0			;STK_ZERO
		DB	#38			;END_CALC
		POP	AF
NXT_DGT_2:	CALL	STK_DIGIT
		RET	C
		RST	#28			;FP_CALC
		DB	#01			;EXCHANGE
		DB	#A4			;STK_TEN
		DB	#04			;MULTIPLY
		DB	#0F			;ADDITION
		DB	#38			;END_CALC
		CALL	CH_ADD_1
		JR	NXT_DGT_2

; E-format to floating point
E_TO_FP:	RLCA
		RRCA
		JR	NC,E_SAVE
		CPL
		INC	A
E_SAVE:		PUSH	AF
		LD	HL,#5C92
		CALL	FP_0_1
		RST	#28			;FP_CALC
		DB	#A4			;STK_TEN
		DB	#38			;END_CALC
		POP	AF
E_LOOP:		SRL	A
		JR	NC,E_TST_END
		PUSH	AF
		RST	#28			;FP_CALC
		DB	#C1			;ST_MEM_1
		DB	#E0			;GET_MEM_0
		DB	#00			;JUMP_TRUE
		DB	#04			;to E_DIVSN
		DB	#04			;MULTIPLY
		DB	#33			;JUMP
		DB	#02			;to E_FETCH
E_DIVSN:	DB	#05			;DIVISION
E_FETCH:	DB	#E1			;GET_MEM_1
		DB	#38			;END_CALC
		POP	AF
E_TST_END:	JR	Z,E_END
		PUSH	AF
		RST	#28			;FP_CALC
		DB	#31			;DUPLICATE
		DB	#04			;MULTIPLY
		DB	#38			;END_CALC
		POP	AF
		JR	E_LOOP

E_END:		RST	#28			;FP_CALC
		DB	#02			;DELETE
		DB	#38			;END_CALC
		RET

; Fetch integer
INT_FETCH:	INC	HL
		LD	C,(HL)
		INC	HL
		LD	A,(HL)
		XOR	C
		SUB	C
		LD	E,A
		INC	HL
		LD	A,(HL)
		ADC	A,C
		XOR	C
		LD	D,A
		RET

; Store a positive integer. Not used in ROM.
P_INT_STO:	LD	C,#00

; Store an integer
INT_STORE:	PUSH	HL
		LD	(HL),#00
		INC	HL
		LD	(HL),C
		INC	HL
		LD	A,E
		XOR	C
		SUB	C
		LD	(HL),A
		INC	HL
		LD	A,D
		ADC	A,C
		XOR	C
		LD	(HL),A
		INC	HL
		LD	(HL),#00
		POP	HL
		RET

; Get floating point number from the calc stack to the BC
FP_TO_BC:	RST	#28			;FP_CALC
		DB	#38			;END_CALCS
		LD	A,(HL)
		AND	A
		JR	Z,FP_DELETE
		RST	#28			;FP_CALC
		DB	#A2			;STK_HALF
		DB	#0F			;ADDITION
		DB	#27			;INT
		DB	#38			;END_CALC

FP_DELETE:	RST	#28			;FP_CALC
		DB	#02			;DELETE
		DB	#38			;END_CALC
		PUSH	HL
		PUSH	DE
		EX	DE,HL
		LD	B,(HL)
		CALL	INT_FETCH
		XOR	A
		SUB	B
		BIT	7,C
		LD	B,D
		LD	C,E
		LD	A,E
		POP	DE
		POP	HL
		RET

LOG_2_A:	LD	D,A
		RLA
		SBC	A,A
		LD	E,A
		LD	C,A
		XOR	A
		LD	B,A
		CALL	STK_STORE
		RST	#28			;FP_CALC
		DB	#34			;STK_DATA
		DB	#EF			;Exponent
		DB	#1A			;
		DB	#20			;
		DB	#9A			;
		DB	#85			;
		DB	#04			;MULTIPLY
		DB	#27			;INT
		DB	#38			;END_CALC

; Floating point to A
FP_TO_A:	CALL	FP_TO_BC
		RET	C
		PUSH	AF
		DEC	B
		INC	B
		JR	Z,FP_A_END
		POP	AF
		SCF
		RET

FP_A_END:	POP	AF
		RET

; Print a floating point number
PRINT_FP:	RST	#28		;FP_CALC
		DB	#31		;DUPLICATE
		DB	#36		;LESS_0
		DB	#00		;JUMP_TRUE
		DB	#0B		;to PF_NEGTVE
		DB	#31		;DUPLICATE
		DB	#37		;GREATER_0
		DB	#00		;JUMP_TRUE
		DB	#0D		;to PS_POSTVE
		DB	#02		;DELETE
		DB	#38		;END_CALC
		LD	A,#30
		RST	#10
		RET

PF_NEGTVE:	DB	#2A		;ABS
		DB	#38		;END_CALC
		LD	A,#2D
		RST	#10
		RST	#28		;FP_CALC
PF_POSTVE:	DB	#A0		;STK_ZERO
		DB	#C3		;ST_MEM_3
		DB	#C4		;ST_MEM_4
		DB	#C5		;ST_MEM_5
		DB	#02		;DELETE
		DB	#38		;END_CALC
		EXX
		PUSH	HL
		EXX
PF_LOOP:	RST	#28		;FP_CALC
		DB	#31		;DUPLICATE
		DB	#27		;INT
		DB	#C2		;ST_MEM_2
		DB	#03		;SUBTRACT
		DB	#E2		;GET_MEM_2
		DB	#01		;EXCHANGE
		DB	#C2		;ST_MEM_2
		DB	#02		;DELETE
		DB	#38		;END_CALC
		LD	A,(HL)
		AND	A
		JR	NZ,PF_LARGE
		CALL	INT_FETCH
		LD	B,#10
		LD	A,D
		AND	A
		JR	NZ,PF_SAVE
		OR	E
		JR	Z,PF_SMALL
		LD	D,E
		LD	B,#08
PF_SAVE:	PUSH	DE
		EXX
		POP	DE
		EXX
		JR	PF_BITS

PF_SMALL:	RST	#28		;FP_CALC
		DB	#E2		;GET_MEM_2
		DB	#38		;END_CALC
		LD	A,(HL)
		SUB	#7E
		CALL	LOG_2_A
		LD	D,A
		LD	A,(#5CAC)
		SUB	D
		LD	(#5CAC),A
		LD	A,D
		CALL	E_TO_FP
		RST	#28		;FP_CALC
		DB	#31		;DUPLICATE
		DB	#27		;21
		DB	#C1		;ST_MEM_1
		DB	#03		;SUBTRACT
		DB	#E1		;GET_MEM_1
		DB	#38		;END_CALC
		CALL	FP_TO_A
		PUSH	HL
		LD	(#5CA1),A
		DEC	A
		RLA
		SBC	A,A
		INC	A
		LD	HL,#5CAB
		LD	(HL),A
		INC	HL
		ADD	A,(HL)
		LD	(HL),A
		POP	HL
		JP	PF_FRACTN

PF_LARGE:	SUB	#80
		CP	#1C
		JR	C,PF_MEDIUM
		CALL	LOG_2_A
		SUB	#07
		LD	B,A
		LD	HL,#5CAC
		ADD	A,(HL)
		LD	(HL),A
		LD	A,B
		NEG
		CALL	E_TO_FP
		JR	PF_LOOP

PF_MEDIUM:	EX	DE,HL
		CALL	FETCH_TWO
		EXX
		SET	7,D
		LD	A,L
		EXX
		SUB	#80
		LD	B,A
PF_BITS:	SLA	E
		RL	D
		EXX
		RL	E
		RL	D
		EXX
		LD	HL,#5CAA
		LD	C,#05
PF_BYTES:	LD	A,(HL)
		ADC	A,A
		DAA
		LD	(HL),A
		DEC	HL
		DEC	C
		JR	NZ,PF_BYTES
		DJNZ	PF_BITS
		XOR	A
		LD	HL,#5CA6
		LD	DE,#5CA1
		LD	B,#09
		RLD
		LD	C,#FF
PF_DIGITS:	RLD
		JR	NZ,PF_INSERT
		DEC	C
		INC	C
		JR	NZ,PF_TEST_2
PF_INSERT:	LD	(DE),A
		INC	DE
		INC	(IY+#71)
		INC	(IY+#72)
		LD	C,#00
PF_TEST_2:	BIT	0,B
		JR	Z,PF_ALL_9
		INC	HL
PF_ALL_9:	DJNZ	PF_DIGITS
		LD	A,(#5CAB)
		SUB	#09
		JR	C,PF_MORE
		DEC	(IY+#71)
		LD	A,#04
		CP	(IY+#6F)
		JR	PF_ROUND

PF_MORE:	RST	#28			;FP_CALC
		DB	#02			;DELETE
		DB	#E2			;GET_MEM_2
		DB	#38			;END_CALC

PF_FRACTN:	EX	DE,HL
		CALL	FETCH_TWO
		EXX
		LD	A,#80
		SUB	L
		LD	L,#00
		SET	7,D
		EXX
		CALL	SHIFT_FP
PF_FRN_LP:	LD	A,(IY+#71)
		CP	#08
		JR	C,PF_FR_DGT
		EXX
		RL	D
		EXX
		JR	PF_ROUND

PF_FR_DGT:	LD	BC,#0200
PF_FR_EXX:	LD	A,E
		CALL	CA_10_A_C
		LD	E,A
		LD	A,D
		CALL	CA_10_A_C
		LD	D,A
		PUSH	BC
		EXX
		POP	BC
		DJNZ	PF_FR_EXX
		LD	HL,#5CA1
		LD	A,C
		LD	C,(IY+#71)
		ADD	HL,BC
		LD	(HL),A
		INC	(IY+#71)
		JR	PF_FRN_LP

PF_ROUND:	PUSH	AF
		LD	HL,#5CA1
		LD	C,(IY+#71)
		LD	B,#00
		ADD	HL,BC
		LD	B,C
		POP	AF
PF_RND_LP:	DEC	HL
		LD	A,(HL)
		ADC	A,#00
		LD	(HL),A
		AND	A
		JR	Z,PF_R_BACK
		CP	#0A
		CCF
		JR	NC,PF_COUNT
PF_R_BACK:	DJNZ	PF_RND_LP
		LD	(HL),#01
		INC	B
		INC	(IY+#72)
PF_COUNT:	LD	(IY+#71),B
		RST	#28			;FP_CALC
		DB	#02			;DELETE
		DB	#38			;END_CALC
		EXX
		POP	HL
		EXX
		LD	BC,(#5CAB)
		LD	HL,#5CA1
		LD	A,B
		CP	#09
		JR	C,PF_NOT_E
		CP	#FC
		JR	C,PF_E_FRMT
PF_NOT_E:	AND	A
		CALL	Z,OUT_CODE
PF_E_SBRN:	XOR	A
		SUB	B
		JP	M,PF_OUT_LP
		LD	B,A
		JR	PF_DC_OUT

PF_OUT_LP:	LD	A,C
		AND	A
		JR	Z,PF_OUT_DT
		LD	A,(HL)
		INC	HL
		DEC	C
PF_OUT_DT:	CALL	OUT_CODE
		DJNZ	PF_OUT_LP
PF_DC_OUT:	LD	A,C
		AND	A
		RET	Z
		INC	B
		LD	A,#2E
PF_DEC_0:	RST	#10
		LD	A,#30
		DJNZ	PF_DEC_0
		LD	B,C
		JR	PF_OUT_LP

PF_E_FRMT:	LD	D,B
		DEC	D
		LD	B,#01
		CALL	PF_E_SBRN
		LD	A,#45
		RST	#10
		LD	C,D
		LD	A,C
		AND	A
		JP	P,PF_E_POS
		NEG
		LD	C,A
		LD	A,#2D
		JR	PF_E_SIGN

PF_E_POS:	LD	A,#2B
PF_E_SIGN:	RST	#10
		LD	B,#00
		JP	OUT_NUM_1

; Handle printing of floating point
CA_10_A_C:	PUSH	DE
		LD	L,A
		LD	H,#00
		LD	E,L
		LD	D,H
		ADD	HL,HL
		ADD	HL,HL
		ADD	HL,DE
		ADD	HL,HL
		LD	E,C
		ADD	HL,DE
		LD	C,H
		LD	A,L
		POP	DE
		RET

; Prepare the two numbers for addition
PREP_ADD:	LD	A,(HL)
		LD	(HL),#00
		AND	A
		RET	Z
		INC	HL
		BIT	7,(HL)
		SET	7,(HL)
		DEC	HL
		RET	Z
		PUSH	BC
		LD	BC,#0005
		ADD	HL,BC
		LD	B,C
		LD	C,A
		SCF
NEG_BYTE:	DEC	HL
		LD	A,(HL)
		CPL
		ADC	A,#00
		LD	(HL),A
		DJNZ	NEG_BYTE
		LD	A,C
		POP	BC
		RET

; Fetch two numbers
FETCH_TWO:	PUSH	HL
		PUSH	AF
		LD	C,(HL)
		INC	HL
		LD	B,(HL)
		LD	(HL),A
		INC	HL
		LD	A,C
		LD	C,(HL)
		PUSH	BC
		INC	HL
		LD	C,(HL)
		INC	HL
		LD	B,(HL)
		EX	DE,HL
		LD	D,A
		LD	E,(HL)
		PUSH	DE
		INC	HL
		LD	D,(HL)
		INC	HL
		LD	E,(HL)
		PUSH	DE
		EXX
		POP	DE
		POP	HL
		POP	BC
		EXX
		INC	HL
		LD	D,(HL)
		INC	HL
		LD	E,(HL)
		POP	AF
		POP	HL
		RET

; Shift floating point numer to right
SHIFT_FP:	AND	A
		RET	Z
		CP	#21
		JR	NC,ADDEND_0
		PUSH	BC
		LD	B,A
ONE_SHIFT:	EXX
		SRA	L
		RR	D
		RR	E
		EXX
		RR	D
		RR	E
		DJNZ	ONE_SHIFT
		POP	BC
		RET	NC
		CALL	ADD_BACK
		RET	NZ
ADDEND_0:	EXX
		XOR	A
ZEROS_4_5:	LD	L,#00
		LD	D,A
		LD	E,L
		EXX
		LD	DE,#0000
		RET

; Add back any carry
ADD_BACK:	INC	E
		RET	NZ
		INC	D
		RET	NZ
		EXX
		INC	E
		JR	NZ,ALL_ADDED
		INC	D
ALL_ADDED:	EXX
		RET

; Handle subtraction
SUBTRACT:	EX	DE,HL
		CALL	NEGATE
		EX	DE,HL

; Handle Addition
ADDITION:	LD	A,(DE)
		OR	(HL)
		JR	NZ,FULL_ADDN
		PUSH	DE
		INC	HL
		PUSH	HL
		INC	HL
		LD	E,(HL)
		INC	HL
		LD	D,(HL)
		INC	HL
		INC	HL
		INC	HL
		LD	A,(HL)
		INC	HL
		LD	C,(HL)
		INC	HL
		LD	B,(HL)
		POP	HL
		EX	DE,HL
		ADD	HL,BC
		EX	DE,HL
		ADC	A,(HL)
		RRCA
		ADC	A,#00
		CALL	E65536
		LD	(HL),A
		INC	HL
		LD	(HL),E
		INC	HL
		LD	(HL),D
		DEC	HL
		DEC	HL
		DEC	HL
		POP	DE
		RET

ADDN_OFLW:	DEC	HL
		POP	DE
FULL_ADDN:	CALL	RE_ST_TWO
		EXX
		PUSH	HL
		EXX
		PUSH	DE
		PUSH	HL
		CALL	PREP_ADD
		LD	B,A
		EX	DE,HL
		CALL	PREP_ADD
		LD	C,A
		CP	B
		JR	NC,SHIFT_LEN
		LD	A,B
		LD	B,C
		EX	DE,HL
SHIFT_LEN:	PUSH	AF
		SUB	B
		CALL	FETCH_TWO
		CALL	SHIFT_FP
		POP	AF
		POP	HL
		LD	(HL),A
		PUSH	HL
		LD	L,B
		LD	H,C
		ADD	HL,DE
		EXX
		EX	DE,HL
		ADC	HL,BC
		EX	DE,HL
		LD	A,H
		ADC	A,L
		LD	L,A
		RRA
		XOR	L
		EXX
		EX	DE,HL
		POP	HL
		RRA
		JR	NC,TEST_NEG
		LD	A,#01
		CALL	SHIFT_FP
		INC	(HL)
		JR	Z,ADD_REP_6
TEST_NEG:	EXX
		LD	A,L
		AND	#80
		EXX
		INC	HL
		LD	(HL),A
		DEC	HL
		JR	Z,GO_NC_MLT
		LD	A,E
		NEG
		CCF
		LD	E,A
		LD	A,D
		CPL
		ADC	A,#00
		LD	D,A
		EXX
		LD	A,E
		CPL
		ADC	A,#00
		LD	E,A
		LD	A,D
		CPL
		ADC	A,#00
		JR	NC,END_COMPL
		RRA
		EXX
		INC	(HL)
ADD_REP_6:	JP	Z,REPORT_6
		EXX
END_COMPL:	LD	D,A
		EXX
GO_NC_MLT:	XOR	A
		JP	TEST_NORM

; HL - HL * DE
HL_HL_DE:	PUSH	BC
		LD	B,#10
		LD	A,H
		LD	C,L
		LD	HL,#0000
HL_LOOP:	ADD	HL,HL
		JR	C,HL_END
		RL	C
		RLA
		JR	NC,HL_AGAIN
		ADD	HL,DE
		JR	C,HL_END
HL_AGAIN:	DJNZ	HL_LOOP
HL_END:		POP	BC
		RET

; Prepare to multiply or divide
PREP_M_D:	CALL	TEST_ZERO
		RET	C
		INC	HL
		XOR	(HL)
		SET	7,(HL)
		DEC	HL
		RET

; Handle multiplication
MULTIPLY:	LD	A,(DE)
		OR	(HL)
		JR	NZ,MULT_LONG
		PUSH	DE
		PUSH	HL
		PUSH	DE
		CALL	INT_FETCH
		EX	DE,HL
		EX	(SP),HL
		LD	B,C
		CALL	INT_FETCH
		LD	A,B
		XOR	C
		LD	C,A
		POP	HL
		CALL	HL_HL_DE
		EX	DE,HL
		POP	HL
		JR	C,MULT_OFLW
		LD	A,D
		OR	E
		JR	NZ,MULT_RSLT
		LD	C,A
MULT_RSLT:	CALL	INT_STORE
		POP	DE
		RET

MULT_OFLW:	POP	DE
MULT_LONG:	CALL	RE_ST_TWO
		XOR	A
		CALL	PREP_M_D
		RET	C
		EXX
		PUSH	HL
		EXX
		PUSH	DE
		EX	DE,HL
		CALL	PREP_M_D
		EX	DE,HL
		JR	C,ZERO_RSLT
		PUSH	HL
		CALL	FETCH_TWO
		LD	A,B
		AND	A
		SBC	HL,HL
		EXX
		PUSH	HL
		SBC	HL,HL
		EXX
		LD	B,#21
		JR	STRT_MLT

MLT_LOOP:	JR	NC,NO_ADD
		ADD	HL,DE
		EXX
		ADC	HL,DE
		EXX
NO_ADD:		EXX
		RR	H
		RR	L
		EXX
		RR	H
		RR	L
STRT_MLT:	EXX
		RR	B
		RR	C
		EXX
		RR	C
		RRA
		DJNZ	MLT_LOOP
		EX	DE,HL
		EXX
		EX	DE,HL
		EXX
		POP	BC
		POP	HL
		LD	A,B
		ADD	A,C
		JR	NZ,MAKE_EXPT
		AND	A
MAKE_EXPT:	DEC	A
		CCF
DIVN_EXPT:	RLA
		CCF
		RRA
		JP	P,OFLW1_CLR
		JR	NC,REPORT_6
		AND	A
OFLW1_CLR:	INC	A
		JR	NZ,OFLW2_CLR
		JR	C,OFLW2_CLR
		EXX
		BIT	7,D
		EXX
		JR	NZ,REPORT_6
OFLW2_CLR	LD	(HL),A
		EXX
		LD	A,B
		EXX
TEST_NORM:	JR	NC,NORMALISE
		LD	A,(HL)
		AND	A
NEAR_ZERO:	LD	A,#80
		JR	Z,SKIP_ZERO
ZERO_RSLT:	XOR	A
SKIP_ZERO:	EXX
		AND	D
		CALL	ZEROS_4_5
		RLCA
		LD	(HL),A
		JR	C,OFLOW_CLR
		INC	HL
		LD	(HL),A
		DEC	HL
		JR	OFLOW_CLR

NORMALISE:	LD	B,#20
SHIFT_ONE:	EXX
		BIT	7,D
		EXX
		JR	NZ,NORML_NOW
		RLCA
		RL	E
		RL	D
		EXX
		RL	E
		RL	D
		EXX
		DEC	(HL)
		JR	Z,NEAR_ZERO
		DJNZ	SHIFT_ONE
		JR	ZERO_RSLT

NORML_NOW:	RLA
		JR	NC,OFLOW_CLR
		CALL	ADD_BACK
		JR	NZ,OFLOW_CLR
		EXX
		LD	D,#80
		EXX
		INC	(HL)
		JR	Z,REPORT_6
OFLOW_CLR:	PUSH	HL
		INC	HL
		EXX
		PUSH	DE
		EXX
		POP	BC
		LD	A,B
		RLA
		RL	(HL)
		RRA
		LD	(HL),A
		INC	HL
		LD	(HL),C
		INC	HL
		LD	(HL),D
		INC	HL
		LD	(HL),E
		POP	HL
		POP	DE
		EXX
		POP	HL
		EXX
		RET

REPORT_6:	RST	#08			; Error report
		DB	#05			; Number too big

; Handle division
DIVISION:	CALL	RE_ST_TWO
		EX	DE,HL
		XOR	A
		CALL	PREP_M_D
		JR	C,REPORT_6
		EX	DE,HL
		CALL	PREP_M_D
		RET	C
		EXX
		PUSH	HL
		EXX
		PUSH	DE
		PUSH	HL
		CALL	FETCH_TWO
		EXX
		PUSH	HL
		LD	H,B
		LD	L,C
		EXX
		LD	H,C
		LD	L,B
		XOR	A
		LD	B,#DF
		JR	DIV_START

DIV_LOOP:	RLA
		RL	C
		EXX
		RL	C
		RL	B
		EXX
DIV_34TH:	ADD	HL,HL
		EXX
		ADC	HL,HL
		EXX
		JR	C,SUBN_ONLY
DIV_START:	SBC	HL,DE
		EXX
		SBC	HL,DE
		EXX
		JR	NC,NO_RSTORE
		ADD	HL,DE
		EXX
		ADC	HL,DE
		EXX
		AND	A
		JR	COUNT_ONE

SUBN_ONLY:	AND	A
		SBC	HL,DE
		EXX
		SBC	HL,DE
		EXX
NO_RSTORE:	SCF
COUNT_ONE:	INC	B
		JP	M,DIV_LOOP
		PUSH	AF
		JR	Z,DIV_34TH		; BSROM - bugfix - was DIV_START
		LD	E,A
		LD	D,C
		EXX
		LD	E,C
		LD	D,B
		POP	AF
		RR	B
		POP	AF
		RR	B
		EXX
		POP	BC
		POP	HL
		LD	A,B
		SUB	C
		JP	DIVN_EXPT

; Integer truncation towards zero
TRUNCATE:	LD	A,(HL)
		AND	A
		RET	Z
		CP	#81
		JR	NC,T_GR_ZERO		; BSROM - bugfixed INT
		LD	(HL),#00
		LD	A,#20
		JR	NIL_BYTES

E65536:		JR	NZ,S65536
		SBC	A,A
		LD	C,A
		INC	A
		OR	D
		OR	E
		LD	A,C
		RET	NZ
S65536:		POP	AF
		JP	ADDN_OFLW

NEW_CHR:	CALL	FP_TO_A			; BSROM - bugfixed CHR$
		RET	C
		RET	Z
		POP	AF
		LD	DE,#0001
		LD	BC,#FFFF
		JP	CHR_DLR1

T_GR_ZERO:	CP	#91			; BSROM - modified INT
T_SMALL:	JR	NC,X_LARGE
		PUSH	DE
		CPL
		ADD	A,#91
		INC	HL
		LD	D,(HL)
		INC	HL
		LD	E,(HL)
		DEC	HL
		DEC	HL
		LD	C,#00
		BIT	7,D
		JR	Z,T_NUMERIC
		DEC	C
T_NUMERIC:	SET	7,D
		LD	B,#08
		SUB	B
		ADD	A,B
		JR	C,T_TEST
		LD	E,D
		LD	D,#00
		SUB	B
T_TEST:		JR	Z,T_STORE
		LD	B,A
T_SHIFT:	SRL	D
		RR	E
		DJNZ	T_SHIFT
T_STORE:	CALL	INT_STORE
		POP	DE
		RET

T_EXPNENT:	LD	A,(HL)
X_LARGE:	SUB	#A0
		RET	P
		NEG
NIL_BYTES:	PUSH	DE
		EX	DE,HL
		DEC	HL
		LD	B,A
		SRL	B
		SRL	B
		SRL	B
		JR	Z,BITS_ZERO
BYTE_ZERO:	LD	(HL),#00
		DEC	HL
		DJNZ	BYTE_ZERO
BITS_ZERO:	AND	#07
		JR	Z,IX_END
		LD	B,A
		LD	A,#FF
LESS_MASK:	SLA	A
		DJNZ	LESS_MASK
		AND	(HL)
		LD	(HL),A
IX_END:		EX	DE,HL
		POP	DE
		RET

; Re-stack two numbers in full floating point
RE_ST_TWO:	CALL	RESTK_SUB
RESTK_SUB:	EX	DE,HL

; Re-stack number in full form
RE_STACK:	LD	A,(HL)
		AND	A
		RET	NZ
		PUSH	DE
		CALL	INT_FETCH
		XOR	A
		INC	HL
		LD	(HL),A
		DEC	HL
		LD	(HL),A
		LD	B,#91
		LD	A,D
		AND	A
		JR	NZ,RS_NRMLSE
		OR	E
		LD	B,D
		JR	Z,RS_STORE
		LD	D,E
		LD	E,B
		LD	B,#89
RS_NRMLSE:	EX	DE,HL
RSTK_LOOP:	DEC	B
		ADD	HL,HL
		JR	NC,RSTK_LOOP
		RRC	C
		RR	H
		RR	L
		EX	DE,HL
RS_STORE:	DEC	HL
		LD	(HL),E
		DEC	HL
		LD	(HL),D
		DEC	HL
		LD	(HL),B
		POP	DE
		RET

; Floating point calculator
; Table of constants
STK_ZERO:	DB	#00
		DB	#B0
		DB	#00

STK_ONE:	DB	#40
		DB	#B0
		DB	#00
		DB	#01

STK_HALF:	DB	#30
		DB	#00
	
STK_PI_2:	DB	#F1
		DB	#49
		DB	#0F
		DB	#DA
		DB	#A2
	
STK_TEN:	DB	#40
		DB	#B0
		DB	#00
		DB	#0A

; Floating point calculator
; Table of addresses
TBL_ADDRS:	DW	JUMP_TRUE
		DW	EXCHANGE
		DW	DELETE
		DW	SUBTRACT
		DW	MULTIPLY
		DW	DIVISION
		DW	TO_POWER
		DW	OR_FUNC
		DW	NO_AND_NO
		DW	NO_L_EQL
		DW	NO_GR_EQL
		DW	NOS_NEQL
		DW	NO_GRTR
		DW	NO_LESS
		DW	NOS_EQL
		DW	ADDITION
		DW	STR_AND_NO
		DW	STR_L_EQL
		DW	STR_GR_EQL
		DW	STRS_NEQL
		DW	STR_GRTR
		DW	STR_LESS
		DW	STRS_EQL
		DW	STRS_ADD
		DW	VAL_DLR
		DW	USR_STR
		DW	READ_IN
		DW	NEGATE
		DW	CODE
		DW	VAL
		DW	LEN
		DW	SIN_FUNC
		DW	COS_FUNC
		DW	TAN_FUNC
		DW	ASN_FUNC
		DW	ACS_FUNC
		DW	ATN_FUNC
		DW	LN
		DW	EXP
		DW	INT
		DW	SQR_FUNC
		DW	SGN
		DW	@ABS
		DW	PEEK
		DW	IN_FUNC
		DW	USR_NO
		DW	STR_DLR
		DW	CHR_DLR
		DW	NOT_FUNC
		DW	DUPLICATE
		DW	N_MOD_M
		DW	JUMP
		DW	STK_DATA
		DW	DEC_JR_NZ
		DW	LESS_0
		DW	GREATER_0
		DW	END_CALC
		DW	GET_ARGT
		DW	TRUNCATE
		DW	FP_CALC_2
		DW	E_TO_FP
		DW	RE_STACK
		DW	SERIES_XX
		DW	STK_CONST_XX
		DW	ST_MEM_XX
		DW	GET_MEM_XX

; The Calculator
CALCULATE:	CALL	STK_PNTRS
GEN_ENT_1:	LD	A,B
		LD	(#5C67),A
GEN_ENT_2:	EXX
		EX	(SP),HL
		EXX
RE_ENTRY:	LD	(#5C65),DE
		EXX
		LD	A,(HL)
		INC	HL
SCAN_ENT:	PUSH	HL
		AND	A
		JP	P,FIRST_3D
		LD	D,A
		AND	#60
		RRCA
		RRCA
		RRCA
		RRCA
		ADD	A,#7C
		LD	L,A
		LD	A,D
		AND	#1F
		JR	ENT_TABLE

FIRST_3D:	CP	#18
		JR	NC,DOUBLE_A
		EXX
		LD	BC,#FFFB
		LD	D,H
		LD	E,L
		ADD	HL,BC
		EXX
DOUBLE_A:	RLCA
		LD	L,A
ENT_TABLE:	LD	DE,TBL_ADDRS
		LD	H,#00
		ADD	HL,DE
		LD	E,(HL)
		INC	HL
		LD	D,(HL)
		LD	HL,RE_ENTRY
		EX	(SP),HL
		PUSH	DE
		EXX
		LD	BC,(#5C66)

; Handle DELETE		
DELETE:		RET

; Single operation
FP_CALC_2:	POP	AF
		LD	A,(#5C67)
		EXX
		JR	SCAN_ENT

; Test that there is enough space between the calc stack and the machine stack
TEST_5_SP:	PUSH	DE
		PUSH	HL
		LD	BC,#0005
		CALL	TEST_ROOM
		POP	HL
		POP	DE
		RET

; Stack floating point number, numeric variable value or an entry in the BEEP's semi-tone table
STACK_NUM:	LD	DE,(#5C65)
		CALL	MOVE_FP
		LD	(#5C65),DE
		RET

; Move a floating point number
DUPLICATE:
MOVE_FP:	CALL	TEST_5_SP
		LDIR
		RET

; Stack literals
STK_DATA:	LD	H,D
		LD	L,E
STK_CONST:	CALL	TEST_5_SP
		EXX
		PUSH	HL
		EXX
		EX	(SP),HL
		PUSH	BC
		LD	A,(HL)
		AND	#C0
		RLCA
		RLCA
		LD	C,A
		INC	C
		LD	A,(HL)
		AND	#3F
		JR	NZ,FORM_EXP
		INC	HL
		LD	A,(HL)
FORM_EXP:	ADD	A,#50
		LD	(DE),A
		LD	A,#05
		SUB	C
		INC	HL
		INC	DE
		LD	B,#00
		LDIR
		POP	BC
		EX	(SP),HL
		EXX
		POP	HL
		EXX
		LD	B,A
		XOR	A
STK_ZEROS:	DEC	B
		RET	Z
		LD	(DE),A
		INC	DE
		JR	STK_ZEROS

; Skip constants
SKIP_CONS:	AND	A
SKIP_NEXT:	RET	Z
		PUSH	AF
		PUSH	DE
		CALL	NO_RW_AT0		; BSROM - fix for rewriting first bytes of ROM
		CALL	STK_CONST
		POP	DE
		POP	AF
		DEC	A
		JR	SKIP_NEXT

; Calculate memory location
LOC_MEM:	LD	C,A
		RLCA
		RLCA
		ADD	A,C
		LD	C,A
		LD	B,#00
		ADD	HL,BC
		RET

; Get from memory area
GET_MEM_XX:	PUSH	DE
		LD	HL,(#5C68)
		CALL	LOC_MEM
		CALL	MOVE_FP
		POP	HL
		RET

; Stack a constant
STK_CONST_XX:	LD	H,D
		LD	L,E
		EXX
		PUSH	HL
		LD	HL,STK_ZERO
		EXX
		CALL	SKIP_CONS
		CALL	STK_CONST
		EXX
		POP	HL
		EXX
		RET

; Store in a memory area
ST_MEM_XX:	PUSH	HL
		EX	DE,HL
		LD	HL,(#5C68)
		CALL	LOC_MEM
		EX	DE,HL
		CALL	MOVE_FP
		EX	DE,HL
		POP	HL
		RET

; Swap first number with second number
EXCHANGE:	LD	B,#05
SWAP_BYTE:	LD	A,(DE)
		LD	C,(HL)
		EX	DE,HL
		LD	(DE),A
		LD	(HL),C
		INC	HL
		INC	DE
		DJNZ	SWAP_BYTE
		EX	DE,HL
		RET

; Series generator
SERIES_XX:	LD	B,A
		CALL	GEN_ENT_1
		DB	#31			;DUPLICATE
		DB	#0F			;ADDITION
		DB	#C0			;ST_MEM_0
		DB	#02			;DELETE
		DB	#A0			;STK_ZERO
		DB	#C2			;ST_MEM_2
G_LOOP:		DB	#31			;DUPLICATE
		DB	#E0			;GET_MEM_0
		DB	#04			;MULTIPLY
		DB	#E2			;GET_MEM_2
		DB	#C1			;ST_MEM_1
		DB	#03			;SUBTRACT
		DB	#38			;END_CALC
		CALL	STK_DATA
		CALL	GEN_ENT_2
		DB	#0F			;ADDITION
		DB	#01			;EXCHANGE
		DB	#C2			;ST_MEM_2
		DB	#02			;DELETE
		DB	#35			;DEC_JR_NZ
		DB	#EE			;back to G_LOOP
		DB	#E1			;GET_MEM_1
		DB	#03			;SUBTRACT
		DB	#38			;END_CALC
		RET

; Find the absolute value of the last value, integer or floating point on the calc stack
ABS:		LD	B,#FF
		JR	NEG_TEST

; Handle unary minus
NEGATE:		CALL	TEST_ZERO
		RET	C
		LD	B,#00
NEG_TEST:	LD	A,(HL)
		AND	A
		JR	Z,INT_CASE
		INC	HL
		LD	A,B
		AND	#80
		OR	(HL)
		RLA
		CCF
		RRA
		LD	(HL),A
		DEC	HL
		RET

INT_CASE:	PUSH	DE
		PUSH	HL
		CALL	INT_FETCH
		POP	HL
		LD	A,B
		OR	C
		CPL
		LD	C,A
		CALL	INT_STORE
		POP	DE
		RET

; Signum
SGN:		CALL	TEST_ZERO
		RET	C
		PUSH	DE
		LD	DE,#0001
		INC	HL
		RL	(HL)
		DEC	HL
		SBC	A,A
		LD	C,A
		CALL	INT_STORE
		POP	DE
		RET

; Handle IN function
IN_FUNC:	CALL	FIND_INT2
		IN	A,(C)
		JR	IN_PK_STK

; Handle PEEK function
PEEK:		CALL	FIND_INT2
		LD	A,(BC)
IN_PK_STK:	JP	STACK_A

; Handle USR number
USR_NO:		CALL	FIND_INT2
		LD	HL,STACK_BC
		PUSH	HL
		PUSH	BC
		RET

; Handle USR string
USR_STR:	CALL	STK_FETCH
		DEC	BC
		LD	A,B
		OR	C
		JR	NZ,REPORT_A
		LD	A,(DE)
		CALL	ALPHA
		JR	C,USR_RANGE
		SUB	#90
		JR	C,REPORT_A
		CP	#15
		JR	NC,REPORT_A
		INC	A
USR_RANGE:	DEC	A
		ADD	A,A
		ADD	A,A
		ADD	A,A
		CP	#A8
		JR	NC,REPORT_A
		LD	BC,(#5C7B)
		ADD	A,C
		LD	C,A
		JR	NC,USR_STACK
		INC	B
USR_STACK:	JP	STACK_BC

REPORT_A:	RST	#08			; Error report
		DB	#09			; Invalid argument

; Test if top value on calc stack is zero
TEST_ZERO:	PUSH	HL
		PUSH	BC
		LD	B,A
		LD	A,(HL)
		INC	HL
		OR	(HL)
		INC	HL
		OR	(HL)
		INC	HL
		OR	(HL)
		LD	A,B
		POP	BC
		POP	HL
		RET	NZ
		SCF
		RET

; Test if the last value on calc stack is greater than zero
GREATER_0:	CALL	TEST_ZERO
		RET	C
		LD	A,#FF
		JR	SIGN_TO_C

; Handle NOT operator
NOT_FUNC:	CALL	TEST_ZERO
		JR	FP_0_1

; Test if the last value on calc stack is less than zero
LESS_0:		XOR	A
SIGN_TO_C:	INC	HL
		XOR	(HL)
		DEC	HL
		RLCA

; Place an iteger value zero or one at the calc stack or memory area
FP_0_1:		PUSH	HL
		LD	A,#00
		LD	(HL),A
		INC	HL
		LD	(HL),A
		INC	HL
		RLA
		LD	(HL),A
		RRA
		INC	HL
		LD	(HL),A
		INC	HL
		LD	(HL),A
		POP	HL
		RET

; Handle OR operator
OR_FUNC:	EX	DE,HL
		CALL	TEST_ZERO
		EX	DE,HL
		RET	C
		SCF
		JR	FP_0_1

; Handle number AND number
NO_AND_NO:	EX	DE,HL
		CALL	TEST_ZERO
		EX	DE,HL
		RET	NC
		AND	A
		JR	FP_0_1

; Handle string AND number
STR_AND_NO:	EX	DE,HL
		CALL	TEST_ZERO
		EX	DE,HL
		RET	NC
		PUSH	DE
		DEC	DE
		XOR	A
		LD	(DE),A
		DEC	DE
		LD	(DE),A
		POP	DE
		RET

; Perform numeric or string comparison
NO_L_EQL:
NO_GR_EQL:
NOS_NEQL:
NO_GRTR:
NO_LESS:
NOS_EQL:
STR_L_EQL:
STR_GR_EQL:
STRS_NEQL:
STR_GRTR:
STR_LESS:
STRS_EQL:	LD	A,B
		SUB	#08
		BIT	2,A
		JR	NZ,EX_OR_NOT
		DEC	A
EX_OR_NOT:	RRCA
		JR	NC,NU_OR_STR
		PUSH	AF
		PUSH	HL
		CALL	EXCHANGE
		POP	DE
		EX	DE,HL
		POP	AF
NU_OR_STR:	BIT	2,A
		JR	NZ,STRINGS
		RRCA
		PUSH	AF
		CALL	SUBTRACT
		JR	END_TESTS

STRINGS:	RRCA
		PUSH	AF
		CALL	STK_FETCH
		PUSH	DE
		PUSH	BC
		CALL	STK_FETCH
		POP	HL
BYTE_COMP:	LD	A,H
		OR	L
		EX	(SP),HL
		LD	A,B
		JR	NZ,SEC_PLUS
		OR	C
SECND_LOW:	POP	BC
		JR	Z,BOTH_NULL
		POP	AF
		CCF
		JR	STR_TEST

BOTH_NULL:	POP	AF
		JR	STR_TEST

SEC_PLUS:	OR	C
		JR	Z,FRST_LESS
		LD	A,(DE)
		SUB	(HL)
		JR	C,FRST_LESS
		JR	NZ,SECND_LOW
		DEC	BC
		INC	DE
		INC	HL
		EX	(SP),HL
		DEC	HL
		JR	BYTE_COMP

FRST_LESS:	POP	BC
		POP	AF
		AND	A
STR_TEST:	PUSH	AF
		RST	#28			;FP_CALC
		DB	#A0			;STK_ZERO
		DB	#38			;END_CALC

END_TESTS:	POP	AF
		PUSH	AF
		CALL	C,NOT_FUNC
		POP	AF
		PUSH	AF
		CALL	NC,GREATER_0
		POP	AF
		RRCA
		CALL	NC,NOT_FUNC
		RET

; Combine two strings into one
STRS_ADD:	CALL	STK_FETCH
		PUSH	DE
		PUSH	BC
		CALL	STK_FETCH
		POP	HL
		PUSH	HL
		PUSH	DE
		PUSH	BC
		ADD	HL,BC
		LD	B,H
		LD	C,L
		RST	#30
		CALL	STK_STO_D
		POP	BC
		POP	HL
		LD	A,B
		OR	C
		JR	Z,OTHER_STR
		LDIR
OTHER_STR:	POP	BC
		POP	HL
		LD	A,B
		OR	C
		JR	Z,STK_PNTRS
		LDIR

; Check stack pointers
STK_PNTRS:	LD	HL,(#5C65)
		LD	DE,#FFFB
		PUSH	HL
		ADD	HL,DE
		POP	DE
		RET

; Handle CHR$
CHR_DLR:	CALL	NEW_CHR			;BSROM - bugfixed CHR$
		JR	C,REPORT_BD
		JR	NZ,REPORT_BD
		PUSH	AF
		LD	BC,#0001
		RST	#30
		POP	AF
		LD	(DE),A
CHR_DLR1:	CALL	STK_STO_D
		EX	DE,HL
		RET

REPORT_BD:	RST	#08			; Error report
		DB	#0A			; Integer out of range

; Handle VAL and VAL$
VAL:
VAL_DLR:	CALL	VAL2			; BSROM - enhanced VAL & VAL$
		PUSH	HL
		LD	A,B
		ADD	A,#E3
		SBC	A,A
		PUSH	AF
		CALL	STK_FETCH
		PUSH	DE
		INC	BC
		RST	#30
		POP	HL
		LD	(#5C5D),DE
		PUSH	DE
		LDIR
		EX	DE,HL
		DEC	HL
		LD	(HL),#0D
		RES	7,(IY+#01)
		CALL	SCANNING
		RST	#18
		CP	#0D
		JR	NZ,V_RPORT_C
		POP	HL
		POP	AF
		XOR	(IY+#01)
		AND	#40
V_RPORT_C:	JP	NZ,REPORT_C
		LD	(#5C5D),HL
		SET	7,(IY+#01)
		CALL	SCANNING
		POP	HL
		LD	(#5C5D),HL
		JR	STK_PNTRS

; Handle STR$
STR_DLR:	LD	BC,#0001
		RST	#30
		LD	(#5C5B),HL
		PUSH	HL
		LD	HL,(#5C51)
		PUSH	HL
		LD	A,#FF
		CALL	CHAN_OPEN
		CALL	PRINT_FP
		POP	HL
		CALL	CHAN_FLAG
		POP	DE
		LD	HL,(#5C5B)
		AND	A
		SBC	HL,DE
		LD	B,H
		LD	C,L
		CALL	STK_STO_D
		EX	DE,HL
		RET

; Read in for INKEY$
READ_IN:	CALL	FIND_INT1
		CP	#10
		JP	NC,REPORT_BB
		LD	HL,(#5C51)
		PUSH	HL
		CALL	CHAN_OPEN
		CALL	INPUT_AD
		LD	BC,#0000
		JR	NC,R_I_STORE
		INC	C
		RST	#30
		LD	(DE),A
R_I_STORE:	CALL	STK_STO_D
		POP	HL
		CALL	CHAN_FLAG
		JP	STK_PNTRS

; Handle CODE
CODE:		CALL	STK_FETCH
		LD	A,B
		OR	C
		JR	Z,STK_CODE
		LD	A,(DE)
STK_CODE	JP	STACK_A

; Handle LEN
LEN:		CALL	STK_FETCH
		JP	STACK_BC

; Decrease the counter
DEC_JR_NZ:	EXX
		PUSH	HL
		LD	HL,#5C67
		DEC	(HL)
		POP	HL
		JR	NZ,JUMP_2
		INC	HL
		EXX
		RET

; Relative jump
JUMP:		EXX
JUMP_2:		LD	E,(HL)
		LD	A,E
		RLA
		SBC	A,A
		LD	D,A
		ADD	HL,DE
		EXX
		RET

; Jump on true
JUMP_TRUE:	INC	DE
		INC	DE
		LD	A,(DE)
		DEC	DE
		DEC	DE
		AND	A
		JR	NZ,JUMP
		EXX
		INC	HL
		EXX
		RET

; End of calculation
END_CALC:	POP	AF
		EXX
		EX	(SP),HL
		EXX
		RET

; Modulus
N_MOD_M:	RST	#28			;FP_CALC
		DB	#C0			;ST_MEM_0
		DB	#02			;DELETE
		DB	#31			;DUPLICATE
		DB	#E0			;GET_MEM_0
		DB	#05			;DIVISION
		DB	#27			;INT
		DB	#E0			;GET_MEM_0
		DB	#01			;EXCHANGE
		DB	#C0			;ST_MEM_0
		DB	#04			;MULTIPLY
		DB	#03			;SUBTRACT
		DB	#E0			;GET_MEM_0
		DB	#38			;END_CALC
		RET

; Handle INT
INT:		RST	#28			;FP_CALC
		DB	#31			;DUPLICATE
		DB	#36			;LESS_0
		DB	#00			;JUMP_TRUE
		DB	#04			;to X_NEG
		DB	#3A			;TRUNCATE
		DB	#38			;END_CALC
		RET

X_NEG:		DB	#31			;DUPLICATE
		DB	#3A			;TRUNCATE
		DB	#C0			;ST_MEM_0
		DB	#03			;SUBTRACT
		DB	#E0			;GET_MEM_0
		DB	#01			;EXCHANGE
		DB	#30			;NOT
		DB	#00			;JUMP_TRUE
		DB	#03			;to EXIT
		DB	#A1			;STK_ONE
		DB	#03			;SUBTRACT
EXIT:		DB	#38			;END_CALC
		RET

; Exponential
EXP:		RST	#28			;FP_CALC
		DB	#3D			;RE_STACK
		DB	#34			;STK_DATA
		DB	#F1			;Exponent
		DB	#38			;
		DB	#AA			;
		DB	#3B			;
		DB	#29			;
		DB	#04			;MULTIPLY
		DB	#31			;DUPLICATE
		DB	#27			;INT
		DB	#C3			;ST_MEM_3
		DB	#03			;SUBTRACT
		DB	#31			;DUPLICATE
		DB	#0F			;ADDITION
		DB	#A1			;STK_ONE
		DB	#03			;SUBTRACT
		DB	#88			;SERIES_08
		DB	#13			;Exponent
		DB	#36			;
		DB	#58			;Exponent
		DB	#65			;
		DB	#66			;
		DB	#9D			;Exponent
		DB	#78			;
		DB	#65			;
		DB	#40			;
		DB	#A2			;Exponent
		DB	#60			;
		DB	#32			;
		DB	#C9			;
		DB	#E7			;Exponent
		DB	#21			;
		DB	#F7			;
		DB	#AF			;
		DB	#24			;
		DB	#EB			;Exponent
		DB	#2F			;
		DB	#B0			;
		DB	#B0			;
		DB	#14			;
		DB	#EE			;Exponent
		DB	#7E			;
		DB	#BB			;
		DB	#94			;
		DB	#58			;
		DB	#F1			;Exponent
		DB	#3A			;
		DB	#7E			;
		DB	#F8			;
		DB	#CF			;
		DB	#E3			;GET_MEM_3
		DB	#38			;END-CALC
		CALL	FP_TO_A
		JR	NZ,N_NEGTV
		JR	C,REPORT_6B
		ADD	A,(HL)
		JR	NC,RESULT_OK
REPORT_6B:	RST	#08			; Error report
		DB	#05			; Number too big

N_NEGTV:	JR	C,RSLT_ZERO
		SUB	(HL)
		JR	NC,RSLT_ZERO
		NEG
RESULT_OK:	LD	(HL),A
		RET

RSLT_ZERO:	RST	#28			;FP_CALC
		DB	#02			;DELETE
		DB	#A0			;STK_ZERO
		DB	#38			;END_CALC
		RET

; Natural logarithm
LN:		RST	#28			;FP_CALC
		DB	#3D			;RE_STACK
		DB	#31			;DUPLICATE
		DB	#37			;GREATER_0
		DB	#00			;JUMP_TRUE
		DB	#04			;to VALID
		DB	#38			;END_CALC

REPORT_AB:	RST	#08			; Error report
		DB	#09			; Invalid argument

VALID:		DB	#A0			;STK_ZERO
		DB	#02			;DELETE
		DB	#38			;END_CALC
		LD	A,(HL)
		LD	(HL),#80
		CALL	STACK_A
		RST	#28			;FP_CALC
		DB	#34			;STK_DATA
		DB	#38			;Exponent
		DB	#00			;
		DB	#03			;SUBTRACT
		DB	#01			;EXCHANGE
		DB	#31			;DUPLICATE
		DB	#34			;STK_DATA
		DB	#F0			;Exponent
		DB	#4C			;
		DB	#CC			;
		DB	#CC			;
		DB	#CD			;
		DB	#03			;SUBTRACT
		DB	#37			;GREATER_0
		DB	#00			;JUMP_TURE
		DB	#08			;to GRE_8
		DB	#01			;EXCHANGE
		DB	#A1			;STK_ONE
		DB	#03			;SUBTRACT
		DB	#01			;EXCHANGE
		DB	#38			;END_CALC
		INC	(HL)
		RST	#28			;FP_CALC
GRE_8:		DB	#01			;EXCHANGE
		DB	#34			;STK_DATA
		DB	#F0			;Exponent
		DB	#31			;
		DB	#72			;
		DB	#17			;
		DB	#F8			;
		DB	#04			;MULTIPLY
		DB	#01			;EXCHANGE
		DB	#A2			;STK_HALF
		DB	#03			;SUBTRACT
		DB	#A2			;STK_HALF
		DB	#03			;SUBTRACT
		DB	#31			;DUPLICATE
		DB	#34			;STK_DATA
		DB	#32			;Exponent
		DB	#20			;
		DB	#04			;MULTIPLY
		DB	#A2			;STK_HALF
		DB	#03			;SUBTRACT
		DB	#8C			;SERIES_0C
		DB	#11			;Exponent
		DB	#AC			;
		DB	#14			;Exponent
		DB	#09			;
		DB	#56			;Exponent
		DB	#DA			;
		DB	#A5			;
		DB	#59			;Exponent
		DB	#30			;
		DB	#C5			;
		DB	#5C			;Exponent
		DB	#90			;
		DB	#AA			;
		DB	#9E			;Exponent
		DB	#70			;
		DB	#6F			;
		DB	#61			;
		DB	#A1			;Exponent
		DB	#CB			;
		DB	#DA			;
		DB	#96			;
		DB	#A4			;Exponent
		DB	#31			;
		DB	#9F			;
		DB	#B4			;
		DB	#E7			;Exponent
		DB	#A0			;
		DB	#FE			;
		DB	#5C			;
		DB	#FC			;
		DB	#EA			;Exponent
		DB	#1B			;
		DB	#43			;
		DB	#CA			;
		DB	#36			;
		DB	#ED			;Exponent
		DB	#A7			;	
		DB	#9C			;
		DB	#7E			;
		DB	#5E			;
		DB	#F0			;Exponent
		DB	#6E			;
		DB	#23			;
		DB	#80			;
		DB	#93			;
		DB	#04			;MULTIPLY
		DB	#0F			;ADDITION
		DB	#38			;END_CALC
		RET

; Reduce argument
GET_ARGT:	RST	#28			;FP_CALC
		DB	#3D			;RE_STACK
		DB	#34			;STK_DATA
		DB	#EE			;Exponent
		DB	#22			;
		DB	#F9			;
		DB	#83			;
		DB	#6E			;
		DB	#04			;MULTIPLY
		DB	#31			;DUPLICATE
		DB	#A2			;STK_HALF
		DB	#0F			;ADDITION
		DB	#27			;INT
		DB	#03			;SUBTRACT
		DB	#31			;DUPLICATE
		DB	#0F			;ADDITION
		DB	#31			;DUPLICATE
		DB	#0F			;ADDITION
		DB	#31			;DUPLICATE
		DB	#2A			;ABS
		DB	#A1			;STK_ONE
		DB	#03			;SUBTRACT
		DB	#31			;DUPLICATE
		DB	#37			;GREATER_0
		DB	#C0			;ST-MEM-0
		DB	#00			;JUMP_TRUE
		DB	#04			;to ZPLUS
		DB	#02			;DELETE
		DB	#38			;END_CALC
		RET

ZPLUS:		DB	#A1			;STK_ONE
		DB	#03			;SUBTRACT
		DB	#01			;EXCHANGE
		DB	#36			;LESS_0
		DB	#00			;JUMP_TRUE
		DB	#02			;to YNEG
		DB	#1B			;NEGATE
YNEG:		DB	#38			;END_CALC
		RET

; Handle cosine
COS_FUNC:	RST	#28			;FP_CALC
		DB	#39			;GET_ARGT
		DB	#2A			;ABS
		DB	#A1			;STK_ONE
		DB	#03			;SUBTRACT
		DB	#E0			;GET-MEM-0
		DB	#00			;JUMP_TRUE
		DB	#06			;fwd to C_ENT
		DB	#1B			;NEGATE
		DB	#33			;jump
		DB	#03			;fwd to C_ENT

; Handle sine
SIN_FUNC:	RST	#28			;FP_CALC
		DB	#39			;GET_ARGT
C_ENT:		DB	#31			;DUPLICATE
		DB	#31			;DUPLICATE
		DB	#04			;MULTIPLY
		DB	#31			;DUPLICATE
		DB	#0F			;ADDITION
		DB	#A1			;STK_ONE
		DB	#03			;SUBTRACT
		DB	#86			;SERIES-06
		DB	#14			;Exponent			
		DB	#E6			;
		DB	#5C			;Exponent
		DB	#1F			;
		DB	#0B			;
		DB	#A3			;Exponent
		DB	#8F			;
		DB	#38			;
		DB	#EE			;
		DB	#E9			;Exponent
		DB	#15			;
		DB	#63			;
		DB	#BB			;
		DB	#23			;
		DB	#EE			;Exponent
		DB	#92			;
		DB	#0D			;
		DB	#CD			;
		DB	#ED			;
		DB	#F1			;Exponent
		DB	#23			;
		DB	#5D			;
		DB	#1B			;
		DB	#EA			;
		DB	#04			;MULTIPLY
		DB	#38			;END_CALC
		RET

; Handle tangent
TAN_FUNC:	RST	#28			;FP_CALC
		DB	#31			;DUPLICATE
		DB	#1F			;SIN
		DB	#01			;EXCHANGE
		DB	#20			;COS
		DB	#05			;DIVISION
		DB	#38			;END_CALC
		RET

; Handle arctan
ATN_FUNC:	CALL	RE_STACK
		LD	A,(HL)
		CP	#81
		JR	C,SMALL
		RST	#28			;FP_CALC
		DB	#A1			;STK_ONE
		DB	#1B			;NEGATE
		DB	#01			;EXCHANGE
		DB	#05			;DIVISION
		DB	#31			;DUPLICATE
		DB	#36			;LESS_0
		DB	#A3			;STK_PI_2
		DB	#01			;EXCHANGE
		DB	#00			;JUMP_TRUE
		DB	#06			;to CASES
		DB	#1B			;NEGATE
		DB	#33			;jump
		DB	#03			;to CASES
SMALL:		RST	#28			;FP_CALC
		DB	#A0			;STK_ZERO
CASES:		DB	#01			;EXCHANGE
		DB	#31			;DUPLICATE
		DB	#31			;DUPLICATE
		DB	#04			;MULTIPLY
		DB	#31			;DUPLICATE
		DB	#0F			;ADDITION
		DB	#A1			;STK_ONE
		DB	#03			;SUBTRACT
		DB	#8C			;SERIES_0C
		DB	#10			;Exponent
		DB	#B2			;
		DB	#13			;Exponent
		DB	#0E			;
		DB	#55			;Exponent
		DB	#E4			;
		DB	#8D			;
		DB	#58			;Exponent
		DB	#39			;
		DB	#BC			;
		DB	#5B			;Exponent
		DB	#98			;
		DB	#FD			;
		DB	#9E			;Exponent
		DB	#00			;
		DB	#36			;
		DB	#75			;
		DB	#A0			;Exponent
		DB	#DB			;
		DB	#E8			;
		DB	#B4			;
		DB	#63			;Exponent
		DB	#42			;
		DB	#C4			;
		DB	#E6			;Exponent
		DB	#B5			;
		DB	#09			;
		DB	#36			;
		DB	#BE			;
		DB	#E9			;Exponent
		DB	#36			;
		DB	#73			;
		DB	#1B			;
		DB	#5D			;
		DB	#EC			;Exponent
		DB	#D8			;
		DB	#DE			;
		DB	#63			;
		DB	#BE			;
		DB	#F0			;Exponent
		DB	#61			;
		DB	#A1			;
		DB	#B3			;
		DB	#0C			;
		DB	#04			;MULTIPLY
		DB	#0F			;ADDITION
		DB	#38			;END_CALC
		RET

; Handle arcsin
ASN_FUNC:	RST	#28			;FP_CALC
		DB	#31			;DUPLICATE
		DB	#31			;DUPLICATE
		DB	#04			;MULTIPLY
		DB	#A1			;STK_ONE
		DB	#03			;SUBTRACT
		DB	#1B			;NEGATE
		DB	#28			;SQR
		DB	#A1			;STK_ONE
		DB	#0F			;ADDITION
		DB	#05			;DIVISION
		DB	#24			;ATN
		DB	#31			;DUPLICATE
		DB	#0F			;ADDITION
		DB	#38			;END_CALC
		RET

; Handle arccos
ACS_FUNC:	RST	#28			;FP_CALC
		DB	#22			;ASN
		DB	#A3			;STK_PI_2
		DB	#03			;SUBTRACT
		DB	#1B			;NEGATE
		DB	#38			;END_CALC
		RET

; Handle square root
SQR_FUNC:	RST	#28			;FP_CALC
		DB	#31			;DUPLICATE
		DB	#30			;NOT
		DB	#00			;JUMP_TRUE
		DB	#1E			;to LAST
		DB	#A2			;STK_HALF
		DB	#38			;END_CALC

; Handle exponential
TO_POWER:	RST	#28			;FP_CALC
		DB	#01			;EXCHANGE
		DB	#31			;DUPLICATE
		DB	#30			;NOT
		DB	#00			;JUMP_TRUE
		DB	#07			;to XISO
		DB	#25			;LN
		DB	#04			;MULTIPLY
		DB	#38			;END_CALC
		JP	EXP			

XISO:		DB	#02			;DELETE
		DB	#31			;DUPLICATE
		DB	#30			;NOT
		DB	#00			;JUMP_TRUE
		DB	#09			;to ONE
		DB	#A0			;STK_ZERO
		DB	#01			;EXCHANGE
		DB	#37			;GREATER_0
		DB	#00			;JUMP_TRUE
		DB	#06			;to LAST
		DB	#A1			;STK_ONE
		DB	#01			;EXCHANGE
		DB	#05			;DIVISION
ONE:		DB	#02			;DELETE
		DB	#A1			;STK_ONE
LAST:		DB	#38			;END_CALC
		RET

; BSROM additional routines
; Input of HEX numbers
HEXA:		LD	HL,SCAN_FUNC
		CP	#25
		RET	NZ
		POP	AF
		CALL	SYNTAX_Z
		JP	NZ,S_STK_DEC
		LD	DE,#0000
HEX1:		RST	#20
		CALL	ALPHANUM
		JR	NC,HEXEND
		CP	#41
		JR	C,CIS
		OR	#20
		CP	#67
		JR	NC,HEXEND
		SUB	#27
CIS:		AND	#0F
		LD	C,A
		LD	A,D
		AND	#F0
		JP	NZ,REPORT_6
		LD	A,C
		EX	DE,HL
		ADD	HL,HL
		ADD	HL,HL
		ADD	HL,HL
		ADD	HL,HL
		OR	L
		LD	L,A
		EX	DE,HL
		JR	HEX1

HEXEND:		CALL	BIN_END
		JP	S_BIN_1

; Allow number in VAL$ and VAL
VAL1:		CP	#18
		RET	Z
		CP	#9D
		RET	Z
		XOR	(IY+#01)
		RET

; Evaluation of VAL and VAL$
VAL2:		LD	HL,(#5C5D)
		BIT	6,(IY+#01)
		RET	Z
		POP	AF
		PUSH	BC
		CALL	FIND_INT2
		POP	AF
		RRCA
		JR	NC,DOLAR
		LD	H,B
		LD	L,C
		LD	C,(HL)
		INC	HL
		LD	B,(HL)
		JP	STACK_BC

DOLAR:		PUSH	BC
		LD	BC,#0004
		RST	#30
		POP	HL
		PUSH	DE
		LD	A,H
		CALL	HEX99
		LD	A,L
		CALL	HEX99
		POP	DE
		JP	CHR_DLR1

; Hex numbers
HEX99:		PUSH	AF
		RRCA
		RRCA
		RRCA
		RRCA
		CALL	HEX98
		POP	AF
HEX98:		AND	#0F
		OR	#30
		CP	#3A
		JR	C,HEX98_1
		ADD	A,#27
HEX98_1:	LD	(DE),A
		INC	DE
		RET

INFSUB:		LD	DE,COPYRIGHT+5
		CALL	PO_TOKENS1
		JP	HLO

MM:		DW	#FFFF

USERJP:		JP	#0052

DISKTOOLS:	DW	#0052

; 128k reset
RES128:		DI
		XOR	A
		LD	I,A
		OUT	(#FE),A
		LD	E,#17
CC0:		LD	BC,#7FFD
		OUT	(C),E
		LD	BC,#0008
		LD	H,A
		LD	L,A
		LD	SP,HL
CC1:		PUSH	HL
		PUSH	HL
		PUSH	HL
		PUSH	HL
		DJNZ	CC1
		DEC	C
		JR	NZ,CC1
		DEC	E
		BIT	4,E
		JR	NZ,CC0
		LD	B,#5C
CC2:		LD	(BC),A
		INC	C
		JR	NZ,CC2
		DEC	HL
		JP	RAM_DONE2

; NMI Menu
NMI_MENU:	PUSH	AF
		PUSH	HL
		LD	HL,#BFE0
		ADD	HL,SP
		JR	C,MM1
		LD	SP,#5800
		LD	HL,NMI_MENU
		PUSH	HL
		PUSH	HL
		PUSH	HL
MM1:		PUSH	BC
		PUSH	DE
		PUSH	IX
		LD	A,I
		PUSH	AF
MMRET:		DI
		LD	C,#FE
		LD	A,R
		OUT	(C),A
		OUT 	(C),0
		CALL	KEY_SCAN
		INC	E
		JR	Z,MMRET
		DEC	E
		CALL	K_TEST
		LD	XH,A
		LD	A,#22
		OUT	(#FE),A
PUST:		CALL	KEY_SCAN
		INC	E
		JR	NZ,PUST
		LD	A,#08
		OUT	(#FE),A
		LD	A,XH
		LD	HL,MMRET
		PUSH	HL
		CP	'U'			; U - user function.
		JR	Z,USERJP
		CP	'E'			; E - extended 128k reset.
		JR	Z,RES128
		CP	'I'			; I - quiet AY. Reset FDC, DMA and stop disk drive if MB-02 is present.
		JP	Z,HARD
		CP	'T'			; T - set tape as actual device (only on MB-02).
		JP	Z,SETTAP
		CP	'D'			; D - set disk as actual device (only on MB-02)
		JP	Z,SETDSK
		CP	'B'			; B - warm start. BASIC program with variables is not deleted.
		JP	Z,BASIC
		CP	'Z'			; Z - user function like 'U' but this key is reserved for MB-02 applications.
		LD	HL,(DISKTOOLS)
		JR	NZ,DSKIP
		JP	(HL)
DSKIP:		CP	'N'			; N - CLEAR #5FFF: NEW - memory above #6000 is not changed.
		LD	DE,#5FFF
		JR	Z,RESNEW
		CP	'R'			; R - CLEAR #FFFF: NEW - classic 48k reset.
		LD	D,E
RESNEW:		JP	Z,NEW_1
NERES:		CP	'S'			; S - save SCREEN$ on tape, or disk if MB-02 is present.
		JR	NZ,NESAV
		LD	IX,#4000
		LD	DE,#1B00
		LD	A,#FF
		JP	SA_BYTES1
NESAV:		CP	'Q'			; Q - quit / return from NMI menu.
		JR	Z,QUIT
		CP	'M'			; M - jump to MRS debugger (MRS must be loaded in memory).
		JR	Z,MRS
		CALL	NUMERIC
		RET	C
		LD	HL,#4000
		ADD	HL,SP
		JR	NC,DD0
		LD	SP,#57F0
DD0:		POP	BC
		CALL	OUT128
		JP	MMRET

; Quit from NMI Menu		
QUIT:		POP	AF
		POP	AF
		LD	I,A
		JP	PO,RET_I
		EI
RET_I:		POP	IX
		POP	DE
		POP	BC
		POP	HL
		POP	AF
		RET

; Jump to MRS debugger
MRS:		POP	AF
		POP	AF
		LD	I,A
		POP	IX
		POP	DE
		POP	BC
		POP	HL
		POP	AF
		LD	(#F4FF),HL
		POP	HL
		LD	(#F544),HL
		JP	#F514

; Print general number
HLODVA:		LD	A,':'
		RST	#10
HLO:		LD	B,H
		LD	C,L
		CALL	STACK_BC
		JP	PRINT_FP

TT:		DW	#0000			;DS #39FF-TT
UU:		DW	#FFFF

DISPL:		LD	C,A
		LD	A,(IY+#02)
		CP	#10
		LD	A,C
		JR	NZ,DIS
		LD	BC,#FBFE
		IN	C,(C)
		RRC	C
		JR	C,DII
PUSTI:		XOR	A
		IN	A,(#FE)
		RRCA
		JR	NC,PUSTI
		LD	SP,(#5C3F)		;LISTSP
		RES	5,(IY+#01)
		RET

DII:		LD	C,(IY+#76)
		BIT	1,C			;bit1=1 don't show colors during autolist
		JR	Z,DIS
		CP	#0D
		JR	Z,DIS
		CP	#20
		JR	C,DIP
DIS:		JP	PO_FETCH

DIP:		BIT	2,C			;bit2=1 show comma instead of codes
		JR	NZ,DID
		POP	AF
DID:		LD	A,#1E
		JR	DIS

; General number printing with spaces
NUM_NEW:	PUSH	DE
		PUSH	HL
		LD	E,' '
		DB	#06
NUMCOM:		LD	L,C
		LD	BC,#D8F0
		CALL	OUT_SP_NO
		JP	OUT_NUM_3

; Check of BASIC program presence
LIN2:		CALL	LINE_NO
		PUSH	HL
		LD	HL,(#5C53)
		LD	A,(HL)
		POP	HL
		RET

; Test of numbers at the begin of line
LIN3:		RST	#18
		CALL	NUMERIC
		PUSH	AF
		CALL	E_LINE_NO
		POP	AF
		RET

; Show empty cursor instead of '*' 
LIN4:		LD	A,(IY+#02)
		CP	#10
		JR	Z,LL40
		LD	D,#20
LL40:		PUSH	HL
		XOR	A
		LD	HL,(#5C51)		;channel R?
		LD	BC,#5CC0
		SBC	HL,BC
		POP	HL
		JR	Z,LL41
		BIT	0,(IY+#76)
		JP	Z,OUT_NUM_2
		DB	#01
LL41:		LD	D,#00			; no cursor at 'R'
		PUSH	DE
		LD	D,(HL)
		INC	HL
		LD	E,(HL)
		EX	DE,HL
		CALL	NUM_NEW
		EX	DE,HL
		POP	DE
		RET

; Moving around edit zone
DOLE:		CALL	ED_RIGHT
		LD	IX,ED_RIGHT
		JR	NZ,HORDOL
		LD	HL,#5C49
		RET

HORE:		CALL	ED_LEFT
		LD	IX,ED_LEFT
		JR	NC,HORDOL
		LD	HL,(#5C49)
		RET

HORDOL:		POP	BC
		LD	B,#00
HD1:		INC	B
		BIT	5,B
		RET	NZ
		PUSH	BC
		CALL	L_03F0
		POP	BC
		LD	A,(HL)
		CP	#0D
		RET	Z
		CP	' '
		JR	C,HD1+1
		SUB	#A5
		JR	C,HD1
		EXX
		LD	HL,INCB-2
		LD	(#5C51),HL
		CALL	PO_TOKENS
		CALL	ED_LIST_1
		EXX
		JR	HD1+1

		DW	INCB
INCB:		EXX
		INC	B
		EXX
		RET

; Switch 128k bank
BANKA:		RST	#20
		CALL	FETCH_NUM
		CALL	CHECK_END
		CALL	FIND_INT1
OUT128:		AND	#0F
		OR	#10
		LD	BC,#7FFD
		OUT	(C),A
		RET

; Comma instead of semicolon
EDIT:		RST	#20
		CALL	FETCH_NUM
		CALL	CHECK_END
		CALL	FIND_INT2
		LD	(#5C49),BC
		CALL	SET_MIN
		CALL	CLS_LOWER
		RES	5,(IY+#37)
VV:		DW	#FFFF
		RES	3,(IY+#01)
		CALL	ED_EDIT
		LD	SP,(#5C3D)
		POP	AF
		JP	MAIN_2

; Modified CLS command
NEW_CLS:	CALL	FIND_INT1
		OR	A
		JR	Z,NECOL
		LD	(#5C48),A
		LD	(#5C8D),A
		CALL	SA_LD_RET
NECOL:		JP	CLS

; New commands
COMM:		CP	#27			;"'"
		JR	Z,BANKA
		CP	#2C			;","
		JR	Z,EDIT
		LD	HL,NEWTAB
COM1:		BIT	7,(HL)
		JP	NZ,PRINT
		CP	(HL)
		INC	HL
		LD	E,(HL)
		INC	HL
		LD	D,(HL)
		INC	HL
		JR	NZ,COM1
		RST	#20
		CALL	CHECK_END
		EX	DE,HL
		JP	(HL)

NEWTAB:		DB	'#'
		DW	54885	
		DB	'_'
		DW	#66
		DB	'*'
		DW	HEA
		DB	'?'
		DW	INFO
		DB	#7F			;(c)
		DW	BASIC
		DB	'^'
		DW	RES128
		DB	'!'
		DW	HARD
		DB	'='
		DW	USERJP

; Quiet AY. Reset FDC, DMA, stop drives if MB-02 is present
HARD:		XOR	A
		LD	BC,#FFFD
		OUT	(#13),A			; FDD motor
		LD	A,#D0
		OUT	(#0F),A			; FDC
		LD	A,#C3
		OUT	(#0B),A			; DMA
		LD	A,#07	
		OUT	(C),A			; AY
		LD	A,#BF
		OUT	(#FD),A
		LD	A,#0D
		OUT	(C),A
		LD	A,#80
		OUT	(#FD),A
		RET

; Warm start
BASIC:		LD	HL,INIT_CHAN
		LD	DE,#5CB6
		LD	BC,#0015
		LD	(#5C4F),DE
		LDIR
		LD	HL,#3C00
		LD	(#5C36),HL
		LD	HL,#0040
		LD	(#5C38),HL
		LD	IY,#5C3A
		LD	HL,(#5CB2)
		LD	(HL),#3E
		DEC	HL
		LD	SP,HL
		DEC	HL
		DEC	HL
		LD	(#5C3D),HL
		IM	1
		EI
		LD	HL,(#5C59)
		JP	WARM_ST

; Enhanced POKE
NEW_POKE:	CALL	SYNTAX_Z
		CALL	NZ,FIND_INT2
		LD	D,B
		LD	E,C
POKLOP:		RST	#18
		CP	#2C
		JR	Z,POKOK
		CP	#3B
		RET	NZ
POKOK:		PUSH	DE
		PUSH	AF
		RST	#20
		CALL	SCANNING
		POP	AF
		POP	DE
		CALL	SYNTAX_Z
		JR	Z,POKLOP
		BIT	6,(IY+#01)
		JR	NZ,POKNUM
POKRET:		PUSH	AF
		PUSH	DE
		CALL	STK_FETCH
		EX	DE,HL
		POP	DE
		LD	A,B
		OR	C
		JR	Z,POKNIC
		LDIR
		POP	AF
		RRCA
		JR	NC,POKLOP
		LD	H,D
		LD	L,E
		DEC	HL
		SET	7,(HL)
		PUSH	AF
POKNIC:		POP	AF
		JR	POKLOP

POKNUM:		PUSH	DE
		RRCA
		JR	C,POKDW
POKDB:		CALL	FIND_INT1
		POP	DE
		JR	POKLD

POKDW:		CALL	FIND_INT2
		POP	DE
		LD	A,C
		LD	(DE),A
		INC	DE
		LD	A,B
POKLD:		LD	(DE),A
		INC	DE
		JR	POKLOP

SS:		DB	#FF
WW:		DW	#FFFF

; New line number test
LIN1:		CALL	CP_LINES
		RET	NC
		LD	A,(HL)
		AND	#C0
		RET	NZ
		SCF
		RET

; New boot screen
INFO:		CALL	CLS
		LD	A,#FE
		CALL	CHAN_OPEN
		LD	HL,(#5C4B)
		LD	BC,(#5C53)
		XOR	A
		PUSH	HL
		SBC	HL,BC
		CALL	INFSUB
		POP	BC
		SCF
		LD	HL,(#5C59)
		SBC	HL,BC
		LD	A,#01
		CALL	INFSUB
		LD	BC,(#5C65)
		LD	HL,#0000
		ADD	HL,SP
		SBC	HL,BC
		LD	A,#02
		CALL	INFSUB
		JP	PRINT_5

; Header command
HEA:		LD	A,#FE
		CALL	CHAN_OPEN
ZNOVU:		DI
		LD	IX,#5C9E
		LD	DE,#0010
		XOR	A
		INC	E
		SCF
		EX	AF,AF'
		LD	A,#0E
		OUT	(#FE),A
		IN	A,(#FE)
		RRA
		CALL	LD_BYTES1
		CALL	SA_LD_RET
		JR	NC,ZNOVU
		LD	(#5C8C),A
		LD	A,#17
		RST	#10
		XOR	A
		RST	#10
		RST	#10
		LD	HL,#5C9E
		LD	A,(HL)
		OR	#30
		RST	#10
		LD	A,#3A
		RST	#10
		LD	B,#0A
MENO:		INC	HL
		LD	A,(HL)
		CP	#20
		JR	NC,MENO1
		LD	A,#1E
MENO1:		RST	#10
		DJNZ	MENO
		LD	A,#17
		RST	#10
		LD	A,#15
		RST	#10
		RST	#10
		LD	HL,(#5CAB)
		CALL	NUM_NEW
		LD	HL,(#5CA9)
		CALL	HLODVA
		LD	A,#0D
		RST	#10
		JR	ZNOVU

		DB	#FF

; BSROM for MB02+
; ROM BIOS
SETRWP:		JR	ROMDIS			; Set rom bank + write protect
SETDWP:		JR	DOSDIS			; Set dos bank + write protect
SETRWE:		JR	ROMENA			; Set rom bank + write enable
SETDWE:		JR	DOSENA			; Set dos bank + write enable
BNKCAL:		JR	BNCALL			; Switch rom/dos bank

SETTAP:		XOR	A
		DB	#E6
SETDSK:		LD	A,#7F
		CALL	SETRWE
		LD	(TAPDSK),A
		JR	SETRWP

TAPDSK:		DB	#03			; Bit0: 0=tape, 1=disk

BNCALL:		CALL	SETRWE
		LD	(REGHL+1),HL
		POP	HL
		INC	HL
		INC	HL
		PUSH	HL
		PUSH	AF
		DEC	HL
		LD	A,(HL)
		DEC	HL
		LD	L,(HL)
		LD	H,A
		POP	AF
		PUSH	HL
		LD	HL,SWITCH
		EX	(SP),HL
		PUSH	HL
REGHL:		LD	HL,#5555
SWITCH:		JP	SETDWE

; BSROM for MB02+
; this is hardware dependant part of ROM BIOS
; here are FFs by standard
; this part of code is loaded during system boot
; valid only for MB02+
ROMDIS:		PUSH	AF
		LD	A,#40
		JR	BNKOUT
DOSDIS:		PUSH	AF
		LD	A,#41
		JR	BNKOUT
ROMENA:		PUSH	AF
		LD	A,#60
		JR	BNKOUT
DOSENA:		PUSH	AF
		LD	A,#61
BNKOUT:		OUT	(#17),A
		POP	AF
		RET		

; BSROM for MB02+
; reserved for future BSDOS patches

		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000
		DW	#0000

; BSROM - new characters
CHAR_SET_N:	DB	#00,#00,#00,#00,#00,#00,#7E,#00	;line
		DB	#00,#7E,#7E,#7E,#7E,#7E,#7E,#00	;square

; Character set
CHAR_SET:	DB	#00,#00,#00,#00,#00,#00,#00,#00	;space
		DB	#00,#10,#10,#10,#10,#00,#10,#00	;!
		DB	#00,#24,#24,#00,#00,#00,#00,#00	;"
		DB	#00,#24,#7E,#24,#24,#7E,#24,#00	;#
		DB	#00,#08,#3E,#28,#3E,#0A,#3E,#08	;$
		DB	#00,#62,#64,#08,#10,#26,#46,#00	;%
		DB	#00,#10,#28,#10,#2A,#44,#3A,#00	;&
		DB	#00,#08,#10,#00,#00,#00,#00,#00	;'
		DB	#00,#04,#08,#08,#08,#08,#04,#00	;(
		DB	#00,#20,#10,#10,#10,#10,#20,#00	;)
		DB	#00,#00,#14,#08,#3E,#08,#14,#00	;*
		DB	#00,#00,#08,#08,#3E,#08,#08,#00	;+
		DB	#00,#00,#00,#00,#00,#08,#08,#10	;,
		DB	#00,#00,#00,#00,#3E,#00,#00,#00	;-
		DB	#00,#00,#00,#00,#00,#18,#18,#00	;.
		DB	#00,#00,#02,#04,#08,#10,#20,#00	;/
		DB	#00,#3C,#46,#4A,#52,#62,#3C,#00	;0
		DB	#00,#18,#28,#08,#08,#08,#3E,#00	;1
		DB	#00,#3C,#42,#02,#3C,#40,#7E,#00	;2
		DB	#00,#3C,#42,#0C,#02,#42,#3C,#00	;3
		DB	#00,#08,#18,#28,#48,#7E,#08,#00	;4
		DB	#00,#7E,#40,#7C,#02,#42,#3C,#00	;5
		DB	#00,#3C,#40,#7C,#42,#42,#3C,#00	;6
		DB	#00,#7E,#02,#04,#08,#10,#10,#00	;7
		DB	#00,#3C,#42,#3C,#42,#42,#3C,#00	;8
		DB	#00,#3C,#42,#42,#3E,#02,#3C,#00	;9
		DB	#00,#00,#00,#10,#00,#00,#10,#00	;:
		DB	#00,#00,#10,#00,#00,#10,#10,#20	;;
		DB	#00,#00,#04,#08,#10,#08,#04,#00	;<
		DB	#00,#00,#00,#3E,#00,#3E,#00,#00	;=
		DB	#00,#00,#10,#08,#04,#08,#10,#00	;>
		DB	#00,#3C,#42,#04,#08,#00,#08,#00	;?
		DB	#00,#3C,#02,#3A,#4A,#4A,#3C,#00	;@ BSROM - more beautiful @ character
		DB	#00,#3C,#42,#42,#7E,#42,#42,#00	;A
		DB	#00,#7C,#42,#7C,#42,#42,#7C,#00	;B
		DB	#00,#3C,#42,#40,#40,#42,#3C,#00	;C
		DB	#00,#78,#44,#42,#42,#44,#78,#00	;D
		DB	#00,#7E,#40,#7C,#40,#40,#7E,#00	;E
		DB	#00,#7E,#40,#7C,#40,#40,#40,#00	;F
		DB	#00,#3C,#42,#40,#4E,#42,#3C,#00	;G
		DB	#00,#42,#42,#7E,#42,#42,#42,#00	;H
		DB	#00,#3E,#08,#08,#08,#08,#3E,#00	;I
		DB	#00,#02,#02,#02,#42,#42,#3C,#00	;J
		DB	#00,#44,#48,#70,#48,#44,#42,#00	;K
		DB	#00,#40,#40,#40,#40,#40,#7E,#00	;L
		DB	#00,#42,#66,#5A,#42,#42,#42,#00	;M
		DB	#00,#42,#62,#52,#4A,#46,#42,#00	;N
		DB	#00,#3C,#42,#42,#42,#42,#3C,#00	;O
		DB	#00,#7C,#42,#42,#7C,#40,#40,#00	;P
		DB	#00,#3C,#42,#42,#52,#4A,#3C,#00	;Q
		DB	#00,#7C,#42,#42,#7C,#44,#42,#00	;R
		DB	#00,#3C,#40,#3C,#02,#42,#3C,#00	;S
		DB	#00,#FE,#10,#10,#10,#10,#10,#00	;T
		DB	#00,#42,#42,#42,#42,#42,#3C,#00	;U
		DB	#00,#42,#42,#42,#42,#24,#18,#00	;V
		DB	#00,#42,#42,#42,#42,#5A,#24,#00	;W
		DB	#00,#42,#24,#18,#18,#24,#42,#00	;X
		DB	#00,#82,#44,#28,#10,#10,#10,#00	;Y
		DB	#00,#7E,#04,#08,#10,#20,#7E,#00	;Z
		DB	#00,#0E,#08,#08,#08,#08,#0E,#00	;[
		DB	#00,#00,#40,#20,#10,#08,#04,#00	;\
		DB	#00,#70,#10,#10,#10,#10,#70,#00	;]
		DB	#00,#10,#38,#54,#10,#10,#10,#00	;^
		DB	#00,#00,#00,#00,#00,#00,#00,#FF	;_
		DB	#00,#1C,#22,#78,#20,#20,#7E,#00	;£
		DB	#00,#00,#38,#04,#3C,#44,#3C,#00	;a
		DB	#00,#20,#20,#3C,#22,#22,#3C,#00	;b
		DB	#00,#00,#1C,#20,#20,#20,#1C,#00	;c
		DB	#00,#04,#04,#3C,#44,#44,#3C,#00	;d
		DB	#00,#00,#38,#44,#78,#40,#3C,#00	;e
		DB	#00,#0C,#10,#18,#10,#10,#10,#00	;f
		DB	#00,#00,#3C,#44,#44,#3C,#04,#38	;g
		DB	#00,#40,#40,#78,#44,#44,#44,#00	;h
		DB	#00,#10,#00,#30,#10,#10,#38,#00	;i
		DB	#00,#04,#00,#04,#04,#04,#24,#18	;j
		DB	#00,#20,#28,#30,#30,#28,#24,#00	;k
		DB	#00,#10,#10,#10,#10,#10,#0C,#00	;l
		DB	#00,#00,#68,#54,#54,#54,#54,#00	;m
		DB	#00,#00,#78,#44,#44,#44,#44,#00	;n
		DB	#00,#00,#38,#44,#44,#44,#38,#00	;o
		DB	#00,#00,#78,#44,#44,#78,#40,#40	;p
		DB	#00,#00,#3C,#44,#44,#3C,#04,#06	;q
		DB	#00,#00,#1C,#20,#20,#20,#20,#00	;r
		DB	#00,#00,#38,#40,#38,#04,#78,#00	;s
		DB	#00,#10,#38,#10,#10,#10,#0C,#00	;t
		DB	#00,#00,#44,#44,#44,#44,#38,#00	;u
		DB	#00,#00,#44,#44,#28,#28,#10,#00	;v
		DB	#00,#00,#44,#54,#54,#54,#28,#00	;w
		DB	#00,#00,#44,#28,#10,#28,#44,#00	;x
		DB	#00,#00,#44,#44,#44,#3C,#04,#38	;y
		DB	#00,#00,#7C,#08,#10,#20,#7C,#00	;z
		DB	#00,#0E,#08,#30,#08,#08,#0E,#00	;{
		DB	#00,#08,#08,#08,#08,#08,#08,#00	;|
		DB	#00,#70,#10,#0C,#10,#10,#70,#00	;}
		DB	#00,#14,#28,#00,#00,#00,#00,#00	;~
		DB	#3C,#42,#99,#A1,#A1,#99,#42,#3C	;(c)
