All posts by Matthias

Wallman

Pascal SDL Projects?

A new page has been set up which gives an overview of projects done in SDL with Pascal (any dialect). The projects may be games, interpreters, libraries, anything. Of course SDL should play a key role and shouldn’t be just used to set up an OpenGL window (or similar). If possible I try to have an interview with the creator of the project.

The first project listed is the famous EGSL project and its successor Pulsar2D. Both have been created by Cybermonkey who kindly gave an interview and provided a lot of screenshots to me.

Feel free to contact me to let me know about other Pascal SDL projects.

Edit: As of 09/02/2016 I added suve’s Alexland and Colorful to the project page. Thanks for the interview and the screenshots.

EGSL and Pulsar2D

Short description

EGSL and Pulsar2D are LUA script interpreters to develop games in an easy, quick and convenient way.

EGSL: Showcase and Basic Data

Developer granted permission to use these screenshots.

  • Project name: Easy Game Scripting with LUA
  • Author: Cybermonkey
  • Latest version: 1.6.0
  • Release date: 30/12/2012
  • Compiler: >= FPC 2.6.0
  • SDL Version: SDL 1.2
  • Further libraries: Vampyre Imaging Library / Lua 5.1 / Lua 5.2
  • License: zlib
  • Open source: yes
  • Official website: http://www.egsl.retrogamecoding.org

Pulsar2D: Showcase and Basic Data

Developer granted permission to use these screenshots.

  • Project name: Pulsar2d
  • Author: Cybermonkey
  • Latest version: 0.6.2
  • Release date: 31/12/2015
  • Compiler: FPC 3.0.0
  • SDL Version: SDL2
  • Further libraries: Lua 5.2
  • License: zlib
  • Open source: yes
  • Official website: http://pulsar2d.org

Interview with Cybermonkey

Could you please give a short description of EGSL and Pulsard2D for those who have never heard of it?

Cybermonkey: EGSL (Easy Game Scripting with Lua) is a Lua interpreter which allows one to code 2D games in a simple way. I could say in a “classical way” because EGSL is inspired by old BASIC dialects. The main difference between EGSL and Pulsar2D is that Pulsar2D uses now the newer SDL2 libraries (which gives us the possibility to use multiple windows). It’s as easy as that: write 10 lines of Lua code and start the script and you’ll have already a small sprite moving example. Of course it is possible to use the framework with FreePascal. Apart from that I recently ported the Pulsar2D framework to FreeBASIC. So one can code Pulsar2D games/demos whatsoever in Lua, FreePascal or FreeBASIC.

Why did you decide to choose Pascal as a programming language and SDL/SDL2 as a library for these projects?

Cybermonkey: I started programming back in the 1980s with the Commodore 64 and BASIC. I learned Turbo Pascal in school and started programming with FreePascal a few years ago. It’s the language I have the most experience with. Not to mention that the FreePascal compiler is well maintained. I chose SDL/SDL2 because of its cross platform capabilities.

What do you think is the most interesting Pascal/SDL/SDL2 project out there (besides of your own, of course :-D)?

Cybermonkey: Actually I don’t know of any other … But of course the most impressive Pascal project is Lazarus for me.

Are there any further steps for EGSL and/or Pulsar2D or any new projects planned? What will they be?

Cybermonkey: EGSL will not be developed any further. Pulsar2D wil be improved from time to time. My plans are to implement Box2D physics and easy handling of tiled based maps made with the Tiled editor. But this has no priority so it can take a long time…

At the moment I am developing a little BASIC interpreter called “AllegroBASIC”. It’s a C project, though. (The editor, however, is made with Lazarus…) Since I am using Allegro4 libs which are obsolete now, I am porting at the same time the project to SDL2 which will be named “RETROBASIC”. If there are people interested in AllegroBASIC, have a look at allegrobasic.pulsar2d.org.

 

Chapter 9 application preview

New Chapter 9 about Music and Sound

The new Chapter 9: Music and Sound has been released. It demonstrates how to use the SDL_mixer 2.0 to load music and sound files to use them in your applications.

I was surprised to find that there have been made many important updates to Tim Blume’s SDL 2.0 units since the latest release (version 1.72). This means for everybody who relies on these units, update to the latest master branch release (later than version 1.72)!

Download ZIP button
IMPORTANT: Get the latest master branch release! Download Link

Otherwise you will struggle to get some important sdl features. E.g. key code constants and the code of the new Chapter 9 won’t work. I adapted Chapter 8 about event handling.

An interesting new header translation project was mentioned to me which allows for dynamic loading of SDL 2.0. Check out Chapter 1 to read more about this project by Imants Gulis.

Many smaller updates have been performed, too. Also the color scheme has been updated since it was stated that the contrast of the former color scheme has been too weak. You may also have noticed the amazing new fractal title background image :-)!

Important hint: The Free Pascal compiler got a new stable release on 25th November of 2015, version 3.0.0. Don’t forget to update your favourite compiler :-)!

Chapter 9 – Music and Sound

Last updated on November 21st, 2021

This chapter will introduce you on how to load music and sounds since these are key features of every game and many applications.

SDL_mixer 2.0 for easy music and sound support

Although SDL 2.0 supports music and sound handling natively, there is an easier way to play music and sound files. The official unit SDL_mixer 2.0 (unit’s name SDL2_mixer) has been created exactly for this purpose and is maintained by the same authors (Sam Lantinga, Stephane Peter, Ryan Gordon) as SDL 2.0 itself. The Pascal translation is fortunately available, too in Tim Blume’s header translations.

Supported music and sound file formats in SDL 2.0

According to the official SDL2_mixer documentation the following music and sound formats are supported:

  • WAVE/RIFF (.wav)
  • AIFF (.aiff)
  • VOC (.voc)
  • MOD (.mod .xm .s3m .669 .it .med and more) requiring libmikmod on system
  • MIDI (.mid) using timidity or native midi hardware
  • OggVorbis (.ogg) requiring ogg/vorbis libraries on system
  • MP3 (.mp3) requiring SMPEG or MAD library on system
  • FLAC (.flac) requiring the FLAC library on system

You’ll need these files:

Software
Version
File name
Link
Description
SDL2_mixer dynamic link library
2.0.1
SDL2_mixer-2.0.1-win32-x86.zip (32-bit Windows)
SDL2_mixer-2.0.1-win32-x64.zip (64-bit Windows)
https://www.libsdl.org/projects/SDL_mixer/
This is the corresponding dynamic link library file for the unit for Windows. Note: Mac OS X and Linux versions are also available.
dial.wav sound file dial.wav
dial.wav
A simple telephone dial sound. Source: pdsounds. License: Public domain.
In my mind.ogg music file In my mind.ogg
In my mind.ogg
A nice music sample. Source/Creator: First. License: CC BY-ND 3.0.
music-menu.bmp image file music-menu.bmp
music-menu.bmp
A simple bitmap image file which displays the menu options for the tutorial program.

