First Steps

Last updated on August 14th, 2022

For this tutorial it is presumed, that you are familiar with procedures, functions, loops, pointers and usual commands of Free Pascal or its dialects. If this is not the case you may face problems because this tutorial deals with the features and usage of the SDL2 library and will not explain basic concepts of Pascal programming. For a quick refresh on some Pascal basics, have a look into this (good) article Modern Object Pascal Introduction For Programmers by Michalis Kamburelis.

You can easily copy the example source code directly from the source code box for each chapter.

The SDL2 unit and the first application

program FirstSteps;

uses SDL2;

begin

  //initilization of video subsystem
  if SDL_Init(SDL_INIT_VIDEO) < 0 then Exit;

    {your SDL2 application/game}

  //shutting down video subsystem
  SDL_Quit;

end. 

That’s it, your first SDL2 program. You may copy the code directly in your environment and run it. It should work without any errors if everything is set up correctly. The most important rule to get ready for SDL2 in your Pascal programs is obviously:

Always include the SDL2 unit in the uses clause.

The SDL2 unit is the heart of every SDL2 application! If you do so, you are perfectly prepared to start coding.

The different features of SDL2 (screen/video handling, audio handling, keyboard handling, and so on) have to be initilized individually using this function:

function SDL_Init(flags: TSDL_Init): cint.

It will return 0 on success and a negative error code on failure. The return value is of integer type cint. What this means, we will discuss later.

In the first example we initialize the SDL2 video subsystem for screen handling by using the flag SDL_INIT_VIDEO. Instead of SDL_INIT_VIDEO you could initilize the respective subsystem by using SDL_INIT_AUDIO for audio subsystem, SDL_EVENTS for event subsystem, and so on. What subssystem you need to initialize depends on what you want to do. The table shows an overview of all the possible flags and their meaning:

FlagDescription
SDL_INIT_TIMERInitilizes timer subsystem for handling of time related events.
SDL_INIT_AUDIOInitilizes audio subsystem for playing music or sound effects.
SDL_INIT_VIDEOInitilizes video subsystem for drawing/showing/manipulating of graphics, textures and screen, usually the most important subsystem.
SDL_INIT_JOYSTICKInitilizes joystick subsystem for handling of joysticks.
SDL_INIT_HAPTICInitilizes haptic (force feedback) subsystem.
SDL_INIT_GAMECONTROLLERInitilizes game controller subsystem.
SDL_INIT_EVENTSInitilizes events subsystem for handling of mouse or keyboard input.
SDL_INIT_EVERYTHINGInitilizes all the subsystems above.
SDL_INIT_NOPARACHUTEIgnores fatal signals. In SDL2 this is set by default and it isn’t possible to change this state. The explanation is given in the official migration guide I will cite here:There’s no SDL parachute anymore. What 1.2 called SDL_INIT_NOPARACHUTE is a default and only state now. This would cause problems if something other than the main thread crashed, and it would interfere with apps setting up their own signal/exception handlers. On the downside, some platforms don’t clean up fullscreen video well when crashing. You should install your own crash handler, or call SDL_Quit() in an atexit() function or whatnot if this is a concern. Note that on Unix platforms, SDL still catches SIGINT and maps it to an SDL_QUIT event.
List of subsystem flags.

Of course you are allowed to combine several subsystem flags by OR, e.g. “SDL_Init(SDL_INIT_VIDEO OR SDL_INIT_AUDIO)” to initilize video and audio support. If you are running some subsystems already but need to load further ones you would use

function SDL_InitSubSystem(flags: TSDL_Init): cint

respectivly. Again 0 ist returned on success and the negativ error code in case of failure.

The flag SDL_INIT_EVERYTING will initialize all subsystems. Use this if you are unsure on what subsystem you should use, although it will need a little bit more resources.

Quitting your programs

Every SDL program has to be closed by

procedure SDL_Quit.

It cleans up your system. Never forget it! This procedure ensures that all subsystems initilized get unloaded. There is a corresponding procedure to unload specific subsystems defined as

procedure SDL_QuitSubSystem(flags: TSDL_Init).

You are allowed to quit two or more subsystems by this function by using OR operator. It is advised to always quit SDL 2.0 applications by SDL_Quit even if you quit all of them individually by SDL_QuitSubSystem before.

Try the example program. You will not see much but if you didn’t get an error message you are successful. Before proceeding, let’s have a quick look into error handling.

Pascal and the C variable types of SDL2

You may wonder about the return value cint in the SDL_Init function declaration. What a strange variable type for a return value, right? Let me explain.

SDL2 has been written in the C programming language. As a consequence, the functions of the SDL2 library expect arguments of C variable type and have return values of C variable type. The prefix c and the variable type name int in cint simply indicate for us, that the function returns a C-language integer value. Further examples of regularly used variable types in the SDL2 library are cuint8 for a C unsigned integer of 8 bit size, cint32 for a C signed integer of 32 bit size, cfloat for a C float point variable.

This notification of the handled C variable types helps you pick the suitable Pascal variable types when working with the SDL2 functions. E. g. ,if you like to store a cint32 return value, a suitable pick would be Longint (or SInt32) which represents a 32 bit (4 byte) signed integer according to Free Pascal’s ordinal types. For cint usually Integer is a good choice (not in Free Pascal or Turbo Pascal compiler mode though, where the Integer size is 2 bytes).

