游戏邦在:
杂志专栏:
gamerboom.com订阅到鲜果订阅到抓虾google reader订阅到有道订阅到QQ邮箱订阅到帮看

9个不按常规出牌的游戏开发技巧

发布时间:2014-10-10 11:20:33

作者:《Game Developer》员工

《Game Developer》的一个最受欢迎的功能便是我们的“不按常规出牌的编码技巧”(诞生于2009年),在此我们可以帮助开发者打开一些他们为了满足最后期限或通过认证而依靠的非常伎俩。我们将使用9个全新的故事,包括一些来自其它开发学科(除编程以外)的非常规技巧。所以请继续下去,沉迷于同行们的精明想法,并尽可能地放松下来—-因为你并不是唯一一个顶着压力使用非常规小伎俩的人。

RSX,隐藏的文本资产

Joe Valenzuela, Insomniac Games

这一技巧是在PS3上,我们在Insomniac的引擎团队拥有一些我们想要分配到我们的引擎/工具发行的纹理。这是一些像噪音纹理以及面向全屏滤网的资源输入。出于某些并不重要的原因,我们并不想将这些内容作为实际资产文件进行分配,所以我们决定将其转变成二进制数组并将其编译成可执行的内容。这里存在一个负面元素—-我们想要这些内容处在不同的内存块中(RSX可视),所以我们最终将复制它们,但却因为资源而浪费了一些内存。

PS3工具链拥有一个链接功能能够将特定的部分置于RSX内存中,但它需要使用1MB的页面,在我们的情况中,它将浪费700k内存。所以我们在名为bss(游戏邦注:即bss alias或balias部分)的可执行内容中添加了一个新的数据部分。在我们的最终架构中拥有像3MB的bss等内容,所以拥有足够的空间能够隐藏一些纹理资产。我们尽早运行某些代码从而让我们能够基于crt初始化去初始化目标内存,复制资产,然后再次将bss初始化为0。

不管你是否相信,它都是可行的!存在一些调整元素能够去适应隐藏的bss使用和工具链升级,但从整体上来看它是非常简单的。

这并不是你所寻找的漏洞

Brett Douville,LucasArts

在2002年初,我们正在准备将《星球大战:绝地战斗机》提交到索尼。还剩下一个不是很重要的TCR漏洞,即控制器的模拟棒功能在我们加载任务后过场动画时会关掉,并因此导致控制器的中心亮起了红灯。当我们升级到索尼所需要的程序库版本时,这一漏洞便会出现,最初编写影像加载代码和控制器本身的IOP逻辑的程序员已经在几个月前离开了LucasArts了。

为了尽快解决代码中我并不理解的问题,我在代码中插入了不同颜色的7个清屏代码,希望我至少能够通过检查在模拟控制关闭时屏幕显示什么样的颜色而将其压缩至1,2个部分。但是当我尝试着去重新创造漏洞时,它却已经消失了。

这是一个早前的编程箴言,如果你并不理解原因,你便不能说是解决了漏洞。但在这种情况下,即离最终提交日期只剩2,3天时间,错过漏洞将酿成大错。所以我将所有清屏代码改成黑色,标记了修复的漏洞,并就此收工。我们按时发行了,并且没有TCR的干扰。

Untitled(from gamasutra)

Untitled(from gamasutra)

独立探索

Jonathan Garrett,Insomniac Games

《瑞奇与叮当3》是一款不能修补代码或数据的在线游戏。这是非常遗憾的。

每次当游戏发行时便会呈现一个最终用户许可协议。这是储存于静态缓冲区的字符串。这一缓冲区是源自服务器,并且不会检查、规格是否符合缓冲区的要求。

我们利用这一点让EULA下载能够充满静态缓冲区,从而覆盖一个已知的全局变量。这一变量将成为一个特定的网络数据包的回调函数处理程序。一旦安装了这一处理器,我们便能够发送网络数据包并跳跃到被覆盖的全局变量的地址上。该地址是面向一些早前储存在EULA数据中的有效负载代码的指示器。

有价值的数据存在于真正的EULA缓冲和被覆盖的全局变量之间,所以有效负载代码的第一件工作便是恢复这一垃圾数据。一旦完成了这件工作,所有的一切便会恢复正常,修补工作也能得以完成。

