|
本帖最后由 yandagui 于 2017-4-16 19:06 编辑
5 D0 D* D, R. |, Z- v
% [( v* \$ z! w, n( H6 D xMapper23转Mapper4实例教程4 C! n# {) j# x8 o8 x1 V1 f
& V0 b# h8 w- w, _4 n
FlameCyclone 2017.4.140 t% l1 M. D3 z
* H8 @. |1 M+ C* s
先看看Mapper23文档:8 H! p% T3 R2 A, b& Z
/ E/ L9 ]" j" d4 b$ ~. a4 ^Mapper 23. L4 Y) x* g/ w: Y1 E' N* r
; n* L7 I- h7 I; z' f/ d
$8000: 选择8KB的ROM存储体映射到$8000- X0 R$ R+ c. U# {! u/ ~
$ d% C- `9 y9 r+ V$ [0 L$9000: 0:垂直镜像! K0 L( P( P% {2 U/ q- ^: J4 I+ Y, A
1:水平镜像
$ S$ M6 `+ c8 ?" T% `+ ? 2:$2400镜像
5 L% L+ r; L+ |0 d 3:$2000镜像, @2 L8 ?3 M [% p$ l0 i
& z& d( S+ H) r( o# m% K) Q6 ^$A000: 选择8KB的ROM存储体映射到$A000! ]1 R. |% g& @/ n$ j% W: N7 D$ p
. r( b* l5 |0 W
$B000: 选择1KB的VROM存储体映射到PPU的$0000(低4位)
+ O! r/ m% k! X( n$B001: 选择1KB的VROM存储体映射到PPU的$0000(高4位)
: }# B. f! w$ N4 C- A$B002: 选择1KB的VROM存储体映射到PPU的$0400(低4位)6 V+ I- e1 D, _ v7 u
$B003: 选择1KB的VROM存储体映射到PPU的$0400(高4位)( i) |2 i( }" C" d7 v; Z
0 ?" q k+ z- A5 Y, s: i2 ]$C000: 选择1KB的VROM存储体映射到PPU的$0800(低4位)" R) p$ F" `$ r: q, B
$C001: 选择1KB的VROM存储体映射到PPU的$0800(高4位)
D$ Q/ X! N; C0 Q2 @$C002: 选择1KB的VROM存储体映射到PPU的$0C00(低4位)$ S- o0 O$ F* u9 [4 [3 ^) i5 G
$C003: 选择1KB的VROM存储体映射到PPU的$0C00(高4位)( X$ A# Z9 O0 E6 x, r8 K- w: j
3 z" U) b" z+ N' l5 w) t$D000: 选择1KB的VROM存储体映射到PPU的$1000(低4位)8 p& V- J: u8 Y w. c; c
$D001: 选择1KB的VROM存储体映射到PPU的$1000(高4位)# j$ M7 c$ \$ g2 S1 m4 l4 H2 e) ^* Y2 Y
$D002: 选择1KB的VROM存储体映射到PPU的$1400(低4位)3 V i, R" _# g, D, M
$D003: 选择1KB的VROM存储体映射到PPU的$1400(高4位)
- F4 N1 h# q; I' ?$ @. m
* s- ]0 L- B2 W$E000: 选择1KB的VROM存储体映射到PPU的$1800(低4位) {, m3 t: }# }" }! h
$E001: 选择1KB的VROM存储体映射到PPU的$1800(高4位)
9 n; e0 y* _8 o$E002: 选择1KB的VROM存储体映射到PPU的$1C00(低4位)
7 t: Y. f) R6 Q$E003: 选择1KB的VROM存储体映射到PPU的$1C00(高4位)
/ Q. } O* J8 F: g- |' c: ?. O9 t: ?* T* F
再看看Mapper 4文档:* D0 `1 R3 U$ o; K8 s3 z
4 z5 D/ g D- ?Mapper 4
$ U7 ]* j8 c- H# J+ X: _5 i1 \! }" |' Y% I g3 s
$8000: 模式号
; ?+ v" _4 {" c* X m' q 位D0-D2:$ \9 q* G" l" f9 S Q
0:选择2KB的VROM存储体映射到PPU的$0000! F; C9 a- S0 y$ g3 h) i6 c9 S
1:选择2KB的VROM存储体映射到PPU的$0800
1 y4 L& M5 w& r 2:选择1KB的VROM存储体映射到PPU的$1000' b) B6 G0 s' u* x: s3 }
3:选择1KB的VROM存储体映射到PPU的$14004 f$ ]6 s3 P" D! A% t8 C
4:选择1KB的VROM存储体映射到PPU的$1800, D" \6 _0 m% s0 _) [
5:选择1KB的VROM存储体映射到PPU的$1C00* e+ J' N, n/ c$ l, t
6:选择8KB的ROM存储体映射到$8000
- _. H! u% h! {* C& L 7:选择8KB的ROM存储体映射到$A000
% ~# {- T5 k O' R* v8 M4 h 位D6:2 Y4 ]" W+ h7 u0 d# T! s
0:允许擦写$8000和$A000
: j, ~0 ^6 l% r7 z" b3 t: G4 E# \ 1:允许擦写$A000和$C000
: C7 J- [% }% Z7 A 位D7:
, ^" H1 c6 O, C. O 0:模式号D0-D2使用普通地址
" R9 C: K7 x! v# J J6 o( g& m 1:模式号D0-D2地址异或$10007 H1 }! ]. V7 w% D& L- f, K* T8 F
; y' k) \$ o. ]& Y6 T6 m6 }, c
$8001: 模式页面号
, ?5 d) K: v: D" L3 A: {$ S 写入一个数(00-07),切换存储体到对应地址; r4 J/ {, q' l% Z4 s! y0 m8 T6 i. C0 Q
" T# p: h( d* W/ ^6 Q$A000: 镜像选择% ]" B. ?, U7 a0 S
0:垂直镜像
# {% f- l( P& [ 1:水平镜像
+ ]8 I% o; m: `9 {! w
7 M0 J' b0 l& E9 u% G9 E$A001: SaveRAM 切换9 ?5 {& z( a. d0 M( F9 p
0:禁用$6000-$7FFF/ A- u4 i7 G7 ~
1:启用$6000-$7FFF7 _% `* W, G! j
$ h, C2 W0 {, x1 a1 o! l$C000: IRQ计数器! m8 y! |( h' F8 b1 N: e; `
IRQ计数器的值存储在此处4 J2 v) `; S0 Q3 l* P. Q
! f, M9 E! _- X/ h2 j @1 q$C001: IRQ暂存器/ h3 {3 b& V% M. J3 `
IRQ暂存器的值存储在此处
4 I4 u4 N- l. H; C7 W' B1 [9 F/ B |5 o4 ~ `9 w3 A/ W: w) j& j
$E000: IRQ控制计数器05 r7 E' v. P) @! A P: H& _2 E
向这里写入任何数来关闭IRQ,并从暂存器中拷贝数据开始计数,进入IRQ
6 E( D7 ]& s% J0 f+ W
7 ]( Q: Y9 Q/ `8 W$ j$E001: IRQ控制计数器1
$ _1 V$ @; i" H6 r, l# Z 向这里写入任何数,允许IRQ(退出IRQ,允许下一个IRQ进来)
+ S, f' v9 {* g5 S L. X3 N* L4 u
# A* I. J: S0 f
; a l: `6 K- i0 ^转换思路:
# O& C0 g* \1 F0 `& \; ^" b将Mapper 23 的切bank 方式和切VRAM的方式修改成Mapper 4 的方式。: B& L2 K0 O1 J6 p
3 t3 a( K; X, y
修改实例:
1 F# x- x7 y: g/ M* oContra (J) 256KB Mapper 23) Z1 P( ]9 d8 l6 Z. b: ^5 N
工具:+ ^" ]+ x& ~$ {3 ]$ F0 B* C1 y& L
1.FCEUX 2。2。34 u* ~+ T7 S8 g9 H
2.HXD0 d! x8 z2 }( _
先来看看这ROM的切bank方式:: X4 _0 B5 B5 G' F! [5 {, g
F989:AD 00 80 LDA $8000
) \% M' R% a# h c$ @F98C:8D EC 07 STA $07EC
) s6 Q9 o4 E5 yF98F:8C 00 80 STY $8000. x5 H- \9 |$ R, Y
F992:C8 INY
* Q) Y: Y- G8 w9 h4 a: N6 y- |* wF993:8C 00 A0 STY $A000: D' I; a9 J# ]! \
F996:60 RTS
6 b: M& s6 r$ z- b
9 ^, ]5 p8 i1 B- O+ _- ]再看看它的切VRAM方式:
% G; K& N/ d8 [- d" a( D- [3 QFACE:AD F0 07 LDA $07F0, | Z/ o; T! A3 d' q1 M) ^
FAD1:8D 00 B0 STA $B0008 c. Y9 z2 K. w% Q
FAD4:4A LSR
3 D0 P" U6 N0 O1 V, t# @/ OFAD5:4A LSR! n) _+ p2 N4 E: e h) N; v
FAD6:4A LSR
- U$ x) C" F" Q2 C, h3 F) u. L( MFAD7:4A LSR2 h: W/ r3 [2 O: L. `' b
FAD8:8D 01 B0 STA $B0013 b0 Q( y K) E8 }/ B) u
FADB:AD F1 07 LDA $07F1
/ K( w- S6 o3 ?FADE:8D 02 B0 STA $B002
4 l$ X+ V& ?3 q; N2 dFAE1:4A LSR' D) j. L+ j- U9 o x, ~3 B
FAE2:4A LSR
+ U/ E# X$ ?' |* j% sFAE3:4A LSR. m/ U! L6 o! ?8 Z8 N1 E& [
FAE4:4A LSR" o( _% }" S/ Q1 C9 }
FAE5:8D 03 B0 STA $B0034 V0 g6 Y) H: R# t. E
FAE8:AD F2 07 LDA $07F2" j. [& `8 u2 ~7 r
FAEB:8D 00 C0 STA $C000
+ x1 o& N# f" V! h9 uFAEE:4A LSR7 j# c/ d/ O# O* Q6 k7 B
FAEF:4A LSR
# \) Q# z' p6 ZFAF0:4A LSR
! }1 O& _: m: DFAF1:4A LSR
. Y" Y" u" R$ \7 h Z1 BFAF2:8D 01 C0 STA $C001$ L* S+ U9 x' M! z, p% R9 w' u
FAF5:AD F3 07 LDA $07F33 T3 N# V# G }
FAF8:8D 02 C0 STA $C0023 o+ V; Q- l4 _4 x
FAFB:4A LSR
`1 N( x( |% \1 W1 ^% aFAFC:4A LSR* R7 L# |* |7 h0 G
FAFD:4A LSR
% G5 u1 |: T# jFAFE:4A LSR5 X3 G! C* [# o- T
FAFF:8D 03 C0 STA $C003
3 X$ D6 B% o8 l/ f: B* ZFB02:AD F4 07 LDA $07F4
! s) ?, ]/ p$ y Y9 @" D) n V% XFB05:8D 00 D0 STA $D0000 B" z1 Z) T8 F* Y( x
FB08:4A LSR8 N8 a" F: Z5 v: w# {
FB09:4A LSR
" r5 G% a c* A$ PFB0A:4A LSR4 s7 E; q4 h7 v3 `/ L' {* h- C) X
FB0B:4A LSR
) F9 W3 V6 ^6 y& R* W7 Z; |; fFB0C:8D 01 D0 STA $D001
. ?% Z# ~) E/ Z# N' E) q9 kFB0F:AD F5 07 LDA $07F5
@- Y$ u7 f% T% K6 x9 |FB12:8D 02 D0 STA $D0022 M' d5 r3 G: |! z L2 Q
FB15:4A LSR
3 ~1 W7 N6 r" N5 ]% VFB16:4A LSR
' l0 ?. B/ Q; b, L# F& CFB17:4A LSR2 L& {" h- K, T9 n
FB18:4A LSR4 c- l0 @" D) A Z* `0 k% S# K
FB19:8D 03 D0 STA $D003
% O+ M Z" T6 J) R/ Z4 QFB1C:AD F6 07 LDA $07F6+ o( S6 e U5 [
FB1F:8D 00 E0 STA $E000
4 I% T$ B: o4 x- M7 K+ P( ?, t7 ]9 dFB22:4A LSR) u) N) v- p* F; \! Q
FB23:4A LSR7 M" W: [8 L; [) I& J$ g
FB24:4A LSR8 x, {: B- ?8 {
FB25:4A LSR: b3 {: w, q* I+ b! J1 G# M% g
FB26:8D 01 E0 STA $E001
1 e& \6 r( j* R1 HFB29:AD F7 07 LDA $07F7
! X) f% H/ s% B& r/ e# q# ]7 Y# a0 HFB2C:8D 02 E0 STA $E0021 N N' c' }; x( e% z+ a" b" d
FB2F:4A LSR5 ~1 _0 x" i' I: q+ ]# F
FB30:4A LSR. b4 x2 M6 l: ^' I6 _/ e1 l8 D
FB31:4A LSR, c8 _( T5 x& O8 p$ @$ G' I
FB32:4A LSR
0 P7 ?9 X3 c p! S- o% z7 a* I" I KFB33:8D 03 E0 STA $E003
" e% |' h) ]# K% ?" m7 oFB36:A9 00 LDA #$00
2 K: R5 x9 U8 }; r) {3 eFB38:8D 00 90 STA $90000 p4 W" x* [6 d- ~ M
FB3B:60 RTS7 o! c) P* E# {, P0 x! S
& p/ C- P+ T* m3 B; o
接下来修改切bank方式:
- [- t6 L* `" ]4 Y# ]7 @FB2B:48 PHA P2 c$ W" M% L. F' E' |, b
FB2C:A9 06 LDA #$069 X2 O" Z8 I: n% W# R: i
FB2E:8D 00 80 STA $8000
" a' W c4 T$ H3 r3 iFB31:68 PLA- ]0 z, t3 [( c/ ?
FB32:8C 01 80 STY $8001
8 w( |+ s9 l. K6 ]2 b+ uFB35:60 RTS
0 V( a6 K1 i m: ~7 P1 V( \) f2 [
3 N S$ K6 l9 W8 [/ o5 M' L/ AFB36:48 PHA* d. r6 j8 T8 ?+ Z. Z
FB37:A9 07 LDA #$07
+ E% `! P/ J5 P0 S- X6 ZFB39:8D 00 80 STA $8000 = #$14
8 @, J/ R, b$ g/ Y9 O! gFB3C:68 PLA
! X: e$ q$ x! t, Q7 O3 Z8 |FB3D:8C 01 80 STY $8001 = #$1D
: R D1 T" s% |- A0 b' M' s$ WFB40:60 RTS
2 a/ n$ C' _6 {" k+ g( O3 T" O) Z3 J$ z' p, i1 R- y5 A# e* Z
还要把原ROM的对$8000和$A000进行写入操作的程序修改一下:
) g5 S u0 a' J- X% x' bF989:AD 00 80 LDA $8000 # ` b$ j! o |! D7 W- f6 H4 I
F98C:8D EC 07 STA $07EC% P+ Y" m0 W! Q" M( Y1 g
F98F:20 2B FB JSR $FB2B
' y' J: V& x. A) ]' E: jF992:C8 INY( V% N F- [1 x K' H8 Q
F993:20 36 FB JSR FB36
. }2 v! E( H- k6 m! Y" }5 @) kF996:60 RTS4 X8 j4 `" h! R2 M4 j+ l
8 N0 G9 L* T( h% Y9 V4 T' n' p再修改切VRAM程序:
) ]. g: C- t& V. hFACE:A9 00 LDA #$00
4 t/ t$ W, ~; D7 nFAD0:8D 00 80 STA $8000
3 d6 c' p6 n$ I* @: E9 g& vFAD3:AD F0 07 LDA $07F05 V1 @5 M8 O4 x2 T; M- p
FAD6:C9 01 CMP #$01
* y# P. O4 B4 X; s! LFAD8:D0 11 BNE $FAEB
( w' G* L% T: |FADA:AD F1 07 LDA $07F1% a4 O& z9 ?& t5 N- E/ H
FADD:C9 04 CMP #$04
" r |8 v$ |9 Z/ {FADF:D0 04 BNE $FAE5
" `. \) N/ j3 Q: j1 D& `; ?FAE1:A9 80 LDA #$803 |4 [$ L- u5 C- z: N0 O
FAE3:D0 06 BNE $FAEB4 n4 q' x8 Z* a
FAE5:C9 05 CMP #$05& j# j' k% `1 K, }
FAE7:D0 02 BNE $FAEB
# G& D# t, I1 d% \& W1 IFAE9:A9 82 LDA #$828 C! Y! ]1 T: w/ l
FAEB:8D 01 80 STA $8001
, R# k& m" [1 G7 F GFAEE:A9 01 LDA #$017 H N( l" U/ S0 i7 h# ]
FAF0:8D 00 80 STA $8000# V' L4 b7 j# R/ |
FAF3:AD F2 07 LDA $07F2
0 S, H% T) l" _$ g _2 Y7 OFAF6:8D 01 80 STA $8001
! a! w8 _# X8 JFAF9:A9 02 LDA #$02
5 ?: n0 S* q6 eFAFB:8D 00 80 STA $8000
( c: Y/ @' |* }- h( wFAFE:AD F4 07 LDA $07F4
8 Z9 L; O4 D& {7 o/ [$ f/ ^+ W* A. ]FB01:8D 01 80 STA $8001
, n* C/ T& [! }% QFB04:A9 03 LDA #$03$ ^1 z6 w3 E0 k6 y& X
FB06:8D 00 80 STA $8000
' P& Z7 [0 O; X( ]. n; CFB09:AD F5 07 LDA $07F5& o7 V& _, Q! q+ \9 d
FB0C:8D 01 80 STA $8001) b+ ?/ S& l4 f5 v% w
FB0F:A9 04 LDA #$04
! M$ I6 c0 p. d5 p- \FB11:8D 00 80 STA $8000/ U$ m l2 |$ q) H+ J2 H
FB14:AD F6 07 LDA $07F69 ]1 u; p" P* J6 n9 N
FB17:8D 01 80 STA $8001
2 `5 u: v% Q5 a1 IFB1A:A9 05 LDA #$05
2 v- J! x, F' q1 M. Z; Z* X8 GFB1C:8D 00 80 STA $8000
4 t8 @2 i, P- V& ]" iFB1F:AD F7 07 LDA $07F7
: C; ^! T Q: f) q& K# m" }1 kFB22:8D 01 80 STA $8001% v2 w! J6 o5 Q# x) O* ^
FB25:A9 00 LDA #$00
( Y- P8 t1 \- W1 R- R" IFB27:8D 00 A0 STA $A0005 z9 F- x1 L" p! u
FB2A:60 RTS0 h. z) \8 k' M: N7 v, A
- y" v# T+ z5 V; W1 A然后保存文件。
: ~3 `/ I3 Y. v$ S$ B使用HXD修改文件头:5 f: |. Y! |* }+ k
将Mapper 23
8 m' ~' W* @5 Y5 m+ L7 i' @06字节的高4位是Mapper号的低4位, o2 v) K$ F9 L* V
07字节的高4位是Mapper号的高4位
, E9 U0 j% @- H9 x: ~# z组合起来就是0x17=1*16+7=23- U! ?0 y1 H4 ~
, E) A! Q! L' p1 g2 ~" y" Q& v- n
修改成 Mapper 4, A+ x1 j' I5 B+ Z: P1 M9 W, a' t. S6 G

