BBC Micro Development Environment

By modern standards, the BBC Micro is not that much fun to work on. The 2MHz CPU doesn't assemble code particularly quickly, the 32K RAM is quickly exhausted, and the disk drives are rather slow. And even once upgraded to fix all of that, the editing environment is still a bit painful.

For this reason, I prefer to do any BBC development on the PC…

Tools

dasm

The assembler I use is DASM. This is just a random one that I found that wasn't awful, wasn't at version 0.something, and had its own macros. So far it has proven acceptable.

emacs

For editing, I use emacs with my 6502-mode, a slightly modified version of Per Olofsson's dasm-mode.

65Link

John Kortink's 65Link lets you use your other computer for something useful: a file server for your BBC Micro. It's like having an endless number of 8-sided discs, but PAGE stays at &E00.

Compiling

I compile projects using GNU make. emacs supports this fairly well, and it's easy to set up.

It's mainly easy because my Makefiles are so decidedly unclever. Here's pretty much what I use:

.PHONY:all
all:
        ../dasm/bin/dos/dasm.exe mandel.s65 -f3 -lmandel.lst -smandel.sym -omandel.bbc

This assembles mandel.s65 and puts the result in mandel.bbc.

Getting it onto the BBC with 65Link

My BBC is linked up to my second PC using a 65Link cable. By sharing the relevant 65Link volumes folder, my development PC can copy files to somewhere the BBC can see them immediately.

.PHONY:all
all:
        ../dasm/bin/dos/dasm.exe mandel.s65 -f3 -lmandel.lst -smandel.sym -o_doMANDEL
        cp _doMANDEL //p1/beebvols/dev/0/

(p1 is the name of my second PC; I've got the 65Link volumes folder shared out as beebvols, and dev is just a random volume.)

Now the file, when assembled, appears on the BBC (when I have the dev volume mounted) as $.MANDEL, albeit with bogus load and execution addresses.

Setting load and execution addresses with 65Link

65Link stores the addresses in a .lea file, named after the main file. The format is a very simple 12 bytes: load address (4 bytes), exec address (4 bytes) then attributes (4 bytes).

This data can be specified as part of the source code. Put the following in the source code somewhere, after the first org in the code segment, so that the data will appear at the beginning of the file:

                org .-12
                ; 12-byte LEA header file for 65link
lea_header subroutine
                dc.l .+12          ;load address
                dc.l gui           ;exec address
                dc.l 0             ;attributes

In the Makefile, use dd to split the output file into two, and copy these two new files to the 65Link volume:

.PHONY:all
all:
        ../dasm/bin/dos/dasm.exe mandel.s65 -f3 -lmandel.lst -smandel.sym -omandel.bbc
        dd if=mandel.bbc of=_doMANDEL.lea count=12 bs=1 status=noxfer
        dd if=mandel.bbc of=_doMANDEL skip=12 bs=1 status=noxfer
        cp _doMANDEL.lea //p1/beebvols/dev/0/
        cp _doMANDEL //p1/beebvols/dev/0/

Now the file will have the correct load and execution addresses set automatically based on the source code.

Quick turnaround

Create a !BOOT file that runs your program with *RUN (or whatever). Now you can start it up with Shift+BREAK. Put this bit of code at the start of your program:

lda #$ff
ldy #%11110111  ;clear bit 3
ldx #%00000000  ;don't change any bits
jsr osbyte

Now a simple tap of BREAK will re-run your program. Doesn't get much easier than that.

The final version should probably not include this code…

Quick turnaround (Tube)

If you're working on the 6502 second processor, using *RUN from !BOOT to start your program causes it to be run automatically on each press of BREAK. No auto boot, no BASIC prompt. The above code doesn't do anything useful, and it's kind of annoying to reload your program if it's not on drive 0.

This is a standard second processor feature, so you're stuck with it. Fortunately it can be worked around with a BASIC program along the following lines:

10F$="PROGRAM"
20DIMX%&200:$(X%+256)=F$:X%?0=(X%+256)MOD256:X%?1=(X%+256)DIV256:Y%=X%DIV256:A%=5:CALL&FFDD:OSCLI"L."+F$:CALLX%!6

(Set F$ to the name of the program you're going to run.)

This does the equivalent of a *RUN, but because the actual CALL is done from BASIC the system is fooled into thinking BASIC is the active program. Result: you're back in BASIC on a tap of BREAK, and the whole thing behaves mostly like it does on an unexpanded system.

Note that this program is almost 128 bytes. It also allocates a string, and it allocates a 512 byte buffer. You may have to play with PAGE, if your program loads low enough – or rewrite my code to be less wasteful.

(This code will work fine on an unexpanded BBC as well, but the comment about PAGE goes double. Maybe even treble…)