|
本帖最后由 yandagui 于 2017-4-16 19:06 编辑 , P+ P' L. i, A4 D! y, b
' v: U9 B# z" z7 R" B0 l% l4 DMapper23转Mapper4实例教程4 s& k, j( I5 S
0 K. s. Y L+ x$ ?8 N6 T
FlameCyclone 2017.4.14$ l5 u, F" D* `8 L( P
/ l2 t' k: V7 v( B; i0 U
先看看Mapper23文档:6 T9 Z! Z5 h. e
' b' A) [1 `& h" _( i( v
Mapper 23
) ^: R5 f0 d1 Y; ?/ ] j' L+ Z
$ S& J1 S, V" S! @+ s- _+ h$8000: 选择8KB的ROM存储体映射到$8000
" r- [1 L }, z' Y) c+ b& V: b
* e; _, g s8 u Q$9000: 0:垂直镜像
) M0 H# ?9 C: v( A: L4 _3 Q 1:水平镜像; P2 T$ I* G; s! p
2:$2400镜像
6 {) _( z2 x" G9 H+ ^ 3:$2000镜像9 H1 P! \1 c/ y. c2 U0 I, E3 h
`" B4 _) V5 \8 u/ o6 ^
$A000: 选择8KB的ROM存储体映射到$A000$ y2 ?' h) T M. ~' O3 T
2 s& T0 y2 `4 O7 H7 n
$B000: 选择1KB的VROM存储体映射到PPU的$0000(低4位)9 m' J8 [6 J/ n7 x
$B001: 选择1KB的VROM存储体映射到PPU的$0000(高4位)
1 l3 \* [, ?: v# M8 p$B002: 选择1KB的VROM存储体映射到PPU的$0400(低4位)
% U0 f4 O* Y8 g5 y7 f/ N) s$B003: 选择1KB的VROM存储体映射到PPU的$0400(高4位)
; R* v$ W8 ?6 q
/ q. n# e1 T6 P; z* n; P$C000: 选择1KB的VROM存储体映射到PPU的$0800(低4位)
% e1 C% P( d6 ]& N$C001: 选择1KB的VROM存储体映射到PPU的$0800(高4位)
& v1 I1 U d4 P: |, r7 `$C002: 选择1KB的VROM存储体映射到PPU的$0C00(低4位)
; k1 |, w6 b! O$C003: 选择1KB的VROM存储体映射到PPU的$0C00(高4位)
6 b3 E a8 L7 O$ _
% j% S! I* n4 j v; ^* b( Y. \7 x5 s$D000: 选择1KB的VROM存储体映射到PPU的$1000(低4位)
! d0 O) M9 x! Z( K$D001: 选择1KB的VROM存储体映射到PPU的$1000(高4位)8 b2 Y' z6 K! _. O3 X {
$D002: 选择1KB的VROM存储体映射到PPU的$1400(低4位)
6 L7 x3 d/ Q) J$ q$D003: 选择1KB的VROM存储体映射到PPU的$1400(高4位)
! \6 Q- j& z3 p5 C. J1 _, q: _/ G
/ `* _0 y2 q" {9 J$E000: 选择1KB的VROM存储体映射到PPU的$1800(低4位)) j& H7 P$ b! i4 b' n/ |
$E001: 选择1KB的VROM存储体映射到PPU的$1800(高4位)
9 A. K# }. H; E& H8 i+ j) U! Q$E002: 选择1KB的VROM存储体映射到PPU的$1C00(低4位)
}6 N7 Q* ? \% H- c1 S0 F# z$E003: 选择1KB的VROM存储体映射到PPU的$1C00(高4位)
& N% z" D$ F% j% b. Q
4 I$ p. c- N4 p1 z: S/ U/ d再看看Mapper 4文档:3 j# R$ V2 D9 o! {8 F5 Q4 B f
# [! H! R1 y) n UMapper 4
( F/ K7 L' ^7 w& R& f( b2 F/ ?4 U4 o: M7 i1 ^! l) O( C0 d4 Z- q. J
$8000: 模式号
9 ?5 F* u. `/ |4 R 位D0-D2:
' ~4 ^- M4 @. T* M) X7 i; \ Q, V: r 0:选择2KB的VROM存储体映射到PPU的$00007 B& @ L4 e, d/ }
1:选择2KB的VROM存储体映射到PPU的$0800, P2 G0 n/ P; R) l8 L$ B
2:选择1KB的VROM存储体映射到PPU的$1000: X; R0 d$ H0 a2 w5 g$ o* Y
3:选择1KB的VROM存储体映射到PPU的$14009 _0 L% A+ T8 Q2 E: ^
4:选择1KB的VROM存储体映射到PPU的$1800% b- Z7 R( `0 V0 _# S0 X1 e2 k9 L
5:选择1KB的VROM存储体映射到PPU的$1C003 G8 E+ r2 m0 T, E) ]/ L- y
6:选择8KB的ROM存储体映射到$8000# }, T" K+ j9 U+ B
7:选择8KB的ROM存储体映射到$A0002 n: W$ X/ a) E8 [, P
位D6:
. j7 r- o; F( |; i9 J 0:允许擦写$8000和$A000
& w6 v( W3 j- p6 V% j* O9 X/ Y 1:允许擦写$A000和$C000+ e {8 s: V" z4 R F- t7 N
位D7:
9 u0 K' e0 h8 |, t( p 0:模式号D0-D2使用普通地址1 `3 r) A5 H: b+ ?/ p
1:模式号D0-D2地址异或$1000
% R- h& G+ W" i. L
% f; j( C+ n6 [# Z$8001: 模式页面号 l8 A; e- F" r" w
写入一个数(00-07),切换存储体到对应地址0 u q4 Q. `& L
4 ^- Q/ s! J7 w. s
$A000: 镜像选择
' }& M J# g$ T; q; R3 c 0:垂直镜像% [! J P+ V2 C4 |, A
1:水平镜像9 V4 Q2 A: k" K1 e
. t1 {& ?' u+ [( @! i" Q6 z
$A001: SaveRAM 切换8 f0 K8 I: i6 O; J
0:禁用$6000-$7FFF
. s4 [' A8 L0 _: D# d# Q' L4 { 1:启用$6000-$7FFF& a- F& d/ f$ J4 x$ g) Y& D
* M. H: I4 x7 P# T2 @, p! q
$C000: IRQ计数器
1 u0 V# a& {/ c1 l/ L IRQ计数器的值存储在此处# w1 G8 l8 p) k+ O# E
2 D* B+ q$ R0 Y% [: p$C001: IRQ暂存器
6 U8 p. l5 m8 a IRQ暂存器的值存储在此处
0 f: y6 U" u9 I6 W0 Z8 t" y- V9 b7 b4 l2 F V4 @0 G3 Q
$E000: IRQ控制计数器0" D7 o! G; L3 q8 J: H1 l8 C8 s0 U
向这里写入任何数来关闭IRQ,并从暂存器中拷贝数据开始计数,进入IRQ9 l& M$ l3 }# R z( n4 k, H# B8 c
: q8 o" D: t$ l8 f. K
$E001: IRQ控制计数器1
B' y4 _" }0 n% y u# p" s1 a5 j8 E: i 向这里写入任何数,允许IRQ(退出IRQ,允许下一个IRQ进来), s( @- q1 R: W! C5 I& w# N
( q; x2 `# V1 a; X/ F! y3 {1 W
4 m/ q1 [( a4 K: R转换思路:$ I: V$ z0 ^' U0 g0 ]9 S5 X
将Mapper 23 的切bank 方式和切VRAM的方式修改成Mapper 4 的方式。
5 X* r! _* o0 w! K' G( j5 k( H. A9 N8 Z6 k3 c+ T, _% |
修改实例:
3 i! o& r# p" w! U2 D; c+ TContra (J) 256KB Mapper 236 W: j6 j! g. \& Q+ q
工具:: f4 ~( Q! T$ C! M
1.FCEUX 2。2。3( n5 P% t; ~4 |# Z6 ~8 U, Z0 w% t4 M$ G* t
2.HXD9 \! N+ t" o t
先来看看这ROM的切bank方式:& j. z; A% Q- W3 d h% I9 h
F989:AD 00 80 LDA $8000 " ^2 B/ z. K3 U4 z" a t
F98C:8D EC 07 STA $07EC" g2 g4 B5 L5 I7 A+ k, Z
F98F:8C 00 80 STY $8000
1 Y0 P8 Y( ~: s- r1 EF992:C8 INY. ~: T4 _9 q: Y8 l; K1 T
F993:8C 00 A0 STY $A000
- q* j) F9 d. k% H1 r6 ` qF996:60 RTS* T" u1 M+ H6 I
0 v1 \/ w, }% Q% u) r
再看看它的切VRAM方式:7 m7 @# i1 R7 F( t# u# N+ @+ A
FACE:AD F0 07 LDA $07F06 i: w/ a/ N$ n! G o
FAD1:8D 00 B0 STA $B000" W! y' Q- ^$ [% O
FAD4:4A LSR$ _+ R7 I" Z% h9 @! K
FAD5:4A LSR8 M8 a$ n" O+ m m# e% W1 S
FAD6:4A LSR
: E, \7 ~4 Z. Y- z CFAD7:4A LSR9 A8 H4 j! [, U
FAD8:8D 01 B0 STA $B001
; W3 e1 k0 ]* H ]3 G; S! sFADB:AD F1 07 LDA $07F16 V. t; S8 S6 I
FADE:8D 02 B0 STA $B002
9 \# O% h) K+ oFAE1:4A LSR: S3 |% m+ o0 f4 N/ \8 a# }
FAE2:4A LSR
1 b; P5 @, ^# Z& j3 I: [4 W" `FAE3:4A LSR
& j, w ?. v& m; XFAE4:4A LSR# D g& U7 J2 D6 T( u1 A
FAE5:8D 03 B0 STA $B0034 W, ^0 e9 d' _
FAE8:AD F2 07 LDA $07F2
; D3 k1 t9 V, H( s MFAEB:8D 00 C0 STA $C000- |* ?" @& ` z* C* `
FAEE:4A LSR
+ x3 G6 S+ h; Z& D% E0 gFAEF:4A LSR1 A$ l; k) N2 B2 a
FAF0:4A LSR0 G- P* O) J/ ^7 b- X
FAF1:4A LSR7 L ]& n3 z8 q8 G- Y/ P! j4 F
FAF2:8D 01 C0 STA $C001! V# y3 |2 s9 x
FAF5:AD F3 07 LDA $07F3% _+ I- u7 b& G5 F
FAF8:8D 02 C0 STA $C002
a1 K9 w H4 x* M0 hFAFB:4A LSR
! ?: t# c# d4 n6 _/ r$ j; F3 L6 MFAFC:4A LSR
7 m0 e' N8 I3 C ^) L7 w/ v3 ?FAFD:4A LSR# G9 h- Q0 O/ m/ U. a: T4 X( n
FAFE:4A LSR/ G9 H, Y$ T: o1 G
FAFF:8D 03 C0 STA $C003+ l. a# x3 r3 E3 X. \5 D! W, O
FB02:AD F4 07 LDA $07F4! l4 t& d% b7 O
FB05:8D 00 D0 STA $D0003 \, Z0 ]6 H+ \- h8 D1 r
FB08:4A LSR
0 t. e c0 Y7 i- \9 NFB09:4A LSR2 Z9 W j) a9 [4 `& s. {+ {
FB0A:4A LSR1 r" x1 V+ p' v8 k
FB0B:4A LSR
, S4 K( H% n1 k; K" [1 ?! E/ KFB0C:8D 01 D0 STA $D001; N2 W: }4 X6 b4 N
FB0F:AD F5 07 LDA $07F5! m4 ?2 `1 J: S$ H
FB12:8D 02 D0 STA $D002
s" m+ w6 o$ J |4 i, j+ t( [FB15:4A LSR
& z# ^" m* J. c* b$ l2 k5 [FB16:4A LSR( |: I& i! E) N3 p8 J- x' c
FB17:4A LSR
* q: R- Q- v9 K4 ?& I3 f" b, R) }3 U9 \FB18:4A LSR% ]1 C1 y8 [" O8 B
FB19:8D 03 D0 STA $D003
' T- j3 Q* s& @4 dFB1C:AD F6 07 LDA $07F6" M* s6 Y/ T/ k9 d2 u- K% ]. _
FB1F:8D 00 E0 STA $E000
' H: G' l" D2 K. bFB22:4A LSR
1 R4 h- C: v' _" |/ k: M& P3 `+ ~" {FB23:4A LSR" g) f M: b4 O1 ]- @
FB24:4A LSR
0 v. M" `7 t* u1 rFB25:4A LSR- X1 F L# V( d5 U$ }
FB26:8D 01 E0 STA $E001- S( `$ }' _5 Y! R2 f
FB29:AD F7 07 LDA $07F7) E7 H I* F% K- b8 M; r
FB2C:8D 02 E0 STA $E002
( C9 Z3 V& x5 c# hFB2F:4A LSR
0 j; X& p( V% q JFB30:4A LSR
$ e: R& ~9 B6 i* EFB31:4A LSR
' l( y2 q5 p, @7 zFB32:4A LSR4 d5 W4 g Q" j9 h( o
FB33:8D 03 E0 STA $E003
Q8 k( U/ D ?7 \& [& NFB36:A9 00 LDA #$00
# V) ?( z A9 LFB38:8D 00 90 STA $90001 D6 v% F& H H6 D
FB3B:60 RTS6 E8 W7 L' A# M1 c" I
0 F( B2 e8 j/ P3 d7 P0 F
接下来修改切bank方式:5 k% t8 G) `3 n) D6 ^( _9 ?
FB2B:48 PHA
7 P" _: {& K* j; RFB2C:A9 06 LDA #$06% t9 \* N9 X1 H3 ^* c6 l
FB2E:8D 00 80 STA $8000
# X0 z1 w: h4 N3 A$ p& k+ ]# kFB31:68 PLA) k g( X3 V/ K" |! B: Z3 r _
FB32:8C 01 80 STY $8001
) E. F* u3 s2 I/ y, U* _* CFB35:60 RTS
# I- R$ j& K, j# f% f5 S
1 p. {7 U5 G1 S' b5 h. G" ?FB36:48 PHA, V6 e; ]8 C: M
FB37:A9 07 LDA #$07
0 B$ S: s( C) Z, G3 }' S: I+ KFB39:8D 00 80 STA $8000 = #$14
$ P$ u, h/ v) Z) E- u2 J+ HFB3C:68 PLA& P/ k. o, `! n/ r9 b
FB3D:8C 01 80 STY $8001 = #$1D- X! _- ]- z2 s3 z
FB40:60 RTS
7 [ g+ Q' }% e# T( W6 X
7 L5 j# R' |+ P" r& g+ Q) @2 _, O6 p还要把原ROM的对$8000和$A000进行写入操作的程序修改一下:
" O6 P# A2 ^+ `$ b+ hF989:AD 00 80 LDA $8000
: q* t/ S0 \3 z5 `" O- y7 _$ W7 UF98C:8D EC 07 STA $07EC
4 z+ c' y7 L% e6 Y0 l( hF98F:20 2B FB JSR $FB2B
5 ^: j/ @. [% M+ u, @3 vF992:C8 INY" f! t! b% I( u& @0 i+ Y7 C% i9 p
F993:20 36 FB JSR FB36
6 O2 P. L/ S! W. ~5 h+ m9 EF996:60 RTS
5 p# P! F( `' ?; z7 [4 b/ W% `$ x b4 g1 b$ m
再修改切VRAM程序:2 x$ ~% `4 ^( `, \0 B# P2 w
FACE:A9 00 LDA #$00
7 i5 L! d# k+ H4 D. z. q e: \" sFAD0:8D 00 80 STA $8000 \# d6 v0 @4 G, S6 f
FAD3:AD F0 07 LDA $07F0
! g, U1 p! o$ O2 X. Z" D1 `1 [FAD6:C9 01 CMP #$01
4 r2 _2 g$ n: b$ E& ^FAD8:D0 11 BNE $FAEB
: [% {2 j! [# F4 M. Z( ZFADA:AD F1 07 LDA $07F1, U0 s- l, V8 B6 }
FADD:C9 04 CMP #$04
3 C3 I6 v1 U% q; {; P4 BFADF:D0 04 BNE $FAE5
% q& ? k+ S( C/ K- pFAE1:A9 80 LDA #$80
; w9 j* ?+ w* X' h9 X3 i2 D* @1 EFAE3:D0 06 BNE $FAEB) F3 i$ i# Q& _5 Z* Z
FAE5:C9 05 CMP #$05
/ b1 b7 E* z4 Z- L6 e* Q2 tFAE7:D0 02 BNE $FAEB
) E( X8 F8 R0 R" x& hFAE9:A9 82 LDA #$821 w) L& A$ \. c7 m, W
FAEB:8D 01 80 STA $8001" Z H9 a! q- i& m
FAEE:A9 01 LDA #$01
4 F$ j$ E, F3 _0 H9 DFAF0:8D 00 80 STA $8000- `. ^; H6 e/ s3 `9 o& C6 i
FAF3:AD F2 07 LDA $07F2
+ f- B3 s3 O! H4 o2 X5 r% ^) TFAF6:8D 01 80 STA $80019 O% D9 Y' R/ x
FAF9:A9 02 LDA #$02. {! V0 {* W* [! @% S+ p3 [1 N
FAFB:8D 00 80 STA $8000+ s/ T( Q" l2 J
FAFE:AD F4 07 LDA $07F4; p" S" `( w" r
FB01:8D 01 80 STA $8001
/ N8 c3 y& q. C! d) @5 i3 Q6 N/ o, MFB04:A9 03 LDA #$03$ V4 V% ~7 K. z/ Y2 c% G
FB06:8D 00 80 STA $8000: X* m4 z2 G) U& a+ k6 B- i9 C
FB09:AD F5 07 LDA $07F59 c0 R8 ?3 P1 W2 _9 z- }& C
FB0C:8D 01 80 STA $8001
: X* X& U A# e( t3 s; K& Q y# rFB0F:A9 04 LDA #$04
2 q: ]+ {. Y) s: t9 g5 XFB11:8D 00 80 STA $8000
6 t- e# i$ `0 J: YFB14:AD F6 07 LDA $07F67 V) V6 Q" g; E( O
FB17:8D 01 80 STA $8001. Q, p" U( l- Z0 c
FB1A:A9 05 LDA #$05
1 F" |" f) ?+ K% {7 r, Q8 {6 MFB1C:8D 00 80 STA $8000
# O2 E3 P2 t: m( t+ r9 XFB1F:AD F7 07 LDA $07F79 d ?7 f; C. W+ z: M6 m' J$ b% r/ h
FB22:8D 01 80 STA $8001* s* B) B" u1 H" `" }; c# A+ _
FB25:A9 00 LDA #$00
. J/ z( c e: ~5 k" k9 Q' xFB27:8D 00 A0 STA $A000. k1 K" @& }) y8 j$ A+ c
FB2A:60 RTS
& |- D0 t7 {5 ~% l! k( Z, b4 V7 ~; v" ~& k2 W
然后保存文件。
$ y; b) G4 }$ ]. I( b0 Q9 ]使用HXD修改文件头:% J" G+ P: j4 T2 s
将Mapper 23
4 D3 ]4 p8 _4 S; t) I" }( q( u8 y0 ]06字节的高4位是Mapper号的低4位
! I) w8 v f, U* i/ a3 p% t07字节的高4位是Mapper号的高4位% n2 h7 t0 T; O7 v% U2 e5 ~$ x
组合起来就是0x17=1*16+7=23- N2 _6 ?& Y5 \$ S1 y( Q. ]
( n' B* ?! M3 v5 o: b修改成 Mapper 4
* D+ \8 p* \ ?' z, H5 G9 _9 U& G7 e
: u1 d9 N+ x+ X1 R
, h1 x4 r0 ^4 u' I/ s; ?1 H再次打开文件:
) W# b- E3 e. Z2 g d, m" X2 z: R4 ?+ w$ G6 ]" _5 g
可以正常运行$ h9 V( p' v+ p) @
通过全面测试,发现出现精灵错乱:5 `5 J" S. c1 z
第1关:5 M/ ]' ?( T! r2 R- R* \
! h6 c1 C' l$ s; {3 _
: I2 {+ F; S! n: O: m
第2关:
8 c: ~6 W, Z3 y; O8 V
1 ^" @4 s* T* k2 N9 H/ {) q. }任务失败后:
$ j3 t" Q4 \5 s7 w7 K" S( @% z/ a) L# y+ W; r
通关后上飞机画面:
% w3 d c2 p0 N2 x" w' l3 l1 v3 U O( g& o
这是为何呢?4 }6 x) `3 m C& z* D; C7 ~4 K
这是因为Mapper 23 中精灵VRAM切bank是一次切1KB% | D) y+ P' O
但是在Mapper 4中精灵VRAM切换却是一次切2KB,而且忽略bank号的D0位
9 G- F. K( G% ^比方bank 0和bank 1是同一个bank,同理bank 2和bank 3是同一个bank/ w# x7 n) z$ |( j5 ^8 m
也就是说
+ a3 \0 A ^2 ~2 D; RMapper 23中的VRAM的; n7 m0 b+ b$ |+ x/ f" @& j
bank 0,bank 1,bank 2,bank 31 Q% c# E% B3 w9 K4 Y3 Z- R! S5 l
在Mapper 4中对应的是
: D& @0 Q# Y4 V6 ?8 B- ~Bank 0,bank 0,bank 2, bank29 a# K- }) W! i' h' B; W& u% ~
然后查找原来的ROM的切VRAM的程序:$ J& Q2 E6 T/ l# j' B5 f( N7 S0 G
知道是从07F0-07F3切到精灵VRAM的:
& y' ~& @" V e" ]; W& ^如图所示:
' U* t1 v6 T, h( J T+ k, S( `3 `
4 v/ w# |$ N4 w4 X! h/ y作为对比,左边是原版,右边是修改。4 e5 k% P9 F) v6 `) r/ D6 G6 g1 V
接下来是完善VRAM切换带来的问题,因为Mapper 4只能切2KB的bank,所以我们不能通过切bank程序解决问题。
/ ?1 e# d0 j0 P- J8 R/ K通过测试知道1,3,5,6,7,8关的精灵VRAM排序如下(07F0-07F3):
5 `+ V; M2 `; |% W, R; @01 04 06 07
5 P: p; r5 z5 B( u) X$ a) ?% w4 h8 V第2,4关如下:- T# p1 H+ C; m! Z
01 05 08 09* n. C! ~& v6 _$ a
任务失败时如下:0 {0 A8 e( ^- Y" {1 s
32 00 00 1B- D% f" _0 b) d" ?
其中任务失败时对应的VRAM是07F3的1B,只要让07F2为1A或1B即可:
, C' a) H3 G. l. q通过调试找到对07F2写入数据#$00时程序如下,于是修改C7E5的值为1A即可:
# J$ l. r' H0 E% @% ^% r9 d2 u( b% E1 z$ c
转到ROM地址: S$ r, u L2 d7 I* m
. Q; A; X1 V% G! z7 u修改数据:
1 I9 {& l9 v& ~7 \9 n, Q
- ~; H5 F% W9 k0 q' z. f- _重新失败后可以看到修复成功:" ~( r/ ^4 D* }8 s, H
1 N: B( `, X$ Z. W6 H
接下来是修复正常进行任务时的精灵错乱问题。
4 W# `! ~ k( c# w9 C首先运行Mapper 23版本,在1,3,5,6,7,8关任意一关的时候,将PPU导出来2 r; h. W) x5 W6 v5 c. l
% c; Q# J/ `9 a) @( {: a' z. x/ _4 X7 t
& m& f4 i$ H/ `# Y7 j: _
5 N/ c7 D, O1 t+ l然后用Hxd打开修改的Mapper 4的ROM和刚刚保存的PPU的数据文件:4 y% i% j) ^0 X
i4 Y$ @) [+ X' X5 V
在ROM文件头第05字节改为0x20:
3 Y) U9 h' A3 i; A8 y& T. h% |7 |, u, |% L; p v
然后转到文件末尾,插入0x20000字节空字节:) P$ k; E, ~; k% ]. Y
~& f; j; t6 H. C. A' z; O0 |
) @. B9 C2 v' x) @4 u7 Z& |/ \) f
0 ]6 L* q4 d5 M
( y6 r" R1 T3 A( p' Q
然后将第1关的PPU数据的前面2KB数据选定:6 G+ A+ j# V+ E/ l
! P: R& _- C- U/ C7 I, N5 F
3 C* A Z+ |' r4 D
" b4 H9 h D% e1 i8 Z1 J复制之后以覆盖方式粘贴到ROM的40010,同样把第2关的PPU数据的前面2KB以覆盖方式粘贴到ROM的40810
4 y Z' S( v- ~& q& S& U
" Y+ v! ]6 {$ Y }然后保存文件:
/ ]! D# r9 e$ S4 p( |
* }0 w) F l, s) L+ S: q7 i最后用FCEUX打开文件,添加07F0-07F3的写入断点) R! p0 j9 L0 j1 o' o& d4 E8 o
+ d0 ^& R* [( D. @地图预览后即将进入第一关画面时程序暂停了,可以知道此时准备将C793的数据写到07F0:
% g8 Q8 I! F% q& J0 b, Y2 n" ^" g3 D$ \% T( ?8 B+ C; u f+ r
测试后知道将C793-0796写入到了07F0-07F3:4 K" K8 q0 q u" o; \* x; ?
同理,经测试每4个字节一组,一共17组,其中01 04对应普通关卡精灵以及其BOSS关的精灵VRAM的bank号,01 05对应2,4关卡精灵以及其BOSS关的精灵VRAM的bank号,再加上一个通关后跳上飞机那段动画的精灵VRAM的bank号。7 d, k; Y z+ c0 s# S6 j4 M$ F4 f
% f( [* N8 z; h6 M
! c/ o& C3 C/ y6 Z" i1 L2 o然后将文件中标记的01 04修改为 80 04,将01 05 修改为82 04即可:
4 q- q% V% w% ~7 N* s
2 r8 l0 I5 p: G保存之后重新运行后效果如下:9 u) Q. d1 g) Q, N# w8 @2 ~
8 m2 A# p: D7 Y" j8 m! x3 [8 w% ?( ^2 }
4 ]4 \0 I+ V; z7 f0 o1 s. [当前使用的是FCEUX模拟器,如果用NEStopia玩的话一开始就死机了,这是因为这个ROM有文件保护吧,它会往$6000里写入数据:
1 a' W" v9 c# z( l5 f; I2 m
- ]" ~0 X( x1 `) zF863:A0 03 LDY #$035 a. v) D8 z4 n
F865:98 TYA
+ f& {% R# ` z/ g }7 S+ uF866:29 01 AND #$01( Y: f/ s6 d* F% ]' w
F868:8D E9 07 STA $07E9
3 q4 J0 p! s- {$ S: l T+ jF86B:8D 00 60 STA $6000+ L" A* `5 W6 Y" g3 P
F86E:AD 00 60 LDA $6000# w' C; f3 s U' _9 Y4 m
F871:29 01 AND #$01: N7 J1 O3 T2 q! D
F873:CD E9 07 CMP $07E90 N5 Q, o0 }" p. U8 Q
F876:D0 05 BNE $F87D
4 {) R* m! D" \/ G+ vF878:88 DEY* G4 }( l2 c8 Y( v1 V& Y3 l6 j
F879:10 EA BPL $F865
: |0 e1 @) i: QF87B:30 03 BMI $F880$ \0 K0 Z; v2 d+ l; ]: A
F87D:4C 00 00 JMP $0000! ^7 e5 t5 h/ S, |% n
F880:A5 1A LDA $001A
$ Z, i- Z% \: \9 _& |F882:65 34 ADC $0034: C: M+ j6 O$ K1 N0 b% [
F884:85 34 STA $0034
! S1 a* c6 Q7 B5 x$ W& m$ X+ U. oF886:4C 80 F8 JMP $F8806 `6 ?' M, z- a& V2 y; Y# h
先取Y值=#$035 G, i) f$ ]. `( g
与#$01相与后得到#$01
- \% n) w! f" R写入到$07E9
: J6 M$ q! N( l" d写入到$6000
3 ^( k% V# |* O5 F+ d: q4 I再读取$6000的数据和#$01相与后和$07E9的数据比较$ q9 Y7 {# w3 g4 x; L% z2 u5 Z
不同的话跳过5字节
7 y9 D$ x8 W2 Y! `5 f I否则Y递减$ `7 e z* V E
为正数就跳回0x100-0xEA=16字节
! v8 m& i( N- b/ D8 |! C为负数就跳过0x3字节& N4 O8 q+ t( i2 ?5 G
跳转到$0000(简直没有人性了,跳到这里死机,真想得出来)
0 i/ x! Q: O' X
, i2 s! {6 e% Y; {# @% S' @: P正是因为这样,NEStopia运行FC时,6000-7FFF默认是不可写的,必须在ROM文件头第6字节的D1位置1设置ROM有SRAM,对于Mapper 4,还需要向$A001写入#$80来启用SRAM。
) }/ F/ q0 @/ A由于$6000不可写,因此想$6000写入#$01后$6000还是#$00,之后读取$07E9的#$01与之相比当然不同了,于是直接跳转到死机程序了。
6 @! }" a; W. Z5 U解决方法是把ROM中的所有的AD 00 60 29 01 CD E9 07 D0 05 88 10 EA 30 03 4C 00 00
7 i! J: z; _# M, D' j中的D0 05改为D0 00,然后保存即可。) v( D3 D3 ~4 O/ H
测试完美运行。. l4 P4 h/ `' h+ D
6 H; k* ^6 u/ `! N4 K# x6 y. r* u7 |( F: w- m6 i
教程到此结束。
N3 G$ Y- T( a8 v' w" |
7 O3 A( D, ~5 F% Q U# s+ w& `* n |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|