这里存在的一个并发症便是EULA文本是复制拷贝字符串的。当它找到一个0字节(这通常都是字符串的结尾)时,拷贝字符串便会结束。我们的字符串通常包含0字节。所以我们创造了一个变异代码,它将不包含任何0字节,并拥有精心创造的引导程序asm。

最终的过程如下:

1.发送过大的EULA

2.EULA缓冲区溢出,杂项数据,回调函数处理程序指示器

3.发送数据包去引导处理器

4.游戏跳转到处理器所指向的引导程序代码

5.引导程序解译有效负载数据

6.有效负载数据下载并储存杂项数据

7.执行补丁

附:在你的发行游戏中包含补丁代码,并且不要使用无限拷贝字符串。

堵塞卡盘

Michael A. Carr-Robb-John, Monolith Productions

1993年我完成了《沙漠风暴》;我将其从16位体的Mega Drive/Genesis版本转变成8位体的Master System。这款游戏(12K)超越了预期卡盘的规格,但却不可能转向另一个规格的卡盘。在今天,12K听起来可能非常小,但是在当时却是完全不同的情况。在开发期间,我做了预算安排并计划了所有的声音和图像资源,它们都应该是符合限制的。而我并未认真考虑到的这是代码。在那些日子里,游戏是基于汇编语言进行编写,也就是Z80,所以我只有一个选择。我花了1周的时间去寻找冗余码,并重新编写某些内容以确保不会占用较多内存。

当我完成这项工作时,游戏能够匹配一个卡盘了(只有98字节)。游戏能够被放到ROM中并在QA中测试几天,然后再递交给Sega进行认证。不幸的是它在一开始未能通过认证,而所需要做出的修改很快就耗尽了那98个字节。我认为当我们最终能够发行游戏时,可能就只剩下6个字节了!

道尔顿分配

Jonathan Adamczewski, Insomniac Games

在接近项目的最后,我们发现在玩了游戏几个小时后,影像并不能像预期的那样出现。我们的一个内存分配的破碎导致我们不能分配全屏影片重放所需要的巨大内存组块。

我们需要寻找一种能够保证我们始终能够获得所需内存的方法。但是在这个项目中已经太晚了,如果去考虑整理碎片将具有很大的风险,我们没有足够空闲的内存能够用于设置影片重放,从其它系统中获取额外的空间也是不切实际的做法。

显然当影片播放时,存在许多限制的系统,所以我们将考虑从它们中“借取”一些内存。然而这些潜在的资源也都太小了,要不就是也遭受着同样的碎片问题。虽然GPU存在许多空间,但出于各种原因,我们并不能将其作为影片的缓冲区。所以我们需要另外的空间来源。

让我们着眼于另外一个问题,即在我们的主要游戏资产中出现了一个特别的内存分配模式:当游戏开始时,磁盘加载了许多资产,但是它们在内存中却不会被改变。在这些资产中,有些非常巨大。并且在影片播放时并不需要它们。

这带给了我一个想法:如果我们将复制其中一个最大的资产文件到内存的任何地方会怎样?GPU的内存将作为存放资产的临时场所,然后我们便能够临时重新使用资产中的空间用于影片重放,并在影片播放完成后从GPU内存中复制资产数据。

所以这便是我们的做法。我们选择了用于其中一个游戏英雄(名为Dalton)的最大动画片段。动画系统被关掉了,动画片段被复制到了GPU的内存空间中,内存被交给了影片重放系统。在影片的最后,动画数据将被复制到它所归属的地方,动画系统将重新开始,如果未发生任何糟糕情况的话游戏将会继续。最终执行将变得非常简单,尽管过程并未延伸许多帧去确保所有包含的系统在每个步骤中都是同步的。

在角色的动画内存被占用后,影片系统的内存将被描述为“道尔顿分配”。

认证头疼

Michael Carr-Robb-John, Monolith Productions

