yandagui 发表于 2017-4-14 19:43:10

[FC][Mapper23转Mapper4实例教程]

本帖最后由 yandagui 于 2017-4-16 19:06 编辑

Mapper23转Mapper4实例教程

FlameCyclone 2017.4.14

先看看Mapper23文档:

Mapper 23

$8000:选择8KB的ROM存储体映射到$8000

$9000:0:垂直镜像
        1:水平镜像
        2:$2400镜像
        3:$2000镜像

$A000:选择8KB的ROM存储体映射到$A000

$B000:选择1KB的VROM存储体映射到PPU的$0000(低4位)
$B001:选择1KB的VROM存储体映射到PPU的$0000(高4位)
$B002:选择1KB的VROM存储体映射到PPU的$0400(低4位)
$B003:选择1KB的VROM存储体映射到PPU的$0400(高4位)

$C000:选择1KB的VROM存储体映射到PPU的$0800(低4位)
$C001:选择1KB的VROM存储体映射到PPU的$0800(高4位)
$C002:选择1KB的VROM存储体映射到PPU的$0C00(低4位)
$C003:选择1KB的VROM存储体映射到PPU的$0C00(高4位)

$D000:选择1KB的VROM存储体映射到PPU的$1000(低4位)
$D001:选择1KB的VROM存储体映射到PPU的$1000(高4位)
$D002:选择1KB的VROM存储体映射到PPU的$1400(低4位)
$D003:选择1KB的VROM存储体映射到PPU的$1400(高4位)

$E000:选择1KB的VROM存储体映射到PPU的$1800(低4位)
$E001:选择1KB的VROM存储体映射到PPU的$1800(高4位)
$E002:选择1KB的VROM存储体映射到PPU的$1C00(低4位)
$E003:选择1KB的VROM存储体映射到PPU的$1C00(高4位)

再看看Mapper 4文档:

Mapper 4

$8000:模式号
        位D0-D2:
        0:选择2KB的VROM存储体映射到PPU的$0000
        1:选择2KB的VROM存储体映射到PPU的$0800
        2:选择1KB的VROM存储体映射到PPU的$1000
        3:选择1KB的VROM存储体映射到PPU的$1400
        4:选择1KB的VROM存储体映射到PPU的$1800
        5:选择1KB的VROM存储体映射到PPU的$1C00
        6:选择8KB的ROM存储体映射到$8000
        7:选择8KB的ROM存储体映射到$A000
        位D6:
        0:允许擦写$8000和$A000
        1:允许擦写$A000和$C000
        位D7:
        0:模式号D0-D2使用普通地址
        1:模式号D0-D2地址异或$1000

$8001:模式页面号
        写入一个数(00-07),切换存储体到对应地址

$A000:镜像选择
        0:垂直镜像
        1:水平镜像

$A001:SaveRAM 切换
        0:禁用$6000-$7FFF
        1:启用$6000-$7FFF

$C000:IRQ计数器
        IRQ计数器的值存储在此处

$C001:IRQ暂存器
        IRQ暂存器的值存储在此处

$E000:IRQ控制计数器0
        向这里写入任何数来关闭IRQ,并从暂存器中拷贝数据开始计数,进入IRQ

$E001:IRQ控制计数器1
        向这里写入任何数,允许IRQ(退出IRQ,允许下一个IRQ进来)


转换思路:
将Mapper 23 的切bank 方式和切VRAM的方式修改成Mapper 4 的方式。

修改实例:
Contra (J) 256KB Mapper 23
工具:
1.FCEUX 2。2。3
2.HXD
先来看看这ROM的切bank方式:
F989:AD 00 80LDA $8000
F98C:8D EC 07STA $07EC
F98F:8C 00 80STY $8000
F992:C8      INY
F993:8C 00 A0STY $A000
F996:60      RTS