You should extract the zip-file and get several files. These are four license text files and a readme text file, furthermore you have eight dll files including the important SDL2_mixer.dll. The other dll files are necessary to play the different sound and music formats. Copy all the files to the Windows system32-folder (or the corresponding place). If you forget this and run the examples below you will get an error with exitcode = 309.

Now that you are prepared, let’s have an overview of the code.

program SDL_MusicSound;
uses SDL2, SDL2_mixer;

var
  sdlWindow: PSDL_Window;
  sdlRenderer: PSDL_Renderer;
  sdlSurface: PSDL_Surface;
  sdlTexture: PSDL_Texture;
  sdlKeyboardState: PUInt8;
  Music: PMix_Music;
  Sound: PMix_Chunk;
  Run: Boolean = True;

begin
  if SDL_Init(SDL_INIT_VIDEO or SDL_INIT_AUDIO) < 0 then Exit;

  // Get window and renderer
  if SDL_CreateWindowAndRenderer(
    640, 640, SDL_WINDOW_SHOWN, @sdlWindow,@sdlRenderer) <> 0 then Exit;

  // Create and render menu texture
  sdlSurface := SDL_LoadBMP('music-menu.bmp');
  if sdlSurface = nil then Exit;
  sdlTexture := SDL_CreateTextureFromSurface(sdlRenderer, sdlSurface);
  if sdlTexture = nil then Exit;
  if SDL_RenderCopy(sdlRenderer, sdlTexture, nil, nil) <> 0 then Exit;
  SDL_RenderPresent(sdlRenderer);

  // Prepare mixer
  if Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT,
    MIX_DEFAULT_CHANNELS, 4096) < 0 then Exit;

  // Load music
  Music := Mix_LoadMUS('In-my-mind-1.ogg');
  if Music = nil then Exit;
  Mix_VolumeMusic(MIX_MAX_VOLUME);

  // Load sound
  Sound := Mix_LoadWAV('dial-1.wav');
  if Sound = nil then Exit;
  Mix_VolumeChunk(Sound, MIX_MAX_VOLUME);

  while Run = True do
  begin

    SDL_PumpEvents;
    sdlKeyboardState := SDL_GetKeyboardState(nil);

    // ESC pressed
    if sdlKeyboardState[SDL_SCANCODE_ESCAPE] = 1 then
      Run := False;

    // Music effect keys
    if sdlKeyboardState[SDL_SCANCODE_1] = 1 then
      if Mix_PlayMusic(Music, 0) < 0 then Writeln(SDL_GetError);
    if sdlKeyboardState[SDL_SCANCODE_2] = 1 then Mix_PauseMusic;
    if sdlKeyboardState[SDL_SCANCODE_3] = 1 then Mix_ResumeMusic;
    if sdlKeyboardState[SDL_SCANCODE_4] = 1 then Mix_RewindMusic;
    if sdlKeyboardState[SDL_SCANCODE_5] = 1 then
      if Mix_FadeInMusic(Music, 10, 3000) = 0 then Writeln(SDL_GetError);
    if sdlKeyboardState[SDL_SCANCODE_6] = 1 then
      if Mix_FadeOutMusic(3000) = 0 then Writeln(SDL_GetError);

    // Sound effect keys
    if sdlKeyboardState[SDL_SCANCODE_7] = 1 then
      if Mix_PlayChannel(1, Sound, 0) < 0 then Writeln(SDL_GetError);
    if sdlKeyboardState[SDL_SCANCODE_8] = 1 then
      if Mix_PlayChannel(-1, Sound, 0) < 0 then Writeln(SDL_GetError);
    if sdlKeyboardState[SDL_SCANCODE_9] = 1 then Mix_Pause(-1);
    if sdlKeyboardState[SDL_SCANCODE_0] = 1 then Mix_Resume(-1);
    if sdlKeyboardState[SDL_SCANCODE_A] = 1 then
      if Mix_FadeInChannel(1, sound, 0, 2000) < 0 then Writeln(SDL_GetError);
    if sdlKeyboardState[SDL_SCANCODE_S] = 1 then
      if Mix_FadeOutChannel(1, 1000) < 0 then Writeln(SDL_GetError);

    // Channel effect keys
     if sdlKeyboardState[SDL_SCANCODE_G] = 1 then
       if Mix_SetPanning( 1, 255, 32 ) = 0 then Writeln(SDL_GetError);
     if sdlKeyboardState[SDL_SCANCODE_H] = 1 then
       if Mix_SetPanning( 1, 255, 255 ) = 0 then Writeln(SDL_GetError);
     if sdlKeyboardState[SDL_SCANCODE_J] = 1 then
       if Mix_SetDistance( 1, 223 ) = 0 then Writeln(SDL_GetError);
     if sdlKeyboardState[SDL_SCANCODE_K] = 1 then
       if Mix_SetDistance( 1, 0 ) = 0 then Writeln(SDL_GetError);
     if sdlKeyboardState[SDL_SCANCODE_L] = 1 then
       if Mix_SetPosition( 1, 45, 127 ) = 0 then Writeln(SDL_GetError);
     if sdlKeyboardState[SDL_SCANCODE_M] = 1 then
       if Mix_SetPosition( 1, 0, 0 ) = 0 then Writeln(SDL_GetError);

  end;

  // Clean up
  if Assigned(sdlSurface) then SDL_FreeSurface(sdlSurface);
  if Assigned(sdlTexture) then SDL_DestroyTexture(sdlTexture);
  if Assigned(sdlRenderer) then SDL_DestroyRenderer(sdlRenderer);
  if Assigned(sdlWindow) then SDL_DestroyWindow(sdlWindow);
  if Assigned(Music) then Mix_FreeMusic(Music);
  if Assigned(Sound) then Mix_FreeChunk(Sound);

  Mix_CloseAudio;
  SDL_Quit;
end.

When running this program, you’ll get a window with a menue. For this to work, make sure to download the music-menu.bmp file and place it in the program folder.

Let’s start with the first part of the code.


program SDL_MusicSound;
uses SDL2, SDL2_mixer;

var
  sdlWindow: PSDL_Window;
  sdlRenderer: PSDL_Renderer;
  sdlSurface: PSDL_Surface;
  sdlTexture: PSDL_Texture;
  sdlKeyboardState: PUInt8;
  Music: PMix_Music;
  Sound: PMix_Chunk;
  Run: Boolean = True;

