[Return to top]

Enhanced BASIC on your system by Lee Davison
[Back]


Hardware.

EhBASIC can be made to work on nearly any 6502 system, it requires very little. The system it was developed on is a combination of my SBC and 6551 projects.
Memory.
EhBASIC makes extensive use of page zero and some use of page 2. Some areas may be re-used as long as care is taken. Program and variable space is from $0300 up to whatever is available, the more the better. The interpreter can be ROM or RAM based and can be assembled to reside almost anywhere in memory, only minor changes need to be made.
Software.
For minimal functionality the interpreter needs only two external routines, a character get routine and a character send routine.

For full functionality two other external routines, load and save, along with two interrupt service routines are needed.

Minimal set-up is required, most of the set-up is performed by the interpreter cold start routine.

How to.
The interpreter calls the system routines via RAM based vectors and, as long as the requirements for each routine are met, these can be changed on the fly if needs be.

All the routines exit via an RTS.

The routines are ..

Input
This is a non halting scan of the input device. If a character is ready it should be placed in A and the carry flag set, if there is no character then A, and the carry flag, should be cleared.
Output
The character to be sent is in A and should not be changed by the routine. Also on return, the N and Z flags should reflect the character in A.
Load
This is entirely system dependant.
Save
This is entirely system dependant.
Also if you wish to use the ON {IRQ|NMI} commands ..
Irq
If no other valid interrupt has happened then this routine should, after checking that the interrupt is set-up, set the IRQ interrupt happened flag.
Nmi
If no other valid interrupt has happened then this routine should, after checking that the interrupt is set-up, set the NMI interrupt happened flag.
Example code.
This is for a simple 6502 system with RAM from $0000 to $BFFF, the interpreter in ROM from $C000 to $EFFF (12k), an 6551 ACIA at $F000 and this code in a 2k ROM from $F800 to $FFFF


; Minimum monitor routines for extended BASIC. Has set-up and
; 6551 ACIA code, nothing else.

LAB_0000	= $0000		; BASIC warm start

NmiBase		= $D8		; NMI handler flag byte
;		= $D9		; NMI handler addr low byte
;		= $DA		; NMI handler addr high byte
IrqBase		= $DB		; IRQ handler flag byte
;		= $DC		; IRQ handler addr low byte
;		= $DD		; IRQ handler addr high byte

ccflag		= $0200		; BASIC CTRL-C flag, 00 = en, 01 = dis
ccbyte		= ccflag+1	; BASIC CTRL-C byte
ccnull		= ccbyte+1	; BASIC CTRL-C byte timeout

VECCC		= ccnull+1	; ctrl c check vector

VECIN		= VECCC+2	; input vector
VECOUT		= VECIN+2	; output vector
VECLD		= VECOUT+2	; load vector
VECSV		= VECLD+2	; save vector

IRQ_vec		= VECSV+2	; IRQ/BRK jump
NMI_vec		= IRQ_vec+$0A	; NMI jump

LANGROM		= $C000		; start of BASIC ROM

A_rxd		= $F000		; ACIA receive data port
A_txd		= $F000		; ACIA transmit data port
A_sts		= $F001		; ACIA status port
A_res		= $F001		; ACIA reset port
A_cmd		= $F002		; ACIA command port
A_ctl		= $F003		; ACIA control port

	*=	$F800

; reset vector points here

RESET
	CLD			; clear decimal mode
	LDX	#$FF		; load byte
	TXS			; set the stack

				; initialise UART (6551 ACIA)
	STA	A_res		; soft reset
	LDA	#$8B		; set specific modes and functions
	STA	A_cmd		; save to command register
;	LDA	#$1A		; 8-N-1, 2400 baud
	LDA	#$1C		; 8-N-1, 4800 baud
;	LDA	#$1E		; 8-N-1, 9600 baud
	STA	A_ctl		; set control register

				; initialise page 2 variables
	LDY	#PG2_END-PG2_TAB	; byte count
PG2_LOOP
	LDA	PG2_TAB-1,Y	; get byte
	STA	VECIN-1,Y	; store in page 2
	DEY			; decrement count
	BNE	PG2_LOOP	; loop if not done

LAB_SMSG
	LDA	TAB_MSG,Y	; get byte from start-up message
	JSR	OUTPUT		; call output routine
	INY			; next byte
	CPY	#LAB_END-TAB_MSG-1	; compare with loop limit
	BNE	LAB_SMSG	; loop if not complete

WAIT_LP
	JSR	RINPUT		; call input routine
	BCC	WAIT_LP		; loop if no key

	AND	#$DF		; mask case bit (make upper case)
	CMP	#"W"		; compare with 'W' (warm)
	BNE	LAB_NWRM	; branch if not

	JMP	LAB_0000	; jump to warm start vector

LAB_NWRM
	CMP	#"C"		; compare with 'C' (cold)
	BNE	WAIT_LP		; loop if not

	JMP	LANGROM		; go do BASIC cold start

; now come the required BASIC routines

; scan the input device
; if byte available return carry set and byte in A
; else return carry clear and $00 in A

RINPUT
	LDA	A_sts		; get ACIA status
	AND	#$08		; mask rx buffer full flag
	CMP	#$08		; is bit set
	BNE	RD_EXIT		; exit with Cb=0 if buffer empty

	LDA	A_rxd		; get byte from ACIA data port (Cb=1)
RD_EXIT
	RTS			;

; wait for ACIA and tx byte
; return sent byte in A and N and Z flags set

OUTPUT
	PHA			; save A
OUTLOOP
	LDA	A_sts		; get status byte
	AND	#$10		; transmit data register empty?
	BEQ	OUTLOOP		; loop if tx buffer full

	PLA			; restore A, set flags
	STA	A_txd		; save to data port
	RTS			;

; load BASIC program routine, default (do nothing)

SETLOD

; save BASIC program routine, default (do nothing)

SETSAV
	RTS			; 

; table of initial values for page 2

PG2_TAB
	.word	RINPUT		; input vector
	.word	OUTPUT		; output vector
	.word	SETLOD		; load vector
	.word	SETSAV		; save vector

; If you want to use the ON {IRQ|NMI} commands you will
; need this interrupt handling code.

; code needed to set the interrupt flags.
; will only set the happened flag the set-up bit is set.

IRQ_CODE
	PHA			; save A
	LDA	IrqBase		; get set-up byte
	LSR	A		; shift bit to right
	ORA	IrqBase		; OR with set-up byte
	STA	IrqBase		; save set-up byte
	PLA			; restore A
	RTI

NMI_CODE
	PHA			; save A
	LDA	NmiBase		; get set-up byte
	LSR	A		; shift bit to right
	ORA	NmiBase		; OR with set-up byte
	STA	NmiBase		; save set-up byte
	PLA			; restore A
	RTI
END_CODE

PG2_END

; start-up message

TAB_MSG
	.byte	"EhBASIC for 6502 (C) 2001 C/W?"
LAB_END

	*=	$FFFA

; 6502 vectors

	.word	NMI_vec		; NMI vector set to BASIC NMI code
	.word	RESET		; RES vector
	.word	IRQ_vec		; IRQ vector set to BASIC IRQ code

	END


e-mail me [e-mail]
Last page update: 28th April, 2002.