FC MMC5 (Mapper 5) 操作

MMC5(mapper5)

概览

mapper号 5
卡带名 MMC5
PRG ROM容量 1024K
PRG ROM窗口 8K / 16K / 32K
PRG RAM容量 128K
PRG RAM窗口 8K / 16K(仅 8000 − 8000- 8000BFFF 在 PRG 模式 1/2 时可用)
CHR ROM容量 1024K
CHR ROM窗口 1K / 2K / 4K / 8K
扩展声音
IRQ

寄存器

音频 ($5000-$5015)

有关声音操作的详细信息,请参阅 MMC5 音频

NES内部状态监控

所有这些寄存器都覆盖了 NES 内部已使用的各种寄存器,并且已完全解码。 游戏可以写入 PPU 寄存器的镜像以使 MMC5 不同步,但尚不清楚这有何用处。

8x16 模式启用 1 ($2000 = PPUCTRL)
7  bit  0
---- ----
xxZx xxxx
  |
  +------- 精灵尺寸 (0: 8x8 像素; 1: 8x16 像素)
8x16 模式启用 2 ($2001 = PPUMASK)
7  bit  0
---------
xxxE Exxx
   | |
   +-+--- 1,2,3: 渲染启用; 0: 渲染禁用

仅当设置了 Z 且设置了至少一个 E 位时,MMC5 才会 从8个独立 bank 中绘制 8x16 精灵.

Unknown ($2002 = PPUSTATUS, read only)

电源分析检测到 MMC5 监视器的两个版本均显示为此处,用途未知.

Unknown ($2005 = PPUSCROLL)

电源分析检测到 MMC5 监视器的两个版本均写入此处,用途未知.

Unknown ($2006 = PPUADDR, MMC5A only)

电源分析检测到 MMC5A 监视器在此处写入,用途未知.

Unknown ($4014 = OAMDMA)

电源分析检测到 MMC5 监视器的两个版本均写入此处,用途未知.

PRG 模式 ($5100)

7  bit  0
---- ----
xxxx xxPP
       ||
       ++- 选择 PRG 切换模式
  • 0 - 32KB * 1 bank
  • 1 - 16KB * 2 banks
  • 2 - 16KB bank ( 8000 − 8000- 8000BFFF) + 8KB * 2 ( C 000 − C000- C000DFFF and E 000 − E000- E000FFFF)
  • 3 - 8KB * 4

CHR 模式 ($5101)

7  bit  0
---- ----
xxxx xxCC
       ||
       ++- 选择 CHR 切换模式
  • 0 - 8KB CHR 页
  • 1 - 4KB CHR 页
  • 2 - 2KB CHR 页
  • 3 - 1KB CHR 页

PRG RAM 保护1 ($5102)

7  bit  0
---- ----
xxxx xxWW
       ||
       ++- RAM 保护 1

为了能够写入 PRG RAM,必须将其设置为二进制“10”(例如 $02)。

PRG RAM 保护1 ($5103)

7  bit  0
---- ----
xxxx xxWW
       ||
       ++- RAM 保护 2

为了能够写入 PRG RAM,必须将其设置为二进制“01”(例如 $01)。

内部扩展RAM模式 ($5104)

7  bit  0
---- ----
xxxx xxXX
       ||
       ++- 指定扩展 RAM 使用情况
$5104写入值 RAM $5C00-5FFF 可作为名称表使用 启用扩展属性模式
$00 只写
$01 只写
$02 读写
$03 只读

命名表映射 ($5105)

7  bit  0
---- ----
DDCC BBAA
|||| ||||
|||| ||++- 选择 PPU $2000-$23FF 的命名表
|||| ++--- 选择 PPU $2400-$27FF 的命名表
||++------ 选择 PPU $2800-$2BFF 的命名表
++-------- 选择 PPU $2C00-$2FFF 的命名表

命名表值:

  • 0 - CIRAM 第 0 页
  • 1 - CIRAM 第 1 页
  • 2 - 内部扩展 RAM
    • 工作于 $5104 模式 0 和 1; 否则名称表将读取为全零.
  • 3 - 填充模式数据
    • 请参阅寄存器 $5106 和 $501

命名表举例

模式 命名表D 命名表C 命名表B 命名表A
水平 $50 %01 %01 %00 %00
垂直 $44 %01 %00 %01 %00
单屏0 $00 %00 %00 %00 %00
单屏1 $55 %01 %01 %01 %01
单屏ExRAM $AA %10 %10 %10 %10
单屏填充 $FF %11 %11 %11 %11
对角 $14 %00 %01 %01 %00

填充模式图块($5106)

当名称表映射到寄存器 $5105 中的填充模式时,所有名称表提取都将替换为该寄存器的值。 只有名称表受填充模式影响。 当 PPU 稍后使用此信息从模式表中获取相应的图块时,CHR 存储不受影响并继续正常工作。

填充模式颜色 ($5107)

7  bit  0
---- ----
xxxx xxAA
       ||
       ++- 指定用于填充模式名称表的背景调色板索引