任何曾经在主机上写过游戏的人都知道所谓的认证头疼。很大程度上,认证是一种尝试也是一种良好的实践,但却存在一两种要求可能成为让开发者伤脑筋的问题。我们必须处理的一种要求便是在用户选择运行你的游戏时,你必须在短短的4秒钟内呈现第一个画面。如果你拥有巨大的执行内容,你可能需要在控制它前花费2,3秒钟进行加载,并且为了呈现主菜单,你仍需要加载一大堆的视觉和声音元素。

我的游戏从用户选择游戏到呈现第一个画面间需要花费26秒,所以我开始感到头痛了。我的第一个工作便是分割菜单所呈现的内容,将加载特定的全局数据推迟到真正需要的时候。让人惊讶的是,这么做的影响比我所预期的还大;这整整节省了9秒钟。在经过许多调整后,我想办法将时间减少到10秒钟,但是我却不能让它更快地进行加载。在与其他工程师讨论问题的时候,我们终于想到了解决方法。

特定的主机同样也有另外的要求,即你的游戏在进入菜单系统前将呈现两个特定的画面。有趣的是我们必须组织用户在特定时间里略过这些画面。如果我们只加载这两个画面,那么在玩家观看这些画面时大多数屏幕是否能够完成加载,即5.5秒钟是否能够完成加载和呈现。

不幸的是,这仍然不足以满足要求,所以我们最终只能申请豁免。

创造声音

Edward J. Douglas, Flying Helmet Games

很长一段时间我都致力于一个长期运行的赛车游戏系列的影片制作。我们的场景混合了直接的网格和华丽的动作序列。当我们在更多续集中迭代时,我们的野心也变得更大,但是我们的技术迭代却相对缓慢。

汽车的动画是通过一个QA“特技驾驶”去获得基本动作,然后在3D动画程序中进行设计以调整动作的时间和布局,并重新导到我们游戏内部的影片工具中,在这里影片重放将模拟所有的物理和引擎行为。我们将获得许多游戏设置数据,包括控制器的汽油和刹车信息,并呈现在3D文件的元数据中,然后在游戏中进行重现。这里所存在的理念在于,这同时也能够驱动汽车音频系统。

问题继续蔓延到之后的几个续集,即在续集中,我们的场景非常复杂,并混合了手动捕捉和记录的汽车动作。早前关于使用引擎元数据去驱动汽车的音频样本的做法已经不再有效—-数据不可能存在了!音频团队不能像影片那样时候再处理音频,因为任何场景都拥有汽车,这取决于玩家的选择和修改,所以音频需要是程序化的。但直到现在,我们的游戏已经获得了许多音频奖项,特别是汽车的引擎声,所以我们决定继续使用它。

在测试之际,我们面对了各种不确定性,但我们那拥有独创性且疯狂的影片,音频和AI程序团队找到了解决方法。汽油和刹车元数据是基于3D场景中一个漂浮的立方体呈现出来。如果一位美术师参与进来并在3DS Max等关键帧编辑器中“绘制”曲线的话,他们将能够创造出他们想要的汽车引擎声。一些音频团队成员临时学习了3DS Max,并通过直觉判断模式转变模式应该是怎样的,并将其压缩在适当的时间范围内。这听起来很棒,但在这最后的几分钟内,我们知道如果想要在下一个续集中使用同一的技术基础,我们便需要一些更强大的技术。

所以在完成这款游戏后我离开了该工作室,在几年后我遇到了一位在我离开后加入该工作室的音频师。这是在我意识到他们从未升级技术不久前,他也是这系列游戏最新续集的“引擎声音创造者”。

好运气

Richard Morwood

我有一列背景纹理,并编写了游戏代码,从而在滚动屏幕时能够将其呈现出来。我的一个背景图像被略过了,即使在花了许多时间去排除故障后仍不清楚具体原因。我们距离截止时间还有5天,所以我在背景列表的纹理中插入了一个额外的参考。这样就没有更多“被略过的”背景了。

HR技巧

Ben Burbank

当我习惯效劳于一家大型公司时,其中一名员工明确了推动自己职业生涯的最佳方法便是为更多同事编写负面的绩效评价。这将帮助他获得更高的年度员工排名,并为他带来更多将近和股权分配。但他告诉我,这种方法变得越来越困难,因为你需要确保你所评价的对象是不同管理者的下属,如此才不会有人识破你的诡计。我关于避免这种循环的方法便是离开并选择其它更小但却更棒的工作场所。

