Un jeu qui fonctionne sous Windows, Linux et dans le navigateur à partir d’un unique fichier de 13 KiB
(iczelia.net)- Un jeu de Snake qui s’exécute sous Windows, Linux et dans le navigateur à partir d’un unique fichier de 13 KiB, avec prise en charge des trois plateformes depuis une seule source
- Il suit les règles classiques de Snake : contrôler le serpent pour manger la nourriture sans heurter les murs, avec score, niveaux et structure en labyrinthe
- Chaque plateforme est implémentée en C (WinAPI/X11) et en JavaScript (HTML5 Canvas), puis compressée et fusionnée pour tenir dans environ 3 à 5 KiB chacune
- Windows s’exécute via un en-tête PE atypique et le mécanisme apphelp, Linux via la compression
lzmaet un dropper shell, et le navigateur via des astuces HTML/CSS - En combinant les trois implémentations, l’auteur obtient un unique exécutable de 13 312 octets, montrant le potentiel expérimental d’une structure d’exécutable multiplateforme
Une approche multiplateforme inspirée par Cosmopolitan libc
- Cosmopolitan libc est une boîte à outils permettant de compiler du code source C en un unique binaire exécutable sur plusieurs systèmes d’exploitation
- Exécution native prise en charge sur divers OS comme Windows, Linux et BSD
- En raison de l’absence de support GUI et de la taille importante des binaires, l’auteur a choisi de relever le défi de créer lui-même un jeu vidéo de moins de 16 KiB
- L’objectif était de produire un jeu basé sur une source unique, exécutable sous Windows, Linux et dans le navigateur
Structure et règles du jeu
- Le jeu est un Snake standard, contrôlé avec les flèches directionnelles ou WASD
ESCpour quitter,Rpour réinitialiser,Ppour mettre en pause, barre d’espace pour démarrer
- Le score augmente à chaque nourriture mangée : 10 points pour la nourriture normale, 20 points pour la nourriture jaune (15 % de probabilité)
- La nourriture disparaît après un certain temps, déterminé par la vitesse du serpent (proportionnelle à sa longueur)
- Après 10 nourritures mangées, on passe au niveau suivant, avec une disposition des murs modifiée aléatoirement
- Le labyrinthe est généré de manière à toujours laisser un chemin jusqu’à la nourriture
- La position initiale du serpent est elle aussi aléatoire, mais placée dans une direction garantissant au moins 5 cases libres
- La taille du fichier du jeu terminé est de 13 772 octets
Implémentation sur les trois plateformes
- La version Windows est écrite en C sur WinAPI et inclut un script de compression et un stub décompresseur
- Elle exploite les octets librement contrôlables après la signature
MZde l’en-tête PE pour insérer un script shell - Le fichier est ainsi à la fois un exécutable Windows valide et un script shell Linux valide
- Au premier lancement, l’erreur « The application was unable to start correctly (0xc0000005) » peut apparaître, mais une relance permet un fonctionnement normal
- Elle exploite les octets librement contrôlables après la signature
- La version Linux utilise la compression
lzma, et un petit dropper shell extrait puis exécute le binaire ELF64 compressé- Elle est conçue pour s’exécuter en ignorant certaines parties situées au début et à la fin du fichier
- La version HTML exploite le fait que le navigateur ignore les données inutiles en tête de fichier et traite ensuite le HTML
- Le CSS est utilisé pour empêcher l’affichage à l’écran des données inutiles
Assemblage et structure du fichier unique
- Les fichiers des trois plateformes sont concaténés dans un ordre précis, afin que chaque environnement n’exécute que la partie qui lui correspond
- Windows reconnaît la section PE, Linux la section ELF, et le navigateur la section HTML
- La taille finale du fichier est de 13 312 octets, aboutissant à un binaire polyglotte exécutable dans les trois environnements
- Le fichier contient successivement un en-tête PE Windows, du code compressé LZMA pour Linux, puis du code HTML/CSS/JavaScript
- Les exemples de code montrent notamment la signature
MZ, le marqueurks, la balise<html>et un bloc<script>placés dans cet ordre
- Les exemples de code montrent notamment la signature
Portée technique
- Mise en œuvre d’une structure d’exécution unique prenant en charge Windows, Linux et le navigateur dans un seul fichier
- Bifurcation des chemins d’exécution selon la plateforme grâce à l’imbrication des formats PE, ELF et HTML
- Une réalisation expérimentale combinant compression, détournement de formats et exécution multiplateforme dans une taille extrêmement réduite de 13 KiB
1 commentaires
Commentaires sur Hacker News
J’ai extrait l’exécutable Linux et j’ai été surpris de voir que readelf et objdump n’arrivaient pas à le lire correctement
En creusant, j’ai découvert que le nom de l’éditeur de liens dynamique avait été forcé dans des champs inutilisés du header PT_DYNAMIC afin d’économiser de l’espace
Mais je considère que casser volontairement le format de cette manière est une économie sans intérêt
Ça peut aussi entrer en conflit avec des mécanismes de sécurité comme l’antivirus ou le DEP, donc je préfère ne pas toucher à ce genre d’exécutable
Je suis étonné de voir à quel point la taille du fichier du Zelda d’origine était petite
C’est fascinant de voir à quel point ils ont réussi à créer de l’émotion et de l’immersion avec si peu de code et de données
The Legend of Zelda (Wikipedia)
La carte a été extraite 40 ans plus tard, et rien qu’en PNG elle dépasse les 800 KB
Voir la carte du jeu
Les designers les ont assemblés comme un puzzle dans les contraintes d’espace
Référence sur la structure de la carte de Zelda
Résultats de mes tests
.htmllzman’existait pas, puis ça a marché après installation du paquetxz.comou.exe, j’obtenais l’erreur 0xc0000005, mais ça fonctionne après avoir désactivé le réglage DEPchmod +x snake.compuis qu’on l’exécute, Mono essaie de le lancer puis échoueEn revanche,
bash snake.comfonctionne bien. Testé sur Debian 13Ce qui est intéressant, c’est que ce fichier est en fait la fusion de trois exécutables en un seul
Il pourrait donc contenir des programmes complètement différents selon la plateforme
Ça me rappelle kkrieger, un FPS de 96 KB
Son niveau graphique était impressionnant pour l’époque
kkrieger (archive)
Je me demande s’il existe un moyen de l’exécuter sur Mac autrement que dans le navigateur
J’obtiens l’erreur
cannot execute binary fileJe me demande si on pourrait pousser ce mécanisme plus loin pour créer un vrai exécutable universel
Par exemple, écrire le code en Haxe, le compiler en C++ pour produire des versions Win32 et Linux,
le convertir en JavaScript pour qu’il puisse aussi s’exécuter en HTML,
puis fusionner les trois résultats dans un seul fichier
J’aime bien l’idée d’une application autonome qui s’exécute partout à partir d’un seul fichier
Je travaille moi aussi sur cette direction en développant une plateforme serverless
L’idée est de créer des applications pilotées par les données dans un unique fichier
.html, avec des web-components chargés à distanceLe fait de pouvoir ouvrir directement du HTML via le protocole
file://est très puissant, mais souvent sous-estiméCe n’est donc pas simplement une instance de navigateur lancée, mais bien deux applications natives complètes
C’est étonnant que les fichiers polyglottes soient apparus si tard
Techniquement, ça semble être quelque chose qu’on aurait pu faire il y a 10 ou 20 ans
EICAR.COM me vient à l’esprit comme un exemple ancien qui faisait à la fois texte et exécutable
Ça me fait penser à des concours de mini-jeux web ultra-compacts comme js13kGames