Skip to content
Techniques & Technology

Size Coding

The art of compression

Size coding emerged from demo scene competitions with strict byte limits, pushing programmers to achieve impossible effects in 64KB, 4KB, or even 256 bytes.

commodore-64commodore-amigaibm-pcsinclair-zx-spectrumdemooptimisationprogramming

How much can you fit in 64 kilobytes? What about 4 kilobytes? 256 bytes? The demo scene answered these questions with productions that seemed to defy physics. Size coding — creating complex audiovisual productions under strict byte limits — became an art form. The techniques developed fed into game compression, procedural generation, and efficient programming practices.

Fast facts

  • Origin: Demo scene size competitions (late 1980s).
  • Categories: 64K, 4K, 1K, 256 bytes, smaller.
  • Techniques: Procedural generation, compression, mathematical synthesis.
  • Influence: Game engines, web development, embedded systems, JavaScript code-golf.

Size categories

Category Limit Challenge
Demo Unlimited Full artistic expression
64K intro 65,536 bytes Procedural textures, music, scenes
4K intro 4,096 bytes Extreme compression, single-pass synth
1K intro 1,024 bytes Minimalist effects, raymarchers
256 byte 256 bytes Pure code golf, single effect
32 / 64 byte 32 / 64 bytes Single instruction-level idea

Legendary productions

Production Size Achievement
.kkrieger 96 KB Complete first-person shooter (Farbrausch, 2004)
Elevated 4 KB Mountain landscape flythrough (Rgba/TBC, Breakpoint 2009)
fr-08: .the .product 64 KB Full 3D engine with procedural textures and music (Farbrausch, 2000)
Memories 4 KB Atari 8-bit raymarched scene
A Mind Is Born 256 bytes Full C64 production with music and visuals (Linus Åkesson, 2017)

Techniques

Procedural generation

Replace stored content with code that generates it. A single trig formula computes a 256×256 cloud texture; a noise function fills a height-field; an L-system grows a tree. The 4 KB demos Elevated and Cdak generate entire mountain landscapes from one ray-march loop and a couple of sine-based noise functions.

Mathematical textures

// 4-byte expression generating a checker pattern
((x ^ y) & 8) ? 1 : 0

Plasma, marble, wood, fire, water — all common demo textures fall out of two or three sines plus an absolute value. The “shader” is shorter than the texture file would be.

Executable compression

The compiled binary is fed to a compressor that emits an unpack stub plus compressed data. Standard tools:

Compressor Platform Typical use
Crinkler Windows x86 4 KB / 64 KB intros — context-mixing arithmetic coder
Aplib Cross-platform LZSS variant, fast decompression
Pucrunch C64 / 6502 Pasi Ojala’s 1998 hybrid LZ77 and RLE; compresses on a PC, decompresses on the C64 with no extra memory
Exomizer C64 / 6502 Among the tightest packers in Codebase64’s 2016 benchmark (45% of input, level with Subsizer), at the cost of slow depacking
kkrunchy Windows x86 Used by Farbrausch (.kkrieger and friends)
upx Cross-platform Generic; used for normal binaries, not size-tight intros

A 4 KB intro typically runs the binary through multiple passes: dead-code elimination, custom linker scripts, then crinkler. Five hundred bytes of output for ten kilobytes of source is normal.

Synthesised audio

Stored samples are too big. Instead: single-pass softsynth. A short oscillator routine generates each note, instrument envelopes are computed live, the song is a list of (note, length, instrument) tuples. Tools like 4klang (Windows 4 KB) and Clinkster (small-intro audio) ship with whole synths in under 1 KB. On retro platforms the SID and AY chips already are softsynths in hardware — the song data dominates rather than the audio code.

Imports / API minimisation

On Windows, calling kernel32.dll requires loading the function pointer table. A 4 KB intro skips the standard linker and walks the PE export tables itself, costing ~30 bytes of stub vs ~200 bytes of normal import handling. On retro platforms the analogue is direct hardware access instead of going through KERNAL/BIOS routines.

Code golf

Single-effect 256-byte productions are mostly hand-crafted assembly where every byte is justified. Common tricks:

  • Reuse a single arithmetic register for both pixel coordinate and frame counter
  • Self-modifying code so two pieces of logic share one instruction
  • Use RST 0 / JMP $0000 style for hardware initialisation by re-entering the boot loader
  • Pack constants into instruction operands that double as data

On the Commodore 64

The C64 answer to the question is documented in the authors’ own words. In summer 2001 an 8-bit minigame contest drew “thirty entries for the C64, Spectrum, Amstrad, and Atari 8-bit” in 512-byte and 2K classes, and C=Hacking issue 21 (February 2002) printed six postmortems under the title “The Art of the Minigame”. Its introduction sets out the discipline: “Whereas many of us are used to optimizing programs for cycle-efficiency, optimizing programs for byte-efficiency turns out to be very different”, and the framework is to “put stuff in zero-page, take advantage of default zero-page values, take advantage of the kernal, always know the register values, and reuse as much code as possible”. Zero-page instructions are two bytes instead of three; a zero-page location that the machine already leaves at zero saves the four bytes of LDA #0 / STA; and Mark Seelye’s “injections” put an STX zp into an earlier routine where X is known to be zero, instead of clearing the location where it is used.

Author Entry Size What the postmortem records
David Holz (White Flame) Codebreaker 415 bytes A Mastermind game; random numbers come from reading $D012 and looping that many times before reading again; “the smallest entry”
Stephen L. Judd Tetrattack! 512 bytes “A 3D engine in 512 bytes”: a line routine, a rotation/projection routine and object bookkeeping. One line routine serves both axes by swapping INX/INY, and the load address is chosen so the end address is $10F0, two vertex coordinates the code needs anyway
Per Olofsson (MagerValp) MagerTris 2K A 512-byte Tetris that would not fit became a 2K entry: a 600-byte engine plus a title screen, tile set and disk high-score list, packed with pucrunch from “6500 bytes uncompressed”. The custom font is stored EOR’d against the ROM font so it compresses better
Mark Seelye (Burning Horizon) Tinyrinth 509 bytes A maze generator and game; “I ended up getting the code down to like 475 bytes, but the version I turned in was 509 bytes”

Olofsson’s note on when to pack is the useful rule of thumb: “at around 700 bytes or so compression starts to make sense – pucrunch breaks even around there somewhere”. Pucrunch itself is Pasi Ojala’s 1998 design, described in C=Hacking 17 as a “Hybrid LZ77 and RLE compressor” whose decompressor “uses no extra memory”; Ojala tried a Huffman back end and dropped it when “the gain was reduced to only about 3% after accounting the extra code and the Huffman tree”. Codebase64’s 2016 benchmark, run on the files of the demo Pearl for Pigs, shows the later generation — Exomizer, Subsizer, Doynamite, ByteBoozer, Bitfire — packing to 45–48% of input against pucrunch’s 54%, with depacking speed the trade: ByteBoozer 2.0 unpacks the first test file in 22 frames, Exomizer in 58 to 79.

Modern applications

Size-coding discipline appears in:

  • Web performance — minified bundles, tree-shaking, server push budgets
  • Embedded systems — fitting firmware in a few KB of flash
  • Game asset compression — Steam / store-page download budgets
  • Demakes and fan projects — fitting a modern game’s idea on retro hardware
  • JavaScript 1k / 13k contestsjs13kgames, Code Golf, 1k JS contest

See also

Not yet fact-checked. This entry was drafted by an AI and nobody has verified it. The dates, figures and technical details may be wrong. Use it to find your bearings, then confirm anything that matters against a primary source.