email sol follow sol rss feed of the blog wishlist Sol::Tutorials

DirectX8, Fmod and CFL


Open source as .cpp as .html

In order to compile the example source, you'll need to link it with zlib.lib, available from, ready binaries for several platforms (including win32) available from

Additionally you'll need CFL3R2 or later, available from; From this package you need to add to your project the following: cfl3.cpp, cfl3_none.cpp and cfl3_zlib.cpp.

The 'media' ZIP file (downloadable from the main page) already contains the required .cfl file, but in order to create one you can run the makecfl utility that comes in the cfl3 package. With this command-line tool you can easily create .ini files, from which the same tool can compile the .cfl files. An example ini file is also included in the 'media' package.

Let's go through the changes again:

CFL                     *cfl;       // CFL library object

We're using just one library currently, so we only need one object. You can mount several .cfl data files into one library. If several .cfl files contain a data file of the same name, cfl will return the one that can be found from the last opened one. Thus, you can make 'patch' data files, or localization of resources, or savegames of your massive RPG, or..

Most of the changes are in the setup() function. First we load the module from memory:

    // Load data from CFL.
    // Please note that CFL is, by design, case sensitive:
    char * musicfile=cfl->getFile("CFD.S3M");
    int musicfilesize=cfl->getFileSize("CFD.S3M");

    mod = FMUSIC_LoadSongMemory(musicfile,musicfilesize);
    if (!mod)
    // Data is no longer needed:
    delete[] musicfile;

Earlier, we opened "cfd.s3m", while, on disk, it's actually "CFD.S3M". This case sensitivity is by design; when porting to the unix world, case is important. Easiest solution is to make sure all your filenames are in lower case. It looks tidier as well.

CFL does not support file streaming. All data is loaded in one chunk. This is, in most cases, enough. If you need to stream data, let's say MP3, you can still include that, uncompressed, inside the CFL file and ask CFL for a file pointer, for instance.

Here we ask for the data and size of the data. CFL3 uses new[] and delete[] internally, so using free() to the data is not wise. getFile function returns NULL if file is not found.

FMOD supports memory loading, so the next step is pretty simple. Finally, we free the memory we no longer need.

We go through pretty much the same steps for D3DX8 texture loader, as you can see:

    char * jpegfile=cfl->getFile("flare64.jpg");
    int jpegfilesize=cfl->getFileSize("flare64.jpg");
    delete[] jpegfile;

Rest of the changes are in the winmain function:

    char * buf;
    buf=new char[1024];

    // First try to open the CFL from the executable (if copy/b:d to the end)
    if (!(cfl=CFL::create(buf,0)))
        // if not found from the exe, try to open the separate file
        if (!(cfl=CFL::create("cfltut.cfl",0)))
            MessageBox(NULL,"Filesystem mount failed.","Oh dear",MB_OK);
    // Free the buffer that contained the exe name.
    delete[] buf;

Here we allocate some memory, and ask windows for the name (and path) of our application. We then ask cfl to create the cfl object using the same filename as the executable; if this fails, we try to open the cfltut.cfl on disk. We do it like this so that we can do something like this:

D:\MYPROJ> copy /b myprogram.exe+mydatafile.cfl

The above command appends the data file after the executable, removing another 'loose' file. After that we're down to two files - fmod.dll and the executable - as you can see if you download the 'final version' package from the 'main' page.

That wraps it up for this tutorial. I hope it shed some light on.. something =)

Next we'll send some comments to Sol =)..

Site design & Copyright © 2021 Jari Komppa
Possibly modified around: June 01 2010