当名称表映射到寄存器 $5105 中的填充模式时,所有属性表提取都将替换为该寄存器的值。 属性表的每个字节通常包含四个2位调色板索引。 该寄存器中的两位将被复制以用于所有四个索引。

PRG 切换 ($5130-$5117)

一般来说,当CPU访问与当前PRG模式指定的PRG组范围相对应的地址时,该PRG组寄存器的位将被应用到适当的PRG地址总线,如下所示:

7  bit  0
---- ----
RAAA AaAA
|||| ||||
|||| |||+- PRG ROM/RAM A13
|||| ||+-- PRG ROM/RAM A14
|||| |+--- PRG ROM/RAM A15, 还可以在 PRG RAM /CE 0 和 1 之间进行选择
|||| +---- PRG ROM/RAM A16
|||+------ PRG ROM A17
||+------- PRG ROM A18
|+-------- PRG ROM A19
+--------- RAM/ROM 切换 (0: RAM; 1: ROM) (仅寄存器 $5114-$5116)

概念性的 bank 寄存器有效区域与 PRG 模式:

寄存器 模式0 32KB 模式1 16KB * 2 模式2 16KB + 8KB * 2 模式3 8KB * 4
$5113 $6000-$7FFF (RAM) $6000-$7FFF (RAM) $6000-$7FFF (RAM) $6000-$7FFF (RAM)
$5114 $8000-$9FFF
$5115 8000 − 8000- 8000BFFF 8000 − 8000- 8000BFFF A 000 − A000- A000BFFF
$5116 C 000 C000 C000-DFFF C 000 − C000- C000DFFF
$5117 8000 − 8000- 8000FFFF (ROM) C 000 − C000- C000FFFF (ROM) E 000 − E000- E000FFFF (ROM) E 000 − E000- E000FFFF (ROM)

RAM 始终映射在 $6000-$7FFF,并且位 $5113.7 被忽略。 ROM 始终映射到由寄存器 $5117 控制的存储体,并且位 $5117.7 被忽略。 这使得在任何模式下都无法将 RAM 映射到中断向量。

模式 0-2:组切换寄存器始终保存 8kb 组索引号的值。 当选择“更大”大小(16 kb 或 32kb)的存储体时,存储体切换寄存器中的低位将被忽略。 换句话说,来自CPU的地址线通过映射器直接到达PRG-ROM芯片。

Games 似乎预计开机时 $5117 为 $FF。 所有游戏在 PRG ROM 的最后一组中都有其重置向量,并且该向量指向大于或等于 $E000 的地址。

PRG-RAM 配置

在商业配置中,位 0 和 1 选择 SRAM 芯片内的页面,位 2 在两个单独的 SRAM 之间选择。 8K 和 32K 游戏具有单个 SRAM 芯片,仅当位 2 清零时才会激活。 16K 游戏有两个芯片,但只有第一个芯片有电池供电。

配置 0 1 2 3 4 5 6 7
ELROM 0K 开放总线 开放总线 开放总线 开放总线 开放总线 开放总线 开放总线 开放总线
EKROM 8K (1 x 8K) 0:$0000 0:$0000 0:$0000 0:$0000 开放总线 开放总线 开放总线 开放总线
ETROM 16K (2 x 8K) 0:$0000 0:$0000 0:$0000 0:$0000 1:$0000 1:$0000 1:$0000 1:$0000
EWROM 32K (1 x 32K) 0:$0000 0:$2000 0:$4000 0:$6000 开放总线 开放总线 开放总线 开放总线
Superset 64K (2 x 32K) 0:$0000 0:$2000 0:$4000 0:$6000 1:$0000 1:$2000 1:$4000 1:$6000

由于在 NES 2.0 之前,iNES 标头缺乏可靠的 PRG-RAM 大小信息,因此某些仿真器可能通过 ROM CRC 检查选择了这些行为。

由于已知没有 ExROM 游戏会使用一个存储体值写入 PRG-RAM,然后尝试使用不同的存储体值读回相同的数据,因此始终将 PRG-RAM 模拟为 64K 可以用作所有游戏的兼容超集 。

2018 年对 MMC5 引脚排列的调查显示,位 2 和位 3 还控制额外的 PRG-RAM 地址引脚,理论上可用于选择单个 128K SRAM 的 32 个存储体,位 2 直接控制 PRG A15,而不是使用两个位 片选/CE 输出。

其他PRG-RAM说明

  • Bandit Kings of Ancient China 将 PRG-RAM 映射到 CPU $8000+ 区域,并希望能够通过那里写入。 当世界地图上恢复背景时,如果不模仿这一点会导致损坏。
  • Uncharted Waters 需要模拟 PRG-RAM 的存储区切换:它在一个 CPU 地址处写入 PRG-RAM,并期望能够通过不同的 CPU 地址读回相同的数据。
  • 使用 16K PRG-RAM 的游戏仅在第一个 8K 时节省电池。
  • 包含电池的 MMC5 游戏列表。

