Category: C

Setting up SDL3 on Linux

Setting up SDL3 on Linux

SDL3 program running on Raspberry Pi.

I knew it wasn’t going to be easy, but it turned out to be quite a bit more difficult than I thought.

The problem is, unlike SDL2, there are no dev versions of SDL3 etc. yet, so you have to build it from scratch.

I’ll be honest, I’m not sure I could have done it without this GitHub repository. User Ravbug who is very busy person (752 contributions on GitHub in the last year- I tip my hat to him or her!) who provided that repository.

It sets up SDL3, SDL_image, sdl_mixer and SDL_ttf.

Follow his link to the Wiki page Scroll down to the bottom for the Linux instructions. I can confirm that it works on Raspberry Pi as well.  You’ll need to install cmake first with

sudo apt install cmake

Then run his cmake to build everything and go for a coffee.
Now go into the build folder under sdl3-sample and do

make

That only takes a second or so.

After you’ve done that you’ll end up with a load of files including an executable sdl-min that you can run. That’s what generated the Tiger’s head – it plays The Sting film’s theme (The Entertainer) music as well demonstrating that it’s using SDL_mixer as well as SDL3 and SDL_ttf (I’m guessing) and of course SDL_image.

But that is just the start

To use SDL3 etc in your C program, you need a bit more configuration than with SDL2. I’m in uncharted waters here but used an AI- Claude 4 to help me get through and it did.

The problem is you have to tell VS Code where the header files are located, the .so files and also the executable needs to know at runtime.

I set up Ravbug’s sdl3_sample in my home folder so all paths start /home/david/sdl3-sample. 

This is my tasks.json

 

{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "shell",
            "label": "clang-14.0 build active file",
            "command": "/usr/bin/clang-14",
            "args": [
                "-I/home/david/sdl3-sample/SDL/include",
                "-I/home/david/sdl3-sample/SDL_image/include", 
                "-I/home/david/sdl3-sample/SDL_mixer/include",
                "-I/home/david/sdl3-sample/SDL_ttf/include",
                "-g",
                "${file}","${workspaceFolder}/hr_time.c",
                "-L/home/david/sdl3-sample/build",	
                "-Wl,-rpath,/home/david/sdl3-sample/build",				
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}",
                "-lSDL3",
                "-lSDL3_image", 
                "-lSDL3_ttf"   

            ],
            "options": {
                "cwd": "/usr/bin"
            },
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}

The lines that are SDL3 specific include the -I’s to provide the include path. -L the path to the .so files and the -rpath line is the path to the runtime files which gets linked into the executable.

If you add these three lines into c_cpp_properties.json then you’ll also avoid the dreaded red squiggles.

            "includePath": [
                "${workspaceFolder}/**",
                "/home/david/sdl3-sample/SDL/include",
                "/home/david/sdl3-sample/SDL_image/include",
                "/home/david/sdl3-sample/SDL_ttf/include"
            ],

And your C’s #includes need the files prefixed like this :

#include <SDL3/SDL.h>
#include <SDL3_image/SDL_image.h>
#include <SDL3_ttf/SDL_ttf.h>

And here it is running on my Pi.

Missile Command running on a Raspberry Pi 5 with SDL3

Converting from SDL2 to SDL3 on Windows

Converting from SDL2 to SDL3 on Windows

Missile Command running with SDL3

These notes were made when converting an existing C game that used SDL2 to SDL3 on Windows. The game was originally developed for Linux Format and I had got it running on Windows with SDL2.

Windows include paths have been made consistent with Linux. The include files path for SDL3 need to be SDL3\… when setting them up. For SDL2, I had them in a folder c:\SDL2\include but noted that in SDL2.h include files were like this:

#include "SDL_main.h"
#include "SDL_stdinc.h"

While in SDL3’s SDL.h they are

#include <SDL3/SDL_stdinc.h>
#include <SDL3/SDL_assert.h>

So I put them c:\SDL3\SDL3

When you include them in your software they are like this:

#include <SDL3/SDL.h>
#include <SDL3/SDL_image.h>

Which is how they are in Linux.

The rest of these notes are taken from the differences between the SDL2 and SDL3 versions of the game. They are not complete but intended to give you an idea of some of the changes you may need to do.

SDL_TTF

