NES红白机学习笔记
计划
- 模拟6502、总线和内存RAM,CPU能够从内存读写数据和获取指令
- 参考CPU的数据手册,能够对指令进行解析
- 解析卡带Cartidge的文件格式
- 实现Mapper功能
- 构建PPU模块,能够调用SFML输出画面
- 增加按键控制功能
CPU-6502
2A03简介
2A03是Ricoh(理光集团)基于6502制造的NMOS处理器。
小端字节处理器。
CPU内存分布
下图展示处理器如何使用总线访问内存。内存分为三个区域:卡带中的ROM、处理器RAM、I/O寄存器。8位控制总线负责通知组件请求是读还是写。8位数据总线用于读写字节。16位地址总线用于选择目标组件。请注意,ROM是只读的,需要通过MMC访问,以便切换bank。I/O寄存器用于和系统其他组件通信,比如PPU和控制器。
16位地址总线可以访问64KB内存地址$0000-$FFFF。具体的分布见下图。RAM区域$0000-$2000,I/O寄存器区域$2000-$4020,扩展ROM区域$4020-$6000,SRAM区域$6000-$8000,程序ROM区域$8000-$10000。
零页是指地址范围$0000-$00FF,在特定模式下允许更快的执行。内存地址$0000-$00FF会被镜像三次到$0800-$2000。比如,任何写到$0000的数据也会写到$0800、$1000和$1800。
位置$2000-$2007每8字节会被镜像到$2008-$3FFF,剩余的寄存器都遵循这个镜像。
SRAM(WRAM)是存储内存,这个地址用于访问记忆游戏Cartridges卡带中的RAM。
从$8000开始的地址是分配给Cartridges卡带的PRG-ROM。游戏只有一个16KB数据区(bank)的,会被加载到$8000和$C000。游戏有两个16KB数据区的,将一个加载到$8000,另一个加载到$C000。游戏拥有超过两个16KB数据区的,使用内存映射器决定哪个数据区加载到内存。内存映射器会监视特定地址(或地址范围)的内存写入,当地址被写入时,它会执行数据区切换。详见附录D。
寄存器
Program Counter (PC)
16位寄存器;
Stack Pointer (SP)
8位寄存器;固定偏移$0100;位置$0100-$01FF;自顶向下增长;不会检测越界;
Accumulator (A)
8位寄存器;从内存取值;
Index Register X (X)
8位寄存器;从内存取值;地址偏移值;读写SP寄存器;
Index Register Y (Y)
8位寄存器;从内存取值;地址偏移值;
Processor Status (P)
- Carry Flag (C) 上个指令结果越界标记;指令SEC/CLC,设置为1/0;
- Zero Flag (Z) 上个指令结果为零标记;
- Interrupt Disable (I) 中断禁用标记;指令SEI/CLI,设置为1/0;
- Decimal Mode (D) BCD十进制模式,会被忽略;指令SED/CLD,设置为1/0;
- Break Command (B) 指明BRK指令,会引发IRQ;
- Overflow Flag (V) 溢出标记;
- Negative Flag (N) 符号位;0为正,1为负;
中断
NES有三种类型的中断:NMI、IRQ、复位,中断向量表存储在$FFFA-$FFFF;
发生中断时,需要进行如下步骤:
- 识别中断;
- 完成当前指令执行;
- PC和P寄存器压栈;
- 设置中断禁用位;
- 读取中断向量表处理函数赋值给PC;
- 执行处理函数;
- 执行RTI指令,恢复P和PC寄存器;
- 继续执行程序;
中断或可屏蔽中断,是由某些内存映射器生成的。
IRQ可以由软件使用BRK指令触发。当发生IRQ时,系统跳到$FFFE和$FFFF所指地址。
NMI(不可屏蔽中断)是当V-Blank出现在每个帧的末尾时,PPU产生的中断类型。它不受中断禁用寄存器影响,所以它发生时,程序总是被中断。当PPU控制寄存器1($2000)被清空时,会阻止NMI的触发。当发生NMI时,系统跳到$FFFA和$FFFB所指地址。
复位中断在系统第一次启动和用户按下复位按钮时触发。当发生复位时,系统跳到$FFFC和$FFFD所指地址。
中断优先级为复位、NMI和IRQ。NES有7个周期的中断延时,即它会花费7个CPU周期来开始执行中断处理。
寻址模式
在6502上总共有13种不同的寻址模式。详见附录E。
指令
6502有56条不同的指令,尽管有些指令有多种,使用不同的寻址模式,使得在可能得256个操作码中总计151个有效。指令可以是1、2或3字节长,根据它们的寻址模式。第一个字节为操作码,其他字节为操作数。指令可以分为几个功能组:
- 加载/存储操作
- 寄存器传输操作
- 栈操作
- 逻辑操作
- 算术操作
- 递增/递减
- 移位
- 跳转/调用
- 分支
- 状态寄存器操作
- 系统函数
PPU-2C02
内存分布

图案表
英文名PatternTable,卡带CHR-ROM映射到此处,也可能是RAM。游戏中使用的一个图案被称为Tile,背景或精灵都是由若干个Tile组成。
每个Tile大小为8x8像素,游戏屏幕大小为256x240像素,由32x30个Tile组成。
一个图案表占用大小4KB,总共有两个占用8KB。对于许多游戏拥有超过两个图案表,需要使用Mapper来控制映射。
简单计算:
一个PatternTable大小4KB,由256个Tile组成。每个Tile大小为4KB/256=16B。一个Tile大小8x8=64像素,每个像素占用16B/64=2bit。
参考
《Nintendo Entertainment System Documentation Version 1.0.pdf》
《任天堂产品系统文件.chm》