再看看它的切VRAM方式:
FACE:AD F0 07LDA $07F0
FAD1:8D 00 B0STA $B000
FAD4:4A      LSR
FAD5:4A      LSR
FAD6:4A      LSR
FAD7:4A      LSR
FAD8:8D 01 B0STA $B001
FADB:AD F1 07LDA $07F1
FADE:8D 02 B0STA $B002
FAE1:4A      LSR
FAE2:4A      LSR
FAE3:4A      LSR
FAE4:4A      LSR
FAE5:8D 03 B0STA $B003
FAE8:AD F2 07LDA $07F2
FAEB:8D 00 C0STA $C000
FAEE:4A      LSR
FAEF:4A      LSR
FAF0:4A      LSR
FAF1:4A      LSR
FAF2:8D 01 C0STA $C001
FAF5:AD F3 07LDA $07F3
FAF8:8D 02 C0STA $C002
FAFB:4A      LSR
FAFC:4A      LSR
FAFD:4A      LSR
FAFE:4A      LSR
FAFF:8D 03 C0STA $C003
FB02:AD F4 07LDA $07F4
FB05:8D 00 D0STA $D000
FB08:4A      LSR
FB09:4A      LSR
FB0A:4A      LSR
FB0B:4A      LSR
FB0C:8D 01 D0STA $D001
FB0F:AD F5 07LDA $07F5
FB12:8D 02 D0STA $D002
FB15:4A      LSR
FB16:4A      LSR
FB17:4A      LSR
FB18:4A      LSR
FB19:8D 03 D0STA $D003
FB1C:AD F6 07LDA $07F6
FB1F:8D 00 E0STA $E000
FB22:4A      LSR
FB23:4A      LSR
FB24:4A      LSR
FB25:4A      LSR
FB26:8D 01 E0STA $E001
FB29:AD F7 07LDA $07F7
FB2C:8D 02 E0STA $E002
FB2F:4A      LSR
FB30:4A      LSR
FB31:4A      LSR
FB32:4A      LSR
FB33:8D 03 E0STA $E003
FB36:A9 00   LDA #$00
FB38:8D 00 90STA $9000
FB3B:60      RTS

接下来修改切bank方式:
FB2B:48      PHA
FB2C:A9 06   LDA #$06
FB2E:8D 00 80STA $8000
FB31:68      PLA
FB32:8C 01 80STY $8001
FB35:60      RTS

FB36:48      PHA
FB37:A9 07   LDA #$07
FB39:8D 00 80STA $8000 = #$14
FB3C:68      PLA
FB3D:8C 01 80STY $8001 = #$1D
FB40:60      RTS

还要把原ROM的对$8000和$A000进行写入操作的程序修改一下:
F989:AD 00 80LDA $8000
F98C:8D EC 07STA $07EC
F98F:20 2B FBJSR $FB2B
F992:C8      INY
F993:20 36 FBJSR FB36
F996:60      RTS

再修改切VRAM程序:
FACE:A9 00   LDA #$00
FAD0:8D 00 80STA $8000
FAD3:AD F0 07LDA $07F0
FAD6:C9 01   CMP #$01
FAD8:D0 11   BNE $FAEB
FADA:AD F1 07LDA $07F1
FADD:C9 04   CMP #$04
FADF:D0 04   BNE $FAE5
FAE1:A9 80   LDA #$80
FAE3:D0 06   BNE $FAEB
FAE5:C9 05   CMP #$05
FAE7:D0 02   BNE $FAEB
FAE9:A9 82   LDA #$82
FAEB:8D 01 80STA $8001
FAEE:A9 01   LDA #$01
FAF0:8D 00 80STA $8000
FAF3:AD F2 07LDA $07F2
FAF6:8D 01 80STA $8001
FAF9:A9 02   LDA #$02
FAFB:8D 00 80STA $8000
FAFE:AD F4 07LDA $07F4
FB01:8D 01 80STA $8001
FB04:A9 03   LDA #$03
FB06:8D 00 80STA $8000
FB09:AD F5 07LDA $07F5
FB0C:8D 01 80STA $8001
FB0F:A9 04   LDA #$04
FB11:8D 00 80STA $8000
FB14:AD F6 07LDA $07F6
FB17:8D 01 80STA $8001
FB1A:A9 05   LDA #$05
FB1C:8D 00 80STA $8000
FB1F:AD F7 07LDA $07F7
FB22:8D 01 80STA $8001
FB25:A9 00   LDA #$00
FB27:8D 00 A0STA $A000
FB2A:60      RTS

然后保存文件。
使用HXD修改文件头:
将Mapper23
06字节的高4位是Mapper号的低4位
07字节的高4位是Mapper号的高4位
组合起来就是0x17=1*16+7=23
http://www.emu618.org/data/attachment/album/201704/14/194043pkfclkg4dfcndfmf.png
修改成 Mapper 4
http://www.emu618.org/data/attachment/album/201704/14/194046k8803wddtdbsst0v.png


再次打开文件:
http://www.emu618.org/data/attachment/album/201704/14/194121doiy8nf8pfygggpd.png
可以正常运行
通过全面测试,发现出现精灵错乱:
第1关:
http://www.emu618.org/data/attachment/album/201704/14/194124m9j9eyv92e8l9d2t.png

