This document describes how to build MINERVA on Windows, Linux, and macOS:
- the SDL2 host emulator for running ROMs
fasm.pyandmfasm.pyfor building ROM cartridges- the host GCC/Clang toolchain used to build the emulator and tools
- the current status of a GCC toolchain for Fantasy Pi ROMs
- the Arm AArch64 cross-toolchain used for the Raspberry Pi kernel
- Circle, the bare-metal Raspberry Pi support library
The commands assume this repository is checked out as fantasy-pi.
First, create a game. A manual with opcodes can be found in fantasy-pi\docs\guide.html
Copy the source files and the assets to fantasy-pi\input_asm\
cd fantasy-pi
.\build.bat
copy the kernel file fantasy-pi\kernel8.img to the boot partition of your Raspberry Pi 5 sdcard.
+------------------------------------------+
| Bare-Metal Kernel |
| (Circle + ARM64 Startup) |
+------------------------------------------+
| Fantasy VM | Renderer | Audio/Input |
+------------------------------------------+
| ROM / Cartridge Image |
| (Game Code + Assets + Metadata) |
+------------------------------------------+
See docs/build/BUILD.md for setup instructions.
Fantasy Pi Studio projects (.fproj) use the C/C++ ROM build path. Open the
.fproj in Fantasy Pi Studio, select the desired build configuration
(Debug, Release, or SizeOptimized), then run Build. The Studio build
service reads the active BuildConfigurations entry from the project file,
generates the project-local files in generated/, and invokes
tools/fpgcc/fpgcc.py.
The build pipeline is:
.fproj + src/*.cpp + generated/*.cpp + assets/manifest.json
-> tools/fpgcc/fpgcc.py
-> build/game.fasm
-> macroassembler/mfasm.py
-> build/game.rom
If BuildKernelImage is enabled in the selected build configuration, Studio
also embeds the ROM into the Raspberry Pi kernel build and writes
build/kernel8.img.
The equivalent command shape for a C/C++ project is:
cd C:\path\to\fantasy-pi
python tools\fpgcc\fpgcc.py games\flappy_bird_cpp_demo\src games\flappy_bird_cpp_demo\generated\gameobject_scripts.cpp `
-I games\flappy_bird_cpp_demo\src `
-I games\flappy_bird_cpp_demo\generated `
-I sdk\include `
-o games\flappy_bird_cpp_demo\build\game.fasm `
--rom games\flappy_bird_cpp_demo\build\game.rom `
--runtime-fasm games\flappy_bird_cpp_demo\generated\gameobject_runtime.fasm `
--asset-manifest games\flappy_bird_cpp_demo\assets\manifest.json `
--gcc-flag=-O0 `
--gcc-flag=-g `
--gcc-flag=-Wall `
--gcc-flag=-std=c++17fpgcc.py is the current Fantasy Pi C/C++ compiler driver. It uses host
GCC/G++ for preprocessing and syntax checks, lowers the supported gameplay
subset to Fantasy Assembly, and then calls the ROM assembler. It is not a full
GCC backend for the Fantasy VM ISA. See docs/build/BUILD.md for the complete
toolchain setup and platform-specific details.
Use official package managers where possible. These links are stable entry points rather than version-pinned download files.
| Tool | Purpose | Link |
|---|---|---|
| Git | Source checkout and Git Bash on Windows | https://git-scm.com/downloads |
| Git for Windows | Windows Git + Unix tools (bash, cp, rm, wc) |
https://gitforwindows.org/ |
| Python | ROM tools and asset pipeline | https://www.python.org/downloads/ |
| CMake | Host emulator build generation | https://cmake.org/download/ |
| Ninja | Fast CMake build backend | https://ninja-build.org/ |
| SDL2 | Emulator window, audio, keyboard, gamepad | https://github.com/libsdl-org/SDL/releases |
| MSYS2 | Recommended native Windows MinGW environment | https://www.msys2.org/ |
| Visual Studio Build Tools | Optional MSVC compiler on Windows | https://visualstudio.microsoft.com/vs/cplusplus/ |
| vcpkg | Optional cross-platform C/C++ dependency manager | https://learn.microsoft.com/en-us/vcpkg/get_started/overview |
| Homebrew | Recommended macOS package manager | https://brew.sh/ |
| Arm GNU Toolchain | AArch64 bare-metal Raspberry Pi kernel compiler | https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads |
| Circle | Raspberry Pi bare-metal C++ environment | https://github.com/rsta2/circle |
| GCC sources | Source release for a future Fantasy Pi GCC port | https://gcc.gnu.org/releases.html |
| Binutils sources | Source release for a future Fantasy Pi assembler/linker port | https://www.gnu.org/software/binutils/ |
| GCC prerequisites | GMP/MPFR/MPC/ISL requirements | https://gcc.gnu.org/install/prerequisites.html |
| Raspberry Pi config.txt docs | Boot partition configuration | https://www.raspberrypi.com/documentation/computers/config_txt.html |
| Raspberry Pi Imager | SD card preparation utility | https://www.raspberrypi.com/software/ |
Important build directories:
| Path | Purpose |
|---|---|
build/cmake/ |
CMake host build for emulator and tests |
build/make/ |
Raspberry Pi bare-metal kernel Makefile |
assembler/src/fasm.py |
Base Fantasy assembler |
macroassembler/src/mfasm.py |
ROM/cartridge macroassembler with assets |
asset_compiler/src/assetc.py |
PNG/WAV/JSON asset converter |
games/test_game/ |
Example ROM project |
emulator/ |
Host emulator frontend |
vm/, renderer/ |
Shared VM and renderer code |
kernel/ |
Circle-based Raspberry Pi kernel |
The ROM builders are Python scripts. Image assets require Pillow and NumPy; without them the macroassembler falls back to dummy asset data.
Windows PowerShell:
py -3 -m pip install --upgrade pip
py -3 -m pip install Pillow numpyLinux/macOS:
python3 -m pip install --upgrade pip
python3 -m pip install --user Pillow numpyIf your distribution blocks pip --user, create a virtual environment:
python3 -m venv .venv
. .venv/bin/activate
python -m pip install Pillow numpyOn Windows PowerShell:
py -3 -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install Pillow numpyfasm.py assembles raw Fantasy Assembly into a binary instruction/data image. It does not build a full ROM header or assets. Use it for low-level tests and experiments.
Windows:
cd C:\path\to\fantasy-pi
py -3 assembler\src\fasm.py games\test_game\src\main.fasm -o build\test_game.binLinux/macOS:
cd /path/to/fantasy-pi
python3 assembler/src/fasm.py games/test_game/src/main.fasm -o build/test_game.binmfasm.py is the normal ROM builder. It supports macros, includes, .asset declarations, and produces a complete .rom or cartridge.bin.
Windows:
cd C:\path\to\fantasy-pi
New-Item -ItemType Directory -Force build | Out-Null
py -3 macroassembler\src\mfasm.py games\test_game\src\main.fasm `
-o build\test_game.rom `
-I games\test_game\src `
-I games\test_game\assetsLinux/macOS:
cd /path/to/fantasy-pi
mkdir -p build
python3 macroassembler/src/mfasm.py games/test_game/src/main.fasm \
-o build/test_game.rom \
-I games/test_game/src \
-I games/test_game/assetsFor the Raspberry Pi kernel build, the Makefile creates build/make/cartridge.bin automatically from games/test_game/src/main.fasm.
The emulator takes a ROM path as its first argument.
Windows:
.\build\host\fantasy_emulator.exe build\test_game.romLinux/macOS:
./build/host/fantasy_emulator build/test_game.romInput mapping in the SDL2 emulator:
| Control | Keyboard |
|---|---|
| D-pad | Arrow keys or WASD |
| A / jump | Z or Space |
| B | X or Left Shift |
| Start | Enter |
| Back / quit | Escape |
SDL2 game controllers are also supported through SDL's controller API.
Two Windows setups are supported. MSYS2/MinGW is the easiest if you want the same GCC-style workflow on all platforms. MSVC + vcpkg is also fine.
Install MSYS2 from https://www.msys2.org/ and open the UCRT64 shell.
pacman -Syu
pacman -S --needed \
git \
mingw-w64-ucrt-x86_64-gcc \
mingw-w64-ucrt-x86_64-cmake \
mingw-w64-ucrt-x86_64-ninja \
mingw-w64-ucrt-x86_64-SDL2 \
mingw-w64-ucrt-x86_64-python \
mingw-w64-ucrt-x86_64-python-pillow \
mingw-w64-ucrt-x86_64-python-numpyBuild:
cd /c/path/to/fantasy-pi
cmake -S build/cmake -B build/host -G Ninja \
-DBUILD_HOST_EMULATOR=ON \
-DBUILD_TOOLS=ON \
-DBUILD_TESTS=ON
cmake --build build/host
ctest --test-dir build/host --output-on-failureBuild a test ROM and run it:
python macroassembler/src/mfasm.py games/test_game/src/main.fasm \
-o build/test_game.rom \
-I games/test_game/src \
-I games/test_game/assets
./build/host/fantasy_emulator.exe build/test_game.romInstall Visual Studio Build Tools with the Desktop development with C++ workload. Install Ninja and CMake from the links above, or through Visual Studio.
Install vcpkg and SDL2:
cd C:\
git clone https://github.com/microsoft/vcpkg.git
.\vcpkg\bootstrap-vcpkg.bat
.\vcpkg\vcpkg.exe install sdl2:x64-windowsBuild from a Developer PowerShell for VS:
cd C:\path\to\fantasy-pi
cmake -S build\cmake -B build\host -G Ninja `
-DCMAKE_TOOLCHAIN_FILE=C:\vcpkg\scripts\buildsystems\vcpkg.cmake `
-DBUILD_HOST_EMULATOR=ON `
-DBUILD_TOOLS=ON `
-DBUILD_TESTS=ON
cmake --build build\host
ctest --test-dir build\host --output-on-failureIf CMake cannot find SDL2, set SDL2_DIR to the SDL2 CMake package directory or use the vcpkg toolchain file above.
Ubuntu/Debian:
sudo apt update
sudo apt install -y \
build-essential \
cmake \
ninja-build \
python3 \
python3-pip \
libsdl2-dev
python3 -m pip install --user Pillow numpyFedora:
sudo dnf install -y \
gcc-c++ \
cmake \
ninja-build \
python3 \
python3-pip \
SDL2-devel
python3 -m pip install --user Pillow numpyBuild:
cd /path/to/fantasy-pi
cmake -S build/cmake -B build/host -G Ninja \
-DBUILD_HOST_EMULATOR=ON \
-DBUILD_TOOLS=ON \
-DBUILD_TESTS=ON
cmake --build build/host
ctest --test-dir build/host --output-on-failureBuild and run the test ROM:
python3 macroassembler/src/mfasm.py games/test_game/src/main.fasm \
-o build/test_game.rom \
-I games/test_game/src \
-I games/test_game/assets
./build/host/fantasy_emulator build/test_game.romInstall Homebrew from https://brew.sh/.
brew install cmake ninja sdl2 python
python3 -m pip install --user Pillow numpyBuild:
cd /path/to/fantasy-pi
cmake -S build/cmake -B build/host -G Ninja \
-DBUILD_HOST_EMULATOR=ON \
-DBUILD_TOOLS=ON \
-DBUILD_TESTS=ON
cmake --build build/host
ctest --test-dir build/host --output-on-failureBuild and run the test ROM:
python3 macroassembler/src/mfasm.py games/test_game/src/main.fasm \
-o build/test_game.rom \
-I games/test_game/src \
-I games/test_game/assets
./build/host/fantasy_emulator build/test_game.romIf SDL2 is installed by Homebrew but CMake does not find it, pass:
cmake -S build/cmake -B build/host -G Ninja \
-DCMAKE_PREFIX_PATH="$(brew --prefix sdl2)"This is the compiler used on your development machine to build fantasy_emulator, tests, and native helper code. It is not the Raspberry Pi kernel cross-compiler and not a Fantasy VM ROM compiler.
Recommended host compilers:
| Host | Recommended compiler |
|---|---|
| Windows | MSYS2 MinGW GCC or MSVC Build Tools |
| Linux | distro GCC or Clang |
| macOS | Apple Clang from Xcode Command Line Tools |
Minimum requirement: C++17.
Check versions:
cmake --version
ninja --version
python3 --version
c++ --versionWindows PowerShell equivalents:
cmake --version
ninja --version
py -3 --version
g++ --versionThe working ROM build path today is mfasm.py. A full GCC/binutils target for Fantasy Pi ROMs is not currently implemented in this repository.
The intended future toolchain would look like this:
fantasy-elf-gcc -O2 -ffreestanding -c game.c -o game.o
fantasy-elf-ld -T fantasy-rom.ld game.o -o game.elf
fantasy-elf-objcopy -O binary game.elf game.code
python3 macroassembler/src/mfasm.py wrapper.fasm -o game.romTo build such a toolchain on any platform, the missing pieces are:
- a binutils BFD target for the Fantasy VM object format or ELF relocations
- a GAS parser for Fantasy assembly, or a compiler that emits
.fasm - a GCC backend under
gcc/config/fantasy/ - libgcc helpers for division, multiplication, and possibly software floating point
- a ROM linker script and startup ABI
Generic GCC/binutils source-build prerequisites:
Linux:
sudo apt install -y build-essential bison flex texinfo gawk libgmp-dev libmpfr-dev libmpc-dev libisl-devmacOS:
brew install gcc binutils gmp mpfr libmpc isl bison flex texinfoWindows:
Use MSYS2 UCRT64:
pacman -S --needed \
base-devel \
git \
texinfo \
bison \
flex \
mingw-w64-ucrt-x86_64-gcc \
mingw-w64-ucrt-x86_64-gmp \
mingw-w64-ucrt-x86_64-mpfr \
mingw-w64-ucrt-x86_64-mpc \
mingw-w64-ucrt-x86_64-islGeneric source build layout:
mkdir -p $HOME/src $HOME/cross/fantasy-elf
cd $HOME/src
curl -LO https://ftp.gnu.org/gnu/binutils/binutils-2.43.1.tar.xz
curl -LO https://ftp.gnu.org/gnu/gcc/gcc-14.2.0/gcc-14.2.0.tar.xz
tar xf binutils-2.43.1.tar.xz
tar xf gcc-14.2.0.tar.xzAfter Fantasy-specific patches exist, the shape would be:
mkdir build-binutils
cd build-binutils
../binutils-2.43.1/configure \
--target=fantasy-elf \
--prefix=$HOME/cross/fantasy-elf \
--disable-nls \
--disable-werror
make -j$(nproc)
make install
cd ..
mkdir build-gcc
cd build-gcc
../gcc-14.2.0/configure \
--target=fantasy-elf \
--prefix=$HOME/cross/fantasy-elf \
--enable-languages=c \
--without-headers \
--disable-nls \
--disable-shared \
--disable-threads \
--disable-libssp \
--disable-libquadmath \
--disable-libgomp \
--disable-multilib
make all-gcc all-target-libgcc -j$(nproc)
make install-gcc install-target-libgccOn macOS, replace $(nproc) with $(sysctl -n hw.ncpu). On Windows/MSYS2, $(nproc) is available in the MSYS2 shell.
Until those Fantasy target patches exist, use mfasm.py for production ROMs.
This toolchain builds kernel8.img for Raspberry Pi. It is different from the Fantasy ROM toolchain.
Download the aarch64-none-elf Arm GNU Toolchain package for your host from:
https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads
Select the package for your host OS:
| Host | Toolchain flavor |
|---|---|
| Windows | mingw-w64-i686-aarch64-none-elf |
| Linux x86_64 | x86_64-aarch64-none-elf |
| macOS Intel | Darwin x86_64 AArch64 bare-metal package if available |
| macOS Apple Silicon | Darwin arm64 AArch64 bare-metal package if available |
Add the toolchain bin directory to PATH.
Windows PowerShell example:
$env:PATH = "C:\Program Files (x86)\Arm\GNU Toolchain mingw-w64-i686-aarch64-none-elf\bin;$env:PATH"
aarch64-none-elf-gcc --versionLinux example:
tar xf arm-gnu-toolchain-*-x86_64-aarch64-none-elf.tar.xz -C $HOME/opt
TOOLCHAIN_DIR=$(find "$HOME/opt" -maxdepth 1 -type d -name 'arm-gnu-toolchain-*aarch64-none-elf' | head -n 1)
export PATH="$TOOLCHAIN_DIR/bin:$PATH"
aarch64-none-elf-gcc --versionmacOS example:
tar xf arm-gnu-toolchain-*-darwin-*-aarch64-none-elf.tar.xz -C $HOME/opt
TOOLCHAIN_DIR=$(find "$HOME/opt" -maxdepth 1 -type d -name 'arm-gnu-toolchain-*aarch64-none-elf' | head -n 1)
export PATH="$TOOLCHAIN_DIR/bin:$PATH"
aarch64-none-elf-gcc --versionClone Circle next to fantasy-pi:
cd /path/to/parent
git clone https://github.com/rsta2/circle.git circleExpected layout:
parent/
fantasy-pi/
circle/
Make sure aarch64-none-elf-gcc is in PATH.
cd /path/to/parent/circle
./configure -r 4 -p aarch64-none-elf- -f
./makeall
make -C addon/linux
make -C addon/vc4/vchiq
make -C addon/vc4/soundThe important output libraries are:
lib/libcircle.a
lib/usb/libusb.a
lib/input/libinput.a
lib/fs/libfs.a
lib/fs/fat/libfatfs.a
lib/sched/libsched.a
lib/sound/libsound.a
addon/linux/liblinuxemu.a
addon/vc4/vchiq/libvchiq.a
addon/vc4/sound/libvchiqsound.a
If configure and makeall are not available in your shell, create Config.mk manually:
cd C:\path\to\circle
@"
PREFIX64 = aarch64-none-elf-
AARCH = 64
RASPPI = 4
"@ | Set-Content Config.mk -Encoding ASCIIThen build the required directories. Put the Arm toolchain, Git Unix tools, and Make in PATH:
$make = "C:\path\to\mingw64\bin\mingw32-make.exe"
$env:PATH = "C:\Program Files (x86)\Arm\GNU Toolchain mingw-w64-i686-aarch64-none-elf\bin;C:\Program Files\Git\usr\bin;$env:PATH"
$dirs = @(
"tools",
"lib",
"lib\usb",
"lib\usb\gadget",
"lib\input",
"lib\fs",
"lib\fs\fat",
"lib\sched",
"lib\net",
"lib\sound",
"addon\linux",
"addon\vc4\vchiq",
"addon\vc4\sound"
)
foreach ($dir in $dirs) {
Push-Location $dir
& $make
if ($LASTEXITCODE -ne 0) { throw "Circle build failed in $dir" }
Pop-Location
}For Raspberry Pi 5, use RASPPI = 5 and rebuild Circle. The current build/make/Makefile is tuned for Raspberry Pi 4 (cortex-a72); update its CPU flags before producing a Pi 5 kernel.
The kernel build expects Circle next to the repository:
parent/
fantasy-pi/
circle/
If Circle lives somewhere else, pass CIRCLE_HOME=/path/to/circle.
Windows PowerShell:
cd C:\path\to\fantasy-pi\build\make
$env:PATH = "C:\Program Files (x86)\Arm\GNU Toolchain mingw-w64-i686-aarch64-none-elf\bin;C:\Program Files\Git\usr\bin;$env:PATH"
C:\path\to\mingw64\bin\mingw32-make.exe clean
C:\path\to\mingw64\bin\mingw32-make.exeLinux/macOS:
cd /path/to/fantasy-pi/build/make
make clean
makeOutput:
build/make/kernel8.img
build/make/kernel.elf
build/make/kernel.lst
build/make/cartridge.bin
Format the boot partition as FAT32 and copy:
kernel8.img
config.txt
start4.elf
fixup4.dat
You can get Raspberry Pi firmware files from a Raspberry Pi OS boot partition or from the official firmware repository:
https://github.com/raspberrypi/firmware/tree/master/boot
Minimal config.txt for Raspberry Pi 4:
arm_64bit=1
kernel=kernel8.img
disable_overscan=1
hdmi_force_hotplug=1The kernel embeds build/make/cartridge.bin. You may also place a cartridge.bin on the SD card root; the kernel tries the SD-card cartridge first and falls back to the embedded cartridge.
Host emulator:
rm -rf build/host
cmake -S build/cmake -B build/host -G Ninja
cmake --build build/hostWindows PowerShell:
Remove-Item -Recurse -Force build\host -ErrorAction SilentlyContinue
cmake -S build\cmake -B build\host -G Ninja
cmake --build build\hostKernel:
make -C build/make clean
make -C build/makeCircle:
cd ../circle
make -C lib clean
make -C lib/usb clean
make -C lib/input clean
make -C lib/fs clean
make -C lib/fs/fat clean
make -C lib/sched clean
make -C lib/sound clean
make -C addon/linux clean
make -C addon/vc4/vchiq clean
make -C addon/vc4/sound cleanMake sure the runtime DLLs are next to fantasy_emulator.exe:
SDL2.dll- MinGW runtime DLLs such as
libgcc_s_seh-1.dll,libstdc++-6.dll,libwinpthread-1.dll,libmcfgthread-2.dll
The CMake build attempts to copy these automatically for MinGW builds.
CMake did not find SDL2. Install SDL2 and reconfigure from a clean build/host directory.
Install Pillow and NumPy:
python3 -m pip install Pillow numpyor on Windows:
py -3 -m pip install Pillow numpyUse MSYS2 or put Git for Windows Unix tools in PATH:
$env:PATH = "C:\Program Files\Git\usr\bin;$env:PATH"Use build/make/Makefile from this repository. It links with Circle's circle.ld, adds kernel/src/main.cpp, and groups static libraries with --start-group.
Link with libgcc.a from the same Arm GNU Toolchain used to compile the objects. The current build/make/Makefile resolves this automatically via:
$(CXX) -print-libgcc-file-name