要用FPGA实现mmc芯片的,肯定需要阅读各个mmc芯片的功能分析文档。类似于需要分析。
首先以MMC1芯片为例。(MMC1芯片有多个版本,暂时不考虑区别)。通过分析弄明白MMC1芯片的工作机制,如何切换bank。让CPU访问存放在ROM中的代码。
所有的内容都是从MMC1 - NESdev Wiki分析整理。
Disch's detailed list of over 50 mappers at romhacking.net(链接中可以下载上百个mapper的说明)
飞狼游戏mapper和bank信息
mapper 1,MMC1芯片(SxRom)。PRG-rom一共128KB字节,8x16Kb(8个bank,每个bank16KB)
MMC1游戏卡电路图
(TODO),结合电路图更容易理解。
MMC1 pinout(管脚图)
.--\/--. PRG A14 (r) <- |01 24| -- +5V PRG A15 (r) <- |02 23| <- M2 (n) PRG A16 (r) <- |03 22| <- CPU A13 (nr) PRG A17 (r) <- |04 21| <- CPU A14 (n) PRG /CE (r) <- |05 20| <- /ROMSEL (n) WRAM +CE (w) <- |06 19| <- CPU D7 (nrw) CHR A12 (r) <- |07 18| <- CPU D0 (nrw) CHR A13 (r) <- |08 17| <- CPU R/W (nw) CHR A14 (r) <- |09 16| -> CIRAM A10 (n) CHR A15 (r) <- |10 15| <- PPU A12 (nr) CHR A16 (r) <- |11 14| <- PPU A11 (nr) GND -- |12 13| <- PPU A10 (nr) `------'
寄存器
一共五个寄存器,load寄存器可以由CPU直接访问,访问地址就是在0x8000-0xFFFF任意区间(不是传统的寄存器是某个固定地址)。其他四个寄存器是内部寄存器,只能通过load寄存器进行设置。对应的地址也是在操作load寄存器的时候其CPU访问的地址就是要写的那个寄存器。比如我要访问Control寄存器,写load register的时候CPU访问地址是0x8000-0x9FFF。
控制机制
load寄存器位说明,只有bit0和bit7有用,bit0就是数据位。
7 bit 0 ---- ---- Rxxx xxxD | | | +- Data bit to be shifted into shift register, LSB first +--------- A write with bit set will reset shift register and write Control with (Control OR $0C), locking PRG ROM at $C000-$FFFF to the last bank.
PRG bank寄存器:一共5个bit。
4bit0 ----- RPPPP ||||| |++++- Select 16 KB PRG ROM bank (low bit ignored in 32 KB mode) +----- MMC1B and later: PRG RAM chip enable (0: enabled; 1: disabled; ignored on MMC1A) MMC1A: Bit 3 bypasses fixed bank logic in 16K mode (0: affected; 1: bypassed)
所以要切换PRG bank,就需要向这个寄存器写入要切换的bank号。通过向load寄存器写入五次,最终写入该寄存器,然后芯片的PRG地址总线输出相应的bank对应的地址线电平有效。完成PRG的bank切换。
示例代码:
;
; Sets the switchable PRG ROM bank to the value of A.
;
; A MMC1_SR MMC1_PB
setPRGBank: ; 000edcba 10000 Start with an empty shift register (SR). The 1 is used
sta $E000 ; 000edcba -> a1000 to detect when the SR has become full.
lsr a ; >0000edcb a1000
sta $E000 ; 0000edcb -> ba100
lsr a ; >00000edc ba100
sta $E000 ; 00000edc -> cba10
lsr a ; >000000ed cba10
sta $E000 ; 000000ed -> dcba1 Once a 1 is shifted into the last position, the SR is full.
lsr a ; >0000000e dcba1
sta $E000 ; 0000000e dcba1 -> edcba A write with the SR full copies D0 and the SR to a bank register
; 10000 ($E000-$FFFF means PRG bank number) and then clears the SR.
rts
MMC1芯片的FPGA实现
GitHub - db-electronics/NESMappers: VHDL Nes Mappers - NES Flash Cart Project
上面的链接有一个MMC1 mapper的 VHDL的实现。
下载mmc1.vhd文件,用Quartus创建一个项目,编译之后可以查看RTL视图
黄色部分就是实现移位寄存器的状态机。控制各个输出管脚的电平来实现bank切换。