第2关:
http://www.emu618.org/data/attachment/album/201704/14/194127iz9b4diniuuiel8x.png
任务失败后:
http://www.emu618.org/data/attachment/album/201704/14/194130o5mumzrffi4i3jfc.png
通关后上飞机画面:
http://www.emu618.org/data/attachment/album/201704/14/194131welpsqvytxmz3upl.png
这是为何呢?
这是因为Mapper 23 中精灵VRAM切bank是一次切1KB
但是在Mapper 4中精灵VRAM切换却是一次切2KB,而且忽略bank号的D0位
比方bank 0和bank 1是同一个bank,同理bank 2和bank 3是同一个bank
也就是说
Mapper 23中的VRAM的
bank 0,bank 1,bank 2,bank 3
在Mapper 4中对应的是
Bank 0,bank 0,bank 2, bank2
然后查找原来的ROM的切VRAM的程序:
知道是从07F0-07F3切到精灵VRAM的:
如图所示:
http://www.emu618.org/data/attachment/album/201704/14/194133ih1whtw4h1yglwdg.png
http://www.emu618.org/data/attachment/album/201704/14/194135nn2wswsyhpz697yc.pnghttp://www.emu618.org/data/attachment/album/201704/14/194137vgoi1ow2oi5gicoi.png
作为对比,左边是原版,右边是修改。
接下来是完善VRAM切换带来的问题,因为Mapper 4只能切2KB的bank,所以我们不能通过切bank程序解决问题。
通过测试知道1,3,5,6,7,8关的精灵VRAM排序如下(07F0-07F3):
01 04 06 07
第2,4关如下:
01 05 08 09
任务失败时如下:
32 00 00 1B
其中任务失败时对应的VRAM是07F3的1B,只要让07F2为1A或1B即可:
通过调试找到对07F2写入数据#$00时程序如下,于是修改C7E5的值为1A即可:
http://www.emu618.org/data/attachment/album/201704/14/194140wrbap8a8ulaz5nr8.png
转到ROM地址:
http://www.emu618.org/data/attachment/album/201704/14/194142llbhl71b7j21wwwh.png
修改数据:
http://www.emu618.org/data/attachment/album/201704/14/194144ou3fk9ujzqttzzeq.png
重新失败后可以看到修复成功:
http://www.emu618.org/data/attachment/album/201704/14/194146jztpp4nj11dr76fa.png
接下来是修复正常进行任务时的精灵错乱问题。
首先运行Mapper 23版本,在1,3,5,6,7,8关任意一关的时候,将PPU导出来
http://www.emu618.org/data/attachment/album/201704/14/194148od800dyk24y4555r.png
http://www.emu618.org/data/attachment/album/201704/14/194150sbjbbwdjd0hw3dj4.png
http://www.emu618.org/data/attachment/album/201704/14/194152ozahja8a0xgusa7d.png
http://www.emu618.org/data/attachment/album/201704/14/194154cxbx8ia6v10qjijo.png
然后用Hxd打开修改的Mapper 4的ROM和刚刚保存的PPU的数据文件:
http://www.emu618.org/data/attachment/album/201704/14/194156l32fhplhscnsccp2.png
在ROM文件头第05字节改为0x20:
http://www.emu618.org/data/attachment/album/201704/14/194158d90miz59w3866lu6.png
然后转到文件末尾,插入0x20000字节空字节:
http://www.emu618.org/data/attachment/album/201704/14/194159jrtpxj0r7qt185pw.png
http://www.emu618.org/data/attachment/album/201704/14/194200i9y62qkyikr5ys5y.png
http://www.emu618.org/data/attachment/album/201704/14/194201kxn9rpldn566enbx.png
http://www.emu618.org/data/attachment/album/201704/14/194202r7xf3rssdatsht33.png
然后将第1关的PPU数据的前面2KB数据选定:
http://www.emu618.org/data/attachment/album/201704/14/194203eglz1bwcxxzxwkps.png
http://www.emu618.org/data/attachment/album/201704/14/194205xml1l888qqlpicle.png
http://www.emu618.org/data/attachment/album/201704/14/194207np44po1544r59o6j.png
复制之后以覆盖方式粘贴到ROM的40010,同样把第2关的PPU数据的前面2KB以覆盖方式粘贴到ROM的40810
http://www.emu618.org/data/attachment/album/201704/14/194209v3buwrb3fjwvm4vm.png
然后保存文件:
http://www.emu618.org/data/attachment/album/201704/14/194211ngzrgol00nrz0rrf.png
最后用FCEUX打开文件,添加07F0-07F3的写入断点
http://www.emu618.org/data/attachment/album/201704/14/194215rfcrx5scwwwxcsfv.png
地图预览后即将进入第一关画面时程序暂停了,可以知道此时准备将C793的数据写到07F0:
http://www.emu618.org/data/attachment/album/201704/14/194217iuu3u3uvuu3rtll2.png
测试后知道将C793-0796写入到了07F0-07F3:
同理,经测试每4个字节一组,一共17组,其中01 04对应普通关卡精灵以及其BOSS关的精灵VRAM的bank号,01 05对应2,4关卡精灵以及其BOSS关的精灵VRAM的bank号,再加上一个通关后跳上飞机那段动画的精灵VRAM的bank号。