CHR 切换 ($5120-$5130)

当使用 8x8 精灵时,仅使用寄存器 $5120-$5127。 寄存器 $5128-$512B 被完全忽略。

当使用 8x16 精灵时,PPU 会忽略精灵图案表地址,并可以从整个 8 KiB 图案表中选择图块,这在其他映射器上与背景图案表重叠。 MMC5 跟踪 PPU 是否正在获取背景块或精灵块,并具有新的寄存器来为背景块指定独立的存储体,即使它们看起来与 PPU 的地址相同。 这有效地创建了 12 KiB 的 CHR 窗口,最多可同时使用8个 1 KiB 精灵库。 寄存器$5120-$5127指定精灵库,寄存器$5128-$512B适用于背景图块,最后写入的一组寄存器($5120-$5127或$5128-$512B)将用于通过PPUDATA($2007)的I/O 。 [1] [2] MMC5 通过计算自上次检测到的扫描线开始以来的获取次数来知道正在获取精灵数据,类似于它检测垂直分割位置的方式。

《Bandit Kings of Ancient China》和《Uchuu Keibitai SDF》的CHR ROM中存储有非模式数据,通过$2007读取。

众所周知,MMC5 会监听与 PPU 相同的地址,以了解何时启用 8x16 精灵模式; 往上看。

CHR 选择 $5120-$512B {#CHR_Bankswitching}

每种模式影响的 PPU 内存:

寄存器 模式0 8KB 模式1 4KB * 2 模式2 2KB * 4 模式3 1KB * 8
$5120 $0000-$03FF
$5121 $0000-$07FF $0400-$07FF
$5122 $0800-$0BFF
$5123 $0000-$0FFF $0800-$0FFF $0C00-$0FFF
$5124 $1000-$13FF
$5125 $1000-$17FF $1400-$17FF
$5126 $1800-$1BFF
$5127 $0000-$1FFF $1000-$1FFF $1800-$1FFF $1C00-$1FFF
$5128 $0000-$03FF 和 $1000-$13FF
$5129 $0000-$07FF 和 $1000-$17FF $0400-$07FF 和 $1400-$17FF
$512A $0800-$0BFF 和 $1800-$1BFF
$512B $0000-$1FFF $0000-$0FFF 和 $1000-$1FFF $0800-$0FFF 和 $1800-$1FFF $0C00-$0FFF 和 $1C00-$1FFF

注意:与 MMC1 和 MMC5 上的 PRG 存储区不同,存储区始终按当前选定的大小进行索引。 当使用 2kb、4kb 或 8kb 存储体大小时,寄存器保存该较大大小的存储体索引,并且忽略较低位。

CHR Bank 高位 ($5130)

7  bit  0
---- ----
xxxx xxBB
       ||
       ++- 后续 CHR bank 写入的高位

当 MMC5 使用 2KB/1KB CHR 存储体时,使用前面的寄存器只能选择 512KB/256KB CHR ROM。 要在这些模式下访问所有 1024KB,首先将高位写入寄存器 $5130,然后将低位写入 $5120-$512B。

唯一CHR ROM大于256KB的ExROM游戏是Metal Slader Glory,它使用4KB CHR库并且不使用扩展属性。 换句话说,没有任何官方游戏依赖于这个寄存器,而且大多数游戏甚至没有初始化它。

在扩展属性模式下($5104 = 1),该寄存器可能充当全局瞬时存储体选择,附加为所有特定于图块的 CHR 存储体的最高有效 2 位,选择要使用的 CHR ROM 的 256KB 适用于屏幕上的所有背景图块。 扩展 RAM 不太可能每次写入都存储所有 10 位,如寄存器 $5120-$512B。

其他寄存器

垂直分割模式 ($5200)

7  bit  0
---- ----
ESxW WWWW
|| | ||||
|| +-++++- 指定垂直分割开始/停止图块
|+-------- 指定垂直分屏边(0: 左; 1: 右)
+--------- 启用垂直分割模式

当启用垂直分割模式时,与相应屏幕区域相对应的所有 VRAM 读取将被重定向到扩展 RAM(只要其模式设置为 0 或 1)。

Uchuu Keibitai SDF 在介绍中使用分屏模式,显示船舶统计数据。 《中国古代匪王》在结尾序列中使用分屏模式[2]。

操作注意事项

每条扫描线获取 34 个 BG 切片。 MMC5 通过观察正在获取哪个 BG 瓦片来执行分割,如果它在分割区域内,则根据瓦片的绝对屏幕位置(即忽略粗略的水平和垂直位置)用分屏数据替换正常的 NT 数据。 滚动输出作为提取的 VRAM 地址的一部分)。 由于它是在每个图块的基础上操作的,因此精细的水平滚动“进入”分割区域:将水平滚动设置为 1-7 将导致分割向左移动 1-7 个像素。 每当滚动超过 8 的倍数时,分割就会“弹回”到其正常位置。

左分割:

瓷砖 0 到 T-1 是分割的。
T 及以上的图块会正常渲染。
右分割:

