3DS 的架构

Rodrigo Copetti 的实用分析

这是原文的志愿翻译。如果您发现任何错误,请帮助改进。谢谢!

如果您使用无障碍阅读工具、电子书或旧版浏览器,切换到“经典”版




相关影像

型号

Model
一台 3DS。
2011 年 2 月 26 日于日本,2011 年 3 月 25 日于欧洲,2011 年 3 月 27 日于美国发售。

主板

Motherboard
主板
Motherboard
带有重要部件标签的主板

图示

Diagram
主架构图
即使如此复杂,我也不得不放弃旧的DS和GBA A/V子系统。

快速入门

由于智能手机的市场占用率猛增,加上应用商店打折以及开发授权价格可控,游戏市场出现不寻常的增长。 这样下去,人们不免要想什么时候孩子们会更喜欢iPhone 4而不是Nintendo DSi。

在寻找答案的过程中,任天堂为其成功的便携式系统设计了继承者。 用户会在其中找到老的、现存的和陌生的技术——其中许多技术无法简单被智能手机复制。

因此,这部《游戏机架构》系列的新作品会详尽地描述这款新游戏机在内部、外部两方面是如何工作的。

推荐阅读

如果您是第一次阅读这个 系列文章,我强烈建议在此之前阅读 GameCubeGame Boy AdvanceNintendo DS 文章,因为他们将解释在本文中提到的各种术语和概念。


型号和变种

在这个掌机的整个生命周期(和斗争)中,任天堂发布了无数次修改,以纠正其目标受众,找回忠实的顾客。

Image
一部原版Nintendo 3DS(初代,来自 2011 年)和一部新 Nintendo 3DS XL(末代,来自 2015 年)并排放置。

从架构的视角来看,总共有 6 种不同型号:

现在,这篇文章的重点将是原始的 Nintendo 3DS (毕竟它是所有游戏都必须兼容的最低标准)。 然而,由于“新”系列的架构差异值得研究,会有一个专门的章节用来讨论它们。


显示

唯一一家让我持续修改分析文章的标准结构的公司就是任天堂。 这次,我需要从立体屏幕(即 “裸眼3D”)开始,然后再深入探讨其他内容。

首先 Nintendo 3DS 作为 Nintendo DS 的继任者,包含了两块 LCD 屏幕。 上屏分辨率为800 x 240像素,并且可以以某种方式显示深度图像。 当我第一次阅读这篇文章时,脑海中浮现的都是问题:

好吧,这里是答案!

原理

不管怎么说,它的基本原理与我在两年前曾分析过的Virtual Boy并没有太大的不同。 回忆一下,Virtual Boy 显示两个图像,每只眼睛一个,并将物体分别从中心偏移。 通过同时查看两张图片,可以感觉到一些物体在另一些物体的后面(深度感)。 这就是立体视差的基础。

Image
左显示器。
Image
右显示器。
演示 Virtual Boy 如何显示立体图像。
马里奥网球(1995)。

Virtual Boy 执行这一操作的方式有些笨拙:它要求用户将头部靠近目镜,然后调整焦距和瞳距。 15年后,任天堂明智地对所有这些麻烦说”不”,并设计了一个新的系统,让用户可以享受3D场景,而无需_过量_干预。

Image
上屏,左眼。
Image
上屏,右眼。
任天堂3DS在其上部屏幕上同时显示的两个画面的示例。 看起来鱼要撞到你了。 同样的原理在15年后适用。
《超级马里奥3D大陆》(2011)。

这将引出我们的下一个问题。

特殊屏幕

再看看上部液晶屏的分辨率。 从理论上讲,它显示的宽度是800 x 240 像素,导致一个荒谬的宽高比。

Image
再看 Nintendo 3DS [1],更仔细地观察其屏幕。

实际上,物理屏幕由半宽像素组成,并以两种模式运行:

此外,为了实现立体视差,这块LCD包含了一个称为视差屏障 [2] 的额外层。 这些不透明的遮光板使得从LCD像素后面发出的背光发生偏移,从而令每只眼睛接收到不同部分的像素的光[3]。 这些半宽像素也会看起来更宽,令人感觉其具有传统的长宽比。

总之,这项技术重现了Virtual Boy原来的效果,而不需要用户操作调整。

不过,这项技术并不完美,存在一些缺陷:

Image
我试图捕捉原版3DS的倾斜效应。 把3D景深滑杆(在屏幕右侧)调到最高,从一侧看屏幕,可以看到上屏产生了鬼影效果。 这在真正使用中看起来相当费眼!

为了补救这种情况,任天堂添加了一个滑杆(叫做3D景深滑杆)用于调整物体之间的深度。 这种调整可以增加或减小两帧之间的差异。 对于觉得这种深度效果并不令人愉快或感觉太疲劳的用户,这么做可以减小这种效果。

将3D滑杆调到最大一开始可能会让人感到不适。 根据我的经验,我的眼睛最终会聚焦,此时我感觉顶部的LCD屏幕就像透过窗户看东西一样。 主要问题是,用户需要不断地移动眼睛才能看到下方的屏幕,这种重复的动作可能会非常费力。

顺便提一句,人们不禁觉得,在渲染立体帧时,图形管线经历了一个完整的循环,这很有趣。 在渲染过程中,3D数据被投射到2D空间中,而现在有了立体屏幕,第三维度又被“恢复”了。 到了这个时候,我们不如直接使用全息图,完全跳过3D投影阶段吧!

小型更新

Image
New 3DS XL 的顶部 中央有一个前置摄像头和一个红外LED,两者都用于头部追踪。

随着“New 3DS”型号的出现,任天堂改进了其立体屏幕,以期达到更好的愉悦体验。 在新型号中,主机集成了面部追踪机制来解决倾斜效应,因此用户不再需要担心保持良好的“头机姿势”了。

特殊游戏

现在,为了让这个系统正常工作,游戏也必须“配合”(双关语)。 就像它们传统上与GPU交互以在显示器上绘制帧一样,它们现在必须广播两个场景帧,但物体会略微偏移。

为了方便开发者,有官方API可以协助完成这项工作,特别是对于那些具有3D场景的游戏。 这些API通过提供构建两个投影矩阵的例程来提供帮助,图形管线随后使用它们来渲染这两个略微偏移的帧。


中央处理器 (CPU)

既然我们了解了显示屏的工作原理,现在让我们来看看这款主机的内部结构。 如果你拿到主板,你会看到三个大芯片,其中一个是 CPU CTR。 这是一个大型系统级芯片(SoC),它承载了整个系统(存储和RAM除外)。

Image
CPU CTR 旁边的一些 FCRAM

CPU CTR 沿袭了任天堂之前便携式主机的设计方法。 也就是说,将所有工程设计都压缩到一个单一的区块中。 这样做可以减少假冒产品的生产,保护敏感组件并改善散热。

在实际的CPU方面,任天堂再次与他们的老朋友ARM合作,生产他们的下一代核心。 ARM传统的授权模式(基于提供可综合设计)允许任天堂根据自己的需求塑造CPU,包括将其集成到大型不透明的SoC中。 最终,ARM为他们提供了一个相对陈旧但经过大幅升级的产品。 他们的选择是ARM11,它是ARM9(在Nintendo DS中出现)的继任者。 更具体地说,是MPCore变体,这是ARM的首个同质多核解决方案。

任天堂利用ARM的设计,打造了一个包含两个ARM11核心的ARM11 MPCore集群。 三年后,随着“New”3DS 的到来,SoC被扩展为包含四个ARM11核心。 这些影响将在适当的时候解释。 因此,在此之前,让我们先分析一下新的CPU核心为这款主机带来了什么。

一个标志性产业

ARM11 系列处理器于 2002 年问世。 当时,手机运行 Java ME 应用程序,并以拥有_真实旋律_的铃声而自豪。 在接下来的几年里,ARM11 取代了流行的ARM9、昙花一现的ARM10和英特尔的XScale,成为移动CPU领域的主力军。 XScale是StrongARM的延续,英特尔后来将其出售,以专注于“低功耗”x86 CPU——如果他们知道移动市场会飞速发展就好了!

Image
一部诺基亚5230(2009年)、一部红色3DS(2011年)和一部树莓派Model B(2012年),它们都搭载了ARM11。

最终,ARM11因其为2006-2009年一代智能手机提供动力而闻名。 这一代手机融合了键盘、翻盖和全触屏设计。 如果你曾拥有诺基亚N95、5230或第一代iPhone,那么你就使用过ARM11处理器。 许多高端相机、GPS或类似外设也采用了这种处理器。 有趣的是,RIM和三星等其他制造商一直沿用英特尔XScale直到2009年。 另外值得一提的是,ARM11也是第一代树莓派的CPU选择。

到了任天堂采用ARM11的时候,其创造者ARM公司已经推出了Cortex-A系列来接替它。 这完全在意料之中,因为任天堂的模式更注重成本效益,而非前卫的CPU。 从另一个角度来看,节省CPU成本可以让他们将预算集中在主机其他方面,你很快就会明白。

新方言……

伴随着闪亮的新CPU,一套新的指令集——ARMv6——也应运而生。

从程序员的角度来看,ARMv6指令集架构(ISA)通过一套新的向量指令多核支持进行创新[4]。 新的向量指令集由SIMD指令组成,这些指令可以一次性操作四组8位值两组16位值(使用现有的32位寄存器)[5]。 然而,这些指令只能操作整数(不能操作浮点数)。 此外,新的多核指令包含“存储”和“加载”操作码,并特别注意了同步(这在多个CPU使用相同的内存位置时至关重要) [6]

总而言之,这对于一个新的芯片系列来说可能看起来并不那么繁荣,但请记住,ARM的CPU会说多种“语言”。 对于基于ARM11的内核,你将获得:

为了减少混淆,ARM倾向于将所有这些都用一个单一的命名法进行打包。 例如,对于ARM11 MPCore操作码,ARM将此变体称为ARMv6k指令集。

……以及碎片化的分发

尽管如此,扩展和替代指令集的采用最终使得针对通用ARM硬件的开发者面临非常复杂的情况,你只需看看为Linux发行版设计的无数ARM移植版本就知道了。

Debian作为最流行的发行版之一,试图通过并行开发两个移植版本来解决这些差异:

然而,随着Raspberry Pi(由ARMv6驱动并由VFP加速)的到来,两者都被认为不可接受。 因此,开发了一个名为“Raspbian”的非官方移植版本,为ARMv6 CPU提供了一个VFP加速版本 [7]。 即便如此,这种趋势仍在继续:几年后,随着ARMv8和AArch64的到来,Debian又衍生出了另一个移植版本arm64,针对新的64位ISA进行了优化。

我不记得在x86上见过这种迷宫(尽管x86 SIMD扩展的采用至少可以说并不一致),但至少现在情况变得更有序了。 AArch64统一了许多扩展并放弃了替代模式(再见了,Thumb和Jazelle)。

核心功能

…… ……这只是一个快速的题外话,让我们回到分析3DS CPU的内容!

对于这项研究,我们可以将ARM11 MPCore分为两个区域:

现在我们先从核心开始,然后再检查AXI总线。

原始的MPCore

Image
ARM11 MPCore CPU集群概述

随初代3DS首次亮相的首个ARM11 MPCore变体包含两个核心。 每个核心都称为MP11,运行频率为268 MHz [8]

除了实现ARMv6k指令集外,MP11还具有8级流水线 [9],并辅以两级分支预测:“动态”(基于先前的执行)和“静态”(仅基于当前指令)。 总体而言,我感觉这些新增特性是新设计理念的一部分,它最终将使标志性的条件执行机制过时,不过我们直到下一代才会真正察觉到这一点。

此外,自ARM946E-S CPU以来,ARM一直配备一个名为CP15系统控制协处理器。 这次,它提供了内存管理(MMU功能)以及输出MPCore集群信息的寄存器内存。

现在,不再有紧密耦合内存(TCM)。 然而,它有16 KB的指令缓存16 KB的数据缓存,这种模式的改变类似于同代其他系统。 如果你好奇,这个L1缓存是4路组相联的。

