wake up! 16b
wake up! 16b
Released at the Outline Demoparty in May 2026, Ommen, NL
An exploration of algorithmic density in 16 bytes of x86 assembly.
Watch Video
Demozoo Entry
Hey everyone. I learned programming as a kid on an old IBM PC with a monochrome green monitor over 30 years ago and always wanted to create a program for this system. I created well over 100 tiny intros in the last 15 years. Recently I was not too active but the fantastic "Rainbow Surf" from Plex in just 16 bytes motivated me to dig up some old dusty sketches again and get to work.
The creation of this program happened with the usual tinkering around. I was messing with cellular automaton for graphics and sounds and discovering sizecoding tricks. Actually: a) polymorphic asm instructions, like add [bx+si],al which is 0x0000 b) jumping into the middle of instructions to save bytes and reuse opcodes. In hundreds of tiny experiments, this one stuck out, just by the sound of it.
When I unfolded what's left and removed "the rest", I had a hard time to grasp what's really going on. I was scratching my head looking at the simple formula that remained after golfing many bytes away. I myself didn't expect that the explanation would go this deep for just these few bytes xD.
My original "M8trix" from 2014 already did smear pseudorandom letters across the screen (in 8 bytes, then in 7) and I always wondered how I could make it "sound good". But chronologically in the development of "wakeup", the sound was first. Since you "see what you hear" it doesn't really matter, but "16 bytes that turn Sierpinski sound into Matrix rain" would be a good subtitle =)
TLDR: Each time step, another Sierpinski triangle line is a) played on the speaker b) drawn to the screen with a stepsize of 56. You can sense the motion, but not really see it, since it's 8192 "pixels wide" but one line of chars is just 80 bytes. On a much much much bigger screen, you could see the triangle. Or, if you don't "skip pixels" and draw it all at once, you would see it as well.
So, here are the 16 bytes of x86 real-mode DOS assembly. When you run it, it uses the video memory as a calculation space to draw an infinite Sierpinski fractal, and at the same time bangs the speaker with that geometry.
int 10h ; 2 bytes<br>mov bh, 0xb8 ; 2 bytes<br>mov ds, bx ; 2 bytes<br>L:<br>lodsb ; 1 byte<br>sub si, byte 57 ; 3 bytes<br>xor [si], al ; 2 bytes<br>out 61h, al ; 2 bytes<br>jmp short L ; 2 bytes
1. The Canvas: A Primed Void
The code starts with a standard BIOS interrupt: int 10h. This sets up video mode 0, giving a 40x25 text mode grid. Then the data segment (ds) is pointed to 0xb800, the memory address of the VGA/CGA text buffer.
When the BIOS clears the screen, it doesn't fill memory with absolute zeroes. Every character space is two bytes: the ASCII character and the color attribute. All 2,000 slots are set to 0x20 (space) and 0x07 (light gray on black). So the screen looks empty, but the memory is already filled with a uniform pattern.
I created a lot of "noise" or "CA" sound intros but this one stands out. It was and is still super unexpected! The specific spice here is how memory is initialized on "clear screen" and what's "before" and "after" the actual visible memory. The "pure" sound is also lovely (I can carefully set everything with a few more bytes to make it sound the same on all systems) but this spicy difference I still have to fully understand makes it sound even better imho =)
2. The Engine: Additive Prefix Sums
The intertwine, the synesthesia goes far beyond what I found so far in other tiny intros. I would even go so far as to say it's revealing more mathematical secrets and relations than using iterated function systems for the "chaos game" without an RNG. Anyway, this time I want you to fundamentally understand the mathematics of what you hear. Not just "you do some operation here and then it sounds interesting".
To strip it down to pure math: assume a zeroed state instead of 0x20, use add instead of xor, and step forward 16 bytes at a time. Assume the accumulator al starts at 2 .
A DOS segment is exactly 65,536 bytes. Moving 16 bytes per step means exactly 4,096 steps to traverse the segment (\( 65536 / 16 = 4096 \)). Then si wraps cleanly back to 0x0000.
Adding up values between cells creates partial sums. Because 4,096 is a multiple of 256 (the 8-bit register size), the carryover aligns perfectly when the segment wraps, cleanly resetting al to 2 at the start of each sweep.
The value follows a binomial sequence, scaled by 2:
$$A^{(p)}[k] \equiv 2 \binom{k+p}{p-1} \pmod{256}$$
Here is how the first 16 steps accumulate row by row:
Pass \ Cell
3. Crystallization: XOR and the Sierpinski Shift
Now, back to combinatorics. By special laws, when doing modulo two, the Sierpinski triangle emerges. This specific bit is what gets banged into the speaker, while the other bits are ignored.
To separate the bitplanes, the fact that carry-free addition of bits is XOR is why it is...