图块 0 到 T-1 正常渲染。
T 及以上的牌是分开的。
拆分时没有任何类型的粗略水平滚动。 右侧分割将始终显示名称表的右侧,左侧分割将始终显示名称表的左侧。 粗略的水平滚动仍然可以用于非分割区域。

ExRAM 始终用作分屏模式下的命名表。

拆分的垂直滚动的操作方式与普通垂直滚动类似。 0-239 是有效的滚动值,而 240-255 会将前几条扫描线的属性表数据显示为 NT 数据。 分割的名称表将换行,以便当您滚动时名称表的顶部将出现在下方(就像使用垂直镜像一样)。

$5202 选择(又一个)CHR 页面用于 BG。 该页面仅用于分割区域。

垂直分割滚动 ($5201)

所有8位指定在分割区域中使用的垂直滚动值

以“CL”模式接线的 MMC5 板应仅使用其底部 3 位与 PPU 的精细垂直滚动值匹配的垂直滚动值。 使用不匹配的值将导致图块看起来在其内部“滚动”。 在“SL”模式下,可以使用任何值。 (现有游戏没有使用 SL 板配置。)

分割区域内不允许水平滚动。

垂直分割 bank ($5202)

在渲染分割区域时,所有8位都选择 $0000-$0FFF 和 $1000-$1FFF 处的 4 KB CHR 存储体。

IRQ 扫描线比较值 ($5203)

所有8位指定生成扫描线 IRQ 的目标扫描线编号。 值 $00 是一种特殊情况,不会产生 IRQ 挂起条件,尽管将其设置为 $00 时可能会获得 IRQ(因为已经设置了挂起标志)。您将需要采取额外的措施来完全抑制 中断请求。 请参阅详细讨论。

IRQ扫描线状态 ($5204, 读/写)

写入时
7  bit  0
---- ----
Exxx xxxx
|
+--------- 扫描线 IRQ 使能标志 (1=已使能)
读取时
7  bit  0
---- ----
SVxx xxxx  MMC5A 默认开机值 = $00
||
|+-------- "In Frame" 标志
+--------- 扫描线 IRQ 挂起标志

只要内部扫描线计数器与写入寄存器 $5203 的值匹配,扫描线 IRQ 待定标志就会被置位。 如果扫描线IRQ被使能,它也会产生/IRQ给系统。

当 PPU 渲染帧时设置“帧内”标志,并在垂直空白期间清除。

每当读取该寄存器时,扫描线 IRQ 待定标志都会被清除(确认 IRQ)。

有关详细信息,请参阅 IRQ 计数器操作。

无符号 8位 * 8位 至 16位 乘法器($5205, $5206 读/写)

写入后可立即从这些寄存器中读取无符号 16 位乘积。 此处的 MMC5A 测试并验证了所有 65536 个被乘数和乘数组合的正确性[3]。

$5205 8 位无符号被乘数
$5206 8 位无符号乘法器
对于这两个寄存器,MMC5A 默认上电写入值 = $FF。

$5205 无符号 16 位乘积(低字节)
$5206 无符号 16 位乘积(高字节)
MMC5A 默认上电读取值 = $FE01,即 $FF * $FF。

内部扩展 RAM ($5C00-$5FFF, 读/写)

有关 MMC5 的 1KB 内部扩展 RAM 的特殊行为,请参阅寄存器 $5104。

MMC5A

MMC5A 是后来的版本,其中包括一些额外的功能。 目前还没有游戏使用这些功能,并且模拟器对它们的支持也很差。

MMC5A 寄存器

寄存器 $5207, $5208, $5209, $520A, 和范围 $5800-$5BFF 仅存在于 MMC5A 中.

CL3 / SL3 数据方向和输出数据源(MMC5A:$5207 只写)

7  bit  0
---- ----
ABxx xxCD  MMC5A 默认开机写入值 = 11xx xxxx
||     ||
||     |+- MMC5.97 (CL3) 输出数据源(0 = 写入 $5208.6 值,当 CPU 在 $5800-$5BFF 范围内读取时,1 = !(M2))
||     +-- MMC5.98 (SL3) 输出数据源(0 = 写入 $5208.7 值,当 CPU 在 $5800-$5BFF 范围内写入时,1 = !(M2))
|+-------- MMC5.97 (CL3) 数据方向(0 = 输出,1 = 输入)
+--------- MMC5.98 (SL3) 数据方向(0 = 输出,1 = 输入)

CL3 / SL3 状态(MMC5A:$5208 读/写)

7  bit  0
---- ----
ABxx xxxx  MMC5A 默认开机写入值 = 00xx xxxx
||
|+-------- 如果/当 $5207.0 = 0 且 $5207.6 = 0 时,MMC5.97 引脚 (CL3) 上输出的值
+--------- 如果/当 $5207.1 = 0 且 $5207.7 = 0 时,MMC5.98 引脚 (SL3) 上输出的值

