Game Boy Advance 之类的设备如何达到帧速率?

电器工程 avr 奥莱德 图形 atmega1284p
2022-01-21 12:49:03

我一直在围绕 AVR 微控制器和小型 OLED 显示器设计自己的手持游戏设备。

我从一个 128x64 像素的单色显示器开始,可以以每秒 60 帧以上的速度舒适地绘制它。

我最近对其进行了重新设计以使用 128x128 像素的 RGB OLED,并没有考虑太多,结果发现我只能达到大约 4 FPS。经过一番深思熟虑和仔细重构,如果我不太关心做其他任何事情,我可以将其提高到 ~12fps!

我的问题是——像 GBA(Game Boy Advance)这样的设备是如何实现接近 60fps 的帧速率的?我曾想过拥有一个单独的“图形处理器”,但意识到将显示数据传输到该处理器仍然会遇到瓶颈。

我还想知道使用大多数这些屏幕往往具有的残留 8 位并行接口,这可能会使我的速度提高 8 倍,除了现代 MCU 不像串行和位那样倾向于具有硬件并行接口-敲打可能会消耗很多速度增益。

还有哪些其他选择?

我目前正在使用通过 USART-SPI 连接到 SSD1306 OLED 控制器的 ATmega1284P。那是单色版本。

彩屏是SSD1351,原本没有连接硬件SPI。我不相信它会产生足够的差异,总体来说太慢了

我知道我可以获得更快的 MCU,但我想知道我可以探索哪些其他选项 - GBA 处理器比我的 1284 慢得多!

4个回答

其他答案在抽象级别(硬件)上很好地涵盖了您的问题,但特别是具有 GBA 的实际经验,我认为更详细的解释可能是值得的。

GBA 有许多绘图模式和设置,可用于控制图形处理器如何解释视频 RAM,但有一件事是不可避免的:帧速率。图形处理器在一个几乎(更多在下面)恒定循环中绘制到屏幕上。(这可能是与您的问题最相关的部分。)

它会一次画一条线,每条线之间有很短的休息时间。在为框架画完最后一条线后,它需要的休息时间大致等于画 30 条线所需的时间。然后重新开始。每一行的时间,每一帧的时间都是预先确定的,一成不变的。在很多方面,图形处理器确实是那个系统的主人,你需要围绕它的行为编写你的游戏,因为无论你是否准备好,它都会继续做它所做的事情。

大约 75-80% 的时间是主动推送到屏幕上。如果你做同样的事情,你能达到什么帧速率?

这 80% 的时间也是 CPU 必须处理用户输入、计算游戏状态以及将精灵/图块加载到当前不在屏幕(或至少不包括在当前绘制的行中)的 VRAM 区域的时间。

帧之间的 20% 是 CPU 必须调整会影响整个下一帧的视频设置或 RAM。

在每行结束时,图形处理器将向 CPU 发送行同步中断。此中断可用于调整一些精灵或一些背景层的设置(通过更改绘制的每条线之间的一个矩形蒙版的大小和位置,您可以获得类似锥形聚光灯的效果。作为就硬件而言,所有这些区域都是矩形的。)。您必须小心保持这些更新很小并在图形处理器开始绘制下一行之前完成,否则您可能会得到丑陋的结果。处理这些中断所花费的任何时间也会减少 80% 的 CPU 处理时间......

对于充分利用该系统的游戏,CPU 和图形处理器都没有真正休息过;每个人都在循环中追逐对方,更新对方目前没有看到的内容。

所有游戏机与早期 PC 和几乎所有家用计算机 (1) 的主要区别在于硬件精灵

链接的 GBA 编程指南从主处理器的角度展示了它们是如何工作的。代表玩家、背景、敌人等的位图被加载到内存的一个区域中。另一个内存区域指定精灵的位置。因此,处理器不必每帧重新写入所有视频 RAM,这需要大量指令,处理器只需更新精灵的位置。

然后,视频处理器可以逐个像素地工作,以确定在该点绘制哪个精灵。

但是,这需要两者共享双端口 RAM,我认为在 GBA 中,视频处理器与主 ARM 和辅助 Z80 处理器位于同一芯片上。

(1) 值得注意的例外:Amiga

“我的问题是——像 GBA 这样的设备是如何达到接近 60fps 的帧率的?”

为了回答这个问题,他们使用了图形处理器。我很确定 Game Boy 使用了精灵图形。在顶层,这意味着图形处理器会加载诸如背景图像、马里奥图像和桃子公主图像等内容。然后主处理器发出诸如“显示背景偏移量”之类的命令在 x 和 y 中很多,在这个 x,y 位置叠加马里奥图像#3”,等等。所以主处理器绝对不关心绘制每个像素,图形处理器绝对不关心计算的状态游戏。每个都针对它需要做的事情进行了优化,结果是一个非常好的视频游戏,而不需要使用大量的计算能力。

GBA 的处理器相当慢。ARM7 非常好;他们只是运行缓慢,几乎没有提供任何资源。

任天堂当时和之前的很多游戏都是横向卷轴游戏是有原因的。硬件。这一切都是在硬件中完成的。你有多层瓦片加上一个或多个精灵,硬件完成所有工作以从这些表中提取像素并驱动显示。

您在前面构建了瓦片设置,然后有一个很小的内存,即瓦片地图。想要左下方的瓷砖是瓷砖 7?你在那个内存位置放了一个 7。想要下一张牌是 19 号牌吗?在图块集中,您将 19 放在那里,以此类推为您启用的每个图层。对于精灵,您只需设置 x/y 地址。您还可以通过设置一些寄存器来进行缩放和旋转,其余的由硬件处理。

如果我没记错的话,模式 7 是一种像素模式,但这就像传统的视频卡,您在其中放置覆盖像素颜色的字节,而硬件负责视频刷新。我想你可以打乒乓球,或者至少当你有一个新框架时你可以翻转它们,但我记错了。同样,在那个时代,处理器的频率相当低,并且没有太多的快速资源。因此,虽然有些游戏是模式 7,但很多都是基于瓷砖的横向卷轴......

如果您想要一个高帧率的解决方案,您需要设计该解决方案。你不能只拿你找到的任何旧显示器并通过 SPI 或 I²C 或类似的东西与之交谈。至少在其前面放置一个帧缓冲区,最好是两个,并在可能的情况下对该显示进行行和列控制。

我怀疑您购买的许多显示器上都有一个您实际上正在与之交谈的控制器。如果您想要 GBA/控制台类型的性能,您可以创建/实现控制器。或者您购买/使用 GPU/视频芯片/逻辑块构建,并使用 HDMI 或其他通用接口连接到库存监视器。

仅仅因为自行车有轮胎、链条和齿轮,并不意味着它可以像摩托车一样快。您需要设计系统以满足您的端到端性能需求。你可以把那个自行车轮子放在那辆摩托车上,但它的性能并不理想;所有组件都必须是整体设计的一部分。

小行星也以这种方式工作。它只需要一个6502。矢量图是用单独的逻辑完成的;6502 向矢量图形控制器发送了一小串数据,该控制器使用 ROM 和该数据来绘制光束和 z 的 xy 绘图,开/关……一些站立有单独的处理器来处理音频和视频。计算游戏的处理器。当然,今天的视频由与主处理器分开的数百个(如果不是数千个)处理器处理......