Living in the future!

The next version of Unvanquished will run on SDL3! Our release will also run natively on Wayland, and many libraries will be updated! Wait, what? Today we offer you a dive into an underestimated topic of game development: the building of redistributable engines and the related infrastructure!

An overlooked topic

It’s a topic often overlooked when you’re not deeply involved in the development of a cross-platform software like a game: it’s not enough to implement an engine that behaves the way you want it to be, it’s not enough to work on a gameplay that’s fun, if in the end you cannot distribute your game and get it run on someone else’s device.

It works on your computer? Fine, but we will not ship your computer with the game to all players…

It works on my computer. Yes but we will not give your computer to the client.
Despite a very common shared belief, the important milestone isn’t the invention of the wheel, it’s the invention of the road. Because once you invented the road, you invented infrastructure maintenance. And only then the wheel becomes viable, and then you can invent everything else starting from that, being a car, trains, logistics, the Internet, or a game engine for online multiplayer games like our Dæmon engine.

Before the road is invented, the wheel is nothing more than a cool concept that cannot be delivered to users. And without the specific infrastructure we will talk about in this blog post, our work would deliver nothing more than cool screenshots, not a game you can actually play.

From an user perspective, it can be tempting to complain about time being spent on things not improving the directly perceived experience (like gameplay!) but the very secret science is that, without such effort being spent, a game isn’t more than a vaporware with cool demo videos. 🤫️

So, today, we look at one key topic of infrastructure maintenance that makes possible to make a game engine that can be distributed, making possible for a game to be played.

SDL3 + Unvanquished = ❤️

So, we bumped a lot of the libraries we build our engine against. But one big bump is the move from SDL2 to SDL3. This move is not only about us getting some up-to-date libraries with fixes, it required to port our code to the new API.

Unvanquished + SDL3 = Love

Since SDL3 isn’t available in most Linux distributions yet, to keep the engine easily buildable by anyone on Linux, we distribute a prebuilt build of SDL 3.2.22 in our downloadable external deps archive.

Usually, we distribute all the libraries used to build the game in the downloadable external deps archive for Windows and macOS but only distribute the NaCl toolchain in the Linux deps archive as Linux users prefer to use their system libraries (with good reasons!). But SDL3 is so edgy we better ship it, because most users wouldn’t have it among their beloved system libraries to begin with… We live in the future of your Linux distribution.

With the next version of the game, every player will benefit from SDL3!

Unvanquished + Wayland = 💪

Alongside the fact that SDL3 works better with Wayland than SDL2, the next engine will works better on Wayland for a greater reason: previously you could only use a native Wayland display if you built the engine yourself. Our released engine was only built for X11 and then relied on XWayland when using a Wayland desktop. That wasn’t a big deal at all, it worked well, but we could do better.

Now that we deeply reworked our release build environment and spent time working again on the SDL3 build, we took the opportunity to enable the Wayland backend and make sure it properly builds ans runs.

If you used Flatpak or your distribution provided Unvanquished compiled against their own SDL2, you may already have benefited from native Wayland rendering, but with the next version of the game, every player will be able to benefit from Wayland!

Backrooms do exist

In fact, all that effort to upgrade our libraries, toolchains and build environment was a 10 months effort! Yes we started this in November of 2024 and only merged this in October of 2025, after many iterations! Yes we did all of that in your back! 😱️

The development of a game is also filled with many of such kind of behind-the-scene long-term work. It unfortunately doesn’t bring much visible changes to the user, but that’s something critical to do or the game development will start to face more and more problems. Because the rest of the world moves forward disregarding of what we do, we should move too if we want to survive.

All that work is usually done silently, in places you may haven’t heard of, and you may live your whole life without knowing about all the challenges faced and problem solving that was required to continue to bring you sometime even no more than the exact same experience you’re used to.

Beware of not lagging behind…

Most of our release build process is scripted, and the build process of all our supported engines and game code binaries are built in docker environments.

Yo dawg I herd you like containers so we put a container in yo container so you can abstract while U abstract.

For the curious people around, we not only build Linux binaries in docker, but we also build the Windows binaries in docker using MinGW, and we also build macOS binaries in docker using Darling, a compatibility layer allowing to run macOS binaries on Linux (similar to Wine or Proton for Windows binaries), allowing us to run AppleClang and other things in Docker. That last part is very tricky but very convenient once it works.

Building everything in Docker with scripts means that once it works, it’s likely to work for a long time. « Don’t break something that works », some will say, and others will just not spend time on upgrading the build environment to allocate their precious times on other tasks. So, with time, things can become really old and lag far behind the current industry standards…

Things start to become problematic when we want to use language features from standards not available is the validated compiler, or we simply cannot upgrade to a library because upstream started using those language features…

Or we find ourselves unable to upgrade some libraries because the system is too old for building them. For example, for building the complete Wayland support in SDL3, you need libdecor, but that is not available in Debian Buster, even not in Debian Bullseye, but fortunately it is in Bullseye’s backports. So at some point, we need to upgrade our build environment.

Also upgrading our build environment may help us bringing you better performance in our final product, either because the updated compiler implements new optimizations, either because the said compiler makes possible to build newer versions of the libraries shipping optimizations themselves.

The Big Bump

So, we moved our Linux baseline from Debian Buster to Debian Bullseye. We do know that Bookworm came after Bullseye and that Trixie is even there! But we need to make sure our binaries are compatible with many distributions, including some Long Term Support ones. Other non-Debian versions may still use older environments, etc. Actually it doesn’t mean that we strongly support Bullseye, it means that we want the game to run on everything that came after Bullseye, including other Linux distributions that have different release schedules and may have published their release in the same time frame as Bullseye but with possible version mismatches.

