Develop C Programs for the BBC Micro Using VBCC on macOS with Docker for 6502 Architecture

Retro Game Coders

Utilizing CC65 as a C compiler is fantastic, but working with the BBC Micro and Master has been quite challenging. Despite the promising work by a few community members, I haven’t made significant progress yet.

I was excited to discover that the impressive VBCC compiler, which I previously used for Amiga and Atari ST development, offers excellent support for BBC, along with many other 6502-based platforms.

VBCC runs flawlessly on Windows!

To get started on Windows, ensure you set your environment variables correctly. Check the end of the page for instructions on creating your BBC disk and executing your programs.

set VBCC=C:\Users\chrisg\vbcc6502\vbcc6502_win\vbcc
set PATH=%VBCC%\bin;%PATH%

Unfortunately, the pre-compiled binaries and compile instructions are only available for Windows and Linux, as the VBCC creator lacks access to a Mac.

Following the Linux/BSD instructions on my Mac proved to be cumbersome, so I first attempted Parallels, which worked but isn’t recommended for everyone. Then, I had a breakthrough.

We’ll use a lightweight Docker container via OrbStack to virtualize Linux, allowing us to run the existing binaries!

Installing and Running OrbStack via Homebrew

OrbStack is free for personal use and provides a lightweight Linux virtual machine, unlike Docker Desktop. While it’s preferable to run ARM images natively, my x86_64 images on Apple silicon will utilize emulation, which is fine for CLI toolchains with minimal performance impact.

If we later acquire an ARM64 Linux VBCC bundle or build VBCC/vasm/vlink from source for ARM64, we can switch to --platform linux/arm64 for native performance.

brew install --cask orbstack

What This Means

Homebrew casks install GUI applications to /Applications and configure their services. By installing only the CLI formula, you get binaries without the app that starts the Linux VM. Using --cask ensures we get the complete package.

Completing and Testing OrbStack

First, verify that the application/GUI installation completes:

open -a OrbStack

Now, let’s check that the CLI is functional:

docker version

To test Docker, try running the Hello World container:

docker run --rm hello-world

(You may need to enter your Mac password)

If this prints the greeting message, Docker is set up correctly.

Installing VBCC

We need to create a directory for our project:

mkdir -p ~/vbcc-6502 && cd ~/vbcc-6502

Download the 6502 zip file and move it to our new directory:

cp ~/Downloads/vbcc6502_r4p2.zip .

In the same directory, create a Dockerfile to set up our Linux container:

nano Dockerfile

Here’s the Dockerfile content:

FROM --platform=linux/amd64 debian:stable-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
    ca-certificates unzip make gcc libc6-dev \
 && rm -rf /var/lib/apt/lists/*
# Place vbcc6502_r4p2.zip next to this Dockerfile before building
COPY vbcc6502_r4p2.zip /tmp/vbcc6502_r4p2.zip
RUN mkdir -p /opt && \
    unzip -q /tmp/vbcc6502_r4p2.zip -d /opt && \
    # Attempt to auto-detect layout, else use known structure
    if [ -d /opt/vbcc6502/vbcc6502_linux/vbcc ]; then \
      ln -s /opt/vbcc6502/vbcc6502_linux/vbcc /opt/vbcc; \
    else \
      VBCCDIR="$(find /opt -type d -name vbcc -print | head -n1)"; \
      ln -s "$VBCCDIR" /opt/vbcc; \
    fi && \
    ln -s /opt/vbcc/bin/* /usr/local/bin/ && \
    rm -f /tmp/vbcc6502_r4p2.zip
ENV VBCC=/opt/vbcc
ENV PATH="/opt/vbcc/bin:${PATH}"
WORKDIR /src
CMD ["/bin/bash"]

Next, we start the Docker build process:

docker buildx build --platform linux/amd64 -t vbcc-6502:amd64 .

Testing VBCC

Now, we’ll create a basic hello.c source file:

#include 
int main(void) {
    puts("Hello, 6502");
    return 0;
}

Run the VBCC compiler through our virtual machine with the following command, targeting C64 and outputting a .prg file for use in Vice or any C64 emulator:

docker run --rm --platform linux/amd64 -v "$PWD:/src" vbcc-6502:amd64 bash -lc \ 'vc +c64 -O2 hello.c -o hello.prg'

For BBC, adjust the target and output filename as follows:

docker run --rm --platform linux/amd64 -v "$PWD:/src" vbcc-6502:amd64 bash -lc \ 'vc +bbc -O2 hello.c -o hello'

Running BBC Programs

Unfortunately, I am not aware of a BBC emulator that supports command line execution like Vice does. Luckily, BeebEm can create BBC disk images:

After creating the disk, import your new program:

Use *CAT to list the files on your disk.

Once your disk is populated with your program, you can execute it and enjoy the results!

Execute your program using *RUN FILENAME.

You will need to update the disk with new versions each time you recompile, but you can continue to use the same disk.

Additionally, my browser-based BBC emulator using JSBeeb allows you to upload your disk and execute it there. I plan to develop a utility to simplify the disk creation process or to run compiled code without needing BeebEm every time.

Optional .dockerignore

To speed up builds, we can create an ignore file:

.git
build
dist
node_modules
*.d64
*.prg
*.img
*.zip

Makefile for Compiling Convenience

Given that the compiler command becomes quite lengthy with Docker integration, let’s simplify things.

Here’s a flexible Makefile that accepts parameters for target, input, and output, designed to work seamlessly with our Docker image while providing sensible defaults.

# vbcc 6502 via Docker
IMAGE     ?= vbcc-6502:amd64
PLATFORM  ?= linux/amd64
# Overridable parameters
TARGET    ?= c64          # e.g. c64, bbc, vic20, apple2r, nes, atari, x16
SRC       ?= hello.c      # one or more sources, space-separated
OUT       ?= hello.prg    # output filename
OPTS      ?= -O2          # additional compiler options, e.g. -g -O3
VC        ?= vc           # vbcc driver in the bundle
.PHONY: build list-targets shell clean version

build: @docker run --rm --platform $(PLATFORM) -v "$$(pwd):/src" $(IMAGE) bash -lc '$(VC) +$(TARGET) $(OPTS) $(SRC) -o $(OUT)'

list-targets: @docker run --rm --platform $(PLATFORM) $(IMAGE) ls /opt/vbcc/config

shell: @docker run --rm -it --platform $(PLATFORM) -v "$$(pwd):/src" $(IMAGE) bash

version: @docker run --rm --platform $(PLATFORM) $(IMAGE) bash -lc '$(VC) -h || true; vbcc6502 -h || true'

clean: @rm -f $(OUT)

This allows us to set the input, output, target, and any other options without necessitating edits to the Makefile each time.

The line .PHONY: build list-targets shell clean version marks our five targets as phony, ensuring their recipes run each time they’re called, without considering existing files in the filesystem.

How to Use the Makefile

# defaults: c64, hello.c → hello.prg
make build

change target

make build TARGET=bbc OUT=hello-bbc

multiple sources

make build TARGET=c64 SRC="main.c util.c" OUT=demo.prg

pass extra options

make build TARGET=apple2r OPTS="-O3 -g" OUT=game

More Complete Hello World .C

You’ll notice that earlier BBC examples might cause the machine to freeze post-execution.

Good news—on the BBC target, you can use +bbcr to return the user to BASIC after the program finishes.

In the example below, “Hello World!” won’t be visible after execution because we clear the screen using a BBC “VDU” command (the ASCII character 12), but you *will* see “Woot!” instead.

#include 
#include 
int main(void) {
    printf("Hello World!");
    __vdu_sequence(1);
    putchar(12);
    __vdu_sequence(0);
    printf("woot!\n\r");
    return 0;
}

There are numerous other VDU commands useful for future projects.

What’s Next?

With a functioning compiler for BBC projects, I’m ready to start porting my C Dungeon game.

First, I need to create a conio.h, the library I depend on for text output. I’ll also explore tools that simplify running compiled code directly or creating/updating BBC disks more efficiently. Stay tuned!



Original article by retrogamecoders.com

Main Menu