警告:PCB 可以将引脚 97 和 98 直接连接到 GND。 尽管尚未完全证实,但在这样连接时将它们设置为输出高电平似乎会破坏这些引脚的输出驱动器。

7  bit  0
---- ----
ABxx xxxx
||
|+-------- MMC5.97引脚(CL3)的输入值
+--------- MMC5.98引脚(SL3)的输入值

16位 带 IRQ 的硬件定时器 (MMC5A: $5209 读/写, $520A 只写)

  • $5209
7  bit  0
---- ----
Vxxx xxxx  MMC5A 默认开机读取值 = $00
|
+--------- 硬件定时器IRQ标志
  • $5209
7  bit  0
---- ----
TTTT TTTT  MMC5A 默认开机写入值 = $00
|||| ||||
++++-++++- 定时器计数 最低有效位
  • $520A
7  bit  0
---- ----
TTTT TTTT  MMC5A 默认开机写入值 = $00
|||| ||||
++++-++++- 定时器计数 最高有效位

根据 krzysiobal 的发现:如果 16 位定时器值不等于 $0000,则在向寄存器 $5209 写入任何值时,定时器会自动启动。 例如,要写入值$0100,您应首先将$01(MSB)写入寄存器$520A,这不会启动定时器。 然后将 $00 (LSB) 写入寄存器 $5209,此时将从值 $0100 开始计时器。

每个 8 位值都直接写入内部 16 位计数器,该计数器在每个 CPU 周期(特别是在 M2 的上升沿)递减。 定时器运行时的额外写入将直接覆盖计数器的该部分。 定时器运行时读取寄存器 $5209 会报告 $00。 从计数器值 $0001 到 $0000 的转换生成 IRQ 并设置硬件定时器 IRQ 标志。 计时器在此时停止。 读取该寄存器会报告 IRQ 标志,然后自动清除 IRQ 和 IRQ 标志。

如果 MMC5 检测到复位,它会清除定时器(如果处于活动状态),并清除 IRQ 和 IRQ 标志(如果已设置)。 复位检测的工作原理是在 M2 上查找大于约 11 usc 的间隙。

该寄存器的IRQ操作完全独立于寄存器$5204。 通过 $5204 禁用中断不会影响 IRQ 生成这些寄存器,并且读取 $5204 不会报告这些寄存器。

未知地址范围 (MMC5A: $5800-$5BFF, 只写)

当寄存器 $5207 = $03 时,该地址范围内的读取和写入反映在 CL3 和 SL3 引脚上。 该函数的目的未知。 在此范围内写入期间,M2 上升沿后不久的分钟 VCC 电流尖峰表现出与内部扩展 RAM 范围 $5C00-$5FFF 中的写入相同的特性,表明该范围内可能存在 RAM,尽管从该范围进行实验读取始终满足要求 具有开放的CPU总线。

地址 $5800 由 Just Breed 写入。 在每个 V-Blank 期间,它将值 $03,然后 $01 写入该地址,读取和写入 PPU 寄存器,完成后将值 $00 写入该地址。 理论上,这被用作调试信号来测量开发过程中的 CPU 使用率/空闲时间。

扫描线检测和扫描线IRQ

MMC5 通过首先从 $2xxx 范围内的同一命名表地址查找三个连续的 PPU 读取来检测扫描线。 一旦看到这一点,无论地址如何,下一个 PPU 读取都是检测到扫描线的点。 这是有效的,因为 PPU 在每个扫描线末尾执行两次匹配的虚拟命名表字节读取,然后在下一个扫描线的开头执行第三次匹配的命名表字节读取,然后读取属性表字节。 因此,当 PPU 在 PPU 周期 4 执行属性表字节读取时,会检测到扫描线。

一旦发生这种情况,如果“帧内”标志(寄存器$5204)被清除,它就会被设置,并且内部8位扫描线计数器重置为零; 但如果已经设置,则扫描线计数器会递增,然后与写入 $5203 的值进行比较。 如果它们匹配,则设置“irq待处理”标志。

当到达所需的扫描线时,无论扫描线 IRQ 是否启用,即即使在将 0 写入扫描线 IRQ 启用标志之后,IRQ 挂起标志都会升高。 然而,只有当扫描线 IRQ 启用标志和 IRQ 挂起标志都被设置时,实际的 IRQ 才会发送到 CPU。 $5203 的值 $00 是一种特殊情况,其中比较永远不会成立。 MMC5 的扫描线 IRQ 发生在 PPU 周期 4 处,这与 MMC3 的简单扫描线计数器不同,后者通常在 PPU 周期 260 左右生成 IRQ。

IRQ操作

寄存器 描述 存取
$5203 扫描线寄存器 只写
$5204 状态寄存器 读写

使用例子

寄存器常量声明

MAPPER_REG_APU_Pulse_1_0        =   $5000
MAPPER_REG_APU_Pulse_1_1        =   $5001
MAPPER_REG_APU_Pulse_1_2        =   $5002
MAPPER_REG_APU_Pulse_1_3        =   $5003
MAPPER_REG_APU_Pulse_2_0        =   $5004
MAPPER_REG_APU_Pulse_2_1        =   $5005
MAPPER_REG_APU_Pulse_2_2        =   $5006
MAPPER_REG_APU_Pulse_2_3        =   $5007

