剖析超级任天堂视频系统

Fabien Sanglard 新闻

摘要

从任天堂工程师的视角,详细探讨超级任天堂的视频系统设计,解释CRT技术与工程选择。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/05/16 03:35

# 设计超级任天堂视频系统 来源:https://fabiensanglard.net/snes_video/index.html 2024年7月29日 设计超级任天堂视频系统 --- 上一次,我探索了超级任天堂卡带的内部结构(https://fabiensanglard.net/snes_carts)。今天,我将深入其视频系统。 我设身处地,想象自己是上村雅之(Masayuki Uemura)团队[\[1\]](https://fabiensanglard.net/snes_video/index.html#footnote_1)[\[2\]](https://fabiensanglard.net/snes_video/index.html#footnote_2)中的一位任天堂工程师,通过研究1989年可用的设备(即电视机),来理解设计SNES视频系统时必须做出的决策。 以下是我学到的内容总结。或许你会喜欢一起探索。 90年代初的电视机内部有什么? --- SNES输出视频的屏幕是一台标准的电视机。它通常用来观看《足球小将》、《哥普拉》、《铁臂阿童木》、《宇宙海盗哈洛克》、《圣斗士星矢》或《龙珠》。 屋顶上有天线接收模拟电视广播(NTSC),一根电缆将信号传输到调谐器,最后是显示图像的部分,称为阴极射线管(CRT)。 更重要的是,有辅助(AUX)输入。基本电视机有一个复合视频接口(黄色),用于传输视频信号。辅助立体声音频信号通过专用插孔传输(在我的丑陋画作中分别为白色和红色)。 CRT的工作原理 --- CRT是一台超级画线机器。当时,它们的额定频率为15kHz,这意味着每秒能绘制大约15,000条线。 CRT内部有一个带有三个电子枪的电子枪组。电子枪始终向前方直线发射电子,两组磁铁(一组垂直,一组水平)控制它们上下左右移动。 在上面的画中,我给电子枪的射线上了色,但这只是为了方便读者理解。电子本身没有颜色。在荧光粉条前面有一个荫罩,确保每个电子枪的电子落在正确的颜色条上。 CRT的世界里没有像素。一个槽**不是一个像素**。下面的画放大了一条扫描线,其中槽的各个部分被击中。唯一可以保证的是,电子枪发射的电子始终落在正确的颜色条上。 高清电视的槽更小,能够更好地渲染颜色信号。在下面的画中,同一条线水平渲染时,由于槽的密度更高,保真度也更高。 如何控制CRT --- CRT消耗五个信号,通过四根线传输。红、绿、蓝信号各有一根线,直接连接到电子枪的阴极。信号越高,发射的电子越多,荧光粉条越亮。三根线上都没有信号意味着没有电子发射,从而在该线上显示黑色。 上图中的白线承载同步信号。有两个信号,分别称为水平同步(HSYNC)和垂直同步(VSYNC)。这两个信号使用同一根线,因此称为复合同步(CSYNC)。 由于我有PC编程背景,我曾习惯于“等待VSYNC”,这让我错误地以为CRT会发出该信号。这是不对的。CRT什么都不发出,它只消耗信号并尝试让电子枪与之同步。 CRT如何绘制图像 --- CRT从左到右绘制一条线(也称为光栅)。当它接收到HSYNC事件时,它会“返回”到屏幕左侧(X=0)。当它接收到VSYNC事件时,它会返回屏幕顶部(Y=0)。 细心的读者会发现这些事件有一个问题:没有办法向下移动。驱动CRT的系统可以随意发出任意多次HSYNC和VSYNC,但最终只会反复绘制屏幕顶部的同一条线。 理解CRT的关键 --- 理解CRT的关键在于明白电子枪会以**向下倾斜**的方式移向屏幕右侧[\[3\]](https://fabiensanglard.net/snes_video/index.html#footnote_3)。在HSYNC时,CRT返回X=0,但由于电子枪已经向下瞄准,下一条线将绘制在前一条线下方。 这为一些很酷的技巧打开了大门。上图画了一个信号,其中VSYNC与最后一次HSYNC同时发出。线条始终绘制在屏幕上的同一位置。但看看下面,如果在两个HSYNC之间发出VSYNC会发生什么。 由于底部只绘制了半条线,CRT开始在屏幕顶部以相同的X位置绘制下一条线。下一组线将与上一组线交错。 线组被称为“场”。场绘制在同一位置的模式称为“逐行”扫描(“p”)。场交错的模式缩写为“i”。在i模式下,垂直分辨率翻倍,但每条线的刷新率减半。 NTSC以约30赫兹的频率发出两个场。因此,所有CRT都在线之间预留了足够的空间用于隔行扫描。以逐行模式绘制时,可以看到扫描线间距。这会导致线之间出现黑色间隙[\[4\]](https://fabiensanglard.net/snes_video/index.html#footnote_4),这是CRT光栅化的特征。 *可见的扫描线间隙。图片来源:retrogameboards.com(https://www.retrogameboards.com/t/scanline-screenshot-thread-because-240p-is-all-the-ps-i-need-56k-warning/71/83?page=5)* 线内有什么? --- CRT在绘制线条时是数字化的,但线内的内容却是模拟的[\[5\]](https://fabiensanglard.net/snes_video/index.html#footnote_5)。如上图所示,三个电子枪直接连接到三根RGB线。系统可以随意改变颜色信号(因此可以使用任何水平分辨率)。唯一的限制是信号传播和荫罩密度。 处理现有设备 --- 虽然SNES设计者可以在线上发出他们想要的信号,但他们仍需确保CRT能够处理这些信号。由于硬件是为显示NTSC信号而设计的,他们的任何决策都必须接近这些规格[\[6\]](https://fabiensanglard.net/snes_video/index.html#footnote_6)[\[7\]](https://fabiensanglard.net/snes_video/index.html#footnote_7)。 - 4:3 宽高比 - 每场行数:262.5 - 每行点数:341.25 - 场频率:59.94Hz 59.94Hz真是个奇怪的数字。难道电网不是以60Hz运行,而电视直接使用交流频率吗?黑白NTSC原本是60Hz。当广播工程师必须找到一种方法在不破坏向后兼容性的情况下将颜色添加到NTSC信号中时,他们决定将频率降低0.1%以避免伪影[\[8\]](https://fabiensanglard.net/snes_video/index.html#footnote_8)[\[9\]](https://fabiensanglard.net/snes_video/index.html#footnote_9)。 作为一名任天堂工程师 --- 现在我们了解了CRT的工作原理,是时候扮演任天堂工程师,设计一个视频系统了。 首先需要选择使用多少条线。NTSC每场使用262.5条线,但半条线用于隔行扫描。我们可以使用262条线来实现逐行扫描。目标帧率为59.94,这需要每秒15,734.26条线,在15KHz额定值的4%以内。 CRT屏幕的宽高比为4:3。如果我们水平使用350个点,将完全匹配该宽高比,并且当控制台图像转换为扫描线时不会出现失真。 262条线,59.94Hz,每条线350个点,意味着我们需要一个以262 * 350 * 59.94 = 5,496,498Hz脉冲的点时钟。我们可以设计一个ASIC来计数点时钟滴答。每350个滴答发出一个HSYNC。每350*262 = 91,700个滴答发出一个VSYNC[\[10\]](https://fabiensanglard.net/snes_video/index.html#footnote_10)。我想我们是不是完成了? 还没完成,我们才刚刚开始。 --- 这个简单的设计有两个问题。 1. 它需要一个5,496,498Hz的点时钟,而我们没有。SNES的成本限制使得视频系统无法拥有独立的振荡器。有一个主振荡器,子系统必须通过分频器来使用它[\[11\]](https://fabiensanglard.net/snes_video/index.html#footnote_11)。 2. 你不能一直绘制颜色。这被称为过扫描。它值得单独一节来讨论。 介绍过扫描 --- 当电子枪位置水平或垂直重置时,它仍会继续发射电子。如果继续发射,会产生可见伪影。 另一个要考虑的是,电视往往会过扫描其屏幕区域[\[12\]](https://fabiensanglard.net/snes_video/index.html#footnote_12),这意味着屏幕上的图像比显示区域稍大。电视过扫描的程度因电视而异。这有助于隐藏抖动。 当电子枪垂直位置重置到Y=0(VSYNC之后)时,它会上下波动一段时间。只有在几微秒后,才能得到直线。水平方向在HSYNC之后也会出现同样的问题。 所有这些问题的解决方案是在VSYNC之后和HSYNC之后“停止”CRT电子枪一小段时间。这些不发射电子的时间段分别称为VBLANK和HBLANK。 那个时代的所有游戏系统都使用了消隐。以下是SNES竞争对手的总结。 | 机器 | 年份 | 行数 | VBLANK行数 | 可见行数 | 每秒行数 | 帧率 | |------|------|------|------------|----------|----------|------| | Capcom街机CPS-1 | 1989 | 262 | 38 | 224 | 15,622 | 59.6294[\[13\]](https://fabiensanglard.net/snes_video/index.html#footnote_13) | | Sega Genesis | 1989 | 262 | 38 | 224 | 15,700 | 59.9227[\[14\]](https://fabiensanglard.net/snes_video/index.html#footnote_14) | | Neo-Geo AES[\[15\]](https://fabiensanglard.net/snes_video/index.html#footnote_15) | 1990 | 264 | 40 | 224 | 15,734 | 59.18[\[16\]](https://fabiensanglard.net/snes_video/index.html#footnote_16) | 选择SNES的垂直分辨率 --- 如果仔细看上面的回顾表格,我们会发现所有竞争系统,即Mega Drive、Neo-Geo和Capcom的CPS-1,都使用了224条可见行数。 他们可能不是随机选择这个数字的。224可以被16整除(224/16=14),这意味着它与图形渲染管线中的tilemap配合得很好。 我最好的猜测是,任天堂不想重新发明轮子。他们不需要更高的分辨率,而是需要更好的图形。让系统脱颖而出的原因是它的PPU。 最终,他们选择了安全的方式,将每帧262行分为224条可见行和38条消隐行(如右侧的图所示)。 街机游戏可以根据每款游戏的需要调整设置。Irem公司的R-Type设计师对CRT默认的“标准”224条有效行数不满意。 他们校准了M72系统的寄存器,绘制284行、512个点,并使用8MHz的点时钟。将128个点留给HBLANK,28行留给VBLANK,最终有效分辨率为384x256,这比当时的其他街机游戏都要高。 代价是垂直刷新率为55.017605 Hz,这在视觉上不太令人满意,并且与CRT推荐值有10%的危险偏差。这个刷新率对于“现代”模拟器来说难以复制,但对于一个1987年的系统来说,这是一项多么令人印象深刻的技术壮举! *R-Type(1984年)拥有惊人的256条可见行数(图片来源:维基百科(https://en.wikipedia.org/wiki/R-Type))!* 选择SNES的水平分辨率 --- 到目前为止,我们已经选择了每帧的行数(262)。我们也知道无法自由选择点时钟。我们必须使用主时钟(21.47727MHz)并通过分频器得到一个接近NTSC点时钟的值。这使我们只能使用21.47727 MHz / 4 = 5.3693175 MHz的点时钟。 行数、点数、点时钟和刷新率通过帧率公式相互关联。 刷新率 =行数 * 点数 / 点时钟 鉴于我们的目标刷新率是59.94Hz,我们对每个行数的点数没有太多选择。 点数 =5369317.5(点时钟)/262(行数)* 59.94(刷新率)≃ 342 然而,由于涉及复合输出时载波伪像的一些复杂原因,任天堂工程师不得不使用每行341个点而不是342个点。这使得SNES的帧率为: 刷新率 =5369317.5 /(341 * 262)=**60.098Hz** 60.098Hz并不是NTSC的59.94 Hz,但正如之前R-Type的例子所示,CRT具有一定的容差,所以这仍然可行。如果你喜欢这部分内容,Nerdy pleasure有更多详细内容[\[17\]](https://fabiensanglard.net/snes_video/index.html#footnote_17)。 选择SNES的水平过扫描 --- 在这341个点中,并非所有点都可用于显示,原因同样是抖动、伪像隐藏和电视过扫描。SNES需要一个水平过扫描期间,在此期间它发出消隐信号。 限制条件包括: - 最终宽高比接近4:3。这意味着224 *(4/3)= 298个可见点。 - 与使用16x16 tile的图形管线tilemap配合良好。这样可能的值有304(16x19)、288(16x18)、272(16x17)、256(16x16)、240(16*15)等。最接近4:3且几乎没有失真的值是304个点。 第三个限制是给PPU留出足够的时间,在HBLANK期间填充其精灵线缓冲区。我的猜测是,检索多达128个精灵的数据量很大,如果选择304个可见点作为水平分辨率,PPU需要超过37个点(约7μs)的HBLANK时间。 最终,任天堂决定每条线使用**256个可见点**,并带有**85个点的HBLANK**。这意味着PPU在HBLANK期间有16μs来检索精灵数据。这也意味着宽高比不是4:3,而是8:7,这导致CRT显示PPU生成的图像时会有轻微的失真。 高垂直分辨率模式:隔行扫描 --- 到目前为止,我们只考虑了逐行模式来设计SNES视频系统。 `` 过扫描分辨率:341x262 可见分辨率:256x224 帧率:60.098Hz `` 尽管99%的游戏最终都使用了这个模式,但SNES也有高分辨率模式。我可以垂直和/或水平地将其分辨率加倍。 垂直加倍分辨率到448行很容易。我们只需改变计数器,使其在最后一次HSYNC之后半行发出VSYNC,以实现帧的交错。这意味着每帧绘制262.5行,但每条线现在只以60.098/2=30.049Hz刷新。这会导致闪烁,不太令人愉快,但垂直分辨率会更高[\[18\]](https://fabiensanglard.net/snes_video/index.html#footnote_18)。 高水平分辨率模式:一种黑客技巧 --- 然而,水平加倍分辨率要困难得多,因为控制台没有所需的点时钟。 黑客技巧是,SNES将每隔一场的水平位置稍微偏移,使得该场的点落在上一场的点之间。最终结果是刷新率减半,并且颜色渗色严重。相当多的游戏使用了这种模式,主要用于菜单屏幕,详见 fullsnes.txt(https://problemkaputt.de/fullsnes.txt)。 `` 高分辨率软件 Air Strike Patrol (任务概览) (whatever mode? with Interlace) Bishoujo Wrestler Retsuden (部分文字) (512x448, BgMode5+Interlace) Ball Bullet Gun (下半屏) (512x224, BgMode5) Battle Cross (游戏内) (but isn't hires?) (512x224, BgMode1+PseudoH)(Bug?) BS Radical Dreamers (仅用户名输入) (512x224, BgMode5) Chrono Trigger (掉入拉沃斯序列) (whatever mode? with Interlace) Donkey Kong Country 1 (任天堂标志) (512x224, BgMode5) G.O.D. (开场及下半屏) (512x224, BgMode5) Jurassic Park (分数文字) (512x224, BgMode1+PseudoH+Math) Kirby's Dream Land 3 (第一个门的叶子) (512x224, BgMode1+PseudoH) Lufia 2 (游戏结束后的制作人员) (whatever mode?) Moryo Senki (?) (512x224, BgMode1+PseudoH) Super Mario RPG (部分静止帧) (512x224, BgMode1+PseudoH) Tetris 2 (关卡选择) (512x224, BgMode1+PseudoH) The Firemen (开场) (512x224, BgMode1+PseudoH) Trolls in Crazyland (标题画面) (512x224, BgMode5) Wild Guns (游戏内) (512x224, BgMode1+PseudoH) Zootto Mahjong (菜单) (512x224, BgMode1+PseudoH) ... 等等 ``

相似文章

超级任天堂卡带内部揭秘

Fabien Sanglard

对超级任天堂卡带的详细技术分析,涵盖 CIC 复制保护、ROM 容量分布、带电池备份的 SRAM 以及 Super FX 等增强处理器。

SNES 图形系统工作原理

Fabien Sanglard

基于 Jonathon Donaldson 的原理图,对超级任天堂图形硬件的详细技术解释,包括 PPU1 和 PPU2 芯片、VRAM、OAM 和 CGRAM。

Super Nintendo 的核心

Fabien Sanglard

对 Super Nintendo 中时钟生成硬件的详细分析,解释了用于产生所需频率的两个振荡器和可调电容器。

Super Nintendo主板的发展历程

Fabien Sanglard

本文详细介绍了Super Nintendo主板在12年生命周期中的版本演变,重点描述了任天堂如何通过Classic、APU和1-CHIP等世代将芯片数量从15个减少到9个。

SNES: 精灵与背景渲染

Fabien Sanglard

本文解释了SNES的PPU如何在紧张的VRAM带宽限制下渲染精灵和背景,描述了不同视频模式中的硬件权衡。