CPU $8000-$9FFF (or $C000-$DFFF): 8 KB switchable PRG ROM bank
CPU $A000-$BFFF: 8 KB switchable PRG ROM bank
CPU $C000-$DFFF (or $8000-$9FFF): 8 KB PRG ROM bank, fixed to the second-last bank
CPU $E000-$FFFF: 8 KB PRG ROM bank, fixed to the last bank
PPU $0000-$07FF (or $1000-$17FF): 2 KB switchable CHR bank
PPU $0800-$0FFF (or $1800-$1FFF): 2 KB switchable CHR bank
PPU $1000-$13FF (or $0000-$03FF): 1 KB switchable CHR bank
PPU $1400-$17FF (or $0400-$07FF): 1 KB switchable CHR bank
PPU $1800-$1BFF (or $0800-$0BFF): 1 KB switchable CHR bank
PPU $1C00-$1FFF (or $0C00-$0FFF): 1 KB switchable CHR bank
PRG切换的窗口是8KB
CHR切换的窗口是1KB
是目前切换的最小窗口了, 如果还有更小的就需要重写了
寄存器
MMC3根据地址拥有4对寄存器
Bank select ($8000-$9FFE, 偶数)
7 bit 0
---- ----
CPMx xRRR
||| |||
||| +++- Specify which bank register to update on next write to Bank Data register
||| 0: Select 2 KB CHR bank at PPU $0000-$07FF (or $1000-$17FF);
||| 1: Select 2 KB CHR bank at PPU $0800-$0FFF (or $1800-$1FFF);
||| 2: Select 1 KB CHR bank at PPU $1000-$13FF (or $0000-$03FF);
||| 3: Select 1 KB CHR bank at PPU $1400-$17FF (or $0400-$07FF);
||| 4: Select 1 KB CHR bank at PPU $1800-$1BFF (or $0800-$0BFF);
||| 5: Select 1 KB CHR bank at PPU $1C00-$1FFF (or $0C00-$0FFF);
||| 6: Select 8 KB PRG ROM bank at $8000-$9FFF (or $C000-$DFFF);
||| 7: Select 8 KB PRG ROM bank at $A000-$BFFF
||+------- Nothing on the MMC3, see MMC6
|+-------- PRG ROM bank mode (0: $8000-$9FFF swappable,
| $C000-$DFFF fixed to second-last bank;
| 1: $C000-$DFFF swappable,
| $8000-$9FFF fixed to second-last bank)
+--------- CHR A12 inversion (0: two 2 KB banks at $0000-$0FFF,
four 1 KB banks at $1000-$1FFF;
1: two 2 KB banks at $1000-$1FFF,
four 1 KB banks at $0000-$0FFF)
MMC6 的M位是指是否使用PRG-RAM.
nesdev给出了详细的情况列表, 可以自行查看, 编码时直接抄就行了
Bank data ($8001-$9FFF, 奇数)
7 bit 0
---- ----
DDDD DDDD
|||| ||||
++++-++++- New bank value, based on last value written to Bank select register (mentioned above)
STEP⑨: 实现部分Mapper
接下来进入本次的主角 Mapper004:
Mapper004: MMC3 - TxROM
MMC3 可谓是最开始几个Mapper中相当占分量的Mapper. MMC3是少数可以触发IRQ的Mapper之一.
MMC6也是用同一个mapper编号, 内部逻辑大致相同.
根据数据库,MMC3(在自己看来)比较有名的游戏, 比如:
MMC3的IRQ最大的用处, 就是处理的分割滚动效果(状态栏在下面)
IRQ 与 NMI区别
Banks
寄存器
MMC3根据地址拥有4对寄存器
Bank select ($8000-$9FFE, 偶数)
MMC6 的M位是指是否使用PRG-RAM.
nesdev给出了详细的情况列表, 可以自行查看, 编码时直接抄就行了
Bank data ($8001-$9FFF, 奇数)
Mirroring ($A000-$BFFE, 偶数)
这个就很简单了
PRG RAM protect ($A001-$BFFF, 奇数)
PRG RAM保护..感觉没必要实现
IRQ latch ($C000-$DFFE, 偶数)
IRQ了, 很重要的一环
IRQ闩锁, 用于指定一个重载值. 当计数器归零后, 计数器会重载这个值. 这个值会在每根扫描减少, 降至0就触发IRQ.
由于内部的原理是通过PPU巴拉巴拉, 所以要在背景精灵启动渲染才会触发倒计时, 否则运行超级马里奥3会程序会挂掉.
IRQ reload ($C001-$DFFF, 奇数)
IRQ重载, 写入任意值会让计数器归0
IRQ disable ($E000-$FFFE, 偶数)
IRQ禁止, 写入任意值标记禁止并且确认挂起的中断
IRQ enable ($E001-$FFFF, 奇数)
IRQ使能, 写入任意值标记使能
Mapper接口: 水平同步
这次功能就需要新的一个接口, 需要在每条扫描行进行一次同步, 我们就把它叫水平同步好了
由于目前的是EZ模式, 我们在每次可见扫描线结束后进行一次同步, 即水平同步. 计数器减到0就触发一次IRQ.
关于IRQ触发更为详细的细节请查看原文.
实现
本次的实现比较重要, 也明显比前面几个代码量更大.
STEP9-MAPPER004.c
结束?
本次先介绍的4种mapper就介绍完毕
项目地址Github-StepFC-Step9
作业
双截龙2: 复仇 模拟出现的问题
重装机兵模拟出现的问题
REF