MAPPER_REG_PCM_MODE_IRQ         =   $5010
MAPPER_REG_RAW_PCM              =   $5011
MAPPER_REG_APU_STATUS           =   $5015

MAPPER_REG_PRG_MODE             =   $5100; 0: 32KB 1: 16KB * 2 2: 16KB + 8 * 2 3: 8*4
MAPPER_REG_CHR_MODE             =   $5101; 0: 8KB 1: 4KB * 2 2: 2KB * 4 3: 1KB * 8
MAPPER_REG_PRG_RAM_PROTECT_1    =   $5102;
MAPPER_REG_PRG_RAM_PROTECT_2    =   $5103;
MAPPER_REG_EX_RAM_MODE          =   $5104; 0: Write Only 1: Write Only 2: RW 3:R
MAPPER_REG_EX_RAM_ADDR          =   $5C00
MAPPER_REG_NT_MAPPING           =   $5105;
MAPPER_REG_FILL_MODE_TILE       =   $5106
MAPPER_REG_FILL_MODE_COLOR      =   $5107

MAPPER_REG_PRG_BANK_6000        =   $5113
MAPPER_REG_PRG_BANK_8000        =   $5114
MAPPER_REG_PRG_BANK_A000        =   $5115
MAPPER_REG_PRG_BANK_C000        =   $5116
MAPPER_REG_PRG_BANK_E000        =   $5117

MAPPER_REG_CHR_BANK_0000        =   $5120
MAPPER_REG_CHR_BANK_0400        =   $5121
MAPPER_REG_CHR_BANK_0800        =   $5122
MAPPER_REG_CHR_BANK_0C00        =   $5123
MAPPER_REG_CHR_BANK_1000        =   $5124
MAPPER_REG_CHR_BANK_1400        =   $5125
MAPPER_REG_CHR_BANK_1800        =   $5126
MAPPER_REG_CHR_BANK_1C00        =   $5127

MAPPER_REG_CHR_BANK_0000_1000   =   $5128
MAPPER_REG_CHR_BANK_0400_1400   =   $5129
MAPPER_REG_CHR_BANK_0800_1800   =   $512A
MAPPER_REG_CHR_BANK_0C00_1C00   =   $512B

MAPPER_REG_CHR_BANK_UPPER       =   $5130
MAPPER_REG_V_SPLIT_MODE         =   $5200
MAPPER_REG_V_SPLIT_SCROLL       =   $5201
MAPPER_REG_V_SPLIT_BANK         =   $5202

MAPPER_REG_IRQ_SCANLINE_VALUE   =   $5203
MAPPER_REG_IRQ_STATUS           =   $5204
MAPPER_REG_MULTIPLIER_A         =   $5205
MAPPER_REG_MULTIPLIER_B         =   $5206

MMC5A_CL3_SL3_DATA              =   $5207
MMC5A_CL3_SL3_STATUS            =   $5208
MMC5A_IRQ_TIMER_LSB             =   $5209
MMC5A_IRQ_TIMER_MSB             =   $520A

初始化


 ;设置一下6000-7FFF的RAM
 LDA #$00
 STA MAPPER_REG_PRG_BANK_6000
 
 ;启用 1KB 扩展RAM ($5C00-$5FFF)
 LDA #$02
 STA MAPPER_REG_EX_RAM_MODE
 
 ;初始化MMC5 图形 bank
 LDA #$00
 STA MAPPER_REG_CHR_BANK_0000
 LDA #$01
 STA MAPPER_REG_CHR_BANK_0400
 LDA #$02
 STA MAPPER_REG_CHR_BANK_0800
 LDA #$03
 STA MAPPER_REG_CHR_BANK_0C00
 
 LDA #$04
 STA MAPPER_REG_CHR_BANK_1000
 LDA #$05
 STA MAPPER_REG_CHR_BANK_1400
 LDA #$06
 STA MAPPER_REG_CHR_BANK_1800
 LDA #$07
 STA MAPPER_REG_CHR_BANK_1C00
 
 LDA #$00
 STA MAPPER_REG_CHR_BANK_0000_1000
 LDA #$01
 STA MAPPER_REG_CHR_BANK_0400_1400
 LDA #$02
 STA MAPPER_REG_CHR_BANK_0800_1800
 LDA #$03
 STA MAPPER_REG_CHR_BANK_0C00_1C00
 
 ;设置屏幕镜像($50: 水平; $44: 垂直)
 LDA #$50
 STA MAPPER_REG_NT_MAPPING
 
 ;设置C000 bank
 LDA #PRG_DATA_BANK_C000 & BANK_DATA_MASK
 ORA #$80
 STA MAPPER_REG_PRG_BANK_C000
 
 ;禁用IRQ
 LDA #$00
 STA MAPPER_REG_IRQ_SCANLINE_VALUE
 STA MAPPER_REG_IRQ_STATUS
 
 ;开启 PRG RAM 写入
 LDA #$02
 STA MAPPER_REG_PRG_RAM_PROTECT_1
 LDA #$01
 STA MAPPER_REG_PRG_RAM_PROTECT_2
 
 LDA #$02
 STA MAPPER_REG_EX_RAM_MODE
 LDX #$00
 LDA #$00
