Developing Games for the Sega Dreamcast
In March 2026, I joined some of my coworkers for a two day long weekend Game Jam. While many of us have professional software development experience, few of us have true gamedev credentials, with my own Pico-8 hobbyist projects being among the more noteworthy. Despite this, there were many fine and interesting submissions, even if they were pretty rough around the edges. I was particularly fond of my own entry — Gravityscape — even if it wasn't voted into the top three (I was heavily docked for barely utilizing the "gravity" theme). Made in the excellent Picotron game engine, I'm pretty proud of how polished it is, especially after only two days. I'll admit I left the gameplay rather barebones intentionally, instead devoting my precious 48 hours to things like fading effects and scrolling text.
A few weeks later, I found myself down a different rabbit hole, looking at homebrew toolchains for retro video game consoles. I've spent a great deal of my time experimenting and playing with old video game hardware, yet I've never been able to actually make any applications for any of them (save for a very poor attempt at Pong on a Game Boy). I barely dedicate enough time to make video games in modern engines, and that's without worrying about learning the ins and outs of legacy hardware RAM restrictions and whatnot. It doesn't help that many of them tend to have rather poor documentation and only recently are treating Linux as a first-class developer platform. I've had my eye on the Natu tookit for GBA for the Nim programming language (my beloved), but it was still a bit low level for me to really dive into (not to mention Nim editor tooling continues to more stagnant than I hoped).
Enter Raylib. Designed to be an easy-to-use, easy-to-setup video game library, it runs on a number of different hardware platforms and has bindings in many different languages. It's rather well documented, with an API and fundamental structure that makes game programming in it very similar to Pico-8/Picotron. Most of the description on the page talks about supporting more mainstream platforms, like desktop OS's and the web, but down at the very bottom there's an image showcasing the library architecture, alongside an expanded list of logos of supported platforms.
Shown there are a few logos not mentioned above, including several video game consoles such as the Nintendo 64 and Switch, the PlayStation, and most interestingly to me — the Sega Dreamcast.
It's Still Thinking
While I admittedly don't use my Dreamcast as much as some of my other systems, I am very fond of it, and I have always heard good things about its development environment. Primarily structured around the KallistiOS SDK (KOS), judging from the number of headlines I see, it's a very active scene. I had explored learning it in the past, but never had the time or interest to learn another new game library. Why specialize on a niche library for an outdated system, when I could learn something with potential for web and desktop development, like Picotron?
If Raylib really did support the Dreamcast, this could change that calculation. The library API was well documented and structured in a similar fashion to how I think about game development. There is even the possibility that the same game code could (with some small changes) compile to both Dreamcast and modern machines. I would likely need to use the C++ bindings due to compiler support, rather than a language I might more personally prefer, but that wasn't a dealbreaker.
What finally sealed the deal on this project was discovering the repository of a Tetris clone developed in Raylib targeting the Dreamcast specifically. A quick glance through the source code gave me much hope. I saw almost entirely Raylib functionality, not arcane RAM manipulation or manually managing disc access. Even the Makefile was straight-forward enough to follow. Upon seeing this, I decided to set out and develop my very first Dreamcast game.
The Proof of Concept or, is This Even Worth My Time
There are two major hurdles in learning a new game engine or framework. The first would be learning how to install and set up the KOS SDK for development, configuring it to build a Raylib application, and then creating a Dreamcast .cdi file that I could run via emulator or burn onto a CD-R. I didn't know how to do any of this. The second (and more time consuming) challenge would be to actually create a game itself. For the sake of this article, I just wanted to focus on the former. This is less an exercise about how good a game dev I am, more of how user friendly the Dreamcast SDKs are.
Fortunately, setting up the toolchains proved to be just as easy as I'd hoped. The instructions to install KOS for Linux (including specifically which packages I would need for Arch) are laid out in the self-proclaimed Dreamcast wiki. I was a little disappointed that there was no AUR package for this, but given how the instructions required changing permissions on an /opt subdirectory and compiling two repositories, I think I can forgive them.
Top tip: I like to keep the packages on my Arch machine well-organized, so rather than just blindly install dependencies I would forget the purpose of, I created a custom PKGBUILD group to install them. That way, I would only ever see my kos-deps package under manually installed dependicies, and they can be cleaned up automatically in the future.
Once KallistiOS was successfully installed, I then ran the script provided by the raylib4Dreamcast project, which amends the KOS install to include the needed libraries for Raylib (which must also separately be installed, fortunately through my package manager). When building a project, KOS produces an .elf executable file, which I have no idea what its purpose is. I thus had to build and install a separate mkdcdisc tool which will convert .elf files into Dreamcast .cdi disc images. With all that one-time setup out of the way, it was only a matter of writing a simple program to test it. I heavily based my example off of one from the Tetris-RayLib4DC repository, and made a cube bounce around the screen a la DVD menu.
#include <raylib.h>
#include "cube.h"
#ifdef DREAMCAST
#include <kos.h>
KOS_INIT_FLAGS(INIT_DEFAULT);
#endif
int main() {
const int screenWidth = 640;
const int screenHeight = 480;
Cube cube = Cube();
InitWindow(screenWidth, screenHeight, "Dreamcast Test");
SetTargetFPS(60);
while (true) {
BeginDrawing();
ClearBackground(WHITE);
cube.update();
cube.draw();
EndDrawing();
}
return 0;
}
// cube.h
#ifndef CUBE_H
#define CUBE_H
class Cube {
public:
Cube();
void update();
void draw();
private:
int x;
int y;
int w;
int h;
int dx;
int dy;
};
#endif
// cube.cpp
#include <raylib.h>
#include "cube.h"
Cube::Cube() {
x = 100;
y = 100;
w = 8;
h = 8;
dx = 5;
dy = 5;
}
void Cube::update() {
x += dx;
y += dy;
if (x + w >= GetScreenWidth() || x <= 0) {
dx *= -1;
}
if (y + h >= GetScreenHeight() || y <= 0) {
dy *= -1;
}
}
void Cube::draw() {
DrawRectangle(x, y, w, h, RED);
}
Included here is the entire example I whipped up, just to get a sense of how things work. As you can see, it is very readable C++ game code, without any low-level Dreamcast behavior at all. You'll notice in the main.cpp file I included a DREAMCAST compilation flag. The neat thing about this set up is that aside from the kos.h header file and its init function, the code between a Dreamcast and Desktop build are identical. Perhaps this would change in a larger codebase, due to differences between controller layouts or some such, but for this a simple compile-time flag allows to build both targets easily.
The raylib4Dreamcast examples include a sample Makefile to create a Dreamcast build, but I personally find them fairly difficult to understand. Instead, I wrote a simple bash script that takes a few options as a parameter, and produces my two target builds.
#!/usr/bin/env bash
case "$1" in
desktop)
CXX="g++"
CXXFLAGS=""
LDFLAGS="-lraylib -lGL -lm"
EXE="desktop"
;;
dreamcast)
. /opt/toolchains/dc/kos/environ.sh
CXX="kos-c++"
CXXFLAGS="-DDREAMCAST"
LDFLAGS="-lraylib -lGL -lm -lkosutils -lADX"
EXE="dc.elf"
;;
clean)
rm -f *.o desktop dc.elf dc.cdi
exit 0
;;
*)
echo "Usage: $0 {desktop|dreamcast|clean}"
exit 1
;;
esac
echo "Compiling"
for cpp in *.cpp; do
$CXX $CXXFLAGS -c $cpp -o ${cpp%.cpp}.o;
done
echo "Linking"
$CXX *.o -o $EXE $LDFLAGS
if [ "$1" = "dreamcast" ]; then
echo "Generating Dreamcast CDI image"
mkdcdisc -e $EXE -o dc.cdi
fi
Is a Makefile cleaner? Perhaps, if you're familiar with them. However, I'm happy with this solution.
And indeed, I'm happy with this setup overall. I've wanted to get into retro development for some time now, but the daunting task of learning yet another build system and API always steered me away. With Raylib, I was able to quickly create a simple tech demo, with the full confidence that I could create a proper game with it. Tune in again in a few months to see how that effort is progressing. I'm fairly confident I'll have something to show.
@000