鼓励奖

Chris Pruett,Robot Invader

[编者注释:这并不是一个不符合常规的游戏开发技巧----但是我们认为这是使用工作技能去解决现实世界问题的一种便捷方法。]

我的妻子玩的电子游戏并不多,但是有一系列游戏却是她从小便沉浸于其中的,那便是《勇者斗恶龙》。几年前,她开始在我那上了年纪的PlayStation上完《勇者斗恶龙VII》。在玩了80个小时后,她惊讶地发现自己的保存文件损坏了。它出现在继续游戏的菜单上,但却不能再选择了。她感到非常震惊且生气。并发誓再也不玩这款游戏了。

我发现一台二手的DexDrive能够读取并编写PC上的PS1内存卡,它在eBay上的售价是15美元。我并未告诉妻子我在尝试着挽回它的保存文件—-我并不想在给了她希望后又让她失望,因为我并不敢保证这一方法可行。如果数据遭到了不可挽回的损害,丢失将会是必然的。另一方面,我也觉得尝试着挽救这些文件不会什么损失。

基于DexDrive,我可以把破损的文件储存在PC上,并在一个十六进制编辑中检查它。我最终将其印刷出来并使用荧光笔标记了十六进制;尽管PS1保存在8kb的组块中,但是将8kb文件打印成十六进制数据却需要好几页。使用PS1模拟器的作者所编写的非正式规格,我明确了主要的数据组块:页眉,图标图像,以及保存数据本身。不幸的是,破译原游戏状态数据具有挑战性;几天后我发现这需要比我所计划的更多的工作量。

相反地,我选择专注于数据的页眉部分。因为图标的设置,我可以准确地说出页眉的开始与结束位置。如果继续游戏的菜单能够呈现出保存文件已经被损坏的信息,也许这便只是页眉被损坏而已。我通过从其它保存文件中复制了页眉数据,并将其黏贴在我的妻子的破损保存文件的页眉部分去测试这一点。然后我将这一数据保存到内存卡并加载它。

奇迹般地,它发挥了作用。继续游戏的菜单显示了来自其它保存文件的数据,但一旦完成了加载,她的游戏将完全恢复。在订购DexDrive和修补保存文件间,整个过程大概花了我3周的时间。在某天晚上我启动了游戏并呈现给她带有奇怪名字的保存文件的继续游戏菜单。它加载了游戏并惊讶地发现了自己的进程,角色,统计以及所有道具都回来了。她真的非常兴奋,但在我们进一步讨论前她已经开始转向一个不同的地下城了。

本文为游戏邦/gamerboom.com编译,拒绝任何不保留版权的转功,如需转载请联系:游戏邦

Dirty Game Development Tricks

by Game Developer Magazine Staff

One of Game Developer’s most popular features was our “Dirty Coding Tricks” bit from 2009, where we got devs to open up about some of the ugly hacks they’ve resorted to in order to make a ship deadline or pass certification. Well, we’re back with nine new from-the-trenches stories, including a few unorthodox tricks from other dev disciplines besides programming. So read on, revel in your colleagues’ ingenuity, and relax — because you’re not the only one that pulls out a dirty trick under pressure.

Crouching RSX, hidden texture assets

Joe Valenzuela, Insomniac Games

This trick was on the PS3: We on the Insomniac engine team had some textures that we wanted distributed with our engine/tools release. These were things like noise textures and source input for full-screen filter effects. For some unimportant reasons, we didn’t want to distribute these as actual asset files, so instead we converted them to binary arrays and compiled them into the executable. There was one downside, though — we wanted these to be in a different chunk of memory (RSX visible), so we would end up copying them out and just wasting the memory for the source.

The PS3 toolchain had a link feature to put certain sections in RSX memory, but it requires using 1MB pages, and in our case it would have wasted 700k. Instead, we added a new data section in the executable that aliased the bss (the “bss alias” or “balias” section). We had something like 3MB of bss in our final builds, so there was more than enough space to hide some texture assets. We ran some code as early as we could in the crt initialization to initialize the destination memory, copy the assets out, and then re-initialize the bss to 0.

