本文通过逆向工程,旨在提升经典赛车游戏《Stunts》的视觉效果。起初,计划通过简单修改图形设置变量来增强画质,但很快发现游戏采用了复杂的多级加载和基于瓦片(tile-based)的渲染引擎。借助社区已有的 Restunts 反编译项目,成功定位了控制渲染距离和模型细节的关键代码。作为概念验证,作者制作了一个初步的“望远镜”MOD,通过修改瓦片数据表增加了视野深度,并强制游戏始终加载高细节模型。尽管此版本存在图形错位等问题,但它成功验证了对渲染机制的理解,为后续更完善的修改奠定了基础。
什么是《Stunts》?
《Stunts》(又名《4D Sports Racing》)是一款赛车游戏,玩家可以在充满跳台、循环和高架路等超现实元素的赛道上驾驶真实世界的汽车。它与《Trackmania》或《Hard Drivin'》相似,但增加了驾驶兰博基尼或保时捷等名车的魅力。
其最重要的特点是拥有一个极其直观的赛道编辑器,让创建新赛道像玩乐高积木一样简单。正是因为这个强大的编辑器,《Stunts》至今仍拥有一个虽小但异常活跃的社区,不断有新赛道和新车辆被创造出来。
初步破解的曲折之路
最初的计划很简单,沿用之前修改另一款游戏的经验:
- 用调试器附加到游戏。
- 在选项菜单中更改图形细节设置。
- 找到存储该设置的内存地址。
- 分析代码中所有使用该地址的地方,找到渲染算法。
- 修改渲染代码以提升画质。
然而,这个计划很快就失败了。游戏的可执行文件 STUNTS.COM 仅有不到1KB,它实际上是一个加载器,会解压并组合多个二进制文件,在内存中生成真正的可执行镜像。
幸运的是,社区已经制作了一个包含了最终完整代码的 GAME.EXE 文件,这省去了分析加载过程的麻烦。但在调试 GAME.EXE 时,又遇到了新问题:
- 游戏选项不会保存到文件中,无法通过断点文件读写操作来定位代码。
- 在可执行文件中搜索菜单里的字符串也一无所获。
“Restunts”项目:柳暗花明
在耗费一小时无果后,转而研究社区提供的 Restunts 项目包。这是一个由粉丝发起的反编译项目,他们虽然没能拿到源码,但通过 IDA Pro 等工具将游戏的机器码反汇编,并逐步将汇编函数移植为等效的 C 语言代码。
这个项目留下了大量宝贵资料,包括:
asmorig:GAME.EXE的原始反汇编代码。asm: 将已移植到 C 的函数替换为调用的版本。c: 已移植的 C 语言函数代码。
借助这些带有详细注释的代码,可以更高效地进行分析。通过搜索代码,很快在 stuntsmainimpl 函数中找到了与菜单相关的逻辑。
尽管选项菜单的函数
run_option_menu未被移植为 C 代码,但通过分析汇编代码,最终确定了图形细节等级被存储在一个名为timertestflag2的全局变量中。为了便于理解,我将其重命名为detail_level。
理解瓦片图形引擎
通过在代码中搜索 detail_level 的使用位置,最终在 update_frame 函数中找到了关键的渲染逻辑。
代码显示,detail_level 被用来从一个数组中获取一个值(0、1 或 2),这个值代表了“快速”、“中等”或“完整”的图形细节。该值被用于一个循环中,决定哪些瓦片需要被渲染。
for (si = 0x16; si >= 0; si--) {if (var_50[si * 3 + 2] <= var_130) {// ... 渲染瓦片 ...}}
这个循环遍历一个包含 23 个待渲染瓦片的列表。每个瓦片数据包含三部分:
- 相对于玩家位置的东向偏移。
- 相对于玩家位置的南向偏移。
- 渲染该瓦片所需的最低细节等级。
游戏会根据玩家的朝向(分为8个方向),从8个预设的瓦片数据表中选择一个。这些表格定义了玩家前方扇形区域内哪些瓦片是可见的。
- 距离越远的瓦片,其渲染所需的细节等级要求越高。
- 细节等级越低,渲染的瓦片数量就越少,视野也就越近。
- 当一个物体进入视野近处(细节阈值为0的区域)时,游戏会加载其高多边形模型;否则,使用低多边形模型。
“望远镜”MOD的诞生与验证
分析至此,可以明确一点:简单地修改 detail_level 变量无法扩展视野,因为可见瓦片的数量和位置是由数据表写死的。要真正扩大视野,必须扩展这些数据表。
不过,在进行这项复杂工作之前,为了验证分析的正确性,我决定先制作一个简单的 MOD。
核心思路: 不增加瓦片,而是移动瓦片。将视野左右两侧的瓦片坐标修改到视野前方,牺牲宽度来换取深度,从而实现类似“望远镜”的效果。
通过十六进制编辑器,我手动修改了8个方向的瓦片数据表,将侧方的瓦片移到了更远的前方。例如,将一个位于 (东2, 南-4) 的瓦片移动到 (东0, 南-5)。
结果是成功的!在游戏的起点,我第一次看到了远处山坡上的障碍物。
同时,我还进行了第二个修改:强制使用高细节模型。通过分析代码,我找到了根据瓦片细节阈值选择高低模型的判断语句。我直接用十六进制编辑器修改了机器码,让程序在加载模型细节等级时,始终将该值设为0,从而迫使游戏一直渲染高细节模型。
初步成果与展望
这个“望远镜”原型 MOD 证明了我对渲染机制的理解是正确的。尽管它存在明显的问题:
- Z轴排序错误: 由于没有重新排序瓦片,导致远处的物体会错误地绘制在近处物体的前面。
- 视野限制: 只有在朝向正南、正北等四个基本方向时才有额外的视野距离。
总而言之,这个初步的实验达到了目的。它验证了核心机制,为下一步扩展瓦片数据表、真正提升画质的计划铺平了道路。