相关影像
快速入门
PlayStation 2 并非当年的最强主机,却积累了其它公司无可企及的人气。
与初代 PlayStation 相比,二代的架构更加复杂,但成功逃离了架构一样复杂的世嘉土星的厄运。
中央处理器 (CPU)
在这款游戏机的核心部分,我们发现了一个名为情感引擎(Emotion Engine,“EE”)的强大封装,这个芯片是东芝和索尼的一个联合项目[1],运行频率约为294.91MHz[2]。
该芯片组包含众多组件,主CPU就是其中之一。 其余部件则供CPU使用,以加快某些任务的执行速度。 为了便于分析,我们将EE分成三个部分:
- 领队: 控制整个芯片的主要组件。
- 可用内存:使处理器可进行有意义运算的关键部件。
- 协处理器: 这些处理器可加速特定计算。
领队
简而言之,主CPU采用MIPS R5900,这是专为这款游戏机设计的MIPS内核。 你可能还记得,索尼在初代PlayStation上就开始使用MIPS芯片(我们可以找到来自LSI的第二个MIPS芯片R3000A)。 对于下一代产品,我们已经有了一个MIPS “R5900”……但这个名字对我们意味着什么呢?
为了了解新数字背后隐藏的信息,让我们回顾一下那个时代的历史。
超越成功
MIPS R4000是一个广受欢迎的CPU系列,被众多系统所采用,其中包括一个强劲的竞争对手。 由于它的成功,MIPS为大众带来了一系列曾经买不起的先进技术(64位计算、8级流水线等)。
1995年,随着**R10000的发布,MIPS实现了又一次飞跃。 现在,在SGI(硅谷图形)的资助下,MIPS生产了一种新的处理器,将R4000的并行能力提升了“数英里远”,首次推出了这些技术[3]:- 推测执行: 在计算条件分支之前,CPU会预测其结果。 预测结果基于存储在内部512条目的表中的先前结果。 一旦计算出条件,如果预测结果正确,CPU就节省了宝贵的时间。 否则,多余的计算将被丢弃。
- 4个超标量流水线: 在流水线设计的基础上,CPU 现在会在流水线的起点获取多达四条指令,并将它们分配到不同的单元,使CPU可以同时执行这些指令。 这样,CPU就实现了更高程度的并行性。
- 乱序执行: CPU还会重新排列指令顺序,尽量填满其单元(只要不增加冒险)。
- 配备128位总线的二级高速缓存(L2 cache),可一次将更多数据输入中央处理器,这是在前面改进的基础上提出的要求。
然而,这种创新是以复杂的设计为代价的,最终产品的价格并不便宜。 SGI只将其捆绑在高端设备中,任何将其引入家用游戏机的尝试都是不可能的。
面向大众的高端产品
SGI/MIPS已经意识到R1000 在商业上的局限性,因此聘请Quantum Effect Devices(QED) 为中低端市场开发经济实惠的R10000版本。 作为一家由MIPS前员工创办的公司,QED的业务是为经济型市场设计MIPS内核的变体。
最终,QED推出了名为R5000的新内核,这是一个经过大幅阉割的R10000内核[4]:
- 乱序执行恢复为顺序执行。
- 取消了推测执行。
- 超标量性仅限于两条指令(2-issue),不再并行化整数指令。 不过,浮点指令仍可与其他指令配对执行。
- 由于之前的阉割,L2 Cache被阉割为64位总线。
因此,它成为了为经济型设备(如SGI的低端工作站)提供动力的理想CPU。 无论如何,请注意,削减后的流水线仍然可以执行并发浮点运算,似乎QED打算将其作为矢量/3D应用的一个有吸引力的产品。 你很快就会发现,另一家公司也很快注意到了这一点。
顺便提一下,在技术池的另一边,也有类似的进步,但方向正好相反:ARM与DEC联手将ARM芯片推向高端市场。
索尼的特别订单
东芝获得MIPS许可证已有一段时间[5],对生产MIPS变体和封装并不陌生。 索尼和东芝一度联手为索尼即将推出的游戏机生产专用CPU。 这给东芝带来了巨大的好处:CPU通常需要满足来自不同利益相关者的各种要求,这样就限制了专用化的机会。 现在,CPU只有一个用途:跑3D游戏。 因此,这为各种创新提供了足够的空间。
尽管如此,东芝最终还是采用了经济实惠的R5000设计,并对其进行了调整,以加速矢量运算。 新内核被命名为R5900,并首次推出了以下“3D”增强功能[6]:
- MIPS III ISA的变体。 这包括以前在任天堂64上看到的原始64位ISA,但扩展了有趣的操作码。 索尼从MIPS IV中添加了一些指令(预取和条件移动),以及他们自己的SIMD扩展指令,称为多媒体指令,用于加速矢量计算(类似于SH-4,但只有整数指令)。
- 多媒体指令仍为32位宽,但一次最多可操作三个128位向量。 它们提供的操作包括矢量算术、取最小/最大和多种标量组合,以形成新的矢量。
- 32个128位通用寄存器: 东芝品牌的又一重大改进。 抛开典型的32位存储空间不谈,我们现在已经跨入了128位领域。 尽管如此,大多数操作都很难使用所有可用空间(MIPS字长仍为64位)。 这时,前面提到的多媒体扩展功能就会发挥作用,因为它的指令集将充分利用扩展寄存器文件。
- 使用新指令时,每个寄存器可以存储由多种标量(从两个64位整数到16个8位整数)组成的向量。
- 为防止性能下降,这些寄存器通过128位总线访问,而CPU的其他部分则使用内部64位数据总线。
- 两个64位ALU。 每一个都可以独立运算64位整数,但也可以组合成128位ALU。 后者是闪耀的多媒体操作码背后的大脑。
除此以外,我们还发现了开发人员可能欢迎的其他改进:
- 6级流水线: 与前代产品相比,增加了一个阶段。
- 双路超标量执行: 由于采用了两个ALU,现在最多可以并行执行两个64位整数运算。
- 这恢复了MIPS R10000失去的另一个优势。
- 24 KB一级高速缓存(L1 cache): 其中16 KB用于指令,8 KB用于数据。
- 电路还实现了预取功能,在指令和数据被请求之前对其进行缓存。 这是通过额外的逻辑来实现的,该逻辑可识别内存中哪些位置更常被请求。
- 16 KB的Scratchpad RAM,也称为“快速RAM”。
- 内存管理单元: 内存访问与系统其他部分的接口。
此外,内核还配有一个专用浮点运算单元(称为“COP1”),用于加速32位浮点数(在C语言中也称为float
)的运算。 这是一个特殊的区块,因为它不遵循IEEE 754标准,最明显的是它没有无穷大(infinity
)(而是计算为0
)[7]。 除此之外,它还有32个32位寄存器。
可圈可点的内存取舍
Emotion Engine旁装有两颗各16 MB的内存芯片,总内存共计 32 MB。 使用的内存类型是RDRAM(似曾相识!(译注:原文为déjà vu,容易让人想起一首已成为meme的eurobeat)),通过16位总线访问。
乍看之下,Emotion Engine的内部总线只有128位宽,并无亮眼之处。 不过,RAM芯片采用了双通道架构,即使用两条独立的16位总线(每个芯片一条总线)连接两个芯片,以提高数据吞吐量。 这一布局理论上可达到3.2 GB/秒的带宽。所以大可放心,这款主机不存在内存延迟问题!
在EE的一角,有一个功能强大的DMA控制器或者叫“DMAC”,用于在主内存和Scratchpad之间或主内存和EE内部任何组件之间传输数据。
数据传输以128位为一批,但有趣的地方就在这里: 每八个批次,主总线会暂时解锁。 这就为并行执行其他DMA传输(最多十次)或让CPU使用主总线留出了一个小窗口期。 这种工作方式被称为切片模式,是该DMA单元的多种可用模式之一。 请注意,虽然切片模式可以减少主总线上的停滞,但其代价是降低整个DMA传输的速度。
汲取历史教训
不管我们愿不愿意,随着EE内部数据流量的增加,这种设计最终将承受统一内存架构(Unified memory architecture,“UMA”)带来的后果。 这就是:多个独立组件试图同时访问主内存,从而造成拥塞。 为了解决这些问题,索尼通过以下方法缓解了对内存的持续需求:
- 用大量高速缓存裹着处理器。 因此,只有在绝对必要的情况下,才需要访问主存储器。
- 本文中提到的99%的缓存/Scratchpad的设立都是出于这个原因。
- 添加128字节回写缓冲区(Write Back Buffer): 与“写入收集管道”(Write Gather Pipe)非常相似,但它不会等到25%满了再写,而是会先检查总线的状态(即拥挤还是空闲)。
这对于能从缓存中获益的应用程序来说,听起来非常方便,但对于那些根本不应该使用缓存的任务(如操作显示列表),又该怎么办呢? 幸运的是,CPU提供了一种不同的内存访问模式,称为“未缓存”(UnCached),它只使用回写缓冲区。 因此,它不会浪费周期来修正缓存(缓存未命中的产物)。
此外,还提供未缓存加速模式。 这种模式增加了一个缓冲区,以加快读取内存中连续地址的速度。
其他有趣的部分
在同一个EE封装中,还有一个名为图像处理单元(Image Processing Unit,“IPU”)的处理器,这次是为图像解压缩而设计的。 作为MDEC的继任者,IPU在游戏需要解码MPEG2影像而不占用主CPU时非常有用。
长话短说,游戏向IPU发送压缩图像流(希望使用DMA),然后以GPU可以显示的格式解码。 PS2的操作系统也依赖IPU提供DVD播放功能。
最后,IPU还能运行压缩的高分辨率纹理,从而节省CPU使用量并减少大量传输。
协处理器
距离竞争对手推出最新产品已经过去两年了。 如果您读过前一篇文章,刚刚开始读这篇文章,我想您还在等待“那个东西”,它能让PS2变得像当年一样强大。 现在,让我来介绍一下索尼在情感引擎中安装的一套非常重要的组件——矢量处理单元(Vector Processing Units,“VPU”)。
架构
矢量处理单元是一个独立的小型处理器,专门用于处理矢量,尤其是由四个float
组成的矢量。 这些处理器速度极快,每次操作只需一个周期,这对于几何图形的处理极为方便。 尽管它们表现出与CPU的FPU类似的非标准化行为。
矢量单元由以下部分组成:
- 矢量单元内存(Vector Unit Memory,“VU Mem”):用作矢量单元的工作空间。 它存储操作所需的值和/或先前操作的结果。
- 矢量单元: 处理器的核心。 它包含一些内存(称为微内存(Micro Memory)),用于存储程序(称为微程序(Microprogram)),指示矢量单元如何操作矢量单元内存中的数据。
- 它采用64位ISA,执行单元分为两个并行的子单元。 第一个子单元进行浮点数乘法或加法运算,而另一个子单元则进行浮点数除法或整数运算。这样就可以同时操作浮点数和整数。 这样就能同时操作浮点数和整数。
- 矢量接口:自动将来自主存储器的顶点数据解压缩为矢量单元可以理解的格式。 该单元还可将微程序传输到微型存储器。
功能
要开始工作,需要“启动”矢量单元。 为此,主CPU负责提供微代码。
EE中安装有两个VPU,但它们的安排方式不同,因此有不同的用途和优化方式。
矢量处理单元0
第一个VPU(VPU0)位于CPU和另一个向量单元(VPU1)之间。 它为主CPU提供“辅助”作用。
VPU0 有两种工作模式:
- 微模式: 这是“传统模式”。 VPU将独立执行存储在微存储器中的微程序中的“微指令”。
- 宏模式: VPU0成为主CPU的“COP2”,执行通过专用128位总线从主CPU接收的 “宏指令”。
- 宏指令的功能与微指令相同,但使用不同的操作码。 不过,VPU执行单元不再被分割(这意味着它一次只能执行一条指令)。
- 虽然这种模式不能充分利用VPU0的所有组件,但仍能加快CPU的矢量运算速度。 此外,就简便性而言,协处理器比独立单元更容易编程(PC程序员会发现这一点很有帮助)。
VPU0的内存映射还可以访问其他VPU的某些寄存器和标志,大概是为了检查其状态或快速读取其他VPU的某些操作结果。
无限世界
过程生成是这些单元可以利用的一种有用方法。 换句话说,与其使用硬编码几何图形构建场景,不如让VPU使用算法生成场景。 在这种情况下,VPU通过计算数学函数来生成几何图形,然后由GPU进行解释(如三角形、直线、四边形等),最终用于绘制场景。
与使用显式数据相比,过程生成内容是并行化任务的理想选择,它可以释放带宽,只需很少的存储空间,而且是动态的(程序员可以设置参数来实现不同的结果)[8]。 许多领域都能从这种技术中获益匪浅:
- 复杂曲面(如球体和车轮)。
- 世界渲染(如地形、粒子、树木)。
- 贝塞尔曲线(Bézier curves),计算机图形学中用于绘制曲线的一种非常流行的方程。 这些曲线被转化为贝塞尔补丁(显式几何体),并根据所需的细节程度支持不同的精度。
另一方面,过程生成内容可能难以处理动画,如果算法过于复杂,VPU可能无法在所需时间内生成几何图形。
总之,程序渲染并不是一种新技术,但由于VPU的出现,它为进一步优化和丰富图形打开了大门。 尽管如此,程序渲染技术的实现并不简单,索尼研发部门发表了多篇论文,介绍了在其游戏机上使用的不同方法[9]。
由您定义工作流程
有了这些新功能,程序员在设计图形引擎时就有了很大的灵活性。 为此,索尼投入了更多资源来设计和记录高效的流水线设计。 以下是针对不同类型工作负载进行优化的图形流水线示例[10]:
在第一个并行设计示例中,CPU与宏模式下的VPU0结合,与VPU1并行生成几何图形。 CPU/VPU0组充分利用Scratchpad和高速缓存,避免使用主总线,而VPU1则依靠主内存获取数据。 最后,两个渲染组同时向GPU发送各自的显示列表。
第二个例子是串行设计,它提出了一种不同的方法,即CPU/VPU0组作为VPU1的预处理器工作。 第一阶段将获取并处理所有几何图形,然后由VPU1将其转化为显示列表。
以上是从理论角度举例说明的,但为了解释更“实际”的实现方法,我将参考Jon Burton发布的一段视频,内容涉及他们开发的一款PS2游戏[11]。
Travellers Tales的前总监解释了他的团队是如何在VPU1中实现完全封装的粒子系统的。 简而言之,VPU1主要是从其VU内存中读取一个预先填充的数据库,该数据库用于计算任何给定时间内粒子的坐标,而无需依赖任何其他组件。 操作结果可以转化为显示列表并立即发送。
通过这种方法,CPU的负荷大大减轻,从而可以执行AI和物理等其他任务。
这样的例子还有很多,但总而言之: 现在,程序员可以找到最佳的设置,这是一件好事。
图形
考虑到EE所做的一切工作,是否还有什么遗漏? 其实就是最后一步: 显示!
这有个简单而快速的专用芯片: 图形合成器(Graphics Synthesizer,“GS”),运行频率约为147.46 MHz。 它内置4 MB DRAM,可在内部进行所有处理。 因此,无需访问主内存。 嵌入式RAM(eDRAM)根据所需的数据类型使用不同的总线连接。
与本网站之前评测过的其他图形系统相比,GS的功能较少。 不过,它的运行速度非常快。
架构设计
GPU只进行光栅化处理,即…… 生成像素、贴图、应用光照和其他一些效果。 这意味着没有顶点变换(这些由VPU完成)。 此外,这是一条固定功能流水线,因此也没有花哨的调整或着色器,只能使用固定的着色模型(如高洛德(Gouraud)着色)。
看起来很简单吧? 那么,让我们深入了解一下每个阶段会发生什么。
预处理
EE通过向嵌入式DRAM中填充所需素材(纹理位图和颜色查找表,后者也称为“CLUT”)来启动图形合成器,为GS的寄存器赋值以对其进行配置,最后发出绘图命令(显示列表),指示GS在屏幕的特定位置绘制基元(点、线、三角形、精灵等)。
此外,GS还会预处理一些后续计算所需的数值。 最值得注意的是数字微分算法值,它将在绘制过程中用于插值。
光栅化
着色器利用之前计算出的值,从基元生成像素。 该单元可同时生成8个像素(带纹理)或16个像素(不带纹理),每个像素条目都包含计算出的以下属性:
- RGBA: 对应于红、绿、蓝和Alpha(透明度)的梯度。
- Z值: 用于后一阶段的深度测试。
- 雾: 可选项,用于模拟环境中的雾。
- 纹理属性: 包含将在下一阶段使用的纹理在DRAM中的地址和其他属性(坐标、详细程度、滤镜等)。
它还会执行剪切测试(Scissoring Tests),根据X/Y值剔除框架区域外的多边形,某些像素属性会转到“像素测试”阶段进行进一步检查。 此外,还可从Gouraud和Flat两种选项中选择一种进行照明。
然后,数据包被传送到“纹理贴图”引擎,但每个属性都由一个专门的“子引擎”来操作,这样就可以并行处理不同的属性。
形成纹理
该阶段由一个大型像素单元驱动,一次最多可计算16个像素,在这里纹理将被映射到多边形(即现在的像素)上。 此外,这里还应用了雾和抗锯齿效果。
纹理映射是从DRAM中定义为纹理缓冲区的区域获取的,不过该区域与一个名为纹理页缓冲区(Texture Page Buffer)的独立区域相互连接,后者似乎是一种纹理缓存机制。 CLUT也使用该页面系统进行映射。 这两个元素都使用512位总线进行检索。
像素单元执行透视校正,将纹理映射到基元上(与之前的仿射映射方法相比,这是一项重大改进)。 此外,它还提供双线性和三线性过滤功能,后者与混合映射纹理一起使用。
测试
在这里,如果某些像素不符合某些要求,就会被舍弃。 因此,将进行以下测试:
- Alpha测试: 将像素的Alpha值(透明度)与 “标准”值进行比较。 这是因为在某些情况下,要求Alpha值在一定范围内或大于/小于任意值。
- 目的地 Alpha 测试: 在将像素绘制到帧缓冲区之前,再次检查像素的Alpha值。
- 深度测试: 将像素的Z值与Z缓冲区中相应的Z值进行比较。 这样可以避免处理隐藏在其他像素后面的像素。
后后处理
GS内部有一个名为可编程CRT控制器(Programmable CRT Controller,“PCRTC”)的专用组件,可将内存中的帧缓冲区发送到视频输出端,这样就能在电视上看到帧。 但这还不是全部:它还包含一个名为合并电路(Merge Circuit)的特殊块,可以将两个独立的帧缓冲区进行Alpha混合(如果游戏想重复使用上一帧来形成新的帧,它就很有用)。 生成的帧可以通过视频信号输出和/或写回内存。
更好的模型
尽管如此,这肯定会给已经闻名遐迩的角色带来更好的设计。 来看看这个“前后对比”吧:
线框 | 表面 | 纹理 |
点击启用交互功能 |
732个三角形
线框 | 表面 | 纹理 |
点击启用交互功能 |
2226个三角形
以下是新游戏系列中的角色,这些角色的建模从头到尾都非常精细:
线框 | 表面 | 纹理 |
点击启用交互功能 |
2744个三角形
线框 | 表面 | 纹理 |
点击启用交互功能 |
2700个三角形
值得一提的是,勇者斗恶龙等游戏采用了一种名为卡通着色/三渲二(Cel Shading)的自定义光照模型(我之前提到过这个术语),不过我在之前的文章中解释过,这主要是由GPU负责的。 在PS2中,所需的色彩计算大概是由Emotion Engine完成的,因为GS不像其他GPU那样灵活。
视频输出
如前所述,PCRTC通过视频信号发送帧缓冲。 该接口可使用多种格式播放视频(可与任何地理区域的电视机配合使用)[12]:
- PAL:以50 Hz的频率发送高达640x512像素的逐行扫描(576p)或隔行扫描(576i)。
- 市场上没有游戏使用576p。 虽然有些游戏支持逐行模式,但使用的是480p模式。
- NTSC:最高640x448像素,60 Hz,逐行扫描 (480p) 或隔行扫描 (480i)。
- VESA: 最高1280x1024像素。
- 数字电视(DTV): 在逐行模式下最高可达720x480像素,在隔行模式下最高可达1920x1080。
- 通过调整PCRTC设置,游戏也可以强制输出1080p格式。 不过,这种模式没有文档记录,因此会出现不可预知的行为。
- 这是否意味着PS2可以“显示高清”? 从技术上讲……是的,但我认为大多数游戏工作室都不会冒着性能下降的风险,去采用一种尚未普及的格式。
可供选择的模式很多,但归根结底都是2000年代初采用的格式,这就把范围缩小到了PAL和NTSC。 此外,尽管PAL提供了比NTSC更高的分辨率,但一些NTSC游戏的欧洲版本还是采用了遮幅(letterboxing)方法来掩盖未使用的水平线,并降低刷新率以适应50Hz的限制(我称这些为“差劲的移植”!)。
视频输出端口(多路A/V端口)非常方便。 它可以传输RGB、色差、S-Video和复合视频信号。 因此,所有重要的信号都在这里,无需专用适配器或内部修改。
音频
新音频芯片是旧SPU的增量升级版,称为……SPU2! 改进之处包括内置2 MB内存和48个可用通道(是原来的两倍)。
SPU2内部有两个声音处理器,分别称为CORE0和CORE1,运行频率约为36.86 MHz。 每个处理器处理24个声道。
奇怪的是,这仍然是两个独立的处理器,要对它们进行配置,必须更改它们的寄存器。 不过,索尼提醒开发人员,两组寄存器的设置必须有1/48000s的间隙。 如果操之过急,SPU2的行为将变得不可预测!
SPU2继承了原始SPU的相同效果。 提供的内存用作“工作区”: 您可以存储原始波形数据,并分配额外空间对其进行处理和应用效果。
最后,芯片可以混合所有通道,提供立体声输出。 现在,有趣的部分来了:SPU2可以将混音后的立体声采样作为新的输入,这使得EE可以访问这些采样(例如,将其与更多音频混合),或继续添加更多效果(如混响、回声和延迟)。
音频输出
音频信号可经由两种渠道输出:
- 数字音频: 称为索尼/飞利浦数字接口或“S/PDIF”。
- 模拟音频:通过数字模拟转换器输出到 A/V 端口。
I/O
最初,PS2的I/O接口并不特别复杂。 然而,该游戏机的后续改版彻底打乱了内部和外部设计。 因此,总体而言,这款游戏机的I/O形式多种多样,分布在不同的版本中。
特殊CPU
首先,有一个专用处理器负责协调不同组件之间的通信,这个CPU就是PlayStation 1中基于MIPS R3000的原版核心。 这次,它被称为I/O 处理器(I/O Processor,IOP),运行频率为37.5 MHz,连接32位总线[14]。
IOP 通过一个名为系统接口(System Interface,“SIF”)的专用I/O接口与情感引擎通信,两个端点都使用各自的DMA单元在彼此间传输数据。 IOP还配有专用内存,即2 MB EDO RAM(与PS1类似),用作缓冲区。
总之,该处理器可以访问前端端口、DVD控制器、SPU2、BIOS ROM 和PC卡插槽。
尽管如此,在薄型机改版一年后(2005年),IOP被SoC取代,取而代之的是PowerPC 401“Deckard”(用于微控制器的PowerPC 601阉割版)、4 MB SDRAM(比以前多2 MB)和以太网收发器(以前在外部附件中)。
继承兼容性
对于那些捆绑了前代CPU的机型,我们可以猜测,PS1兼容性也是其中的一部分。 索尼确实捆绑了一个PS1模拟器(名为PS1DRV
),只要插入PS1光盘,它就会加载。 在这种情况下,IOP的频率会降低,以PS1的速度运行,EE 会被“再利用”以模拟旧的GPU,SPU2会被重新映射,以类似于原版SPU。
对于基于PowerPC的机型,向后兼容性依然存在,但要通过完整的软件实现。
接口
这款游戏机保留了原版PlayStation的前端端口,同时还配备了几个 “实验性”接口,这些接口最初看起来非常有前景。
最受欢迎的是两个USB 1.1端口。 其理论速度为12 Mbps,但这在很大程度上取决于IOP的带宽(往往要慢很多)。 尽管如此,它还是被第三方配件广泛采用。
还有一些“实验”并没有持续很长时间。 例如,前置i.Link端口(也称为IEEE 1394端口,或苹果世界中的“火线”(FireWire))。 该端口曾用于连接两台PS2进行本地多人游戏,但在第三次改版后被取消(可能被“网卡”取代,详情见下文)。
不同寻常的以太网和硬盘组合
控制台背面还有一个PC卡插槽。 为此,你可以从索尼购买“网络适配器卡”,它提供了两个额外的接口:
- 一个以太网端口,用于在线多人游戏。
- 一个专用的外置硬盘单元端口: 这是由索尼销售的,内置一个典型的3.5英寸ATA硬盘驱动器,容量为40 GB。 它能让游戏存储临时数据(或永久安装),以加快加载速度。 不过,只有少数游戏使用了这一功能。
在后来的版本中,PCMCIA端口被扩展槽(Expansion Bay)取代,3.5英寸硬盘可以安装在控制台内部。 您必须先购买一个网络适配器,它不仅提供调制解调器和/或以太网端口(取决于型号),还包括可插入ATA-66硬盘的插座。
在幕后,硬盘中的数据采用名为“PFS”的文件系统进行结构化处理[17]。 奇怪的是,该布局不包含分区表,只有一个非常原始的目录,称为对齐分区分配(Aligned Partition Allocation,APA)。 这可能是因为索尼只供应40 GB的硬盘。 因此,可扩展性并不在他们的优先考虑之列。
适配器内的以太网收发器支持高达100 Mbps(12.5 MB/s)的传输速率。 然而,观察到的传输速率却很低(在某些情况下低至2 MB/s)。 原因很简单: 要实现可用的网络通信,需要实现标准“OSI 模型”的所有层;而收发器只是其中的一个部分。 其余部分通常委托给IOP(因此是在软件中完成的),但由于IOP的性能有限[20],这就造成了瓶颈。
瘦身
薄型机对整个以太网+硬盘型号进行了修改:没有了扩展槽,但在背面永久安装了一个以太网端口(特定型号还包括一个Modem)。
除此以外,新版本还增加了一个新的红外传感器,可与索尼品牌的遥控器(需单独购买)配合使用。
互动配件
新版控制器DualShock 2是DualShock的略微改进版。
在最初的PlayStation时代,原版手柄曾推出过多个版本,功能各不相同(同时也给市场带来了碎片化)。 现在,为了开发者的方便,有了一款统一了之前所有特性的控制器。
与初代DualShock相比,新版本稍作重新设计,包括两个模拟摇杆和两个振动电机,分别提供更丰富的输入和反馈。
控制器插槽旁边是记忆卡(Memory Card)插槽,现在可兼容PS1和PS2记忆卡。 后者的记忆卡嵌入了用于安全目的的额外电路,称为MagicGate,可使游戏限制不同记忆卡之间的数据传输。 IOP负责对内容进行加密和解密,并在MagicGate芯片组(记忆卡内部)和DVD驱动器的帮助下完成,后者捆绑了加密密钥。
不过,有些第三方记忆卡不支持MagicGate。
操作系统
主板上安装了一个4 MB ROM芯片,其中存储了大量用于加载shell菜单(用户可以与之交互)的代码,但它也提供系统调用,以简化I/O访问[23](游戏依赖于此)。
接通电源后,MIPS R5900和IOP都将从地址0xBFC00000
开始(这是所有MIPS CPU的特征复位向量)。 不过,为了处理预期的冲突,存储在该地址(指向BIOS ROM)的相应代码将根据每个CPU的标识符使其在不同的位置分支。
在R5900的情况下,CPU将遵循以下步骤[24]:
- 初始化硬件。
- 从ROM向RAM加载内核。 加载后,内核将为应用程序(主要是游戏)提供一个与硬件交互的抽象层。 此外,它还提供了多线程应用程序接口(合作式和基于优先级的)。
- 内核加载
EELOAD
,这是一个内核模块,它反过来引导OSDSYS
。 后者是显示开屏动画和shell菜单的程序。
另一方面,IOP将初始化部分硬件,然后加载多个模块,使IOP能够访问该游戏机的硬件。 完成后,IOP 将进入“等待命令”状态。
值得指出的是,模块的使用使索尼可以在不改变IOP的情况下发布PS2的新硬件版本(直到他们改变了IOP),从而在此过程中降低了一些生产成本。
交互界面
PS2 shell的功能与其他第六世代游戏机基本一致。
shell由多个用户界面组成,用于管理典型操作,如操作存储卡中的保存数据或更改时钟。 它还提供一些高级选项,如更改当前视频模式。
可更新性
BIOS确实存储在只读存储器中,但这并不妨碍索尼在出厂后对其进行修改。 你看,在幕后,BIOS为将来的修改打开了两扇门:
- 应用程序(游戏和
OSDSYS
)可以在运行时对内核例程打上猴子补丁(monkey patch)[25]。 官方SDK和非官方的“ps2sdk”都广泛使用了这一功能,因为索尼的工程师后来发现他们的内核漏洞百出(双关语)。 EELOAD
会查找存储在存储卡和/或硬盘中的OSDSYS
更新二进制文件[26]。 索尼依靠它增加了DVD电影播放器和硬盘支持,因为这些驱动程序都没有捆绑在该游戏机的早期版本中。- 这些更新随游戏机或硬盘套件(盒装最终幻想11的一部分)的安装光盘一起分发。
- 与必须向后兼容旧版SDK的内核不同,游戏机的后续版本在BIOS ROM中提供了以前的更新。
- 为了控制分发,二进制文件必须使用数据加密标准(Data Encryption Standard,DES)进行签名[27],这是一种对称加密系统,使用的密钥只有索尼知道(理论上)。 此外,二进制文件必须存储在支持MagicGate的存储设备中。
无论如何,索尼最终在PS2晚期机型(BIOS版本为2.30
)中取消了第二种方法。 我推测索尼并没有计划进行更多更新,这只是增加了黑客的攻击面。
游戏
在其生命周期结束时(2013年,整整13年之后!),游戏库中的游戏多达1850种[28]。
这里发生的一切确实令人印象深刻。 PS2并非“程序员友好型”架构(从PC程序员的角度来看),但却能开发出如此多的游戏,我也不禁怀疑其中是否有更多的因素(如“许可减免”、发行成本低、开发成本、外形小巧等)。
开发生态
索尼提供硬件和软件来协助游戏开发。
在软件方面,PlayStation 2 SDK包括[29]:
- EE工具链: 一套C和C++编译器、汇编器、链接器和调试器,用于控制EE的每个元素。 主CPU主要使用C/C++编程,但向量单元等性能关键部件则使用汇编(微代码/宏代码)编程。
- 程序包还包括一个“EE模拟器”,它可以在不将代码发送到真实硬件的情况下对代码进行粗略测试,尽管模拟器并不像EE芯片那样精确。
- 所有这些工具都能在Linux、Solaris和Windows上运行。 后者在Cygnus环境下运行。
- 底层库: 连接许多系统功能(使用BIOS调用)。
- “分析”工具,用于分析性能使用情况。
- 用于连接官方开发硬件的附加工具。
在硬件方面,索尼为工作室提供了专用硬件,以便在内部运行和调试游戏。 最初的开发套件是将裸板堆叠在一起,以复制PS2未发布的硬件。 后来的工具包(命名为开发工具)外观更美观,输入/输出功能更强,并将工作站硬件(运行RedHat 5.2)与PS2硬件结合在一起,在同一机箱中构建和部署游戏[30]。
将Devkit、官方SDK和CodeWarrior(著名的IDE)组合在一起是最受欢迎的设置之一。
存储介质
光盘驱动器可以读取DVD和CD,因此游戏可以使用其中任何一种格式发布,但出于显而易见的原因,你会发现大多数游戏都是DVD格式。
如果是DVD-5(最常见的“子格式”),DVD 可容纳4.7 GB的数据;如果是DVD-9(双层版本,不太常见),则可容纳8.5 GB的数据[31]。 实际上还有第三种格式,即双面的DVD-10,但从未有商业游戏使用过这种格式。
由于使用的介质类型不同,游戏机不仅可以玩游戏,还可以播放电影。 这就需要解码器来读取DVD电影格式,为此,PS2最初在存储卡中安装了所需的解码器(毕竟存储卡只是一种存储介质),但后来的机型在BIOS ROM中预装了DVD软件。
就速度而言,CD-ROM以24速读取(3.6 MB/s),DVD-ROM以4速读取(5.28 MB/s)[32]。
网络服务
正如您所看到的,这些游戏机的网络功能直到后来的改版才实现了标准化,而改版是在首次发布四年后才到来的。 同样,如果游戏工作室决定提供在线服务(如多人游戏),他们也要负责提供必要的基础设施。 后来,索尼部署了动态网络验证系统(Dynamic Network Authentication System,“DNAS”),这不是一个在线服务器,而是一个验证系统,用于防止盗版游戏连接到网络。
不同寻常的游戏
除了这些画面精美的游戏外,索尼还发布了基于“Kondara”(反过来又基于Red Hat 6)的Linux发行版,分为两张DVD(第一张名为“运行时环境”,第二张名为“软件包”)和一个VGA适配器、USB键盘和鼠标,以及一些开发人员手册。 这套软件被称为Linux Kit,你可以通过启动第一张DVD来运行操作系统,然后像其他老式Linux环境一样继续运行。 显然,你需要在游戏机中安装一个硬盘来安装Linux发行版。 安装完成后,始终需要第一张DVD才能启动该操作系统。
Linux Kit包括针对EE的编译器(gcc 2.95.2和glibc 2.2.2)和针对矢量单元的汇编器,以及在GS中“加速”的窗口系统(XFree86 3.3.6)[33]。 总的来说,这听起来像是一个有趣的环境。 事实上,我为撰写本文而阅读的一篇研究论文就是使用这种设置完成的。
反盗版和自制游戏
这里有很多东西要谈,我们先从DVD光驱开始,好吗?
DVD防拷
这个领域尤其令游戏工作室担忧,因为这款游戏机使用的是一种非常实惠的光盘格式来发布游戏。 因此,盗版风险很高。
操作系统加载游戏时,会向DVD光驱发送特定命令。 专门用于读取游戏内容的命令与标准DVD命令(即读取DVD电影)的行为截然不同。 原来,授权游戏在光盘内部包含一个无法读取的“映射文件”,该文件按名称、位置和大小索引文件系统。 当DVD被要求读取游戏光盘时,它将始终使用映射文件在光盘中导航,这意味着不包含映射文件的盗版游戏将无法读取。
与此相辅相成的是锁区系统,该系统可防止进口游戏在不同地区的游戏机上运行。
规避保护机制
在解释了这款游戏机最关键的部分后,让我们来看看已发现(并商业化)的多种能攻破保护机制的方法。
攻击DVD光驱
PS2一上市,就出现了许多承诺“解锁”DVD光驱的第三方产品。 由于没有支持自制软件的迹象(Linux解决方案除外),盗版成为最大的受益者。
自制芯片
与同代(以及前代)其他使用光盘系统的游戏机一样,第三方公司对DVD子系统进行逆向工程也是迟早的事。 我们的目标是找到一个可用的漏洞,迫使驱动程序在文件系统中进行导航,而不需要一个无法访问的映射文件。
这最终以改机芯片的形式得以实现,同时也解除了防拷机制检查和锁区限制。
作弊光盘
除了需要焊接技术才能安装的改机芯片,市场上还出现了未经授权的“正版”光盘。 这些光盘对内核进行了修补,以移除区域保护并使用游戏内作弊器。
最重要的是,“作弊光盘”具有无需对游戏机进行任何修改的优点。 我想最值得一提的例子就是CodeBreaker。
换盘
在最新进展的过程中,又出现了另一种伎俩。 这一次,它利用了光驱对故障扇区的处理。 Swap Magic看起来像另一张“正版”光盘,但它的“游戏”是让DVD读取一个在刻意地故障的扇区上发现的不存在的可执行文件,从而完全停止光驱[34]。 用户可以利用这个机会将光盘换成非正版光盘。 然后,仍在内存中加载的Swap Magic引导新光盘的主可执行文件,最后加载真正的游戏。 所有这些都是在光驱仍认为插入的是正版光盘的情况下进行的。
这并不一定需要改装游戏机。 不过,根据型号的不同,PS2的外壳需要做一些改动,以阻挡光驱的弹出感应器。 在某些型号中,在某些地方放置棉花片也是破解方法之一。
脱离改机芯片
随着时间的推移,人们收集并分享了更多关于这款游戏机的研究成果。 因此,新的、更复杂的发现引发了新一轮的开发浪潮,至少不再主要依赖外部硬件。 此外,盗版也不再是重点。 相反,在未经索尼批准的情况下运行第三方程序的能力(称为自制软件)迅速登上了目标排行榜的榜首。
独立溢出
PS2在记忆卡中存储了一个名为TITLE.DB
的数据库文件,其中包含用于优化PS1游戏模拟的信息[35]。 插入PS1游戏时,操作系统会获取数据库文件,并将整个文件加载到内存中的固定地址(第一击)。 信息解析器使用strncpy()
函数实现,这是一个C语言函数,用于将字符串(字符链)从一个地方复制到另一个地方。
对于熟悉C语言的人来说,你可能已经猜到我要说什么了。 问题是strncpy()
不知道字符串有多长,所以除非终止(在字符串链的末尾放置\0
),否则复制将“永远”进行下去(结果难以预料!)。 幸运的是,该函数包含一个可选参数,用于指定要复制的最大字节数,从而防止缓冲区溢出。 虽然看起来有些可笑,但索尼并没有使用这个参数,尽管每个数据库条目都有256字节的固定大小(第二击)。
在RAM中仔细观察,TITLE.DB
恰好被复制到一个保存寄存器$ra
的旁边,该寄存器记录了当前函数执行完毕后的返回地址(第三击),这就是独立漏洞[36]: 制作一个包含大量字符串的TITLE.DB
,在其中嵌入一个可执行文件,并设计该字符串,这样$ra
就会被覆盖,指向可执行文件。 如果你能将该文件上传到记忆卡(通过其他漏洞或PC USB适配器),你就能得到一个简单的自制软件启动器。
这一发现发表于2003年。 因此,随着薄型机的推出,索尼推出了新的BIOS ROM版本,对这一漏洞进行了修补。 令人奇怪的是,这并不是最后一次暴露出笨拙代码带来的失误。
签名漏洞
2007年11月,一个黑客组织开始销售Memor32[37],这只是另一种典型的第三方记忆卡,只是出于某种原因,它内置了个FPGA和USB端口。 直到一款名为Memento的固件出现在互联网论坛上,Memor32的真实面目才逐渐清晰:从记忆卡中运行未经授权的可执行文件,就像独立漏洞一样。
Memento的实现依赖于DVD播放器签名检查方式的缺陷。 人们发现,虽然二进制文件必须使用索尼公司的密钥签名,但二进制文件的完整性却没有得到检查。 因此,任何人都可以将可执行代码替换为其他代码(但仍可在相同的空间内执行),而操作系统会很乐意运行它。 Memento固件利用这一漏洞将其代码伪装在DVD播放器中,并捆绑了一些实用程序,允许用户加载游戏(从光驱或硬盘)。
然而,Memor32和Memento的流行很快就被免费(最初是开源)的替代品所取代:FreeMCBoot。
通用解决方案
Memento被逆向工程破解后,互联网上出现了一种不需要Memor32的替代品。 FreeMCBoot利用了相同的漏洞,但它可以安装在任何MagicGate记忆卡上。 唯一的缺点是仍需要另一个漏洞(如光盘交换)来引导安装程序。
有趣的是,FreeMCBoot的用户界面借用了OSDSYS
的资产,从而为启动其他自制软件提供了一个熟悉的菜单。 它还对内核进行了修补,添加了访问USB 1.1端口中大容量存储设备的API,而这正是许多自制程序用来定位附加文件的地方。
此外,安装程序还提供了两个选项:只安装当前游戏机所需的文件,或安装适用于所有PS2变体的全局设置。 奇怪的是,后一个选项的实现却很有难度[38]。 起初,安装程序会在记忆卡的分区表上做手脚,以避免空间耗尽,这并不是一件特别安全的事。
幸运的是,2011年,PlayStation 3的安全系统刚刚遭到破坏,暴露了许多隐藏在其中的秘密。 其中包括一组用于向后兼容PS2的全球MagicGate密钥。 从那时起,制作PS2可执行文件就不再需要使用有限的DVD二进制签名技巧了。 因此,自1.8b
版以来,FreeMCBoot一直是在PlayStation 2上运行任何类型自制软件的最安全、最受欢迎的方法。
后续开发
一旦运行自制软件的途径变得更容易获得,就会以完善以前的漏洞和开发自制应用程序的形式继续取得进展。 后者有些最终促进了与盗版相关的功能,但也扩展了操作系统的有限功能(例如为游戏提供补丁),我想这最终取决于用户的意图。
下面列举几个与自制软件相关的著名例子:
- FreeHDBoot: FreeMCBoot的变种,安装在硬盘上,系统也会尝试从硬盘启动。
- 由ps2dev小组开发的ps2sdk[39]: 事实上的非官方SDK,用于编写PS2自制程序而不会有侵犯版权的风险。 该项目可追溯到2000年,当时它仅以松散库的形式存在,用于访问特定组件[40],随着时间的推移,它被统一为一个单一的软件包,为自制软件开发者提供了便利。
- 多位作者开发的LaunchELF[41]: 一个带有额外实用程序的文件管理器。 它后来以“uLaunchELF”和“wLaunchELF”的形式继续存在。
- Open USB Loader(OPL),由多位作者编写[42]: 可从多种来源(HDD、USB、i.Link甚至以太网上的SMB和NMB)启动光盘映像,并具有打补丁功能。
- ffgriever的ESR[43]: 该程序最初名为“Vast CDVDV”,它能欺骗整个系统(包括DVD光驱),使其在不修改硬件的情况下运行游戏的刻录副本。 原始游戏内容必须打上补丁,伪装成DVD电影(这样DVD驱动器就不会拒绝接受它),而ESR则控制EE和IOP,将执行重定向到实际游戏。
在以后的日子里,还会有新的发现:
- krat0s的Fortuna:2019年发布的另一款自制软件启动器,依赖于一个完全不同的漏洞。 这次是保存管理器(
OSDSYS
的一部分)图标解析器的缓冲区溢出[44]。 它的主要优点是兼容后期的PS2机型,因为这些机型取消了对外部OSDSYS更新的支持(因此与FreeMCBoot不兼容)。 - alexparrado的OpenTuna[45]: Fortuna的开源替代软件,源于对后者的逆向工程。
- cturt的FreeDVDBoot[46]:2020年发布的新漏洞。 它包括DVD播放器中新的缓冲区溢出,可被利用执行任意代码。 用户只需使用FreeDVDBoot刻录DVD,就可以执行任何二进制文件,包括FreeMCBoot安装程序甚至 ESR(索尼非常幸运,因为它没有在多年前被发现! 其他公司也没有发现)。
这就是全部了,伙计们。
恭喜您,感谢您阅读到本文的结尾! 老实说,这篇文章要谈的东西太多了,我都怀疑读者看完这篇文章后会不会对PlayStation相关的东西感到厌倦。
不管怎样,说句心里话,我希望你读完这篇文章后能有新的发现,如果你有任何意见,请随时与我联系。
下篇文章见!
Rodrigo