begin
  if SDL_Init(SDL_INIT_VIDEO or SDL_INIT_AUDIO) < 0 then Exit;

  // Get window and renderer
  if SDL_CreateWindowAndRenderer(
    640, 640, SDL_WINDOW_SHOWN, @sdlWindow,@sdlRenderer) <> 0 then Exit;

  // Create and render menu texture
  sdlSurface := SDL_LoadBMP('music-menu.bmp');
  if sdlSurface = nil then Exit;
  sdlTexture := SDL_CreateTextureFromSurface(sdlRenderer, sdlSurface);
  if sdlTexture = nil then Exit;
  if SDL_RenderCopy(sdlRenderer, sdlTexture, nil, nil) <> 0 then Exit;
  SDL_RenderPresent(sdlRenderer);

The program is called “SDL”. It uses the SDL2 and the new SDL2_mixer unit.

We’re going to use event handling as discussed in Chapter – Keyboard State and Key States to check what keys have been pressed. Consequently we need a variable “sdlWindow” for the SDL 2.0 window and a keyboard state variable “sdlKeyboardState”.

The pointer variable “Music” is of the new type PMix_Music and points at the loaded music file data later. The “Sound” pointer variable is of type PMix_Chunk and points at the loaded sound file data later. Note: Each song is referenced by an own PMix_Music pointer and each sound effect (e.g. explosions, shots, …) is referenced by an own PMix_Chunk pointer.

What is the difference between music and sound?

Music is associated with PMix_Music pointers and sounds are associated with PMix_Chunk pointers, but why distinguish them at all? – Well, it is convenient to have them separated since they have rather different properties. Music is usually several minutes long, sounds are usually just a few seconds short. It is usually just one song played at a time, sounds need to mix up if necessary. For music it usually doesn’t plays a role if it is sligthly delayed to when it should start, for sounds a larger delay usually means a strange feeling for the player. So, for music there is exactly one channel reserved where the music is played. For sounds eight sound channels are available to make it possible for them to mix up. Now let’s get back to the code.

The variable “Run” is a boolean variable to determine when the main loop of the program should be exited.

The program is initialized by SDL_Init as known. Note though that not only SDL_INIT_VIDEO but additionally SDL_INIT_AUDIO is set. They are combined by the or operator (not the and operator :-)!).  The window is set up afterwards by SDL_CreateWindow as known. Also the menu texture file is created and renderered as known. Check Chapter – Loading and rendering a Bitmap file as a reminder, in case.


  // Prepare mixer
  if Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT,
    MIX_DEFAULT_CHANNELS, 4096) < 0 then Exit;

  // Load music
  Music := Mix_LoadMUS('In-my-mind-1.ogg');
  if Music = nil then Exit;
  Mix_VolumeMusic(MIX_MAX_VOLUME);

  // Load sound
  Sound := Mix_LoadWAV('dial-1.wav');
  if Sound = nil then Exit;
  Mix_VolumeChunk(Sound, MIX_MAX_VOLUME);

To initialize SDL2_mixer

function Mix_OpenAudio(frequency: cint; format: cuint16; channels: cint; chunksize: cint): cint

has to be called. It requests four parameters. These are the frequency, the audio format, the channels (mono or audio) and the chunksize. All these parameters are of Integer type. Function Mix_OpenAudio returns 0 on success and -1 on errors.

The frequency in Hertz (1/s) usually is 22050 Hz or MIX_DEFAULT_FREQUENCY in games but double as high for CD quality sound (44100 Hz). The higher the frequency, the more CPU power is needed.

Next we have to define the audio format. It determines how the audio data is stored. MIX_DEFAULT_FORMAT equals AUDIO_S16SYS. Different values are given in the following list (from official SDL2_mixer documentation):

  • Format constant name Description
  • AUDIO_U8 Unsigned 8-bit samples
  • AUDIO_S8 Signed 8-bit samples
  • AUDIO_U16LSB Unsigned 16-bit samples, in little-endian byte order
  • AUDIO_S16LSB Signed 16-bit samples, in little-endian byte order
  • AUDIO_U16MSB Unsigned 16-bit samples, in big-endian byte order
  • AUDIO_S16MSB Signed 16-bit samples, in big-endian byte order
  • AUDIO_U16 same as AUDIO_U16LSB (for backwards compatability probably)
  • AUDIO_S16 same as AUDIO_S16LSB (for backwards compatability probably)
  • AUDIO_U16SYS Unsigned 16-bit samples, in system byte order
  • AUDIO_S16SYS Signed 16-bit samples, in system byte order

Then we decide for a sound channel type, which means either stereo or mono. For stereo sound we choose 2 and for mono we choose 1 as value. MIX_DEFAULT_CHANNELS equals stereo output.

Finally the chunksize has to be set, where 4096 bytes per sample is a good and default value. Too low values may lead to skipping samples. Too high values may lead to delayed playing.

Loading music and sounds from files in SDL 2.0

We will load the music by

function Mix_LoadMUS(_file: PAnsiChar): PMix_Music.

_file can be the absolute path. If the Pascal file and the music file are in the same folder the file name is sufficient (as shown in the example). If the loading was unsuccessful, the function returns nil. The volume can be set by

function Mix_VolumeMusic(volume: cint): cint.

The volume can be set between 0 (silence) to 128 (maximum volume). The latter equals MIX_MAX_VOLUME. By the way, if you set -1 as argument, the return value corresponds to the set volume.

Quite similar sound files are loaded by

function Mix_LoadWAV(_file: PAnsiChar): PMix_Chunk.

Although the function’s name doesn’t indicate this, use this function to load the sound files of any format (Wave, Aiff, Riff, Ogg, Voc), not only for .wav sound files. It return nil on error. There is alittle difference when setting the volume by

function Mix_VolumeChunk(chunk: PMix_Chunk; volume: cint): cint.

Instead of just setting a general volume, the volume is bound to a certain sound. In the example case the sound is in variable “sound”. Just to mention it here, there is a third possibility, to set the volume for a certain channel:

function Mix_Volume(channel: cint; volume: cint): cint.

This can be quite handy, anyway, channels are discussed a little bit later below. If your argument is -1 the average volume will be returned.

