BBC BASIC upgrade

Although Atom BASIC is an impressive achievement in terms of what can be crammed into just 8K of ROM, programmers may soon find it a chore to write programs with just 26 variables named A to Z. As memory prices fell, it became practical to provide more. The BBC micro had 16K for the OS ROM and another 16K for a far more advanced interpreter with the ability to define functions and procedures.

The BASIC makes well-defined calls to the OS, so porting the language only involves providing the OS functions. The Atom-to-BBC-BASIC upgrade board used the same BASIC ROM as the real BBC, but with a new 4K MOS ROM. Their binary code can be loaded into the RAM 'underneath' the Atom ROMs, then the Atom ROMs switched off before jumping to the new reset vector.

The hardware modifications require swapping the 16K at 4000 hex with the 16K at 8000 hex. This allows the BBC BASIC ROM to be seen at 8000 up, where it was in the BBC micro. The 6522 that was optional on the Atom must be fitted, and able to interrupt the CPU so that the new BBC OS can implement the ESC, TIME, and SOUND features.

The OS ROM expects the standard display modes of the 6847. To take advantage of the new display modes, which are more compatible with BBC display modes, the OS ROM would have to be modified. If located in RAM, there is plenty of scope for experimentation before committing it to Flash ROM.

The BBC micro had several hardware devices that are not present on the Atom or this project. Notably the UPD7002 Analogue to Digital converter, the 76477 sound generator, the speech chip, the Econent interface. Therefore the OS ROM does not implement the OS software to use them. The OS ROM is only 4K instead of 16K, so other features may simply have been unable to fit in there.

The FPGA design includes a control bit to change CPU's view of the memory map to match the Atom to BBC BASIC upgrade board. Note that the video circuit and RAM paging stay the same, to avoid design complications.

Getting the firmware into the project is a little tricky. The existing LPT to Atom program simply sends Atom BASIC command lines. The upgrade ROM code is 16K plus 4K of binary. It is impractical to convert this to a text file of poke commands by hand, but a small PC utility can do this. There are other possible ways, such as re-vectoring the Atom's tape input routines to collect binary from the LPT slave port, or transfer files as intel hex files, but are harder to do.

Implementation

The utility for binary to RAM-poke commands has been written and the output has been used to poke the firmware into paged RAM. As a bonus, it can also be used to load utilities and DOS.

The BBC-mode memory map hardware definitely re-maps the CPU's view of the system, and a small assembly program has verified this.

The system seems to have some problems, in that it can crash when switching modes. Suspecting the mode selection took some time to settle I added a nop code or two to delay the CPU before accessing the switched RAM. This improved things a little but not completely.

LFFBA:  lda     VEC_98
VDUCHR: plp
        pla
        sec
OSEVEN: sbc     #$01
        sta     VAR_FD
        pla
        sbc     #$00
        sta     VAR_FD+1
NVRDCH: jmp     (BRKV)
NVWRCH: jmp     (IRQ2V)
OSFIND: jmp     (FINDV)
OSGBPB: jmp     (GBPBV)
OSBPUT: jmp     (BPUTV)
OSBGET: jmp     (BGETV)
OSARGS: jmp     (ARGSV)
OSFILE: jmp     (FILEV)
OSRDCH: jmp     (RDCHV)
OSASCI: cmp     #$0D
        bne     OSWRCH
OSNEWL: lda     #LF
        jsr     OSWRCH
        lda     #CR
OSWRCH: jmp     (WRCHV)
OSWORD: jmp     (WORDV)
OSBYTE: jmp     (BYTEV)
OSCLI:  jmp     (CLIV)
hw_nmi_vec:        .word   HANDLER_NMI
hw_res_vec:        .word   HANDLER_RESET
hw_irq_vec:        .word   HANDLER_IRQ
HANDLER_RESET:
        ldx     #$19
LFF1A:  lda     TBL_DEFAULT_VECTORS,x
        sta     IRQ1V,x
        dex
        bpl     LFF1A
        txs
        txa
        inx
        stx     $EA
        stx     ROW_MULT_TAB_PTR+1
        stx     $E7
        lda     #$0A
        sta     VAR_FD+1
        lda     #$8A
        sta     IO_SYS_PIA_CONTROL
        lda     #$07
        sta     IO_SYS_PIA_PORT_C