Init_Ex_RAM_Set;清空内部扩展RAM
 STA MAPPER_REG_EX_RAM_ADDR + $0000,X
 STA MAPPER_REG_EX_RAM_ADDR + $0100,X
 STA MAPPER_REG_EX_RAM_ADDR + $0200,X
 STA MAPPER_REG_EX_RAM_ADDR + $0300,X
 INX
 BNE Init_Ex_RAM_Set

切换 PRG bank

切换 PRG RAM bank 到 $6000-7FFF ($5113 写入 bank)
;机器码: 8D 13 51
Switch_Prg_Bank_6000
 STA MAPPER_REG_PRG_BANK_6000
模式0 (32KB * 1) ($5100 = $00)
切换 bank 到 $8000-FFFF ($5117 写入 bank)
;机器码: 09 80 8D 14 51
Switch_Prg_Bank_8000
 ORA #$80
 STA MAPPER_REG_PRG_BANK_E000
模式1 (16KB * 2) ($5100 = $01)
切换 bank 到 $8000-BFFF ($5115 写入 bank)
;机器码: 09 80 8D 15 51
Switch_Prg_Bank_8000
 ORA #$80
 STA MAPPER_REG_PRG_BANK_A000
切换 bank 到 $C000-FFFF ($5117 写入 bank)
;机器码: 09 80 8D 17 51
Switch_Prg_Bank_C000
 ORA #$80
 STA MAPPER_REG_PRG_BANK_E000
模式2 (16KB * 1 + 8KB * 2) ($5100 = $02)
切换 bank 到 $8000-BFFF ($5115 写入 bank)
;机器码: 09 80 8D 15 51
Switch_Prg_Bank_8000
 ORA #$80
 STA MAPPER_REG_PRG_BANK_A000
切换 bank 到 $C000-DFFF ($5116 写入 bank)
;机器码: 09 80 8D 16 51
Switch_Prg_Bank_C000
 ORA #$80
 STA MAPPER_REG_PRG_BANK_C000
切换 bank 到 $E000-FFFF ($5117 写入 bank)
;机器码: 09 80 8D 17 51
Switch_Prg_Bank_E000
 ORA #$80
 STA MAPPER_REG_PRG_BANK_E000
模式3 (8KB * 4) ($5100 = $03)
切换 bank 到 $8000-FFFF ($5114 写入 bank)
;机器码: 09 80 8D 14 51
Switch_Prg_Bank_8000
 ORA #$80
 STA MAPPER_REG_PRG_BANK_8000
切换 bank 到 $A000-BFFF ($5115 写入 bank)
;机器码: 09 80 8D 15 51
Switch_Prg_Bank_A000
 ORA #$80
 STA MAPPER_REG_PRG_BANK_A000
切换 bank 到 $C000-DFFF ($5116 写入 bank)
;机器码: 09 80 8D 16 51
Switch_Prg_Bank_C000
 ORA #$80
 STA MAPPER_REG_PRG_BANK_C000
切换 bank 到 $E000-FFFF ($5117 写入 bank)
;机器码: 09 80 8D 17 51
Switch_Prg_Bank_E000
 ORA #$80
 STA MAPPER_REG_PRG_BANK_E000

切换 CHR bank

当使用 8x8 精灵时, 仅使用寄存器 $5120-$5127. 寄存器 $5128-$512B 被完全忽略, 两种模式区别如下:

  • 8x8精灵时, 使用$5120-$5123选择背景图案, $5124-$5127选择精灵图案

  • 8x16精灵时, 使用$5128-$512B选择背景图案, $5120-$5127选择8K精灵图案(与4K背景图案并不重合)

MMC5 8x16精灵模式下 CHR切换 影响
CHR bank 寄存器 8x8精灵 ($2000.5 = 0时)
PPU $0000-$0FFF 图案作用
8x16精灵 ($2000.5 = 1时)
PPU $1000-$1FFF 图案作用
$5120-$5123 背景图案或精灵图案 精灵图案左4K(与背景图案不重合)
$5124-$5127 精灵图案或背景图案 精灵图案右4K(与背景图案不重合)
$5128-$512B 完全忽略 背景图案(与8K精灵图案不重合)
其他Mapper CHR切换 影响
PPU地址 8x8精灵 ($2000.5 = 0时) 8x16精灵 ($2000.5 = 1时)
PPU $0000-$0FFF图案作用 背景图案($2000.4 = 0)

精灵图案($2000.3 = 0)
背景图案($2000.4 = 0)

精灵图案左4K(偶数Tile索引)
PPU $1000-$1FFF图案作用 背景图案($2000.4 = 1)

