在我们开始之前,你会发现该系统是SNES和Game Boy的混合体。 事实上,图形核心仍被称为PPU。 因此,我建议大家先阅读这些文章,因为我将重温许多以前解释过的概念。
与以前的Game Boy相比,我们现在有了一个液晶屏幕,可以显示多达32768色(15位)。 它的分辨率为240x160像素,刷新率为约60 Hz。
硬件组织
图形分布在这些内存区域中:
- 96 KB 16位VRAM(视频 RAM): 其中64 KB存储背景,32 KB存储精灵。
- 1 KB 32位对象属性内存(Object Attribute Memory,OAM): 最多可存储128个精灵条目(不是图形,只是索引和属性)。 如其大宽度所示,OAM的总线专为快速访问而优化。
- 1 KB 16位调色板RAM(Palette RAM,PAL RAM): 存储两个调色板,一个用于背景,另一个用于精灵。 每个调色板包含256个条目,每个条目有15位颜色,其中颜色
0表示透明。
构造帧
如果你读过前面的文章,你就会发现GBA并不陌生,不过它还有一些额外的功能可能会让你大吃一惊。 无论如何,新系统只需两节AA电池即可运行这一事实让本研究更加令人着迷。
我将借用世嘉的索尼克进化3(Sonic Advance 3)的画面来展示一帧画面是如何构成的。
图块

你可能会注意到这里有一些奇怪的垂直图案,这些不是图形,而是"图块地图"(见下一节)。
GBA 的图块是严格的8x8像素位图,可以使用16种颜色(4bpp)或256种颜色(8bpp)。 4bpp图块占用32个字节,而8bpp图块占用64个字节。
图块可以存储在VRAM的任何位置。 不过,PPU希望将它们分组为字符块:16 KB的连续区域。 每个字符块保留给特定类型的图层(背景或精灵),由程序员决定每个字符块的起始位置。 这可能会导致一些重叠,从而使两个字符块可以共享相同的图块。
由于字符块的大小,每个字符块最多可存储256个8bpp图块或512个4bpp图块。 总体而言,最多可分配6个字符块,总共需要96 KB内存: 这正是游戏机所拥有的VRAM容量。
只有四个字符块可用于背景,两个可用于精灵。
背景

背景层3(BG3)
该图层将在某些扫描线上水平移动,以模拟水的效果
自Game Boy Color推出以来,该系统的背景层有了很大改进。 它终于包含了超级任天堂中的一些功能(还记得仿射变换吗?)。
PPU 最多可以绘制四个背景层。 每个图层的功能取决于所选的运行模式:
- 模式0:提供四个静态图层。
- 模式1:只提供三个图层,但其中一个是仿射图层(可旋转和/或缩放)。
- 模式2:提供两个仿射层。
每个图层的尺寸最大为512x512像素。 如果是仿射层,则最大尺寸为1024x1024像素。
定义背景图层的数据称为图块地图。 现在,这些信息以屏幕块(screenblocks)的形式编码:一种定义背景层部分(32x32图块)的结构。 一个屏幕块仅占2 KB,但构建整个图层需要多个屏幕块。 程序员可以在VRAM的任意位置放置屏幕块,这些屏幕块可能会与背景字符块重叠。 这意味着并非所有图块条目都包含图形!
精灵
精灵的大小可以达到64x64像素。 然而,在如此小的屏幕上,精灵最终会占据屏幕的很大一部分。
如果这还不够,PPU现在还能对精灵进行仿射变换!
精灵条目有32位宽,其值可分为两组:
- 属性: 包含x/y位置、水平/垂直翻转、大小、形状(正方形或矩形)、精灵类型(仿射或常规)和第一个图块的位置。
- 仿射数据: 仅用于仿射精灵。 它们指定了缩放和旋转。
结果
一如既往,PPU会自动合并所有图层,但这还没有结束! 系统有几种效果可以应用在这些图层上:
- 马赛克:使图块看起来更加方方正正。
- Alpha混合: 结合两个重叠图层的颜色,产生透明效果。
- 窗口效果: 将屏幕分成两个不同的窗口,每个窗口都可以有自己独立的图块和特效,两个窗口的外部区域也可以用图块渲染。
另一方面,有多个选项可用于更新帧:
- 命令CPU: 处理器现在可以随时完全访问VRAM。 不过,如果它在帧中改变某些数据,可能会产生不必要的假象,因此在大多数情况下,等待垂直/水平消隐(VBlank/HBlank)(传统方法)仍然是最安全的选择。
- 使用DMA控制器:DMA传输速率快10倍,可在 垂直/水平消隐期间调度。 该游戏机提供四个DMA通道(两个预留给声音,一个用于关键操作,另一个用于通用)。 请注意,在操作过程中,控制器将使CPU停止运行(尽管CPU几乎不会注意到这一点!)。
超越图块
有时,我们可能想制作一个背景,而图块引擎无法从中绘制出所有需要的图形。 现在,现代游戏机通过帧缓冲区架构解决了这一问题,使程序员可以单独任意改变每个像素。 然而,在内存极小的情况下,这是不可能实现的...... 而GBA恰好有96 KB的 VRAM。 这足以分配一个与我们的LCD屏幕一样大小的位图。
好消息是,PPU通过三种额外模式实现了这一功能,这些模式被称为位图模式:
- 模式3:分配一个全彩(16bpp,32768色)帧。
- 模式4:提供两个帧,每个帧只有一半的颜色(8bpp,256色)。
- 模式5:提供两个全彩帧,每个帧的大小减半(160x128像素)。
使用两个位图的原因是为了实现翻页功能(page-flipping): 在显示的位图上绘图可能会在过程中出现一些奇怪的假象。 如果我们改用另一个位图,用户就不会看到任何异常。 一旦第二个位图绘制完成,PPU 就可以更新以指向第二个位图,从而有效地交换显示的帧。

超级猴子球(Super Monkey Ball Jr.)(2002)
位图模式允许CPU为场景提供一些基本的3D图形
前景对象是精灵(独立图层)。

Tonc的演示
使用一些基元对位图进行渲染
注意屏幕上没有显示由图块引擎产生的明显图案

尼克(Nickelodeon)的《海绵宝宝》(SpongeBob SquarePants)
作为GBA视频卡带发行的剧集(当然,它受到了很大的压缩)。
总的来说,这听起来像是一项尖端功能,然而,大多数游戏都坚持使用图块引擎。 为什么呢? 因为在实践中,它耗费了大量的CPU资源。
图块引擎使CPU能够将大部分计算工作委托给图形芯片。 相比之下,PPU提供的帧缓冲区系统仅限于将该内存段显示为单个背景层,这意味着除非CPU进行计算,否则无法再进行单独的仿射变换、分层或特效。 此外,帧缓冲区占用80 KB内存,因此只有16 KB(一半)可用来存储精灵图块。
因此,这些新模式主要用于特殊情况,如播放动态视频(Game Boy Advance Video系列完全依赖于此)或显示3D几何图形(由CPU渲染)。 无论如何,其结果至少可以说是令人印象深刻的。





