4 Punkte von GN⁺ 2026-01-13 | 1 Kommentare | Auf WhatsApp teilen
  • Ein Snake-Spiel, das als einzelne 13-KiB-Datei unter Windows, Linux und im Browser läuft und alle drei Plattformen mit einer einzigen Codebasis unterstützt
  • Es folgt den klassischen Snake-Regeln: Die Schlange wird gesteuert, frisst Futter und darf nicht gegen Wände stoßen; enthalten sind Punktestand, Level und Labyrinth-Strukturen
  • Die Implementierungen für die einzelnen Plattformen wurden in C (WinAPI/X11) bzw. JavaScript (HTML5 Canvas) erstellt und jeweils auf etwa 3–5 KiB komprimiert und zusammengeführt
  • Unter Windows kommen ein ungewöhnlicher PE-Header und der apphelp-Mechanismus zum Einsatz, unter Linux lzma-Komprimierung und ein Shell-Dropper, im Browser HTML/CSS-Tricks
  • Durch die Kombination der drei Implementierungen entstand eine einzelne ausführbare Datei mit 13.312 Byte, die die experimentellen Möglichkeiten einer Multiplattform-Executable-Struktur zeigt

Ein von Cosmopolitan libc inspirierter Multiplattform-Versuch

  • Cosmopolitan libc ist ein Toolkit, mit dem sich C-Quellcode zu einem einzelnen Binärprogramm kompilieren lässt, das auf mehreren Betriebssystemen ausgeführt werden kann
    • Unterstützt native Ausführung auf verschiedenen OS wie Windows, Linux und BSD
  • Wegen fehlender GUI-Unterstützung und der Begrenzung durch große Binärdateien entschied sich der Autor für die Herausforderung, selbst ein Videospiel mit weniger als 16 KiB zu bauen
    • Das Ziel war ein Spiel auf Basis einer einzigen Codequelle, das unter Windows, Linux und im Browser läuft

Spielaufbau und Regeln

  • Das Spiel ist ein standardmäßiges Snake-Spiel, gesteuert mit den Pfeiltasten oder WASD
    • ESC zum Beenden, R zum Zurücksetzen, P zum Pausieren, Leertaste zum Starten
  • Mit jedem gefressenen Futter steigt der Punktestand; normales Futter bringt 10 Punkte, gelbes Futter (15 % Wahrscheinlichkeit) 20 Punkte
    • Futter verschwindet nach einer bestimmten Zeit, die von der Geschwindigkeit der Schlange abhängt (proportional zu ihrer Länge)
  • Nach 10 gefressenen Futterstücken geht es ins nächste Level, wobei die Wandanordnung zufällig verändert wird
    • Das Labyrinth wird so erzeugt, dass immer ein Pfad zum Futter existiert
    • Auch die Startposition der Schlange ist zufällig, wird aber in eine Richtung mit mindestens 5 freien Feldern gesetzt
  • Die fertige Spieldatei hat eine Größe von 13.772 Byte

Implementierung auf den drei Plattformen

  • Die Windows-Version wurde als C-Code auf Basis der WinAPI geschrieben und enthält ein Kompressionsskript sowie einen Dekompressor-Stub
    • Die frei kontrollierbaren Bytes nach der MZ-Signatur im PE-Header werden genutzt, um ein Shell-Skript einzubetten
    • Dadurch ist die Datei zugleich eine Windows-Executable und ein gültiges Linux-Shell-Skript
    • Beim ersten Start kann der Fehler „The application was unable to start correctly (0xc0000005)“ auftreten, beim erneuten Start funktioniert sie jedoch normal
  • Die Linux-Version verwendet lzma-Komprimierung, und ein kleiner Shell-Dropper extrahiert und startet das komprimierte ELF64-Binärprogramm
    • Sie ist so aufgebaut, dass beim Ausführen bestimmte Teile am Anfang und Ende der Datei übersprungen werden
  • Die HTML-Version nutzt aus, dass Browser unnötige Daten am Anfang der Datei ignorieren und anschließend das HTML verarbeiten
    • Über CSS wird sichergestellt, dass unnötige Daten nicht auf dem Bildschirm erscheinen

Zusammenführung und Aufbau der Einzeldatei

  • Die Dateien für die drei Plattformen werden in einer bestimmten Reihenfolge aneinandergehängt (concatenate), sodass jede Umgebung nur den für sie passenden Teil ausführt
    • Windows erkennt den PE-Abschnitt, Linux den ELF-Abschnitt, der Browser den HTML-Abschnitt
  • Die endgültige Datei ist 13.312 Byte groß und bildet damit ein Polyglot-Binärprogramm, das in allen drei Umgebungen lauffähig ist
  • Im Inneren der Datei sind ein Windows-PE-Header, für Linux LZMA-komprimierter Code sowie HTML/CSS/JavaScript-Code nacheinander enthalten
    • Im Beispiel-Codeblock erscheinen der MZ-Header, der ks-Marker, das <html>-Tag und der <script>-Block in dieser Reihenfolge

Technische Bedeutung

  • Implementiert eine Ausführungsstruktur, die mit einer einzigen Datei Windows, Linux und Browser zugleich unterstützt
  • Nutzt die verschachtelte Verwendung der Formate PE, ELF und HTML, um plattformspezifische Ausführungspfade zu verzweigen
  • Eine experimentelle Leistung, die auf extrem kleinen 13 KiB Komprimierung, Format-Hacking und Multiplattform-Ausführung kombiniert

