|
|
本帖最后由 yandagui 于 2017-4-16 19:06 编辑
( d4 c+ {1 }- }5 ~- H1 {: P$ j$ {
# p) o6 I. e8 B% yMapper23转Mapper4实例教程9 J# q) ^ ?" g) ]
3 S- v! K% e7 _6 ~5 b
FlameCyclone 2017.4.145 n3 s8 b* A+ f& F0 w1 g0 n9 v
, \7 n% @' x1 ^% A0 a1 l! R1 {先看看Mapper23文档:
4 h, ], a" O# h0 z- n/ J+ A1 D- w0 ]) w: c x# n/ I
Mapper 23" c) J8 Y1 z, B! J+ k) E
# t1 ?: b8 f2 `: x$8000: 选择8KB的ROM存储体映射到$8000
" W( H( ?/ P( V5 d( H' i O9 h& s
6 W% D, c: h* d0 Y! e: I( z0 c$9000: 0:垂直镜像
/ k" c: ^1 C: b4 h+ p% W 1:水平镜像4 d; J: r- ]. k; R+ q
2:$2400镜像
H: H0 i- B7 k- h+ Z( U4 i4 X 3:$2000镜像2 o0 K) @3 [( ^1 K. W3 u0 \! e( b
6 ^3 E( J- L/ D$A000: 选择8KB的ROM存储体映射到$A000; P) w* p4 ]4 a8 ~+ K, o- E7 E
2 ]* N. h5 M" P6 U* [! I
$B000: 选择1KB的VROM存储体映射到PPU的$0000(低4位)& a: @3 D! l- Z9 Y, ]0 A3 u5 G
$B001: 选择1KB的VROM存储体映射到PPU的$0000(高4位): E X5 _4 L8 a- I
$B002: 选择1KB的VROM存储体映射到PPU的$0400(低4位)! k) O) I' F7 t& M4 m
$B003: 选择1KB的VROM存储体映射到PPU的$0400(高4位)5 ] b! O7 s' ]# r! {
1 v) U7 U; |- O, I
$C000: 选择1KB的VROM存储体映射到PPU的$0800(低4位)
" @5 E+ L" c) V) v$C001: 选择1KB的VROM存储体映射到PPU的$0800(高4位)! _5 l. m/ f e3 }
$C002: 选择1KB的VROM存储体映射到PPU的$0C00(低4位)0 Z* K3 n! ]/ w' \
$C003: 选择1KB的VROM存储体映射到PPU的$0C00(高4位)
/ b i# B5 i6 l1 ~5 K
' ]$ m# k$ \* T% Y) `$D000: 选择1KB的VROM存储体映射到PPU的$1000(低4位)
3 i" E# x/ |* H1 p+ Q+ _; ^$D001: 选择1KB的VROM存储体映射到PPU的$1000(高4位)6 u$ m: t) u5 h8 ] @
$D002: 选择1KB的VROM存储体映射到PPU的$1400(低4位)
, i8 B, V% V# w% q# Z& E$D003: 选择1KB的VROM存储体映射到PPU的$1400(高4位)
" H* Y o' b, h$ T, x% ~6 V1 r. o0 A+ T3 f# |" Q
$E000: 选择1KB的VROM存储体映射到PPU的$1800(低4位)2 a3 H) u4 ?9 ]9 B1 q0 W1 F. {
$E001: 选择1KB的VROM存储体映射到PPU的$1800(高4位)
8 e. k' Y3 {8 o' }) J$E002: 选择1KB的VROM存储体映射到PPU的$1C00(低4位)- i7 d! ~0 l; e4 ?7 o
$E003: 选择1KB的VROM存储体映射到PPU的$1C00(高4位)
2 R0 _4 s" o7 I2 U) \
# S: c/ V5 M1 g4 i. l6 ]再看看Mapper 4文档:
+ |4 g) E* p2 b# j* w' X* O; u; Y; w% R
- H/ N6 J3 J5 F8 kMapper 4
+ @' B; B( B, R6 Q! k+ O' Z6 s9 m! p! {# B; l
$8000: 模式号) H s7 ^0 B. \
位D0-D2:
{5 Y+ Z- I3 T8 C% ~1 Z7 X% F, N) d 0:选择2KB的VROM存储体映射到PPU的$0000
+ Y/ Q7 o/ ?! {' M+ s6 g 1:选择2KB的VROM存储体映射到PPU的$0800+ D1 u, S8 l$ r% L; o: S' ~# m
2:选择1KB的VROM存储体映射到PPU的$1000
* l$ _# T. F4 L8 p$ W 3:选择1KB的VROM存储体映射到PPU的$1400$ A) W1 o8 W$ o
4:选择1KB的VROM存储体映射到PPU的$1800! l7 v3 T5 ?* H+ @( p) R
5:选择1KB的VROM存储体映射到PPU的$1C00
4 H) P4 q- r7 e/ t! E, P2 ] 6:选择8KB的ROM存储体映射到$8000' b/ {% x% O0 s' U5 L$ H, q
7:选择8KB的ROM存储体映射到$A000
6 c0 L0 T, B9 N$ W% @; |7 @# m 位D6:
7 l9 n" X( p6 {( L 0:允许擦写$8000和$A0009 M1 C3 T( p' l/ e8 B- T- t2 ?
1:允许擦写$A000和$C000 W1 |0 ?% H4 X' m( z. q) I# g
位D7:
1 h0 L9 t& L. ~1 a0 ? 0:模式号D0-D2使用普通地址
: c6 q {, ]: W( K 1:模式号D0-D2地址异或$1000; Y- J5 J6 {. L5 h
/ X2 q& t$ P: x1 H$ D$8001: 模式页面号
- i5 F& G7 s- Z/ r/ j- D 写入一个数(00-07),切换存储体到对应地址
7 ]+ {5 b H# I* Z
5 X/ x5 C5 n% }# N7 ]" n# v- E$A000: 镜像选择
2 j* ?+ u7 s6 ~ 0:垂直镜像2 m2 G r8 [; ?3 h
1:水平镜像
* ]$ ~( l$ F/ {3 m
8 Y K1 v6 I" l/ C/ S$A001: SaveRAM 切换- i% `+ c7 X4 h( u. |% X
0:禁用$6000-$7FFF. Y5 {& u! v% G
1:启用$6000-$7FFF
( S3 O: O9 q3 l" d
% j; `# b1 g& g3 X# |$C000: IRQ计数器
! x" }* C: `% ^) F8 L6 y IRQ计数器的值存储在此处2 t- H* d$ J" q: P# `
" _* k2 D& s) m- j$ I9 o9 B$C001: IRQ暂存器, U* j+ k( q# S7 u: V4 T8 }
IRQ暂存器的值存储在此处( F2 j% ?# Z6 |1 \6 u5 s9 H
) T; f% B5 U! o( }6 i. v; B
$E000: IRQ控制计数器0
# o; Z) U* Z0 b, U9 w 向这里写入任何数来关闭IRQ,并从暂存器中拷贝数据开始计数,进入IRQ. }4 U4 A. N4 v! D' D( Z. X
$ o q9 ^* v! E# E5 ]$E001: IRQ控制计数器1
6 N. j& b3 x/ Q g+ w1 X 向这里写入任何数,允许IRQ(退出IRQ,允许下一个IRQ进来)2 | |7 L' _* z/ J8 i3 U
2 I( N% {9 l1 h% i. _$ }: B" w9 q# L3 P! p
转换思路:# e* ~/ P; N3 o! T* o; W
将Mapper 23 的切bank 方式和切VRAM的方式修改成Mapper 4 的方式。$ ?. R7 O Z8 ~! w2 q4 e
7 @5 H& O$ c, _. c
修改实例:1 [8 u' D! A/ |! @
Contra (J) 256KB Mapper 23' u$ }6 o' q- P, b6 f4 A. F
工具:
8 Q' ?6 B; `$ d9 O& N( v4 i: }+ U1.FCEUX 2。2。3
! R! n7 O# D! S) }1 R$ |" Q2.HXD8 a% J$ @# Y: ]
先来看看这ROM的切bank方式:! f7 g- p$ T: L3 H
F989:AD 00 80 LDA $8000 5 n" n1 j: k- c9 D
F98C:8D EC 07 STA $07EC
/ _! J; x8 e+ D: wF98F:8C 00 80 STY $8000; F8 I: M7 G; d& m! G6 a, p J
F992:C8 INY
- N w9 ]6 N" m! hF993:8C 00 A0 STY $A000
- W" E( u5 m2 m) Z8 }F996:60 RTS
+ J1 T6 N( m" e) j& L I
: {3 ]6 T+ L8 X! o2 c @2 r1 B9 |再看看它的切VRAM方式:
& s9 a o. e7 Z7 zFACE:AD F0 07 LDA $07F04 {+ L! I. ?, `" F( e- `) ]
FAD1:8D 00 B0 STA $B000) D% l- v" e+ z' [: _" V
FAD4:4A LSR
7 b% v* P" S0 P0 g+ iFAD5:4A LSR8 h! b8 }0 N; _6 |, C4 q* J9 y( Y
FAD6:4A LSR
4 [% ~+ F8 [1 t# qFAD7:4A LSR) [$ E- _, c. z, y5 `5 y
FAD8:8D 01 B0 STA $B001' u% e q L4 M! c
FADB:AD F1 07 LDA $07F11 m" T, \. f! p
FADE:8D 02 B0 STA $B002
0 Y; f3 ^8 o! r+ d) ]FAE1:4A LSR
3 p6 @/ t X% ^( G. b8 HFAE2:4A LSR& k# X/ B5 ~5 R& J. i& }
FAE3:4A LSR2 J3 J5 f0 Q7 @1 w5 g; g# _
FAE4:4A LSR7 d$ C! O W0 ]4 J1 U( {
FAE5:8D 03 B0 STA $B003; |4 @# n3 e! ]; b$ [, p/ v" L
FAE8:AD F2 07 LDA $07F23 m6 x* Y2 Y7 |- O
FAEB:8D 00 C0 STA $C000
# b- G" i. Y. fFAEE:4A LSR! A9 O% ^; j! J' ~0 Q
FAEF:4A LSR
. M2 f& |+ @$ R( nFAF0:4A LSR" r9 X$ \- v: f
FAF1:4A LSR5 r9 U/ V8 w5 G& a: b3 L% R9 N
FAF2:8D 01 C0 STA $C001
; _/ _2 v7 ^9 |9 `% eFAF5:AD F3 07 LDA $07F3! c- Q9 u2 O: s# c1 v9 J A$ x
FAF8:8D 02 C0 STA $C002( o- N4 m7 f3 q
FAFB:4A LSR" }$ a& t& v, a9 b/ O
FAFC:4A LSR
9 e0 Y9 d* b" _( s) p+ TFAFD:4A LSR
% g1 u$ Q2 d' e, b" a7 BFAFE:4A LSR9 {8 R3 O# x. `$ a! h, u! g
FAFF:8D 03 C0 STA $C003
0 d5 u# e1 Q* r! i5 N/ nFB02:AD F4 07 LDA $07F4
" Y; ~" Z! H& Z$ m& OFB05:8D 00 D0 STA $D000
/ N" w4 A# ` g- N' m7 eFB08:4A LSR
: O/ W7 g# p4 \& NFB09:4A LSR
" l7 K# Z! x9 L4 f5 HFB0A:4A LSR
4 o- ~+ I$ ~! R+ E; |, UFB0B:4A LSR
9 O: [& Q0 o$ [FB0C:8D 01 D0 STA $D001. ]) ~; G4 P d, R0 J* S
FB0F:AD F5 07 LDA $07F51 v7 p" s! ^) x- b7 k
FB12:8D 02 D0 STA $D002
$ R( X' m; E( I2 i0 I6 T5 F+ PFB15:4A LSR L2 u4 B+ w: L$ J
FB16:4A LSR; F5 R9 ]- L) U& ?) K
FB17:4A LSR9 b, g$ B F$ P# ]4 z8 P" v
FB18:4A LSR; ]; f: f: p5 S Y2 u# G) ?9 Z/ r
FB19:8D 03 D0 STA $D003
8 g2 F8 r6 H6 {FB1C:AD F6 07 LDA $07F69 Q5 K( B, n5 l" n
FB1F:8D 00 E0 STA $E000
: [. f7 W0 f" [% `2 J4 U, W$ A3 cFB22:4A LSR
) u9 V/ J7 g( X- |% B% R# gFB23:4A LSR
0 a4 l# u6 M1 X7 PFB24:4A LSR
1 t0 z- j* U# MFB25:4A LSR. r$ u6 c! R) p5 c; @; h/ g+ E
FB26:8D 01 E0 STA $E001; ?1 h) J# [+ L6 R
FB29:AD F7 07 LDA $07F7
3 E) L5 C& d' p7 J' H |FB2C:8D 02 E0 STA $E002' s! z/ Y) d G# R
FB2F:4A LSR4 X- G1 ~1 o1 ]! t- m8 x
FB30:4A LSR1 B X9 X, i" v5 t( E
FB31:4A LSR
' g6 p: S5 e& H! y7 QFB32:4A LSR
2 O# E; O# @% n' S- c2 E0 JFB33:8D 03 E0 STA $E003
8 z- I z, x9 O) p3 _( VFB36:A9 00 LDA #$00 P8 X- M' }; m" i( V
FB38:8D 00 90 STA $9000! t( z, b* ?. z# K5 k
FB3B:60 RTS
+ E! h: U+ }* |/ H* M% z! ^( T M& z+ o K
接下来修改切bank方式:
" j; ^" Z4 G0 I; W: h0 h$ kFB2B:48 PHA; l2 p6 K- W4 p3 s% V8 ]
FB2C:A9 06 LDA #$06$ V5 r3 k. G7 G7 ]; m* @
FB2E:8D 00 80 STA $8000+ u6 x: ]* Z3 o0 ]# ]8 s
FB31:68 PLA+ x. o7 v& J4 w9 |4 V5 ^3 U
FB32:8C 01 80 STY $8001
& r8 k; J5 N1 L2 C# E# dFB35:60 RTS" \3 L% i7 p* m! Q) S8 j
" s) U/ `4 j) M$ w7 U/ J# nFB36:48 PHA
% b2 a1 m% O/ { m' i. ^FB37:A9 07 LDA #$073 m& C& D& ~/ d5 b0 ?& U3 Z, V
FB39:8D 00 80 STA $8000 = #$147 A0 @7 h9 o& {/ j. e# y
FB3C:68 PLA
0 O) }+ |3 M. A% Y U/ w0 qFB3D:8C 01 80 STY $8001 = #$1D# T3 q( M3 t6 \
FB40:60 RTS
" h7 ?( X9 _2 ?: D
; F$ m) [( ?# l A- S. ^还要把原ROM的对$8000和$A000进行写入操作的程序修改一下:$ e7 K( w% |- b: U0 ?+ A
F989:AD 00 80 LDA $8000
8 S( c- ~+ B0 lF98C:8D EC 07 STA $07EC
, ]4 i; k1 L4 \+ }9 dF98F:20 2B FB JSR $FB2B
' k* T3 U7 L+ ^$ `" dF992:C8 INY9 i/ z5 P0 j1 B/ A
F993:20 36 FB JSR FB36& q* A( i6 [6 W. L1 |) ~: _. `( d# s
F996:60 RTS7 w! e% E( r, {
" w0 @0 W3 S1 f8 u再修改切VRAM程序:
7 M) ~5 E Z- b4 P7 g4 Q$ zFACE:A9 00 LDA #$00$ B) h- E8 D# n+ n- _
FAD0:8D 00 80 STA $8000
# d+ k5 ?! |! n* `FAD3:AD F0 07 LDA $07F0( S) E+ G Q" N6 b
FAD6:C9 01 CMP #$01
/ U. V' ?/ Q- \4 u! t- @9 P/ m6 ^FAD8:D0 11 BNE $FAEB2 Y6 x+ u) [/ _; a1 B
FADA:AD F1 07 LDA $07F12 n' v/ u9 X% @. c
FADD:C9 04 CMP #$04
5 M6 x8 w6 y0 N4 JFADF:D0 04 BNE $FAE5
' ^ E& n. K5 H& f1 a- HFAE1:A9 80 LDA #$80* ? \0 {- i' S
FAE3:D0 06 BNE $FAEB
5 G" F% k h. M. q+ Q- f: eFAE5:C9 05 CMP #$05% M# @( ^! a8 ]: e
FAE7:D0 02 BNE $FAEB
: j6 ^* q$ ^$ HFAE9:A9 82 LDA #$82
: G( q7 U) V R; I" KFAEB:8D 01 80 STA $80015 |' O, S7 U' l( c) m
FAEE:A9 01 LDA #$01# K$ M$ t& h8 u2 U' Z3 A% _8 O8 w
FAF0:8D 00 80 STA $80007 z- M# w0 ^( i. z
FAF3:AD F2 07 LDA $07F2& b! ~$ A# a6 a# {# O1 p* t
FAF6:8D 01 80 STA $80015 X1 W" X; [( Y: c# ~+ [. W) e
FAF9:A9 02 LDA #$026 ?4 @0 }3 G7 \0 @8 ~0 ~; I. _/ K" O
FAFB:8D 00 80 STA $80000 Q% @) c/ h% E& ?/ s7 j& O
FAFE:AD F4 07 LDA $07F4. {3 Q7 l' s, K" h0 S' r1 k; l
FB01:8D 01 80 STA $8001
) D4 g7 _+ z8 PFB04:A9 03 LDA #$031 G. Z6 H5 G( o
FB06:8D 00 80 STA $80003 o9 A0 F& C9 h/ |' H6 S7 Q
FB09:AD F5 07 LDA $07F5- l! K- M( i) `2 n ^/ z6 b5 R" z/ E
FB0C:8D 01 80 STA $8001
$ S- u9 L, q! UFB0F:A9 04 LDA #$041 s3 o# @ M" Z" w
FB11:8D 00 80 STA $8000
. ~ a9 z8 I+ P, S! R. f5 \FB14:AD F6 07 LDA $07F64 p' F; H6 W# a- n1 O! x
FB17:8D 01 80 STA $8001( A( N& P2 O6 U: f* z
FB1A:A9 05 LDA #$05
6 C4 u1 T) j% a/ J1 V+ P6 c6 @FB1C:8D 00 80 STA $8000' X# G! ~' l& q# B6 k( [0 l
FB1F:AD F7 07 LDA $07F7 k: W6 A( ~- L7 N$ I7 w
FB22:8D 01 80 STA $8001! e3 |2 t6 Y4 ^( {2 {6 c
FB25:A9 00 LDA #$00. d! u+ }- R: T+ c+ v
FB27:8D 00 A0 STA $A000
& ^4 g$ I, t, {* e8 E+ H- q- ?5 bFB2A:60 RTS
. I; n3 S) I5 z/ f6 \. P
D& `# w3 |4 B: ]) y然后保存文件。6 U) R) r% ~0 [) C1 m: I
使用HXD修改文件头:
l [) L8 ?- Y7 Q8 N, P将Mapper 23$ L0 U7 O# C% b9 I$ ]( K! N
06字节的高4位是Mapper号的低4位
- z% y5 I b* @# X07字节的高4位是Mapper号的高4位8 b) p0 O- V' j8 g" k/ `
组合起来就是0x17=1*16+7=23 R' @; B* ]6 s; D* K& @/ ?

8 l7 P+ v, t9 q9 y; K Z修改成 Mapper 4
1 ~1 K* e' m, O
4 f0 K* _; V- u3 |+ L# H, k" M9 e/ {0 m2 x" Y
6 }2 Y' P; {+ i再次打开文件:
( A' T9 X( I2 ] - \4 g2 H8 s2 \
可以正常运行
0 e* S, n! j4 A3 _' L7 b通过全面测试,发现出现精灵错乱:) p* K5 i3 W" {- t/ X
第1关:
3 `4 B3 q' P6 {! h
6 z/ r+ U. |' Z5 q
$ M& h1 X/ j- v' b第2关:$ W: Q2 `" e2 C0 }( h

# _4 p8 O- u. J. d o任务失败后:* N( Y5 Q& L8 `* S
' Y B Z) U: s: i9 K( ?4 n
通关后上飞机画面:
0 i) N1 X& m* k' |1 t. h % x, ?: l. O) Y& [3 F
这是为何呢?
$ p+ r# c( R$ B' D5 L这是因为Mapper 23 中精灵VRAM切bank是一次切1KB) t3 g5 J r9 b4 v/ `
但是在Mapper 4中精灵VRAM切换却是一次切2KB,而且忽略bank号的D0位
* L F: j& R9 B; H* t& b' ~; e' Z比方bank 0和bank 1是同一个bank,同理bank 2和bank 3是同一个bank
" o R( C8 ~ e$ q* _+ c6 u( r也就是说
* m% {9 H" F/ E2 F2 nMapper 23中的VRAM的
7 D: i: A0 c# Q5 |* K1 gbank 0,bank 1,bank 2,bank 35 T R/ V7 m' y
在Mapper 4中对应的是9 m# G1 G4 Z2 w, n
Bank 0,bank 0,bank 2, bank2
1 X/ a! C. C) S) z0 u9 R& n) H+ o/ r然后查找原来的ROM的切VRAM的程序:
. d3 r+ P, t& D: w8 D l# q7 v知道是从07F0-07F3切到精灵VRAM的:3 ]% }& l C+ D F6 Y
如图所示:
4 q' h8 K% z5 q3 N- |
( P* M3 r. Z5 p8 t& u' m% U1 T 8 t% c7 m9 ~9 E+ k. L
作为对比,左边是原版,右边是修改。
, n! o' _% d% c接下来是完善VRAM切换带来的问题,因为Mapper 4只能切2KB的bank,所以我们不能通过切bank程序解决问题。
; T: C1 W) X" D \通过测试知道1,3,5,6,7,8关的精灵VRAM排序如下(07F0-07F3):2 f" v! m/ y( a1 D' p& D' ~/ j0 W
01 04 06 07) N+ n* x+ A* y" E A
第2,4关如下:. T6 g# h* S" j* b. s* {
01 05 08 09
# I; t7 v$ O \4 \任务失败时如下:1 ]7 d S1 E5 @/ A X+ Q4 P6 l
32 00 00 1B% A( B8 F" k) f( v& S, K
其中任务失败时对应的VRAM是07F3的1B,只要让07F2为1A或1B即可:
/ d6 T+ `7 ]9 p. Y通过调试找到对07F2写入数据#$00时程序如下,于是修改C7E5的值为1A即可:
( l5 c; M. V+ M* D # `. ^0 ?* ?8 i( |- {. y0 ^8 u4 T
转到ROM地址:
* H7 q& o# p4 t, e7 C7 z0 z
1 r# V% P5 G% |# D) C4 J修改数据:
0 c0 ~! ]+ o3 Y- G* u : ?5 N! o) U" V K, j* p; a( R: @
重新失败后可以看到修复成功:
4 B- A5 u. f7 Y/ A" T* ]
: f- \* |7 l5 L接下来是修复正常进行任务时的精灵错乱问题。+ ?# [5 g4 [# m5 |) D
首先运行Mapper 23版本,在1,3,5,6,7,8关任意一关的时候,将PPU导出来* `7 ^$ [0 D8 @6 W1 H0 s

( c& f% z+ y0 }7 r
' l C! E, ~. w2 G& j9 v5 h " h# o$ V- X) ^' s* b. }6 l
3 Q* y4 ]& Y9 z" o
然后用Hxd打开修改的Mapper 4的ROM和刚刚保存的PPU的数据文件:
, p: Q# `4 }+ o( {1 ?9 J# b$ b
& U- M& t, A& C7 k3 X4 j: b) c在ROM文件头第05字节改为0x20:2 q. X4 O0 m$ w! L3 {( R! \
/ [4 k8 O$ }# _8 ?
然后转到文件末尾,插入0x20000字节空字节:
* v0 N; K$ t. H6 w0 z+ F6 P. }4 }$ w1 d - C- c( }- ?* t$ r/ V; d' c0 `, i
@3 t& |' a8 ~* j9 a2 a
$ \+ c% a1 h! E' R' m5 [0 Y
8 n1 S' d/ X0 `9 M3 m
然后将第1关的PPU数据的前面2KB数据选定:
) a1 B$ [3 q& Q o* J ) ^) t* m+ `$ D3 D' O& H, |
9 W4 d1 m+ R! ?1 r

+ Z$ \7 Y" e7 I; \2 o b! i$ Y复制之后以覆盖方式粘贴到ROM的40010,同样把第2关的PPU数据的前面2KB以覆盖方式粘贴到ROM的40810
; l9 W% l0 P0 ^# C
8 N3 @* \0 A; [% v( {) ^然后保存文件:6 J6 k4 ^* R% S1 k

5 ?$ O+ b+ J8 S. S- e最后用FCEUX打开文件,添加07F0-07F3的写入断点, }( U& v! [" g
; o4 \- k/ v' q. @
地图预览后即将进入第一关画面时程序暂停了,可以知道此时准备将C793的数据写到07F0:9 t; W! j* V) h3 Y' c
- n- f3 |' T5 F) P% m
测试后知道将C793-0796写入到了07F0-07F3:4 i% ` p. ^+ Y. y
同理,经测试每4个字节一组,一共17组,其中01 04对应普通关卡精灵以及其BOSS关的精灵VRAM的bank号,01 05对应2,4关卡精灵以及其BOSS关的精灵VRAM的bank号,再加上一个通关后跳上飞机那段动画的精灵VRAM的bank号。- s1 F, i1 Z" f! p/ U
- p6 T7 n4 {5 o/ P+ H+ r
5 r: U: p$ x( U* g- u
然后将文件中标记的01 04修改为 80 04,将01 05 修改为82 04即可: b6 l4 _1 B2 e2 g: S& ~
! [9 w/ m3 C3 f' A" e7 Q! x0 G
保存之后重新运行后效果如下:
! K/ j) n0 S, {5 J) m8 u0 u7 }
% R2 L2 s# s' g: \" Y: ^ * P% Z2 a% D8 | R0 A" _" f% E: ~
, q& W* H P0 l( {# D
当前使用的是FCEUX模拟器,如果用NEStopia玩的话一开始就死机了,这是因为这个ROM有文件保护吧,它会往$6000里写入数据:2 H" ]! v8 ` }4 J u2 J

' w, {* G( `' `$ W4 BF863:A0 03 LDY #$03
+ p6 P0 h0 a; G; q: W5 {F865:98 TYA# r! D( @0 e8 q O9 ?5 s8 ?
F866:29 01 AND #$012 G" K. q% h6 p& k" u5 C
F868:8D E9 07 STA $07E9
" Q: c) i& O# e- t* [; }F86B:8D 00 60 STA $60004 `5 C- c7 y& [) ^ v
F86E:AD 00 60 LDA $6000
. \; B- u, U1 k1 c/ S* z7 y+ eF871:29 01 AND #$010 t2 ^5 \' i! y+ r9 r) w ?4 q
F873:CD E9 07 CMP $07E9% A3 j g4 V4 K: A/ p( y2 w. G
F876:D0 05 BNE $F87D
9 R' w1 g9 B) Z( q0 m+ F0 MF878:88 DEY
: T7 j9 v0 k5 M6 _- K$ h3 Y# x0 `$ ^F879:10 EA BPL $F865
- @6 B/ o0 W8 D2 C- @7 P# bF87B:30 03 BMI $F880
T/ J& W* a9 l& bF87D:4C 00 00 JMP $0000
1 V! n+ T2 K( \" m; Q$ J LF880:A5 1A LDA $001A$ p. _8 O P$ U
F882:65 34 ADC $0034
, P( `) y/ P1 M7 h3 z6 aF884:85 34 STA $0034
* i' j+ K/ k8 m; X' t0 w0 RF886:4C 80 F8 JMP $F880
9 O. a* `% F& ~# d' X9 f$ X. R先取Y值=#$03
* ~) u D. f7 K- y) M与#$01相与后得到#$01
1 }! d, t2 J( m% J* a写入到$07E9
+ X" ~+ H% l- G9 ?/ C( I写入到$6000
& G8 D4 Z4 r! n) w0 ~0 p0 R6 D* n再读取$6000的数据和#$01相与后和$07E9的数据比较& v8 v. S% u5 B6 z1 F
不同的话跳过5字节5 Y- j, S9 g1 F9 H1 C7 ^$ t5 S O8 h' ]
否则Y递减/ c+ y! g Y" x
为正数就跳回0x100-0xEA=16字节! j) V& w! J( t5 `. c
为负数就跳过0x3字节/ Z' T0 k6 ] s9 Z
跳转到$0000(简直没有人性了,跳到这里死机,真想得出来)/ X* v% d. o# t7 L7 z, R: X- G7 \% n' _
9 k2 }7 w& |: c+ M# {
正是因为这样,NEStopia运行FC时,6000-7FFF默认是不可写的,必须在ROM文件头第6字节的D1位置1设置ROM有SRAM,对于Mapper 4,还需要向$A001写入#$80来启用SRAM。: v% O& ~; z' A/ \3 n
由于$6000不可写,因此想$6000写入#$01后$6000还是#$00,之后读取$07E9的#$01与之相比当然不同了,于是直接跳转到死机程序了。
9 ?& D% ]6 \! M3 E5 n0 J3 R( x W解决方法是把ROM中的所有的AD 00 60 29 01 CD E9 07 D0 05 88 10 EA 30 03 4C 00 00
( L% O9 `" j0 q6 z中的D0 05改为D0 00,然后保存即可。
' g7 y7 o1 H8 H- Y) x& o测试完美运行。0 s8 V9 B" A0 T; ^& _

, N- e" N3 W- i& c3 U+ i: R$ o7 h) b1 P
4 r$ Q; m4 Z0 H" P4 b教程到此结束。- Q5 A; T" n! v- z0 ^* J
# e8 j: j% ?+ v/ L6 ?( [* k+ j6 r3 k |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|