这款游戏仅 13 KiB,却能在 Windows、Linux 和浏览器中原生运行

这款游戏仅 13 KiB,却能在 Windows、Linux 和浏览器中原生运行

Hacker News 摘要

原标题:This game is a single 13 KiB file that runs on Windows, Linux and in the Browser

作者 Kamila Szewczyk 在这篇博文中介绍了一个有趣的编程挑战:创建一个体积小于 16 KiB 的单文件游戏,且该文件能同时在 Windows、Linux 和网页浏览器中原生运行。

游戏简介

这是一个标准的贪吃蛇游戏,在所有平台上都具有相同的规则和界面:

核心玩法:玩家控制蛇移动并吞掉食物。每吃掉一个食物,蛇的身体就会变长。

计分规则:普通食物每个 10 分;黄色水果有 15% 的概率生成,每个价值 20 分。

游戏关卡:每吃掉 10 个食物会进入下一关,系统会随机生成墙壁布局。

生存机制:撞墙即游戏结束。食物会在一定时间后消失,消失速度与蛇的移动速度成正比。

操作方式:使用方向键或 WASD 控制方向,空格键开始游戏,P 键暂停,R 键重置,ESC 键退出。

实现方式

为了实现跨平台的兼容性,作者实际上编写了三个版本的游戏,并将它们合并到了一个二进制文件中:

Windows 版本:使用 C 语言和 WinAPI 编写,针对 i686 架构。

Linux 版本:使用 C 语言和 X11 图形库编写,针对 x86_64 架构。

网页版本:使用 JavaScript 和 HTML5 Canvas 编写。

每种实现经过编译或混淆压缩后,体积都在 3 到 5 KiB 之间。

多语合一的技术细节

这个 13,312 字节的文件之所以能被三个不同的平台识别,是因为作者巧妙利用了各平台文件格式的冗余和特性:

1. Windows 执行文件与 Shell 脚本的共存

Windows 的 PE 文件头以 MZ 签名开始。作者在签名后放置了特定的字符,使其在 Windows 下是有效的程序头,而在 Linux 环境下被识别为一个 Shell 脚本。

• 在 Windows 上,程序通过一个压缩桩进行解压运行。由于文件头结构特殊,初次运行可能会触发系统的 AppHelp 报错,但再次运行即可正常启动。

• 在 Linux 上,文件开头的 Shell 代码会控制脚本跳过前面的 PE 数据,直接定位到文件中间的 Linux 负载。

2. Linux 负载的提取与运行

Linux 部分被存储为经过 lzma 压缩的 ELF64 二进制文件。当文件在 Linux 终端执行时,内置的 Shell 脚本会使用 tailhead 命令提取出这部分数据,解压到临时目录,赋予执行权限并运行,最后清理现场。

3. 网页版本的嵌入

浏览器在解析 HTML 文件时,通常会忽略开头的非法字符(即前文提到的 Windows 和 Linux 机器码),直到遇到真实的 HTML 标签。

• 为了让浏览器不显示开头的乱码,作者使用了 CSS 技巧(如 font-size: 0 和背景颜色控制)将这些“垃圾数据”隐藏。

• HTML 之后紧跟着混淆后的 JavaScript 游戏代码,由浏览器引擎解析并执行。

文件结构概览

文件的布局顺序如下:

头部:以 MZ 开头,包含 Windows PE 头部信息和 Linux 的 Shell 跳转脚本。

中部:包含经过压缩的 Windows i686 机器码。

中后部:通过 ks 标记引导,包含 Linux 负载的解压逻辑和压缩的 ELF 二进制数据。

尾部:以 <html> 标签开始,包含网页版的样式、画布定义以及压缩后的 JavaScript 脚本。

最终得到的这个 13 KiB 文件不仅是一个有效的 Windows 可执行文件(.exe),也是一个有效的 Linux 脚本,同时还是一个可以直接用浏览器打开的网页文件。


原文:https://iczelia.net/posts/snake-polyglot/

评论:https://news.ycombinator.com/item?id=46580864

Report Page