最后,每个核心都包含一个名为向量浮点协处理器(Vector Floating-point Coprocessor)的协处理器,也称为“VFP”,在ARM11中则称为“VFP11”。 它加速浮点数的算术运算,包括32位单精度(即 float)和64位双精度(即 double)两种类型 [10]。 不过它并非一个大型协处理器,因为它的寄存器文件由三十二个32位寄存器组成,因此双精度数会占用两个寄存器。 无论如何,这个处理器实现了VFPv2指令集并遵循IEEE 754标准。 考虑到前几代的困难,后者是一个受欢迎的决定。

“新”MPCore

Image
“新”CPU集群概述

随着2014年新3DS的发布,引入了一个新的SoC(CPU LGR),随之而来的是一次豪华的CPU升级。

最明显的变化是,现在我们有四个MP11核心,而不是两个。 然而,这带来的影响并非简单就能阐明,但我们会在适当的时候看到它们。

第二个变化是,CPU集成了2MB的L2缓存,由四个核心共享。 这种类型的缓存是16路关联的,它预示着四个核心可以同时访问它。 如果你想了解更多,我在Xbox 360的文章中介绍过关联缓存。

接下来,所有核心现在都运行在804 MHz(是原始速度的三倍,这无疑会引起一些人的注意)。

AXI总线

Image
任天堂3DS AXI实现互连不同类型组件的示例。 在这里,CPU和DMA充当主设备,而RAM节点是从设备。 然而,角色可以根据需要改变。

无论是两个还是四个MP11核心,所有这些都通过ARM自豪地开发的一种流行总线——高级可扩展接口(AXI)进行连接。 该协议是AMBA3模型的一部分,它是我们在WiiWii U(两者都搭载ARM9 CPU)中见过的原始AMBA修订版的继任者。 通过这种方式,ARM将AXI模型作为系统级芯片(SoC)的关键构建块。

一般来说,AXI模型提供了一套用于连接具有不同带宽要求的组件的协议。 它们可以自由选择任何特定的拓扑结构,例如PlayStation 3的令牌环模型或Xbox 360的网格解决方案。 现在,在Nintendo 3DS中,我们发现了总线和星形设计的结合

遵循AMBA互连节点的方法,将存在主从层次结构来表示哪个实体负责。 主组件(通常是CPU核心)将是向从设备(即内存和I/O块)发送命令的实体。

此外,AXI网络可以通过一个专用模块(称为AXI互连)作为总线矩阵进行仲裁[11]。 这就是我们在MPCore中发现的,它依赖于独立的64位总线[12]。 通过这种方式,网络解决了高带宽组件的拥塞问题(这是PlayStation 2等主机曾经面临的问题)。 此外,多个主设备可以使用单独的通道与从节点通信,以避免等待其他主设备完成。 如果这还不够,传统的增强功能,如突发事务,也得到了实现,MP11核心就利用了这一点。

在3DS的案例中,AXI互连容纳在一个更大的模块中,称为窥探控制单元(SCU),它还负责自动维护MP11核心之间的一级缓存一致性。

还有其他CPU吗?

到目前为止,我一直将MPCore视为该系统中唯一的CPU,原因是在这项分析中混合使用不同的CPU可能会使其变成一篇难以理解的文章。 也就是说,直到现在。

事实是,任天堂对这款主机有额外的要求。 他们想要一个完善的安全系统,同时也希望能够即时将主机变成Nintendo DSi或GBA。 因此,为了所有这些,他们最终捆绑了三个不同的CPU包——其中一个就是前面提到的ARM11。 另外两个则被很好地隐藏起来,游戏完全不知道它们的存在。 事实上,像Citra这样的3DS模拟器根本不关心它们[13]

Image
任天堂3DS与其前身(任天堂DS Lite)并列,后者已成为一个普遍的参照物。

但我们确实关心! 因此,以下是该系统所包含的完整CPU列表:

不幸的是,或者出于显而易见的原因,这三个CPU从未同时可用。 相反,主机有三种运行模式:

如果你仔细思考,任天堂3DS最终总共包含了四个处理器(两个MP11核心 + 一个ARM9 + 一个ARM7),而在新3DS中更是达到了惊人的六个。 这复杂程度真是令人咋舌? 这真是太复杂了,不是吗?幸运的是,这个系统没有遭受世嘉土星那样的复杂性困扰,这要归功于任天堂和ARM的工程设计。 毕竟,3DS开发者只需要处理MPCore。

由于ARM9和ARM7主要用于I/O、安全和向下兼容性(这些都不需要开发者关注),我将在本文的后续章节中讨论它们。 但如果你想了解更多关于ARM7和ARM9的设计,我分别在之前的文章(Game Boy AdvanceNintendo DS)中写过。

多核通信

我想现在的问题是,CPU和核心如何相互通信? 嗯,最简单的方法是共享RAM……但你也可以尝试更高效的方法,这取决于尝试通信的核心:

Image
每个CPU提供的通信通道示意图。

可用内存

拥有三个不同的CPU也意味着内存布局不会简单,特别是如果你关心安全的话。

Image
任天堂3DS的内存组织概览。

长话短说,我们有以下内存块:

发现了一种新型内存

任天堂3DS包含其前身通用内存的32倍,这固然令人高兴,但“FCRAM”又是什么呢? 它与其他标准有什么不同吗?

嗯,快速周期DRAM(FCRAM)是又一项RAM发明,这次由富士通和东芝于2002年开发。 作为DRAM技术(即SDRAMEDO DRAMRDRAM等)的替代品,FCRAM在非连续读取方面表现出色,其延迟低于DRAM [16]。 这样做是为了复制更昂贵的SRAM所提供的性能。

FCRAM通过提供内存阵列的改进设计,直接与DDR DRAM竞争。 它没有在其上增加更多电路,而是将阵列分成更小的子块,然后使用3级流水线进行访问 [17]。 通过这样做,在随机位置的读写变得更快。 这些改变在设计时仍然考虑了向下兼容性。 因此,FCRAM与DDR DRAM控制器兼容(因此,其全称是“DDR FCRAM”)。

更快的内存传输

MPCore和AMBA总线的发明者碰巧也提供了一个名为CoreLinkDMA控制器品牌,而任天堂是其忠实客户。 因此,3DS在其SoC中捆绑了多个CoreLink DMA-330块也就不足为奇了 [18]

这些DMA特别连接到AXI总线并充当主设备。 每个DMA都可以在通过AMBA协议(无论是AXI还是较慢的APB)互连的两个从设备之间传输数据 [19]

任天堂在ARM9旁边安装了一个CoreLink DMA,这被称为XDMA,它提供多达四个通道(因此,最多可进行四次并发传输)。 在ARM11块旁边还有另一个DMA,这次被称为CDMA,它提供多达八个通道。 随着新3DS的到来,在ARM11块(现在是四核集群)旁边又安装了一个CoreLink DMA-330。

编程

综上所述,如何为这种非正统的CPU配置系统编程呢? 公平地说,非常规系统对视频游戏开发者来说并不陌生。 但在这种情况下,3DS程序员只能访问ARM11 MPCore。 此外,一旦你阅读到“操作系统”部分,你就会知道这个集群的能力会受到进一步限制。

无论主机版本如何,程序员都将其算法基于多线程模型:程序使用线程将指令序列分组,然后由操作系统根据需要将这些线程调度到物理核心。 这个标准曾经是Xbox 360软件的新奇之处,它提供了一层抽象,使开发者无需编写仅兼容固定数量和类型CPU核心的软件。

处理“新”硬件

由于新3DS与原始规格有很大不同,任天堂设置了一个薄薄的兼容层,以使旧3DS游戏无需手动干预即可在新硬件上运行。

本质上,当在新3DS主机上启动游戏时,游戏的代码会指定它是否专门针对新模型[20]。 如果是,操作系统将激活所有新特性(更快的时钟速度、额外的RAM和L2缓存的使用),供该游戏享受。 如果不是,操作系统将保持其独占硬件处于非激活状态,直到用户退出游戏,这样游戏就可以安全地假设它正在旧硬件上运行,并且不会出现问题。

为了继续支持旧3DS,游戏可以用两个代码库打包(一个用于“新”型号,另一个用于“旧”型号)。 由游戏工作室决定是同时支持旧3DS和新3DS,还是只支持新3DS。

你可能想知道新3DS所包含的其余独占硬件(即额外的ARM11核心和DMA)会发生什么。 嗯,要正确理解其原理,我会在你阅读到“操作系统”部分时解释这一点,但我恐怕你不会喜欢这个答案!


图形

紧随新CPU而来的总是一个现代GPU。 那么,任天堂这次构建了什么样的图像处理单元(PPU)呢? 说实话,一个都没有。 这是他们掌机系列中首次求助于GPU供应商

尽管如此,任天堂的要求并未改变。 该公司仍然想要一个性能可接受的芯片……以及其知识产权核心。 将使他们能够将GPU嵌入到他们的SoC中,就像他们对ARM CPU所做的那样。

Image
《马力欧赛车7》(2011)
Image
《索尼克世代》(2011)
Image
新 Super Mario Bros. 2 (2012)
Image
《动物森友会:新叶》(2012)
Image
《塞尔达传说:姆吉拉的假面3D》(2015)
任天堂3DS游戏示例。 所有游戏都渲染两个400 x 240像素的帧和一个320 x 240像素的帧。

与此同时,一家潜在的候选公司刚刚在2006年SIGGRAPH大会上公布了他们的新发明[21]。 一段时间以来,数码媒体专业公司(Digital Media Professionals Inc.,也称为“DMP”)一直在为嵌入式市场构建经济实惠的GPU,虽然他们的芯片没有什么特别之处,但它们保证了不错的OpenGL ES支持。 此外,他们的授权框架提供了可综合的GPU

这对于任天堂来说似乎足够了,他们愉快地协商获得了DMP最新核心PICA200的授权,并随后将其捆绑到CPU CTR(任天堂3DS的SoC)内部。 这款GPU运行频率为268 MHz

PICA200的架构

如果用一句话来概括,PICA200是一个低成本、低功耗的3D处理器,它结合了预统一架构和现代化的API。 PICA200的底层架构被称为Maestro 2G [22],其设计符合OpenGL ES 1.1,但扩展了OpenGL ES 2.0的元素 [23]。 然而,PICA200的API并不局限于任何一个标准。

你看,尽管流水线是分离的,并且像素阶段是固定功能的(类似于PlayStation 2),DMP还是通过一套Maestro函数扩展了有限的电路,提供了超越嵌入式市场预期的功能 [24]。 这包括片段光照、多种阴影算法、多边形细分、凹凸贴图、程序纹理和多种雾效。

此外,与Nintendo DS不同,PICA200只使用帧缓冲区。 就是这样。 精灵引擎,一种解决高昂内存需求的流行方法,现在已成为过去。 这还包括扫描线技巧,因为现代GPU的工作速度远快于CRT的刷新率。

硬件组织

既然我们知道这个主机可以绘制3D图形,现在的问题是:它在哪里存储其素材? 有两个位置,大型FCRAM块和较小但更快的VRAM

任天堂只为GPU提供了6MB的VRAM。 理想情况下,程序员会尽可能多地将数据放入其中,但由于它会很快被填满,因此预计它将用于存储需要即时访问的数据(即命令、缓冲区和重复纹理),而将其余数据放在FCRAM中。 PICA200带有一个DMA单元,可以在FCRAM和VRAM之间传输数据。 因此,归根结底,程序员有责任提出一个高效的布局以避免瓶颈。

Image
数据如何在可用内存中进行编排的例子.

在渲染过程中,程序员为许多操作分配专用的渲染缓冲区(即帧、模板、深度等)。 一直如此。 然而,对于3DS,LCD控制器不理解PICA200在帧缓冲区中渲染的数据。 因此,程序员还需要为LCD帧缓冲区保留额外的空间[25]。 每个缓冲区都绑定到一个物理屏幕,并以LCD控制器所需的格式编码帧。

这意味着3DS需要至少分配三个LCD帧缓冲区(两个用于立体上屏,一个用于下屏)。 然而,为了避免显示伪影,可能会分配一套重复的缓冲区以进行页面翻转

基于此,显示过程如下:

  1. LCD根据索引寄存器的指示,持续显示活动LCD帧缓冲区的内容。
  2. 同时,GPU在单独的帧缓冲区中完成新几何体的渲染。
  3. 帧缓冲区被导出到非活动的LCD帧缓冲区。
  4. GPU交换活动LCD帧缓冲区的索引。
    • 出于实际原因,索引交换发生在垂直同步结束时,以避免画面撕裂[26]
  5. 此后,LCD将扫描最近更新的LCD帧缓冲区。