Playing, pausing, resuming music and sounds


  while Run = True do
  begin

    SDL_PumpEvents;
    sdlKeyboardState := SDL_GetKeyboardState(nil);

    // ESC pressed
    if sdlKeyboardState[SDL_SCANCODE_ESCAPE] = 1 then
      Run := False;

    // Music effect keys
    if sdlKeyboardState[SDL_SCANCODE_1] = 1 then
      if Mix_PlayMusic(Music, 0) < 0 then Writeln(SDL_GetError);
    if sdlKeyboardState[SDL_SCANCODE_2] = 1 then Mix_PauseMusic;
    if sdlKeyboardState[SDL_SCANCODE_3] = 1 then Mix_ResumeMusic;
    if sdlKeyboardState[SDL_SCANCODE_4] = 1 then Mix_RewindMusic;
    if sdlKeyboardState[SDL_SCANCODE_5] = 1 then
      if Mix_FadeInMusic(Music, 10, 3000) = 0 then Writeln(SDL_GetError);
    if sdlKeyboardState[SDL_SCANCODE_6] = 1 then
      if Mix_FadeOutMusic(3000) = 0 then Writeln(SDL_GetError);

    // Sound effect keys
    if sdlKeyboardState[SDL_SCANCODE_7] = 1 then
      if Mix_PlayChannel(1, Sound, 0) < 0 then Writeln(SDL_GetError);
    if sdlKeyboardState[SDL_SCANCODE_8] = 1 then
      if Mix_PlayChannel(-1, Sound, 0) < 0 then Writeln(SDL_GetError);
    if sdlKeyboardState[SDL_SCANCODE_9] = 1 then Mix_Pause(-1);
    if sdlKeyboardState[SDL_SCANCODE_0] = 1 then Mix_Resume(-1);
    if sdlKeyboardState[SDL_SCANCODE_A] = 1 then
      if Mix_FadeInChannel(1, sound, 0, 2000) < 0 then Writeln(SDL_GetError);
    if sdlKeyboardState[SDL_SCANCODE_S] = 1 then
      if Mix_FadeOutChannel(1, 1000) < 0 then Writeln(SDL_GetError);

The main application loop is entered and should be left if variable “Run” is false which is achieved by pressing the ESCAPE key.

For each key state a different music or sound related function is used to do something. Let’s discuss them now in detail. We start with the functions triggered by the keys 1 – 4:

function Mix_PlayMusic(music: PMix_Music; loops: cint): cint 
procedure Mix_PauseMusic 
procedure Mix_ResumeMusic 
procedure Mix_RewindMusic

Mix_PlayMusic plays music. The first argument is the music itself which we previously got from the example .ogg music file and associated with the “Music” pointer of PMix_Music type. The second argument determines how often the music is played. Additionally -1 means infinite repetition. This function returns 0 on success and -1 on error.

The meaning of the three procedures Mix_PauseMusic, Mix_ResumeMusic and Mix_RewindMusic ist obvious from their names. They are used to pause, resume (if paused before) and rewind the played music.

The analogous function and procedures for sound channels triggered by the keys 7 – 9 and 0 are shown now:

function Mix_PlayChannel(channel: cint; chunk: PMix_Chunk; loops: cint): cint
procedure Mix_Pause(channel: cint) 
procedure Mix_Resume(channel: cint)

As you can see the function Mix_PlayChannel has three parameters. The first parameter asks for a channel with which the sound should be associated. SDL2_mixer provides eight sound channels. Usually you should use -1 which means the first free channel will be used to play the sound. Anyway, you could specifiy a certain channel here if you like. The second parameter asks for a sound pointer of PMix_Chunk type. The  third parameter is the same as for music, -1 means an infinite loop. Attention though for specific repetitions. The value for loops is increased by 1. So, if you want a sound to be played once, you need the argument to be 0. The return value corresponds to the sound channel the sound is played on, it is -1 on error.

The procedures Mix_Pause and Mix_Resume are self-explanatory. Use them to pause or resume a certain channel, which is the argument. If the argument is -1 (as in the example code) you pause or resume all channels. By the way, you may have noticed that there is not a rewind analogue, because sounds are not expected to be rewound.

Fading effects


...

    if sdlKeyboardState[SDL_SCANCODE_5] = 1 then
      if Mix_FadeInMusic(Music, 10, 3000) = 0 then Writeln(SDL_GetError);
    if sdlKeyboardState[SDL_SCANCODE_6] = 1 then
      if Mix_FadeOutMusic(3000) = 0 then Writeln(SDL_GetError);

    // Sound effect keys
    
...
    
    if sdlKeyboardState[SDL_SCANCODE_A] = 1 then
      if Mix_FadeInChannel(1, sound, 0, 2000) < 0 then Writeln(SDL_GetError);
    if sdlKeyboardState[SDL_SCANCODE_S] = 1 then
      if Mix_FadeOutChannel(1, 1000) < 0 then Writeln(SDL_GetError);

    // Channel effect keys
     if sdlKeyboardState[SDL_SCANCODE_G] = 1 then
       if Mix_SetPanning( 1, 255, 32 ) = 0 then Writeln(SDL_GetError);
     if sdlKeyboardState[SDL_SCANCODE_H] = 1 then
       if Mix_SetPanning( 1, 255, 255 ) = 0 then Writeln(SDL_GetError);
     if sdlKeyboardState[SDL_SCANCODE_J] = 1 then
       if Mix_SetDistance( 1, 223 ) = 0 then Writeln(SDL_GetError);
     if sdlKeyboardState[SDL_SCANCODE_K] = 1 then
       if Mix_SetDistance( 1, 0 ) = 0 then Writeln(SDL_GetError);
     if sdlKeyboardState[SDL_SCANCODE_L] = 1 then
       if Mix_SetPosition( 1, 45, 127 ) = 0 then Writeln(SDL_GetError);
     if sdlKeyboardState[SDL_SCANCODE_M] = 1 then
       if Mix_SetPosition( 1, 0, 0 ) = 0 then Writeln(SDL_GetError);

  end;

Important to know about effects like fading. They are performed on the fly to your data, so the more effects you use, the more computational power they require. It is important to unregister effects you don’t need anymore.

These are the four fade functions triggered by the keys 5, 6, A and S :

function Mix_FadeInMusic(music: PMix_Music; loops: cint; ms: cint): cint 
function Mix_FadeOutMusic(ms: cint): Integer 
function Mix_FadeInChannel(channel: cint; chunk: PMix_Chunk; loops: cint; ms: cint): cint
function Mix_FadeOutChannel(which: cint; ms: cint): cint

The function Mix_FadeInMusic works the very same way as Mix_PlayMusic above, but there is a further parameter which allows for a fade in effect in milliseconds. 3000 milliseconds equals 3 seconds. It returns 0 on success and -1 on error.

Mix_FadeOutMusic fades out the playing music within the given time in milliseconds in the moment the function is called (hence the key is pressed in the example program). Attention, it returns 1 on success and 0 on error.

Quite similar the functions Mix_FadeInChannel and Mix_FadeOutChannel work. Instead of the music pointer, the sound pointer and the channel has to be given. By the way, also here the number of times the sound is played is increased by 1, so if you want to play a sound with fade in effect once, the argument has to be 0. The fade effect applies only for the first run. Both functions return 0 on success and -1 on error.

Panning and distance effects

The functions triggered by the keys G – M are:

function Mix_SetPanning(channel: cint; left: cuint8; right: cuint8): cint

For setting the panning you need the channel to which panning should be applied and the volume values which may vary from 0 (quiet) to 255 (loudest). For a consistent panning effect you may substract the left value from the right value (left: volume, right: 255-volume). To unregister this effect, you should set both values to 255, which is recommended to be done if you don’t need panning anymore. The function returns 0 on errors.

