Tuesday 6 June 2017

Gotchas When Porting C++ and OpenGL Applications to the Dreamcast

Over the past month or so I've been steadily working on porting my game engine Simulant to the Dreamcast. While it's not quite ready for prime-time, I did discover a lot of road-bumps along the way, and I thought I should write some of them down so that anyone else porting to the Dreamcast will at least have some results on Google to look at!

Compile the Dreamcast SDK with GCC 4.x

It didn't take very long to compile my code, but when it came to linking all kinds of trouble awaited me. Whenever I tried to link, most of the C++ symbols (things like string and vector) were missing. After several days trying different linker flags I decided the problem must be with the SDK itself. A quick `nm` of libstdc++.a showed up the problem; only a handful of symbols were in there!

I've been using a Docker container to compile my code, which is fortunate because it allowed me to gradually roll back the Fedora version until I hit one that correctly compiled libstdc++. Fedora 21 is where it worked!

The moral of the story is that for some reason, GCC 5.x and above will not correctly compile libstdc++.a from GCC 4.x - so if you're compiling the SDK for C++ code, you're going to need to use an old GCC version.

Don't rely on std::atomic or std::async

The SH4 CPU only has a single limited atomic instruction which rules out support for std::atomic. That by itself wouldn't be so bad, but it turns out that even though the standard defines that std::async can be implemented without atomics, GCC hasn't done that.

In most cases it's trivial enough to build what you need using std::mutex and std::thread - but it is a bit of a hassle.

std::chrono::high_resolution_clock ... er... isn't

This had me confused for a while. I had a sample GL application running; a spinning cube, and it would run at a consistent 1FPS. I know the DC is slow compared to modern machines, but, 1FPS for a cube?!

Turns out that the "high resolution" timer had an accuracy of 1 second! Using the built-in KallistiOS timer functions fixed it.

libGL is still a WIP

The GL port for the DC is a great little library, but it has some rough edges. I recommend that you get your application runnable on both your PC and the DC and focus on targetting GL 1.1. If the graphics in your application don't work on the Dreamcast but do on the PC then investigate and submit a patch!