采用开放标准

有趣的是,就像ARM11 MPCore采用ARM的AXI协议互连其核心一样,DMP采用了不太专有的选项,称为开放核心协议(OCP)[27]。 顾名思义,开放核心协议对其用户不施加任何许可限制,这可能是使用PICA200的供应商认为有利的。 为了比较,AXI于2003年发布(与AMBA 3规范一起),而OCP于2001年发布。 这确实让我好奇任天堂安装了什么样的技术来将来自PICA200的OCP信号转换为符合AXI的信号,以便SoC的其余部分能够理解它。 我猜测PICA200和AXI总线之间有一个桥接器。

有趣的是,PICA200的前身ULTRAY2000与其继任者有许多相似之处。 然而,最显著的区别是数据接口改用PCI和DDR-SDRAM协议 [28]

构造帧

自然地,GPU不了解显示器的立体或双屏性质,它只负责在游戏过程中渲染三个屏幕:

所有这些都可以显示8位RGB颜色,相当于高达1678万种颜色。

考虑到玩家期望所有三个屏幕(特别是前两个)都能达到可接受的帧率,单个PICA200在其整个运行过程中将承受大量工作负载,这是在评估其性能时需要记住的重要方面。

话虽如此,以下是数据如何传输以绘制单个帧的概述:

Image
PICA200中图形流水线的概述。

……按照本系列文章的惯例,我们现在将查看每个阶段发生的情况。

指令

Image
命令阶段概述.

这是任天堂首款最终以“常规方式”绘制三角形的掌机。 也就是说,通过使用命令。 但这并不是一个令人惊讶的因素,因为PICA200预计将遵循OpenGL ES的教义。

本质上,PICA200通过读取命令缓冲区来绘制多边形 [29]。 此外,顶点数据可以嵌入到命令中,也可以存储在VRAM的单独缓冲区中,后者效率最高。

Vertex

Image
顶点 (vertex) 阶段概述.

PICA200提供了四个并行操作的顶点处理器(VP)。 然而,如果激活了几何着色器(下一个流水线阶段),则只能使用三个处理器。

每个核心计算由四个24位浮点值组成的96位向量 [30],但与ARM11的VFP不同,它们不符合IEEE-754 [31]。 顶点处理器使用PICA200特有的汇编语言进行编程(让人联想到Nvidia NV30的时代),并按以下方式操作 [32]

  1. 开发者使用PICA200汇编编写顶点着色器。 作为参考,指令集与Microsoft的vs_2_0非常相似 [33]
  2. 着色器使用专有汇编器进行编译。
  3. 3DS程序必须将编译后的二进制文件复制到内存中(FCRAM或VRAM)。
  4. 然后,3DS程序发出GPU命令以加载二进制文件并将其与程序连接。

一旦顶点核心处理完毕,它们将结果输出到同步控制块,该块充当顶点缓存和缓冲区。 它具有384字节的容量,能够容纳多达32个96位向量。 最后,下一个阶段从该块读取数据。

几何

Image
几何 (geometry) 阶段概述.

几何阶段是第八代主机的标志性功能,允许开发者从简单的顶点数据中生成复杂的几何体。

在这种情况下,PICA200的几何阶段是通过占用四个顶点处理器中的一个来实现的。 然后,“几何”顶点核心加载不同的顶点着色器。 最后,它从其他三个处理器接收顶点数据。

几何着色器的用途示例包括正方形或线条生成(使用点图元)、几何细分、轮廓边缘渲染;以及随机粒子生成。

光栅器

Image
光栅阶段概述.

在此阶段,所有图元都转换为像素。

PICA200上的光栅化单元非常简单,它只是从图元生成三角形,然后应用剔除和裁剪以移除不可见的三角形(分别隐藏在其他三角形后面和/或在视图区域之外)。 这与OpenGL ES的操作方式非常相似,尽管开发者在PICA200上工作时必须注意某些坐标系是反转的。

像素

Image
片元阶段概述。

片元阶段由两个区域组成:纹理单元,可以从内存中获取纹理并进行处理。 以及着色单元,可以对纹理数据执行额外操作。

PICA200包含四个纹理单元 [34],每个单元都有256字节的L1缓存,并且它们都共享8 KB的L2缓存。 然而,这些单元并非同质的。 相反,每个单元的服务范围各不相同[35]

  • 只有三个单元可以处理2D纹理。
  • 只有一个单元可以执行阴影、立方体和投影纹理映射。
  • 最后一个单元更像是一个噪声生成器,这意味着它只输出随机纹理。 它使用随机数生成器和颜色查找表的组合。 这是一种纤薄而高效的纹理程序生成实现方式,同时节省了带宽。

之后,着色单元的工作是创造性地处理输入的纹理。 然而——考虑到我们正在谈论第八代主机,这有些出乎意料——PICA200的单元不可用像素着色器进行编程 [36]。 相反,我们发现有六个可配置的颜色混合器,每个混合器接收三个RGB或Alpha值并对其执行逻辑操作。 结果传递给下一个混合器,依此类推。 每个颜色混合器都可以从上一个混合器(第一个除外)、纹理单元或常量值获取输入。

总而言之,这是Flipper时代(同时遵守OpenGL规范 [37])的现代反映,但不要忘记开发者还可以将其与前面提到的Maestro函数结合使用。

后处理

Image
后处理阶段概述。

帧经过处理并准备写入帧缓冲区(或渲染目标)后,它会经历一系列最终的“校正”。 这类似于OpenGL ES 2.0的流水线。

话虽如此,帧会经过alpha模板深度测试。 之后,结果可以使用颜色混合器或逻辑运算符(AND、XOR等)与现有帧(在帧缓冲区中)混合。 最后,帧以整体形式或通过模板过滤器(用于遮罩)写入内存中分配的缓冲区。

为了进一步平滑边缘,PICA200可以以两倍于选定尺寸的帧缓冲区进行渲染,然后使用2x2抗锯齿进行平均。 这是一种称为超采样旧技术

一旦帧缓冲区准备好显示,它必须复制到内存中另一个名为LCD帧缓冲区的块中(其格式更符合LCD屏幕的扫描线程序),然后以扫描线的形式传输到LCD。

交互式比较

现在你已经了解了PICA200如何在屏幕上绘制三角形,是时候来看一些实际例子了。 这里我收集了来自《任天堂明星大乱斗》游戏中的两个马里奥,一个是Wii版,一个是3DS版。 请注意,新版“愤怒马里奥”的细节感知水平与家用机版本非常接近。

线框表面纹理
3D model
Wii的任天堂明星大乱斗X(Super Smash Bros. Brawl)(2008)
5455个三角形
线框表面纹理
3D model
3DS版《任天堂明星大乱斗》(2014)。
3,080个三角形。

值得再次提醒的是,实际上,PICA200将同时渲染三个屏幕,这是Wii的GPU所没有承受的任务。

隐藏的附加功能

“新”3DS版本似乎还捆绑了一个不常见的DSP,名为MVD。 它执行H.264&MJPEG解压缩以及YUV到RGB的颜色转换 [38]。 CPU通过写入其寄存器来对其进行编程。 反过来,MVD内部有一个专用的DMA单元,可以独立处理FCRAM中的数据。

总的来说,关于这个组件没有详细的文档,我只能推测它位于SoC的某个地方。 新3DS上的网页浏览器似乎是其唯一的用户(用于加速视频播放)。

怀旧渲染

解释了这么多之后,还剩下一个问题没有回答:PICA200如何渲染任天堂DS和Game Boy Advance游戏? 你可能还记得DS和GBA的GPU在渲染和广播帧方面表现出完全不同的操作模式。

