STA $2006 ; VRAM 地址设为 $2000 LDA $2007 ; A=$CC VRAM 缓冲=$AA LDA $2007 ; A=$AA VRAM 缓冲=$BB
这个只适用于$0000-$FEFF,访问调色板数据没有这种现象。
在屏幕刷新的时候访问VRAM:
前面说过,在屏幕刷新的时候存取VRAM的地址和数据是不合法的。许多程序存取这些寄存器来制造不同的滚动效果。比如,一些游戏从屏幕底部开始滚动,那么它可能向$2006写第一行的状态来复位屏幕滚动。更好的诡计是PPU在屏幕刷新时用VRAM的地址寄存器来储存当前地址。通过向$2006修改地址以及让PPU从一个不同的地方接着刷新。关于$2007如何影响屏幕刷新仍不了解。 当不知道向$2006中写什么数据时,看下面的图表。 写到$2006的地址
位 描述 0-Tiles的水平偏移量(例如1 = 8象素);水平位置=水平偏移量×8 4 5-Tiles的垂直偏移量(例如1 = 8象素);垂直位置=垂直偏移量×8 9 A、命名表的号码($2000,$2400,$2800,$2C00); B C、附加的垂直偏移量,单位:象素(0..3);扫描线=垂直偏移量+附加的垂D 直偏移量 E、00 F 5、声音处理器
NES的集成CPU里包含了一个4声道的声音处理器(2A03),为播放音乐提供准模拟的声音。4个声道分别是:2个方波,一个三角波和一个噪声发生通道,每个声道的特性都不一样。
声道:
方波声道能够产生54.6Hz到12.4KHz的方波,它的主要特性是频率扫略功能和调整输出的占空周期;三角波声道可产生27.3Hz到55.9KHz分辨率是4位(16级)的三角波,它的主要特性是输出模拟三角波和线性计数器(可用来定时关闭声道);噪声通道能产生29.3Hz到44.7KHz的随机噪声,它的主要特性是产生伪随机数,在声道输出随机频率。
帧计数器:
2A03有一个内含的帧计数器,它能够产生60Hz(1/1帧率)、120Hz(1/2帧率)和240Hz(1/4帧率)的信号,提供给其他一些声音硬件使用。1/4帧率的信号是由CPU频率乘以2即3579545Hz再除以14915得到的。
声音硬件延迟:
在2A03复位之后,到各个声音硬件开始接收时钟信号之间有2048个时钟周期的延迟。当这2K个时钟周期之后,声音开始正常工作,输出使能有效。这种现象只发生在系统复位之后的2048个时钟周期内。这个资料的准确性有待验证。 控制寄存器:
2A03的声音控制寄存器在CPU内分配的特殊地址如下: 寄存器地址 描述 $4000-$4003 方波1 $4004-$4007 方波2 $4008-$400B 三角波 $400C-$400F 噪声 $4015 声道使能、音长计数状态 只有$4015是可读可写的,其他都是只能够写的,如果你读这些寄存器最可能得到的是$40(因为NES数据线的重负荷)。读这些只写寄存器对寄存器本身和声道都没有任何影响。每个声音通道都有4个寄存器,具体描述如下: 寄存器\\位 $4000/$4004/$400C 0 1 2 3 音量衰减率 4 5 6 7 音长计数中无衰止/衰减循环占空周期类型 减 使能 扫描使能 1减少/0$4001/$4005 右移量 增加波扫描更新率 长 $4002/$4006/$400A 波长低八位 波长高三$4003/$4007/$400B/$400F 音长计数值 位 $4008 $4009/$400D $400E $4015:音长状态(读) 线性计数值 未使用 播放采样率 未使用 音长计数中止/线性计数开始 随机数类型发生 DMC的IRQ状态 方方三噪声 DMC 未使用 1 2 角 方方三$4015:通道使能(写) 噪声 DMC 未使用 1 2 角 声道结构体系: 总表:
设备 三角波 噪声 方波 三角阶梯发生器 √ 线性计数器 √ 可编程定时器 √ √ √ 音长计数器 √ √ √ 4位DAC √ √ √ 音量衰减单元 √ √ 扫频单元 √ 占空周期发生器 √ 波长转换器 √ 随机数发生器 √ 三角阶梯发生器:
这是一个5位的单向的计数器,只存在于三角波通道,计数器输出的低4位分别通到一个XNOR(异或非)门。4个XNOR门被同一个选通信号控制,当选通是0时,计数器输出的4个低位在门电路的输出端反相;当选通是1时,不反相。选通信号连到计数器的最高位,这样就可以在XNOR门的输出端产生一个计数序列,就造出了一个比较理想的三角阶梯信号发生器。XNOR门的输出反馈到一个4位的DAC输入端。当三角波的音长计数器或线性计数器是0时,这个5位的计算器会暂停,同时锁定,计数器不会被重设置到某一个特定的状态。在系统复位的时候,计数器装入0。计数器的时钟输入直接连接到三角波通道内一个11位的可编程定时器的输出端,这样,这个5位的三角波阶梯信号发生器的输出频率就是通道内可编程定时器频率的1/32。
线性计数器:($4008)
这是一个7位的递减计数器,只存在于三角波通道,计数器减到0时输出。计数器的时钟是240Hz(1/4帧率),用帧来计算长度就是0.25×N,其中N是预先装入的7位的值。计数器会保持计数状态直到输出0,这时线性计数器和三角阶梯发生器的时钟信号被禁止,导致两个计数器被锁定,线性计数器的输出保持是0,声道因此而出现静音。线性计算器有两种工作模式:装入和计数。在装入模式,所有的输入(写到$4008)的值都会在传送到输出,也就没有计数;在计数模式,计数器会从当前值向下减,在$4008的数会被忽略。下表表示了如何通过$4008的最高位设置计数器: 旧值 新值 模式 0 X 计数 1 0 在写周期没有变化,计数 1 1 没有变化 可编程定时器($4002/3、$4006/7、$400A/B、$400F):
这是一个11位可预设的递减计数器,每个声音通道都有,但是注意在噪声通道不是直接可用的,详见“波长转换器”。这个计数器在计数完成的时候自动重载,因此它在减到0前会计算N+1个时钟周期,其中N是预装入的11位值。
这个计数器直接使用6502的频率(1.79MHz)作为时钟,输出频率是
1.79MHz/(N+1)。当到达计数终点的时候会产生一个1时钟周期的脉冲,而输出频率会被反馈到对应于声音通道的特殊设备。对于方波,这个计数终点脉冲会被送到占空周期发生器;对于三角波,会被送到三角阶梯发生器;对于噪声,会被送到随机数发生器。
音长计数器($4003、$4007、$400B、$400F):
这是一个7位的递减计数器,时钟是60Hz,每个声音通道都有。当计数器减到0,计数停止,相应的通道出现静音。可以通过设置音长计数时钟的禁止位来暂停计数,写1则中止计数,0则允许计数。在不同的寄存器里,这个位的位置不同,见寄存器表。计数值通过$4003、$4007、$400B和$400F的3-7位来写入。输入的5位值通过下面2个表转换到计数器的7位值: 第3位=0 帧 4-6位的值 第7位=0 第7位=1 0 05 06 1 0A 0C 2 14 18 3 28 30 4 50 60 5 1E 24 6 07 08 7 0E 10 第3位=1 4-7位 帧 0 7F 1 01 2 02 3 03 4 04 5 05 6 06 7 07 8 08 9 09 A 0A B 0B C 0C D 0C E 0E F 0F 音长计数器的状态可以通过$4015来读取,0表示计数器处于0状态(停止在0),1表示处于非0状态。通过写0到$4015可以令音长计数器永远处于0状态,使得声道被禁止;写1可以取消禁止状态,但它不会改变计数器里面的值。在系统复位时这个寄存器全部5个使用的位都被设置为0。
4位DAC:
这是一个标准的4位DAC(数模转换)单元,有16级输出电压,4个声道共用。在2A03里,方波1和方波2混合通过引脚1输入,三角波和噪音通过引脚2输入。这些模拟量输出需要一个负的电流源,以使得电压的级输出变成平滑的声音信号。因为NES只外置了一个100欧姆的下拉电阻,使得输出波形的幅值很小,但是也获得最小的不平滑度。这个不平滑度小到难以发现,就算用示波器也不明显。
音量衰减单元($4000、$4004、$400C):
音量衰减器只存在于方波和噪声通道。当衰减禁止位(第4位)被设置为1,当前的音量值(0-3位)被直接送到DAC。在下列情况中,音量值会被忽略,而直接送0到DAC。
·声道硬件要停止声音,例如音长计数器或扫频单元;
·处于占空周期或随机数发生器输出频率信号的负值部分,也即在声音使能的时候送到DAC的或者是音量值或者是0(无声)。
当衰减禁止位被清零,0-3位当前的值就是衰减率。衰减率是指音量从最大值向下线性衰减的速度,衰减速度是240/(N+1),N的值从$0-$F。当衰减到0之后,根据寄存器第5位的状态将发生两种情况: 第5位 行为 0 音量停在0,声道静音 1 音量循环不断从最大值减到0 只有通过对寄存器进行写操作才能重新设置硬件的衰减状态,否则就一直按当前状态进行衰减甚至循环,即使寄存器的第4位被设置成禁止衰减也没有用。
扫频单元:
这个东西只存在在方波通道中。当寄存器的第7位被设为1,扫频被激活,波长会实时地增加或减少(对应频率降低或提高)。波长的值通过$4002/3和$4006/7被不断的读入和更新,写到那里的值会立刻反应到声音里。第4-6位代表了频率扫略速度,或者说$4002/3和$4006/7里波长值被改变的频率。刷新率是120Hz/(N+1),N是写入的值,从0-7。第3位控制扫频的模式,1表示波长减少,0表示波长增加。第0-2位是右移量,用来控制波长增量的右移量,见下表:
第3位 表达式,N是右移量从0-7 0 波长=波长+(波长>>N) 1 波长=波长-(波长>>N)