Leap of faith, hoping your Linux binary will run on Linux.

Debian Bullseye gives us a good compromise between compatibility with LTS systems and new features and requirements. It bumps GCC from the version 8 to 10. For example this bumps the available C++ standard for engine development from C++ 17 to C++ 20! Also, the JPEG library is now able to build some faster Neon code for arm64. Unfortunately, this is still not enough to allow us to use the AVX2 code in the WebP library… We can’t have everything! We would need Bookworm as a baseline for that…

For building the Windows engines, we updated the build environment from Debian Buster to Debian Trixie, woohoo! This gives us MinGW GCC 14 instead of MinGW GCC 8!

For building both Linux and Windows engines, and the game virtual machines, we went from CMake 3.13.4 to… Cmake 3.31.8, the highest CMake available before CMake 4 at the time we updated our docker scripts. Some dependencies don’t build with CMake 4 yet, so that’s not an option for us yet.

For building the macOS engines, we went from CMake 3.16.9 to 3.28.6, as higher versions don’t run yet within the Darling version we still use.

For developers, we created a page on the wiki detailing the highest versions of various things (language standards, tools, compilers…) you can require when contributing to Unvanquished or the Dæmon engine:

The lib upgrade

We bumped a lot of libraries, as much as we could. We now use the latest versions of the said libraries, one exception is that we upgraded to WebP 1.5.0 instead of 1.6.0 since 1.6.0 can’t be built in the Debian Buster environment because of missing AVX2 intrinsics support in GCC 10. That’s fine.

The biggest upgrade can be seen on Linux libraries. We previously built against system’s static libraries for some of them. This made the build faster, but it meant we used libraries as old as the ones the old Debian we used shipped (which meant Buster, meh). So even if we’re not on Buster anymore, we also made sure we also rebuild all the deps ourselves for Linux, to make sure our Linux engine binaries use the exact same versions we use in Windows and macOS engines. Not only it makes sure we get the latest fixes and improvements, it also reduce the differences between engines of those systems.

Here is a selection of libraries that are now updated. Our next release will use them:

  Before Now
Linux Windows & macOS Linux, Windows & macOS
SDL 2.32.8 2.32.8 3.2.22
OpenAL 1.23.1 1.23.1 1.24.1
PNG 1.6.36 1.6.39 1.6.50
JPEG 1.5.2 2.1.5.1 3.1.1
WebP 0.6.1 1.3.2 1.5.0
Ogg 1.3.2 1.3.5 1.3.6
Vorbis 1.3.6 1.3.7 1.3.7
Opus 1.4 1.4 1.5.2

Breakpad + MinGW + DWARF5 = 🔥

By updating both the GCC compiler to build Linux binaries and the MinGW compiler to build Windows binaries, we faced an interesting problem. We couldn’t extract debug symbols from them!

When they say you can break too.

We use Breakpad for generating and analyzing crash dumps for the Dæmon engine and NaCl gamelogic modules, and not having Breakpad working would be very annoying!

The thing is that upstream Breakpad doesn’t support MinGW, so we use  a fork (based on Jon Turney’s work) that adds support for MinGW. But like anything else, as long as it worked, it wasn’t updated… and that old version supported DWARF4 debug symbols but not DWARF5 ones, and newer compilers use DWARF5 by default. One can say there is a compiler and linker switch to force the usage of older debug symbols formats, it’s true, but that only applies to newly generated symbols, not to symbols imported from libs! We were screwed!

The problem was that our fork supporting MinGW didn’t supported DWARF5, while upstream Breakpad supported DWARF5 but did not supporting MinGW… So we had to roll up our sleeves, and merge both of them to cast the Breakpad to rule them all! Here is our Breakpad for MinGW and more.

Goodness incoming!

As we move toward our next release, stay tuned, and play the game! Download Unvanquished, and join a server for getting some fun! :bsuit:

5 thoughts on “Living in the future!”

  1. I just got fired, because i did too much background work that wasn’t visible. I know the pain 🙂

    So thank you for being awesome <3

    1. Ouch, that’s sad news! I hope you’re fine! It’s very important indeed to make sure the work is known in some way or another! Some people may believe they don’t need you because everything is working, while they need you for it to be working! 🙂️

      Thank you for the encouragement and maybe see you in game soon! 😉️

  2. I just learned from Unvanquished from a post made on phoronix about your porting to SDL3. I will have my look on the next version!

    I would like to make one suggestion, and this is to support motion (gyro) aiming! You can see a lot of videos on Youtube about what it is and how it’s awesome (for example, this one: https://www.youtube.com/watch?v=rOybuNm9XR8) and you can also see the gyro wiki (http://gyrowiki.jibbsmart.com/) for more details and even some code examples in some posts like this one (http://gyrowiki.jibbsmart.com/blog:7-building-blocks-for-better-controls) or this one (http://gyrowiki.jibbsmart.com/blog:player-space-gyro-and-alternatives-explained). So yeah, if you would support motion aiming natively, that would be awesome!

    P.S. There is a typo where you said that “toolchains and build environment was a 10 months effort” and then you said that it started in “2004” instead of “2024”. I mean, 2 decades is not much of a difference but still, better to fix that 😅

    1. Hi, and welcome! I’ll look at that gyro aiming thing, thanks for all those links. 🙂

      We haven’t fully implemented gamepads/joystick support yet, as controlling player actions (move, aim, in-game interaction) is already implemented, but controlling the UI isn’t yet…, so we first need to finish that before improving the gamepad support with such gyro thing. 😉

      I fixed the typo, thanks for the report! Hehe yes it was obvious it wasn’t 20 years. 😁

Leave a Reply

Your email address will not be published. Required fields are marked *