- Um jogo da cobrinha que roda em Windows, Linux e navegador em um único arquivo de 13 KiB, com suporte às três plataformas a partir de uma única base de código
- Segue as regras clássicas de Snake, em que você controla a cobra para comer alimentos e evitar bater nas paredes, com pontuação, níveis e estrutura de labirinto
- Cada plataforma foi implementada em C (WinAPI/X11) e JavaScript (HTML5 Canvas), com cada versão comprimida e mesclada para ficar na faixa de 3 a 5 KiB
- No Windows, a execução usa um cabeçalho PE incomum e o mecanismo apphelp; no Linux, compressão
lzma e um shell dropper; no navegador, truques de HTML/CSS
- Ao combinar as três implementações, foi criado um único executável de 13.312 bytes, mostrando a possibilidade experimental de uma estrutura de executável multiplataforma
Tentativa multiplataforma inspirada na Cosmopolitan libc
- Cosmopolitan libc é um toolkit que permite compilar código-fonte em C em um único binário executável em vários sistemas operacionais
- Suporta execução nativa em diferentes SOs, como Windows, Linux e BSD
- Devido à falta de suporte a GUI e à limitação de tamanho dos binários, o autor escolheu o desafio de criar diretamente um videogame com menos de 16 KiB
- O objetivo era produzir um jogo baseado em uma única base de código que rodasse em Windows, Linux e navegador
Estrutura e regras do jogo
- O jogo é um Snake padrão, controlado pelas setas ou WASD
ESC para sair, R para resetar, P para pausar e barra de espaço para iniciar
- A pontuação aumenta sempre que um alimento é comido, com alimento normal valendo 10 pontos e alimento amarelo (15% de chance) valendo 20 pontos
- Os alimentos desaparecem após certo tempo, definido de acordo com a velocidade da cobra, que é proporcional ao seu comprimento
- Após comer 10 alimentos, o jogo avança para o próximo nível, com a disposição das paredes mudando aleatoriamente
- O labirinto é gerado de forma que sempre exista um caminho até o alimento
- A posição inicial da cobra também é aleatória, mas é colocada em uma direção com pelo menos 5 casas de espaço livre
- O tamanho final do arquivo do jogo concluído é de 13.772 bytes
Como cada plataforma foi implementada
- A versão para Windows foi escrita em C com base em WinAPI e inclui um script de compressão e um stub descompressor
- Ela aproveita bytes livremente controláveis após a assinatura
MZ do cabeçalho PE para inserir um script de shell
- Com isso, o arquivo é ao mesmo tempo um executável de Windows e também um script de shell válido no Linux
- Na primeira execução, pode aparecer o erro “The application was unable to start correctly (0xc0000005)”, mas ao executar novamente ele funciona normalmente
- A versão para Linux usa compressão
lzma, e um pequeno shell dropper extrai e executa o binário ELF64 comprimido
- Ela é configurada para executar ignorando partes do início e do fim do arquivo
- A versão HTML aproveita o fato de o navegador ignorar a parte inicial desnecessária do arquivo e processar o HTML
- O CSS é usado para fazer com que dados desnecessários não apareçam na tela
Combinação em um único arquivo e sua estrutura
- Os arquivos das três plataformas são concatenados em uma ordem específica, de modo que cada ambiente execute apenas a parte que lhe interessa
- Windows reconhece a seção PE, Linux a seção ELF e o navegador a seção HTML
- O tamanho final do arquivo é de 13.312 bytes, completando um binário poliglota que pode ser executado nos três ambientes
- Dentro do arquivo estão incluídos, em sequência, o cabeçalho PE do Windows, o código comprimido com LZMA para Linux e o código HTML/CSS/JavaScript
- Nos blocos de código de exemplo aparecem, em ordem, a assinatura
MZ, o marcador ks, a tag <html> e blocos <script>
Significado técnico
- Implementa uma estrutura de execução em arquivo único que dá suporte a Windows, Linux e navegador
- Faz ramificação do caminho de execução por plataforma por meio do uso sobreposto dos formatos PE, ELF e HTML
- Em um tamanho extremamente pequeno de 13 KiB, reúne de forma experimental compressão, hacking de formatos e execução multiplataforma
1 comentários
Comentários do Hacker News
Extraí o executável de Linux e fiquei surpreso porque readelf e objdump não conseguiam lê-lo direito
Investigando, descobri que ele economizava espaço ao enfiar à força o nome do linker dinâmico em campos não usados do cabeçalho PT_DYNAMIC
Mas acho que corromper de propósito esse tipo de formato é uma economia sem sentido
Também pode entrar em conflito com recursos de segurança como antivírus ou DEP, então eu não gostaria de mexer com esse tipo de executável
Fiquei impressionado com o tamanho minúsculo dos arquivos do Zelda original
É admirável o quanto de emoção e imersão eles conseguiram criar com tão pouco código e dados
The Legend of Zelda (Wikipedia)
Extraíram o mapa 40 anos depois, e só o PNG já passa de 800KB
Ver mapa do jogo
Os designers montaram tudo como um quebra-cabeça dentro das limitações de espaço
Referência da estrutura dos mapas de Zelda
Resultado dos meus testes
.htmllzma, mas depois de instalar o pacotexzfuncionou.comou.exe, deu erro (0xc0000005), mas funcionou depois de desativar a configuração de DEPchmod +x snake.come executar, o Mono tenta abrir e falhaEm vez disso, executar com
bash snake.comfunciona bem. Testado no Debian 13O interessante é que esse arquivo tem a forma de três executáveis fundidos em um só
Então, em cada plataforma, ele poderia até conter programas completamente diferentes
Isso me lembrou o kkrieger, um FPS de 96KB
O nível gráfico dele era impressionante na época
kkrieger (archive)
Queria saber se existe alguma forma de executar isso no Mac além do navegador
Aparece o erro
cannot execute binary fileFiquei pensando se seria possível evoluir esse mecanismo para criar um verdadeiro executável universal (universal binary)
Por exemplo, escrever o código em Haxe e compilar para C++, gerando versões para Win32 e Linux,
depois converter para JavaScript para também rodar em HTML,
e então juntar os três resultados em um único arquivo
Gosto da ideia de um aplicativo executável único que rode em qualquer lugar
Eu também estou pesquisando nessa direção enquanto crio uma plataforma serverless
A ideia é fazer um app orientado a dados em um único arquivo
.html, carregando web-components remotamenteO recurso de abrir HTML diretamente pelo protocolo
file://é poderoso e muitas vezes ignoradoOu seja, não foi só abrir uma instância do navegador, mas criar dois aplicativos nativos completos
É curioso que arquivos polyglot só tenham aparecido tão tarde
Tecnicamente isso parece algo que já poderia existir há 10 ou 20 anos
EICAR.COM me vem à cabeça como um exemplo antigo que funciona ao mesmo tempo como texto e executável
Isso me lembrou competições de microjogos para web como o js13kGames