Image
由NDS[Graphics Engine](nintendo-ds#graphics)渲染的一帧,其流水线将2D和3D数据分离。 这是符合OpenGL规范的PICA200无法理解的。

解释是,DS和GBA的PPU(图像处理单元)都集成在SoC中,DSi/DS/GBA游戏将像它们最初在之前的游戏机上那样操作这些PPU。 PPU的输出(扫描线)被传递到一个名为LgyFB的模块,该模块可以选择性地放大帧,然后将其转发到帧缓冲区,PICA200将负责显示它。 ARM11及其DMA负责在此过程中处理所有内存传输。

自然,这种安排会增加一些延迟(即 卡顿),尽管对用户来说可以忽略不计。


音频

总的来说,SoC中包含两个音频模块

3DS专用硬件

你可能知道,这个DSP之前也捆绑在任天堂DSi中,但被视为可选加速器。 在3DS中,它成为了指定的音频处理器,因此不再是可选组件。

该DSP名为CEVA TeakLite II [39],运行频率约为134 MHz [40]。 它由ParthusCeva制造,该公司提供用于音频处理的可综合核心 [41],我猜“synthesisable”是任天堂在合作时寻找的关键词。

此外,该DSP输出采样率高达32 kHz16 bit的立体声样本(2通道)。

在这个组件旁边,我们可以找到512 KB的RAM,供DSP作为工作区使用。 它是双缓冲的(每个缓冲区256 KB),因此CPU和DSP都可以不间断地读写 [42]。 除此之外,DSP还带有一个专用的DMA,可以在这512 KB内存中传输数据。

操作

出于所有目的和意图,游戏将此视为一个不透明的DSP。 因此,只有任天堂知道如何对其进行编程。

3DS编程,由于使用官方SDK开发,捆绑了一个DSP固件(完全由任天堂编写),该固件在运行时上传到DSP芯片 [43]。 之后,程序依赖该固件执行与音频相关的例程。 此外,操作系统提供的音频服务进一步抽象了程序与DSP固件之间的通信 [44]

无论如何,尽管DSP固件可能多年来有所变化,但某些功能保持不变。 例如,DSP可以混合ADPCMPCM样本。 支持多达24个通道 [45]。 还有滤波和排序功能,包括生成PSG类声音。

有趣的是,破解3DS(使其可以执行自制应用程序)的步骤中,可选地涉及提取HOME菜单的DSP固件,以便自制程序可以使用它提供音频输出 [46]

向下兼容模块

另一方面,我们找到了CSND模块。 3DS可以将其用作DSP的扩展,而DS/DSi/GBA游戏则依赖它来模拟其硬件。

在功能方面,CSND具有32个通道[47],是NDS对应模块的两倍。

奇怪的是,早期的自制程序默认使用此模块提供声音,同时等待DSP被逆向工程。

流水线

DSP和CSND都独立工作,并分别将音频输出到扬声器。

Image
音频管道概述.

值得注意的是,最初的任天堂3DS与扬声器的功能配合不佳,任天堂最终为嗡嗡声和3D滑块波动的情况提供了故障排除指南 [48],所有这些都是由外壳设计引起的。


I/O

考虑到任天堂的主机在尖端CPU和GPU之前更偏爱慷慨的I/O,本节往往包含丰富的技术。 让我们看看任天堂3DS提供了什么。

外部接口和外设

NDS 内置了很多模块,NDSi 在此基础上又增加了一些(但同时也移除了 GBA 卡带插槽)。 现在我们有了一个结合了两个年代(2000 年代和 2010 年代)接口的新主机。

Image
主机结构的主图. 你可以感觉到左侧的I/O区域是这款主机的一个强大卖点。

公平地说,我们仍然没有像 USB 这样的标准接口,但考虑到 3DS 集成了以下丰富的部件,这可能不是必需的:

“新”的增强

如果这还不够的话,New 3DS 在此基础上增加了更多模块。 这包括:

为了照顾旧款主机的用户,任天堂也提供了针对旧机型的增强外设,虽然它们中的绝大多数都依靠红外线收发口进行连接。 因此,一次只能使用一个外设。

Image
新任天堂3DS XL和原始3DS的正面视图,请注意它们提供的不同按钮组。
Image
原版3DS的SD卡槽已打开。 这里可以看到两个后置摄像头、SD卡槽和一个音频插孔。 在新3DS中,microSD卡无法在不取下后盖的情况下更换。

然而,并不是所有新 3DS 的增强功能都能通过外设实现。 例如,新 3DS 的面部追踪功能依赖于额外的 ARM11 核心。

内部接口

现在是时候看看这些接口——以及其他接口——的内部连接了。

首先,大量的接口通过 串行外设接口(SPI)协议互联。 主机有四条 SPI 总线,这些总线均可被 ARM9(我假设也包括 ARM7)访问。 ARM11 只能访问它们中的 大部分 [49]。 无论如何,SPI 总线连接以下模块 [50]

有趣的是,部分外设具有两个接口,其中一个用于复现旧的 NDS(i) I/O 布局,另一个用于向 3DS 软件提供增强功能。

其次,一个 人机接口设备 (HID) 模块同时连接到 ARM11 和 ARM9 数据总线。 该模块用于处理按键。 数据通过一个 16 位寄存器读取。

接下来,I²C 总线使用了更加复杂的串行通信协议。 它连接到了以下设备 [51]

最后,有一些 寄存器 用于操作 FIFO 块,这些块又连接到两个相对高速(16 MB/s)的外设 [52]

辅助计算机

听起来可能很混乱,但还有更多的硬件需要讨论。 其余部分由一个名为辅助微控制器(MCU)的中间芯片处理 [53]。 这只是一个由NEC设计并由瑞萨制造的微控制器。 具体来说,型号是78K0R,它捆绑了一个专有(但低功耗且相对现代)的处理器和一个ROM[54]。 78K0R存储着由主机操作系统处理的固件,ARM9和ARM11都可以与它交互,其他外设也可以。

MCU芯片专门控制以下设备 [55] [56]

这组设备中的一部分已经可以被主CPU访问。 这是因为MCU还执行监控任务,从而节省了ARM11或ARM9的资源。

紧跟潮流

有了如此庞大的I/O硬件列表,你现在可以看到任天堂是如何努力与智能手机市场竞争的。 这导致了在主机生命周期中部署的有趣服务:


操作系统

大量的 CPU 最终影响了整个操作系统的复杂度。 不仅如此,这台主机中还包含了多个不同的系统。 这种设计作为主机运行不同服务的机制(例如: 对 NDSi、NDS、GBA 的向下兼容、恢复模式等)。

因此,为了避免本节变得更加混乱,我们一步步来。

架构

一台 3DS 主机中包含了四个固件[57]

所有的固件都包含了分别用于 ARM11、ARM9 和 ARM7 CPU 的二进制文件。 唯一的例外是 ARM7 在 NATIVE_FIRM 和 SAFE_FIRM 下不会被启用。

通常而言,3DS 首先会启动一个 Boot ROM,然后引导 NATIVE_FIRM。 在这之后,正在运行的操作系统可能会基于用户的操作重启至不同的固件(例如,游玩 NDS 游戏或者进入主机更新画面)。

现在让我们看看每个 CPU 在 NATIVE_FIRM 模式下的行为。

安全处理器

当 NATIVE_FIRM 启动后,ARM9 运行自己的操作系统,该系统包含名为 Kernel9 的内核和名为 Process9 的单个程序 [60]

Kernel9 的设计遵循 微内核 模型,也就是说它只提供了对硬件的必要抽象,包括:

另一方面,Process9 是一个实现了如下服务的用户空间程序:

内核和 Process9 位于仅限 ARM9 访问的 1MB(New 3DS 中为 1.5MB)SRAM 上。

在安全性方面,Kernel9 和 Process9 之间没有权限区分,因为后者可以无条件访问一个系统调用,该调用可以在内核模式下运行任意代码。

总结来说,ARM9 除了连接到主机的 I/O 之外,也承担了 安全处理器 的职责,就像 Wii 和 Wii U 的 ARM9 那样,并与 NDS 中第二 CPU 仅用于负责 I/O 和音频任务的 协处理器 架构不同。

用户处理器

相应地,ARM11 上也运行了内核(称为 Kernel11),其架构与 ARM9 上的内核架构相似。 两者的区别在于,ARM11 上会运行多个用户空间进程,并通过它们提供服务,例如:

ARM11 的内核位于专用的 512KB SRAM 上 [61],这块内存也被称为“AXI Work RAM”或“AXI WRAM”,因为它与 ARM11 使用 AXI 协议连接。

强制行为

现在来说坏消息,NATIVE_FIRM还对用户程序施加了不同寻常的限制。

Image
结合两个操作系统后,运行NATIVE_FIRM的任天堂3DS的权限级别概览。

首先,ARM11 的调度器硬编码了每个核心的行为(而不是将各个核心均视为通用处理单元):

例外地,syscore 可以将其执行时间的 30% 借给用户应用程序,这可能有助于降低一些操作的负载,尽管并非所有例程都可以在 syscore 下工作(尤其是时间敏感的操作)[63]

这种限制在 New 3DS 中进一步扩展,其 ARM11 MPCore 现在配备了四个核心,其中:

接下来,对于游戏中可用的内存,我们已经知道旧款 3DS 和 New 3DS 分别配备了 128MB 和 256MB 的 FCRAM。 现在你需要知道的是对于应用来说,相应的可用内存分别只有 64 MB124 MB [67]。 这意味着系统占用掉了主机约 50% 的内存,这并不是一个特别令人愉快的特性! 为了缓解这种情况,游戏可以在它们的元数据中设置一个标志(称为 APPMEMTYPE)向系统请求更多的 FCRAM,分别为 96 MB176 MB。 在幕后,该标志指示系统重新启动主机并在不预先启动HOME菜单的情况下启动游戏,从而在此过程中节省内存。

综合来看,你现在可以感受到新3DS中并非所有额外的硬件都会自动意味着更快的软件。 这很遗憾,也让我觉得新3DS从软件角度来看是一个仓促的产品。 但公平地说,任天堂从未计划将“新”3DS作为原始3DS的完全继任者。 “新”品牌显然是为了重振3DS系列,考虑到销量数字至少可以说不尽如人意。

存储介质

现在我们了解了操作系统的设计方式,接下来看看数据在这款主机中是如何存储的以及存储在哪里。

引导 ROMs

遵循其悠久的祖先Game Boy,SoC存储了一系列未加密的ROM,其中包含用于启动NATIVE_FIRM的程序 [68]。 这些引导程序被称为Boot9Boot11;分别由ARM9和ARM11执行。 同样,出于安全原因,它们在物理和虚拟上都保持隐藏。 举个例子,Boot9存储了AES解密密钥,这些密钥不能随意放置。

有趣的是,Boot9的代码显示它不仅仅能够从eMMC NAND引导NATIVE_FIRM。 然而,由于某些例程具有硬编码目录和额外的安全层,Boot ROM最终只能加载eMMC NAND中的NATIVE_FIRM固件。

此外,虽然随着新3DS的到来,多个组件发生了变化,但BootROMs却丝毫未变 [69]

OTP内存

为了进一步提高安全级别,主机将一系列主机独有的信息存储在一次性可编程(OTP)内存中 [70]。 与WiiWii U类似,这些信息也包括加密密钥。

OTP在制造过程中写入一次,因此每个主机之间的密钥都不同。 因此,一个被破解的主机不一定会危及其他主机。 考虑到某些先前的实现包含全局密钥,这对于掌机来说是一个重要的里程碑。

eMMC NAND

Image
初版3DS上的三星制造eMMC芯片。

在大型SoC旁边,有一个eMMC NAND闪存芯片。 然而,其尺寸因制造商而异 [71]。 例如,东芝提供了943MB1888MB的芯片,而三星则提供了954MB1240MB的芯片。

为了解决这种差异,任天堂使用一个通用尺寸定义了3DS分区表:旧3DS为943MB(东芝尺寸),新3DS为1240MB(三星尺寸)。 因此,如果你的主机配备了更大的eMMC芯片,额外的空间不幸地被闲置了。

无论如何,主机依靠eMMC存储其系统数据,包括多个固件,以及用户数据(3DS和DSi模式下的存档和配置)。

SD/microSD

曾经是可选(有时是象征性)介质的SD卡,现在享有与内部存储类似的职责,因为3DS依赖它从eShop下载软件并存储用户数据(游戏存档、相机照片和麦克风录音)[72]

此处存储的软件和用户数据受AES-128-CTR加密保护。

启动过程

现在我们了解了操作系统的结构以及数据的存储位置,接下来看看任天堂3DS如何从一个闪亮的关机砖块变成一个提供多种服务的可操作主机。

多核混乱

考虑到3DS必须在其SoC中管理四个处理器(2核ARM11 + ARM9 + ARM7)——如果看新3DS,则是六个——人们不禁会想,这些“中央”处理器在主机启动期间是如何突然变得异常协调的。 嗯,这都归结于实现主从层次结构。

对于ARM9和ARM7,没有太多疑问,两者可以单独供电并加载不同的二进制文件。 因此,挑战主要集中在传播同质多核ARM11上。

在ARM11 MPCore集群中,所有核心都从0x00000000向量开始执行[73]。 然而,CP15(系统控制协处理器)提供了一个名为CPU ID的寄存器,除其他功能外,它用于识别当前正在执行指令的核心。 因此,程序员可以查询此寄存器来决定当前CPU核心是应该发出命令(主)还是等待命令(从)。 ARM后来通过提供一个名为mpidr的专用寄存器(在ARMv7 CPU中找到)改进了这项技术。

得益于此,任天堂工程师能够识别3DS集群中的任何CPU核心,并实现一个引导加载程序,使所有核心协调一致,然后执行必要的功能以使主机运行起来。

启动流程

是时候深入了解引导过程了。 与同代任何其他主机一样,安全性至关重要,这将对引导阶段产生影响。 为了避免本节过于冗长,我简化了安全系统设置的阶段,但你会在“反盗版”部分找到更多信息。

话虽如此,一旦主机通电,将发生以下事件序列 [74] [75]

  1. ARM9和ARM11通电。
  2. ARM9的复位向量位于地址0xFFFF0000,指向Boot9[76]。 ARM11被无限复位,直到其复位引脚被抬起。
  3. Boot9清除ARM11的复位引脚,然后初始化ARM9的MPU。

ARM11 MPCore现在将并行开始执行Boot11:

  1. ARM11的复位向量位于地址0x00000000[77],恰好与Boot11位于同一位置。
  2. Boot11将根据其执行的核心进行分支。 如果大于核心2,则无限挂起。
  3. 等待ARM9完成固件引导。

同时,ARM9将忙于继续执行Boot9:

  1. AES和RSA公钥被导出到AES和RSA引擎(这将在“反盗版”部分解释)。
  2. Boot9将尝试从NAND引导。
    1. 在NAND中,位置0x0处有一个名为“NCSD头”的分区,它声明有八个分区,每个分区都有一个固件可供引导。
    2. 对于列出的每个固件分区,Boot9将获取其头,验证SHA-256哈希和RSA-2048签名(使用先前从BootROM加载的一组密钥),并重复此过程直到一个验证成功。然后,它将从那里引导。 然后,它将从那里引导。
  3. 如果NAND中的所有验证都失败,Boot9将尝试从Wi-Fi模块中的闪存引导。 如果这也失败,主机将显示错误屏幕。
  4. 第一个验证成功的分区恰好包含NATIVE_FIRM。 Boot9将根据头的参数将固件复制到不同的内存区域。
  5. 禁用Boot9和Boot11的一半。这样做,FCRAM将变得可访问。 这样做,FCRAM将变得可访问。
  6. 将ARM9和ARM11的执行重定向到固件的入口点。

现在NATIVE_FIRM已引导:

  1. ARM9将:
    1. 加载Kernel9。
    2. Kernel9隐藏OTP内存并加载Process9。
    3. ARM9 CPU现在已启动并运行Process9。
  2. 同时ARM11执行以下操作:
    1. 加载Kernel11。
    2. 在New 3DS的情况下,Kernel11将写入一个名为CFG11_BOOTROM_OVERLAY_CNT的新寄存器,以覆盖Boot11代码 [78]。 这将允许将新ARM11核心(核心3和核心4)的执行从Boot11重定向到Kernel11中的任意函数,从而控制它们。
    3. Kernel11将启动各种系统进程,包括PM(进程管理器)。
    4. PM将启动“NS”(任天堂用户界面Shell)系统模块。
    5. NS将启动游戏或HOME菜单应用程序。
    6. 现在由用户控制。

备用启动过程

前面所有的解释都集中在启动NATIVE_FIRM上,这导致了传统的原生3DS模式。 对于TWL_FIRM、AGB_FIRM和SAFE_FIRM等其他固件,情况则复杂一些。 事实证明,之前的启动过程仍然是必需的,因为只有NATIVE_FIRM可以从电源循环启动。 但是一旦NATIVE_FIRM运行起来,它就可以引导这些固件中的任何一个,并且每个固件都会以不同的方式编程ARM9。 无论哪种情况,在Boot9期间设置的安全机制仍然会生效。

特别是TWL_FIRM和AGB_FIRM,它们操作一组特殊的寄存器,根据DS、DSi或GBA游戏所期望的硬件和内存布局来塑造3DS硬件。 FCRAM仍然可以访问,允许从这些位置(除了NTR卡槽)引导游戏ROM。 然而,FCRAM将被重新配置以遵循DS和GBA总线规范(16位宽,而不是32位)。

关于向下兼容固件的一个重大区别是,ARM7最终将处于活动状态(因为任天堂DSi/DS和GBA软件需要它)。

要退出任一模式,非原生固件包含一个重新启动系统的例程,从而使其返回NATIVE_FIRM。 因此,回到3DS模式。

交互界面

第七代主机界面已登陆任天堂3DS。 一个明显的迹象是用户不再需要零售游戏来充分利用他们的主机,只需浏览界面,你就会发现捆绑了许多应用程序和服务。 这包括这款主机的特殊功能(3D相机、立体视角和增强现实)。 与智能手机竞争的压力再明显不过了。

Image
HOME菜单,安装了一些应用程序。 这次我还插入了马里奥大陆的游戏卡带。
Image
Wii的“Miis”已进入3DS。
Image
设置应用程序。

在用户界面设计方面,我倾向于认为它借鉴了Wii系统菜单的许多模式,但移植到了双屏便携系统上。 HOME菜单(交互式界面的名称)使用1页导航系统,其中每个已安装的应用程序都显示在一个可滚动的网格上。 除了这里和那里的一些快捷方式,每个服务都是一个要启动的应用程序。

现在,作为任天堂的产品,你可以期待它特别注重创造力和对细节的关注。 家庭是目标受众,然而,成年人是付费者,任天堂深知这一点。

保持一致性

NS模块不仅负责启动交互式界面,它还为3DS软件提供了调用例程来处理某些交互的能力。 一个例子是“返回HOME菜单”叠加层,每当用户按下“HOME”按钮时都必须显示。

Image
用户可以在游戏中按下“HOME”按钮,这将重新显示HOME菜单而不会关闭当前应用程序。 此事件由正在运行的应用程序处理,但例程由NS服务提供。

此外,3DS软件还可以调用“迷你应用程序”来处理其他事件(例如显示虚拟键盘),这些被称为Applets [79]

这两组都是所有应用程序的关键依赖项,因为它们负责一致地对外部事件做出正确反应。 有趣的是,由于Applets和NS例程不属于游戏本身,在New 3DS系统中,即使游戏在兼容模式下运行(即所有“新”硬件都已禁用),它们仍将使用全部硬件执行,为未优化的3DS游戏提供小幅性能提升。

传统的 shell

虽然特殊固件包含了DS/GBA游戏所期望的旧BIOS例程,但并没有DS或DSi界面。

旧的Wi-Fi设置屏幕(由DSi和DS游戏调用)是唯一的例外。 有趣的是,虽然原始DS Wi-Fi设置无用(因为它们只能连接到WEP保护的接入点),但DSi的对应设置(从DSi和“DSi增强型”DS游戏访问)可以更改3DS的Wi-Fi设置。 然而,这些游戏捆绑了一个只适用于真实DSi的旧Wi-Fi驱动程序(3DS包含Atheros AR6014,而DSi配备Atheros AR6002或AR6013)。 因此,为了解决这个问题,当固件启动时,两个Wi-Fi设置会自动同步[80]

可更新性

当然,一个可更新的系统几乎是必需的,不仅是为了提供新功能,也是出于安全考虑。

你可以通过在线或游戏卡带更新系统软件。 令人困惑的是,两者都包含不同的更新包。 游戏卡带只捆绑了系统更新,不包含更新后的用户应用程序,而网络更新则包含所有内容 [81]。 因此,版本名称会编码两者的混合,以防用户使用了两种渠道。

要安装更新,NS服务会重启到SAFE_FIRM,由系统更新程序负责此过程 [82]


游戏

现在是时候检查游戏开发和分发是如何进行的了。 此外,我们还将看到任天堂为这款主机准备的一些独家服务。

开发生态

在任天堂3DS到来之前,为嵌入式系统开发需要巨大的努力和高度的耐心。 与桌面应用程序相比,工具链不标准化,有时彼此之间也不兼容(ActiveSync是我记得最清楚的例子)。 文档范围通常不超过制造商提供的范围,技术支持也是如此。

进入2010年代,随着基于ARM的智能手机产业和更高效编译器的涌入,为这些平台开发不再是一项复杂的任务。 因此,为任天堂3DS开发的游戏工作室能够享受这一发展。 现在,任天堂尚未提供标准工具链,但他们走在正确的轨道上(最终在任天堂Switch上实现)。

奇怪的是(这是一个有趣的对比),早在2011年,苹果就提供了Clang/LLVM 1.3和OpenGL ES 3.0用于开发iOS应用程序,这被认为是移动项目的尖端技术。 嗯,你将在本节中看到,任天堂并非如此。 然而,目前,如果你拿起一部旧的iPhone 4s并尝试在App Store(其唯一的官方媒介)上安装任何应用程序,它会告诉你你的系统太旧了。 而你仍然可以在你的3DS上玩任何零售游戏。 这值得深思。

硬件套装

任天堂与两家供应商合作生产开发套件 [83]。 第一家供应商是著名的Intelligent Systems,另一家是Kyoto MicroComputers

在众多选项中,工作室可以租用通用“CTR-BOX”。 这是一个包含3DS硬件的金属盒子,连接着一个充当控制器和显示器的“假”3DS外壳。 通过它,开发者可以部署、测试和调试他们的代码。

对于更单一用途的工具,工作室可以获得官方烧录卡,将游戏原型分发给外部测试人员。 这些烧录卡仍然只能在非零售设备上运行,尽管这包括比功能齐全的CTR-BOX更便宜的选项(功能有所减少)。

随着新3DS的到来,IS和Partner提供了带有更新硬件的“SNAKE”套件。

软件套件

一如既往,获得许可的工作室还将从任天堂获得一个SDK包,其中包括[84]

  • ARM的CC++编译器armcc的变体,为任天堂3DS和ARM11 MPCore建模。
    • 这只会为ARM11 MPCore生成代码。 ARM9和ARM7不在考虑范围内,因为3DS游戏只在ARM11集群中运行。
  • 为IS和Partner开发套件制作的调试器
  • 与硬件和操作系统服务通信的API
  • 四个图形库
    • GL:一个更简单但更慢的OpenGL ES API。
    • GD:GL的更快替代方案,生成PICA200命令。
    • GR:最接近硬件的PICA200命令API,但学习曲线最陡峭。
    • GX:用于PICA200管理的通用库。
  • 一个3DS应用程序打包器,以便创建可执行文件。
  • 进一步的库,以简化常见的开发任务,例如实现网络协议、在线游戏和音频/视频解码和处理。
  • Visual Studio 2010的插件,以便可以将其用作主IDE。
  • PICA200的辅助工具
  • 性能分析器,用于测量和优化性能。

如果这还不够,开发者还可以访问NintendoWare下载代码示例、库和为任天堂3DS开发设计的更多工具。 此外,随着New 3DS的到来,Unity等游戏引擎也为这个(曾经被忽视的)平台提供了支持[85]

存储介质

任天堂3DS可以从三种不同的介质运行软件。

游戏卡

Image
一款零售游戏的例子。 请注意路易吉抓住3DS横幅的创意触感。

这是零售软件的分发渠道。 内部称为“CTR卡”,它们只是任天堂设计的另一种专有卡/卡带。 公平地说,除了右上角的一个装饰性缺口外,它们与NTR卡(NDS使用)没有太大区别。 内部有只读和/或可写存储。

CTR卡的变体差异很大。 它们的PCB可以捆绑一个尺寸从128MB4GB的ROM芯片,同时还包括一些“备份内存”来存储存档,这可以是128KB或512KB。 在其他变体中,整个CTR存储则填充了闪存(高达2GB),并且分区以将游戏和存档存储在同一个物理芯片中。

此外,由于游戏也将捆绑官方SDK,因此游戏可用的ROM/RAM容量取决于所链接的SDK版本。

在内部,ROM芯片连接到8位数据总线 [86],而备份内存依赖于串行总线。 两者都连接到16.6 MHz的时钟。 当卡插入主机时,3DS首先使用NTR(NDS)命令查询它[87],然后一旦检测到它是3DS卡,就切换到“CTR模式”。

eShop/SD卡

Image
任天堂3DS的任天堂eShop商店。

可扩展存储,第八代主机的标志。 任天堂3DS现在可以从SD(或microSD)卡安装和启动软件;因此,零售卡不再是游戏的唯一介质。 事实上,SD存储是新兴分发渠道的结果:捆绑在每台任天堂3DS中的任天堂在线商店。

多亏了eShop,出现了新的分发技术:用户可以在发货日期之前预订游戏和DLC[88]。 这些会在发售日期到来之前下载,但只能在发售日期到来后才能玩。

在存储各自的存档时,任天堂允许其下载的软件请求最多1MB的SD卡存储。 但是,如果零售版本已经需要更多空间,则此规则将被豁免,在这种情况下,系统将分配与相应CTR卡已提供的“备份内存”一样多的空间。

本地无线

Download Play,NDS的一项首次亮相功能,允许玩家在主机之间传输小型游戏,现在已推向任天堂3DS。 它现在带有一个经过改进的协议,该协议依赖于厚重的安全层,与新主机中执行的其他软件保持一致。

我想说现在最大的区别是,传输的游戏(或者“演示版”,就其价值而言)现在被安装到NAND中(与其他任何可安装包一样) [89]。 只为它们保留了一个插槽,因此每当有新游戏传输进来时,已安装的程序就会被替换。

Virtual Console

如果,在解释了所有这些之后,用户仍然感到无聊,任天堂为他们准备了另一个产品:Virtual Console

Image
Game Boy Color游戏的Virtual Console目录。
Image
Game Boy Color游戏在任天堂3DS上运行的示例。 默认情况下,游戏会缩放到全屏(保持原始宽高比) 然而,按住“Start”或“Select”键,你将获得一个1:1的比例,并带有一个漂亮的边框。

再次,多亏了捆绑的eShop应用程序,任天堂还通过整合最初为以下主机发布的游戏来扩展其3DS独占目录:

Virtual Console游戏表现得与安装在主机中的任何其他应用程序一样。 除了DSiWare软件,应用程序包中包含一个ROM和模拟器。 后者实现了有趣的功能,例如下载游戏(针对某些游戏)和存档状态。

Image
SFC游戏的Virtual Console目录(仅限New 3DS用户)。
Image
SNES游戏在任天堂3DS上运行的示例(由于游戏暂停,显示屏显得昏暗)。 请注意选项菜单如何允许你在[4:3 and 8:7 aspect ratios]之间切换(super-nintendo#display-modalities)。

再次,新3DS用户的情况有所不同,因为他们还可以访问SFC目录。 这尤其让我感到奇怪,因为我记得有一段时间(自制)SNES模拟器是为初代任天堂DS开发的(它只有区区ARM9-ARM7和几兆RAM)。

额外的向下兼容性

现在,这里还有虚拟主机游戏的一个特殊之处:这款主机也可以正式玩Game Boy Advance游戏。 然而,它们并非对所有人开放。 只有在2011年8月之前购买任天堂3DS的用户(就在主机降价80美元之前),才成为“大使计划”的成员 [90]。 其中一项福利包括可以访问一系列GBA游戏,这些游戏出于某种原因至今仍保持独占。

Image
HOME菜单上显示的GBA游戏示例。
Image
GBA游戏在任天堂3DS上无需模拟运行(AGB_FIRM上没有截图功能)。

更令人费解的是,GBA游戏并非在ARM11上使用模拟器运行(尽管安装了一个,但从未被使用过!)。 相反,它们启动第三个固件AGB_FIRM,以在ARM7之上原生运行。 最终,这些独占GBA游戏仍然是AGB_FIRM的唯一用途,就好像任天堂计划在未来推出更大的东西,但从未实现。 这是任天堂3DS拥有比软件实际利用的更多硬件的又一个例子。

如果你好奇,GBA游戏使用的是捆绑的ARM7核心。 因此,它们不允许模拟器(在ARM11核心上运行)提供的额外功能。 尽管如此,这以牺牲全速和精确度运行为代价。 无论如何,由于3DS不包含GBA卡槽,GBA游戏会在系统重启到AGB_FIRM之前复制到FCRAM中,然后让ARM7控制(而ARM11和ARM9提供基本支持任务) [91]

拥有所有这些功能,并且作为一款便携式主机,人们不禁会想,为什么任天堂没有在eShop上分发GBA和任天堂DS/DSi游戏。 我感觉,很可能是一个营销和授权问题。

游戏更新

第八代主机的另一个要求是,游戏现在可以在发货日期之后接收补丁。 没错,不再需要在销售前对游戏进行质量控制了!

抛开讽刺不谈,游戏更新也通过eShop分发 [92],这适用于所有类型的游戏(下载游戏除外)。 所有更新都会下载到SD卡上,eShop游戏会将其更新(连同游戏本身)一起应用。

网络服务

旧的(任天堂Wi-Fi连接)退出,新的(任天堂网络)登场! 与Wii U提供的相同服务也在任天堂3DS上实现,而且它们统一得非常好,所以我建议查看Wii U文章,其中有详细解释。


反盗版和自制游戏

这款主机的破解历史是一段漫长而有趣的事件序列。 最初,人们的兴趣集中在破解游戏卡读卡器(试图复制NDS的成功),然后转向更复杂的、只涉及操作系统的方案。

主要目标

首先,我们先来描述这个系统的两个主要目标:

它们可能看起来是两个独立的战线(类似于Xbox 360Wii U),但在这款主机的情况下,两者是相互交织的。 你很快就会看到。

读卡器战线

读卡器是CPU与游戏卡内存芯片之间的接口。 它的唯一工作是利用命令简化通信。

在CTR卡带的ROM/闪存内部,系统会找到一个名为NCSD的安全格式数据块,这将由操作系统处理,操作系统将负责对其进行认证、验证和解密。

总之,似乎操作系统全权负责与读卡器的通信,所以我们继续下一个战线。

操作系统战线

我们继续之前,如果你不熟悉对称和非对称加密系统,我建议阅读本系列之前的文章。 它们还将解释为什么像这样的系统如此依赖非对称加密系统(如RSA和ECDSA)。

专用硬件

如果你怀疑ARM11缺乏保护整个系统的强大能力,那你是对的。 任天堂也知道这一点,所以他们格外小心,捆绑了额外的组件来弥补:

  • ARM11核心实现了XN标志,ARM9捆绑了内存保护单元(MPU),这意味着CPU不会仅仅因为当前程序告诉它这样做就从内存中的任何位置执行代码。
  • 如前所述,ARM9充当专用处理器来处理所有与安全相关的任务,而ARM11 MPCore执行游戏。 此外,ARM9专门连接到几个隐藏的加密加速器
    • 一个AES引擎,无需消耗(和暴露)CPU资源即可执行AES-128加密/解密。 这继承自NDSi,但现在可以存储多达64个密钥,并可以在多种分组密码模式下运行,包括CTR、CCM、CBC和ECB[93]。 每个密钥槽还具有自己的密钥混淆器,这意味着可以使用两个任意密钥生成最终的AES密钥。 此外,密钥混淆器不允许任何人读取生成的密钥,只能将其视为黑盒来加密/解密数据。
    • 一个RSA引擎。 相比之下,它使用给定的RSA公钥执行RSA加密/解密。 这次,它只包含四个密钥槽,并且没有密钥混淆器 [94]。 但是,它仍然是一个只写空间,这意味着没有人能够读取存储在那里的密钥。 你很快就会看到,这个系统充满了RSA-2048和RSA-4096签名,这解释了为什么这个组件与AES引擎一样关键。
    • 一个伪随机数生成器(PRNG):这些寄存器每次读取时都返回不同的值。
  • OTP(一次性可编程)内存,存储主机独有的密钥、主机信息和CTCert(用于与任天堂服务器进行身份验证的ECDSA私钥)。 为了进一步复杂化,这些密钥将使用Boot9中找到的AES-CBC密钥进行加密。 最后,该区域包含一个标志,一旦不再需要,就禁用其访问。
  • 最后但同样重要的是,eMMC内存包含一个名为CID(卡识别)的寄存器,并存储有关eMMC制造的独特信息,这些信息将输入到AES的密钥混淆器中以进一步混淆。

最重要的是,所有东西都密封在一个SoC中,包括两个引导ROM(Boot9和Boot11)。 这些是未加密的,但由于它们无法访问,因此它们不构成威胁。

信任链

考虑到我们已经介绍了RSA、AES和引导ROM作为安全系统的一部分,这应该不足为奇。 为了让你大致了解任天堂3DS的信任链:

  1. ARM9的引导ROM(Boot9)捆绑了用于解密和验证NAND内容的公钥。 AES引擎将使用Boot9中存储的密钥进行初始化。 通过此,将访问OTP内存的内容。
  2. eMMC的内容使用Boot9的AES密钥结合eMMC CID进行解密。
  3. NAND和CTR卡使用NCSD格式进行格式化[95]。 NCSD存储一个头和最多八个分区的集合。 NCSD头包含使用RSA-2048和SHA-256的签名,这相当强大。 为了解密此签名,系统会在引导ROM或ITCM内存中找到其RSA公钥(后者先前已从OTP解密并复制)。 选择取决于NCSD块的来源(NAND或CTR卡)。
  4. 一旦NCSD块被验证,系统就会访问每个分区。 这些分区使用NCCH(Nintendo Content Container Header)格式构建。 无论数据是从NAND、CTR卡还是SD卡中提取的,NCCH块也包含RSA-2048 + SHA-256签名 [96],并且其负载使用AES-128 CTR进行加密。
  5. 此外,已安装的软件以title(类似于Wii系统)的形式进行分类。 在这种情况下,所有标题都使用RSA-2048、RSA-4096或ECDSA进行签名;加上SHA256 [97]。 公钥存储在NATIVE_FIRM中。
    • 令我惊讶的是,有些签名是ECDSA形式的,考虑到没有安装硬件加速器。
  6. 一旦负载经过验证和解密,系统就会找到ARM11可以读取的可执行文件、库或资产(即手册、图标或横幅)。

请注意,此解释侧重于主3DS固件(NATIVE_FIRM)。 然而,TWL_FIRMAGB_FIRM也将实现各自的加密。

随着时间的推移,黑客掌握了这款主机的保护方式,任天堂进一步调整了信任链,以阻止NCCH数据的解密。 在某些方面,它达到了目的,但在另一些方面,任天堂最终暴露了太多。 你将在以下章节中看到。

操作系统功能

一旦NATIVE_FIRM启动并运行,除了上述信任链之外,还存在以下安全机制:

  • 用户程序只能通过系统调用访问硬件功能,这些调用由Kernel11酌情授权。 根据硬件的不同,它还将涉及Kernel9。
  • 从架构角度来看,ARM11用户程序完全不知道ARM9及其相邻组件。
  • 用户应用程序是沙盒化的,这意味着它们无法访问彼此的空间。
  • 最后但同样重要的是,随着在线服务的增加,用户将需要合法的游戏卡和更新的固件才能访问新功能。这将阻止那些可能考虑将主机保持在易受攻击固件上的用户。 这将阻止那些可能考虑将主机保持在易受攻击固件上的用户。
  • 从eShop下载的软件也有其怪癖。 在这种情况下,标题的许可证以Ticket的形式编码,票证再次使用RSA-2048和SHA-256进行签名 [98]。 Ticket要么链接到单个主机ID和eShop的用户帐户;要么对任何主机都是全局的。 此外,任天堂在下载标题的元数据中使用额外的RSA证书,以进一步扩展信任链 [99]

缺陷

尽管任天堂3DS采用了现代保护技术,例如非对称加密和大量可用硬件,但在其实现中仍然存在一些根本性缺陷。 请看黑客社区发现的以下内容:

这不仅为首次攻击尝试铺平了道路,而且在任天堂试图修补其系统时,也将成为其限制。

击败

任天堂3DS和自制程序的历史是一个成功的故事。 大量的视频教程可以证明这一点。 然而,这段经历也揭示了非常巧妙的发现,从最初需要专有且昂贵的设备,演变为只需在电脑上点击几下即可完成。

DS烧录卡时代(2011-2013)

从何说起呢? 嗯,就从任天堂DSi停下来的地方开始:烧录卡

2008年任天堂DSi发布后,任天堂加入了一个新元素来对抗烧录卡:一个列出所有授权卡的白名单文件,从而阻止“未经授权的卡” [104]。 烧录卡制造商绝没有停止生产,他们只是推出了旧烧录卡的新变体,允许用户重新编程卡带头,使卡能够识别为不同的授权游戏,而任天堂则不断修改列表(通过软件更新)。

这种方法也涵盖了3DS,遵循与NDSi相同的过程。 他们绝不会获得独占的3DS硬件访问权限,但这就是自制程序在这款主机上开始的方式。

3DS烧录卡时代(2013-2016)

这款主机的前两年并没有取得太大进展(这对任天堂来说是一项重大成就!)。 然而,在2013年8月,情况发生了转变……

第一张_真正_的3DS烧录卡
Image
Gateway3DS套装[105]

忽略了从未出现的“3DS烧录卡”的预告[106]Gateway3DS可以被认为是第一款可以买到的3DS烧录卡。 然而,其说明并不像DS的那么简单。 你可以通过查看盒子里的内容来感受这一点:

  • 一张列入白名单的DS烧录卡(称为_蓝色Gateway_),其唯一目的是运行Gateway制作的NDS ROM。 作为“安装”过程的一部分,用户首先需要运行这个“游戏”并按照说明操作。
  • 一个要放置在3DS SD卡中的Launcher.dat文件。
  • 一张3DS烧录卡(称为_红色Gateway_),用于加载3DS游戏。 像任何其他烧录卡一样,它也带有一个microSD卡槽,用于存储3DS游戏。 然而,最大的区别在于3DS游戏镜像被刷入microSD卡中,这意味着一次只能存储一个3DS游戏。
    • 这说得通,因为RSA签名不能伪造(至少,这在计算上是不可行的)。 然而,复制游戏的精确克隆(NCSD块)却成功了。 暂时忘掉自制程序吧。

完成安装过程后,用户必须按照以下说明运行任何游戏:

  1. 插入_红色_Gateway卡。 暂时什么都不会出现。
  2. 打开3DS设置应用程序,导航到DS配置文件编辑器屏幕。
  3. 出于某种原因,3DS将重启,刷入的3DS游戏将显示出来。
  4. 玩完游戏后,返回HOME菜单将在3DS的SD卡中创建一个存档文件。

就这样,用户现在可以从网上下载3DS ROM并在他们的主机上运行了……但这怎么可能呢? 任何人是如何设法提取解密游戏的? Gateway3DS使用了(甚至发现了)哪些漏洞?

事实上,这个产品内部隐藏着大量功能。 让我们一步步分析。

Gateway3DS内部
Image
3DS设置应用程序中的DS消息编辑器。 字符限制仅由图形界面强制执行。

2012年某个时候,黑客“ichfly”在NDS的旧配置文件编辑器中发现了一个有趣的现象,该编辑器存在于NATIVE_FIRMTWL_FIRM中。 在其中一个文本字段中,你可以输入一个“消息”值,然后该值将作为问候语显示在PictoChat聊天室中[107]。 3DS的设置应用程序不允许你输入超过允许的字符数。 然而,没有任何东西可以阻止任天堂DS游戏这样做。 这种情况发生时,打开3DS的系统设置应用程序(称为MSET)会崩溃,有趣的是,这是由堆栈溢出引起的[108]。 这是否让你想起某个马的名字?

现在,Gateway神秘的Launcher.dat是设置应用程序通常读取的配置文件。 发生的情况是Gateway制作了他们自己的Launcher.dat,以嵌入用于其漏洞利用后续阶段的数据。 奇怪的是,Launcher.dat存储在NAND中(而不是SD卡中),因此最初的漏洞利用链也改变了设置应用程序从何处加载此文件。

如果你将此与Process9/Kernel9漏洞结合使用,你就可以获得该主机上的完全执行权限,并可以开始摆弄系统服务。 OTP和引导ROM等某些硬件仍然无法触及。 然而,这是一个重要的里程碑。

到目前为止还不错吧? 现在让我们将这些信息与Gateway的软件包联系起来:

  • DS/蓝色烧录卡只是安装损坏的DS配置文件(这将触发MSET漏洞利用)的入口点。
  • 3DS/红色烧录卡包含一个用固件编程的ProASIC3 FPGA(由Gateway分发)。 FPGA和microSD卡结合起来模拟零售游戏。
  • Launcher.dat是MSET漏洞利用的有效载荷。 它捆绑了一个内核漏洞利用和一系列系统补丁。 换句话说,一个自定义固件(CFW)。 运行Gateway CFW的主机可以提取游戏或使用红色烧录卡加载3DS游戏。 令人惊讶的是,Gateway还制作了他们的CFW,使其需要插入红色烧录卡才能工作(烧录卡中的DRM机制,情况逆转了吗?)。
后续轶事

直到2013年11月,Gateway似乎一切顺利,此时出现了大量其卡的克隆产品。 “R4i Gold 3DS Deluxe”加入了一些健康的竞争,尽管它使用了一些Gateway的固件代码。 作为报复,Gateway3DS采取了严厉措施:后续的Gateway3DS固件更新如果检测到克隆产品,就会损坏3DS NAND。 真是讽刺!

2013年10月,黑客“Smealum”发布了一段视频,展示了他自己的基于MSET的实现,该实现转而引导存储在3DS SD卡中的NATIVE_FIRM副本 [109]。 这意味着卡在系统版本4.5.0上的主机可以在不失去运行漏洞利用能力的情况下引导更新的系统版本。 Smealum将此功能称为redNAND(来自“重定向NAND”),虽然它没有公开发布,但Gateway后来在其2013年12月发布的CFW中整合了此功能(现在称为emuNAND[110]。 这成为Gateway3DS的一个强大卖点。

Gateway使用了什么Process9/Kernel9漏洞尚不清楚。 然而,在2013年12月,Fierce_Waffle、Xerpi和Megazig逆向工程并开源了Gateway的有效载荷,形成了一个名为“3DS Toolkit”的工具[111] [112]

在接下来的几年里,第二代3DS烧录卡将出现在市场上。 例子包括StargateSky3DS和数十个克隆产品。 这次,它们不依赖操作系统漏洞来工作,并且可以从它们的microSD卡加载多个游戏。 然而,它们的用途将完全基于复制零售3DS游戏(包括它们的签名),换句话说,仅仅用于盗版目的。

任天堂迅速采取行动

拥有可更新的系统软件意味着任天堂不必坐视不理地看着自己的系统被破解:

一如既往,这标志着另一场猫捉老鼠游戏的开始。 不过,长话短说,系统更新9.3.0(2014年12月发布)最终通过修补其私有内核漏洞 [115]终结了Gateway3DS。 从那时起,Gateway3DS的固件更新只改进了emuNAND对最新系统版本的支持(对于那些没有更新到破坏性更新的用户)。 2016年,Gateway发布了最后一个更新。 与此同时,Sky3DS享受支持直到系统软件11.0(2016年5月发布)[116],此时任天堂彻底将其列入黑名单。

我想现在可以公平地说,与任天堂DS正版卡提供的“即插即用”体验相比,3DS烧录卡市场最终对普通用户来说过于动荡和不可靠。 到目前为止,这对任天堂来说总算是一些好消息。

自制程序黎明(2014)

2014年,在盗版导向的开发圈子中,出现了以自制程序为中心的解决方案[117]。 破解3DS仍然需要旧系统版本、Gateway3DS卡和emuNAND——但一旦替代工具获得关注,这种情况就会慢慢改变。

Image
Plutoo、Derrek和Smealum在第32届混沌通信大会(2015年)上展示他们的发现 [118],以下段落将解释其中大部分。
开源SDK

最初的自制程序以Launcher.dat文件的形式出现,这些文件是在devkitARM(用于基于ARM的CPU的通用工具链)和一套脚本的帮助下生成的。 Fierce Waffle提供了“ROP Loader”,这是一个工具包,包含一个用于安装MSET漏洞利用的DS程序;以及一个触发Kernel11漏洞利用的Launcher.dat。 值得指出的是,当时还没有任何工具可以帮助访问3DS的独占硬件。

2014年初,Smealum在yellows8、ichfly、WinterMute、fincs、mtheall和plutoo的合作下,发布了ctrulib,这是一个开源C库,旨在促进自制程序开发[119]。 现在它被称为libctru,由devkitPro团队维护,他们已将其整合到他们的工具链中。

一年后,neobrain发布了nihstro[120],一个PICA200着色器汇编器和反汇编器,使得PICA200的编程工作变得更加愉快。

要运行自制程序,用户可以选择将自制二进制文件刷入microSD卡,然后使用Gateway3DS引导它(因为他们的CFW已经禁用了签名检查)[121]

Ninjhax链
Image
Homebrew Launcher,灵感来自标志性的Wii对应产品。iconic Wii counterpart. 它的到来标志着3DS自制程序的复杂化。

Gateway的毒性更新给用户留下了痛苦的印记。 寻找非专有替代方案的时刻已经到来。

幸运的是,人们正在为此努力。 在2014年下半年,Homebrew社区迎来了一个新的里程碑:Smealum发布了Ninjhax,一个由以下组件组成的软件包 [122]

  1. 一个精心制作的QR码,供“Cubic Ninja”扫描,这是一款允许使用QR码共享用户设计关卡的游戏。 这成为了一个新的入口点漏洞。
  2. GSPWN:一个用户态漏洞,其中GPU的DMA用于覆盖HOME菜单的堆。 此外,与ROP结合导致权限提升。 这导致能够创建和终止进程、SD卡访问、解密和转储标题以及覆盖可执行数据。
  3. Homebrew Launcher:一个由于GSPWN而在HOME菜单进程下运行的新服务。 它提供了一个图形用户界面来加载未签名的自制应用程序(使用新的便携式.3dsx格式)并接管进程。 启动器通过打开一个具有足够权限的官方应用程序,然后用GSPWN劫持它,用自制代码替换代码,最后执行它来加载自制程序。
    • 凭借其修改用户数据的能力,Homebrew Launcher还可以用于安装随着发现而出现的替代入口点(即 OotHax、Ironhax等)。 从而减少对Cubic Ninja的依赖。 一个值得注意的售后漏洞是MenuHax,它利用了HOME菜单主题引擎中的一个漏洞,并在启动时触发,使其成为启动有效载荷的永久解决方案
    • 如果你好奇,Wii U也经历了类似的方法,作为运行Homebrew的早期尝试。

请注意,Gateway3DS这次不在考虑范围内。 无论如何,Homebrew Launcher仍然在用户态的范围内(这意味着自制应用程序只能访问64MB RAM,并且无法访问音频DSP [123])。

获得Kernel11访问权限

事实证明,在Ninjhax发布之前,2014年2月,yellows8获得了一个非常重要的发现:一个导致Kernel11权限的漏洞。

Kernel11使用一个名为memchunk header的结构来跟踪FCRAM中未使用的内存页。 这些数据以链表的形式存储,每个头包含前一个和下一个头的地址。 嗯,memchunk header存储在FCRAM中,可能由于GSPWN等其他漏洞而被覆盖。 因此,memchunk header可以被修改以授予用户态对AXI WRAM的访问权限。 通过这样做,攻击者最终可以修改Kernel11的页表,以授予用户空间所有FCRAM访问权限,从而导致对Kernel11的任意控制。 这个发现被称为memchunkhax

然而,任天堂在2014年12月修补了它[124]。 但是,一个名叫derrek的黑客发现了一个竞态条件,其中memchunk header的“next”指针可能被替换为精心制作的指针的位置。 因此,当Kernel11尝试访问精心制作的memchunk header时,它最终将以Kernel11权限执行任意代码。 就这样,memchunkhax2应运而生。

多亏了新的权限提升,自制软件获得了对系统(直到ARM9区域)的完全控制……但为什么要止步于此呢?

最受欢迎的工具

考虑到Gateway3DS的emuNAND、Ninjhax、CTRLib和新的内核漏洞的可用性,新软件的涌入太过巨大而无法忽视。 举几个例子:

新主机,永久性修改(2015)

当自制开发者忙于修改他们的系统时,任天堂发布了一款_新_产品,令所有人大吃一惊:New 3DS

除了额外的硬件(本文中已提及)之外,引导过程还增加了一个新阶段:arm9loader。 通过此,任天堂通过添加新密钥增强了其信任链,这些密钥必须借助OTP内存的哈希值进行解密(因此,使用主机独有的值)[133]。 然而,arm9loader和新密钥仍然存储在NAND中,这意味着内容可能被覆盖。 这导致了2015年最具破坏性的漏洞之一,涉及Plutoo、Yellows8和Delebile。

arm9loaderhax

arm9loader的第一次实现存在缺陷:ARM9系统的解密密钥从未从AES引擎中移除。 因此,借助额外的漏洞利用,可以重构部分加密密钥 [134]。 因此,任天堂很快再次尝试了arm9loader v1.1(在系统更新9.6.0中发现)。 巧合的是,这导致了一个更强大的漏洞:Plutoo发现用于解密ARM9系统的密钥从未经过验证。 因此,arm9Loader在引导NATIVE_FIRM时,即使解密数据错误(即 垃圾)也会引导。 此外,如果Firm0(NATIVE_FIRM的第一个副本)无法引导,Boot9将尝试加载Firm1,而Firm0的残余部分则留在ARM9的RAM中。

总而言之,如果:

……你就拥有了arm9loaderhax,一个在引导时提供Kernel9权限的任意代码执行的永久漏洞!

由于现在可以访问Kernel9(尽管通过困难的方式),因此投入了工作来简化该过程(即开发自动化安装程序)。

arm9loaderhax的影响

新的发现意味着新的发展。 在接下来的几个月里,更先进的工具将成为每个自制程序用户“必备”列表的一部分。

首先,一个“一统天下”的新CFW发布了:Luma3DS [135]。 在众多功能中,Luma3DS提供:

最初,Luma3DS是使用BootCtr引导的,但一旦arm9loaderhax成为任何3DS事实上的破解方案,情况就改变了。 因此,arm9loaderhax + Luma3DS的组合成为任何破解教程的一部分。

随之,其他软件也出现了:

值得一提的是,在撰写本文时,这些是安装在被破解3DS上最受欢迎的实用程序。

黄金时代(2016-2017)

然是一个通用且强大的解决方案,但安装arm9loaderhax仍然被认为是一项复杂而危险的活动。 这不仅需要预先转储主机的OTP内存(使用其他漏洞),而且忽略任何一步都可能将一台正常工作的任天堂3DS变成一块砖头。

但不用担心,新的开发正在进行中(考虑到任天堂仍在努力保护其主机,这是一项巨大的努力)。

Image
naehrwert、nedwill和derrek在第33届混沌通信大会(2016年12月)上展示了一系列新发现[139]

在33C3大会上,derrek公布了两项重大发现[140],这导致了后续的里程碑。

提取Boot9

由于某种原因,ARM9的RAM内容在复位后不会被清除。 因此,Derrek发现,通过使用外部硬件,他可以利用任意代码覆盖ARM9 RAM中(先前从Boot9复制的)异常向量。 然后,复位系统,在非常精确的时序下(也使用外部硬件)使其发生故障以触发异常,并希望ARM9执行了新代码。 这将包括类似“将Boot9的所有内容复制到RAM中的X位置”的操作。

果然,这奏效了。 通过此,Derrek和其他人设法分析了Boot9 ROM的内容,从而发现了新的漏洞。

Sighax

Boot9的一个漏洞是Sighax [141],这是Boot9的RSA-2048签名验证中的一个缺陷。 类型为“PKCS #1 v1.5”(该系统采用)的RSA签名包含一个名为填充的区域以防止被逆向。 此外,它们存储一个使用“ASN.1”模型编码的SHA-256哈希,这保证了被解密数据的真实性

现在,Boot9中找到的相应解析器缺乏多项保护,包括边界检查。 最终,这使得Derrek能够生成一个精心制作的RSA签名(通过暴力破解),该签名在任何数据上都将始终成功。 通过这样做,整个信任链被废止

对于好奇者,我建议阅读GBATemp上一篇更冷静地描述该理论的全面文章 [142]

有了这个,现在就可以为ARM9核心制作一个固件,用精心制作的RSA签名对其进行签名,将其安装到NAND中,然后Boot9将“直接运行它”。 现在的问题是,普通用户如何使用未修改的主机来做到这一点?

Boot9strap

时间来到2017年。 大多数人都知道Sighax的存在,但只有少数人能够应用它,这都是因为新方法需要一个精心制作的RSA签名和对NAND的写入访问权限,这两者都来之不易(而且别忘了任天堂仍在通过系统更新严厉打击用户态漏洞)。 幸运的是,Sighax正在民主化进程中。

尽管Derrek的公告没有包含合适的RSA签名或Boot9的副本(我猜是出于版权原因),但这并没有阻止黑客SciresM和Myria找到替代资源,使他们能够制作RSA签名。

总而言之,他们发现1.0.0之前的系统版本与Sighax之前暴露的漏洞存在相似之处[143],并且,多亏了这一点,他们能够开始暴力破解RSA签名。 结果是成功的,最终在大量英伟达GPU的帮助下找到了匹配[144]

现在他们可以制作Boot9会接受的替代固件了,他们需要找到一种方法将Boot9重定向到他们的有效载荷。 挑战是在Boot9隐藏其引导ROM之前重定向执行。 为了解决这个问题,两人通过ARM9的异常处理程序找到了一条路径。 ARM9无法覆盖这些处理程序,但NDMA可以——而且CPU可以命令NDMA这样做。

总而言之,该团队能够使用NDMA用跳转到任意代码填充异常处理程序,然后指示ARM9复制到NULL,导致一个将以无限制访问权限执行有效载荷的异常。 最终,这被打包在一个名为boot9strap的解决方案中,并充当一个替代引导加载程序,可以从SD卡加载有效载荷或继续正常引导。 因此,Godmode9添加了新的选项来备份OTP和引导ROM。

因此,boot9strap迅速取代arm9loaderhax,成为以最高权限加载任意代码的事实解决方案。

Ntrboot
Image
一些在ntrboot发现后销售的DS烧录卡有一个开关,可以启用“3DS模式”(见照片右上角),这可以触发ntrboot。

此时,只剩下一个问题:用户如何安装boot9strap?

嗯,团队并没有止步于此。 通过查看他们最近的Boot ROM转储,他们发现了一个有趣的例程:在引导过程中,Boot9会查询是否按下了特定的组合键并且盖子已关闭。 如果是,Boot9将(以完全权限)重定向执行到插入的NDS卡。

因此,ntrboot应运而生:将一个sighax签名的有效载荷刷入NDS烧录卡,使用磁铁模拟关闭的外壳,然后按下所需的组合键。 即时获得Boot9权限。

如果这还不够,任天堂无法通过软件更新修复这些漏洞,因为它们硬连接在Boot ROM中。 一个可能的解决方案是推出新的硬件版本,然而,从未出现过。

剩余的岁月(2018年至今)

现在自制社区已经完成了它的巨著,任天堂3DS的剩余岁月将只看到破解方法的简化,所有这些都共享相同的目标:安装boot9strap。

Image
随着破解3DS的方法急剧发展,有时对新用户来说发展得太快,像3ds.hacks.guide这样由社区维护的网站目前被誉为最可靠和最新的教程集。

此时,野外有许多漏洞:“SoundHax”、“Safehax”、“Browserhax”……太多了无法在此提及。 对于好奇者,3DBrew提供了一份全面的列表[145]

为了让你了解2023年漏洞利用变得多么优雅,让我向你展示一种用户依赖的常见方法,它不需要额外的硬件。 这个过程被称为“seedminer + BannerBomb3”,它结合了以下漏洞,其中大部分由zoogie编写:

  1. seedminer:安装在3DS SD卡中的用户数据使用AES-128-CTR加密。 其密钥由一个名为movable.sed的文件中找到的其他密钥构成(主机独有,存储在NAND中)。 嗯,后来发现这个文件可以通过使用主机的Friend Code、SD卡中的子目录名称(由主机生成)和短期暴力破解来重建。 一旦提取,这些密钥允许篡改SD卡中的DSiWare数据。
  2. BannerBomb3:一个当设置应用程序尝试解析已安装DSiWare游戏的横幅时,导致堆栈溢出的漏洞[146]。 结合seedminer,这作为具有Kernel11权限的入门级漏洞。
  3. 现在,如何利用BannerBomb3(即使用哪个有效载荷)取决于用户当时遵循的教程。 为了简单起见,有两条路线:
安全模式路线

这条路线包括利用SAFE_FIRM,并在早期教程中进行了描述:

  1. unSAFE_MODE:用户可以通过在主机启动期间按下组合键进入安全模式,然后替代固件允许用户执行系统更新,这对于修复主机很有用。 嗯,zoogie发现代理设置可以溢出 [147]。 因此,在安全模式下提供用户态执行。
  2. safehax:一个“firmlaunch-hax”的移植版本,可在SAFE_FIRM下工作。 任天堂最初在2015年2月发布的系统更新9.5.0中修补了它[148]。 然而,SAFE_FIRM是出厂固件的不可变副本,因此它具有NATIVE_FIRM曾经_享有_的旧漏洞。
    1. firmlaunch-hax:当固件启动时,ARM9将固件头存储在FCRAM中进行验证和解析。 借助竞态条件,执行可以控制ARM9,因此可以启动boot9strap安装程序。 任天堂通过将头保留在ARM9 RAM中来修复此问题,尽管这在SAFE_FIRM上未修补。
HOME菜单路线

一段时间后,新的教程提出了新的路线。 这利用了HOME菜单,采用了一种新的Menuhax风格的破解:

  1. menuhax67:屏幕亮度配置值可以溢出[149],导致从HOME菜单进行用户态控制。
  2. nimdsphax:一个现代漏洞利用链,结合了“ctr-httpwn”、“nimhax”和“dsp [150]
    1. ctr-httpwn by yellows8:用于网络连接的HTTP服务可以通过覆盖其堆内存(使用旧的GPU DMA漏洞)来控制[151]
    2. nimhax by luigoalma:使用ctr-httpwn升级并接管控制用户文件系统、主机配置和应用程序管理的服务[152]
    3. dsp pwn by luigoalma:使用nimhax控制DSP,DSP反过来使用GPU的DMA覆盖Kernel9内存空间。 从而获得ARM9权限。
2023年后和结论

无论如何,在撰写本文时,任天堂尚未完全屈服于这场猫捉老鼠的游戏。 2023年5月,系统更新11.17.0修补了BannerBomb3,使最后一个不需要额外材料的入口点之一失效[153]。 这意味着用户现在需要获得合法的3DS游戏(然后可以利用),一张兼容ntrboot的DS烧录卡;或者等待WebKit漏洞(新3DS浏览器只剩下一个[154]))。


这就是全部了,伙计们。

Image
我的任天堂3DS们。 除了左边的XL版,我还额外买了两个用于这篇文章:右边你看到的红色那台(最初列为“坏掉的”,结果只是电源插座接触不良)和另一台(正确列为“用于零件”)来拍摄主板照片。

呼!这又是个长篇大论了。 但很高兴您能够坚持下来并读到最后!

如果您很好奇幕后故事 —— 这篇文章我写了将近一年,主要原因太多太多了;但重要的是,我终于设法完成了它。

回头看的话,很难说 3DS 取得了如同 NDS 的成功。 考虑到写在这里的分析,我认为很多外在的因素阻碍了它的营销。 起初,他们发布的时机很不走运,价格也不太诱人。 从我的视角来看,在 2011 年发布的时候,2008 年经济危机的巨大影响仍在(那时我还在西班牙生活),所以 3DS 不太可能成为大人(或者小孩)的首选。 后来我来到了英国,2018 年的时候,我才终于搞来了一台。

无论如何,我要感谢 #ReSwitched 和 #Godmode9 指出了我初稿中的许多错误。 这或许是我(目前为止)研究过的最复杂的主机,所以我非常感谢能找到愿意提供帮助的社区。

下篇文章见!
Rodrigo


参与贡献

这篇文章是 游戏主机架构 系列的一部分。如果您觉得我的文章很有趣,请考虑捐赠。您的资助将用于购买工具和资源,以帮助我提高现有文章和即将发表的文章的质量。

Donate with PayPal
Become a Patreon

你也可以购买英语版本的电子书。我会将获得的利润视为捐赠。

eBook edition

特别感谢下列人员的捐助:

- All of the generous eBook readers
- Adam Obenauf
- Adrian Burgess
- Ahayri
- Alberto Massidda
- Alex Christensen
- Angus MacMullen
- Antonio Bellotta
- AT13C
- Ben Morris
- Bitmap Bureau
- Cedric Wille
- Chris B
- Chris Lidyard
- Christopher Owen
- Claire Morgan
- CyberpunkDre
- Daniel Cassidy
- Daniel Kamm
- danielsdesk
- David Golden
- Dudeastic
- Dylan Garrett
- Elizabeth Isley
- Encapsulation
- Erik Vunn
- Ghani Talib Elhoda
- Grady Haynes
- Hadlee Simons
- Hamza Khan
- J Konings
- Jacob Harrison
- James Scalzitti
- James William Jones
- Jason Lizarraga
- João Baptista
- John Mazouri
- José Miguel Sánchez García
- Lexa Fayte
- Lilia Roo
- lilo-san
- ltlollo
- Luke Groeninger
- Luke Wren
- M Kenny
- Maciej Korzeniowski
- Mahadi Xion
- Marc C.
- Martin Atkins
- Maxwell Grimley
- MCE
- Mia
- Michael Driscoll
- myltik 
- Neil Moore
- Nicholas T.
- Olivier Cahagne
- Owen Christensen
- Paul Wightmore
- Pedro Henrique Martins Garcia
- Peter Upfold
- petey893
- Red Wolf
- Sanqui
- Sariya Melody
- Scott Munro
- shy
- Simon Pichette
- Str33tz
- Thomas Finch
- Thomas Peter Berntsen
- Tian Zhang
- tomyun
- tucara
- ulala
- XON
- z-team
- zombie343

或者,您可以通过 建议更改添加翻译 来提供帮助。


Copyright and permissions

This work is licensed under a Creative Commons Attribution 4.0 International License. You may use it for your work at no cost, even for commercial purposes. But you have to respect the license and reference the article properly. Please take a look at the following guidelines and permissions:

Article information and referencing

For any referencing style, you can use the following information:

For instance, to use with BibTeX:

@misc{copetti-nintendo3ds,
    url = {https://www.copetti.org/zh-hans/writings/consoles/nintendo-3ds/},
    title = {3DS 的架构 - 一份实证分析},
    author = {Rodrigo Copetti},
    year = {2023}
}

or a IEEE style citation:

[1]R. Copetti, "3DS 的架构 - 一份实证分析", Copetti.org, 2023. [Online]. Available: https://www.copetti.org/zh-hans/writings/consoles/nintendo-3ds/. [Accessed: day- month- year].
Special use in multimedia (Youtube, Twitch, etc)

I only ask that you at least state the author’s name, the title of the article and the URL of the article, using any style of choice.

You don’t have to include all the information in the same place if it’s not feasible. For instance, if you use the article’s imagery in a Youtube video, you may state either the author’s name or URL of the article at the bottom of the image, and then include the complete reference in the video description. In other words, for any resource used from this website, let your viewers know where it originates from.

This is a very nice example because the channel shows this website directly and their viewers know where to find it. In fact, I was so impressed with their content and commentary that I gave them an interview 🙂.

Appreciated additions

If this article has significantly contributed to your work, I would appreciate it if you could dedicate an acknowledgement section, just like I do with the people and communities that helped me.

This is of course optional and beyond the requirements of the CC license, but I think it’s a nice detail that makes us, the random authors on the net, feel part of something bigger.

Third-party publishing

If you are interested in publishing this article on a third-party website, please get in touch.

If you have translated an article and wish to publish it on a third-party website, I tend to be open about it, but please contact me first.


来源 / 继续阅读

反盗版

音频

CPU

游戏

图形

I/O

操作系统

影像


Rodrigo Copetti

Rodrigo Copetti

希望你能喜欢这篇文章!如果想了解本文作者的相关信息,点击这里 如果你想支持他,请点击这里

rsslinkedintwitterblueskygithub facebookreddit