Crash Bandicoot 游戏封面


25 年前,开发者是如何将游戏塞进那么小的内存中的?Quora 上,这个问题获得了 50 万人的阅览,Dave Baggett 对问题的回答也获得了六千多的点赞,其中不乏游戏大师。

问题描述

家庭游戏系统软件采用了 64K~128K 的磁卡(cartridge),然而却能够提供玩好几个小时的各式各样的图形、精灵鬼怪和声音。游戏系统好像要提供大量的功能(功能性的函数、库、硬件加 速和图形指令等等)似的,大量的图片、音乐和音效、动画效果、游戏算法能放入如此小的存储空间中,是多么得令人吃惊,更别提是 25 年前!

上面提到的存储空间大小目前看来也就等同于一个采用中等分辨率压缩(moderate-resolution compressed)的 JPEG 文件——一张图片而已。我十分好奇,在那个年代软件开发究竟是怎么一回事。我坚信在当时,开发者肯定没有一个所谓编写开源软件的协作开发环境,更别提在那 样一个软件开发能收获巨大经济回报的时代。

我十分好奇,那个年代的开发者究竟基于哪些知识、技术、想法或者洞察力完成了这样的开发。有没有可能一些想法已经丢失或者没有被记录下来?曾经 的电子游戏种类如此丰富,并且使数以百万的人花费数百小时在上面获得快乐,更别提游戏开发采用了这样高效的方式——这显然是一项壮举。这种效率让我想起了 录制音乐 demo。结合这些,我想提出下列的问题:如何更好理解计算机科学的原则和技术的使用方式,比如,如何将 64K 的 demo 进行编码。

这个问题的重点是那个时候的专业技能:那时的开发者为何如此成功?他们使用了哪些已经失传的技术、解决办法,或者算法技巧?

Dave Baggett 的回答

下面是 20 世纪 90 年代末的一个相关轶事。当时,我和 Andy Gavin 共同为 PS1 编写游戏“古惑狼”(Crash Bandicoot)。

在当时,RAM 依然是最主要的问题。PS1 只有 2MB 的 RAM,然而我们不得不做一些疯狂的事情使游戏适配硬件。我们的游戏数据大约有 10MB 大小,所以我们不得不进行动态的分页输入输出(paged in and out dynamically),虽然加载滞后帧速率就会下降到 30Hz,但是我们并没有任何故障。

之所以能成功运行,是因为 Andy 写了一个令人难以置信的分页系统,可以将 64K 数据页进行交换,从而作为古惑狼这款游戏的数据遍历水平。这就是当时的 “全栈”能力,在这个分页系统中,运行了上至高级内存管理,下至操作码级别的直接内存访问系统(DMA)的全部代码。Andy 甚至控制了 CD-ROM 磁盘上字节的物理布局,这样一来,即使磁盘的速率是 300KB/s,PS1 还是能在游戏执行到某个位置时加载到相应的数据。

我当时主要负责编写打包工具,这个工具的功能是将资源文件,比如声音、图形图像、小动物的声音控制代码(译者注:lisp control code)等打包为 64K 的数据分页,塞进 Andy 的系统当中去。(顺带一提,这个问题——将任意大小的对象打包成固定大小的数据分页,生产数据包——是一个 NP 完全问题,所以看起来在合理的时间或者线性复杂度下得到最优解是不可能的。)

然而有些时候算法并不合适,我的打包工具采用了各种各样的算法(如最先适配、最好适配(first-fit,best-fit)等等),只为找 到最好的打包方案,包括使用随机搜索类似于 Simulated annealing 中用到的梯度下降的过程。基本上,我写了一大堆不同的打包策略,一一尝试,并择优选择。

像那样使用随机指导搜索(a random guided search)的问题在于,你永远不知道你能否再次得到同样的结果。有些古惑狼的关卡只能靠“碰碰运气”来进行随机打包,并放入最大允许页数(我印象中是 21)。这意味着,一旦你将这个关卡打包,可能更改了一个乌龟的代码,就永远不会再找到这个 21-分页的数据包了。有几次,一个艺术家修改一些内容,就会毁掉现行的分页计数,所以我们不得不半随机似的改变其他内容,直到打包器能再次找到可用的数 据包。并且我还要在凌晨 3 点给这个倔强的艺术家解释清楚。

现在回忆起来,到目前为止最好的部分,也是当时最糟糕的部分,正是使核心C/程序集代码(C/assembly code)适配。那时距离“最终测试版”的发版期限没有几天了,而这几天是我们抓住假期发行游戏的最好机会,在此之前,我们失去了整整一年的时间。当时我 们正在将语义上相同,而语法上具有不同表现(semantically identical but syntactically different manifestations)的C语言代码进行随机排列(permute),以此希望编译器能够生成 200 字节、125 字节、50 字节然后是小于 8 字节的代码。

作为当时排列所采用的方法“for (i=0; i < x; i++)”——如果我们采用上面用到的变量,并使用 while 循环来重写这段方法,以用作他用,那么会发生什么呢?这是我们尝尽各种一般方法——比如像将数据塞进指针的最低两位(这个方法只能在 R3000 上生效,因为所有的地址都是 4 字节对齐的(4-byte aligned))——之后的解决之道。

最终,古惑狼成功了的适配了 PS1 的内容,还多出了 4 字节的空闲空间。是的,2097152 之外的 4 字节。那真是美好时光啊。

作者:张帆

来源:51CTO

