自从我提出这个问题以来,我学到了很多关于 NES PPU 的新东西,所以我将自己回答这个问题。
首先,PPU 的内存映射如下所示:
$0000 - $0FFF Pattern table 0
$1000 - $1FFF Pattern table 1
$2000 - $23BF Nametable 0
$23C0 - $23FF Attribute table 0
$2400 - $27BF Nametable 1
$27C0 - $27FF Attribute table 1
$2800 - $2BBF Nametable 2
$2BC0 - $2BFF Attribute table 2
$2C00 - $2FBF Nametable 3
$2FC0 - $2FFF Attribute table 3
$3000 - $3EFF [0x2000 - 0x2EFF] mirror
$3F00 - $3F09 Background palette
$3F10 - $3F19 Sprite palette
$3F20 - $3FFF Palette mirror
除此之外,还有一个称为 OAM 的 $FF (256) 字节区域,还有一个称为辅助 OAM 的 $20 (32) 字节区域。
它们是如何写入的?
模式表用于以模式保存NES的图形数据,即这里存储的任何内容都显示了所使用的精灵的形状。这些通常存储在卡带上的 CHR ROM 中,但它们也可以由游戏的程序员写入 PPU 内存。下面将解释这种情况的发生方式。
除了模式表之外,除了 OAM 和 Secondary OAM 之外的所有内容都由游戏的程序员写入 PPU 内存。这通过使用寄存器 $2006 和 $2007 来实现。如何?
每当程序员想要写入 PPU 内存中的某个地址时,他可以通过写入 $2006 来存储(sta、stx、sty 以及可能还有其他指令)他想要访问的地址来实现 像他在正常装配中那样通过 CPU 两次。一个例子是:
LDA #$20
STA $2006
LDA #$00
STA $2006
用户先写入地址的高字节,再写入低字节。现在,一个 PPU 内部 15 位锁存器(不确定锁存器是否是正确的字)将 PPU 地址 $2000 存储在其中。每当程序员想要写入这个地址时(在这种情况下,它是第一个命名表的起始地址),他可以通过将他想要存储在这个内存区域中的值写入内存地址 $2007 来正常执行此操作。写入该地址时,写入的值将被放入 15 位锁存器中的地址,锁存器将递增 1 或 32(由地址 $2000 中的值的第 2 位决定)。基本上就是这么简单。
当然,事情没那么简单。地址 $2000 - $2007 称为 PPU 的 Memory Mapped Registers,之所以这样称呼,是因为它们位于 CPU 的内存中。它们位于那里是因为 CPU 和 PPU 不能直接访问彼此的内存,因此 CPU 必须找到一些通往 PPU 内存的网关,这些地址就是它。这些寄存器有很多奇怪的异常和怪癖,它们都被解释了here。
除此之外,还有前面提到的 OAM 和辅助 OAM,但它们是完全不同的东西,应该通过阅读实际可行的资料来彻底解释,而不是快速解释。
最好从提到的来源 (again, here) 阅读它以获得完整的理解,但这只是对那些好奇并且实际上对这类东西有基本了解的人的快速解释。