NES 编程 - 名称表?
Posted
技术标签:
【中文标题】NES 编程 - 名称表?【英文标题】:NES Programming - Nametables? 【发布时间】:2011-03-01 22:38:20 【问题描述】:我想知道 NES 如何显示其图形肌肉。我在网上研究了一些东西并通读了一遍,但我想知道最后一件事:Nametables。
基本上,根据我的阅读,NES 命名表中的每个 8x8 块都指向模式表中的一个位置,该位置保存图形内存。此外,nametable 也有一个属性表,它为每个 16x16 块设置一个特定的调色板。它们像这样连接在一起:
(假设 16 个 8x8 块) 命名表,带有 A B C D = 指向精灵数据的指针:
ABBB
CDCC
DDDD
DDDD
属性表,其中 1 2 3 = 指向调色板数据的指针,
1<2<
^'^'
3<3<
^'^'
因此,在上面的示例中,块将被着色
1A 1B 2B 2B
1C 1D 2C 2C
3D 3D 3D 3D
3D 3D 3D 3D
现在,如果我将它放在固定屏幕上 - 效果很好!因为 NES 分辨率是 256x240 像素。现在,如何调整这些表格以进行滚动?
因为 Nametable 0 可以滚动到 Nametable 1,如果你继续滚动 Nametable 0 将再次环绕。我明白了。但我不明白的是如何滚动属性表。根据我在网上阅读的内容,它为其分配属性的 16x16 块会导致屏幕边缘图块的颜色失真(如在 SMB3 中从左到右滚动时看到的那样,反之亦然)。
我担心的是我了解如何滚动名称表,但是如何滚动属性表?例如,如果我在屏幕左侧有一个绿色块,理论上向右移动屏幕应该会导致右侧的图块也是绿色的,直到它们更多地移动到框架中,它们将恢复到他们的正常颜色。
~~~~编辑: 我确实想指出,我知道扫描线 X 和 Y。这个想法刚刚在我脑海中闪过。
假设我在 10 的扫描线 Y。这意味着我正在将 10 个值水平读取到我的命名表中。这意味着我的第一列不在屏幕上,因为它的像素宽度仅为 8。但是,颜色属性保持不变,因为它的宽度为 16。
假设整个列的颜色属性是绿色,我是否正确假设对用户来说,屏幕左侧的前 6 个像素将被着色为绿色,屏幕上最右边的 10 个像素应该是绿色也? 那么,我的假设是否正确,根据屏幕,左边?
【问题讨论】:
+1 表示很棒。我不知道,但你只是问这个就摇滚。 【参考方案1】:This site相信你已经非常非常熟悉了。我会先说我从来没有为 NES 编程过,但我对曾经发布的所有 Gameboy 硬件非常有经验,而且 NES 与 GB/DMG 有很多相似之处。我敢打赌,您要么需要做以下几件事之一:
不要滚动属性表。确保您的关卡在您移动的方向上都有相似的色块。我猜很多第一代游戏都是这样做的。
继续并允许有限的属性滚动 - 只需确保发生更改的区域要么部分颜色共享,要么足够稀疏以使更改不会被注意到。
李>取出您的旧 skool atari 2600 计时器,并在 HBlank 更新结束时写入寄存器 $2006 以完成您需要的颜色交换,等待几个抽动,然后在 HBlank 返回期间恢复,以便下一行的左边缘不受影响。我有一种感觉,这是最常用的解决方案,但如果没有一个非常好的模拟器和耐心,这将是一件痛苦的事情。它还会消耗您的整体 CPU 使用率,因为您必须在多条扫描线的中断中等待才能完成效果。
我希望我能为您提供更具体的答案,但这希望对您有所帮助。谢天谢地,GB/DMG 有一个稍微先进的滚动系统。 :)
【讨论】:
其实以上都不是。属性随着它们的名称表滚动,因此设置滚动就像写入两个寄存器一样简单。大多数游戏都通过seam 进行命名更新,这根本不是很复杂。沿一个轴滚动的游戏会将这个接缝定位在屏幕外,但沿两个轴滚动的游戏(例如 SMB3)没有足够的内存来执行此操作,因此它们的接缝位于屏幕的可见边缘。这会使边缘看起来有问题。 啊,旧硬件及其怪癖 - 感谢您的评论。【参考方案2】:当您滚动时,超级马里奥兄弟 3 和柯比大冒险都会在屏幕边缘显示着色伪影。我相信这两款游戏都设置了空白屏幕左侧 8 个像素的位,因此任何一帧都会影响 0-8 个像素。
如果我没记错的话,Kirby's Adventure 总是试图将有颜色故障的列放在屏幕滚动的一侧,以使其不那么明显。如果不切换到垂直镜像,我认为这些伪影是无法避免的,这会带来自身的困难。
免责声明:我写任何 NES 代码已经过去五年了。
【讨论】:
【参考方案3】:每个名称表都有自己的属性表,因此从一个名称表滚动到另一个名称表时应该没有图形工件。如果您的游戏垂直和水平滚动,您所指的颜色故障类型实际上只是一个问题。您只有两个名称表,因此双向滚动需要您蚕食可见屏幕。这个问题有多种解决方案,可以在这篇 nesdev 帖子中找到一个很好的总结:
http://nesdev.parodius.com/bbs/viewtopic.php?p=58509#58509
【讨论】:
【参考方案4】:这个网站可能会有所帮助。 http://www.games4nintendo.com/nes/faq.php#4
(搜索“2005/2006 美元怎么了?”并开始阅读该区域。)
基本上看起来不可能让它像素完美,但是这些将是您可能需要研究的部分。
希望我能提供更多帮助。
【讨论】:
【参考方案5】:每个名称表都有自己的属性表。如果您将游戏世界限制在两个屏幕上,您只需要编写一次名称表和属性表。当您尝试使世界大于两个屏幕时,困难的部分就来了。超级马里奥兄弟 1 通过向右滚动、根据需要环绕并在该列出现之前一次渲染一列块(16 像素)来做到这一点。我不知道如何有效地编码(请记住,您只有一毫秒的 vblank 时间)。
【讨论】:
以上是关于NES 编程 - 名称表?的主要内容,如果未能解决你的问题,请参考以下文章