25年前,开发者如何将游戏塞进内存?相关推荐

  1. QQ把游戏放进聊天框,这一点Facebook和微信都没做到

    从张小龙的一条朋友圈开始,再到各类"操作指南"的发布,短短两天,微信小程序就成功吸引了所有人的注意力,很多评论者将之视为"解放手机内存的杀手锏",对社交场景的这 ...

  2. 微电脑世界:25年前和后 信息技术50年

    微电脑世界:25年前和后 信息技术50年   http://www.sina.com.cn 2004年02月11日 10:10 微电脑世界   微电脑世界 2004年2月封面 在岁末年初,包括本刊在内 ...

  3. 独立开发者分享:游戏本地化的6个建议

    在进入不同市场的时候,游戏本地化尤为重要,对于一款游戏在海外市场的表现起着决定性的作用.最近,海外独立开发者在博客中分享了自己的一些游戏本地化建议,希望可以为尝试本地化的童鞋们带来帮助,以下请看Gam ...

  4. 为什么游戏开发者不玩游戏_什么是游戏开发?

    为什么游戏开发者不玩游戏 Game Development is the art of creating games and describes the design, development and ...

  5. 雷军自曝25年前旧照 网友发现端倪:25年前就有MIX 2S了?

    五一假期各位有没有出去跨越山和大海去看人山人海呢?肯定也有不少朋友和小编一样宅在家里不想出门,也不想明白灭霸的感受,毕竟灭霸是个反派. 五一大家都放假了,然而大佬却没有闲着,最近雷军频繁的在网上和米粉 ...

  6. 暗影之枪显示连接服务器失败,暗影之枪传奇进不去怎么办?游戏更新进不去问题详解[多图]...

    暗影之枪传奇有时候会发现进不去游戏,因为这是国外服务器,特别是更新之后,这时候要怎么办呢?下面是友情MT为大家带来的暗影之枪传奇游戏更新进不去问题详解,希望能帮助到大家! 暗影之枪传奇进不去怎么办? ...

  7. 如何成为一位Unity3D游戏开发者:对游戏开发抱有热情

    如何成为一位Unity3D游戏开发者:对游戏开发抱有热情 随着3D技术应用的越来越广泛,对于3D大家有怎样的体验?在日常生活中,能体验到3D技术的方式不少,但是运用比较广泛的应该是--3D电影!通过一 ...

  8. 把路由器塞进弱电箱——以京东云无线宝一代为例

    把路由器塞进弱电箱--以京东云无线宝一代为例 把无线宝塞进弱电箱需要几步? 打开弱电箱 放入无线宝 关上冰箱,不,弱电箱 前言 开头先讲了一个烂梗,那就废话不多说直接进正文.本文涉及到的京东云无线宝参 ...

  9. 吃鸡进游戏显示错误服务器繁忙,绝地求生游戏崩溃进不去怎么办 服务器炸了繁忙解决方法...

    绝地求生PC1.0版本,尤其是国服开启后,许多玩家遇到了游戏崩溃.进不去,以及服务器炸了.繁忙.登不上去等情况.作为一个大型吃鸡手游,绝地求生公测后诸多问题倒是不难理解,不过进不去登不上这些问题要怎么 ...

  10. 25个不错PHP的游戏编程脚本代码分享

    本文介绍了25个不错PHP的游戏编程脚本代码,包括简单的掷骰器.随机名称生成器.场景生成器.牌组创建器(Deck builder)和装备(shuffler).简单的扑克发牌器.Hangman游戏.纵横 ...

最新文章

  1. django 增加验证邮箱功能
  2. IMAX融资5000万美元,三年内要打造25个VR项目
  3. 单例模式 之 单例模式——懒汉模式
  4. 【SD】自定义销售订单审批状态
  5. Spring boot MultipartResolver
  6. 微信小程序UI------实现携程首页顶部的界面(弹性布局)
  7. C++语言,线性素数筛(欧拉筛)
  8. 2015.3.12Arinc424 Tools中SiniArincCls.csParserFile(string sFile)函数正则表达式理解
  9. kali linux怎么安装无线网卡驱动,Kali Linux 安装BCM43142网卡驱动
  10. r语言导入ggplot2_R语言绘图之ggplot2包
  11. 阿里云python中文社区_python 写中文
  12. android窗帘拉开动画,Android 窗帘(Curtain Menu)效果五之应用场景和使用方法
  13. Mbps、Kbps、bps、MB、KB、B、b的区别
  14. 魔兽世界诞生记(下)
  15. GWAS相关名词解释及基础知识储备[长期更新]
  16. 如何理解矩阵的「秩」?
  17. 商标销售可以是有利可图的业务
  18. SQL注入系列之环境搭建(一)----ASP+ACCESS注入环境搭建
  19. 什么是CT 技术。。。你懂了么?
  20. 收购Five9被称为“天作之合”,Zoom能否靠买买买换来高增长?

热门文章

  1. IDEA 重复执行 updating indices问题
  2. c语言字符串的加减乘除,c语言加减乘除代码
  3. win7取消计算机密码怎么设置,Windows7取消开机密码怎么设置_Win7怎么取消开机密码?-192路由网...
  4. android 距离感应器控制屏幕熄灭_华为nova3e、小米6X、OPPOA7x对比,选IPS屏幕还是TFT屏幕,自选...
  5. 兔子生兔子java_用Java编程计算兔子生兔子的问题
  6. C语言解决狐狸找兔子的问题(数组)
  7. VMware虚拟机不能上网了怎么办
  8. c语言学习体会300字,大一个人总结自我评价300字_大学生学年自我鉴定评价
  9. 思科路由器的介绍及实战
  10. 泰克示波器3系MDO再次升级,使EMI测试不再求人