精灵图案($2000.3 = 1)
背景图案($2000.4 = 0)

精灵图案右4K(奇数Tile索引)
模式0 (8KB * 1) ($5101 = $00)
切换 CHR bank 到 PPU $0000-$1FFF ($5127 写入 bank)
;机器码: 8D 27 51
Switch_Chr_Bank_0000
 STA MAPPER_REG_CHR_BANK_1C00
模式1 (4KB * 2) ($5101 = $01)
切换 CHR bank 到 PPU $0000-$0FFF ($5123 写入 bank)
;机器码: 8D 23 51
Switch_Chr_Bank_0000
 STA MAPPER_REG_CHR_BANK_0C00
切换 CHR bank 到 PPU $1000-$1FFF ($5127 写入 bank)
;机器码: 8D 27 51
Switch_Chr_Bank_1000
 STA MAPPER_REG_CHR_BANK_1C00
模式2 (2KB * 4) ($5101 = $02)
切换 CHR bank 到 PPU $0000-$07FF ($5121 写入 bank)
;机器码: 8D 21 51
Switch_Chr_Bank_0000
 STA MAPPER_REG_CHR_BANK_0400
切换 CHR bank 到 PPU $0800-$0FFF ($5123 写入 bank)
;机器码: 8D 23 51
Switch_Chr_Bank_0800
 STA MAPPER_REG_CHR_BANK_0C00
切换 CHR bank 到 PPU $1000-$17FF ($5125 写入 bank)
;机器码: 8D 25 51
Switch_Chr_Bank_1000
 STA MAPPER_REG_CHR_BANK_1400
切换 CHR bank 到 PPU $1800-$1FFF ($5127 写入 bank)
;机器码: 8D 27 51
Switch_Chr_Bank_1800
 STA MAPPER_REG_CHR_BANK_1C00
模式3 (1KB * 8) ($5101 = $03)
切换 CHR bank 到 PPU $0000-$03FF ($5120 写入 bank)
;机器码: 8D 20 51
Switch_Chr_Bank_0000
 STA MAPPER_REG_CHR_BANK_0000
切换 CHR bank 到 PPU $0400-$07FF ($5121 写入 bank)
;机器码: 8D 21 51
Switch_Chr_Bank_0400
 STA MAPPER_REG_CHR_BANK_0400
切换 CHR bank 到 PPU $0800-$0BFF ($5122 写入 bank)
;机器码: 8D 22 51
Switch_Chr_Bank_0800
 STA MAPPER_REG_CHR_BANK_0800
切换 CHR bank 到 PPU $0C00-$0FFF ($5123 写入 bank)
;机器码: 8D 23 51
Switch_Chr_Bank_0C00
 STA MAPPER_REG_CHR_BANK_0C00
切换 CHR bank 到 PPU $1000-$13FF ($5124 写入 bank)
;机器码: 8D 24 51
Switch_Chr_Bank_1000
 STA MAPPER_REG_CHR_BANK_1000
切换 CHR bank 到 PPU $1400-$17FF ($5125 写入 bank)
;机器码: 8D 25 51
Switch_Chr_Bank_1400
 STA MAPPER_REG_CHR_BANK_1400
切换 CHR bank 到 PPU $1800-$1BFF ($5126 写入 bank)
;机器码: 8D 26 51
Switch_Chr_Bank_1800
 STA MAPPER_REG_CHR_BANK_1800
切换 CHR bank 到 PPU $1C00-$1FFF ($5127 写入 bank)
;机器码: 8D 27 51
Switch_Chr_Bank_1C00
 STA MAPPER_REG_CHR_BANK_1C00

IRQ使用

IRQ首次启用 ($5203 写入 扫描线, $5204 写入 $80)
;机器码 A9 XX 8D 03 52 A9 80 8D 04 52
IRQ_Activate
 LDA #IRQ_SCANLINE_BEGIN
 STA MAPPER_REG_IRQ_SCANLINE_VALUE ;设置IRQ生成的位置, IRQ将会在IRQ_SCANLINE_BEGIN处生成
 LDA #$80
 STA MAPPER_REG_IRQ_STATUS ;启用IRQ
 CLI
IRQ启用 ($5204 写入 $80)
;机器码 A9 80 8D 04 52
IRQ_Enable
 LDA #$80
 STA MAPPER_REG_IRQ_STATUS ;启用IRQ
IRQ禁用 ($5204 写入 $00)
;机器码 A9 00 8D 03 52 8D 04 52
IRQ_Disable
 LDA #$00
 STA MAPPER_REG_IRQ_SCANLINE_VALUE
 STA MAPPER_REG_IRQ_STATUS ;禁用IRQ
IRQ确认 ($5204读)
;机器码 AD 04 52
IRQ_Disable_Acknowledge
 LDA MAPPER_REG_IRQ_STATUS ;读取IRQ状态寄存器将会确认IRQ

你可能感兴趣的:(FC,6502asm,6502,6502,FC,红白机,nes)