Believe it or not, it worked! There was a little tweaking to accommodate hidden bss use and toolchain updates, but overall it was pretty straightforward.

This is not the bug you’re looking for

Brett Douville, LucasArts

In early 2002, we were readying Star Wars: Jedi Starfighter for submission to Sony. One niggling TCR bug remained, which was that the controller’s analog stick functionality would shut off while we were loading our post-mission cutscenes, causing the red light in the center of the controller to go off as well. This bug had shown up when we updated to a library version required by Sony, and the programmer who had originally written both the movie-loading code and the IOP logic for the controller itself had left LucasArts some months before.

In the hopes of narrowing down the problem quickly in code I didn’t understand, I inserted seven screen clears in different colors in the code I determined to be the likely source of the problem, hoping that I could at least narrow it down to one or two sections of code by checking what color the screen was when the analog controls turned off. But when I then tried to reproduce the bug, it had disappeared.

It’s an old programming adage that if you don’t understand the cause, you can’t be said to have fixed the bug. But in this case, we were two or three days away from our intended submission date and missing it would have been a big deal. So I changed all the screen clears to black, marked the bug fixed, and called it a day. We shipped on time, with no TCR showstoppers.

(s)elf-exploitation

Jonathan Garrett, Insomniac Games

Ratchet and Clank: Up Your Arsenal was an online title that shipped without the ability to patch either code or data. Which was unfortunate.

The game downloads and displays an End User License Agreement each time it’s launched. This is an ascii string stored in a static buffer. This buffer is filled from the server without checking that the size is within the buffer’s capacity.

We exploited this fact to cause the EULA download to overflow the static buffer far enough to also overwrite a known global variable. This variable happened to be the function callback handler for a specific network packet. Once this handler was installed, we could send the network packet to cause a jump to the address in the overwritten global. The address was a pointer to some payload code that was stored earlier in the EULA data.

Valuable data existed between the real end of the EULA buffer and the overwritten global, so the first job of the payload code was to restore this trashed data. Once that was done things were back to normal and the actual patching work could be done.

One complication is that the EULA text is copied with strcpy. And strcpy ends when it finds a 0 byte (which is usually the end of the string). Our string contained code which often contains 0 bytes. So we mutated the compiled code such that it contained no zero bytes and had a carefully crafted piece of bootstrap asm to un-mutate it.

By the end, the hack looked like this:

1. Send oversized EULA

2. Overflow EULA buffer, miscellaneous data, callback handler pointer

3. Send packet to trigger handler

4. Game jumps to bootstrap code pointed to by handler

5. Bootstrap decodes payload data

6. Payload downloads and restores stomped miscellaneous data

7. Patch executes

Takeaways: Include patching code in your shipped game, and don’t use unbounded strcpy.

Jamming the cartridge

Michael A. Carr-Robb-John, Monolith Productions

In 1993 I was finishing off Desert Strike; I was doing the conversion from the 16-bit Mega Drive / Genesis to its humble little brother, the 8-bit Master System. The game was exceeding the desired cartridge size by about 12K, and going to the next size cartridge was out of the question. Today, 12K sounds incredibly small, but back then it was a major deal. During development, I had budgeted and planned all the sound and graphic resources and they were within their limits. The only section I hadn’t been so strict on was the code. In those days, games were written in assembly language — in this specific case, Z80 assembly — so I had only one option left. I spent a week going through and finding redundant code and rewriting things to use a smaller memory footprint (usually at the cost of being more processor-intensive.)

By the time I had finished, the game fit onto a cartridge with just 98 bytes! The game was burned onto ROM and tested for a few days by the chaps in QA before being submitted to Sega for certification. Unfortunately it didn’t pass on the first time, and the required fixes pretty quickly used up those 98 bytes. I think when we did publish, there were only 6 bytes free!

The Dalton Allocator

Jonathan Adamczewski, Insomniac Games

Toward the end of one project, we discovered that after playing through the game for many hours, movies would not trigger when they were supposed to. Fragmentation within one of our memory allocation heaps had made it impossible to reliably allocate the large blocks of memory that were needed for full-screen movie playback.

