Doing spectacular things with very little code has a long tradition in the demoscene. Born out of necessity when home computers were slow and memory space scarce, pushing against artificial boundaries became a popular “sport” when PC hardware power blew up. Time and again we’ve seen demosceners tighten the limits in search of a good challenge and do voodoo with 64 and even 4 kilobytes (see CAN’s coverage of Hartverdrahtet here). At the recent edition of Assembly, a demoscene main event in Helsinki (Finland) with a 20 year history, this race for minimal footprint has reached a new low: 1 kilobyte (1024 bytes) or less! While technically 1k (and smaller) intros are nothing new, Assembly’s first ever “1 kilobyte intro competition” marks a breakthrough for the category. The winning entry: Embers by TDA – a x86/GLSL code ticket to a red-hot ride into fractal hell.
We asked Firehawk and TS, Embers’ two programmers from Finland, to break things down for CAN (see the stats at the bottom of this post) and talk us through the bits.
Getting started: “In May 2012, when the new 1K category for Assembly 2012 was introduced, we immediately felt we wanted to participate in the competition. From earlier experience with our tools we knew we could do a “hello world” in about 350 bytes in Mac OS X Lion. From there we set out our budget: 350 bytes to cruncher and library import, 300 bytes to audio and audio code and the rest to visuals. It took us about 2 weeks worth of evenings to get there.”
Visuals: “We knew we had to use some sort of fractal: early tests with basic shapes and distortions however were beyond ugly. The problem with fractals is that they are overused in demoscene and finding something fresh is close to impossible. Ultimately we chose mandelbox since it can have a lot of different variations just by changing the scale. It also hasn’t been used that much in our scene and we were able to limit it to angles which look like something new.”
Audio: “We had already developed an analog-modeling softsynth for use in 4k intros, but it was clearly much too large for use in a 1k. By choosing a minimal subset of features that would still sound reasonably good, we were able to considerably reduce the footprint of the synthesizer. However, even this bare-bones version of the synth was too large and thus unsuitable for our needs. Thanks to Mac OS’s heritage as an audio production platform, the operating system comes with a standard selection of audio units that range from compressors and equalizers to actual synthesizers. The DLSSynth AU provides a MIDI-controllable Roland GS-compatible wavetable synth and while limited to the standard patch set, it sounded good enough. Most importantly, the low-level audio unit API required very few function calls to use.”
Compression: “Even though we thought we were prepared to make a 1k intro, there were a lot of surprises. Compression efficiency in 1 kilobyte is a key factor, so writing repetitive code and data that compresses better is the way to go. Even unconventional tricks like transposing the music to a different key to decrease the overall entropy of the uncompressed binary may be beneficial. Another key factor is avoiding any overhead that comes from interfacing with the OS. By arranging and rearranging libraries and prototyping with different ways to initialize the full screen rendering (CGL, AGL, GLUT) and audio playback (Audio Units, DLSSynth) we managed save about 100 bytes. Implementing our own content aware gzip compressor Laturi helped us save roughly another 5%.”
1k VS 4k: “In 4 kilobytes compressor and library import size is something that is almost negligible compared to the content. In 1k it is not. As for actual visual content in a 1k intro the most efficient way is to write everything to the shader. Using x86 assembly to interface with OpenGL will result large code and very little being drawn to the screen.”
Final version composition (in final, compressed binary):
– decompressor stub and gzip-header: 44 bytes
– library imports and mach-o binary headers: 182 bytes
– hashes for the functions imported: 108 bytes
– x86 machine code for setting up audio and video: 213 bytes
– audio data (MIDI): 131 bytes
– GLSL shader code: 342 bytes
Uncompressed size of Embers: 2145 bytes
– Custom linker with custom gzip-compressor
– import by hash for system libraries
– “pure” shader (GLSL) visual
– DLSSynth for audio
– Mandelbox scale 2. Iteration count glow + specular lighting
Embers runs on Intel Macs (Mac OS X 10.7 or higher, fast graphics card recommended) and is available for download here. Check out also the two excellent runner-up 1k intros traceless by TBC (2nd place) and braids by Luminesce (3rd place).