PRINT_BBC_BASIC:
        jsr     PRINT_IMMEDIATE
        .byte   $06,$0C,$0F
        .text   "BBC BASIC"

        .byte   $0A,$0A,$0D
        lda     #$0E
        sta     IO_SYS_VIA_T1_C_L
        lda     #$27
        sta     IO_SYS_VIA_T1_C_L+1
        lda     #$40
        sta     IO_SYS_VIA_AUX_CONTROL
        lda     #$C0
        sta     IO_SYS_VIA_IE
        lda     #$00
        ldx     #$04
LFF64:  sta     W_GFX_WIN_LEFT,x
        dex
        bpl     LFF64
        sta     GFX_CUR_V_LAST
        sta     GFX_CUR_V_LAST+1
        sta     BUFFER_0100_LESS_1
        lda     #$0E
        sta     VAR_FD
        lda     #$80
        sta     VAR_FD+1
        lda     $C000
        cmp     #$AA
        bne     LFF85
        jsr     LC001
        cli
LFF85:  jmp     ENTRY_PAGED_ROM
PRINT_IMMEDIATE:
        pla; sta STRING_POINTER
        pla; sta STRING_POINTER+1
PRINT_IMMEDIATE_LOOP:
        ldy     #$00			; y is zero throughout
        inc     STRING_POINTER
        bne     PRINT_IMMEDIATE_SKIP
        inc     STRING_POINTER+1
PRINT_IMMEDIATE_SKIP:
        lda     (STRING_POINTER),y
        bmi     PRINT_IMMEDIATE_EXIT
        jsr     OSWRCH
        jmp     PRINT_IMMEDIATE_LOOP
PRINT_IMMEDIATE_EXIT:
        jmp     (STRING_POINTER)
OSWRCH: jmp     (WRCHV)
DO_WRCH:php
        cld
        stx     VE4_BYTE_TEMP_X
        sty     VE5_BYTE_TEMP_Y
KEY_WAIT_FOR_RELEASE:
        bit     IO_SYS_PIA_PORT_C	; is repeat key pressed?
        bvc     KEY_RELEASED		; bit 6 of port C
        jsr     KBD_SCAN		; yes, scan again to debounce
        bcc     KEY_WAIT_FOR_RELEASE
KEY_RELEASED:
        jsr     WAIT_100_MS
KBD_SCAN_LOOP:
        jsr     KBD_SCAN
        bcs     KBD_SCAN_LOOP
        jsr     KBD_SCAN
        bcs     KBD_SCAN_LOOP
LFE8A:  tya
        ldx     #$17		; final in 24-byte table
        jsr     CHK_FOR_CTRL
LFE90:  lda     TABLE_FEBC,x
        sta     VE2_WORD_PTR
        lda     #$FD		; MSbyte of all printing routines
        sta     VE2_WORD_PTR+1
        tya
        jmp     (VE2_WORD_PTR)	; jumps to printing routine
CHK_FOR_CTRL_AGAIN:
        dex
CHK_FOR_CTRL:
        cmp     TABLE_FEA4,x
        bcc     CHK_FOR_CTRL_AGAIN
        rts
TABLE_FEA4:
        .byte   $00,$08,$09,$0A,$0B,$0C,$0D,$0E
        .byte   $0F,$1E,$7F,$00,$01,$05,$06,$08
        .byte   $0E,$0F,$10,$11,$1C,$20,$21,$3B
TABLE_FEBC:	
        .byte	<LFD1D, ; INVERT_CHAR
		<LFD35,	; KEY_BS
		<LFD11, ; INC_CUR_POSN
		<LFD3B, ; KEY_LF
		<LFD60, ; KEY_VT
		<LFD42, ; KEY_FF
		<LFD19, ; PRINTING_FD19
		<LFD66  ; KEY_S0
		
	.byte	<LFD6B, ; KEY_S1
		<LFD56, ; KEY_RS
		<LFD29, ; DO_DELETION
		<LFDB8, ; KEY_CNV_TST
		<LFDAB, ; KEY_21_24
		<LFD73, ; KEY_SHIFT_LOCK
		<LFD7B, ; KEY_CURSOR_CTRL
		<LFDBB  ; KEY_TEST_CTRL
	.byte	<LFD87, ; KEY_COPY
		<LFD99, ; KEY_DEL
		<LFDB8, ; KEY_CNV_TST
		<LFDB1, ; KEY_20
		<LFDAF, ; KEY_3C_3F
		<LFDA1, ; KEY_20
		<LFD9F, ; KEY_21_3A
		<LFD9B  ; KEY_5B_5F