We needed to find a way to be sure that we could always get the memory we needed. However, it was too late in the project and too risky to consider defragmentation of the heap, we didn’t have enough spare memory available to set aside exclusively for movie playback, and taking space away from other systems at that stage was impractical.

It was clear that when movies were playing, there were many other systems sitting idle, so we gave some consideration to “borrowing” memory from them. However, these other potential sources were either too small, or else also suffered from the same kind of fragmentation problems that we were already seeing. There was plenty of free space available for the GPU, but for various reasons we could not use that for the movie-playback buffers. So we needed another source of space.

While looking into another problem, a particular pattern of memory allocations within our main game-asset heap stood out: When the game started up, a number of assets were loaded from disk, and once in memory were never modified. Some of those assets were very large. None of them were needed while a movie was playing.

This gave us an idea: What if we were to copy the contents of one of the larger asset files to somewhere else in memory? The GPU’s memory would work just fine as a place to temporarily stash the asset, and then we could temporarily reuse the space in the asset heap for movie playback, copying the asset data back from GPU memory when the movie finished.

So that’s what we did. We chose the largest set of animation clips used for one of the game’s heroes (named Dalton). The animation system was switched off, animation clips copied into the GPU’s memory space, and the memory handed to the movie-playback system. At the end of the movie, the animation data was copied back to where it belonged, the animation system restarted, and the game proceeded as if nothing horrible had happened. The implementation ended up being fairly straightforward, though the process does span a number of frames to ensure that all the systems involved are safely synchronized with each other through each step of the process.

The memory for the movie system has since been described as coming from “the Dalton Allocator” after the character whose animation clip memory was usurped.

(I’ve since discovered that there’s some history of this kind of thing at the studio — of both stashing random things in GPU memory, and failing to set aside enough space earlier in the project…)

Certification headache

Michael Carr-Robb-John, Monolith Productions

Anyone that has ever written a game on a console knows about the certification headache. For the most part, certification is simply common sense and good practices, but there are one or two “requirements” that just seem to be nothing more than a way to cause developers problems. One such requirement that we’ve had to deal with is that from the time the user chooses to run your game, you must be displaying the first presentation screen within four seconds. If you have a large executable, it can take at least two or three seconds just for it to load before you get control, and you still have to load a whole bunch of visuals and sounds in order to present the main menu.

My game was taking 26 seconds from the time the user selected the game to the time it displayed the first presentation screen, so I could already feel that headache starting. My first job was to isolate what was required to display the menus, and put off loading specific global data until it was actually needed. Surprisingly, this had a bigger impact than I was expecting; it knocked off over nine seconds. Many tweaks later, I had managed to knock it down to around 10 seconds, but I just couldn’t get it to load any faster. While discussing the problem with another engineer (best problem-solving method I have ever found), the solution dawned on us.

The specific console also has another requirement that two specific screens are displayed by your game before progressing into the menu system. What is also of interest is that the user must be prevented from skipping the screens for a set amount of time. Let’s see now — if we loaded only those two screens, and did most of the menu loading while the player is watching those screens… voila — 5.5 seconds to load and display.

Unfortunately, that still was not enough to satisfy the letter of the requirement, so we eventually had to ask for a waiver, which was granted (probably because we were so close).

Painting sounds

Edward J. Douglas, Flying Helmet Games

I was running cinematics on a long-running racing series. Our scenes were a mix of straightforward startgrids and fancier action sequences. As we iterated on further sequels, our ambitions with the scenes got greater and greater, but our technology iterated at a slower pace.

You see, the cars would be animated by a QA “stunt driver” to get the base motion, then hacked up in a 3D animation program to adjust the timing and placement of the action, and re-exported to our in-game cinematic tool where playback would simulate all the physics and engine behavior. Lots of gameplay data was captured, including gas and brake information from the controller and represented in metadata in the 3D file, then reproduced in-game. The idea was that this would drive the car audio system as well.

The problem came a few sequels down, where our scenes were very complicated, with a mix of hand-animated car action and recorded capture. The old tricks of using the engine metadata to drive simple audio rev samples for our cars wouldn’t work anymore — the data just wasn’t there! The audio team couldn’t post-process the audio like a movie, because any scene could have any car in it, depending on player’s choice and modifications, so the audio needed to be procedural. But by this time, our games had won numerous awards for audio, especially for the car engine sounds, so we were determined to make it work.

