|
本帖最后由 yandagui 于 2017-4-16 19:06 编辑
: {4 g2 V. k6 }1 H( |- e9 E$ _' D" T7 M0 c" G2 W' B8 T
Mapper23转Mapper4实例教程6 Q: k% g4 ]8 R' N5 u
6 {0 n: E# i" I0 U
FlameCyclone 2017.4.14, @7 G/ k+ o J
& r, X1 J5 o1 y先看看Mapper23文档:
0 N) m* X0 p: k1 u+ q) S2 ^8 f4 A/ N9 O' X/ ]
Mapper 23( u: r5 Q- B& q6 \. U
5 G' ?* q4 g8 G
$8000: 选择8KB的ROM存储体映射到$8000/ h3 s0 G; L8 k( L8 ^( \( W
( Q' ^- `, Y/ k7 Q$9000: 0:垂直镜像& d) I$ k/ I3 W
1:水平镜像
4 }2 b. i: ]# I6 g! L 2:$2400镜像
1 j) N) G) f* o, T9 U5 C 3:$2000镜像
7 N" o, z$ u, \$ Q! w# l- ]: h6 K8 {6 t7 u
$A000: 选择8KB的ROM存储体映射到$A000+ n3 d y5 s$ [0 t/ R! z
& [$ [7 F8 X# Q) h$ \9 {$B000: 选择1KB的VROM存储体映射到PPU的$0000(低4位)
( u3 W. X6 X6 H3 z8 Y7 o, A$B001: 选择1KB的VROM存储体映射到PPU的$0000(高4位)# T' x1 R P1 B9 s
$B002: 选择1KB的VROM存储体映射到PPU的$0400(低4位)
. c" A! v5 E3 D) I3 f4 c3 t$B003: 选择1KB的VROM存储体映射到PPU的$0400(高4位)) T- E* g4 [5 p+ w
' R, N$ R: [' P0 M/ ~$C000: 选择1KB的VROM存储体映射到PPU的$0800(低4位)0 K3 b4 ~) S- h" R8 j6 @: r0 }
$C001: 选择1KB的VROM存储体映射到PPU的$0800(高4位)
8 Z- l5 B: K' E3 T' ]$C002: 选择1KB的VROM存储体映射到PPU的$0C00(低4位), p, W, f4 v7 V$ M
$C003: 选择1KB的VROM存储体映射到PPU的$0C00(高4位)/ M# e, m: v9 J% [% b: k3 a. C4 U
4 c9 T& l( ]* I+ F4 f$D000: 选择1KB的VROM存储体映射到PPU的$1000(低4位)
5 Y, q" E; o+ X) G. h+ D$D001: 选择1KB的VROM存储体映射到PPU的$1000(高4位)+ A; O5 A+ ]1 A( y
$D002: 选择1KB的VROM存储体映射到PPU的$1400(低4位)
$ @+ |6 K9 f3 V( K# r$D003: 选择1KB的VROM存储体映射到PPU的$1400(高4位)
/ y8 t. B* F( n4 T& \2 j" i* P
$E000: 选择1KB的VROM存储体映射到PPU的$1800(低4位)
- E! X4 ?) P6 Z8 ]9 H* K. ~$ O$E001: 选择1KB的VROM存储体映射到PPU的$1800(高4位)
4 |) E; o& q5 @$E002: 选择1KB的VROM存储体映射到PPU的$1C00(低4位)2 R" N9 f1 U7 V1 E9 [
$E003: 选择1KB的VROM存储体映射到PPU的$1C00(高4位)
; C+ k5 v, F" y0 O) a0 g) r( {& q/ X. ?# [
再看看Mapper 4文档:
+ `! S/ W0 O8 y4 j, c* ^. i( H5 i4 ]) b3 w
Mapper 4
$ W6 g# N" j$ N
9 O! |3 O2 N; H' B8 ]4 m$8000: 模式号
, @( d" O$ T$ Y8 n 位D0-D2:
/ W4 M1 G+ R S; U# p* Z 0:选择2KB的VROM存储体映射到PPU的$0000' e# d2 {4 R- e% g5 F" r, G% I
1:选择2KB的VROM存储体映射到PPU的$0800& h, L& I& J# @ ]4 m
2:选择1KB的VROM存储体映射到PPU的$1000
6 V6 k1 w" {. w 3:选择1KB的VROM存储体映射到PPU的$1400
0 w5 {! p, y& B; S4 P 4:选择1KB的VROM存储体映射到PPU的$18007 X* m9 c- F- w: B4 s! _' t! p
5:选择1KB的VROM存储体映射到PPU的$1C00
9 i% X C- D4 ^% a) M6 c1 `5 m 6:选择8KB的ROM存储体映射到$8000
" o/ \" m% s8 r7 h. M 7:选择8KB的ROM存储体映射到$A000
1 A. D! c1 N& b% M) N( a 位D6:
+ E1 m# { w( b O z- a& C' `7 |& i 0:允许擦写$8000和$A000, b* ^" y& Z$ V; s6 \, B
1:允许擦写$A000和$C000
: S p/ V* u& o: r4 ~. \ 位D7:0 W+ x* T6 P0 W: |9 a o# C) x9 X
0:模式号D0-D2使用普通地址
4 h* C( l9 n/ o3 R 1:模式号D0-D2地址异或$1000
9 U# S1 }' Z% X: a& H3 n9 G9 E% Y& \3 r$ s, k! j+ F
$8001: 模式页面号9 @8 S8 h9 c1 t; i: v2 Y" h
写入一个数(00-07),切换存储体到对应地址1 y% z z5 {6 W! B8 x7 S' }) i! {
( T. b+ Y& X1 `# l4 w' b$A000: 镜像选择
{5 Y7 X$ s0 }5 X4 ]1 S7 S% U 0:垂直镜像( d# x6 ^! W0 b1 }' R9 K' b+ ~
1:水平镜像8 L7 K, b3 r7 ~! M. r8 X+ b
# o0 J: [$ L9 U+ d( H" I7 g8 E6 ~$A001: SaveRAM 切换
; h% q$ M( Y, K$ i4 B, B 0:禁用$6000-$7FFF
' o$ C3 `! B/ x2 e+ g 1:启用$6000-$7FFF
/ G2 @8 o! Q6 }* l: ?9 @. \6 z9 b' J7 D; j/ `; ]
$C000: IRQ计数器" h* k+ J: Z# {
IRQ计数器的值存储在此处
$ o( X$ }, o7 w. j# j2 ?- f9 ^8 D& a
6 t* e6 D6 Z; f& n4 ~$C001: IRQ暂存器, \+ B3 _( L& w6 D
IRQ暂存器的值存储在此处; M0 Z) J: Y8 }3 N4 S0 I- C
7 _& N2 {1 m7 d3 \8 L0 q3 ~, v
$E000: IRQ控制计数器08 D+ g; t; w# ?" b% T& j6 k% c
向这里写入任何数来关闭IRQ,并从暂存器中拷贝数据开始计数,进入IRQ, W5 f" Q2 H, u( l0 w8 a8 }
% m: R5 K' j2 q" K/ c4 M$ p
$E001: IRQ控制计数器1' V5 p. n9 n: H
向这里写入任何数,允许IRQ(退出IRQ,允许下一个IRQ进来)
9 T s9 ?! H* X/ `7 a$ m6 F( j; l" w# R j
3 [1 w# }0 Z5 d! G, @1 h
转换思路:
: B+ R" `1 p8 C将Mapper 23 的切bank 方式和切VRAM的方式修改成Mapper 4 的方式。; F4 z ~" W) o: d; y- e1 z0 Q+ O
, i/ U; ]. g" _, O* c
修改实例:. U* h( O7 B; G1 K6 E
Contra (J) 256KB Mapper 23
. _. _) P) c% P" ^工具:
; J) o1 O5 E( Q1.FCEUX 2。2。3' O. D2 N5 ], l, `9 `+ |
2.HXD
3 l! @0 d: Q: R3 F先来看看这ROM的切bank方式:) y0 M' [8 g$ D O
F989:AD 00 80 LDA $8000
' P6 }( c8 ?$ SF98C:8D EC 07 STA $07EC/ g- ?* R+ Y/ e4 U2 |/ K" K
F98F:8C 00 80 STY $8000* \0 N8 n8 E& \8 y
F992:C8 INY/ r. t$ r7 _& J' J
F993:8C 00 A0 STY $A000" ~/ O; ^: O5 `) ^
F996:60 RTS; O z! A. X& P' v
5 ^7 r Y4 Z6 C' {$ @- i
再看看它的切VRAM方式:, X( Y: |: L, z5 a
FACE:AD F0 07 LDA $07F0
3 ?3 M, I7 R4 I8 ` o: HFAD1:8D 00 B0 STA $B000
. V: O2 H, [0 sFAD4:4A LSR) K! e- n# l' `: A5 k+ o3 A6 E9 ]
FAD5:4A LSR
9 Z( Q( o6 V# e+ o( r* pFAD6:4A LSR ^- {1 l2 N: o8 k0 n
FAD7:4A LSR
9 S2 B: h5 m. w6 n- j* \FAD8:8D 01 B0 STA $B001$ \0 `2 O4 ^9 G* i# j: _
FADB:AD F1 07 LDA $07F1$ _' t0 m0 R2 P2 X9 m
FADE:8D 02 B0 STA $B002
5 X0 y2 c; b5 l6 F9 V6 ZFAE1:4A LSR
2 ]1 M4 B* A! X& PFAE2:4A LSR: A0 {8 c# L- H9 D) ^$ W; G
FAE3:4A LSR
1 o% t8 s. P( n$ ZFAE4:4A LSR B* |( p& }9 Z, s% r! i) Q& _
FAE5:8D 03 B0 STA $B003
4 ^; W. `. N7 q u# gFAE8:AD F2 07 LDA $07F2: ]# I% X+ ~' i$ C% a
FAEB:8D 00 C0 STA $C000# |7 }" z1 u M: w: ]8 |
FAEE:4A LSR0 Y" C, G9 I3 c5 d
FAEF:4A LSR
# k3 P; K$ k2 @1 ?" [FAF0:4A LSR
$ V( h+ F& g8 U% RFAF1:4A LSR. I+ \9 O; {# a% a* _$ U% M" @
FAF2:8D 01 C0 STA $C001
& }6 d8 ?% D- J7 Y2 f7 w' n6 bFAF5:AD F3 07 LDA $07F3
* z& ^$ M) ^& AFAF8:8D 02 C0 STA $C002, j' Y# q, n. R2 E
FAFB:4A LSR
5 C1 ]+ `* ^$ wFAFC:4A LSR
$ n J5 X S1 }( \FAFD:4A LSR
; s7 F* {2 M) m' hFAFE:4A LSR
* Z; v3 b" Z, {3 H9 p* S9 mFAFF:8D 03 C0 STA $C003$ _& y2 T. w8 `, K& t) o/ W F
FB02:AD F4 07 LDA $07F4
4 F0 N8 Y6 G# P8 s5 n" D! tFB05:8D 00 D0 STA $D000& U7 Y z( p. i+ {+ s/ Y- h$ O
FB08:4A LSR
+ h5 O7 o0 q/ s. nFB09:4A LSR' C |. _4 d n: ^3 e# A
FB0A:4A LSR; [8 U5 M: O y) \
FB0B:4A LSR1 x7 v* n+ x1 l) V
FB0C:8D 01 D0 STA $D001; f. |% \7 L" H4 W6 I8 F1 I* n
FB0F:AD F5 07 LDA $07F5& a; W+ V) {4 m
FB12:8D 02 D0 STA $D002
6 ` M9 [8 {8 \FB15:4A LSR
- R4 A4 X! X/ W2 ]: A9 TFB16:4A LSR: b+ s' h& {9 f" l) o
FB17:4A LSR
* y" z; i9 N6 {/ r6 r4 ^FB18:4A LSR
6 N% g( ~0 Q1 O [FB19:8D 03 D0 STA $D003
2 ^0 s- X5 m6 f7 fFB1C:AD F6 07 LDA $07F6: C* ?. B9 l; k# w8 X6 V
FB1F:8D 00 E0 STA $E0005 n- k3 X8 ]' ]; \8 P- ]$ u5 }" L
FB22:4A LSR- J/ f1 A6 W+ p" q: Q6 B0 O1 J* m
FB23:4A LSR. F( ?& }/ j0 @
FB24:4A LSR
: u9 |8 b4 _( |, i5 rFB25:4A LSR; y" e4 t" c5 w1 k" d6 y+ R, R8 @
FB26:8D 01 E0 STA $E001
' i( x/ r5 C2 U- Z4 X& R+ w iFB29:AD F7 07 LDA $07F7
6 L! T6 J- L' [; [/ d" ^FB2C:8D 02 E0 STA $E002. x, ]# N+ w/ n& o
FB2F:4A LSR7 J* [3 m. u/ N& b" `
FB30:4A LSR& ]3 p5 F2 t' {3 y& ^4 v
FB31:4A LSR# i* k( T+ G* H1 Y {; `4 H3 B" C2 J
FB32:4A LSR' c% ]2 _- Y4 Q- ?! T
FB33:8D 03 E0 STA $E003
! b; t# N1 F$ G% ?, ^FB36:A9 00 LDA #$00
5 a* O& ~* @# {+ u6 YFB38:8D 00 90 STA $9000
' y; e" E2 [4 \& U# ^5 X) M6 HFB3B:60 RTS
9 J# @3 G9 q- P3 x' ^' D
8 [& N% S7 b6 J接下来修改切bank方式:
1 ^* d" @' b5 X( dFB2B:48 PHA
2 P% q8 w( K- B. `2 H7 \% \) gFB2C:A9 06 LDA #$06
5 w* r+ a! f! _2 _5 I& m& }FB2E:8D 00 80 STA $8000
2 B. E% E5 A% M9 z+ ]) C* o3 AFB31:68 PLA
7 \' K( e$ L( Z; YFB32:8C 01 80 STY $8001/ w6 e& R" a) v' k7 }, `
FB35:60 RTS/ ]1 S- p! e `7 G
" U+ ~1 D, a3 A3 z4 \FB36:48 PHA/ n7 v8 i8 ]4 D1 b( p& g: z5 `% D) g
FB37:A9 07 LDA #$07. k1 S3 l. k1 \9 U$ n. H
FB39:8D 00 80 STA $8000 = #$14
1 C& f1 l( x- e+ tFB3C:68 PLA: P5 B; K$ e+ Q: q5 ~* [5 E+ y
FB3D:8C 01 80 STY $8001 = #$1D
8 c V5 v% L4 G S8 hFB40:60 RTS1 H0 G [: Y* c+ F& O1 G
# d5 o+ G7 ~" X4 C' W
还要把原ROM的对$8000和$A000进行写入操作的程序修改一下:
3 P% ~* F8 Q- V% t% UF989:AD 00 80 LDA $8000 ( u* I. `6 v$ d! G
F98C:8D EC 07 STA $07EC1 z9 J5 a' m5 A% E* [' ~* B
F98F:20 2B FB JSR $FB2B! F" W1 {: v7 Q8 O) ?9 O: _
F992:C8 INY: H. r T& _5 Q
F993:20 36 FB JSR FB36
+ X" S( ], [% d' j, I9 `F996:60 RTS8 r2 G0 ^5 T+ }' A) }: l$ P& D
/ [, u" Z- A4 l4 _8 y* x
再修改切VRAM程序:6 Q# k! v9 D- `$ z4 m
FACE:A9 00 LDA #$00
2 P. d! s4 m( _9 f: l3 JFAD0:8D 00 80 STA $8000- K, \. h$ D% D. ]9 G
FAD3:AD F0 07 LDA $07F0
2 I* r' r U; }3 R& j9 LFAD6:C9 01 CMP #$01/ T4 i3 _0 [! r$ ?; j! A+ ^5 B
FAD8:D0 11 BNE $FAEB8 r* ~# p+ h# O! b: A1 V/ [) k
FADA:AD F1 07 LDA $07F18 O4 S. |7 D; [7 S- X
FADD:C9 04 CMP #$04. Z( T/ K8 V0 p# S ^5 l& z- D
FADF:D0 04 BNE $FAE5! F+ t! I4 O: @
FAE1:A9 80 LDA #$80- ~3 E8 F" ~1 ~/ N2 N1 t
FAE3:D0 06 BNE $FAEB
8 l6 n3 Z" _3 B1 r- T/ DFAE5:C9 05 CMP #$05
+ S8 d- F$ `: S: V5 A! U2 g" MFAE7:D0 02 BNE $FAEB3 O* |$ o# @8 u
FAE9:A9 82 LDA #$82
" e: A. X4 m; Q$ ~FAEB:8D 01 80 STA $8001+ O1 r* |; Y' i* A: W
FAEE:A9 01 LDA #$016 u) S6 {* p; V) n: K4 q F
FAF0:8D 00 80 STA $8000
% z0 j$ [' j( f7 T/ \9 tFAF3:AD F2 07 LDA $07F2; r: s8 b: o/ W4 y3 c( ^5 ?
FAF6:8D 01 80 STA $80012 q+ a5 r3 G( v( M8 z
FAF9:A9 02 LDA #$02
' k/ X1 h; @* RFAFB:8D 00 80 STA $8000
# H8 V7 B( F0 ]# I1 I2 |* G4 LFAFE:AD F4 07 LDA $07F4
6 p9 T) o) C6 E4 h! x8 ~FB01:8D 01 80 STA $8001
# @! f6 g8 J$ \/ \8 r& u, IFB04:A9 03 LDA #$03
3 Z& A+ w* W: k; g4 KFB06:8D 00 80 STA $8000- b, ^+ _+ ^/ x& u7 m3 Z
FB09:AD F5 07 LDA $07F5
7 x* `: j; G# r( IFB0C:8D 01 80 STA $8001
' j# ~2 A5 N) H; q9 aFB0F:A9 04 LDA #$04
3 h9 y/ t2 g# V% qFB11:8D 00 80 STA $8000) y9 { _' w6 }* q( E: B d1 i
FB14:AD F6 07 LDA $07F6) N! k3 B j p! a* M
FB17:8D 01 80 STA $8001$ z3 p4 f8 R! e- \
FB1A:A9 05 LDA #$05
; F* X1 h( F- i. _( OFB1C:8D 00 80 STA $8000* Z- K! S) L8 l- W& M
FB1F:AD F7 07 LDA $07F7
+ b4 |2 _; v& ]5 NFB22:8D 01 80 STA $80017 v1 z4 B5 G* C; U; m" @
FB25:A9 00 LDA #$00
; U, R$ |2 Q/ E: zFB27:8D 00 A0 STA $A000; T2 h7 n& b/ E) p' p
FB2A:60 RTS( z: z: |) n: z& O, _7 L
; S" `4 h R- |) K; h h( S然后保存文件。
2 w3 w. a" t- {使用HXD修改文件头:
# f, `3 C: ~9 j6 x9 `$ Y+ C将Mapper 234 ~9 [ U% L8 s* }: p% c: x
06字节的高4位是Mapper号的低4位
m$ z1 l& ^5 P/ D! }07字节的高4位是Mapper号的高4位
D/ A2 F$ r# u$ N2 T5 Z3 l- Y" w组合起来就是0x17=1*16+7=238 Z) ]$ ~9 |5 S& T9 S4 {
$ ~) }* d7 y0 \0 ^1 W9 L' `) C修改成 Mapper 4( A0 W: y/ i5 q) ]
, p" ]) T$ q+ G% R" @ x. `
3 P. j8 O% s0 W! D* {9 g$ J3 P
. W% X) \! t9 c+ c& i再次打开文件:
* |; Z6 m' Z+ _: ~1 V, ]! g' q0 i! ?, X/ e" D
可以正常运行
& E1 H9 I) F7 j0 v& [3 W通过全面测试,发现出现精灵错乱:% _7 t0 l: x2 F+ j* c6 r; T& F
第1关:7 t) J& i# g3 ?+ a
( ^5 A0 o; W9 F) }
6 l$ ?% X9 O# ^! |$ I, |" P第2关:& y+ @0 j8 Q7 {
5 M0 s6 ]8 @2 V) B$ e m+ ^
任务失败后:! K7 p& Y% `3 \" P- y8 u ]
' x- ~# X5 Z: c, e, h8 Y; G' _通关后上飞机画面:* y* x" h3 s3 L
3 U7 |" D5 c, L0 s6 ^这是为何呢?) ?/ n% ~. w0 Z
这是因为Mapper 23 中精灵VRAM切bank是一次切1KB
, _2 b5 j: T7 H: C% d但是在Mapper 4中精灵VRAM切换却是一次切2KB,而且忽略bank号的D0位
( S! P: M. `1 q; I c比方bank 0和bank 1是同一个bank,同理bank 2和bank 3是同一个bank: I. q6 a: _/ ^' c+ }( e
也就是说
$ L* p/ s7 J: F% H( vMapper 23中的VRAM的
+ v6 y$ |8 n3 k) W, C0 ybank 0,bank 1,bank 2,bank 3
3 ?" B: `- n# P在Mapper 4中对应的是, y# t; O1 I- E* J& @; ?5 m9 ?
Bank 0,bank 0,bank 2, bank2
1 _" z; M4 I5 `然后查找原来的ROM的切VRAM的程序:& k) @; s2 R* p1 J, @( O! j/ V5 W
知道是从07F0-07F3切到精灵VRAM的:! m- i; L' l# C+ ~1 Z
如图所示:
, o( d( X4 A4 _# C& \
8 V3 A$ d. b8 n9 {) a
* X. T! ]" }9 H3 \! n作为对比,左边是原版,右边是修改。
1 y# V# f$ o! _& {9 v8 Z5 E接下来是完善VRAM切换带来的问题,因为Mapper 4只能切2KB的bank,所以我们不能通过切bank程序解决问题。
& i- J1 y+ M. r: }( T0 P. V5 O通过测试知道1,3,5,6,7,8关的精灵VRAM排序如下(07F0-07F3):
( J `/ n R2 h) F4 O) _' z9 d01 04 06 07
$ U* b- V, C" o2 x# K ^第2,4关如下:
; ?" b, M" r+ l# r- \01 05 08 09" o( @( ^+ U2 ^0 ^# p7 ], F- C) S
任务失败时如下:" a7 |6 a" T. d+ I! u6 u: x
32 00 00 1B
7 h2 U6 P: g# N5 @7 w l其中任务失败时对应的VRAM是07F3的1B,只要让07F2为1A或1B即可:! O5 u3 u9 O+ S8 C6 ~; u5 J
通过调试找到对07F2写入数据#$00时程序如下,于是修改C7E5的值为1A即可:
, O* ]! h: i% s; W8 S+ X. o- w2 @" R+ S- U' m3 N
转到ROM地址:
. {& W% Q$ ^2 e- p$ J/ f4 X# k. X
' Y( H' f" j2 r/ \0 x修改数据:
$ J4 T8 u k, j1 W
: R3 c3 L* F5 ?; h4 \# \3 `- }重新失败后可以看到修复成功:
. M3 L7 V# o* I, ]9 h: E! H' E( N' m( S
接下来是修复正常进行任务时的精灵错乱问题。
$ {( ?- h2 r3 q$ D8 E8 p首先运行Mapper 23版本,在1,3,5,6,7,8关任意一关的时候,将PPU导出来
# t( w' B2 v9 Q3 M7 a8 l& c, h0 m( I* X5 c9 y$ v' P# m
$ g7 V5 T$ `9 K* [+ T6 }7 {+ d% P$ u$ ^. E0 W' m* [" v- c
8 W8 l- d# A* ~2 t然后用Hxd打开修改的Mapper 4的ROM和刚刚保存的PPU的数据文件:
9 O* E2 Q. O6 K3 z: k+ e' E( a$ w3 I8 Y
在ROM文件头第05字节改为0x20:- @$ o! Y% M" f( ^, r( P) s5 L
% _ p( r6 P* f* u) B% @ p: m
然后转到文件末尾,插入0x20000字节空字节:6 S1 }% w+ {0 b3 V ~ E
3 Y3 P4 v- }& Z% f' @4 x5 e+ I( ~5 Z; V% T0 e
. @) B: ]( u1 D( l
! ?& E3 S! _& v0 I F! q: |然后将第1关的PPU数据的前面2KB数据选定:- P% h1 ]. w" k: S/ y: q9 f
& o- a$ r3 Y' Y4 i
6 a& v5 o; k# Z2 N
+ l" N# X! h" r9 j7 @, U* A4 }% m
复制之后以覆盖方式粘贴到ROM的40010,同样把第2关的PPU数据的前面2KB以覆盖方式粘贴到ROM的408104 k0 n4 B* l" i+ @+ j
# P) S7 \( Q+ {5 _
然后保存文件:
- l+ l6 D3 J4 T$ j/ C+ Y4 h f$ D" i6 X% U' D! h5 b
最后用FCEUX打开文件,添加07F0-07F3的写入断点6 R( v d5 @! m9 U- K8 i
) Q6 [+ ? C. @
地图预览后即将进入第一关画面时程序暂停了,可以知道此时准备将C793的数据写到07F0: J/ b/ ?1 o" i" ?
5 F5 r4 f) q# ?) |
测试后知道将C793-0796写入到了07F0-07F3:
# b. S' B* E3 z" h+ |" {. k; X2 K! {同理,经测试每4个字节一组,一共17组,其中01 04对应普通关卡精灵以及其BOSS关的精灵VRAM的bank号,01 05对应2,4关卡精灵以及其BOSS关的精灵VRAM的bank号,再加上一个通关后跳上飞机那段动画的精灵VRAM的bank号。
: o7 A9 z( ]0 P6 z& d- P) T4 ~4 V7 U. X8 N! c
1 q9 @' L: i% h$ c" N1 ?然后将文件中标记的01 04修改为 80 04,将01 05 修改为82 04即可:
/ y% I! J' \: T+ A. S4 H6 B" V( x+ d; { X8 `( V
保存之后重新运行后效果如下:
( \0 ^9 J" {/ M: M. w. K
4 T; e% C W" x6 o; B0 T' I" r4 ]0 j0 {- D" S. q# u
, y9 b8 ?! K6 x$ Z" T
当前使用的是FCEUX模拟器,如果用NEStopia玩的话一开始就死机了,这是因为这个ROM有文件保护吧,它会往$6000里写入数据:
( F1 D8 h3 x7 t3 R6 L& u9 [! M5 y1 \) e* U/ l
F863:A0 03 LDY #$033 O% x# q! Q# ~, k
F865:98 TYA
3 @! w ?. I# G D) HF866:29 01 AND #$01% U5 E* l2 z. [2 a
F868:8D E9 07 STA $07E9 R& |9 g) z9 x
F86B:8D 00 60 STA $6000- X& q: H. C5 w. l) P+ S
F86E:AD 00 60 LDA $6000! t, M- ?% j! I4 h& O
F871:29 01 AND #$01
2 Y' i0 M* x- hF873:CD E9 07 CMP $07E9
; `& h; G9 n; Z+ N; PF876:D0 05 BNE $F87D' N( w' l2 M5 F/ m
F878:88 DEY
9 W0 R, _) I- e6 hF879:10 EA BPL $F865
$ |2 E! b+ |3 @) L, c6 q" k8 b7 [F87B:30 03 BMI $F8801 c9 _8 z: g( i. U/ R2 U
F87D:4C 00 00 JMP $0000
; @* Z( K/ s8 B% n) AF880:A5 1A LDA $001A
- ~ [; x( w, W" k3 W4 c) pF882:65 34 ADC $0034
6 ^5 p0 V$ P/ k- O3 l# h( [F884:85 34 STA $0034
R8 y X+ b; x% k. W7 o( v' ]F886:4C 80 F8 JMP $F880
+ P$ \5 S0 D- n8 \先取Y值=#$03
% v4 E1 H3 H0 c0 v& }与#$01相与后得到#$01, ~* K* F' C/ E- P$ f, g
写入到$07E9
& y2 B& L d2 u+ z; v写入到$6000
, e+ E3 H# y, l6 S9 R6 v4 S再读取$6000的数据和#$01相与后和$07E9的数据比较) h# |$ s- Y6 I# X% N3 f5 Z4 M
不同的话跳过5字节3 Q, p) n1 K- t% P& c
否则Y递减
5 c8 R& [7 M! }& @: Y! ^为正数就跳回0x100-0xEA=16字节
& K- I4 ^; w9 U$ C6 C0 W9 M为负数就跳过0x3字节
) a+ [( l) ~' }0 Q$ w5 M8 \: I跳转到$0000(简直没有人性了,跳到这里死机,真想得出来)
4 m( m5 E7 P, H
/ K& t% e& T% D( a+ ]. r+ d正是因为这样,NEStopia运行FC时,6000-7FFF默认是不可写的,必须在ROM文件头第6字节的D1位置1设置ROM有SRAM,对于Mapper 4,还需要向$A001写入#$80来启用SRAM。- A, H" R6 u1 u/ J( O w
由于$6000不可写,因此想$6000写入#$01后$6000还是#$00,之后读取$07E9的#$01与之相比当然不同了,于是直接跳转到死机程序了。
, B& j4 J2 _* h' l/ c解决方法是把ROM中的所有的AD 00 60 29 01 CD E9 07 D0 05 88 10 EA 30 03 4C 00 005 |$ a! w, ]* V
中的D0 05改为D0 00,然后保存即可。
4 Q, Z0 j b, k测试完美运行。
5 k; _: Y2 n, {) R# i0 u4 F- h
8 H" Y& }2 G$ g4 ?+ O" w4 `" t5 p6 q/ ?! e, G- @4 D" x# p
教程到此结束。: U1 R+ c, g4 _3 @ U! P1 {
; O% Q3 S2 A! _' y5 O9 L2 C8 {3 d |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|