TTF_RenderUTF8_Blended( is now TTF_RenderText_Blended with an extra text length parameter.

SDL_Rects are mostly replaced by SDL_FRect

This is a big change. Everywhere I was passing in an SDL_Rect became an SDL_Frect which is four floats rather than four ints.

SDL_RenderCopy is now SDL_RenderTexture and the last two params are now SDL_FRects.

To fix this I used a load of (float) casts.

SDL_RenderDrawLine becomes SDL_RenderLine and has an SDL_FRect parameter instaed of SDL_Rect.

Same for SDL_RenderDrawPoint which becomes SDL_RenderPoint.

SDL_GetMouseState keeps the same name but returns float * for both parameters now.

Setup changes slightly

There’s no SDL_SetMainReady() and SDL2main.lib is gone.

Also gone is SDL_INIT_EVERYTHING in SDL_Init()– you have to or the specific subunits. E.g. SDL_INIT_VIDEO | SDL_INIT_EVENTS

Also there’s no SDL_RENDERER_PRESENTVSYNC for SDL_CreateRenderer. Vsync is disabled by default as I found when my game ran about 30x faster and finished in a few seconds! Instead you need to call SDL_SetRenderVSync(renderer, 1) where 1 is syncing with each retrace, or 2 with every 2nd retrace.

Several of the events have been renamed, so SDL_KEYDOWN becomes SDL_EVENT_KEY_DOWN, SDL_MOUSEBUTTONDOWN becomes  SDL_EVENT_MOUSE_BUTTON_DOWN and similar for other events.  Also event.key.keysym.sym becomes event.key.key.

Finally SDL_FreeSurface( becomes SDL_DestroySurface.

I’m sure there are more but changing these was sufficent to get my game compiling and running correctly with SDL3.

New tutorial posted – how to build controllermap in Linux

New tutorial posted – how to build controllermap in Linux

Controllermap utility

Remember controllermap? The utility that creates a configuration string for a game pad etc. I found that it is no longer installed by default when you install libsdl2-dev on Linux.  I found the hard way, trying to use it on my new Raspbverry Piu 5.

But the source code is available for it in the libsdl 2 releases.

So I wrote a quick tutorial that explains how to get the source code and build it using clang on VS Code on a Pi or any Linux box.  It’s linked here or you can find it on the tutorials menu.

Compiling C with Visual C++ 2022

Compiling C with Visual C++ 2022

monitor displaying programming languageIt’s been a few years since I compiled the code for the first eBook and I needed to create an SDL application on Windows. I copied a project, as it was the fastest way to setup the include and lib paths, and the lib files needed to compile.

Compared to clang/gcc on Linux, setting up visual studio projects on Windows can be a bit of a pita. You’ve got to be careful not to mix up the x64 and x86 files, add everything twice (once for Win 32 and once for x64).

So I copied .sln and .vcxproj files, started compiling and kept getting this error:

Error LNK2019 unresolved external symbol main referenced in function “int __cdecl invoke_main(void)” (?invoke_main@@YAHXZ) maze D:\development\LinuxFormat\maze\MSVCRTD.lib(exe_main.obj) 

I messed around with settings, still no joy. did a bit of searching around and found that some people fixed it by setting the Link System Subsystem but that didn’t fix it. Also one person had forgotten to add SDL2_main.lib to the list of lib files to be linked in.

Then I noticed the project was defaulting to 64-bit. I checked my includes and it was only setup for 32-bit. D’oh. So copying the settings from 32-bit to 64-bit fixed it.

Yet another curious bug

Yet another curious bug

MatchThree latest version with a bugI’m aware that C is notorious for unexpected behaviour (UB). Let me describe this bug:

My second game in C + SDL for my newest eBook is Match Three and compiled with Clang-11 on my Raspberry Pi 4B. I’m getting a weird bug that doesn’t occur when I compile it on Windows under MSVC; the only differences between the source code on the PI and Windows are the paths to SDL and the sn._s calls but there aren’t many of those. Also I compiled it with clang-14 on Ubuntu 22.04 LTS on a Hyper-VM and that behaves properly.

 

Each piece is held a struct in a 10 x 10 array. One field is  called size. It’s 0 normally but if it is set to a value, typically  64 then it counts down, one per frame and the piece is drawn rotated by 8 degrees each frame. When it reaches 0 the piece is removed. This is my “down the plughole” way of removing pieces. It takes exactly 64/60 seconds to vanish. I use the size field to draw it when size is non-zero so it shrinks as it rotates It’s a nice effect.

 

The bug though is that when it starts up, several pieces start rotating and keep rotating. The size field stays at 63. There’s no code that explains this behaviour and it only happens on the Raspberry Pi, not on Windows or on Ubuntu. Is it a compiler bug or some weird UB on the PI version. It’s an interesting bug and I’ve only wasted a week of evenings on it so far!

New Linux Timing Code

New Linux Timing Code

silver and white round analog watch

For some time, I had a problem with my old Linux timing code. The units hr_time.h/c had to have the includes arranged in the right order and some flags set for it to compile. Plus it never seemed right having to do this in hr_time.h

#include <linux/time.h>
#define __timespec_defined 1
#define __itimerspec_defined 1
#define __timeval_defined 1

But today I found some better code on this SolarianProgrammer website and I’m always happy to give credit where it’s due. I’ve witched to using C17 which clang on Ubuntu (clang 14) and Raspberry Pi (clang 11) both seem to accept.

So now my hr_time.h looks like this:

hr_time.h

#pragma once
#include <stdlib.h>
#include <time.h>

void startTimer();
void stopTimer();
double diff();

hr_time.c

#include "hr_time.h"
#include <time.h>
#include <stdlib.h>
#include <stdio.h>

struct timespec start;
struct timespec end;

void startTimer() {
	if (timespec_get(&start, TIME_UTC) != TIME_UTC) {
		printf("Error in calling timespec_get\n");
		exit(EXIT_FAILURE);
	}
};

void stopTimer() {
	if (timespec_get(&end, TIME_UTC) != TIME_UTC) {
		printf("Error in calling timespec_get\n");
		exit(EXIT_FAILURE);
	}
};

double diff()
{
	return  (double)(end.tv_sec - start.tv_sec) + 
			((double)(end.tv_nsec - start.tv_nsec) / 1000000000L);
}

I’m only ever using one timer, if you want to modify this to pass in a timer in the startTimer and stopTimer then it’s easy enough.

Is C a portable language?

Is C a portable language?

brown and black suitcase with red and yellow plastic toyI occasionally write answers on Quora.com and many recurring questions are about assembly language. Now I used to write games in 6502 and Z80 assembly language when the only alternative was Basic. But assembly language is very tedious to write, painstaking and it’s slow to write programs in assembly language. Most of your code is moving values between memory and registers or vice versa.

Anything major you write will not easily port onto a different CPU or Operating System. A Mac uses a different CPU to most Windows PCs and a Raspberry Pi uses a similar CPU design to a Mac (M1 or M2) but there are still differences in calling OS routines on Raspberry Pi OS (based on Debian) and Mac OS.

Higher level languages are generally portable. I’ve written C# code that runs on Linux and my game which was 2,200 lines of C needed about an hours work to run on Ubuntu Linux and Raspberry Pi.

But if you have a large complex C application, it may have issues when porting it.  A developer Rex Jaeschke wrote a book on portability and published it in 1989. He’s recently updated it and it’s available on Wikibooks.  It’s called Portability and the C language and is several hundred pages long. If you ever want to port C, it is very worthwhile reading. I’ve added a permanent link to the Link to C utilities page.

 

Is Tiobe Index misinformation?

Is Tiobe Index misinformation?

news, false, conceptEvery month a new Tiobe Index is published purporting to show the most popular programming languages. Except, if you look at other programming language popularity surveys, lists etc, the Tiobe Index increasingly seems to be at odds with everybody else.

Take the programming language C. As you can imagine I have a particular interest in it. I was at first delighted when I saw it at #3 in the Tiobe Index. In fact, in their most recent index it is listed as the 2nd most popular programming language. Well that is just crazy. No matter how much I might want it, there is no way on Earth that it is the 2nd most popular programming language.

It’s not just me saying it. Let’s look at who else says it.

SiteC's RankingComments
Tiobe Index2Updated monthly
GitHub Octoverse Programming languages9Annually- this is October 2022
Reddit Programming languages10Subreddits for programming languages
Red Monk Programming Language Rankings10June 2022. Updated every 6 months
StackOverflow developer survey11Annually
Statista most used programming languages 202211
Hackerrank Developer skills report 202312

There are other programming language lists or surveys but those show what I mean.  No one else has C anywhere that high. Here it’s in positions 9-12 with an average roughly around 10.5 if you exclude Tiobe or 9.3 if you don’t.  I think their methodology is flawed and biased by age. Older languages appear to carry more weight.

Never mind C, what about JavaScript? Everyone else has it in first place (except HackerRank who has it in 4th). Tiobe index has it in 7th. Misinformation is defined as “false information that is spread, regardless of intent to mislead.”. Maybe that’s a bit harsh but that’s how I regard the Tiobe Index.

Nice to see an article favouring C

Nice to see an article favouring C

brown wooden letter c decorToptal.com is a site for recruiting freelances for projects. They have published an article by a developer Daniel Munoz which praises C and shows how it is still quite relevant today. It’s definitely worth a read.

Given the pressure today to move to Rust, Go and even Kotlin, it’s nice to see someone praising C.  Of course for the games I do C is near perfect.

Posted in C
How to debug programs using SDL

How to debug programs using SDL

Terminal fprintf outputThere’s nothing worse than a program halting with a simple “Segmentation fault” and no idea where or why. It happened to me today working on the 2nd eBook (for Raspberry Pi) and I had to figure out where it was going wrong.

In the end it was a really silly bug, I was trying to load masks but had left the masks/ folder out of the filename.

How did I find it? I sprinkled a few fprintf(stderr,”message”); throughout the program changing “message” to something appropriate and launched it from a terminal. I’d thought it was in a function LoadTextures() so added a call before and after but you can see that worked and the segmentation fault happened after LoadTextures().

So I added it before and after LoadMasks() and my second run it happened before it reached the After LoadMasks message.

Note, I used stderr as the output path because, unlike stdout which is buffered and can be cleared, anything sent to stderr appears immediately.  More about this in this offsite article.

The using SDL part of the title is just to show that you can find bugs even in programs that use SDL.