Coming on to beta, things were looking dicey, but a combination of ingenuity and madness between our cinematics, audio, and AI engineering teams found the solution. The gas and brake metadata was represented by a float scale on a cube in the 3D scene. If an artist went in and “drew” curves in a keyframe editor like 3DS Max, they could draw in the car engine sounds they wanted. A few members of the audio team rushed to learn 3DS Max, and by using their intuition of how rev patterns should look, they drew in the animation, exported all the scenes, and squeezed it all in in time. It sounded great, but after this last-minute hack, we knew we’d need something more robust if we’d continue with the same tech-base for the next sequel.

…Or so I thought. I left the studio after that game, and a few years later I met an audio guy who had joined that team after I left. It wasn’t long before I realized they never upgraded the tech, and he was the “engine rev painter” guy for the latest sequel.

…And one for good luck

Richard Morwood

I had a list of background textures, and I coded the game to show each one as they scrolled across the screen. One of my background images was being skipped and I couldn’t figure out why, even after spending a lot of time debugging. Deadline was five days away, so I just stuck an extra reference to the texture in the background list. Ta-da! No more “skipped” background. :)

HR hacks

Ben Burbank

When I used to work for a very big company, one of the employees figured out that the best way to advance his career was to write negative performance reviews for as many co-workers as possible. This resulted in him receiving a higher annual staff ranking, which in turn led to larger bonuses and stock grants. It eventually becomes difficult, he told me, because you need to make sure to only review people with different managers, so nobody can catch on to your ruse. My trick for avoiding this cycle was to quit and go work someplace much smaller and awesome.

Honorable mention: Nice save

Chris Pruett, Robot Invader

[Editor's note: This isn't, strictly speaking, a dirty game dev trick -- but we figured it's a handy way to use job skills for real-world problems. Also, it's a sweet story.]

My wife doesn’t play a lot of video games, but one series she’s been hooked on since childhood is Dragon Quest. A few years ago, she started playing Dragon Quest VII on my aging PlayStation. After putting about 80 hours into it (which, as I understand it, is about three-quarters of the way through the main quest), she discovered, to her horror, that her save file had become corrupted. It appeared in the continue menu, but was grayed-out and could not be selected. She was devastated. She was angry. She swore never to play games again.

I found a used DexDrive, a device for reading and writing PS1 memory cards with a PC, on eBay for $15. I didn’t tell my wife that I was trying to fix her save — I didn’t want to get her hopes up and I didn’t actually think it would be possible. Presumably the data was irrecoverably damaged, a lost cause. On the other hand, I thought, it couldn’t hurt to try.

With the DexDrive, I was able to dump the broken save to a PC and examine it in a hex editor. I ended up printing it out and marking the hex up with a highlighter; though PS1 saves came in 8kb blocks, printing 8kb as 16-columns of hexadecimal data comes out to a lot of pages. Working with an unofficial spec written by the author of a PS1 emulator, I located the main chucks of the data: the header, the icon image, and lastly, the save data itself. Unfortunately, decoding the raw game state data proved challenging; after a few days I decided that it was going to require a lot more work than I had planned.

Instead, I concentrated on the header portion of the data. Because of the placement of the icon (which is at a consistent offset from the top of the file and easy to identify as pixel data in hex), I could tell exactly where the header started and stopped. If the continue menu could tell that the save was busted, maybe it was just the header that was broken. I tested this theory by copying the header data from some other save I got off the internet, and pasting it over the header section of my wife’s broken save. Then I saved this data back to the memory card and loaded it up.

Miraculously, it worked. The continue menu showed stats from the other save, but once loaded her game was completely restored. Between ordering the DexDrive and patching the save, the whole process had taken me about three weeks. That night I booted the game up and showed her the continue menu with the strangely named save. She loaded it up and was very surprised to find her progress, her characters, her stats, and her items all as she left them. She was pretty excited, but before we could talk about it she was off to complete another dungeon.(source:gamasutra)

 


上一篇:

下一篇: