I wrote a program which took any binary file and encoded it as a named array of char's, short's or long's in source format. This, I then would compile and include into a library file (I have hundreds of sprites, so cutting down on linking time is a desirable thing) using my compiler's library manager.
Setting things up properly with a hand made makefile I am able to build smooth as glass, with the speed and reliability of resource binding methods. The makefile defines dependencies from graphics files to object files. The build command is assigned to a batch file which processes the graphics source into a C file, compiles the C file to an object file and then deletes the C file (to save space.) Of course, it is also required that the application be able to read these resources straight from memory.
I present the binary to C translator below. Clearly it is not difficult to adapt this program to other languages as well.
The SymbolName is the global symbol name that points to the start of the resource in question, which is accessible in your source code. The Size is 1, 2 or 4 standing for char, short and long, respectively. If the optional FormatString is used, it must contain a %%s and a %%u in succession. The %%s will be replaced by the symbol name and the %%u will be replaced by the resource size and is output at the end. The output goes to stdout.
// // Copyright 1996 Paul Hsieh. All rights reserved. // // This program is public domain, subject to the conditions that any use made // of it that results in a derivative work or product must credit the author, // Paul Hsieh and that this source never be distributed without these comments // appearing intact at the top of the program. // #include <stdio.h> char *sizetype[5]={ "NULL","char","short","??","long" }; char buffer[4]; char comma=' '; char *separator[6]={ "\n"," "," "," "," "," " }; char Fmt[1024]; main(int argc, char *argv[]) { int i,size=1; long count=0; FILE *fp; if( 3>argc ) { printf("Syntax: %s file name [size [format]]\n",argv[0]); exit(-1); } if( argc>=4 ) { sscanf(argv[3],"%d",&size); if( 1>size || size>4 || size==3 ) { printf("Invalid size\n"); exit(-1); } } printf("/* Inline declaration of %s from %s */\n\n",argv[2],argv[1]); printf("%s %s[]= {\n",sizetype[size],argv[2]); fp = fopen(argv[1],"rb"); while( 0!=fread(buffer,1,size,fp) ) { printf("%c%s0x",comma,separator[count%6]); for(i=size-1;i>=0;i--) { printf("%02x",buffer[i]); buffer[i]='\0'; } comma=','; count++; } printf("};\n\n"); if( argc>=5 ) { Fmt[0]='\0'; for(i=5;argc>=i;i++) { if( Fmt[0]!='\0' ) strcat(Fmt," "); strcat(Fmt,argv[i-1]); } printf(Fmt,argv[2],count); printf("\n"); } else { printf("/* %ld %ss = %ld bytes */\n",count, sizetype[size], count*((long)size)); } exit(0); } |
I have written a slightly more sophisticated program that supercedes the functionality of bin2c. Its called metaC. What it does is take a meta-C file which is a mostly C source file which includes tokens for inlining data directly, and translates them to proper C files with direct inline data declarations.
In more detail:
METAC: A program for inlining binary data into C written by Paul Hsieh Metac will take a C-like file, simply output the file's contents to standard out until it reads an inline file token. Such tokens appear with the syntax: @filename So, for example, if you wanted to include a string that you have authored as an ordinary text file into your C code you could simply write: char Msg1[] = "@readme.txt"; then filtering through metac, the @readme.txt contents are injected inline between the quotes as standard C syntax chars, replacing the occurrence of @readme.txt. The idea was inspired by Window's resources which were in turn inspired by people who would arbitrarily tack data on the ends of their executables. Clearly this idea is more general and easier on the programmer. But it has the disadvantage or necessarily including the inlined data in memory during execution. KNOWN BUGS: Intrudes on otherwise legal uses of the @ symbol. |
The program is available for download here:
I cannot distribute the source because I am using a library that I am not at liberty to distribute (and because its an embarassing hack.) Clearly this program is not much of a challenge to write, but is provided here as a convenience for the lazy programmer.