function Mix_SetDistance(channel: cint; distance: cuint8): cint

The higher the distance, the quieter the sound appears. The value can range between 0 (near) and 255 (far). If distance is set to 0 the effect is unregistered. It returns 0 on errors.

function Mix_SetPosition(channel: cint; angle: cint16; distance: cuint8): cint

This function adjusts volumes according to an angle and a distance value, hence it combines the effects of the two functions discussed before for panning and distance. The distance value works the same way as discussed for Mix_SetDistance. Angle of 0 (degree) means in front of you, 90 means directly to the right, 180 means directly behind, 270 means directly to the left.

Closing the SDL2 mixer and clean up


  // Clean up
  if Assigned(sdlSurface) then SDL_FreeSurface(sdlSurface);
  if Assigned(sdlTexture) then SDL_DestroyTexture(sdlTexture);
  if Assigned(sdlRenderer) then SDL_DestroyRenderer(sdlRenderer);
  if Assigned(sdlWindow) then SDL_DestroyWindow(sdlWindow);
  if Assigned(Music) then Mix_FreeMusic(Music);
  if Assigned(Sound) then Mix_FreeChunk(Sound);

  Mix_CloseAudio;
  SDL_Quit;
end.

For the clean up the surface, textre renderer and the window are destroyed as known. New are the procedures Mix_FreeMusic and Mix_FreeChunk to free the music and sound data.

procedure Mix_FreeMusic(music: PMix_Music)
procedure Mix_FreeChunk(chunk: PMix_Chunk)

The arguments have to be the music and sound pointer respectively.

SDL_mixer 2.0 has to be closed by

procedure Mix_CloseAudio.

Finally SDL 2.0 and the application are shut down as known.

← previous Chapter | next Chapter →

10 Years Anniversary of FreePascal-meets-SDL.net

Happy New Year! 10 Years Free Pascal meets SDL!

Hi all,

right on time for the 1st January 2016, I finished the first part of the major update of www.FreePascal-meets-SDL.net. That’s an excellent start of the new year, isn’t it? 🙂

At the same time I’m happy and proud to announce that www.FreePascal-meets-SDL.net exists for ten years now! It has been originally established on 20th July 2005 and got 34,000+ views by now. It helped a lot of people to get familiar with Free Pascal and SDL or SDL2 and got a lot of positive responses.

I would like to thank all of you readers and supporters for your responses and encouragement in the past ten years, since I’m sure, without this, www.FreePascal-meets-SDL.net wouldn’t exist anymore today. A special thanks goes to Cybermonkey (developer of the amazing SDL based  EGSL Engine) who made many helpful and encouraging comments and to the whole Pascal Game Development Community where a fruitful affiliation has been established for many years.

For the new year and the ten years anniversary I decided to improve the website’s design since the old design is classic yet outdated in many ways, not only from an aesthetic point of view. I would like to allow for more interactivity, e.g. allow for comments directly to a certain tutorial page. Additionally the site is mobile-friendly now. Also I stopped using third-party forum software or a third-party visitor counter, which was suitable back in 2005. Just to name a few aspects, expect even more improvements and changes to come. At the moment the forum is gone completely, anyway, I’m not decided yet, if I re-introduce an own forum again.

All the seven chapters of the SDL 2.0 Tutorial have been corrected and extended and a completely new chapter consisting of two parts has been added. Step by step I will update the content (e.g. SDL 1.2 Tutorial) for the new design. Until I’m finished with transferring and making up the content, there is a link “Old Website” in the menu which will link to the old Website. So you can still access all the old resources.

The download area will be gone for now, since all downloads there are just related to the SDL 1.2 Tutorial and furthermore it would be more convenient to have them directly within the chapter page that is related to them. The tables section is also gone for now, no need for having them anymore.

And now have fun exploring the new site and functionality. By the way, you should be able to log-in via several social media services (e.g. Twitter), so you are not in need to create a new account.

 

News Archive 2005-2015

News archive 2005-2014

The following table is extracted directly from the original news page of the old FreePascal-meets-SDL.net website, which shows the news from 20th July of 2005 to 19th July of 2014.

The table had two colons, the left one showing the date, the right one the news text. Have fun browsing through the old news.

19th July 2014 Chapter 7 is finished and released today. It explains how to generate text with SDL2_ttf.


5th April 2014 The new SDL2 chapter 6 has been released. It treats further very important texture manipulation functions, e.g. rotation, scaling and colour manipulations, and also describes some functions to set a viewport and the “logical size resolution”.


19th January 2014 Yeah, new year, new chapters! They treat the brand new SDL2. With this update the first five chapters treating SDL2 are released. They introduce to SDL2 and cover many basic and new concepts. For example the concept of textures (in contrast to surfaces) is explained, displaying images, drawing primitives and much more. Expect more chapters to come. The old chapters treating SDL 1.2 are still available for those who are still interested in them.


16th November 2013 I didn’t have much time to care too much about this site lately. Anyway, on 12th August 2013 finally SDL2 (short for SDL 2.0) has been released! This is excellent news since with SDL2 a lot of improvements and new features are introduced to SDL. Check out the SDL2 MigrationGuide to see which new features are introduced and what you need to know about SDL2. And there are some Pascal units available already, check these out here (pure units), here (pure units, different project) and here (units incorporated in a game library called Bare Game Library). As soon as possible I will also start to update my tutorials to the use of the new units, probably archiving the old tutorial pages treating SDL 1.2 and just start from scratch for the new pages treating SDL 2.0. Thanks to Cybermonkey for the hint in the forum! 🙂


10th March 2012 A new chapter 8a is now released. It explains how to convert a SDL image to an OGL texture. Before writing this chapter I thought about extending chapter 8 but then I felt it might be too many new information, especially if someone’s new to SDL AND OpenGL. Also made several minor changes to the website, e.g. every page got the doctype line for better browser compatibility.


3rd July 2011 I’m very happy to announce that more than 10,000 visitors hit my site by now! Eventually this hobby project can be counted as success. Thanks to all visitors, readers and especially participants who mentioned bugs and ideas in the forum! Last but not least to mention the fruitful partnership with the Pascal Game Development project and their magazine! Thanks to Jason and his team!Since FPC ships SDL with pre-compiled units since a while I decided to remove the path setting steps in several chapters (3a, 5, 7, 8). They may confuse readers. Furthermore they are quite specific for the FP IDE, I doubt many people really use this nowadays for serious development. Otherwise beginners who might still use the FP IDE or a different IDE should get the idea when seeing how to set the unit paths in FP IDE. Therefore, for people who install the units manually I added these information at the end of the first chapter with a little explanation. I added a FAQ page for frequently asked questions, mainly from the forum. The first question added concerns the 64 bit compatibility of SDL (thanks to Cybermonkey for a a lot of contributions to solve this).