$ w* |2 C8 B/ N4 ]( G- }) Q, ?- v6 ~4 ]5 b
- C: z) [% E. G# Y再次打开文件:2 q! P( E/ O: }2 ^. ?- L5 m3 z

9 ^$ o( h9 Y' X# H# n" r/ U3 ~可以正常运行" F8 Z! i) |8 e* t
通过全面测试,发现出现精灵错乱:
# E1 D9 w4 K, \第1关:: x6 ~& u0 n4 {% q2 L

; R" v" f' D( [
1 }/ Z5 J s2 n# h0 D3 f第2关:
3 Q4 N1 y7 |8 [! @% a3 i7 j0 m
/ l6 p" w' n5 ^. w任务失败后:
6 R5 I5 T, o3 w @
+ _0 u) @+ F" B$ a通关后上飞机画面:% C9 @+ s3 b d8 m6 s
7 w$ t5 Q( c6 {- l
这是为何呢? P0 j( G8 O$ z; f- r
这是因为Mapper 23 中精灵VRAM切bank是一次切1KB
/ |7 T: f$ n3 C. a但是在Mapper 4中精灵VRAM切换却是一次切2KB,而且忽略bank号的D0位- `* K; G6 o+ N( L! L8 ]# c( o
比方bank 0和bank 1是同一个bank,同理bank 2和bank 3是同一个bank
$ O; F6 ~' Y9 L% w- I$ n6 G6 o也就是说
' r% L2 A" g5 ?8 u) u5 T: L0 pMapper 23中的VRAM的
* Q- r9 o4 b7 y( F: E( U' O9 l/ Cbank 0,bank 1,bank 2,bank 3- Y! U+ a- B1 x" V: ?
在Mapper 4中对应的是, B3 t! i, }' P
Bank 0,bank 0,bank 2, bank2
" Y9 I, M( c) d然后查找原来的ROM的切VRAM的程序:8 q* [. Z* R. b2 H0 ?: p6 Z
知道是从07F0-07F3切到精灵VRAM的:; K( E% H: p0 a2 p
如图所示:
9 j9 f3 z6 g/ e6 Z/ T; J
2 \- s$ o0 B* G+ a" x * g5 J5 ^3 X% u' y, t0 i3 j
作为对比,左边是原版,右边是修改。
) c j7 m' _& q1 k; { c接下来是完善VRAM切换带来的问题,因为Mapper 4只能切2KB的bank,所以我们不能通过切bank程序解决问题。
% ?4 t: c7 G% b: j5 c2 u通过测试知道1,3,5,6,7,8关的精灵VRAM排序如下(07F0-07F3):4 F1 E6 T$ d5 _+ ~5 Q! Y
01 04 06 07: f1 [2 l* V+ g0 \3 E7 x+ k0 b0 K1 a
第2,4关如下:
- m- N/ F! Q' c2 N$ a( r8 y8 N; C6 p6 L01 05 08 093 P- q3 k* I7 v) _: b
任务失败时如下:7 K) c3 {' H" c
32 00 00 1B
- ~, v5 m2 c2 F其中任务失败时对应的VRAM是07F3的1B,只要让07F2为1A或1B即可:. X" O: d- d5 `3 K A
通过调试找到对07F2写入数据#$00时程序如下,于是修改C7E5的值为1A即可:* s3 K5 k/ F2 r
/ @, B- F/ }" \: A) l, l
转到ROM地址:
) Q( s5 b. G" a1 H - U* O9 r1 o1 S) j
修改数据:1 U; }% W8 m4 n( Y! K8 ~' @' [
+ P7 U, {- v2 f1 v6 h
重新失败后可以看到修复成功:
; _7 J% Y9 r: j4 L ) X% F6 J) I4 P# s+ f
接下来是修复正常进行任务时的精灵错乱问题。
; \2 K+ K( G8 ]& `( J首先运行Mapper 23版本,在1,3,5,6,7,8关任意一关的时候,将PPU导出来
/ A9 v9 ^$ P8 s, i% ? ; w) q) ~) Q: |6 Z* i- e) U

9 _. i" C1 [* \9 E3 n
8 X) K9 w- s4 |2 n5 x
6 m# W0 |# v! H( X! F) m# l' _然后用Hxd打开修改的Mapper 4的ROM和刚刚保存的PPU的数据文件:
: x- R- R% ^7 ^- L1 I) { & l8 S7 m( u4 _* a9 l3 s
在ROM文件头第05字节改为0x20:
( |+ I$ K% b7 q, ^+ ] ( [0 l: B- S* N9 O
然后转到文件末尾,插入0x20000字节空字节:' e, j. }9 l: v: Z% E
2 |! N7 H N" T' x3 m; G: t9 X1 W6 [8 Q
$ [+ l! x \: n; q# f% f9 |) ?

2 F9 b/ A8 A- o4 p) X, l: Z 6 ^* j& d! ?) `, x( b. ~8 _
然后将第1关的PPU数据的前面2KB数据选定:% _8 P2 b9 m4 [$ d$ z) ?
6 Q7 S+ V0 h( ?5 g/ I: Q

% Q- W# d) G; a
8 A6 J" O) b! ?7 b7 o3 `* c" {复制之后以覆盖方式粘贴到ROM的40010,同样把第2关的PPU数据的前面2KB以覆盖方式粘贴到ROM的40810
2 \3 T }0 p" A3 ~ $ o' w+ D: t6 B6 ?( ]! S# i! O% R& {
然后保存文件:" b. i# `& r* ~, f6 H, y

9 M6 J* I j% V0 a+ x$ T$ ^最后用FCEUX打开文件,添加07F0-07F3的写入断点
5 W& @3 ]& }$ o. t ; U$ [+ a) L( d( U3 @' u" a8 q
地图预览后即将进入第一关画面时程序暂停了,可以知道此时准备将C793的数据写到07F0:7 o* u+ p4 q5 W8 o% V6 a$ J w

. _( c3 N; z ^0 `测试后知道将C793-0796写入到了07F0-07F3:- z5 M$ ?+ |6 M. }: ]: P3 v( @
同理,经测试每4个字节一组,一共17组,其中01 04对应普通关卡精灵以及其BOSS关的精灵VRAM的bank号,01 05对应2,4关卡精灵以及其BOSS关的精灵VRAM的bank号,再加上一个通关后跳上飞机那段动画的精灵VRAM的bank号。$ l: `- K8 s$ x) n: W! I# L
2 G! g3 c' t" T! k* q: U; P# I9 D; a
4 P5 e* x4 Z; H2 a0 Q然后将文件中标记的01 04修改为 80 04,将01 05 修改为82 04即可:
3 W% J3 O; V) L6 [$ e, q / Q% S+ n+ Q; h* U9 H# A' o. w4 J
保存之后重新运行后效果如下:+ R7 t/ ?) |! e
3 L- i* B& N# {
# T- Z& x( y+ |
# o j0 n/ C) x8 s( w( b! o, `- S
当前使用的是FCEUX模拟器,如果用NEStopia玩的话一开始就死机了,这是因为这个ROM有文件保护吧,它会往$6000里写入数据:
+ [6 Y2 N0 s/ _/ d : [9 N/ z, s" c, b8 V$ m
F863:A0 03 LDY #$03: J2 P+ M+ m2 H
F865:98 TYA k3 X( C0 F' }% N, W
F866:29 01 AND #$01( u; t& ^" s% w3 ]- ?- @6 L
F868:8D E9 07 STA $07E9
! d# A- ^1 Q) h* WF86B:8D 00 60 STA $6000/ Q5 b3 s% G. b1 B
F86E:AD 00 60 LDA $6000
, _$ i$ \+ I' v& d, o) SF871:29 01 AND #$017 i3 Z; S7 \2 V3 u. \9 k
F873:CD E9 07 CMP $07E9
' E/ w( C3 \) @$ Z1 | lF876:D0 05 BNE $F87D) P5 J4 e+ x) ~( o+ R) r
F878:88 DEY" o$ x: ~+ }, k! I+ z# A6 l
F879:10 EA BPL $F865, l7 r1 v4 J4 w1 _6 u% n5 Y
F87B:30 03 BMI $F880
) ^9 h! H6 x) D7 e0 UF87D:4C 00 00 JMP $0000
" [6 o) E( ~9 U; N7 } G$ QF880:A5 1A LDA $001A$ {# O) l# Z8 }$ G7 F9 p
F882:65 34 ADC $0034/ D: ^! q- r8 G
F884:85 34 STA $0034
! R( X% h3 ~) |F886:4C 80 F8 JMP $F880
1 R. Z/ L7 z4 F& d6 I1 {! e" j+ t3 f先取Y值=#$03
8 V# y* s8 @) q6 Q与#$01相与后得到#$01+ f+ A3 Z }. [4 x6 h
写入到$07E9
; T/ ^2 ]1 A/ \写入到$6000* t( |1 c) M9 Q, |" b1 N
再读取$6000的数据和#$01相与后和$07E9的数据比较
6 q( p8 i# ?( w) Y7 W7 G不同的话跳过5字节. o1 ]4 G" m# {+ n
否则Y递减
0 A. \# Q3 p2 _8 n为正数就跳回0x100-0xEA=16字节: y# y3 }( p! j% b x9 W
为负数就跳过0x3字节
A! e% O5 g, V0 Z H/ H跳转到$0000(简直没有人性了,跳到这里死机,真想得出来)
2 U0 S' a& o2 T# S; i% M6 F6 K3 m i/ p: S$ m: y
正是因为这样,NEStopia运行FC时,6000-7FFF默认是不可写的,必须在ROM文件头第6字节的D1位置1设置ROM有SRAM,对于Mapper 4,还需要向$A001写入#$80来启用SRAM。: Y# i9 u( k$ M
由于$6000不可写,因此想$6000写入#$01后$6000还是#$00,之后读取$07E9的#$01与之相比当然不同了,于是直接跳转到死机程序了。
) {2 p( [! G/ L& i解决方法是把ROM中的所有的AD 00 60 29 01 CD E9 07 D0 05 88 10 EA 30 03 4C 00 00
2 ]/ v9 {) B w# P' g: u9 F中的D0 05改为D0 00,然后保存即可。- B3 l, l* e M
测试完美运行。- t. o. H8 ?2 T0 w

. W. t. R, B, }: v
- j6 Q8 V' z J5 }教程到此结束。
- ?2 ?9 S( d' a) t
6 D! C4 I, j7 p |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|