# Datafile routines

- find_datafile_object
- fixup_datafile
- get_datafile_property
- load_datafile
- load_datafile_callback
- load_datafile_object
- register_datafile_object
- unload_datafile
- unload_datafile_object

Datafiles are created by the grabber utility, and have a .dat extension. They can contain bitmaps, palettes, fonts, samples, MIDI music, FLI/FLC animations, and any other binary data that you import.

Warning: when using truecolor images, you should always set the graphics mode before loading any bitmap data! Otherwise the pixel format (RGB or BGR) will not be known, so the file may be converted wrongly.

See the documentation for pack_fopen() for information about how to read directly from a specific datafile object.

DATAFILE *load_datafile(const char *filename);
Loads a datafile into memory, and returns a pointer to it, or NULL on error. If the datafile has been encrypted, you must first use the packfile_password() function to set the appropriate key. See grabber.txt for more information. If the datafile contains truecolor graphics, you must set the video mode or call set_color_conversion() before loading it.

> See also: load_datafile_callback, unload_datafile, load_datafile_object, set_color_conversion, fixup_datafile, packfile_password, find_datafile_object, register_datafile_object.

> Examples using this: excustom, exdata, exexedat, exgui, exsprite, exunicod.

DATAFILE *load_datafile_callback(const char *filename, void (*callback)(DATAFILE *d));
Loads a datafile into memory, calling the specified hook function once for each object in the file, passing it a pointer to the object just read.

> See also: load_datafile, unload_datafile, load_datafile_object, set_color_conversion, fixup_datafile, packfile_password, find_datafile_object, register_datafile_object.

void unload_datafile(DATAFILE *dat);
Frees all the objects in a datafile.

> See also: load_datafile.

> Examples using this: excustom, exdata, exexedat, exgui, exsprite, exunicod.

DATAFILE *load_datafile_object(const char *filename, const char *objectname);
Loads a specific object from a datafile. This won't work if you strip the object names from the file, and it will be very slow if you save the file with global compression. See grabber.txt for more information.

> See also: unload_datafile_object, load_datafile, set_color_conversion, find_datafile_object, register_datafile_object.

void unload_datafile_object(DATAFILE *dat);
Frees an object previously loaded by load_datafile_object().

> See also: load_datafile_object.

DATAFILE *find_datafile_object(const DATAFILE *dat, const char *objectname);
Searches an already loaded datafile for an object with the specified name, returning a pointer to it, or NULL if the object cannot be found. It understands '/' and '#' separators for nested datafile paths.

> See also: load_datafile, load_datafile_object.

const char *get_datafile_property(const DATAFILE *dat, int type);
Returns the specified property string for the object, or an empty string if the property isn't present. See grabber.txt for more information.

void register_datafile_object(int id, void *(*load)(PACKFILE *f, long size), void (*destroy)(void *data));
Used to add custom object types, specifying functions to load and destroy objects of this type. See grabber.txt for more information.

> See also: load_datafile, load_datafile_object.

void fixup_datafile(DATAFILE *data);
If you are using compiled datafiles (produced by the dat2s and dat2c utilities) on a platform that doesn't support constructors (currently any non GCC-based platform), or if the datafiles contain truecolor images, you must call this function once after your set the video mode that you will be using. This will ensure the datafiles are properly initialised in the first case and convert the color values into the appropriate format in the second case. It handles flipping between RGB and BGR formats, and converting between different color depths whenever that can be done without changing the size of the image (ie. changing 15<->16-bit hicolor for both bitmaps and RLE sprites, and 24<->32-bit truecolor for RLE sprites).

> See also: set_gfx_mode, set_color_conversion, Differences between platforms.

## Using datafiles

When you load a datafile, you will obtain a pointer to an array of DATAFILE structures:

>        typedef struct DATAFILE
>        {
>           void *dat;     - pointer to the actual data
>           int type;      - type of the data
>           long size;     - size of the data in bytes
>           void *prop;    - list of object properties
>        } DATAFILE;

The type field will be one of the values:

>        DAT_FILE       - dat points to a nested datafile
>        DAT_DATA       - dat points to a block of binary data
>        DAT_FONT       - dat points to a font object
>        DAT_SAMPLE     - dat points to a sample structure
>        DAT_MIDI       - dat points to a MIDI file
>        DAT_PATCH      - dat points to a GUS patch file
>        DAT_FLI        - dat points to an FLI/FLC animation
>        DAT_BITMAP     - dat points to a BITMAP structure
>        DAT_RLE_SPRITE - dat points to a RLE_SPRITE structure
>        DAT_C_SPRITE   - dat points to a linear compiled sprite
>        DAT_XC_SPRITE  - dat points to a mode-X compiled sprite
>        DAT_PALETTE    - dat points to an array of 256 RGB structures
>        DAT_END        - special flag to mark the end of the data list

The grabber program can also produce a header file defining the index of each object within the file as a series of #defined constants, using the names you gave the objects in the grabber. So, for example, if you have made a datafile called foo.dat which contains a bitmap called THE_IMAGE, you could display it with the code fragment:

>        #include "foo.h"

>        DATAFILE *data = load_datafile("foo.dat");
>        draw_sprite(screen, data[THE_IMAGE].dat, x, y);

If you are programming in C++ you will get an error because the dat field is a void pointer and draw_sprite() expects a BITMAP pointer. You can get around this with a cast, eg:

>        draw_sprite(screen, (BITMAP *)data[THE_IMAGE].dat, x, y);

When you load a single datafile object, you will obtain a pointer to a single DATAFILE structure. This means that you don't access it any more like an array, and it doesn't have any DAT_END object. Example:

>        music_object = load_datafile_object("datafile.dat", "MUSIC");
>        play_midi(music_object->dat);

Back to contents