If you would like to use the C-language variable type names in your code yourself, you need to add the Free Pascal’s ctypes unit. For Delphi there is a ctypes.inc file shipped with the bindings.

As a beginner working with the units, you don’t have to be too concerned with these details, but now you know why these variable types have these names.

SDL2 functions and errors

Every SDL2 function returns an error value for you to check if the function runs properly at runtime. The values returned are of integer or pointer type. There is no general rule what values correspond to which status. In SDL2 usually an integer value of 0 means “function runs/ran succesfully”, values lower than 0 correspond to a status “function couldn’t be run, something is wrong”. For pointers nil means error and any non-nil pointer means success. However, in most cases I won’t do error checking in the examples to keep the code short. I will mention the error values to be expected though.

You should know that there is a function called

SDL_GetError: PAnsiChar

which translates the last error received into a message (of type PAnsiChar) that can be read out and printed to the screen by any function that can handle strings as well (e.g. the Pascal’s common write() function). Since SDL2 is written in C originally, the PAnsiChar type is used in contrast to the String type (which is more common among Pascal programmers for message storage and handling).

A quick way to return the error message is to use the SDL2 message box feature:

function SDL_ShowSimpleMessageBox(flags: TSDL_MessageBoxFlags; title: PAnsiChar; _message: PAnsiChar; window: PSDL_Window): cint

The flags for the message box could be:

  • SDL_MESSAGEBOX_ERROR
  • SDL_MESSAGEBOX_WARNING
  • SDL_MESSAGEBOX_INFORMATION
  • SDL_MESSAGEBOX_BUTTONS_LEFT_TO_RIGHT
  • SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT

While the flags indicate the reason for the message box, the title and the message argument are used to set a box title and a message. The window argument can be set to the nil pointer.

The following short code snippet demonstrates a convenient way of using the box for showing error messages in the case of SDL2 initialization as done above.

//initilization of video subsystem
if SDL_Init(SDL_INIT_VIDEO) < 0 then 
begin
  SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, 'Error Box',  SDL_GetError, nil);
  Exit;
end;

Well, we have initilized the video subsystem and released it afterwards, and we learned about showing error messages in a simple message box. Simple Directmedia Layer deserves its name, doesn’t it?

Only if you agree, you may proceed to the next chapter ;-)!

← Chapter 2 (Windows) | ← Chapter 2 (Linux) | next Chapter →

13 thoughts on “First Steps

  1. Hello I’m just wondering, how do we set up the Pascal-SDL2 library if i wanted to use the command line and fpc by itself.

    Thank you.

    1. It is as simple as having the sdl2 unit (sdl2.pas) and the pre-compiled library file (e. g. sdl2.dll on Windows) in the program directory and calling fpc to compile your source code. Have fun!

      1. Does it have to be a specific version of the sdl dll?
        i have tried with version 2.0.8, 2.24.2 and 2.26.2.
        All resulted in this error: “The application was unable to start correctly (0xc000007b). Click OK to close the application.”

        Running win 10, fpc 3.2.2 and pulled the units from github today.

        Thanks in advance.

        1. Hello Christian,

          sorry for the delayed response.

          Do you run the 32 or 64 bit version of Win10? You need to use the appropriate SDL2 DLL file.

          Does this solve the problem?

          Best regards
          Matthias

  2. Perhaps important – Pascal and Mesa are slightly incompatible and will throw a floating point exception on video init under some conditions. See here: https://github.com/PascalGameDevelopment/SDL2-for-Pascal/issues/56

    On my dev machine with hardware acceleration on an RX550, everything works fine without workarounds. But trying to use Mesa’s software rendering in or outside a virtual machine on my system trips a FPE. I’ve also had a user report a different FPE on different hardware. So this is something that will (seemingly inexplicably) work fine for some devs/users, and break for others.

    We should therefore encourage anyone using SDL2 with Pascal to apply the workaround as part of SDL init:

    uses math;

    SetExceptionMask(GetExceptionMask + [exInvalidOp,exDenormalized,exZeroDivide,exOverflow,exUnderflow,exPrecision]);

  3. Hello. It can’t work on Ubuntu 16.04 🙁
    All libraries installed. It’s compiled, but crashed with error:
    Runtime error 200 at $00007F859C697634
    $00007F859C697634

    I tried another version of Tim Blume’s SDL2 units (1.62-master) and this error repeated.

    1. I’m confused, did you use the example code as is shown in the chapter (above)?

      Runtime error 200 means “division by zero”.

        1. I cannot confirm this behavior. I tried it again on Linux Mint (x64, Ubuntu based).

          Do you use Lazarus as IDE? If so, try to start a completely new project (Simple Program).
          1) Then run the code (basically an empty Pascal program). Does it work?
          2) Add SDL2 to the uses clause and add the appropriate path to the project’s unit path. Run it. Does it work?
          3) Add the sample code again. Run it. Does it work?

          1. This error very strange. It compiles, but crashed after run program.
            I completely reinstall fpc + lazarus + libsdl2*. It works. Yet.
            Thank you for your lessons, Matthias.

Leave a Reply

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