http://www.emu618.org/data/attachment/album/201704/14/194219gusvrtbn2utc2vz3.png
然后将文件中标记的01 04修改为 80 04,将01 05 修改为82 04即可:
http://www.emu618.org/data/attachment/album/201704/14/194221bltohlzdkjkxfcxo.png
保存之后重新运行后效果如下:
http://www.emu618.org/data/attachment/album/201704/14/194223kwwsvu7gwzsr9vga.png
http://www.emu618.org/data/attachment/album/201704/14/194225ppunnjelebuapyqp.png
http://www.emu618.org/data/attachment/album/201704/14/195739udvbnzdxnbv244dg.png
当前使用的是FCEUX模拟器,如果用NEStopia玩的话一开始就死机了,这是因为这个ROM有文件保护吧,它会往$6000里写入数据:
http://www.emu618.org/data/attachment/album/201704/14/195740oqs64zvshq509590.png
F863:A0 03   LDY #$03
F865:98      TYA
F866:29 01   AND #$01
F868:8D E9 07STA $07E9
F86B:8D 00 60STA $6000
F86E:AD 00 60LDA $6000
F871:29 01   AND #$01
F873:CD E9 07CMP $07E9
F876:D0 05   BNE $F87D
F878:88      DEY
F879:10 EA   BPL $F865
F87B:30 03   BMI $F880
F87D:4C 00 00JMP $0000
F880:A5 1A   LDA $001A
F882:65 34   ADC $0034
F884:85 34   STA $0034
F886:4C 80 F8JMP $F880
先取Y值=#$03
与#$01相与后得到#$01
写入到$07E9
写入到$6000
再读取$6000的数据和#$01相与后和$07E9的数据比较
不同的话跳过5字节
否则Y递减
为正数就跳回0x100-0xEA=16字节
为负数就跳过0x3字节
跳转到$0000(简直没有人性了,跳到这里死机,真想得出来)

正是因为这样,NEStopia运行FC时,6000-7FFF默认是不可写的,必须在ROM文件头第6字节的D1位置1设置ROM有SRAM,对于Mapper 4,还需要向$A001写入#$80来启用SRAM。
由于$6000不可写,因此想$6000写入#$01后$6000还是#$00,之后读取$07E9的#$01与之相比当然不同了,于是直接跳转到死机程序了。
解决方法是把ROM中的所有的AD 00 60 29 01 CD E9 07 D0 05 88 10 EA 30 03 4C 00 00
中的D0 05改为D0 00,然后保存即可。
测试完美运行。
http://www.emu618.org/data/attachment/album/201704/14/200424y1nggy1yf1mmyf11.png

教程到此结束。

**** Hidden Message *****

街机爱好者 发表于 2017-4-14 21:37:22

虽然看不懂,但还是进来支持一下楼主发的修改游戏的教程,楼主辛苦了。{:4_137:}

cococo8858 发表于 2017-4-15 07:40:42

巨巨威武,不但分享作品,还分享技术。目前只能纯支持了。希望有一天能看懂。{:4_118:}

文子萝卜 发表于 2017-4-15 08:18:51

长文一般不看{:4_112:}

afti 发表于 2017-4-15 09:07:05

感谢发布实例教程!

qqture2005 发表于 2017-4-15 10:18:45

很好的实例教程,学习了。

shilinnnn 发表于 2017-6-23 09:40:56

学校谢谢。。。。。。。。。。。。。。。。。。。。。

ey136 发表于 2017-8-15 17:17:13

感谢分享,看一下楼主的修改方法
页: [1]
查看完整版本: [FC][Mapper23转Mapper4实例教程]