Graphics by Lord Azathoth

Packing a Lot of Files in One
When programming a small game with few graphics and few sound effects, we have a lot of different files (.PCX, .WAV, ..) to use. How about use only one file?
How about packing
The target of the 'packer' is very simple: insert all the different sorts of files (images, sounds, ..) in only one file. So we can use a file with a lot of records with variable size to contain all the data. I think to have a header of the file like this:

    struct PACKHEADER {
       char  type[2];           // Signature of the packer. Must be 'PK'
       BYTE  version;           // Version of the pack
       DWORD offset;            // Offset of the data from the beginning of the file
       DWORD counter;           // Number of record in the file
       char  autor[10];         // Autor of the pack
       char  program[15];       // Title of the program that use the pack
       char  fill[FILL_LENGTH]; // Fill to 64 bytes
    };

The offset and the fill fields are used to reserve space for future implementations of the packer.

For the data we can use a record like this (followed by the data itself):

    struct DATAHEADER {
       char  name[15]; 	// Name of the data
       BYTE  type; 		// Type of data
       WORD  counter; 	// Number of records
       DWORD size; 		// Size of the data
    };

With name we can identify the data informations in the file. This field can't be duplicated! The type field identify the type of data that follow the record ( image, sound, game level, ..). The counter field contain the number of records registered in the data. For have the size of one record, divide size by counter.
Insert and delete records
For insert data in the file we should read all the records and check if another record with the same name is present for prevent duplications. We need the name, a pointer to the data and the size of the data information for insert a record in the packer. There are a good implementation of the `insert` algorithm:

    // Insert general data information
    BOOL pack_insert_data(char *filename, char *name, int size, void *data)
    {
       BOOL ret;
       FILE *stream;
       int position;
       struct PACKHEADER packheader;
       struct DATAHEADER dataheader;

       // Open the file and check the signature
       if((stream=fopen(filename, "rb+"))==NULL) return(PACK_OPEN);
       if(fread(&packheader, sizeof(struct PACKHEADER), 1, stream)!=1) {
          fclose(stream);
          return(PACK_READ);
       }
       if(packheader.type[0]!='P'||packheader.type[1]!='K') {
          fclose(stream);
          return(PACK_INVALID);
       }

       // Look for records with the same name
       if(strlen(name)>14) name[14]='\x0';
       for(;;) {
          position=filelength(fileno(stream));
          if(fread(&dataheader, sizeof(struct DATAHEADER), 1, stream)!=1) break;
          if(!strcmp(dataheader.name, name)) {
             fclose(stream);
             return(PACK_DUP);
          }

          // Ignore the data
          fseek(stream, dataheader.size, SEEK_CUR);
       }

       fflush(stream);
       fseek(stream, filelength(fileno(stream)), SEEK_SET);
       // Fill the DATAHEADER structure and write it to the file
       strncpy(dataheader.name, name, 14); dataheader.name[14]='\x0';
       dataheader.type=TYPE_IMAGES;
       dataheader.counter=0;
       dataheader.size=size;
       if(fwrite(&dataheader, sizeof(struct DATAHEADER), 1, stream)!=1) {
          fclose(stream);
          return(PACK_WRITE);
       }

       // Write the data
       if(fwrite(data, size, 1, stream)!=1) {
          fclose(stream);
          return(PACK_WRITE);
       }

       // Update the packheader
       packheader.counter++;
       fseek(stream, 0, SEEK_SET);
       if(fwrite(&packheader, sizeof(struct PACKHEADER), 1, stream)!=1) {
          fclose(stream);
          return(PACK_WRITE);
       }

       fclose(stream);
       return(PACK_OK);
    }

For deleting a record we should use a swap file where we copy all the records without the one that we want to delete. Look the demo program for the code implementation.

[main] [prec] [next] [email]
Site Made and Maintained by The Dark Angel <DarkAngel@tin.it>
My ICQ Number is 2063026
You Visited This Page
times
This page hosted by Get your own Free Home Page