A short tutorial by Timo Wiren (glaze/wAMMA)
| Revision history | ||
| Revision 1.0.4 | 2008-02-25 | Used 7z instead of gzip, -O1 instead of -Os and a few other things. |
| Revision 1.0.3 | 2006-09-24 | Now using /tmp directory, little additions here and there. Marq: My last name is not Wigren ;-) |
| Revision 1.0.2 | 2006-04-28 | Cleanup. |
| Revision 1.0.1 | 2005-08-14 | Added a new URL and basic tips. Cleanup. |
1. About the author and this howto
2. Basic size optimization
3. Compressing the object code
4. Example code
5. Links to external websites
I'm a computer science student at the University of Turku, Finland. I have been programming since 1998 and using GNU/Linux since 2001. I mostly develop graphics code, 2D and 3D, and use C and C++ and Java. I've been interested in demoscene since 1999, but I have released only a few crappy half-done productions.
This howto does not cover all areas of size optimization. It mostly covers the usage of standard tools to produce smaller code. GCC, the C language and SDL is used in this howto.
These are pretty basic things, but it doesn't hurt to mention them here:
-s option to strip debug information.-s -R .comment -R .gnu.version produce
nice results.-O1 instead of -Os to
optimize for size.static saves space.-ffast-math.-fomit-frame-pointerWe can compress the binary and add decompression script in front of
it. To compress, use gzip --best -f program or (better)
7z a -tGZip -mx=9 program.gz program
Save the following decompression script to a file unpack.header:
a=/tmp/I;tail -n+2 $0|zcat>$a;chmod +x $a;$a;rm $a; exit
Now you can put the decompression script to the beginning of file and
your program after it:
cat unpack.header program.gz > program
Remember to make the resulting file executable: chmod +x program.
Of course, there are more things you can do. LibC inserts standard and
bloaty code by default, so rename main() to _start(), and put the
following inline assembly code to the end of main function:
asm ( \
"movl $1,%eax\n" \
"xor %ebx,%ebx\n" \
"int $128\n" \
);
This ends the program without LibC code. Now you must compile it like this:
gcc -Os -fomit-frame-pointer -c program.c
ld -dynamic-linker /lib/ld-linux.so.2 program.o /usr/lib/libSDL.so -o program
Now you should be able to do 4k intros and the rest is up to smart algorithms and reuse of code and data. Of course there are many other small tricks that were not covered in this howto, but i'll add them when i remember those or find new ones.
XOR texture scroller (s.c):
/* XOR texture scroller begins */
#include <SDL/SDL.h>
void _start() {
int* v, x, y, w = 320, h = 240, i = 0;
SDL_Surface* b;
SDL_Event e;
b = SDL_SetVideoMode(w, h, 32, SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_HWACCEL);
v = b->pixels;
do {
SDL_PollEvent(&e);
for (y = 0; y < h; ++y)
for (x = 0; x < w; ++x)
v[y * w + x] = (x+i) ^ y;
SDL_Flip(b);
++i;
} while (e.type != SDL_KEYDOWN);
SDL_Quit();
asm ( \
"movl $1,%eax\n" \
"xor %ebx,%ebx\n" \
"int $128\n" \
);
}
/* XOR texture scroller ends */
I was able to make the scroller binary size 634 octets. I also have programmed a simple ray tracer under 2k.
gcc -O1 -ffast-math -fomit-frame-pointer -c s.c
ld -dynamic-linker /lib/ld-linux.so.2 s.o /usr/lib/libSDL.so -o s
strip -s -R .comment -R .gnu.version s
sstrip s
7z a -tGZip -mx=9 s.gz s
cat unpack.header s.gz > s
chmod a+x s
rm s.gz s.o
wc -c s