2nd January 2011 New chapter 4a created dealing with SDL_GFX which is a valuable extension of SDL. It is demonstrated how to compile your own SDL_gfx.dll, how images are zoomed and rotated, a framerate manager is introduced and primitives are drawn. The author’s page is added to the link list.In 2005, when starting this page, one of the two main purposes was to show how to install/configure your Windows machine to work with Free Pascal and SDL, nowadays FPC is shared with JEDI-SDL implemented as an auto-installer, also JEDI-SDL itself is installed by an auto-installer. So actually a manual installation isn’t necessary anymore for recent versions of these software packages. For archiving reasons I will keep chapter 1 as is but it is kind of obsolete. I did minor changes to chapter 1 and 1a.


7th November 2010 Recently issue #3 of the Pascal Gamer Magazine has been released. Please check this great stuff out!


22nd October 2010 Two important news this time. Firstly, chapter 6 ist now completely updated. From now on ALL chapters show the complete source code of the example programs completely first and are then treating the source step by step. Secondly, PascalGameDevelopment.com and the Pascal Gamer Magazine are from now on official partner sites of Free Pascal meets SDL. If you’re interested in Pascal game development you should really check out these sites. Especially the forum of PascalGameDevelopment.com is a rich resource for programmers. There are currently two issues published of the Pascal Gamer Magazine which are available online for free, so don’t hesitate to give this high quality magazine a try.


11th September 2010 Just a small counter (page views) update. This was requested by the counter provider.


8th August 2010 Updated chapter 5 completely.


9th June 2010 Updated chapter 4 completely.


1st November 2009 Updated chapter 2 and 3. Explanation of variable type UInt32 shifted from chapter 3 to 2. I decided to give the exact definition for any function provided in my tutorial according to the corresponding source code. So instead of general arguments like “components” or “parameters”, the exact parameter list and their variable types are shown.


27th September 2009 Took me longer than expected, but added now the new chapter 8 describing how to prepare Free Pascal and SDL for OpenGL programming. Thanks to Roin who mentioned a now fixed major bug which let the source code snippets appear centered instead of left aligned in many browsers (Epiphany, Firefox, IE). Changes in main page. Reworked chapter 3. Moved information about SDL_DELAY function from chapter 4 to chapter 3. Added a result box at the end of any chapter describing what the program is going to do if working correctly.


8th July 2009 Along with the new URL www.FreePascal-meets-SDL.net, a whole bunch of updates come up. I reworked and shortened chapter 1 now giving some information about the recently provided JEDI-SDL units of FPC since version 2.2.2. Renamed chapter 1b to 1a. More details on SDL_DELAY function in chapter 4. Reworked the table of chapter 5. Added new chapter 3a describing the usage of different image format (e.g. JPG, PNG, GIF…). I’m working and planning to release two new chapters in the next time, so stay tuned. Please don’t forget to update your links or bookmarks to the new URL.


13th July 2008 Reader Robvdl mentioned that Firefox users aren’t able to view many images and to download some files. I fixed this now. Thanks Robvdl. I also added a new subforum now for questions related to programming.


26th April 2008 New chapter 7 added! Now you learn how to introduce music and sound to your programs. I reworked chapter 3 and now explain not only how to display a picture but how to blit parts of pictures which is a quite important feature at all. Updated chapter 1 and link section a little.


13th January 2008 Happy new year! I reworked the first chapter because the JEDI-SDL project now provides an auto-installer. The new chapter 1b describes the installation and configuration of Lazarus. This surely isn’t directly related to SDL but the combination of SDL and Lazarus yields a quite powerful development kit. The links are updated and I started adding copyright information.


7th October 2007 Read in a pascal development forum that someone had problems getting my tutorials to run because he didn’t know about CRT unit which I used habbitually in any chapter. When I thought about it, it seemed really avoidable in most cases so I reworked all chapters and removed it if possible.


26th July 2007 Reworked chapter 6 for JEDI-SDL and added mouse handling.


15th June 2007 Reworked chapter 5 for JEDI-SDL.


6th May 2007 Reworked chapter 4 for JEDI-SDL.


4th May 2007 Major changes have been applied to this site. Since the SDL4FP project seems to be dead I will now rewrite all tutorials for JEDI-SDL project. This project is alive and in development and has much more translated headers. The first three chapters are finished and can be accessed by the menu. The old chapters for SDL4FP are available, too but you should really think about switching to JEDI-SDL.


3rd April 2006 Added first part of chapter 6, which describes event handling. Furthermore I updated some chapters, added some links and a brand new tables page which contain two useful tables. I will add new tables if I think they could be useful.


15th October 2005 Added new chapter, added links and download area.


22nd July 2005 Made some updates to the site and added a new chapter.
20th July 2005 Today page got online with first three chapters describing how to configure a windows system to use Free Pascal and SDL library. Furthermore there is a forum to keep contact if needed.

Chapter 1 – Introduction

Last updated on July 22nd, 2020

The introduction is short.

What is SDL or rather SDL2?

SDL abbreviates Simple Direct Media Layer. In August 2013 the official successor of original SDL (SDL 1.2) has been released, simply called SDL2 (or SDL 2.0). It is a library to develop powerful applications for many different operating systems (platforms) by learning only one set of commands. This is called cross-platform development. The following platforms are officially supported by SDL2:

  • Windows
  • Mac OS X
  • Linux
  • iOS
  • Android.

Internally the SDL library layer translates your commands to the platform specific commands, which is reflected by the followig diagram.

SDL2 Layers Diagram
Image by Adriatikus at English Wikipedia [Public domain], Wikimedia
SDL2 Layer Diagram

It’s especially meaningful to use the SDL library if you plan to develop games or need fast paced rendering. Jump and run-, Role-playing-, Real time/turn based strategy-, side-scrolling-, arcade-, board-, card-, simulation-, multi-user dungeon-, puzzle-, shooter-, network games and so on are possible, and any combination of these ;-).

Licensing

The SDL2 library, as well as the units for translation, are licensed under the zlib license. This license grants a high degree of freedom. So even closed-source, commercial applications and games are possible with SDL2 and Free Pascal. As a sidenote, you are free to choose the MPL license for the units, if you like.

How to get SDL2 for Free Pascal or Object Pascal?

There are several SDL2 units out there (see comparison and discussion here) which translate SDL2 to Pascal, since originally it has been written in C. Over time it turned out that the PGD community SDL2 units are the best choice to use if you like to get into SDL2 development in Free Pascal or Object Pascal.

A detailed installation instruction to set your system up for SDL2 development under Pascal is found in Chapter 2 for Windows or Linux. If you did install SDL2 for Free Pascal or Object Pascal already, proceed to Chapter 3. Please choose:

Chapter 2 (Windows) → | Chapter 2 (Linux) → | Chapter 3 →

Chapter 2 – Installation and Configuration

Last updated on July 22nd, 2020

What is covered, what not?

  • installation guide for SDL 2.0 under Microsoft Windows
  • installation of Free Pascal Compiler (FPC)
  • installation of Free Pascal IDE and Lazarus IDE
  • installation of SDL 2.0
  • configuration of FP IDE and Lazarus IDE to work with SDL 2.0
  • after this you are ready to code awesome SDL 2.0 stuff 🙂

Free Pascal IDE or Lazarus IDE

IDE stands for integrated development environment. Although you could write your programs in a simple text editor, an IDE makes your life much easier. For example, it highlights keywords, makes it easier for you to set up the compiler, and much more. Now let’s have a look at these two IDEs:

You may notice that the native Free Pascal IDE (left) looks old, but it is shipped right along with the Free Pascal Compiler. In contrast to that the Lazarus IDE (right) looks up-to-date, but requires it to be installed additionally. My advise is nonetheless, use the Lazarus IDE.

The Free Pascal Compiler (FPC)

We need three different software packages. First of all we need the stand-alone Free Pascal Compiler or Lazaruse IDE (which already has a copy of the Free Pascal Compiler included). If you are not sure, I recommend to go with the Lazarus IDE package.

SDL Library and SDL 2.0 units

Additionaly we need the original SDL library files (.dll files). And finally we need units that connect our SDL 2.0 code written in Free Pascal to the SDL library files. The latter will be done by SDL 2.0 units.

This table provides all information and sources you need with respect to installation steps 1) – 3). Keep in mind, you have to download either the Lazarus IDE or the stand-alone Free Pascal Compiler, not both.

Software,
Version,
approx. Size [MB]
Filenames,
Source link
Details and remarks
Lazarus IDE (has FPC included)
1.4.4 or later
N/A
lazarus-1.4.4-fpc-2.6.4-win32.exe
http://www.lazarus-ide.org/index.php?page=downloads
Linux and Mac OS X versions are here: http://www.lazarus-ide.org (see Downloads).
Free Pascal Compiler (stand-alone)
3.0.0 or later
22-40
fpc-3.0.0.i386-win32.exe
Windows 32 bit version
fpc-3.0.0.i386-win32.cross.x86_64-win64.exe
Windows 64 bit version (needs 32 bit version)
If you need the Linux, Mac OS X or other versions, check them out here: http://www.FreePascal.org (see Download).
SDL 2.0 units
1.72* (see remark)
0.1
Pascal-SDL2-for-Pascal-master.zip
https://github.com/PascalGameDevelopment/SDL2-for-Pascal
On the right upper side is a button saying Download ZIP. Click on this button for the download of the latest release. *Better go with the latest availabe version (not version 1.72!) since some important bugfixes have been made lately.
SDL 2.0 dynamic link library
2.0.4
0.35
SDL2-2.0.4-win32-x86.zip
SDL2-2.0.4-win32-x64.zip
http://www.libsdl.org
SDL 2.0 > Download > Choose the download suitable for your system.

Download Lazarus or the stand-alone Free Pascal Compiler (FPC)

If you have Free Pascal or the Lazarus IDE installed already, you can skip the steps 1a) and 1b).

1a) For Lazarus IDE: Download the latest version of the Lazarus IDE. It has the Free Pascal Compiler accompanied. Remark: As of today (12/02/2016) the bundle doesn’t provide the most recent Free Pascal Compiler (3.0.0) but the version before (2.6.4). The tutorial examples will work with both versions though.

1b) For Free Pascal IDE: 32 bit Windows: Download the latest stable Free Pascal compiler, version 3.0.0 or higher. 64 bit Windows: You have two choices, 1) Simple way: Go with the 32 bit version of Free Pascal. (Recommended), 2) Install the 64 bit version of Free Pascal on top of the 32 bit version of Free Pascal. In this case you need both files. Hence, you need to download both Free Pascal installers shown above.

Download SDL 2.0 and Header translation

2) Download the latest version of Tim Blume’s SDL 2.0 units, better go with the latest branch (master branch), and do not use version 1.72 since it contains some bugs. Click on “Clone or download” and then on “Download ZIP” (see arrows in image below) of the page and make sure that Branch: master (not v1.72!) is chosen at the left side (see arrow in image below). This is important for any operating system: Windows, Linux, Mac OS X.

Download SDL2 units on GitHub
Choose the master branch (1), click on “Clone or download” (2) and click on Download ZIP (3).

3) Download the latest version of SDL 2.0 runtime library, version 2.0.4 or higher.

Install Lazarus or the Free Pascal Compiler

4a) For Lazarus: 32 and 64 bit Windows: Execute lazarus-1.4.4-fpc-2.6.4-win32.exe  to install Lazarus for a 32 bit or 64 bit Windows system and follow the self-installer. Let the self-installer create a shortcut on your desktop.

4b) For Free Pascal IDE: 32 and 64 bit Windows: Execute fpc-2.6.4.i386-win32.exe  to install Free Pascal for a 32 bit or 64 bit Windows system. Let the self-installer create a shortcut on your desktop. Don’t modify any checked options during installation process. The default path is: C:\FPC\[Compiler version]\. [Compiler version] should be 3.0.0 or higher numbers. 64 bit Windows only: After you installed the 32 bit Free Pascal, you may execute fpc-3.0.0.i386-win32.cross.x86_64-win64.exe optionally to add the 64 bit version on top.

Install SDL 2.0 and Header translation

5) Extract SDL2-2.0.4-win32-x86.zip or SDL2-2.0.4-win32-x64.zip to get the SDL runtime library. This leads to two extracted files. There is a text file and the very important SDL2.dll.

6) 32bit Windows: Copy those files (especially the SDL2.dll!) to your system32-folder, C:\WINDOWS\system32\. 64bit Windows:  Copy those 64bit files to your system32-folder (!), C:\WINDOWS\system32\, Windows is expecting you to do this. Do not use the SysWoW64-folder (Hint: 32 bit files on 64 bit Windows go here).

If it is not possible to copy the files into this folder (or you are unsure about its location) alternativly you can copy the SDL2.dll right into the same folder where the SDL 2.0 application (.exe) is located. That is because SDL 2.0 first  looks for the SDL2.dll in the folder from which it is executed and if it isn’t found there, in the corresponding system folder! Anyway, if it isn’t found anywhere, the program will raise an error.

Now you have installed Free Pascal and the SDL runtime library on your system. Finally SDL 2.0 units have to be installed.

