Wake up! 16b
(hellmood.111mb.de)- Wake up! 16b ist ein 16-Byte-x86-Real-Mode-DOS-Intro, das auf der Outline Demoparty vorgestellt wurde und gleichzeitig ein Sierpinski-Fraktal sowie Ton über den Textpuffer erzeugt
- Mit
int 10hund der Einstellungds=0xb800wird das Startbild des 40x25-Textmodus als Rechenraum genutzt, wobei Leerzeichen- und Farbattribute die Ausgabe beeinflussen xor [si], alarbeitet wie eine Addition ohne Carry, erzeugt so die Sierpinski-Struktur von Bit 1 und sendet dasselbe Byte perout 61h, alan den PC-Lautsprecher- Die eigentliche Schleife bewegt sich pro Wiederholung um -56 Byte und wird nach 8.192 Schritten zurückgesetzt; der Ton sinkt um eine Oktave, und auf dem Bildschirm erscheint ein diagonal geschertes Muster in 10 Zeichenspalten
- Laufzeitumgebungen wie der
0xB000-Patch für MDA/Hercules sowie Unterschiede bei BIOS- und RAM-Zustand verändern das Ergebnis, wodurch natürliche Hardware-Artefakte Teil des Sizecoding werden
Kernstruktur des 16-Byte-x86-Intros
- Wake up! 16b ist ein 16-Byte-x86-Real-Mode-DOS-Assembler-Intro, das im Mai 2026 auf der Outline Demoparty im niederländischen Ommen vorgestellt wurde
- Es verwendet den VGA/CGA-Textpuffer als Rechenraum, um ein unendliches Sierpinski-Fraktal auf dem Bildschirm zu erzeugen, und sendet dieselben Daten an den PC-Lautsprecher-Port, um Ton zu erzeugen
- Der gesamte Code besteht aus 16 Byte
int 10h ; 2바이트 mov bh, 0xb8 ; 2바이트 mov ds, bx ; 2바이트 L: lodsb ; 1바이트 sub si, byte 57 ; 3바이트 xor [si], al ; 2바이트 out 61h, al ; 2바이트 jmp short L ; 2바이트 - Im Entwicklungsprozess wurden zelluläre Automaten untersucht, die Grafik und Sound gemeinsam nutzen, außerdem polymorphe Assembler-Instruktionen, bei denen
add [bx+si],alzu0x0000wird, sowie Sizecoding-Techniken, die Bytes und Opcodes durch Sprünge mitten in Instruktionen wiederverwenden - Die frühere Arbeit "M8trix" war ein 8-Byte- bzw. 7-Byte-Intro aus dem Jahr 2014, das pseudorandomisierte Zeichen über den Bildschirm ausbreitete; bei Wake up! 16b kommt zuerst der Ton, danach greift der visuelle Effekt ein
Der initialisierte Textbildschirm
int 10hsetzt Videomodus 0 und erzeugt damit ein 40x25-Raster im Textmodusmov bh, 0xb8undmov ds, bxsetzen das Datensegmentdsauf die VGA/CGA-Textpufferadresse0xb800- Wenn das BIOS den Bildschirm löscht, füllt es den Speicher nicht mit Nullen, sondern die 2.000 Zeichenslots mit dem Zeichenbyte
0x20(Leerzeichen) und dem Farbattribut0x07(hellgrau auf schwarzem Hintergrund) - Der Bildschirm wirkt leer, aber im Speicher bleibt ein gleichmäßiges Muster erhalten, und dieser Anfangszustand beeinflusst Sound und visuelle Ausgabe
- Auch Daten vor und hinter dem sichtbaren Videospeicher sowie die Art der Initialisierung nach „clear screen“ fließen in das Ergebnis ein und erzeugen einen raueren, eigenständigeren Klang als erwartet
Kumulierte Summen und Binomialstruktur
- Betrachtet man nur die mathematische Struktur, kann man annehmen, dass der Zustand statt bei
0x20bei 0 beginnt, dass stattxoreinaddverwendet wird, dass in Schritten von 16 Byte vorgerückt wird und dassalbei 2 startet - Ein DOS-Segment umfasst exakt 65.536 Byte, und bei Schritten von 16 Byte benötigt man 4.096 Schritte, um das gesamte Segment zu durchlaufen
- 4.096 ist ein Vielfaches von 256, also der Größe eines 8-Bit-Registers; dadurch richten sich Carryovers beim Wraparound des Segments aus, und zu Beginn jedes Sweeps kehrt
alzu 2 zurück - Addiert man die Werte zwischen den Zellen fortlaufend, entsteht eine Partialsumme (prefix sum), und die Werte entfalten sich wie eine mit Faktor 2 skalierte Folge von Binomialkoeffizienten
- Betrachtet man mehrere Durchläufe über die ersten 16 Zellen, akkumulieren sich die Werte zeilenweise; da es sich um 8-Bit-Werte handelt, wird alles oberhalb von 256 wieder umgebrochen und erscheint erneut als kleiner Wert
XOR und die Sierpinski-Struktur
- Aufgrund kombinatorischer Eigenschaften modulo 2 erscheint das Sierpinski-Dreieck, und dieses Bit wird direkt an den PC-Lautsprecher ausgegeben
- Auf Bitebene ist eine Addition ohne Carry ein XOR, deshalb verwendet der Code
xor [si], alstattadd - Der Startwert 2 entspricht binär
00000010, sodass nur Bit 1 zwischen0x00und0x02umgeschaltet wird - Dieses Muster entspricht dem elementaren zellulären Automaten Rule 60
- Nach dem Satz von Lucas stimmt dieses Muster mit Bit 1 der Additions-Tabelle überein; in der Tabelle werden Positionen mit aktivem Bit 1 als
2dargestellt
Wie Daten zu Klang werden
out 61h, alsendet das berechnete Byte an den mit dem PC-Lautsprecher verbundenen Port61h- Bit 1 von Port
61hbestimmt, ob die Lautsprechermembran nach außen gedrückt oder nach innen gezogen wird - Der Code berechnet das Fraktal per XOR, schreibt das Ergebnis in den Speicher und sendet dasselbe Byte unmittelbar danach an den Lautsprecher-Port
- Die Einsen und Nullen des Fraktals erzeugen eine Rechteckwelle (square wave) mit natürlich variierender Pulsbreite und Frequenz; zeilenweise abgespielt entsteht daraus ein selbstähnlicher, nahezu tempoinvarianter Bytebeat
- In den ausgegebenen Klang mischt sich nicht nur der Textpuffer, sondern auch der Rest des 64-KB-Segments ein; durch den dort enthaltenen shadowed Video-ROM-BIOS-Code entsteht ein rauerer, funkigerer Sound als beim erwarteten, auf Sierpinski-Zeilen basierenden overlayed rectangle wave bytebeat
56-Byte-Schritt: Oktave und diagonale Scherung
- Der eigentliche Code bewegt sich nicht in 16-Byte-Schritten, sondern durch die Kombination aus
lodsbundsub si, byte 57pro Wiederholung um -56 Byte zurück - Diese Schrittweite füllt den Bildschirm nur spärlich, hält aber zugleich den Soundpuffer davon ab, zu groß zu werden, und wird genutzt, um einen visuellen Effekt ähnlich wie bei M8trix zu reproduzieren
-
Audio
- 56 teilt 65.536 nicht ohne Rest
- Der Code besucht nur Offsets, die Vielfache von 8 sind, und setzt sich erst nach 8.192 Schritten sowie 7 Wraparounds zurück
- Durch die verdoppelte Zykluslänge sinkt die Grundfrequenz auf die Hälfte, der Ton fällt also um eine Oktave
-
Visuals
- Auf einem Bildschirm mit 80 Byte Breite entspricht ein Sprung von -56 Byte einem Vorwärtssprung um 24 Byte, also einer Verschiebung um 12 Spalten
- Es werden nur 10 verschiedene Spalten besucht
- Das Fraktal erscheint daher nicht als geschlossenes Bild, sondern diagonal geschert in 10 Zeichenspalten, die sich nach oben über den Bildschirm bewegen
- Das eigentliche Dreieck ist 8.192 „Pixel“ breit, eine Bildschirmzeile umfasst aber nur 80 Byte, sodass die Bewegung zwar wahrnehmbar ist, die Gesamtstruktur jedoch kaum direkt sichtbar wird
- Würde man ohne ausgelassene Pixel auf einmal zeichnen oder einen deutlich größeren Bildschirm verwenden, ließe sich das Dreieck erkennen
Ausführung auf echter Hardware
- Der Scener miragept führte es auf echter Hardware aus und patchte die Adresse von
0xB800auf das von MDA verwendete0xB000, um grünen Text passend für MDA/Hercules zu erhalten - Die verwendete Maschine war kein exakter IBM-Rechner, sondern ein 286er mit EGA-Karte, die MDA/Hercules emulieren konnte, zusammen mit einem echten MDA-Monitor
- Im aufgenommenen Audio mischt sich dauerhaftes Rauschen der Maschine ein, und der IBM-5151-Monitor besitzt langes Phosphor-Nachleuchten, was für extrem schnelle Darstellung nachteilig ist
- Durch die Änderung des Adressbytes klang der Ton etwas anders, funktionierte aber wie beabsichtigt; im späteren Teil ist die Sierpinski-Struktur sogar besser sichtbar als in der Originalversion
- Je nach Emulator und BIOS-Version unterscheiden sich die im RAM verbleibenden Artefakte, und da der Code XOR auf diesen Speicherzustand anwendet, reagiert die Ausgabe empfindlich auf die Laufzeitumgebung
- Man könnte den Speicher vorher löschen, um eine gleichmäßigere Ausgabe zu erhalten, doch dafür wären zusätzliche Bytes nötig; gerade das Akzeptieren des natürlichen Hardwarezustands bleibt ein Reiz des Sizecoding
Weiterführendes Material
- Nanogems - Kuratierte Liste herausragender Tiny Intros aus der Demoszene
- HellMood's productions on Pouet
- Capture on a 286/MDA/Hercules - Aufnahme von miragept auf echter Hardware
- Sizecoding Wiki
- "Rainbow Surf" - Plex' 16-Byte-x86-Intro
- "M8trix" - HellMoods 8-Byte-Intro
1 Kommentare
Hacker-News-Kommentare
https://youtu.be/b-Fa6HtvGtQ?si=LpQszgA9_K-m3V3-
Beide sind witzig und experimentierfreudig. Parker ist stärker in der klassischen Mathematik verankert, während Mould fachübergreifend unterwegs ist und den Drang nach Experimenten/DIY perfekt bedient
Wenn dir dieses Video gefällt, kann ich nur dringend empfehlen, auch die beiden Kanäle anzuschauen
https://www.youtube.com/@standupmaths
https://www.youtube.com/@SteveMould
Diese Demo hatte nicht einmal Ton
Das hier ist wirklich eine gewaltige Arbeit und ein Meisterwerk, das man als Abschlusswerk nehmen könnte. Realistischer ist aber wohl, dass es auf einer anderen Architektur wieder weitergeht
Bravo
https://www.youtube.com/watch?v=QKLhH_ANwIc
Unsere Size-Coding-Community dachte, wir hätten die Tricks mit zellulären Automaten schon vor Jahren alle entdeckt, aber dann kam Plex und hat gezeigt, dass das nicht stimmt ♥
Ich weiß nicht, ob es einen Artikel über den Vorgänger namens m8trix gab, aber ich habe ihn mir damals, als er herauskam, 2014 einmal genauer angesehen: https://scot.tg/2014/05/31/amazing-code-density/
Das alles ist so schön, echte Kunst. Schade, dass man in der Branche bei all dem AI-Zeug normalerweise kaum Gelegenheit bekommt, so etwas zu bauen