Datafile routines

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.

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.

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

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.

void unload_datafile_object(DATAFILE *dat);
Frees an object previously loaded by 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.

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.

void fixup_datafile(DATAFILE *data);
If you are using compiled datafiles (produced by the dat2s utility) that contain truecolor images, you must call this function once after your set the video mode that you will be using, to convert the color values into the appropriate format. 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 between 15<->16 bit hicolor for both bitmaps and RLE sprites, and 24<->32 bit truecolor for RLE sprites).

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

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");

Back to Contents