1 Kommentare

 
GN⁺ 2026-01-13
Hacker-News-Kommentare
  • Ich habe die Linux-Executable extrahiert und war überrascht, dass readelf und objdump sie nicht richtig lesen konnten.
    Bei näherer Untersuchung stellte sich heraus, dass der ungenutzte Bereich des PT_DYNAMIC-Headers zweckentfremdet wurde, um dort den Namen des dynamischen Linkers unterzubringen und so Platz zu sparen.

    1. Ich frage mich, ob das manuell gemacht wurde oder ob es Tools gibt, die so etwas erzeugen.
    2. Mich würde auch interessieren, ob es Tools gibt, die solche ungewöhnlichen Binärdateien analysieren können.
    • Mit ndisasm oder einem Hex-Editor kann man sie lesen.
      Ich halte das absichtliche Beschädigen solcher Formate aber für eine sinnlose Einsparung.
      Es könnte außerdem mit Sicherheitsfunktionen wie Antivirenprogrammen oder DEP kollidieren, daher würde ich solche Executables lieber nicht anfassen.
    • Ich weiß nicht, was mit „choke“ gemeint ist; in meiner Umgebung haben beide Tools normal funktioniert.
  • Ich bin erstaunt, wie klein die Dateigröße des ursprünglichen Zelda-Spiels war.
    Es ist beeindruckend, wie viel Emotion und Immersion mit so wenig Code und Daten erzeugt werden konnte.
    The Legend of Zelda (Wikipedia)

    • Das ist wirklich wie Magie. Das Spiel Eindeloos auf dem Commodore 64 hatte ebenfalls eine riesige Karte in nur 64 KB.
      40 Jahre später wurde die Karte extrahiert, und allein als PNG ist sie über 800 KB groß.
      Spielkarte ansehen
    • Zelda 1 war 128 KB groß und hatte keine Komprimierung. Der Nachfolger war ungefähr doppelt so groß.
    • Die Dungeons und Höhlen befanden sich tatsächlich alle innerhalb einer einzigen rechteckigen Karte.
      Die Designer haben sie innerhalb der Platzbeschränkungen wie ein Puzzle angeordnet.
      Referenz zur Zelda-Kartenstruktur
  • Meine Testergebnisse:

    • Browser: Es läuft, wenn man die Dateiendung in .html ändert.
    • Linux: Es gab einen Fehler, dass der Befehl lzma fehlt; nachdem ich das Paket xz installiert hatte, funktionierte es.
    • Windows: Beim Ausführen als .com oder .exe trat der Fehler 0xc0000005 auf, aber nachdem ich die DEP-Einstellung deaktiviert hatte, lief es.
    • Funktioniert auch unter Windows 11 problemlos.
    • Wenn man einfach chmod +x snake.com macht und es dann ausführt, versucht Mono es zu starten und scheitert.
      Mit bash snake.com funktioniert es dagegen. Getestet auf Debian 13.
  • Interessant ist, dass diese Datei im Grunde drei Executables in einer vereint.
    Deshalb könnte sie auf jeder Plattform auch ein völlig anderes Programm enthalten.

  • Das erinnert mich an das 96-KB-FPS-Spiel kkrieger.
    Das Grafikniveau war damals erstaunlich.
    kkrieger (Archiv)

    • Verwandte Diskussionen: 2017, 2023, 2024
    • Es läuft auch heute noch auf modernen PCs. Ich habe es gerade selbst heruntergeladen und ausprobiert.
    • Als ich kürzlich Metroid Prime 4 gespielt habe, musste ich daran denken, wie es wäre, ein modernes Spiel mit dieser Idee zu entwickeln.
  • Ich frage mich, ob es auf dem Mac außer im Browser eine Möglichkeit gibt, das auszuführen.
    Ich bekomme den Fehler cannot execute binary file.

  • Ich frage mich, ob man diesen Mechanismus weiterentwickeln könnte, um eine echte universelle Binärdatei (universal binary) zu erstellen.
    Man könnte zum Beispiel Code in Haxe schreiben, ihn nach C++ kompilieren und daraus Versionen für Win32 und Linux bauen,
    ihn zusätzlich nach JavaScript übersetzen, damit er auch als HTML läuft,
    und dann alle drei Ergebnisse in einer einzigen Datei zusammenführen.

  • Mir gefällt die Idee einer Single-Executable-App, die als eine Datei überall läuft.
    Ich erforsche selbst eine ähnliche Richtung beim Bau einer serverlosen Plattform.
    Dabei werden datengetriebene Apps in nur einer .html-Datei erstellt, während web-components aus der Ferne geladen werden.
    Die Möglichkeit, HTML direkt über das file://-Protokoll zu öffnen, ist mächtig, wird aber oft übersehen.

    • Der Autor des Originals hat es tatsächlich dreimal implementiert — als C mit WinAPI, als C mit X11 und als JS-Version mit HTML5 Canvas.
      Es geht also nicht einfach nur darum, eine Browserinstanz zu starten, sondern es wurden zwei vollständig native Apps gebaut.
    • Leider sind die Browserfunktionen in Umgebungen ohne HTTPS stark eingeschränkt.
    • Ich würde gern mehr über diese Art der Entwicklung von Single-HTML-Apps erfahren. Gibt es vielleicht veröffentlichte Beispiele?
  • Erstaunlich, dass Polyglot-Dateien erst so spät auftauchen.
    Technisch gesehen wäre das vermutlich schon vor 10 bis 20 Jahren möglich gewesen.

    • Ich frage mich, wann die erste Polyglot-Datei aufgetaucht ist.
      EICAR.COM fällt mir als frühes Beispiel ein, das zugleich Textdatei und Executable ist.
  • Das erinnert an ultrakleine Webgame-Wettbewerbe wie js13kGames.