n0isy/fire-and-forget-2-recomp
GitHub: n0isy/fire-and-forget-2-recomp
对 1990 年 DOS 赛车游戏《Fire & Forget II》的逐函数现代化重构,采用 C11+SDL2 实现,支持原生和浏览器运行并附带了字节级可验证的关卡脚本工具链。
Stars: 1 | Forks: 0
# Fire & Forget II — Recomp
对 **Fire & Forget II: The Death Convoy**
(Titus Interactive,1990,DOS/EGA)的一次忠实现代化重构(“重新编译”),采用可移植的 **C11 + SDL2** 编写,支持原生运行,并可通过
**WebAssembly** 在浏览器中运行 —— 包含移动端的触摸控制。
该引擎是通过阅读反汇编/反编译的原始 DOS 可执行文件,
并逐个函数进行转写来重构的 —— 而*不是*通过视频来近似还原游戏玩法。
每一个重构的子系统都在运行于 QEMU + GDB 下的真实游戏中进行了验证:
**尚未移植:**声音(AdLib / PC speaker)—— 这是唯一缺失的子系统。
## 你需要原始游戏图像
重构的引擎**及其所有游戏逻辑数据**(关卡脚本、敌人
表、调色板、sprite 合成器程序、LUT、文本……)均以可读的源码形式提供,
因此你不再需要原始可执行文件的 DGROUP 数据块来构建或运行 —— 本次构建是
自包含的(参见下文的*重构数据与工具*)。
**未**重构的是原始**图像**。要运行游戏,你必须拥有
Fire & Forget II,并从你自己的副本中提取其画面、sprite 和 HUD 字体:
```
scripts/extract_assets.sh /path/to/your/FF2 # needs FF2EGA.EXE, *.CPT, HIGH
```
这会使用你副本中的 `cpt/*.CPT` 图像、`font_ega.bin` HUD 字体和你的 `HIGH` 分数文件,填充(从未提交的)`assets/` 目录。它还会切分出
`dgroup.bin`,引擎不再读取该文件 —— 它只是为了让 `tools/waveasm.py --verify` 能够将自带的关卡脚本与你自己的原始副本进行交叉核对。
## 构建与运行
原生环境(需要 SDL2 + CMake):
```
cmake -S src -B build
cmake --build build
FF2_ASSETS=assets ./build/ff2game
```
浏览器(需要 [emscripten SDK](https://emscripten.org)):
```
./build_wasm.sh # emits web/index.{html,js,wasm,data}
# 使用任意 static file server 提供 web/ 服务并打开 index.html
```
## 操作说明
| 操作 | 键盘 | 移动端 |
|---|---|---|
| 转向 / 加速 / 刹车 | `←` `→` / `↑` / `↓` | 虚拟摇杆(左侧) |
| **FIRE** —— 机枪;在菜单中:投币 | `Space` 或 `Ctrl` | 🔫 按钮 |
| **START·FLY** —— 开始;在油门全开时:起飞 / 降落 | `Enter` 或 `Shift` | ▲ 按钮 |
| **MISSILE** —— 同时按下 FIRE+START(消耗燃料) | 组合键 | 🚀 按钮 |
| 重启(网页端) / 退出(原生端) | `Esc` | — |
在触摸设备上,屏幕控制会自动出现(在 URL 后追加 `?touch` 可强制显示)。右上角有一个全屏按钮。
## 项目结构
```
src/ the reconstructed engine (C11), one module per original subsystem
src/game/data/ the DGROUP game‑logic data, reconstructed as typed C source
src/CMakeLists.txt
wave/ level scripts in the recovered wave DSL (source of wave_data.c)
tools/ reconstruction tooling (wave (dis)assembler, extractors, Ghidra scripts)
web/ browser shell (HTML/CSS/JS + vendored nipplejs for the touch joystick)
scripts/ graphics extraction from your own game copy
build_wasm.sh WebAssembly build
assets/ your copy's graphics, created by scripts/extract_assets.sh (never committed)
```
源文件中包含详细的出处注释:每个例程都引用了它所重构的原始
函数(segment:offset 地址)以及使用的证据。
## 重构数据与工具
原版游戏将其关卡脚本和查找表保存在可执行文件的 DGROUP 数据
段中。该项目并没有在运行时加载该二进制数据块,而是将其重构为
可读的、**强类型的 C 语言源码**,位于 `src/game/data/` 目录下 —— 包括敌人原型、变形和
sprite 合成器程序、调色板、面板文本、道路曲线、sine/perspective
LUT、RNG 种子、演示输入录制等。这就是使构建实现
自包含的原因。
最有趣的部分是**关卡/波次脚本**。原版游戏内置了
专用的脚本 VM —— 其关键字表(`CLEAR`、`GETCHAR`、`PUT`、`WAVE`、`GOSUB`……)
仍然保留在数据段中。我们恢复了那种小语言:
- `tools/wavedis.py` 将原始 DGROUP 字节码**无损反汇编**为
位于 [`wave/levels.wave`](wave/levels.wave) 的人类可读 DSL —— 包括助记符、敌人名称
符号、标签,甚至被剪切/无效的脚本也作为 `DEFB` 被逐字保留;
- `tools/waveasm.py` 将 `wave/levels.wave` **汇编**回字节,并生成
引擎执行的 `src/game/data/wave_data.c`。该往返过程与
原始文件进行了**字节级验证** —— 全部 3090 个字节码字节以及关卡
目录重组后完全一致。
因此,`wave/levels.wave` 是关卡设计的可编辑事实来源,而已提交的
`wave_data.c` 是其构建产物(使用
`tools/waveasm.py wave/levels.wave --c src/game/data/wave_data.c` 重新生成)。`tools/` 中的其他工具是
`pp20_unpack.py` / `bob_extract.py`,它们是用于 CPT
图像的独立解码器。参见 [`tools/README.md`](tools/README.md)。
## 法律声明
这是一个非官方的粉丝保护 / 研究项目,不隶属于或受到
版权所有者的认可。*Fire & Forget II* 及所有原始游戏内容均为
其各自所有者的财产。本仓库**不提供任何原始的二进制文件或图像** —— 没有
可执行文件,没有 CPT 画面/sprite,没有字体;你必须拥有原始游戏,并从你自己的副本中提取
这些内容才能进行游戏。引擎及其数据表是对反汇编游戏的原始
转写,仅出于教育和保护目的提供。
[nipplejs](https://github.com/yoannmoinet/nipplejs) 基于 MIT 许可协议。
标签:AI工具, Bash脚本, 客户端加密, 身份验证强制, 逆向工具