Difference between revisions of "FPC and SDL"

From Lazarus wiki
Jump to navigationJump to search
(OpenGL link added)
(General cleanup and fix syntaxhighlight tag errors)
 
(44 intermediate revisions by 16 users not shown)
Line 1: Line 1:
==Introduction==
+
{{FPC and SDL}}
  
I assume that you already have at least minimal knowledge of what SDL is and its basic functions.<br>
+
'''Simple DirectMedia Layer''' or '''SDL''' is a cross-platform development library designed to provide low-level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D. It is used by video playback software, emulators and popular games.
For those who want to learn more I suggest to visit the [http://www.libsdl.org SDL homepage].<br>
 
This page is going to explain how to use SDL with Free Pascal, where to obtain the pascal headers etc.
 
  
==Obtaining FPC headers for SDL==
+
== Introduction ==
 +
For general information and documentation about SDL, visit the [https://www.libsdl.org/index.php Official SDL Website]. This page is going to explain how to use SDL with Free Pascal and where to obtain the Pascal headers, etc. More information is available at the [https://wiki.libsdl.org/SDL2/FrontPage LibSDL Wiki].
  
After installing SDL itself on your system you'll need pascal headers to be able to use SDL with FPC.<br>
+
== Obtaining FPC headers for SDL2 ==
You can download from CVS(deprecated)
+
After installing the SDL library itself on your system, you'll need the Pascal headers for it to be able to use SDL with FPC. Since version 2.2.2, most SDL units are included with FPC. You can, of course, also download them from SDL2-for-Pascal, in case you need some bug fix or a unit that's not in the version shipped with FPC.
  
cvs -d :pserver:cvs@cvs.freepascal.org:/FPC/CVS login
+
=== SDL2-for-Pascal ===
 +
&emsp;&emsp;'''See:''' [https://github.com/PascalGameDevelopment/SDL2-for-Pascal The SDL2-for-Pascal GitHub Repository].
  
password is 'cvs'
+
You can download the latest release from the [https://github.com/PascalGameDevelopment/SDL2-for-Pascal/releases Releases page].
  
cvs -d :pserver:cvs@cvs.freepascal.org:/FPC/CVS -z3 co projects/contrib/sdl
+
You can also download and browse the current source code using Git, see [https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories GitHub's "About Remote Repositories" page] for instructions. In short, just do:
 +
<syntaxhighlight lang="shell">
 +
git clone https://github.com/PascalGameDevelopment/SDL2-for-Pascal.git
 +
</syntaxhighlight>
  
OR
+
After you download the SDL2-for-Pascal sources, you want to be able to use these units in your programs. For the simplest scenario, just add the following lines to your <code>fpc.cfg</code> file:
 +
<syntaxhighlight lang="shell">
 +
-Fi<jedi-sdl-path>/units/sdl2.pas
 +
-Fu<jedi-sdl-path>/units/sdl2.pas
 +
-Fu<jedi-sdl-path>/units/sdl2_gfx.pas
 +
-Fu<jedi-sdl-path>/units/sdl2_image.pas
 +
-Fu<jedi-sdl-path>/units/sdl2_mixer.pas
 +
-Fu<jedi-sdl-path>/units/sdl2_net.pas
 +
-Fu<jedi-sdl-path>/units/sdl2_ttf.pas
 +
</syntaxhighlight>
 +
…where <var><jedi-sdl-path></var> is the path where you placed the SDL2-for-Pascal sources.
  
[http://www.delphi-jedi.org/Jedi:TEAM_SDL_HOME this page].<br>
+
Alternatively, you can copy all <code>*.pas</code> and <code>*.inc</code> files from these directories to one chosen directory, and add only this chosen directory to your <code>fpc.cfg</code>.
Unpack the v1.0 SDL sources into a directory. Copy all *.pas files (SDL/Pas; SDL_Image/Pas etc)<br>
 
into some directory you can access with relative paths to your project.<br>
 
For example make a "basesdl" directory in your project and copy all the pas files there.<br>
 
  
==Tips and tricks==
+
=== SDL headers from Free Pascal SVN (deprecated) ===
 +
The code can be downloaded with:
 +
<syntaxhighlight lang="shell>
 +
svn co http://svn.freepascal.org/svn/fpcprojects/contrib/sdl/ fpc-sdl
 +
</syntaxhighlight>
  
There is one more thing I'd like to point out. If you use SDL_mixer you'll notice that it's dependent
+
== Tips and tricks ==
on smpeg library. This can be a setback since this isn't a standard library and is hard to get (CVS only afaik).<br>
+
=== SDL_mixer library ===
However the SDL_mixer.pas header for it uses smpeg by default even if SDL_mixer itself isn't linked to it.<br>
+
When using SDL_mixer, the call to Mix_OpenAudio MUST happen before the call to SDL_SetVideoMode, otherwise you will get a (sometimes loud) audible pop.
To remove this you just need to remove smpeg.pas from it's uses and comment out one line in the sources mentioning<br>
 
mp3s (it's a case near the end). This way your app. won't use smpeg.so/dll anymore.
 
  
==Mac OS X specific issues==
+
=== SMPEG Library ===
 +
If you use sdl2_mixer, you'll notice that it's dependent on the [https://github.com/icculus/smpeg SMPEG Library]. For modern Linux distributions this is not a problem, because smpeg is distributed with many of them, but it can be more troublesome for FreeBSD and Windows:
 +
* You can install smpeg for FreeBSD from ports: <code>/usr/ports/multimedia/smpeg</code>.
 +
* You can get smpeg.dll for Windows from [https://github.com/icculus/smpeg/blob/main/VisualC.zip SMPEG for Visual C sources].
  
SDL uses a dirty trick to create a GUI window for drawing things in on several OS'es, such as Mac OS X, Win32 and others. It has a macro inside the SDL_main.h header which redefines the term <tt>main</tt> into <tt>SDL_main</tt>, and includes its own <tt>main</tt> function inside libSDL. This libSDL main function creates the GUI window and does some other setup, and then calls the function <tt>SDL_main</tt> (i.e., your main program).
+
Alternatively, you can simply modify the source of SDL_mixer.pas to remove smpeg from it's uses clause and comment out one line in the sources mentioning mp3s (it's a case near the end). Remember that you will also need to have an <code>sdl2_mixer.dll</code>/<code>sdl2_mixer.so</code> that is ''not'' linked to smpeg&mdash;otherwise the sdl2_mixer library will depend on smpeg anyway.
  
Of course, under Pascal such macro trickery does not work. The win32 Pascal ports of SDL contain a translation from C into Pascal of the main function inside libSDL. For Mac OS X, this is not possible because there this main function is written in Objective C.
+
== macOS specific issues ==
 +
=== SDL Framework and SDL libraries ===
 +
On macOS, SDL2 uses Cocoa to setup the drawing window and to handle all events (such as keypresses). This is done using a small piece of code that is automatically called when the program starts up, and which subsequently calls a function with the name ''SDLmain''.
  
The only workaround currently is to edit rtl/bsd/system.pp, and change the line
+
There are however two different ways to package/distribute SDL for macOS, and depending on which version you use, the procedure to get this startup code into your program is slightly different.
  
  procedure main(argcparam: Longint; argvparam: ppchar; envpparam: ppchar); cdecl; [public];
+
=== The framework version ===
 +
This the version that you get when you download the macOS version of SDL from [https://libsdl.org/ libsdl.org]. In this case, the startup code is only available in source form. It is located on the installation disk image, in the folder <code>devel-lite</code>. After copying the <code>SDL.framework</code> from the disk image to <code>/Library/Frameworks</code> and copying the <code>devel-lite</code> folder anywhere on your hard drive (e.g., in your home directory), you can compile it into libSDLMain.a by opening a Terminal session, navigating to the copied <code>devel-lite</code> folder, and executing the following commands:
 +
<syntaxhighlight lang="shell">
 +
gcc -c -o SDLMain.o SDLMain.m -I/Library/Frameworks/SDL.framework/Headers
 +
ar r libSDLMain.a SDLMain.o
 +
ranlib libSDLMain.a
 +
</syntaxhighlight>
  
into
+
You can then move the generated <code>libSDLMain.a</code> library anywhere you want. To make sure the linker can find it when you compile SDL applications, pass the <code>-Fl<var>/full/path/to/folder/containing/libSDLMain.a</var></code> command line parameter to the compiler.
  
  procedure SDL_main(argcparam: Longint; argvparam: ppchar; envpparam: ppchar); cdecl; [public];
+
=== The Unix library version ===
 +
There is also a "classic Unix" version of SDL for macOS (no framework, just a bunch of separate libraries), which you get if you compile SDL from sources, or if you install SDL using Fink or MacPorts. In this case, <code>libSDLmain.a</code> is already included in a compiled form. You just have to use the compiler's <code>-Fl</code> parameter, as explained in the previous section, to make sure that the linker can find this library.
  
If you then recompile the RTL, you will obtain an RTL which can be used to compile SDL programs. However, it will ''only'' work for SDL programs, since other programs now won't have a main function. We hope to solve this problem in a future version.
+
== For FPC 2.2.2 and later ==
 +
The SDL unit included with FPC includes all necessary framework, library and main procedure name renaming statements, so you no longer have to do anything special. Just add the sdl unit to your program and everything will be taken care of. However, the remarks about libSDLMain in the above section still hold (libSDLMain.a is required by the SDL unit included with FPC).
  
Apart from the above, you also have to link against the [[OpenGL]] and Cocoa frameworks, and against libgcc. You can do this by adding <tt>-k-framework -kOpenGL -k-framework -kCocoa</tt> on the command line when compiling SDL programs (and adding <tt>{$linklib gcc}</tt> in your program).
+
Note that if you use the original units as distributed by the JEDI team, you may still need to follow the instructions in the section below.
  
If you installed the SDL libraries using fink, add <tt>-k-L/sw/lib -k-lSDL</tt> to your fpc command.
+
== For FPC 2.0.2&ndash;2.2.0 ==
 +
With FPC v2.0.2 to v2.2.0, and possibly also when using the original SDL units as distributed by the JEDI team, you have to use the <code>-XMSDL_main</code> command line option and tell the linker to include some frameworks:
 +
# Install sdl, for example using fink.
 +
# Add the following to your program:
 +
#* <syntaxhighlight lang="pascal">
 +
{$linklib gcc}
 +
{$linklib SDLmain}
 +
uses sdl;
 +
</syntaxhighlight>
 +
# Then, this command line does it:
 +
#* <syntaxhighlight lang="shell">
 +
fpc -XMSDL_main -k-L/sw/lib -k-lSDL -k-framework -kOpenGL -k-framework -kCocoa -Fu<pathtosdl.pas files> -Fi<pathtosdl.inc files> YourProgram.pas
 +
</syntaxhighlight>
  
Upto here, this is valid for fpc 2.0.0
+
If you installed the SDL libraries using fink, also add <code>-k-L/sw/lib -k-lSDL</code> to your fpc command.
  
With MacOS X 10.4 and fpc 2.1.1 you do not have to change rtl/bsd/system.pp any longer. <tt>-XMSDL_main</tt> does the trick:
+
If <code>sdl.pas</code> and <code>jedi-sdl.inc</code> are in the directory of your program, you can omit <code>-Fu<pathtosdl.pas files> -Fi<pathtosdl.inc files></code>.
  
1) as before, install sdl, for example using fink.
+
== Examples ==
 
+
Creating an empty SDL window:
2) Add the following to your program:
+
<syntaxhighlight lang="pascal">
 
+
program sdltest;
  {$linklib gcc}
+
{$linklib gcc}
  {$linklib SDLmain}
+
{$linklib SDLmain}
   uses SDL;
+
uses sdl;
 
+
var
3) Then, this command line does it:
+
   scr: PSDL_Surface; // Our main screen
 +
begin
 +
  SDL_Init(SDL_INIT_VIDEO); // Initialize the video SDL subsystem
 +
  scr := SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE); // Create a software window of 640x480x8 and assign to scr
 +
  SDL_Quit; // close the subsystems and SDL
 +
end.
 +
</syntaxhighlight>
  
  <tt>fpc -XMSDL_main -k-L/sw/lib -k-lSDL -k-framework -kOpenGL -k-framework -kCocoa -Fu<pathtosdl.pas files> -Fi<pathtosdl.inc files> YourProgram.pas</tt>
+
You can then compile this code with: <syntaxhighlight lang="shell" inline>fpc -Fu<pathtosdl.pas files> -Fi<pathtosdl.inc files> example.pas</syntaxhighlight>
  
If sdl.pas and jedi-sdl.inc are in the directory of your program, you can omit <tt>-Fu<pathtosdl.pas files> -Fi<pathtosdl.inc files></tt>.
+
If you use Lazarus, make sure you fill in the "other unit files" and "include files" properly.
 
 
== Examples ==
 
  
Creating an empty SDL window:
+
== Ubuntu ==
 +
With Ubuntu, you can install the following, which saves you having to manually install the SDK packages…
 +
<syntaxhighlight lang="shell" inline>sudo apt install libsdl1.2-dev</syntaxhighlight>
 +
…and possibly also…
 +
<syntaxhighlight lang="shell" inline>sudo apt install libsdl2-dev</syntaxhighlight>
  
program sdltest;<br>
+
FPC knows SDL from home.
{$linklib gcc}
 
{$linklib SDLmain}<br>
 
uses sdl;<br>
 
var scr: PSDL_Surface; // Our main screen<br>
 
begin
 
  SDL_Init(SDL_INIT_VIDEO); // Initialize the video SDL subsystem
 
  scr:=SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE); // Create a software window of 640x480x8 and assign to scr
 
  SDL_FreeSurface(scr); // Free the surface
 
  SDL_Quit; // close the subsystems and SDL
 
end.
 
  
You can then compile this code with
+
== SDL2 Units ==
 +
=== Tutorials ===
 +
See the [https://www.freepascal-meets-sdl.net/sdl-tutorials/ Free Pascal meets SDL] website for tutorials on using Free Pascal and SDL.
  
  fpc -Fu<pathtosdl.pas files> -Fi<pathtosdl.inc files> example.pas
 
  
If you use lazarus, make sure you fill the "other unit files" and "include files" properly.
+
[[Category:Tutorials]]
 +
[[Category:Audio]]
 +
[[Category:Video]]
 +
[[Category:Multimedia]]
 +
[[Category:Headers and Bindings]]
 +
[[Category:FPC]]

Latest revision as of 05:39, 21 September 2023

English (en) 中文(中国大陆)‎ (zh_CN)

Simple DirectMedia Layer or SDL is a cross-platform development library designed to provide low-level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D. It is used by video playback software, emulators and popular games.

Introduction

For general information and documentation about SDL, visit the Official SDL Website. This page is going to explain how to use SDL with Free Pascal and where to obtain the Pascal headers, etc. More information is available at the LibSDL Wiki.

Obtaining FPC headers for SDL2

After installing the SDL library itself on your system, you'll need the Pascal headers for it to be able to use SDL with FPC. Since version 2.2.2, most SDL units are included with FPC. You can, of course, also download them from SDL2-for-Pascal, in case you need some bug fix or a unit that's not in the version shipped with FPC.

SDL2-for-Pascal

  See: The SDL2-for-Pascal GitHub Repository.

You can download the latest release from the Releases page.

You can also download and browse the current source code using Git, see GitHub's "About Remote Repositories" page for instructions. In short, just do:

git clone https://github.com/PascalGameDevelopment/SDL2-for-Pascal.git

After you download the SDL2-for-Pascal sources, you want to be able to use these units in your programs. For the simplest scenario, just add the following lines to your fpc.cfg file:

-Fi<jedi-sdl-path>/units/sdl2.pas
-Fu<jedi-sdl-path>/units/sdl2.pas
-Fu<jedi-sdl-path>/units/sdl2_gfx.pas
-Fu<jedi-sdl-path>/units/sdl2_image.pas
-Fu<jedi-sdl-path>/units/sdl2_mixer.pas
-Fu<jedi-sdl-path>/units/sdl2_net.pas
-Fu<jedi-sdl-path>/units/sdl2_ttf.pas

…where <jedi-sdl-path> is the path where you placed the SDL2-for-Pascal sources.

Alternatively, you can copy all *.pas and *.inc files from these directories to one chosen directory, and add only this chosen directory to your fpc.cfg.

SDL headers from Free Pascal SVN (deprecated)

The code can be downloaded with:

svn co http://svn.freepascal.org/svn/fpcprojects/contrib/sdl/ fpc-sdl

Tips and tricks

SDL_mixer library

When using SDL_mixer, the call to Mix_OpenAudio MUST happen before the call to SDL_SetVideoMode, otherwise you will get a (sometimes loud) audible pop.

SMPEG Library

If you use sdl2_mixer, you'll notice that it's dependent on the SMPEG Library. For modern Linux distributions this is not a problem, because smpeg is distributed with many of them, but it can be more troublesome for FreeBSD and Windows:

  • You can install smpeg for FreeBSD from ports: /usr/ports/multimedia/smpeg.
  • You can get smpeg.dll for Windows from SMPEG for Visual C sources.

Alternatively, you can simply modify the source of SDL_mixer.pas to remove smpeg from it's uses clause and comment out one line in the sources mentioning mp3s (it's a case near the end). Remember that you will also need to have an sdl2_mixer.dll/sdl2_mixer.so that is not linked to smpeg—otherwise the sdl2_mixer library will depend on smpeg anyway.

macOS specific issues

SDL Framework and SDL libraries

On macOS, SDL2 uses Cocoa to setup the drawing window and to handle all events (such as keypresses). This is done using a small piece of code that is automatically called when the program starts up, and which subsequently calls a function with the name SDLmain.

There are however two different ways to package/distribute SDL for macOS, and depending on which version you use, the procedure to get this startup code into your program is slightly different.

The framework version

This the version that you get when you download the macOS version of SDL from libsdl.org. In this case, the startup code is only available in source form. It is located on the installation disk image, in the folder devel-lite. After copying the SDL.framework from the disk image to /Library/Frameworks and copying the devel-lite folder anywhere on your hard drive (e.g., in your home directory), you can compile it into libSDLMain.a by opening a Terminal session, navigating to the copied devel-lite folder, and executing the following commands:

gcc -c -o SDLMain.o SDLMain.m -I/Library/Frameworks/SDL.framework/Headers
ar r libSDLMain.a SDLMain.o
ranlib libSDLMain.a

You can then move the generated libSDLMain.a library anywhere you want. To make sure the linker can find it when you compile SDL applications, pass the -Fl/full/path/to/folder/containing/libSDLMain.a command line parameter to the compiler.

The Unix library version

There is also a "classic Unix" version of SDL for macOS (no framework, just a bunch of separate libraries), which you get if you compile SDL from sources, or if you install SDL using Fink or MacPorts. In this case, libSDLmain.a is already included in a compiled form. You just have to use the compiler's -Fl parameter, as explained in the previous section, to make sure that the linker can find this library.

For FPC 2.2.2 and later

The SDL unit included with FPC includes all necessary framework, library and main procedure name renaming statements, so you no longer have to do anything special. Just add the sdl unit to your program and everything will be taken care of. However, the remarks about libSDLMain in the above section still hold (libSDLMain.a is required by the SDL unit included with FPC).

Note that if you use the original units as distributed by the JEDI team, you may still need to follow the instructions in the section below.

For FPC 2.0.2–2.2.0

With FPC v2.0.2 to v2.2.0, and possibly also when using the original SDL units as distributed by the JEDI team, you have to use the -XMSDL_main command line option and tell the linker to include some frameworks:

  1. Install sdl, for example using fink.
  2. Add the following to your program:
    • {$linklib gcc}
      {$linklib SDLmain}
      uses sdl;
      
  3. Then, this command line does it:
    • fpc -XMSDL_main -k-L/sw/lib -k-lSDL -k-framework -kOpenGL -k-framework -kCocoa -Fu<pathtosdl.pas files> -Fi<pathtosdl.inc files> YourProgram.pas
      

If you installed the SDL libraries using fink, also add -k-L/sw/lib -k-lSDL to your fpc command.

If sdl.pas and jedi-sdl.inc are in the directory of your program, you can omit -Fu<pathtosdl.pas files> -Fi<pathtosdl.inc files>.

Examples

Creating an empty SDL window:

program sdltest;
{$linklib gcc}
{$linklib SDLmain}
uses sdl;
var 
  scr: PSDL_Surface; // Our main screen
begin
  SDL_Init(SDL_INIT_VIDEO); // Initialize the video SDL subsystem
  scr := SDL_SetVideoMode(640, 480, 8, SDL_SWSURFACE); // Create a software window of 640x480x8 and assign to scr
  SDL_Quit; // close the subsystems and SDL
end.

You can then compile this code with: fpc -Fu<pathtosdl.pas files> -Fi<pathtosdl.inc files> example.pas

If you use Lazarus, make sure you fill in the "other unit files" and "include files" properly.

Ubuntu

With Ubuntu, you can install the following, which saves you having to manually install the SDK packages… sudo apt install libsdl1.2-dev …and possibly also… sudo apt install libsdl2-dev

FPC knows SDL from home.

SDL2 Units

Tutorials

See the Free Pascal meets SDL website for tutorials on using Free Pascal and SDL.