7a) For Lazarus IDE: Extract the SDL2-for-Pascal-master.zip. The Free Pascal Compiler is located in a subfolder called “fpc”. I suggest to copy all the files to a folder with full path C:\Lazarus\fpc\[Compiler Version]\units\SDL2\. [Compiler version] should be 2.6.4 or higher numbers. Skip step 7b).

7b) For Free Pascal IDE: Extract the SDL2-for-Pascal-master.zip. I suggest to copy all the files to a folder with full path C:\FPC\[Compiler Version]\units\SDL2\. [Compiler version] should be 3.0.0 or higher numbers. All later chapters will assume you installed to this path.

Configuring the Lazarus IDE

Now the compiler has to be told where to find the new units.

8) Open the Free Pascal IDE (for example by clicking the shortcut on desktop).

Lazarus IDE Desktop Icon

9) In Lazarus the path to external units has to be set for each project. Create a project if no project is set up (Project > New Project …). In the menue choose the following item Project > Project Options …. Now a window should pop up.

10) Under “Compiler Options” choose “Paths” (see red mark). Choose the three dots button (see red mark on the right side) for the “Other units files (-Fu)” field (red mark). This makes the “Path Editor” pop up. In the area “Search paths:”, click on the yellow folder symbol in the right bottom corner. Choose the path to your SDL-units (e.g. C:\Lazarus\2.6.4\units\SDL2). Make sure the path leads to the folder, where the sdl2.pas file is located! This file contains all the basic features of SDL 2.0.

Lazarus IDE Include Paths

Confirm by clicking “OK” until all windows are closed. Your Lazarus IDE is now set up for SDL 2.0 application development :-)!

Configuring the Free Pascal IDE (skip if you use Lazarus)

Now the compiler has to be told where to find the new units.

8) Open the Free Pascal IDE (for example by clicking the shortcut on desktop).

Free Pascal IDE Desktop Icon

9) In the menue choose the following item Options > Directories…. Now a window should pop up.

10) The first tab whitin this new window is called “Units”. Here you add the full path to your SDL-units (e.g. C:\FPC\3.0.0\units\SDL2) right below the other paths. Leave the last backslash out. Make sure the path leads to the folder, where the sdl2.pas file is located! This file contains all the basic features of SDL 2.0.

SDL2 directories
Since the screenshot is old, the compiler version has been 2.6.2, which is reflected in the shown pathes. It should be 3.0.0 or higher numbers for you.

Confirm by clicking “OK”.

Finally

Congratulations! You have configured your system for developing SDL 2.0 applications with the Lazarus IDE or the Free Pascal IDE! Simple, isn’t it? 🙂

For those of you who try running a program and get an abortion together
with a messege saying “exitcode = 309”: You skipped step 6! Did you copy
the SDL2.dll to your system32- or system-folder respectively? If so and the
error still occurs you should copy the SDL2.dll into the folder
where the programs are placed. Now it should work.

← Chapter 1 | Chapter 3 →

First Steps

Last updated on November 21st, 2021

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 SDL 2.0 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 SDL 2.0 in your Pascal programs is obviously:

Always include the SDL2 unit in the uses clause.

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

The different features of SDL 2.0 (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 SDL 2.0 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.

C variable types

You may wonder about the return value cint in the SDL_Init function declaration. This and other similar types (which we will see in other chapters again) originate from the original C-language in which SDL2 has been written. cint simply means a C integer variable. Similar to a Pascal integer, a C integer can be different in memory size depending on your system and that is why it is important to know exactly with which variable types you are working. Further examples: cuint8 is a C unsigned integer of 8 bit size, cint32 is a C signed integer of 32 bit size, cfloat is a C float point variable, and so on.

In Free Pascal they are correctly translated to the corresponding Pascal variable type by the ctypes unit. In Delphi this is done by a ctypes.inc file shipped with the units.

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.

SDL 2.0 functions and errors

Every SDL 2.0 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 SDL 2.0 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 SDL 2.0 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 →

Does SDL provide 64 bit compatibility?

Yes, SDL is 64 bit compatible.

If you experience troubles: First of all, make sure the problem is really caused by the 64 bit operating system you use. Does the program run without any problems if run it in a 32 bit operating system?

Make sure, that the Free Pascal compiler you use is the 64 bit version. There are different links on the download page of Free Pascal to different 64 bit operating systems for different architectures (Intel, AMD, PowerPC), so did you install the right 64 bit version of FPC?

If all this applies and you still get an error saying

sdlutils.pas Warning: Conversion between ordinals and pointers is not portable

and/or

sdlutils.pas Error: Typecast has different size (4 -> 8) in assignment

(or similar messages) then your problem clearly is related to 64 bit compatibility.

In the FPC reference is written about this type-checking error:

If you typecast a pointer to an ordinal type of a different size (or vice-versa), this can cause problems. This is a warning to help in finding the 32-bit specific code where cardinal/longint is used to typecast pointers to ordinals. A solution is to use the ptrint/ptruint types instead.

That is exactly what is done by sdlutils.pas and many other files and causes the errors and warnings!

In other words, the size of pointers and integers is different on 64 bit systems. They should be of same size to make conversion safe. To circumvent this problem you have to replace a conversion of UINT32(POINTER) by PTRUINT(POINTER) and INTEGER(POINTER) by PTRINT(POINTER). The PTRUINT and PTRINT integer types are always the same size as the pointer by definition. For FPC users both types are introduced since version 1.9.3. For other compilers (e.g. Delphi, Kylix, GPC, …) they are not and you have to define them yourself (see below).

Examples:

1) sdlutils.pas:

p := Pointer( Uint32( SrcSurface.pixels ) + UInt32( y ) * SrcSurface.pitch + UInt32( x ) * bpp );" gets "p := Pointer( PtrUInt( SrcSurface.pixels ) + UInt32( y ) * SrcSurface.pitch + UInt32( x ) * bpp );

2) sdlutils.pas:

Addr1 := cardinal( Pixels );" gets "Addr1 := PtrUInt( Pixels );

3) sdl_flic.pas:

line := PUint8(Integer(line) + flic.Surface.pitch);" gets "line := PUint8(PtrInt(line) + flic.Surface.pitch);

Definition of PTRUINT and PTRINT for non-FPC compilers:

{$ifndef FPC}

type

PtrInt = LongInt;

PtrUInt = LongWord;

{$endif}

There is a patch which is replacing all the questionable parts of the JEDI-SDL package, so you wouldn’t have to do it manually. Furthermore it is introducing the definition of the new types for non-FPC compilers. Link: Patch for 64 bit support. Unfortunately it is only useful if you manage your JEDI-SDL files by CVS or SVN. Nevertheless you could download the patch and check what the patch is changing and how to do it properly (the examples are generated from the patch).

More infos about this topic in the forum: Forum discussion about 64 bit compatibility. Thanks to Cybermonkey for his helpful response.