- Un juego de Snake en un único archivo de 13 KiB que puede ejecutarse en Windows, Linux y el navegador, con soporte para las tres plataformas desde una sola fuente
- Sigue las reglas clásicas de Snake, controlando la serpiente para comer comida y evitar chocar con las paredes, e incluye puntuación, niveles y estructura de laberinto
- Cada plataforma fue implementada con C (WinAPI/X11) y JavaScript (HTML5 Canvas), y cada versión fue comprimida y fusionada hasta quedar en unos 3 a 5 KiB
- En Windows se ejecuta usando un encabezado PE poco convencional y el mecanismo apphelp; en Linux, con compresión lzma y un shell dropper; y en el navegador, mediante trucos de HTML/CSS
- Como resultado de combinar las tres implementaciones, se completó un único archivo ejecutable de 13,312 bytes, mostrando la posibilidad experimental de una estructura de ejecutable multiplataforma
Un intento multiplataforma inspirado en Cosmopolitan libc
- Cosmopolitan libc es un toolkit que permite compilar código fuente en C como un único binario ejecutable en varios sistemas operativos
- Soporta ejecución nativa en diversos OS como Windows, Linux y BSD
- Debido a la falta de soporte GUI y a la limitación del gran tamaño de binario, el autor eligió el reto de crear directamente un videojuego de menos de 16 KiB
- El objetivo era crear un juego basado en una sola fuente que se ejecutara en Windows, Linux y el navegador
Estructura y reglas del juego
- El juego es un Snake estándar, controlado con las flechas o WASD
ESC para salir, R para reiniciar, P para pausar y barra espaciadora para comenzar
- La puntuación aumenta cada vez que se come comida: la comida normal vale 10 puntos y la comida amarilla (15% de probabilidad) vale 20 puntos
- La comida desaparece después de cierto tiempo, determinado por la velocidad de la serpiente (proporcional a su longitud)
- Después de comer 10 alimentos se pasa al siguiente nivel, y la disposición de las paredes cambia aleatoriamente
- El laberinto se genera garantizando que siempre exista un camino hasta la comida
- La posición inicial de la serpiente también es aleatoria, pero se coloca en una dirección con al menos 5 casillas de espacio libre
- El tamaño del archivo del juego terminado es de 13,772 bytes
Cómo está implementado en cada plataforma
- La versión para Windows está escrita en C sobre WinAPI e incluye un script de compresión y un stub descompresor
- Aprovecha los bytes libremente controlables después de la firma
MZ del encabezado PE para insertar un script de shell
- Gracias a eso, el archivo es al mismo tiempo un ejecutable de Windows y un script de shell válido en Linux
- En la primera ejecución puede aparecer el error “The application was unable to start correctly (0xc0000005)”, pero al volver a ejecutarlo funciona normalmente
- La versión para Linux usa compresión
lzma, y un pequeño shell dropper extrae y ejecuta el binario ELF64 comprimido
- Está construida para ejecutarse saltando ciertas partes al inicio y al final del archivo
- La versión HTML aprovecha que el navegador ignora la parte inicial innecesaria del archivo y procesa el HTML
- Mediante CSS, los datos innecesarios se ocultan para que no se vean en pantalla
Unión y estructura del archivo único
- Los archivos de las tres plataformas se concatenan en un orden específico, de modo que cada entorno ejecuta solo la parte que le corresponde
- Windows reconoce la sección PE, Linux la sección ELF y el navegador la sección HTML
- El tamaño final del archivo es de 13,312 bytes, completando un binario polyglot capaz de ejecutarse en los tres entornos
- Dentro del archivo se incluyen secuencialmente el encabezado PE de Windows, código comprimido con LZMA para Linux y código HTML/CSS/JavaScript
- En el bloque de código de ejemplo aparecen en orden la firma
MZ, el marcador ks, la etiqueta <html> y el bloque <script>
Importancia técnica
- Implementa una estructura de ejecución en un solo archivo que soporta Windows, Linux y navegador
- Divide la ruta de ejecución por plataforma mediante un uso superpuesto de los formatos PE, ELF y HTML
- Es un logro experimental que combina compresión, hacking de formatos y ejecución multiplataforma en un tamaño extremadamente pequeño de 13 KiB
1 comentarios
Comentarios en Hacker News
Extraje el ejecutable de Linux y me sorprendió que readelf y objdump no pudieran leerlo bien.
Al investigarlo, resultó que habían metido a la fuerza el nombre del enlazador dinámico en un campo no utilizado del encabezado PT_DYNAMIC para ahorrar espacio.
Pero me parece que romper el formato a propósito es un ahorro sin sentido.
También podría chocar con funciones de seguridad como el antivirus o DEP, así que no me gustaría tocar ejecutables así.
Me sorprendió lo pequeño que era el tamaño del archivo del Zelda original.
Es asombroso cuánto impacto e inmersión lograron crear con tan poco código y datos.
The Legend of Zelda (Wikipedia)
Extrajeron el mapa 40 años después y solo el PNG ya pesa más de 800 KB.
Ver mapa del juego
Los diseñadores las organizaron como si fuera un rompecabezas dentro de las limitaciones de espacio.
Referencia sobre la estructura del mapa de Zelda
Según mis pruebas
.html.lzma, pero funcionó después de instalar el paquetexz..como.exedaba error (0xc0000005), pero funcionó después de desactivar la configuración de DEP.chmod +x snake.comy lo ejecutas, Mono intenta abrirlo y falla.En cambio, si lo ejecutas con
bash snake.com, funciona bien. Esto fue en Debian 13.Lo interesante es que este archivo en realidad combina tres ejecutables en uno.
Así que en cada plataforma podría contener un programa completamente distinto.
Me recordó a kkrieger, un FPS de 96 KB.
El nivel gráfico en su momento era impresionante.
kkrieger (archivo)
Me pregunto si hay alguna forma de ejecutarlo en Mac aparte del navegador.
Me aparece el error
cannot execute binary file.Me pregunto si, desarrollando más este mecanismo, se podría crear un verdadero ejecutable universal (universal binary).
Por ejemplo, si escribes el código en Haxe y lo compilas a C++ puedes generar versiones para Win32 y Linux,
luego convertirlo a JavaScript para que también se ejecute en HTML,
y después unir los tres resultados en un solo archivo.
Me gusta la idea de una app ejecutable única que pueda correr en cualquier lugar desde un solo archivo.
Yo también estoy investigando esa dirección mientras construyo una plataforma serverless.
La idea es crear apps basadas en datos con un solo archivo
.html, cargando web-components de forma remota.La capacidad de abrir HTML directamente con el protocolo
file://es muy potente, pero a menudo se pasa por alto.O sea, no solo lanzó una instancia del navegador, sino que hizo dos apps nativas completas.
Me sorprende que los archivos polyglot hayan aparecido tan tarde.
Técnicamente parece algo que ya habría sido posible hace 10 o 20 años.
EICAR.COM me viene a la mente como un ejemplo temprano que era a la vez texto y ejecutable.
Me hizo pensar en competencias de minijuegos web como js13kGames, centradas en tamaños diminutos.