|
|
本帖最后由 yandagui 于 2017-4-16 19:06 编辑
/ r7 Y- {& T) [! m7 D2 f4 d
# M7 j1 q. L9 D( m n/ ]Mapper23转Mapper4实例教程
" F: \# H$ Y$ P0 V: |& j9 ^4 M' \+ l- H4 E6 |* B. b$ b, x
FlameCyclone 2017.4.14
6 |% y- ?- j) e& |
5 B1 ?3 h Q/ D8 K9 {先看看Mapper23文档:
- y% g j1 E/ w0 m m6 `" X
0 e5 h3 K) O' d' ]9 b+ o/ }Mapper 23
5 M7 {) }: Y( w) }6 Q
1 T: y" `; B2 |. x1 i$8000: 选择8KB的ROM存储体映射到$8000 r0 B _7 Z* @; v0 G' f, @
. b4 P+ z8 N9 d5 [4 ~* N8 p5 `$9000: 0:垂直镜像0 r7 l+ O+ W! c) v: u, V, {
1:水平镜像$ W& o. R2 q: O! H9 T% _4 P/ a
2:$2400镜像
# t- q& }4 I2 h% B. Z 3:$2000镜像
" f/ Q( q( N. V+ `- G6 y
6 c7 }9 w+ a4 I$A000: 选择8KB的ROM存储体映射到$A000: k' y) Z* F6 E; P
8 Y8 U# m3 m, R$ i/ w2 F& W! e% F$B000: 选择1KB的VROM存储体映射到PPU的$0000(低4位)
$ K! I% \' J8 \: q# q$B001: 选择1KB的VROM存储体映射到PPU的$0000(高4位)
) i* ~) b) V+ b7 j# T2 S% D" L$B002: 选择1KB的VROM存储体映射到PPU的$0400(低4位)
$ `7 D3 A4 i6 O$B003: 选择1KB的VROM存储体映射到PPU的$0400(高4位)
; s: x3 p' a8 D1 j' [1 n
+ V: d5 q2 Z, _" I9 @) `- m h; W3 i7 K$C000: 选择1KB的VROM存储体映射到PPU的$0800(低4位)+ e9 D7 [. \/ }! D! z' [, o
$C001: 选择1KB的VROM存储体映射到PPU的$0800(高4位); D/ n* p) y1 E, I. W% s) o2 M7 h
$C002: 选择1KB的VROM存储体映射到PPU的$0C00(低4位)5 h' T# _2 F9 ]: S% v. m9 `
$C003: 选择1KB的VROM存储体映射到PPU的$0C00(高4位)
1 Y6 o- S. f5 P' T* ~
; C) W. n& g' E8 m$D000: 选择1KB的VROM存储体映射到PPU的$1000(低4位)
) x1 x8 `0 V- M O0 A9 u$D001: 选择1KB的VROM存储体映射到PPU的$1000(高4位)
) w5 b: X, J+ U$D002: 选择1KB的VROM存储体映射到PPU的$1400(低4位)
+ f1 Y C" ~( o$D003: 选择1KB的VROM存储体映射到PPU的$1400(高4位)
* b1 r6 s( n5 X1 t l* _1 V' j8 n ]; d2 {
$E000: 选择1KB的VROM存储体映射到PPU的$1800(低4位)
4 i' p. i2 B1 O* r: h$E001: 选择1KB的VROM存储体映射到PPU的$1800(高4位)7 H) R+ _% n0 l$ h
$E002: 选择1KB的VROM存储体映射到PPU的$1C00(低4位)# x9 W0 h4 G' c. `" I
$E003: 选择1KB的VROM存储体映射到PPU的$1C00(高4位)
7 i8 @' b2 t! J) C4 x2 t4 w7 X& x6 [7 a$ a
再看看Mapper 4文档:
$ f- t5 m0 n7 }# I8 T5 ?4 U i7 l" b- y$ p6 q) i1 `
Mapper 4
2 H F; z6 u \3 m" ?
8 y, |- o2 `. S) r3 b1 o$8000: 模式号. e4 Z* K3 j7 [4 ^, W4 o8 }
位D0-D2:# L, \9 i: l# g5 H7 {
0:选择2KB的VROM存储体映射到PPU的$0000
8 Z- {/ u' @- @, t' J5 [. t/ v 1:选择2KB的VROM存储体映射到PPU的$0800
7 t' `, v5 T0 w3 a6 b 2:选择1KB的VROM存储体映射到PPU的$1000' V. l+ P+ E. \
3:选择1KB的VROM存储体映射到PPU的$1400
- F- ^+ E9 f% K6 t 4:选择1KB的VROM存储体映射到PPU的$1800
# F% a+ S1 g& |+ R& X 5:选择1KB的VROM存储体映射到PPU的$1C000 g9 _$ b6 y, T: F' H+ c6 } @- t
6:选择8KB的ROM存储体映射到$8000. C8 n' Z9 C5 v: M4 `3 |1 A
7:选择8KB的ROM存储体映射到$A0009 @, p- r' _2 v' I) k
位D6:9 m" K5 Y7 d& n6 {7 M
0:允许擦写$8000和$A0004 e1 I( N$ k$ ?" a
1:允许擦写$A000和$C0006 ]- Y; R, L; u- f
位D7:
" Y6 x& Y8 j) y* j1 J8 L5 q+ L: N 0:模式号D0-D2使用普通地址
2 y* w& z; C- C1 n' @7 [+ ` 1:模式号D0-D2地址异或$1000 S3 u$ g7 B' _
' u9 I1 N/ M3 ~+ s& N; W% `( ~
$8001: 模式页面号
/ ?9 c/ c4 _5 q4 h! t& L8 R9 Q" j 写入一个数(00-07),切换存储体到对应地址
$ T; U, ]4 M, {% L% ^0 v7 W, g& l( k) L" C
$A000: 镜像选择
( G: a/ E, ~( k! Z' ? 0:垂直镜像
! L6 N- b$ k3 ~ 1:水平镜像2 D2 t( ~0 N5 A2 O! Z, r
+ H# _3 l' i. ?
$A001: SaveRAM 切换4 e4 v% x4 W6 N& Q4 ?
0:禁用$6000-$7FFF' I2 q" o( h4 g. W" f9 M7 {
1:启用$6000-$7FFF; t- N+ _4 P( G8 F, i' I8 L% U
5 ` C2 J% M/ L9 }8 \- m: ^
$C000: IRQ计数器7 D; h1 F, K) D( |# _3 w
IRQ计数器的值存储在此处
c- E/ Y& W' l. m% |+ k/ O
) n6 M' p5 v: X% e$C001: IRQ暂存器; X( U# {9 p4 q$ W9 ^' e" ?
IRQ暂存器的值存储在此处
+ I, [2 [# r" O, F7 G7 u* B4 \
$ C U% C! U2 r% H& [1 e" e z4 X$E000: IRQ控制计数器05 D4 {1 t2 q5 b; A+ \6 c4 D8 N
向这里写入任何数来关闭IRQ,并从暂存器中拷贝数据开始计数,进入IRQ) Y( V& k8 e4 L# n/ H
6 n$ }- i" g* g: g$E001: IRQ控制计数器19 b' ~; `: n0 k; `7 k$ F
向这里写入任何数,允许IRQ(退出IRQ,允许下一个IRQ进来)
3 A! A% U$ V _% \/ b: [! q
+ H4 P! T1 p7 g+ N: C8 A6 a
5 d) W g# j) S8 }; F5 Z转换思路:
9 b5 b3 q. u+ Q1 R将Mapper 23 的切bank 方式和切VRAM的方式修改成Mapper 4 的方式。+ {% n) z- ?% n8 B v8 Z
: S: V' u" m5 \) T; k. t8 Q修改实例:
/ h, T: [' v0 ~7 j, hContra (J) 256KB Mapper 238 W7 R) v" k9 }- q2 Q7 h A! r
工具:) O7 K5 Z3 b$ F; {6 k
1.FCEUX 2。2。3 N7 `$ \2 A: y! W3 q
2.HXD
; Z/ C( C9 }2 h' c$ l先来看看这ROM的切bank方式:
X& M# R4 g$ N6 i8 D3 ~+ Q4 R# iF989:AD 00 80 LDA $8000 & z: D# Y( V; m; E O7 V) K
F98C:8D EC 07 STA $07EC% [- ~6 H8 _/ T! B
F98F:8C 00 80 STY $80005 e' m( w( F+ i# S) o
F992:C8 INY
/ _! O9 q/ O' Q/ VF993:8C 00 A0 STY $A000" T" ^" b1 O) F) Q9 |) I4 }
F996:60 RTS
# v/ f: T3 o; l- F, Q7 w
9 ?( O" k( \' E$ d2 \, [再看看它的切VRAM方式:
h* E9 n2 D" C5 A5 Q+ sFACE:AD F0 07 LDA $07F0
4 {8 J/ r$ M# dFAD1:8D 00 B0 STA $B000
^0 T4 T0 V" CFAD4:4A LSR6 c+ ]: K; K( o# M6 e/ @
FAD5:4A LSR4 a/ g- ]7 r8 z/ [' a5 e# ]. G
FAD6:4A LSR
4 H1 c6 M: L# UFAD7:4A LSR+ T/ z# `2 T) X6 b: ?$ T/ W! T. K0 j1 o
FAD8:8D 01 B0 STA $B001' X' U7 N- ]& G* v$ h/ Y
FADB:AD F1 07 LDA $07F1
6 ~) {; f; v9 `# v& OFADE:8D 02 B0 STA $B0021 K7 w, C5 O# A
FAE1:4A LSR) o4 R% R4 K' p8 k- X8 S* M6 X0 Z
FAE2:4A LSR
% x Y+ c* ]8 U3 Q8 cFAE3:4A LSR6 w7 d0 B. J1 J6 V0 u9 N/ y, Y" N
FAE4:4A LSR5 b# G& |* r j0 S v$ y
FAE5:8D 03 B0 STA $B003* k7 Q, o+ [5 t; Q" k( F8 o
FAE8:AD F2 07 LDA $07F2
% i- P, [5 Q0 N* }+ X* S3 U) XFAEB:8D 00 C0 STA $C000: N) ?5 B G, K& L
FAEE:4A LSR- a$ u7 H- w% L2 I9 W+ `. |! _; J* ~8 _
FAEF:4A LSR
5 |+ f$ N# ]+ y- Q4 o* H$ cFAF0:4A LSR; H8 x# _# r0 h& {% `, \. M
FAF1:4A LSR
' H: p& M# t- XFAF2:8D 01 C0 STA $C0017 t+ [% j0 j! V) Y
FAF5:AD F3 07 LDA $07F3/ J% H2 r$ |+ m4 p
FAF8:8D 02 C0 STA $C0027 ~5 T% u$ k/ j; `4 V/ n7 c
FAFB:4A LSR! h1 U; I. X" j9 n7 \
FAFC:4A LSR
, H: j5 ], Q6 xFAFD:4A LSR
; I# p" H# ~ \2 w) gFAFE:4A LSR
1 W: J: D& D8 W3 X9 QFAFF:8D 03 C0 STA $C003
/ [1 R! L. e; l; J' jFB02:AD F4 07 LDA $07F4+ J, q# R! q" {. V
FB05:8D 00 D0 STA $D000
$ B0 D0 H5 C4 s+ }. @FB08:4A LSR
7 n* l" m) {: S7 RFB09:4A LSR
1 }* h( o( Z% r/ o4 D) t5 mFB0A:4A LSR
, @! J: Z4 M5 s5 F7 l# QFB0B:4A LSR0 i" P2 C4 R V2 C9 E; h! I
FB0C:8D 01 D0 STA $D001# g$ j3 J& S! l9 j: a
FB0F:AD F5 07 LDA $07F5
, I3 |+ L) Y3 ^+ w2 G+ C( mFB12:8D 02 D0 STA $D002- |2 U0 _& E- @6 C1 k) V+ }
FB15:4A LSR' |8 w6 I$ p) s2 |
FB16:4A LSR
$ J/ \3 _/ L/ `" l0 o7 tFB17:4A LSR
. p6 Y" A6 I: M, `4 D, sFB18:4A LSR
) |" X5 j- N) IFB19:8D 03 D0 STA $D003' I( Z8 N# g+ h+ E6 [- y$ N& U, o: y- O
FB1C:AD F6 07 LDA $07F64 T) e( j: r1 K% G' R
FB1F:8D 00 E0 STA $E000
) W% y& B$ e) G# tFB22:4A LSR
/ v5 U) F& o" _ ?# M1 oFB23:4A LSR
8 f3 c O" w/ Y. kFB24:4A LSR
$ ^0 k7 z* ]# L) Z# t: l" vFB25:4A LSR
3 z7 Z5 ~0 n- h A% w4 nFB26:8D 01 E0 STA $E0013 @5 T# @7 z0 X9 x! C+ `
FB29:AD F7 07 LDA $07F7
I! |& p: S; Z; M! D) w0 wFB2C:8D 02 E0 STA $E0022 E0 W: g. Z8 ]; ^3 H: d$ c8 Z: \
FB2F:4A LSR2 K. O8 a1 X" X' S7 Z7 O2 C
FB30:4A LSR
( y4 R% g$ j& k) V6 p/ qFB31:4A LSR. C) R* J7 x$ a N" D* ?1 j8 d
FB32:4A LSR
- W6 h' n6 q% jFB33:8D 03 E0 STA $E003
* Y+ Y1 B: U$ \0 \! p% WFB36:A9 00 LDA #$00% a8 J: f$ b+ [9 j' ]1 g
FB38:8D 00 90 STA $9000
0 {# l @4 f* {% `! R. wFB3B:60 RTS' i9 N# r( E j. o; R
! h* V, q7 ~% f( S
接下来修改切bank方式:! a* B6 A4 g) b$ ~
FB2B:48 PHA4 ?8 f, |0 ~% [/ w+ t* n
FB2C:A9 06 LDA #$06
$ Q6 N7 ~: {7 Z5 K4 R1 Z" TFB2E:8D 00 80 STA $8000. `! i5 v0 ]: D
FB31:68 PLA
1 ?+ p1 f- |. a7 fFB32:8C 01 80 STY $8001
( K# g0 Y' o; `* T. XFB35:60 RTS; A" D. w: ^4 X' o
6 N# p" L- I+ @. eFB36:48 PHA
$ ]0 K5 n$ J' rFB37:A9 07 LDA #$07
4 | e( n# p3 O8 }! E2 |4 iFB39:8D 00 80 STA $8000 = #$146 ? Y' u; F* w9 S7 x
FB3C:68 PLA
" y+ [ _( E5 Q8 cFB3D:8C 01 80 STY $8001 = #$1D
5 z% h! B" \- a K# w9 R) T$ H( nFB40:60 RTS$ P* j7 o: J5 h2 T5 N( G& h
: \/ E6 w& V% h: n
还要把原ROM的对$8000和$A000进行写入操作的程序修改一下:
3 M! M3 Q. f& _6 E u" bF989:AD 00 80 LDA $8000 " M1 T7 G8 |1 i: ^2 i
F98C:8D EC 07 STA $07EC2 R1 L3 V, w# h5 q1 V5 F6 ~! \
F98F:20 2B FB JSR $FB2B, d; ]4 q5 g8 O0 S+ _$ r
F992:C8 INY
1 E# L* F' ]% I2 Q' PF993:20 36 FB JSR FB367 a: `* Y/ ]' U9 z* w& I) J s9 c* q" b
F996:60 RTS( s: x* Z2 v a
4 |2 ?& G( V7 N% S
再修改切VRAM程序:3 ^ ~* ]/ h8 q& W* y! \; R9 C$ O
FACE:A9 00 LDA #$00/ K3 U3 K" [- U$ ?& `7 ?& ?6 I
FAD0:8D 00 80 STA $8000
4 a% Y5 Z Z( j- t; Z7 E6 PFAD3:AD F0 07 LDA $07F0
7 R8 D1 d5 R: f! u! |7 PFAD6:C9 01 CMP #$01
6 B7 V/ Y/ ?0 Z' B! l# c. fFAD8:D0 11 BNE $FAEB
' U. T% y6 C/ H7 dFADA:AD F1 07 LDA $07F1
& [2 L+ X- c: {& P) hFADD:C9 04 CMP #$046 {5 c1 \, {% h" I" L( w5 z
FADF:D0 04 BNE $FAE5
3 w8 R3 c- v zFAE1:A9 80 LDA #$80
1 g* {) O! b& o7 `! E- QFAE3:D0 06 BNE $FAEB% k# n5 c3 L1 n5 R$ b3 P
FAE5:C9 05 CMP #$05
! T) o) z, j9 q+ R; H1 D% tFAE7:D0 02 BNE $FAEB
4 f: C. g, E0 I$ V8 H8 [; FFAE9:A9 82 LDA #$82& V |/ @1 g5 K* v7 F% \2 }6 D+ T
FAEB:8D 01 80 STA $8001
/ K" r6 |! b* B+ S; mFAEE:A9 01 LDA #$01( e0 e2 C/ ]6 y- W
FAF0:8D 00 80 STA $8000
* ~7 ^/ z( n8 i$ ~2 u; HFAF3:AD F2 07 LDA $07F2
) K" \/ `8 [- _- F3 D' j1 UFAF6:8D 01 80 STA $8001
8 S1 [) q9 u: x. K) q0 eFAF9:A9 02 LDA #$02
% Y; Q! q* T) g" T; b) i) eFAFB:8D 00 80 STA $8000- Y6 W5 `! H; m& F
FAFE:AD F4 07 LDA $07F4
; c! g) r' H2 ?+ {FB01:8D 01 80 STA $8001
1 A* @; y( Y6 g1 V4 l! ~4 uFB04:A9 03 LDA #$03
n$ f6 h' w4 K3 N" fFB06:8D 00 80 STA $8000
& k" Y. u% Q% m/ d, uFB09:AD F5 07 LDA $07F5
5 ~7 G' u4 y& g; {FB0C:8D 01 80 STA $8001
& P* F5 |& c$ m' q& ~) N" yFB0F:A9 04 LDA #$04# ?, b: g: v& f) Z
FB11:8D 00 80 STA $8000
1 z2 ?& k5 r4 s% d3 g7 {) y& eFB14:AD F6 07 LDA $07F6! s- s2 r0 N; O. o* E
FB17:8D 01 80 STA $8001
- B" I: T& x5 N* u. FFB1A:A9 05 LDA #$05
/ W* A7 v# \$ w: |8 N/ R V' JFB1C:8D 00 80 STA $8000
% H9 ]# B Q9 ? {2 a3 e" NFB1F:AD F7 07 LDA $07F7# \& w' z0 @+ @
FB22:8D 01 80 STA $80016 D3 L$ A& y0 H7 {& }7 J
FB25:A9 00 LDA #$000 G0 o& [8 F/ G# q$ a5 o4 K& b
FB27:8D 00 A0 STA $A0004 B" {! R1 w) n% p5 |
FB2A:60 RTS* s. b! [; V5 _6 Y3 K3 u% N
, ?0 Y7 o! \ `8 k2 t. V, r4 Y5 E然后保存文件。
( M% a7 K+ C* ]4 }: Y/ N使用HXD修改文件头:9 R8 A3 i! O9 h( _- g8 x
将Mapper 238 @$ s, u) K/ F' T1 B- M
06字节的高4位是Mapper号的低4位( @% @- w9 P( B5 B
07字节的高4位是Mapper号的高4位
+ X& l+ p( u( r/ H# ^! |组合起来就是0x17=1*16+7=23
7 m( D# y& C. X; R, z0 c( j% w. g
$ i7 t! X J3 s$ u2 Z( y修改成 Mapper 4$ \# w% A5 }: B# q# [' y( m' @

W5 K5 O) w# |/ D3 m3 |5 K
, N/ }+ [" S) R* q7 Z( ~* v! _
! n! ~$ D# t# j# }再次打开文件:5 Z# v. o& `- P+ G. b5 q1 ?) N

" H' Z5 r& i7 D* u, c可以正常运行
r$ m: g5 \" J X4 M通过全面测试,发现出现精灵错乱:
. i* d' z" a+ S. C第1关:7 D F6 z) p( N, u- y
: b0 U q% I$ P1 _
6 O$ O, \# j0 g: G, r5 F% }: n
第2关:
2 l" H% I1 L: M! P4 a; ^
) a4 j, ]/ H0 g' T/ S0 O; _! A, ~任务失败后:
9 Y; ^4 [2 S5 X% T
; ]! _7 ~8 `6 `6 l* g O4 c通关后上飞机画面:: D; X: N( l$ U

a/ @- ?1 h# L: V7 [8 l/ q这是为何呢?! E- }( z$ x( e- ` K& Y9 c
这是因为Mapper 23 中精灵VRAM切bank是一次切1KB! ~- E( m# @/ E
但是在Mapper 4中精灵VRAM切换却是一次切2KB,而且忽略bank号的D0位2 |8 V3 O1 ?! ]
比方bank 0和bank 1是同一个bank,同理bank 2和bank 3是同一个bank
' _+ N) d! x, t; R也就是说3 s5 I: C$ y+ }1 n& \& y5 l
Mapper 23中的VRAM的0 N1 S3 k/ u2 n( w, }9 H
bank 0,bank 1,bank 2,bank 3( B1 h: {4 \4 L+ _
在Mapper 4中对应的是: l! P9 a$ U( {. x
Bank 0,bank 0,bank 2, bank2
. I) ~& w, ?: r" a! I& q5 Q然后查找原来的ROM的切VRAM的程序:+ A0 k( Y! t h( `3 \7 f
知道是从07F0-07F3切到精灵VRAM的:0 \; P R- e2 A, U3 x0 V$ x
如图所示:( }% } S0 h. r& a- G2 T& v0 k

9 l" ~" i, R5 t8 x + j) l; m8 b9 c0 E Z
作为对比,左边是原版,右边是修改。( s2 \/ T! \$ T( s @! P
接下来是完善VRAM切换带来的问题,因为Mapper 4只能切2KB的bank,所以我们不能通过切bank程序解决问题。
3 P9 v- m, n! }$ U$ N通过测试知道1,3,5,6,7,8关的精灵VRAM排序如下(07F0-07F3):
9 ^7 v2 w8 K7 ]4 c% I01 04 06 07+ o1 f. s7 e( c3 O9 f
第2,4关如下:+ u. p! R' X: t1 m/ ?+ q. l
01 05 08 09! }9 u2 q8 N/ S/ v9 m7 F* ?5 ~
任务失败时如下:2 X5 D- V( J8 O4 t6 a( V
32 00 00 1B/ R, Q: C: ^( f) E# Q3 o
其中任务失败时对应的VRAM是07F3的1B,只要让07F2为1A或1B即可:5 F$ e& B- W7 H. N& O) ?* u
通过调试找到对07F2写入数据#$00时程序如下,于是修改C7E5的值为1A即可:. n! w A ~3 }( ~+ T5 ]- r" U! U: K

! A ~9 G) B7 s! @+ x转到ROM地址:
, {7 K( Y6 Q* o# W5 D0 ^# T
- B3 `; s5 L0 m1 Y* H修改数据:
3 i* M. \* L8 `; a - e, a* H1 u3 C; t9 F0 l
重新失败后可以看到修复成功:
. p+ s* R1 U/ p 8 E5 Y" ~& K, f( h
接下来是修复正常进行任务时的精灵错乱问题。9 j/ @- M( t2 `6 E0 {. m( z. A2 T
首先运行Mapper 23版本,在1,3,5,6,7,8关任意一关的时候,将PPU导出来
) T% i; Y5 i- |* a5 S
0 ~: l+ o+ g; i 5 v Z5 `' k3 z# B6 w6 A8 s4 x& X
7 ~8 G$ v* R/ C* T1 q! o

m" I! P/ l0 c- M5 k8 U% K然后用Hxd打开修改的Mapper 4的ROM和刚刚保存的PPU的数据文件:
+ S. \7 W' @0 Y
4 P$ y; n( } _在ROM文件头第05字节改为0x20:
' _5 [2 p9 A* j7 m! P8 b, d# [
% }* F: O( a! j& t然后转到文件末尾,插入0x20000字节空字节:; l( A9 C. e% T, O3 {0 y

, _6 K5 H. o6 b
`# _: T" q b2 k& W' X u( U Q5 i6 L
( I8 [# o; u V h# {4 G! R
然后将第1关的PPU数据的前面2KB数据选定:
2 b" c# g X4 b) F' L9 T
& }. _8 I" `7 y& P3 a9 S r0 a q + D' q! `+ a) S1 s
6 ^; @0 C! q$ Z
复制之后以覆盖方式粘贴到ROM的40010,同样把第2关的PPU数据的前面2KB以覆盖方式粘贴到ROM的408105 d6 _8 n N' d" x

# ?" \2 |+ \% K$ L# E$ V然后保存文件:
! r5 O# @3 r! Z* h, ]4 [, l5 X: j ) U2 t+ |# v# F0 _4 B+ X
最后用FCEUX打开文件,添加07F0-07F3的写入断点* _7 v: g. _1 p+ r& p- u! y
: j" J* [$ |: V1 T7 l
地图预览后即将进入第一关画面时程序暂停了,可以知道此时准备将C793的数据写到07F0:& R- J: p5 d: X

, Y! j# I, L" e8 J% r+ o测试后知道将C793-0796写入到了07F0-07F3:5 M! O/ W4 E6 e( e1 y
同理,经测试每4个字节一组,一共17组,其中01 04对应普通关卡精灵以及其BOSS关的精灵VRAM的bank号,01 05对应2,4关卡精灵以及其BOSS关的精灵VRAM的bank号,再加上一个通关后跳上飞机那段动画的精灵VRAM的bank号。
2 K2 N+ C8 P3 r
; V8 [( R9 l7 s$ O/ c7 i y) J . t9 V f3 A- x8 @( _$ {0 I& q9 n
然后将文件中标记的01 04修改为 80 04,将01 05 修改为82 04即可:1 J( g& A. H. i ^" D* L1 l

) [) D7 X; H3 L; }保存之后重新运行后效果如下:
1 |9 R2 K; }/ x0 _ 5 }# U5 n% o7 ]

$ \" D/ S, o% m
/ X( y4 \ l! Q当前使用的是FCEUX模拟器,如果用NEStopia玩的话一开始就死机了,这是因为这个ROM有文件保护吧,它会往$6000里写入数据:+ r4 G/ m: i0 m9 c+ A5 o! s

" \6 j, i; j6 n1 t) M4 I% ?F863:A0 03 LDY #$034 ?" Z1 T' {6 r& V/ I% G' z
F865:98 TYA; |& b4 i, Z8 t8 ^3 v
F866:29 01 AND #$01$ {% Y! b7 x" g3 A, h
F868:8D E9 07 STA $07E9/ R! s+ e1 m! n* P
F86B:8D 00 60 STA $6000
9 |2 | O4 d$ D' Y0 R, B3 AF86E:AD 00 60 LDA $60000 o! p7 u3 P1 d/ y
F871:29 01 AND #$01
( d- q, r7 x$ [6 a5 s ^F873:CD E9 07 CMP $07E9+ G, x4 `4 @: C$ h: r
F876:D0 05 BNE $F87D
' n2 A% J1 [9 o7 n; D+ M+ oF878:88 DEY" P( z$ \! u% ~, n+ `; ?5 ~
F879:10 EA BPL $F865
2 _0 g# }' S7 q+ }( ^F87B:30 03 BMI $F880
/ [$ T4 Q D6 }2 q0 ]F87D:4C 00 00 JMP $0000# u3 T; k# A7 m, \9 V
F880:A5 1A LDA $001A
% J; {5 c8 k6 c2 L, HF882:65 34 ADC $0034
# C' H9 T$ m" b8 iF884:85 34 STA $00340 l" d( H# C0 Y; |
F886:4C 80 F8 JMP $F880- _/ J+ b" q# T7 s
先取Y值=#$03# j2 C$ K5 y: ~% L. H$ ^( f
与#$01相与后得到#$01
; A$ v/ @, @& Z c6 R$ I7 J写入到$07E9
5 j* }4 T; c* _ ?) ]' q写入到$60006 ^7 X; t; D1 w& S# c Y
再读取$6000的数据和#$01相与后和$07E9的数据比较
+ W( y0 W0 F8 a$ w不同的话跳过5字节* \. x: ?. V- ? x, d# n
否则Y递减
: i6 q2 `# |4 p为正数就跳回0x100-0xEA=16字节$ g( ]) u( v5 ]3 ^9 P/ A
为负数就跳过0x3字节
7 _: J* t. p; g; J& v: E( E; A/ Z) ~跳转到$0000(简直没有人性了,跳到这里死机,真想得出来)
1 ]0 Q, c+ N- B
v {8 C/ L, |" ]3 h正是因为这样,NEStopia运行FC时,6000-7FFF默认是不可写的,必须在ROM文件头第6字节的D1位置1设置ROM有SRAM,对于Mapper 4,还需要向$A001写入#$80来启用SRAM。
/ x: A$ ~5 ?- g; l由于$6000不可写,因此想$6000写入#$01后$6000还是#$00,之后读取$07E9的#$01与之相比当然不同了,于是直接跳转到死机程序了。
9 K. }6 J' T9 m+ d: ?3 B* p解决方法是把ROM中的所有的AD 00 60 29 01 CD E9 07 D0 05 88 10 EA 30 03 4C 00 00
. B ?1 \8 Z! X( i1 e- p3 t中的D0 05改为D0 00,然后保存即可。: N* a% H% u% \4 V$ U! e
测试完美运行。
) i7 N. w, D/ L& l. o; g" g ! m) i+ @+ G6 N( x# f
+ ]5 o) e+ {8 D" s5 I7 \+ x教程到此结束。( q. [3 D( J( _; n
0 U5 T2 S% s: D# E6 m |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|