Difference between revisions of "FPC and SDL"

From Free Pascal wiki
Jump to navigationJump to search
m (Adjusted heading levels)
(30 intermediate revisions by 13 users not shown)
Line 1: Line 1:
==Introduction==
+
{{FPC and SDL}}
  
For general information and documentation about SDL visit the [http://www.libsdl.org SDL homepage]. This page is going to explain how to use SDL with Free Pascal, where to obtain the pascal headers etc.
+
=Introduction=
  
==Obtaining FPC headers for SDL==
+
'''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.
  
After installing SDL itself on your system you'll need pascal headers to be able to use SDL with FPC.
+
For general information and documentation about SDL visit the [http://www.libsdl.org SDL homepage]. This page is going to explain how to use SDL with Free Pascal, where to obtain the Pascal headers etc.  More information is available at [http://wiki.libsdl.org the libsdl-wiki].
  
===SDL headers from JEDI-SDL===
+
=Obtaining FPC headers for SDL=
  
See [http://www.delphi-jedi.org/Jedi:TEAM_SDL_HOME JEDI-SDL Home Page].
+
After installing the SDL library itself on your system you'll need Pascal headers to be able to use SDL with FPC. Since version 2.2.2, most SDL units are included with FPC itself. You can of course also download them from JEDI-SDL in case you need some bug fix or a unit not in the version shipped with FPC.
 +
 
 +
==SDL headers from JEDI-SDL==
 +
 
 +
See [http://jedi-sdl.pascalgamedevelopment.com/ JEDI-SDL Home Page].
  
 
You can download [http://prdownloads.sourceforge.net/jedi-sdl/JEDI-SDLv1.zip?download JEDI-SDLv1.0 Beta]..
 
You can download [http://prdownloads.sourceforge.net/jedi-sdl/JEDI-SDLv1.zip?download JEDI-SDLv1.0 Beta]..
Line 15: Line 19:
 
You can also download and browse current CVS sources, see [http://sourceforge.net/cvs/?group_id=43805 JEDI-SDL SourceForge CVS] for instructions. In short, just do
 
You can also download and browse current CVS sources, see [http://sourceforge.net/cvs/?group_id=43805 JEDI-SDL SourceForge CVS] for instructions. In short, just do
  
  cvs -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/jedi-sdl login  
+
  cvs -d:pserver:anonymous@jedi-sdl.cvs.sourceforge.net:/cvsroot/jedi-sdl login  
  
 
(when prompted for a password, simply press the Enter key)
 
(when prompted for a password, simply press the Enter key)
  
  cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/jedi-sdl co JEDI-SDLv1.0
+
  cvs -z3 -d:pserver:anonymous@jedi-sdl.cvs.sourceforge.net:/cvsroot/jedi-sdl co JEDI-SDLv1.0
  
 
After you downloaded (and eventually unpacked) JEDI-SDL 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:
 
After you downloaded (and eventually unpacked) JEDI-SDL 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:
Line 49: Line 53:
 
   ./Oxygene
 
   ./Oxygene
  
Note that all jedi-sdl code should be compiled in Delphi-compatible mode. Most jedi-sdl units include jedi-sdl.inc that already has the line {$mode delphi} added, but some example programs don't include jedi-sdl.inc. So be sure to compiled them with -Sd command-line option (or add {$mode delphi} directive).
+
Note that all jedi-sdl code should be compiled in Delphi-compatible mode. Most jedi-sdl units include jedi-sdl.inc that already has the line {$mode delphi} added, but some example programs don't include jedi-sdl.inc. So be sure to compile them with -Sd command-line option (or add {$mode delphi} directive).
  
===SDL headers from FreePascal CVS (deprecated)===
+
==SDL headers from Free Pascal SVN (deprecated)==
  
Get them using CVS:
+
The code can be downloaded with:
  
  cvs -d :pserver:cvs@cvs.freepascal.org:/FPC/CVS login
+
  svn co http://svn.freepascal.org/svn/fpcprojects/contrib/sdl/ fpc-sdl
  
(password is 'cvs')
+
=Tips and tricks=
  
cvs -d :pserver:cvs@cvs.freepascal.org:/FPC/CVS -z3 co projects/contrib/sdl
+
== SDL_mixer library ==
  
==Tips and tricks==
+
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.
  
=== SDL_mixer library ===
+
== SMPEG library ==
When using SDL_mixer, the call to  Mix_OpenAudio MUST happen before the call to SDL_SetVideoMode, otherwise you will get a ( sometimes load ) audible pop.
 
  
=== SMPEG library ===
+
If you use SDL_mixer you'll notice that it's dependent on smpeg library. For modern Linux distros this is not a problem because smpeg is distributed with them, but it can be troublesome eg for FreeBSD and Windows:
  
If you use SDL_mixer you'll notice that it's dependent on smpeg library. For modern Linux distros and FreeBSD this is not a problem (because smpeg is distributed with them), but it can be troublesome e.g. for Windows. You can get smpeg.dll for Windows from [http://icculus.org/SDL_sound/downloads/sdl_sound_visualc_srcs.zip SDL_sound for Visual C sources].
+
* You can install smpeg for FreeBSD from ports: /usr/ports/multimedia/smpeg.  
 +
* You can get smpeg.dll for Windows from [http://icculus.org/SDL_sound/downloads/sdl_sound_visualc_srcs.zip SDL_sound for Visual C sources].
  
 
Alternatively, you can simply modify the source of SDL_mixer.pas: 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 SDL_mixer dll/so that is ''not'' linked to smpeg -- otherwise SDL_mixer library will depend on smpeg anyway.
 
Alternatively, you can simply modify the source of SDL_mixer.pas: 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 SDL_mixer dll/so that is ''not'' linked to smpeg -- otherwise SDL_mixer library will depend on smpeg anyway.
  
==Mac OS X specific issues==
+
=macOS specific issues=
  
===For FPC 2.1.1+ on Intel Mac OS X===
+
==SDL Framework and SDL libraries==
  
If you encounter relocation errors stating that __text and __TEXT sections of executable are read-only (this happens on linking), pass following parameters on command line:
+
On macOS, SDL 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''. More information is available at http://www.libsdl.org/faq.php?action=listentries&category=7#55
  
<tt>fpc myprogram.pas -k-read_only_relocs -kwarning</tt>
+
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.
  
This will change relocation errors to warnings only and your program will be linked and should work.
+
===The framework version===
  
===For FPC 2.0.2+===
+
This the version that you get when you download the macOS version of SDL from [http://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 ''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:
  
With fpc 2.0.2 or later you do not have to change rtl/bsd/system.pp any longer. <tt>-XMSDL_main</tt> does the trick:
+
gcc -c -o SDLMain.o SDLMain.m -I /Library/Frameworks/SDL.framework/Headers
 +
ar r libSDLMain.a SDLMain.o
 +
ranlib libSDLMain.a
  
1) as before, install sdl, for example using fink.
+
You can then move the generated ''libSDLMain.a'' librray 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.
  
2) Add the following to your program:
+
===The Unix library version===
  
  {$linklib gcc}
+
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.
  {$linklib SDLmain}
 
  uses sdl;
 
  
3) Then, this command line does it:
+
==For FPC 2.2.2 and later==
  
  <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>
+
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).
  
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>.
+
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.0-===
+
==For FPC 2.0.2 to 2.2.0==
  
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).
+
With fpc 2.0.2 to 2.2.0, and possibly also when using the original SDL units as distributed by the JEDI team, you have to use the <tt>-XMSDL_main</tt> command line option and tell the linker to include some frameworks:
  
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.
+
1) install sdl, for example using fink.
  
The only workaround currently is to edit rtl/bsd/system.pp, and change the line
+
2) Add the following to your program:
  
  procedure main(argcparam: Longint; argvparam: ppchar; envpparam: ppchar); cdecl; [public];
+
<syntaxhighlight lang="pascal">
 +
{$linklib gcc}
 +
{$linklib SDLmain}
 +
uses sdl;</syntaxhighlight>
  
into
+
3) Then, this command line does it:
  
  procedure SDL_main(argcparam: Longint; argvparam: ppchar; envpparam: ppchar); cdecl; [public];
+
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 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.
+
If you installed the SDL libraries using fink, also add <tt>-k-L/sw/lib -k-lSDL</tt> to your fpc command.
  
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).
+
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 installed the SDL libraries using fink, add <tt>-k-L/sw/lib -k-lSDL</tt> to your fpc command.
 
  
== Examples ==
+
= Examples =
  
 
Creating an empty SDL window:
 
Creating an empty SDL window:
  
program sdltest;<br>
+
<syntaxhighlight lang="pascal">
{$linklib gcc}
+
program sdltest;
{$linklib SDLmain}<br>
+
{$linklib gcc}
uses sdl;<br>
+
{$linklib SDLmain}
var scr: PSDL_Surface; // Our main screen<br>
+
uses sdl;
begin
+
var  
 +
  scr: PSDL_Surface; // Our main screen
 +
begin
 
   SDL_Init(SDL_INIT_VIDEO); // Initialize the video SDL subsystem
 
   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
+
   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
 
   SDL_Quit; // close the subsystems and SDL
end.
+
end.</syntaxhighlight>
  
 
You can then compile this code with  
 
You can then compile this code with  
  
  fpc -Fu<pathtosdl.pas files> -Fi<pathtosdl.inc files> example.pas
+
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.
 
If you use lazarus, make sure you fill the "other unit files" and "include files" properly.
 +
 +
= Tutorials =
 +
 +
See the [https://www.freepascal-meets-sdl.net/sdl-tutorials/ Free Pascal meets SDL website] for tutorials on using Free Pascal and SDL.
 +
 +
[[Category:Tutorials]]
 +
[[Category:Audio]]
 +
[[Category:Video]]
 +
[[Category:Multimedia]]
 +
[[Category:Headers and Bindings]]
 +
[[Category:FPC]]

Revision as of 01:50, 17 March 2020

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

Introduction

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.

For general information and documentation about SDL visit the SDL homepage. This page is going to explain how to use SDL with Free Pascal, where to obtain the Pascal headers etc. More information is available at the libsdl-wiki.

Obtaining FPC headers for SDL

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

SDL headers from JEDI-SDL

See JEDI-SDL Home Page.

You can download JEDI-SDLv1.0 Beta..

You can also download and browse current CVS sources, see JEDI-SDL SourceForge CVS for instructions. In short, just do

  cvs -d:pserver:anonymous@jedi-sdl.cvs.sourceforge.net:/cvsroot/jedi-sdl login 

(when prompted for a password, simply press the Enter key)

  cvs -z3 -d:pserver:anonymous@jedi-sdl.cvs.sourceforge.net:/cvsroot/jedi-sdl co JEDI-SDLv1.0

After you downloaded (and eventually unpacked) JEDI-SDL 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>/JEDI-SDLv1.0/SDL/Pas
 -Fu<jedi-sdl-path>/JEDI-SDLv1.0/SDL/Pas
 -Fu<jedi-sdl-path>/JEDI-SDLv1.0/SDL_Mixer/Pas
 -Fu<jedi-sdl-path>/JEDI-SDLv1.0/SDL_Image/Pas
 -Fu<jedi-sdl-path>/JEDI-SDLv1.0/SDL_Net/Pas
 -Fu<jedi-sdl-path>/JEDI-SDLv1.0/SDL_ttf/Pas
 -Fu<jedi-sdl-path>/JEDI-SDLv1.0/smpeg/Pas
 -Fu<jedi-sdl-path>/JEDI-SDLv1.0/SFont/Pas
 -Fu<jedi-sdl-path>/JEDI-SDLv1.0/SDL_Sound/Pas
 -Fu<jedi-sdl-path>/JEDI-SDLv1.0/SDLMonoFonts/Pas
 -Fu<jedi-sdl-path>/JEDI-SDLv1.0/SDLSpriteEngine/Pas
 -Fu<jedi-sdl-path>/JEDI-SDLv1.0/Cal3D/Pas
 -Fu<jedi-sdl-path>/JEDI-SDLv1.0/ODE/Pas
 -Fu<jedi-sdl-path>/JEDI-SDLv1.0/SDLCtrls/Pas
 -Fu<jedi-sdl-path>/JEDI-SDLv1.0/SDL_flic/Pas

(where <jedi-sdl-path> is the path where you placed jedi-sdl 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.

To test that everything works, you can compile and run one of numerous demo programs included, e.g.

 cd <jedi-sdl-path>/JEDI-SDLv1.0/SDLSpriteEngine/Demos/Oxygene/
 fpc -Sd Oxygene.dpr
 ./Oxygene

Note that all jedi-sdl code should be compiled in Delphi-compatible mode. Most jedi-sdl units include jedi-sdl.inc that already has the line {$mode delphi} added, but some example programs don't include jedi-sdl.inc. So be sure to compile them with -Sd command-line option (or add {$mode delphi} directive).

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 SDL_mixer you'll notice that it's dependent on smpeg library. For modern Linux distros this is not a problem because smpeg is distributed with them, but it can be troublesome eg for FreeBSD and Windows:

Alternatively, you can simply modify the source of SDL_mixer.pas: 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 SDL_mixer dll/so that is not linked to smpeg -- otherwise SDL_mixer library will depend on smpeg anyway.

macOS specific issues

SDL Framework and SDL libraries

On macOS, SDL 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. More information is available at http://www.libsdl.org/faq.php?action=listentries&category=7#55

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 librray 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 to 2.2.0

With fpc 2.0.2 to 2.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 the "other unit files" and "include files" properly.

Tutorials

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