Back to the front page

bin2lzo2c

February 11th 2001

With libdream, there was a little utility called bin2c that takes a binary file (like your graphics) and makes it into a big lump of static data ready to add as a header to your program. When you do this, your program gets quite a bit bigger (by the size of the data).

If you add uninitialised char[]'s to it, they are stored as BSS (that's what the Atari always used to call it anyway) - which means the compiled program just has a single instruction to make the space when it runs, not a big lump of zeros in the binary.

Obviously, the bigger your program, the longer it takes to download it over the serial cable, so it's in your interest to get it to be smaller, even if you do think you have loads of memory. This little bodge-up uses the minilzo version of the LZO compression library bolted onto the front of bin2c to give you compressed initialised data. You can unpack it into memory with a single function call - unpacking is fast. You need to add a single header and a single source file to your program to support LZO.

To use it, compress your binary file:

bin2lzo2c rawdata.bin sprites_packed sprites.h
You'll get a header file called sprites.h with a single array of unsigned chars in it, called sprites_packes.

Add the necessary stuff to your code:

#include "minilzo.h"
#include "sprites.h"

/* where SPRITESIZE is the size of the original data */
unsigned char sprites[SPRITESIZE]; 
and then in your setup code:
	lzo_uint newlength;

	// unpack our sprite data, ready to use
        if (lzo_init() != LZO_E_OK)
        {
                        printf("lzo_init() failed !!!\n");
                        return 3;
        }
        newlength = SPRITEDATA_SIZE;
        rv=lzo1x_decompress_safe(sprites_packed, sizeof(sprites_packed), sprites, &newlength, NULL);
        if (rv == LZO_E_OK && newlength == SPRITEDATA_SIZE)
                        printf("decompressed %lu bytes back into %lu bytes\n",
                                        (long) sizeof(sprites_packed), (long) newlength);
        else
        {
                        /* this should NEVER happen */
                        printf("internal error - decompression failed: %d\n", rv);
                        printf("decompressed size = %lu (from %lu)\n",newlength, sizeof(sprites_packed));
                        return 1;
        }
If your feeling lucky/confident, then you can get that down to one line of setup and one per packed chunk of data.
	lzo_uint newlength;

	lzo_init();
	lzo1x_decompress_safe(sprites_packed, sizeof(sprites_packed), sprites, &newlength, NULL);
And that compressed the simple tiles I'm using in my boulderdash from 35K down to 3K, while adding about 7k to the final code. I think thats pretty good, and it'll obviously improve as I add more data.

Main caveats with bin2lzo2c (not the LZO library) are that it has fairly limited error checking, and that it loads the whole file into memory to pack it, so you'll need a bit of RAM for large files. In the case of Dreamcast apps, it's a fairly safe assumption that your PC has more memory than your DC, so it oughtn't be an issue :-)