|
本帖最后由 yandagui 于 2017-4-16 19:06 编辑
6 w6 z0 ~9 L/ W4 r& I
. m) _' N5 ]# S# m( b! Z8 R5 fMapper23转Mapper4实例教程/ h i' ?4 ^8 k4 y/ i5 t% q
6 q/ o) P! k+ f* ]FlameCyclone 2017.4.14
* Y4 ]! u3 H6 C
; h1 G' A# [6 A先看看Mapper23文档:8 n0 Q# z/ X+ F9 I
% I4 C, o+ ]' ~' `5 Z+ ]) }
Mapper 23( j7 D* w0 I1 Z4 a+ Q; {9 x
! C, [; ]% Y P) {
$8000: 选择8KB的ROM存储体映射到$80002 V. o6 l; @3 C+ H! f& C
( ~/ ~' [1 b; X" c# H N
$9000: 0:垂直镜像) `6 Z8 r( W/ Q% w9 I3 R
1:水平镜像
+ l2 K7 l" d$ y* h& S( r 2:$2400镜像
3 C+ m8 U# t* A2 O# f) @0 X8 H 3:$2000镜像5 g( |9 X- C, {: o/ ]# x
6 K- T' D: t( ~$A000: 选择8KB的ROM存储体映射到$A000
. r6 B) n2 k" f7 w8 n
' N- n# T2 [5 o3 H7 y( i4 a5 L$B000: 选择1KB的VROM存储体映射到PPU的$0000(低4位)
1 M/ Q! T+ | E1 C/ D5 _; b/ |$B001: 选择1KB的VROM存储体映射到PPU的$0000(高4位): P7 ?3 Q/ i4 |/ P* K9 E5 M
$B002: 选择1KB的VROM存储体映射到PPU的$0400(低4位)' z8 E( _/ A2 k2 [; V
$B003: 选择1KB的VROM存储体映射到PPU的$0400(高4位)2 s W0 p, m8 e/ t7 `9 G
0 j% X, ?. Y" a# _
$C000: 选择1KB的VROM存储体映射到PPU的$0800(低4位), H% J& S+ D. `
$C001: 选择1KB的VROM存储体映射到PPU的$0800(高4位)3 [7 E2 I: x0 [/ A% `) Q# ^
$C002: 选择1KB的VROM存储体映射到PPU的$0C00(低4位)
! K8 F: `" b* Y+ h- ^0 b$C003: 选择1KB的VROM存储体映射到PPU的$0C00(高4位)
, i$ I4 l$ @$ C
, L. C6 `3 }, C0 V1 Q$D000: 选择1KB的VROM存储体映射到PPU的$1000(低4位)
* S( x; [1 c6 E% `1 X* _$D001: 选择1KB的VROM存储体映射到PPU的$1000(高4位)8 k1 T0 |/ m; Y2 o6 K0 P; V
$D002: 选择1KB的VROM存储体映射到PPU的$1400(低4位)
$ l* S8 o$ j: i, Y8 `$D003: 选择1KB的VROM存储体映射到PPU的$1400(高4位)
2 ^" O% u/ H/ q- g$ S2 e, O
1 H. Z* {" b9 D$E000: 选择1KB的VROM存储体映射到PPU的$1800(低4位)8 G7 k. }: t9 H5 S3 G5 L
$E001: 选择1KB的VROM存储体映射到PPU的$1800(高4位)% \ m+ I* y! f; k
$E002: 选择1KB的VROM存储体映射到PPU的$1C00(低4位)
; I4 g( j" F% W* n7 Z6 J$E003: 选择1KB的VROM存储体映射到PPU的$1C00(高4位)( Z9 X( i0 G: N9 q. x, |
' q/ @1 X( E' h: A& \
再看看Mapper 4文档:
2 e# g) F) M* k8 D& x% n' I" [4 d7 r
Mapper 45 m; s0 J5 M" |$ U
! ?4 u- o' Q2 g. E( j7 ~
$8000: 模式号9 b. P; w/ l3 O* K& c4 t
位D0-D2:3 _1 w" ]* K, j& F5 A: F) L: ^
0:选择2KB的VROM存储体映射到PPU的$0000
. I$ z$ i4 P3 f# L4 R6 i 1:选择2KB的VROM存储体映射到PPU的$0800) p: \4 A1 C" J( `7 |: j
2:选择1KB的VROM存储体映射到PPU的$1000
) \. J. @. f- `3 A$ _. \& M 3:选择1KB的VROM存储体映射到PPU的$1400
/ S' g: J; k6 L( ?9 X! F0 f+ k 4:选择1KB的VROM存储体映射到PPU的$1800
% l# e6 J8 M* P% I m$ u( a4 |2 m& M 5:选择1KB的VROM存储体映射到PPU的$1C009 ]1 p6 C6 o2 L3 F$ P d2 F% P) W
6:选择8KB的ROM存储体映射到$8000
. H; J2 I0 l: z7 F8 X x. N 7:选择8KB的ROM存储体映射到$A000
% X, C2 N, q( S9 A6 x 位D6:! T/ p7 q+ S% r, d0 a
0:允许擦写$8000和$A000+ \. ?9 s6 R5 o4 n2 J- N/ {
1:允许擦写$A000和$C000
7 u: x; `( e& y+ ~, ? 位D7:& ?- @. w! m2 a- O% M
0:模式号D0-D2使用普通地址
: u4 t0 |! n3 I" ~7 ? 1:模式号D0-D2地址异或$1000
$ b2 O# o) s* x' Y( q% f9 K: W; S
$8001: 模式页面号
# @2 E8 G. S* I/ u- \1 K 写入一个数(00-07),切换存储体到对应地址' w9 J g+ U* t: C7 z- T- J0 Q
( [' i0 n; J, Y b
$A000: 镜像选择
' b F" f4 T: N" r+ V1 r% U' h0 I% x 0:垂直镜像) \7 L; c( y0 P* K6 M0 A. N1 |7 n; @* V
1:水平镜像
% C) q; G) H& ]6 f3 e+ H2 H2 r5 N/ N5 Y- x
$A001: SaveRAM 切换
4 E+ F; @7 d* d! ` 0:禁用$6000-$7FFF% \3 R5 G' p. Y2 A; D1 e6 Z1 S
1:启用$6000-$7FFF' r4 W6 V2 @2 S4 [6 \+ I0 d
' e6 j2 f1 V6 A% B" ]: C6 k, ?, o$C000: IRQ计数器
# {' m. ?5 c/ I7 T5 v IRQ计数器的值存储在此处0 ^8 O" Z5 n7 H+ r, |' T) O
5 `# v* v! @" e" l! o' F8 t8 p
$C001: IRQ暂存器
' E) f+ z& {9 T9 ^ a IRQ暂存器的值存储在此处
* W1 a$ W, d( X5 `* Y0 _" f. ?: N$ q n9 b# @. g0 J. y' a) X
$E000: IRQ控制计数器0
5 P2 o7 w- [+ C: g 向这里写入任何数来关闭IRQ,并从暂存器中拷贝数据开始计数,进入IRQ( G5 I, P; M2 F7 F* i! s/ u
2 x. l' \* z) u1 h2 y
$E001: IRQ控制计数器19 p* j) U M) i
向这里写入任何数,允许IRQ(退出IRQ,允许下一个IRQ进来), O- _2 t3 Y; S
* w! O, w5 b) D4 A, W; \7 B- m( Z
% J D& W& O4 h# e' A7 u. Q转换思路:
! a5 I4 |" Q! P' O& _将Mapper 23 的切bank 方式和切VRAM的方式修改成Mapper 4 的方式。% j/ ^$ m0 d: [7 n; H9 w
5 c) E: ~" D% R) [) V
修改实例:
. W4 l! ?; H8 m, s3 a9 AContra (J) 256KB Mapper 23
# z% u3 ` W4 L( N. y工具:
: S: x5 e7 g8 j4 D, U1.FCEUX 2。2。3/ P5 n+ B& l5 ?/ l; `1 o8 N+ N
2.HXD; f8 ` A. j2 ~4 Y
先来看看这ROM的切bank方式:
! x0 n, E3 T3 d: r; Z2 U7 iF989:AD 00 80 LDA $8000 : Z, d" b7 Z9 ?( m2 G' w+ J/ s
F98C:8D EC 07 STA $07EC
6 U/ W% X. Y& `, \6 uF98F:8C 00 80 STY $80000 e1 u9 C! r1 B
F992:C8 INY* n6 O) s% A* y7 Y+ X* T$ q" `
F993:8C 00 A0 STY $A0006 U9 y: d3 `4 A2 R8 N, q7 w
F996:60 RTS+ {+ c( ]# X: K9 A
& f& W# X9 A9 d8 r) |# L; `再看看它的切VRAM方式:
* a( p- }7 O9 `- s0 ?FACE:AD F0 07 LDA $07F0
@# n7 d, ?( Z6 WFAD1:8D 00 B0 STA $B000
# B# F* v; c4 M( }FAD4:4A LSR, b1 @8 [2 e7 B' n* a
FAD5:4A LSR
0 Q$ m4 ~; H0 N- ?FAD6:4A LSR
! M7 j1 Y* [/ L; _: CFAD7:4A LSR/ m# L: y- Y6 o3 X
FAD8:8D 01 B0 STA $B001& P" w/ q# W9 t, S8 S! v
FADB:AD F1 07 LDA $07F1
; ]+ g) ^/ u+ c. {3 PFADE:8D 02 B0 STA $B002
/ P; `5 v7 K% X+ R9 v3 C; S/ d$ D! vFAE1:4A LSR- {& z+ w( m- w% @& S. N/ @" K
FAE2:4A LSR
7 _' q% U: |4 V9 U& P; ^# HFAE3:4A LSR
( f# V' {0 |% x: M: F& |9 B9 aFAE4:4A LSR
/ ]( f C% j4 d7 \ b1 ]FAE5:8D 03 B0 STA $B0035 M P1 y! m# E, B8 ]% H2 d
FAE8:AD F2 07 LDA $07F28 U7 v/ U/ g- a! L* f, V; a
FAEB:8D 00 C0 STA $C000( D. A0 o( c- ^2 Z4 Q
FAEE:4A LSR
2 A3 T# y" U p# ]5 pFAEF:4A LSR, F. N& d4 v6 O) {- F
FAF0:4A LSR8 f: }: v/ `" z5 L) S6 D
FAF1:4A LSR- k* H/ D) B- y6 D, i5 R
FAF2:8D 01 C0 STA $C0012 ^8 O1 o5 V, z3 Y+ [% V
FAF5:AD F3 07 LDA $07F3* ^ U# z) R! \+ Y4 Q. U' D& U$ g/ W
FAF8:8D 02 C0 STA $C0024 c( {8 @) c0 @) {. k! p; Z
FAFB:4A LSR
) `2 a) n- h. Z4 @# y$ eFAFC:4A LSR
# K& x X9 ^( G8 lFAFD:4A LSR
: v3 g1 B7 g% ?FAFE:4A LSR/ A1 n6 Q% b; R& h
FAFF:8D 03 C0 STA $C0031 w! N9 U. {) C( k2 n# s5 u! D/ Y& n
FB02:AD F4 07 LDA $07F4
! H5 O9 |& S7 W( t- C. uFB05:8D 00 D0 STA $D000
^! e& a: V, L- ~# X) ^- qFB08:4A LSR! E2 D: R; ^7 E8 L* `
FB09:4A LSR C( s6 s9 `1 ~5 ~0 A
FB0A:4A LSR% r' x) a; h& j7 p' W
FB0B:4A LSR
* e, G* c- Z1 P$ j$ NFB0C:8D 01 D0 STA $D001
+ `$ H- Y; C2 f! b5 ]7 WFB0F:AD F5 07 LDA $07F5
6 N! j$ U ^; @4 [! x# u1 O' AFB12:8D 02 D0 STA $D002' M8 p* @% z7 u
FB15:4A LSR8 a( c# N6 Z. }' n( r( u/ n
FB16:4A LSR; s8 a) w4 n& C2 R/ B8 ^3 ^
FB17:4A LSR2 H* e. n2 a$ p; V. X' K! C
FB18:4A LSR6 ~6 r/ ?+ M6 m( |" H
FB19:8D 03 D0 STA $D003/ |7 ?) W9 E4 |% n! j( K
FB1C:AD F6 07 LDA $07F6; h6 i1 h- X3 b3 V( R
FB1F:8D 00 E0 STA $E000/ p3 R. u% \. n! g4 L
FB22:4A LSR+ R' {% I$ _1 m7 N! s
FB23:4A LSR J, T' j- d, l% ~
FB24:4A LSR; }' h, { j& N/ X
FB25:4A LSR9 [7 m. }" E0 ]1 }' ?# c
FB26:8D 01 E0 STA $E001
5 U- ]( Q" `% `$ I" hFB29:AD F7 07 LDA $07F7# [, @" p0 j$ t3 x ^
FB2C:8D 02 E0 STA $E002
2 G( w+ }- ~0 c2 m! ?4 d. N" oFB2F:4A LSR: M8 p+ N: X/ C- D& X
FB30:4A LSR+ j2 J8 ?; {2 _- g
FB31:4A LSR& d& s* h, z8 v. h+ [0 \
FB32:4A LSR
) R( |- ^) c }1 rFB33:8D 03 E0 STA $E003, _: R; y1 R& B0 e( J) G
FB36:A9 00 LDA #$00
9 Y+ n: d! p/ a# A0 QFB38:8D 00 90 STA $9000
: [& j9 q1 j5 |FB3B:60 RTS5 _" ^! v7 W( V$ t
* i0 I, F) m) }( S7 A
接下来修改切bank方式:
% f4 T$ A' {5 Q' YFB2B:48 PHA) s2 G# M$ _$ D! y. A
FB2C:A9 06 LDA #$06% e; f3 H! U9 ?( L1 K1 ^" u5 h- \
FB2E:8D 00 80 STA $8000/ b$ j2 L4 I) W, J: ~# I' H
FB31:68 PLA
6 b$ D4 h! y+ \7 VFB32:8C 01 80 STY $8001: f# ]& J/ ` q2 b* s/ \
FB35:60 RTS( v3 Y2 w: J" V" \
; ]1 [6 m- V* J/ S3 F. u2 {FB36:48 PHA
8 M4 z% E8 m* H0 BFB37:A9 07 LDA #$07
% u& n- U4 m) fFB39:8D 00 80 STA $8000 = #$14
. }6 v' m9 _9 O+ x! @8 P; EFB3C:68 PLA" D) {( v* [9 ]0 ]% _
FB3D:8C 01 80 STY $8001 = #$1D1 J8 q) `4 u7 r2 I6 Y
FB40:60 RTS' [2 D( n- X, I- |* L& e. M
/ c7 j* L$ Q7 T% ]6 c还要把原ROM的对$8000和$A000进行写入操作的程序修改一下:9 f$ v6 |4 A/ ~+ {7 J5 q+ d& F) Q
F989:AD 00 80 LDA $8000
/ a: h$ ?6 r3 X& q' [0 L; ~F98C:8D EC 07 STA $07EC2 ?% B/ q& I' I2 H+ U
F98F:20 2B FB JSR $FB2B
V( `6 `1 Z% K* {# {. i; uF992:C8 INY P* N, g; `6 U( c- I' Z" K
F993:20 36 FB JSR FB368 i9 \( N" G* o+ @3 F
F996:60 RTS, `' U u' B- w% I7 G4 _ K' t
. G8 }+ S2 v/ g! p( ?- O0 ^再修改切VRAM程序:6 b) e- P2 n4 o1 P, A6 }
FACE:A9 00 LDA #$00% u- k# z4 `: J* S! n. u4 ?
FAD0:8D 00 80 STA $80004 ?" _ R" _) ?' Q9 Y+ |
FAD3:AD F0 07 LDA $07F0! s/ h1 P5 ] ]6 p
FAD6:C9 01 CMP #$01# s0 d% `6 g- O" `, b& w
FAD8:D0 11 BNE $FAEB
; ~3 b0 O' k2 z" s1 i- z; kFADA:AD F1 07 LDA $07F1
: D! W+ ~0 I' F3 Q" ZFADD:C9 04 CMP #$04
' e7 W( T$ X: V+ t1 vFADF:D0 04 BNE $FAE5. K. I+ `. G/ v' ~- ~
FAE1:A9 80 LDA #$80
' _: c3 I% j* `3 rFAE3:D0 06 BNE $FAEB
1 M: E# i5 j# M" a2 V, n8 }FAE5:C9 05 CMP #$05: A; w0 [" N1 K( q5 v. T% [ t
FAE7:D0 02 BNE $FAEB
?7 K s* G- z- O* UFAE9:A9 82 LDA #$82
- }/ W- [- \0 f4 @6 l1 t" |FAEB:8D 01 80 STA $8001
4 Z1 Y: q( ^) c5 [/ J0 m. Y6 qFAEE:A9 01 LDA #$01
- A& w' j9 b* c% j% u( @5 f% TFAF0:8D 00 80 STA $8000; x; P O9 v" U+ ~
FAF3:AD F2 07 LDA $07F2
9 N& x7 N ?- J4 v! R& c% [FAF6:8D 01 80 STA $8001
" v0 u+ c- S) _6 ?- e# cFAF9:A9 02 LDA #$02& l+ t Y* L F" m3 R. `1 \" C" i
FAFB:8D 00 80 STA $8000
2 D" U, p. P* i4 s+ T; N6 vFAFE:AD F4 07 LDA $07F4, M- e P: X* H6 G
FB01:8D 01 80 STA $8001
7 x- m, A+ s! X$ \FB04:A9 03 LDA #$03
2 h6 k& J2 N UFB06:8D 00 80 STA $8000
7 x ^9 @$ ^" M$ P1 hFB09:AD F5 07 LDA $07F5+ |( c1 Q0 S2 g) M/ f9 Z
FB0C:8D 01 80 STA $8001
. q% ?$ d1 V1 b, bFB0F:A9 04 LDA #$04
5 \) Y: u; b2 w8 C4 z: x: y* jFB11:8D 00 80 STA $8000; M! x3 |; J. R+ f4 z9 t$ ~
FB14:AD F6 07 LDA $07F6
" m% N- S0 w. }! R/ k# C6 bFB17:8D 01 80 STA $8001! b3 C. @) h9 z o' t' D
FB1A:A9 05 LDA #$05: F$ P5 s! L: Y
FB1C:8D 00 80 STA $80004 H+ L6 P) q" M# g3 z6 t' Y
FB1F:AD F7 07 LDA $07F76 u- d, b8 T# u' P6 Z7 V" ~* ^
FB22:8D 01 80 STA $8001% z- M. @. F) O* N8 F: F: f
FB25:A9 00 LDA #$009 p7 L7 j: W2 F; t5 s. J0 {
FB27:8D 00 A0 STA $A000% \; _; E( }3 J5 v& D+ A
FB2A:60 RTS
( \0 W, s; o" q. O
: G, s& o7 l7 f3 s) P1 p# C- u; }然后保存文件。9 i! W2 B* `& u+ C! k: ?& K
使用HXD修改文件头:
3 A }' t: a. ]+ j b, R% x J将Mapper 23
+ r1 |- l/ j! p5 R06字节的高4位是Mapper号的低4位
2 _+ u3 f, w) }07字节的高4位是Mapper号的高4位
) Q- t+ @9 P+ l$ r$ T# i. }- s I组合起来就是0x17=1*16+7=23/ O+ W0 L' G& u, R$ N- _6 H

! z" n* N7 R+ ?9 B修改成 Mapper 44 N- {8 C+ u8 Z8 v) c

7 E3 t( U+ k& O0 x: ]( G$ M! b2 p3 L6 p7 {' H7 \; g4 b* ^$ I/ W
2 i0 K8 F, {" e! ]5 l5 l9 @; g
再次打开文件:$ m, |8 a5 w2 Q5 a0 a# ?0 f- i

9 d- ~5 I' }, [) t可以正常运行
( T1 U+ a- s& B4 I4 H3 j通过全面测试,发现出现精灵错乱:
( v8 \. {2 n k3 v% z$ ~5 f第1关:; |/ l/ [7 [/ }4 X' N* R% S6 W+ J
: Y- y: S7 l( v5 ?
* q# _& c: S: C' G9 G9 C
第2关:
8 a* p) B) \! ?% F* o* w
& i- ~6 f8 [1 Y5 E8 b) o任务失败后:
# Q/ D, R2 u; x * V) N7 Q4 e" F$ b7 }6 [
通关后上飞机画面:) F. }9 U' c0 R2 [+ ~

3 m" J- j5 } i5 g3 F2 ^4 N这是为何呢?- _8 N% ~+ k& g& I. t; j
这是因为Mapper 23 中精灵VRAM切bank是一次切1KB" Q' {3 |8 v4 v8 K1 x! P
但是在Mapper 4中精灵VRAM切换却是一次切2KB,而且忽略bank号的D0位
/ v" @" g& J' G比方bank 0和bank 1是同一个bank,同理bank 2和bank 3是同一个bank% @$ ]0 q' w2 |& a* E( e6 f' K f
也就是说
/ w- v3 t* r! Q S) C' q8 GMapper 23中的VRAM的
2 p" z9 l3 y* i$ G! Gbank 0,bank 1,bank 2,bank 3+ p( L8 _6 a$ V* Y9 O5 y+ H
在Mapper 4中对应的是* X" P' ^9 {$ o, H) w9 q8 t
Bank 0,bank 0,bank 2, bank2
6 d! a8 ]% s: c" |' D1 E( x @, [然后查找原来的ROM的切VRAM的程序:
; w% u3 v7 c$ I( ^2 l% \知道是从07F0-07F3切到精灵VRAM的:
7 r! n: `7 C ^如图所示:
/ U/ U9 m& V* J) |. a7 Q: O) y
% _* ?4 j: o. o1 t! T Q 
; M! g7 W' Z. L$ p作为对比,左边是原版,右边是修改。
- s9 T# N8 h3 H& H a( m接下来是完善VRAM切换带来的问题,因为Mapper 4只能切2KB的bank,所以我们不能通过切bank程序解决问题。3 j0 Y: I8 O( l( V7 \( r6 B
通过测试知道1,3,5,6,7,8关的精灵VRAM排序如下(07F0-07F3):
+ t& x2 t5 o V# H; M" b' K01 04 06 07
) u" ~0 D* u: V8 |) W第2,4关如下:
2 `. K5 z8 l0 I01 05 08 09
7 o. @: z7 X5 [0 K( h任务失败时如下:2 u* m2 X9 R8 z6 z5 i' B, N- R
32 00 00 1B9 W: V# g& I" S* M: L4 k1 A3 U7 o
其中任务失败时对应的VRAM是07F3的1B,只要让07F2为1A或1B即可:$ J% V/ y5 W. B# K' Q
通过调试找到对07F2写入数据#$00时程序如下,于是修改C7E5的值为1A即可:: G) |+ A: ^( `6 p

. i+ w5 x9 N4 j2 l: q% t' j转到ROM地址:
( h% R- Y! b# m& t0 C
. m$ t/ z" T8 @. Z; t. q修改数据:2 F- w, G( s) H! I3 c( G# I

$ x2 @ O! R6 |6 k) f! K重新失败后可以看到修复成功:
1 G. t8 a2 Z' x" g( w5 G- F
$ L8 h: ~1 S# c: @0 r接下来是修复正常进行任务时的精灵错乱问题。, W6 y& C; G2 V, {0 i* v
首先运行Mapper 23版本,在1,3,5,6,7,8关任意一关的时候,将PPU导出来
4 Q! z5 r4 D1 r: l& C/ w' ]6 o$ S5 \
& c% L8 o$ o) d$ m k8 f; @
& _) V2 o# w6 |0 Q% T/ S+ v1 B
8 [- y. { B8 {% i, i5 G 0 Z# ]+ |0 j7 h# f# @3 l" a7 a
然后用Hxd打开修改的Mapper 4的ROM和刚刚保存的PPU的数据文件:0 ]1 t/ \0 r, _% r% } S, Y1 M
3 q# v3 o7 a4 j$ z- W
在ROM文件头第05字节改为0x20:
3 O3 H' B9 S( L# {
! {* t7 }( ]! g$ A1 k# x2 M- U然后转到文件末尾,插入0x20000字节空字节: v8 ?4 T" x, }3 m2 k" P" ]0 r

, T5 M- H4 i7 H5 v' q7 v. n* x$ \
6 H2 e: Q' {, H. T O# p
! X( g' O1 S$ F8 c
$ ~* r' L/ `: F i6 a; o然后将第1关的PPU数据的前面2KB数据选定:3 i/ R* G: K% e" Z# T1 ]2 M

6 Y# I" D! x* j- j3 d1 q & b' \, p+ b, `1 |
5 @5 Q9 h: X& l( E, k1 I b
复制之后以覆盖方式粘贴到ROM的40010,同样把第2关的PPU数据的前面2KB以覆盖方式粘贴到ROM的40810 l2 z( o; S* T' @$ T% b
- i2 a( g* m9 ^2 U7 C2 [) b
然后保存文件:
# o7 p7 k: D* H2 ~ $ |! F) u# S# k, `, }
最后用FCEUX打开文件,添加07F0-07F3的写入断点; y4 q" R1 R6 k6 F) R- v. I) Z5 w
4 |$ T! i9 o' m' c8 Y
地图预览后即将进入第一关画面时程序暂停了,可以知道此时准备将C793的数据写到07F0:! y% ^! ~. M% E5 h" l# v# _
8 q# p0 E1 t: x+ d+ R0 B% L7 H/ p
测试后知道将C793-0796写入到了07F0-07F3:
" {$ }2 E( b* s0 ~8 B3 w同理,经测试每4个字节一组,一共17组,其中01 04对应普通关卡精灵以及其BOSS关的精灵VRAM的bank号,01 05对应2,4关卡精灵以及其BOSS关的精灵VRAM的bank号,再加上一个通关后跳上飞机那段动画的精灵VRAM的bank号。7 f( @7 U9 v, U
2 i5 i6 I4 i/ r' t3 X# f ; I$ B7 m0 w; r4 q1 D
然后将文件中标记的01 04修改为 80 04,将01 05 修改为82 04即可:" g) Q2 m" q" H- |2 g$ ]2 b

( D; }. W% d8 `: ]6 L保存之后重新运行后效果如下:7 I& i7 T; n4 q! ~0 B8 a

. @) ]* [' k5 Y( C ) v: G7 R1 m' b, L$ @

; A; E, {8 ^' L+ r2 i% p当前使用的是FCEUX模拟器,如果用NEStopia玩的话一开始就死机了,这是因为这个ROM有文件保护吧,它会往$6000里写入数据:9 A$ ~& { g1 x& g9 W4 B
. T0 f1 V, E/ y
F863:A0 03 LDY #$03
0 z6 {+ m, r/ C) \5 a5 s. r) [- n+ |F865:98 TYA
$ U* R1 u3 y/ ^# TF866:29 01 AND #$01. T% G5 J! E8 q( ?& F) F
F868:8D E9 07 STA $07E9
, e9 M' C0 K7 k N" L$ _F86B:8D 00 60 STA $6000
$ L4 B+ d/ N" z1 r1 D: H$ E5 `F86E:AD 00 60 LDA $6000% V8 \, `+ _5 I, D- w& _6 M
F871:29 01 AND #$01
/ ]- {& F( S F$ g2 ^2 d. tF873:CD E9 07 CMP $07E9
4 l( i8 O+ {1 ]1 _# n, l+ w- J5 HF876:D0 05 BNE $F87D1 c1 V2 t- r$ x& u2 M$ y" c0 d
F878:88 DEY4 }; m* c; _' S' w& |
F879:10 EA BPL $F865% n/ i( o& r" d" r3 L4 D
F87B:30 03 BMI $F880
$ Z$ c) O$ K0 c4 c2 {F87D:4C 00 00 JMP $0000
' [/ Z$ S3 }1 d9 K. XF880:A5 1A LDA $001A& Q, n4 o. @5 w7 w$ A
F882:65 34 ADC $0034
0 V# t7 ?1 X* B2 a9 U2 JF884:85 34 STA $0034/ x5 T! k; j+ I T
F886:4C 80 F8 JMP $F8809 G# Z' @& R- A5 U4 Z% `
先取Y值=#$03: M* B2 Z( k) _2 k
与#$01相与后得到#$01
' a* W- G. Z w5 L, G# w写入到$07E9
% `3 {$ _$ y- c! Z写入到$6000- y: R3 K% l2 A# z
再读取$6000的数据和#$01相与后和$07E9的数据比较: D1 _8 Y) G( \# E
不同的话跳过5字节' A% n4 M7 O) O' `# W" R9 X
否则Y递减' K9 L% n+ y+ x: X+ B
为正数就跳回0x100-0xEA=16字节: s4 v1 M- H! H
为负数就跳过0x3字节
* e& I6 a, \6 [; v" O跳转到$0000(简直没有人性了,跳到这里死机,真想得出来)
: g- d" t" W2 q( `: T
5 G& O+ M/ s7 H" M正是因为这样,NEStopia运行FC时,6000-7FFF默认是不可写的,必须在ROM文件头第6字节的D1位置1设置ROM有SRAM,对于Mapper 4,还需要向$A001写入#$80来启用SRAM。
; q" R; m4 E& {3 C. c0 u由于$6000不可写,因此想$6000写入#$01后$6000还是#$00,之后读取$07E9的#$01与之相比当然不同了,于是直接跳转到死机程序了。
# j0 [1 n% j1 h$ _$ T3 O解决方法是把ROM中的所有的AD 00 60 29 01 CD E9 07 D0 05 88 10 EA 30 03 4C 00 00
% i( G1 F* ^5 E中的D0 05改为D0 00,然后保存即可。
& ~( \, n9 u3 E+ T& Y# Y测试完美运行。9 P; |7 { ~' q- r+ p$ n
7 R& h2 e3 }# L4 F5 a* l! c
5 `; ~- o& L3 k* [教程到此结束。/ s4 l/ w/ A8 R0 e% _/ G
5 } \- t+ R6 n9 x' n4 t5 m |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|