不是延期就是崩盘,游戏移植到底有多难?
那些对“传火”近乎痴迷的冒险者,如今在探索罗德兰王国时恐怕已不再那么苦痛,他们可以瘫倒在床、卷入被窝,舒适的从北方不死院踏上征程。但在这背后,《黑暗之魂 重制版》迈向 Switch 的旅途却并不顺利,维塔士大约从去年8月起就接手了移植工作,经历了漫长的等待后,这款作品直到今年10月才正式发售。
移植游戏得花上一年多的时间?这或许让人有些困惑。有人将延期的原因归咎于平台的性能问题,也有不少人认为任何理由都是托词,甚至衍生出“是为了给其它作品发售让路”的阴谋论。这些言论并非单单针对某一款产品,它们或许已经成为玩家看待移植工作的普遍观点。
面对人们积蓄已久的不满情绪,维塔士制作人 Lukas Codr 此前还详细剖析过项目的难点,尽管这项工作看似只是简单的“搬家”,但在实际进行操作时,无论是代码的兼容、还是帧率的匹配,亦或是截然不同的网络系统都暗藏着巨大挑战。
这并非个例,Team Cherry 在将《空洞骑士》捣腾到 Switch 平台时,前前后后也花去了一年时间。移植同样成为了许多日本厂商难以跨过的高槛,内容搬运后缺胳膊少腿、错误频出早已被视为一种正常现象。如此看来,要做成这门“吃老本”的生意没有想象中容易,它背后又需要突破哪些关隘?
老游戏的隔阂深如海
在高级语言和跨平台的游戏引擎兴起之前,各平台的内容移植成本可能难以想象。不同硬件的运行规则,几乎可以将底层的逻辑全都翻新一遍,随之而来的结果便是:仅有关卡、数值和系统这些概念层面的东西能够沿用下来,而图形素材、音乐资源往往都得重新制作。
作为佐证,上世纪八九十年代的游戏在移植过程中往往被改得面目全非。1984年,《炸弹人》开发商 Hudson 与任天堂合作,负责将几款 FC 上的作品搬到家用电脑 PC-8801 和夏普 X1 上,其中不少游戏受经移植后已经完全变样,这种改变甚至深入到核心的设计部分。
原版《马里奥兄弟》(水管马里奥)的主要玩法是从下层撞击平台,将敌人撞翻后跑过去消灭它们。底层中央还有个名为“POW”的方块,撞击后所有在场的怪物都会翻转过来,等同于 STG 游戏中的“保险”。但经由 Hudson 过一道手,PC-8801 上的《马里奥兄弟 特别版》简直可以当成另一款游戏。
劣化后的图形素材暂且不提,特别版的关卡和玩法几乎完全变样。玩家时而需要穿梭左右横移的平台,时而又需要利用“蹦床”震翻敌人,游戏还加入了限时收集道具的元素。有趣的是,这些魔改当时并不让人反感,设计上也有许多独特之处,反而彰显了第三方厂商的创意和实力。
从技术层面来看,Hudson 对内容进行换皮和翻新或许也是被逼无奈。早期的游戏基本都由汇编构筑代码,与今天编程的高级语言不同,它有时会具体到寄存器和内存地址的调用,而在移植过程中,每个平台、每块芯片的指令集、位宽,甚至连寄存器数量都不一样,这成了难以调和的麻烦事。
以 SFC 和 MD 为例,它们处理器分别为65c816和摩托罗拉68000。前者只有2个寄存器,而68000则包含8个通用寄存器和8个地址寄存器,两者的寻址逻辑、调用命名、资源的处理和存放地址截然不同。
对于汇编而言,在 x86 架构转向 x64 架构时,改一下数据格式和名称还勉强管用,而放到 ARM 架构时这套规则就像天书,有时重写代码还要更为效率。
2013年时,有开发者试图将 SFC 上的《星际火狐》移植到 MD 平台,但他最终只完成了一个简单的 Demo。不仅缺少声音和精细的图形素材,整体的运行效率也就8~9帧,完全算不上一款可玩的游戏,足以见得这背后的困难程度。
不过,随着硬件性能的提升,人们想到另一个围魏救赵的办法:既然重构老游戏的汇编代码这么麻烦,倒不如重构老游戏的运行环境,将程序和模拟器捆在一起。一个较为常见的说法是,如果新平台和老平台的指令集、操作系统完全不同,那么大致需要10~40倍的 CPU 算力才能实现模拟,这在今天已经不是问题。
西班牙开发商 BlitWorks 就是“模拟移植法”的好手,该公司的创始老哥 Angel Horna 痴迷于钻研新旧游戏平台的特性,曾经还编写过盛名在外的 Nebula(星云)模拟器。它们在2012年接到世嘉委托,负责将 DC 上的《街头涂鸦》(Jet Set Radio)高清化,并移植到各个主流平台。
尽管 DC 上的游戏已开始通过高级语言编写,但要对细枝末节进行修改,并将其带到 PC、移动端和其它主机平台仍是不小的工作量。让人出乎意料的是,BlitWorks 只花9个月就完成了任务,达成这项壮举的诀窍在于,它们构建了一种新的混合技术,从而使得新平台能够运行旧代码 —— 说白了,其实也就是将 Dreamcast 模拟器和游戏整合了一下。
实际上,为了让新机器能够玩上老游戏,索尼这些年来也一直在研究模拟器。PS3 上有 PS1、PS2 的模拟器,PS4 上也默默出了几个 PS2 游戏的模拟版,与 BlitWorks 的逻辑可能十分相似。而在刚刚发布的 PlayStation Classic(迷你 PS)中,索尼还植入了它们过去所反对的东西:以开源架构设计的民间模拟器 PCSX ReArmed。从中也能看出潜移默化的态度转变。
一个世代的距离同样遥远
如果说太久远的作品有点难搞,那么隔代、或者同世代游戏的移植又如何呢?它们的出产日期最多差个 6~7 年,代码和硬件制式的变化也没那么大。在这一点上,虽然现今的内容移植确实简单不少,但如果要彰显诚意,保留原汁原味的体验、甚至高于原汁原味的体验,同样是个劳神费力的苦差事。
让我们继续述说 BlitWorks 的幕后轶事。在将 PC 平台的《Fez》移植到 PS3 上时,它们又发现了一个新的难点,该作主要由 C# 编写,而 PlayStation 平台当时对此并不支持。该问题有两种解决方案,要么是将 Mono Runtime 整个移植到新平台,要么是用 C++ 把游戏重写一遍。
(*注:PS 不支持 C# 原生开发,但支持 Mono 这个环境,所以可以将《Fez》代码整合到 Mono 中。)
如果继续使用 C#,游戏可能会受到 CPU 性能的掣肘,就像早期的 Xbox 360 版本一样;而如果将代码转写为 C++,又会变成漫长而乏味的任务。由于无法预估 C# 移植产生的问题,BlitWorks 最终还是选择了转写,这也能够保证游戏更顺畅的运行。
事实证明它们做出了正确的决断,尽管《Fez》看起来是一款 2D 像素游戏,但内部其实包括很多 3D 结构和多边形块。处理这些图形对于 PC 和本世代主机来说是小菜一碟,但直接搬运到移动平台、或上世代主机时却会遭遇着色器相关的麻烦。不过正因为进行了转写,BlitWorks 此时可以轻松的对部分代码进行调整。
《Fez》在移植的过程中还衍生出一个副产品。为了日后更轻松的将 C# 转换成 C++,BlitWorks 在2013年推出了一个名为“Unsharper”的自动化软件,它随后也被应用于《全金属狂怒》《堡垒》等独立游戏的移植工作。
你或许会认为这些专接外包的小厂技术力不够,所以才会把事情搞得这么麻烦。但为了将《最后生还者》从 PS3 弄到 PS4,即使是大名鼎鼎的顽皮狗也愁白了头。在接受 Edge 杂志采访时,该作的创意总监 Neil Druckmann 就半开玩笑的说:“我真希望有个按钮能够一键「打开 PS4 模式」,但结果与预期一致,(移植过程)就像地狱一般。”
事实上,由于新老两代主机的规格和运行方式略有不同,《最后生还者》起初在 PS4 上的运行效率不到10帧。即使对渲染相关的代码进行重新优化,游戏也没能达到每秒30帧的“基础要求”,就更别提宣传口号中的“60帧”目标了。根据首席程序员 Christian Gyrling 的回忆来看,当时距离作品的发售节点已不足3个月,团队中弥漫着一股恐慌的情绪。
问题的症结主要在于,将分辨率提高到1080P、并更新了一批美术素材后,每帧画面的处理和渲染速度实在是太慢了。顽皮狗的解决方案是将 CPU 的负载分流为两部分,让它首先只计算玩法,算完之后再对图形进行渲染,毕竟一个有序通行的岔路口,可比大家都挤在一起堵死要好得多。这么整捣一下,开发团队陡然发现 —— “1080P+60帧”的目标居然真成了。
不过,帧数提高本身又会给项目带来新的挑战。为了填充这多出来的30帧,《最后生还者 重制版》还得从原始动画数据中重新采样,并逐帧调整美术细节。这在动作游戏中可能更加麻烦,《黑暗之魂2》最初的武器耐久值就通过帧数判定,当 PC 玩家以60帧的效率运行游戏时,装备的损耗速度明显增加。
源代码丢了怎么办
关于游戏移植的另一则趣闻是,就在几个月前,国内媒体盛传《最终幻想8》没有移植的原因是“源代码丢失”。但事实上,该作的高清复刻早在2013年底就登陆了 Steam,这一传言甚至漂洋过海,还被 Square Enix 的技术总监土田善紀拿出来调侃了一番:
我听到了有传言说 FF8 不能移植是因为源代码丢失了,不知道这种流言是怎么来的呢?但是明明已经有移植过了的 Steam 版了呀?一般来说,不可能会有这都保管不好的事情发生吧?不过话说有人看到我 FFT 的角色动画程序了吗?我找不到它了。
土田可能没想到,此番针对传闻的发言,最后却阴差阳错指到了社友野村哲也的脑袋上……在开发《王国之心HD 1.5 Remix》时,他们其实搞丢过初代的源码,为此只能深度的挖掘原作,并对内容进行重建。碰巧的是,搞丢源代码的糊涂蛋绝非只有 Square Enix,这甚至成了一种行业常态。
对于许多专注游戏移植的团队而言,它们的工作往往始于一张光盘,而不是源代码。《旺达与巨像 重制版》的开发商 Bluepoint 创始人 Marco Thrush 曾经表示,为了凑齐100%的内容,它们总是得从零售光盘里获取数据,然后进行拆包和反向编译。尽管经验丰富的开发者,能从拆包文件中找到许多有用的资源,然后通过重建引擎的方法将所有内容都拼回去,但这背后又会徒增许多不必要的成本和精力。
Hyjinx 工作室就是“源代码遗失”的受害者,在帮 Konami 制作《寂静岭 高清典藏版》时,它们拿到的源码居然不是最终版本,其中还包含了早期的 Bug 和内容缺陷。负责移植的制作人 Tomm Hulett 打趣的说到:“游戏中有一处 Heather (《寂静岭3》人物)还是蓝色的。”
由于掺杂了大量的纹理问题和 Bug,一部分材质和声音也得自己提取,Hyjinx 工作室花了两年时间才把这个 HD 合集给搞定。作为参考,《寂静岭2》从无到有其实也才用了两年。
值得警醒的是,反向编译有时还不能解决所有问题。
加拿大开发商 Beamdog 曾打算对《冰风谷2》进行重制,但该作的所有权随着混乱的企业收购多次易手,导致游戏的源代码无从追迹。它们调查过雅达利转交给威世智的数据,也向黑曜石的朋友寻求过帮助,最终还是无功而返。而最大的难点在于,现存市面上《冰风谷2》(包括 GOG 版)的代码几乎都经过了压缩,Beamdog 也无法从本体中取得完整、有效的信息,只能取消整个项目。
即使是暴雪这样的厂商,对源代码的保护有时也会疏忽大意。2017年5月,时值《星际争霸 重制版》的制作节点,Reddit 用户 Khemist49 却从 eBay 上淘到了一张“《星际争霸》母盘源代码”的刻录盘。他将光盘返还后得到了“隆重”的感谢,暴雪寄来了一大摞外设和周边产品,还为他报销了嘉年华活动的所有费用,并邀其共进晚餐。
再来看看黑暗之魂
近几年涉及到移植的难度,通常与平台之间的程序、引擎支持相关。比如用 DirectX 技术编写的程式,在只支持 OpenGL 的硬件上就不会那么好用。由于许多厂商都开始使用虚幻和 Unity 等跨平台引擎,与之对应的游戏只需要进行较少的适配工作,已经算是很好移植了。
让我们将眼光聚焦回《黑暗之魂》Switch 版本身。黑暗之魂初代所用的引擎名为“PhyreEngine”,这是索尼2008年在 GDC 上开始宣传的一款产品,Falcom 旗下的《英雄传说 闪之轨迹1》,以及 Square Enix 旗下的《勇者斗恶龙 建造者》都使用了这个引擎开发。虽然 PhyreEngine 由索尼制作,但它们倒是持开放态度,无论你是开发商、发行商还是中间件团队,都可在任何平台上基于引擎打造产品。
问题在于,PhyreEngine 直到今年1月17日才支持 Switch,而维塔士至少从2017年8月起就已经开工了。这意味着它们要么参照老思路,可能得自行一个个调用 OpenGL 的原生 API;要么废弃一部分之前的工作,研究 PhyreEngine 的新版特性。相比之下,前者的工序复杂而不稳妥,后者可能更便于纹理、着色器的直接调整,但又面临着新版引擎兼容不完善的风险。
Unity 此前也不乏踩坑的例子,《Sword of the Guardian》制作人 Billy Chan 认为,Unity 对 Switch 的支持就不太完善,他的作品在 PC 和 Xbox One 上能以60帧运行,而当缩减为30帧的 Switch 版本时,游戏中人物移动将有不自然的滑动。
《尤卡莱莉大冒险》和《战神:夜袭》的移植工作,同样也因引擎问题而遭受阻碍,这些中小型的开发者和外包团队,当然不具备顽皮狗那样的资源去逐帧修改内容。
除了引擎所带来的问题外,杂七杂八的小毛病还需要耗去更多时间,比如现代化的操作适配,长宽比和界面的调整,以及游戏本身与平台的内容联动。《黑暗之魂》Switch 版就新增了6人联机,其中需要做大量的优化工作。而 Bluepoint 重制《旺达与巨像》的第一项工作 —— 是得搞一套日版的 Linux 系统,用来打开官方提供的硬盘文件。
从商业的角度来看,移植、复刻、重制如今都成了一种有利可图的策略。整体上,它能以低于新内容的制作成本,来重新焕发老品牌的价值。与此同时,玩家也乐于在续作或者系列重启前,体验到一款经过细致包装的老游戏,这理应是享受经典的绝佳方式。
不过,电子游戏历史基金会创始人 Frank Cifaldi 却认为,这些工作在情感和艺术上还有着额外的意义:“我认为意识也是继承的一种形式。我想说的是,通过重新制作来延续这些作品的生命力,绝对是在保护游戏的传统、理念和世界地位。”
无论对应的是成功的商业模式、亦或是背后的艺术价值,它们本身就已决定了,移植和翻新在最为基础的理念中也不应被当成简单工作。从最早的硬件隔阂,到现今数不尽的烂摊子,一款作品的转移过程也可能包含着密密麻麻的任务,这需要非凡的专业知识,同样面临着额外的后勤和美术需求。
尽管在缺少官方信息的情况下,外人无法剖析更为深入的原因,但《黑暗之魂》的移植工作或许也卷入了相似的漩涡。试想一下,结合之前那些苦痛的案例,当你需要重整几万行陌生的代码时,它的困难与否自然也就心中有数了。