QBXL Technical Articles

Advanced Libraries in FreeBASIC

By SJ Zero

FreeBASICs greatest strength is it's ability to seamlessly integrate with a number of standard C libraries while maintaining the ease of use that is QB. Even before FB had a built-in graphics library, intrepid coders were using SDL to get graphics and sound routines working. Before the current version included a SDL_NET and Winsock, a number of coders, myself included, fought with the headers to get network support into FreeBASIC. Today, I'm just going to cover how to get started with three advanced libraries: SDL, fmod, and tinyPTC. After understanding the fundamentals, you'll see that using C libraries is simple enough that with few exceptions, C libraries are no more difficult to use in FreeBASIC than QB libraries were to use.


0. What are these libs, anyway?

These libs are particularly useful because they tend to provide functions for games.

SDL is a library with Graphics and Input support built in, and a bunch of sublibraries for network, true type font support, and other things. It can be used with OpenGL, but I won't be covering that today.

TinyPTC is primarily a graphics lib, the simplest one available. It does little more than give you a pointer to the graphics reigon to fire at.

Fmod is a 3d sound and music library. Though it's license is strange, it works acceptably for playing sounds, and it nicely encapsulates 3d sound.

1. Including the library
The first step in getting any of these libraries to work is including their header files in your project.

For SDL, it's simply

'$INCLUDE: "SDL\SDL.bi"

For FMOD, it's

'$Include: 'fmod.bi'

and for tinyPTC, you'll want

'$INCLUDE: 'tinyptc.bi'

2. Initilizing the library, loading a file
Obviously, you can't just include the lib and fire away if it's got to do stuff first.

To initilize SDL and load a bitmap into memory, you must:

CONST SCR_WIDTH  = 640
CONST SCR_HEIGHT = 480
DIM bitmap AS SDL_Surface ptr 'our bitmap
DIM video AS SDL_Surface ptr 'our screen surface

    SDL_Init ( SDL_INIT_VIDEO )

    video = SDL_SetVideoMode( SCR_WIDTH, SCR_HEIGHT, 32, 0 ) 'sets the video mode for 640x480x32
    MenuScreen = SDL_LoadBMP("bitmap.bmp")

To initilize FMOD and load a sound into memory, you must:

    DIM sound AS INTEGER 'it's just a handle, so it's an int!

    IF FSOUND_GetVersion <= FMOD_VERSION THEN
          ErrorQuit "FMOD version " + STR$(FMOD_VERSION) + " or greater required"
    End If

    If FSOUND_Init(44100, 32, 0) = FALSE Then
          ErrorQuit "Can't initialize FMOD"
    End If

    sound = FSOUND_Sample_Load(FSOUND_FREE,"sound.wav", FSOUND_HW3D, 0, 0)

Finally, there's no data formats to load with tinyPTC because it's so simple, but you initilize it by going:

const SCR_WIDTH = 320
const SCR_HEIGHT = 200
const SCR_SIZE = SCR_WIDTH*SCR_HEIGHT
   
    if( ptc_open( "tinyPTC test", SCR_WIDTH, SCR_HEIGHT ) = 0 ) then
        end -1
    end if

3. Blitting, playing, or plotting
The most important step, obviously, is to get whatever you want to do to the screen or speakers. This part is relatively easy, and can be encapsulated further into a wrapper function. For SDL, sending an image to the screen means going:

SUB BlitImage(x as integer,y as integer,image as sdl_surface ptr)
   DIM Rectangle as SDL_Rect
   DIM Rectangle2 as SDL_Rect

        
         Rectangle.X = 0
         Rectangle.Y = 0
         rectangle.w = image->w
         rectangle.h = image->h
         Rectangle2.x = x
         Rectangle2.y = y
 
         SDL_BlitSurface image, @rectangle, screenSurface, @rectangle2
     
END SUB 

For FMOD, the steps to play a sound aren't that difficult either:

FUNCTION fModPlayWave( samp1 as integer ) AS INTEGER
'where samp1 is the number returned by FSOUND_SampleLoad


        DIM position(0 to 2)' as FSound_Vector
        DIM vel(0 to 2)' FSound_Vector
       
       
        fModPlayWave = FSOUND_PlaySoundEx(FSOUND_FREE, samp1, NULL, TRUE)
       
END FUNCTION

And tinyPTC, which is again, not a high level lib like the other two, can plot pixels using the following code:

SUB putd(BYREF buffer(), BYVAL x AS INTEGER, BYVAL y AS INTEGER, BYVAL colr as INTEGER)
buffer((y * SCR_WIDTH) + x) = colr
ptc_update @buffer(0) 'This is a pageFlip
END SUB

4. Shutting down

So you don't have to manage menory and do all the boring mundane tasks, you must remember to shut down the library before your program exits. Luckily, all three programs allow this with one line. If you can't shut it down, the library no longer cares. It's beautiful.

SDL: SDL_Quit ()
fmod:  FSOUND_Close ()
tinyPTC:   PTC_Close ()

That's all there is to quitting!

As you can see, there is nothing inherently more difficult in using libraries in FreeBASIC compared to QuickBASIC. In fact, because coders don't need to jump through hoops to get to memory, it's actually much easier, even with the more modern OS and hardware.

--SJ Zero is the god of freebasic...no, no he isn't.