|
- ;[FC][Mapper19 IRQ]3 Y& d' X2 R' z5 A3 y1 {$ Y
- ;FlameCyclone 20230710
* O! K/ ^' L; I% m
8 R5 L! E" H C8 d/ @$ i: I- ;文件头& j! c) o- N/ E' c( M
- ;======================================================================7 A; X1 [) Q6 T$ {1 f X8 P
- .INESPRG 4 ;16KB PRG 数量9 M; W8 c& y' ~/ f3 V/ ^
- .INESCHR 1 ;8KB CHR 数量
7 b; [. p- T+ Z0 L5 H - .INESMAP 19 ;mapper 19
* t2 }3 h# |8 A8 x& ~% Z' s8 F - .INESMIR 1 ;命名表镜像 0水平 1垂直
4 [6 h" c5 w- z6 [/ q. t - " i5 A- g# r* o& i6 v
- ;必要条件7 }5 C7 v# o* C& i, S; B. q7 @
- ;1.持有CHR ROM
, E" z4 h1 j& m8 y - ;2.背景Tile和精灵Tile必须使用不同的图案表, 如背景图案$0000, 精灵图案$1000
1 D! I( F! Y7 a. B/ G1 F - ;3.精灵内存(OAM)不为空% C9 G0 n, z, U: t) ?9 e
- - r+ F/ K7 `7 E/ y0 y! t$ t# D
- ;==================================================
1 I& @- Q) X3 k. O5 X4 W - ;NES端口常量& v! D$ ~: I+ c5 m8 x" P0 Y
- PPU_CTRL = $2000 ;PPU控制寄存器# r* u6 e. }$ c. _: @$ Y" G
- PPU_MASK = $2001 ;PPU掩码寄存器
% e! D$ K5 M0 M7 d+ E! P - PPU_STATUS = $2002 ;PPU状态寄存器:读取后PPU_SCROLL和PPU_ADDRESS被复位,下一个写到PPU_SCROLL的数据是水平的,写到PPU_ADDRESS的数据是高位% P- k$ ?( S5 l; G
- PPU_OAM_ADDR = $2003 ;精灵RAM地址:用来设置通过PPU_OAM_DATA访问的256字节精灵RAM地址。每次访问PPU_OAM_DATA后该地址增加1
& Q' ]# U0 \) C5 a: }5 S: x - PPU_OAM_DATA = $2004 ;精灵RAM数据:用来读/写精灵内存。地址通过PPU_OAM_ADDR来设置,每次访问后地址增加1
( k N9 L" m# U1 p! H) c - PPU_SCROLL = $2005 ;屏幕滚动偏移:第一个写的值会进入垂直滚动寄存器(若>239,被忽略)。第二个值出现在水平滚动寄存器
6 b5 c. h8 g! i! A5 i. e7 E - PPU_ADDRESS = $2006 ;VRAM地址:设置PPU_DATA访问的VRAM地址。第一个写地址的高6位。第二个写低8位。每次访问PPU_DATA后地址增加/ K8 U$ n- N, K, L
- PPU_DATA = $2007 ;VRAM数据:用来访问VRAM数据,通过PPU_ADDRESS设置的地址在每次访问之后会增加1或32 # n' m) ?& F7 R* P
- OAM_DMA = $4014 ;DMA访问精灵RAM:通过写一个值xx到这个端口,引起CPU内存地址为$xx00-$xxFF的区域传送到精灵内存7 ?4 H: P7 k2 ^4 m
- APU_STATUS = $4015 ;声音通道切换
9 V6 ~' J/ e) E - JOY1_FRAME = $4016 ;手柄1 + 选通
& V$ j. @/ e* ~ - JOY2_FRAME = $4017 ;手柄2 + 选通+ Z2 f( ?$ a; r H7 z
- $ f; J/ j+ Y' z/ |$ X7 n* H7 `9 e
- ;==================================================# O/ n1 o/ u p6 Z, e- j+ D
- ;MAPPER 19端口常量
/ p+ G9 _) x0 V1 E - M19_CHR_0000 = $8000, G0 d" o3 B" Z! ]3 @. b; G
- M19_CHR_0400 = $8800& I4 S( ]/ O1 H
- M19_CHR_0800 = $90005 C3 `( @* ?- J. b1 n8 v
- M19_CHR_0C00 = $98001 T" P5 I, U; x" d4 P/ @; h
- M19_CHR_1000 = $A0006 J, x1 P+ ]7 E' v' l
- M19_CHR_1400 = $A800
# V5 V: c% o: v/ h+ Y: c3 G# z - M19_CHR_1800 = $B000
( H3 [: |, m! @ - M19_CHR_1C00 = $B8001 u/ R' Y5 U+ {* I% L8 T
- M19_NT_2000 = $C0009 ^' t# O5 U0 _3 H" z) B/ ]( a H
- M19_NT_2400 = $C8008 ~/ |# S4 ]9 i
- M19_NT_2800 = $D000, u+ O2 L. j$ l2 }" N/ B* {- C6 U
- M19_NT_2C00 = $D800
- C1 [5 o5 O' E. @/ [& q8 V - M19_PRG_8000 = $E000
9 Y3 ^# [; t4 `+ M# S - M19_PRG_A000 = $E800
* ?7 B: P. q0 s b$ e1 ` - M19_PRG_C000 = $F000
' {; J2 i* V( n8 n) Y+ { - M19_IRQ_COUNT_L = $5000
3 P/ l$ d8 o( G- h) ~5 L8 @+ a) \ - M19_IRQ_COUNT_H = $5800
6 x# ~& {! I# U5 K7 o. j - * g: u% V% e' w, |* m; _- C
- ;==================================================, D3 }5 R6 j9 I. P1 k4 l
- ;程序块配置/ F4 j! {+ O; ~+ f' Y. U5 \
- BANK_DATA_MASK = $07
% ~0 q$ w1 Q# G! W7 q+ s% f- z - ;--------------------------------------------------
. R& Y" n, @6 D. G - RESET_BANK = $075 v. g: `% f t
- RESET_ADDR = $FC00
; P3 v% A, P3 m; ^" a
7 Y7 d" p; ]. Q6 ^' G- ;==================================================
& W" }& K9 Y/ A; M$ r2 t - ;图像块配置
3 {7 u0 n+ G( m! z" p- E - CHR_DATA_BANK = $08
, _ W. P# U6 h. p& N) R7 g - / c4 \5 p! h0 h" I) c+ _0 c
- ;==================================================4 n# a$ }+ b1 l8 L5 d
- ;零页内存地址配置6 p- ~5 w& \ T0 D/ S& w! n
- Use_Ram_Addr = $80
; D' P& L1 I8 }/ O* x1 P - PPU_Ctrl_Buf = Use_Ram_Addr N# r2 \$ o/ ~6 G# M
- PPU_Msak_Buf = PPU_Ctrl_Buf + $01
{5 t4 I4 S( x4 _6 X - PPU_Scroll_H = PPU_Msak_Buf + $01: A. c, i6 c% j. n x2 Q+ B% K( }
- PPU_Scroll_V = PPU_Scroll_H + $01
3 ?1 ]4 C' l& U2 c - FC_Data_L = PPU_Scroll_V + $01. H: t# d5 L/ b
- FC_Data_H = FC_Data_L + $01
& f3 @# u. W3 |8 P5 O% i - FC_Data_Buf = FC_Data_H + $01
0 W( R* m$ a) R3 N - ;==================================================
3 X# j) X) Q" V$ E' D - # n5 F/ a1 T4 S3 n+ Y9 t( K
- GAMEPAD_MERGE_FLAG = $04
3 W4 I7 k! n. i3 a
% I# N& N8 K1 m- Gamepad_Keep = FC_Data_Buf + 1
% K$ G( ~/ d" j3 S: | - Gamepad_Once = Gamepad_Keep + 2
, i/ F3 G! y! r! y; O - Gamepad_Temp = Gamepad_Once + 2
8 T' L' F- c+ j" L- q -
W& v/ \. t Z {) c. s. Z. j - Gamepad_0_State = Gamepad_Temp + 2, b" z3 l5 h5 ~% r: ~
- Gamepad_1_State = Gamepad_0_State + 1
z# h0 d4 G! E5 ?9 a - Gamepad_0_Value = Gamepad_1_State + 18 r) N2 }# X( T' ]5 K1 N0 n5 T
- Gamepad_1_Value = Gamepad_0_Value + 11 p# M" W. Z# \1 z1 w
- Gamepad_Port_Value = Gamepad_1_Value + 1. z# b9 R- _3 L) `: }
- Gamepad_Merge = Gamepad_Port_Value + 1. t4 E8 R* b: G0 }* a5 Q6 Z% a% G3 n4 l
3 U6 h: ]0 t: N, q+ o/ P8 o3 ~- ;==================================================
8 x* V" y2 @- H/ A8 t- i; Y1 d - IRQ_Index = Gamepad_Merge + $01
2 g0 s' m. O4 g9 A - ;==================================================* z9 _4 R$ z" x! A
+ d# @ _5 j# H: w: e- ;CHR图形数据
- \3 O/ H8 Z- z - ;==================================================4 M, P3 P: M" t" G# i4 k" o0 U
- .BANK CHR_DATA_BANK
- [ D! Q9 b, y - .INCBIN "chr_bank/chr_data.chr"
, m" M, v2 Y* e% R5 q3 d3 ~- e - 6 n1 s" O( N6 F; g' A! r" k4 C* F1 [
- .BANK RESET_BANK & BANK_DATA_MASK( b0 S9 j1 b+ K. Y0 o
- .ORG RESET_ADDR: Z4 D! H& I8 l1 h5 |1 D4 h
- . ~) R2 w# h& I% M% v6 P
- ;--------------------------------------------------
& ^+ p+ O& S+ B e" I - Attributes_Data+ u' A$ t7 n: Q, \$ a. S
- ;命名表属性. I a' H( Z! P' [* @6 ]7 \
- .DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00! l% u6 {3 B) g- u+ K7 O
- .DB $50,$50,$50,$50,$50,$50,$50,$50,$FF,$FF,$FF,$FF,$BB,$AA,$AA,$AA) f' C4 d& p( E3 _% {
- .DB $0F,$0F,$0F,$0F,$0B,$0A,$0A,$0A,$AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA
! X) U- K7 q$ P7 B - .DB $AA,$AA,$AA,$AA,$AA,$AA,$AA,$55,$55,$55,$55,$55,$55,$55,$55,$55# l8 z+ K" h" q: L3 ~
- ;--------------------------------------------------: ]3 `2 O# U1 N0 M. k8 r+ ]8 W9 v
- ;调色板数据
?0 j* d) q2 t6 v d0 i - Palette_Data- m! |% ^# q/ I3 Z8 A* B$ ], p
- .DB $0F,$27,$20,$0F,$0F,$24,$20,$0F,$0F,$21,$20,$0F,$0F,$25,$20,$0F
" b3 m! @5 J. h$ n0 B - .DB $0F,$24,$20,$0F,$0F,$24,$20,$0F,$0F,$24,$20,$0F,$0F,$24,$20,$0F6 b; [6 X! G8 r* m3 F- a
+ o: m8 m; o t0 B& W4 F- ;==================================================8 m& o- Z( N# \- n, ?( j( o3 ]/ M
- ;命名表初始化
8 \- [+ ~' a: N2 W - Init_Name_Table
" z" M* i8 w: s* m5 I# R - LDA #$209 a0 U! }0 O- w( e
- STA PPU_ADDRESS
, E9 n- G& G% s1 J: ?; i) i - LDA #$00
0 L I2 Z6 ^; W B1 w2 J - STA PPU_ADDRESS
. i' Q: U# `3 Q3 `1 g3 s - LDA #$00 {1 p9 F* q& p& G% k
- LDY #$00$ S& \4 O0 v4 V% j6 Z& [6 ~$ p4 m! k
- LDX #$10
( `: |* \# D" y0 `5 N3 I - Init_Name_Table_Write+ ]. }6 x* A: I' L2 V
- STA PPU_DATA8 [/ h" N( l- j% Q8 G: V
- INY' d) O5 p. }: ?$ d1 k
- BNE Init_Name_Table_Write! D$ R l) N& [
- DEX# V. E6 S* \- x5 X, Q% l: G" ?
- BNE Init_Name_Table_Write
( `7 j" a/ n# B9 D - RTS& W, X9 E5 f# E n0 c3 @
-
1 a% B) P6 N4 X - ;==================================================7 C# Y% R5 S0 b/ c$ C- a; M8 \2 i
- ;调色板初始化4 A7 v8 v5 e6 d4 o V, ]4 T
- Init_Palette7 \+ j! m2 v) |, k6 T! d
- BIT PPU_STATUS
7 q( B# j+ H0 k2 K* }0 p4 A4 ? g C& K! W - LDA #$3F
7 Y( }, Q7 i! c. R: v, k! [7 [1 j - STA PPU_ADDRESS' h1 u& B2 }. @7 V8 r$ d( }: O: v
- LDA #$00$ k7 h$ N' Y! b, Z F; {% g
- STA PPU_ADDRESS% P+ s0 d7 h s5 p: S7 ~
- LDX #$00. w8 \# i- v) \3 t
- Init_Palette_Write
# i3 H9 {; u9 q' b* W \1 j - LDA Palette_Data,X
& ~0 Z6 d; r3 Y; D1 ^* H9 b4 C! I - STA PPU_DATA) M* z6 @$ A) H, X$ c: B+ G) S* R
- INX& N, o& ^; ?# n6 ?
- CPX #$20
' V6 i+ x" q& [. s4 T H0 U - BCC Init_Palette_Write% i2 Z, }# K8 [! i7 n8 r
- RTS
" l U# T0 R0 f -
6 Y* V& n" g! F( O5 J - ;==================================================
; @% ]* q8 ^/ |& D4 Q - ;设置命名表属性
9 ?. n* F- K7 |" @9 _ - Init_NameTable_Attributes
0 l! e2 @" b Y7 Y) K# S - BIT PPU_STATUS
6 E! ?; B8 @0 o6 I$ X' L! B - LDA #$23$ V H$ G, q( i
- STA PPU_ADDRESS. f2 K: B3 ^. r. F
- LDA #$C0
4 @: Y- T- |- o2 D - STA PPU_ADDRESS$ W) T7 F7 d; U6 L
- LDX #$006 Y. H* d7 U6 \1 p' c0 X. A
- Init_NameTable_Attributes_Write$ l3 n5 b. R+ J6 u, Q+ s
- LDA Attributes_Data,X8 i Z" F# N6 G* `; N4 u: B
- STA PPU_DATA
d; ~& f6 ~8 c$ L5 o - INX( v7 |) X2 Q% S! d
- CPX #$40
4 g" B, P3 u5 b, f- N - BCC Init_NameTable_Attributes_Write
: i1 y, G+ g/ q& ^- }! o0 |3 h: ~ - RTS
- A% R7 _2 h' }4 X/ t - 2 c1 t( L; d5 M+ \1 b
- ;==================================================) G$ m; F7 c; O
- ;初始化命名表文本 u# L( O; {) p0 k: P0 }
- Init_Name_Table_Text
$ \! ]7 u6 x0 d/ U5 f - BIT PPU_STATUS% h( z7 P6 \% K/ p+ i7 C" K3 E
- LDA #$20: ^+ f8 g; x9 o& H) ]1 i$ t% T
- STA PPU_ADDRESS' a/ S/ O; z+ g n0 U& `+ I
- LDA #$00
" \/ S P0 o: H9 e% P2 S2 D' I$ m6 m - STA PPU_ADDRESS
2 d) W1 E/ ]7 b- I" [1 z+ q - LDA #$00
4 l3 f5 A* S+ k - STA FC_Data_Buf
; _% q( h* Y5 \6 E8 k' g( [ - LDY #30
- I2 Z1 n' I" N' k2 [* h6 y7 T - Init_Name_Table_Text_Write3 }0 U4 e, _, @4 h+ z5 Q0 ] W
- LDX #32+ w# X y3 `- Z! c
- Init_Name_Table_Text_Write_Char: W- Z: V) Y: _, e! K- Q
- LDA #'0'
7 V E7 m) m* I5 ? - CLC
. R) q* _" a/ ?" M - ADC FC_Data_Buf
5 v! S% h3 B1 E7 R! X# R: E - STA PPU_DATA, `6 f v1 y+ t' X) Y
- DEX
) i$ K% ?8 l: X/ g - LDA #$14
5 n& m8 y* `! k R' ?# Z - STA PPU_DATA
: ~3 u7 E' j- D5 W( R; W2 u - DEX0 M" k3 W! r. E6 m; M
- BNE Init_Name_Table_Text_Write_Char" l1 E; n9 r2 p4 l
- INC FC_Data_Buf
6 z5 Q. U3 K, f5 X' {" k - DEY
, R8 i. \5 i( F* ]4 K! w# | - BNE Init_Name_Table_Text_Write
! P9 x9 A* u* F# i5 C5 l - RTS. L. l) j; _# V
* N5 w- I* c+ k- ;==============================
/ @, R6 k3 u& B& \. N& f$ | - Init_OAM_Ram;初始化精灵内存: [; I9 E* {. n6 \8 z* O3 Y) f
- LDX #$00 X% H( C8 X% T2 {3 k# l- D# s6 S
- LDA #$00& E% w. u$ S6 Y" K. p& d, ^) f! Q# p7 x
- STA PPU_OAM_ADDR
. d# l/ w- \8 S' x - LDA #$F80 q2 C) r4 ^4 q/ w- \$ v1 c: k& c) i
- Init_OAM_Ram_Write) G% ?8 m5 z4 o/ T
- STA PPU_OAM_DATA
# Y" B6 [9 o2 F - INX
l0 a9 N' C2 B! g9 [ - BNE Init_OAM_Ram_Write
6 l5 y( I* f+ i9 d - RTS
- A; O n3 \' E5 X) I( t6 Z -
0 H4 `/ t* s/ U3 x! j9 }# L - GamepadProcess;手柄处理
- D) E2 c5 z& d2 ?2 c8 N - JSR GamepadDatacan+ L Z3 i: C6 l' d f* H
- LDA <Gamepad_0_Value% F. t0 a# R: m" Y: n5 D' S
- STA <Gamepad_0_State
, h! ~+ w; \( j( V5 G - LDA <Gamepad_1_Value
( c( q4 Q7 F, X f/ b4 D - STA <Gamepad_1_State# Y; f; o7 V! x+ D
- JSR GamepadDatacan- q0 b' v: B. w- f3 @, _
- LDX #$01& P7 |/ ~" f" ^" M2 ?
- GamepadMergeCheck;合并手柄输入检查
7 W: `2 `0 Y: Q3 ~. I1 V - LDA <Gamepad_0_Value,X J. T/ p) U. Z/ a
- CMP <Gamepad_0_State,X6 W( Q5 s7 L7 r* x+ `3 A
- BEQ GamepadMergeInput0 J# C. g& r% p# ^" S' i2 K# n
- LDA <Gamepad_Temp,X+ b P ~4 y+ j4 G- C
- STA <Gamepad_0_Value,X
3 d3 Y+ R) Q* h& f7 @% W. [0 g2 f - GamepadMergeInput;合并手柄输入
# c4 N; W2 A& _* c - DEX
; U9 b& m" `- _8 R& i3 q" y& n9 U - BPL GamepadMergeCheck0 D! a3 N+ v K: ~
- LDA <Gamepad_Merge4 Z- h! ?# Y# @: t4 c
- AND #GAMEPAD_MERGE_FLAG% K* o- S6 t) y8 A2 v0 F5 Q; k
- BNE GamepadStateProcess/ r* ^- ]4 u& B1 e6 |
- LDA <Gamepad_0_Value; B& @5 W: W; P
- ORA <Gamepad_1_Value
1 M, h! {. L* E7 X - STA <Gamepad_0_Value* E5 o h `2 @7 T' i% l2 s8 t
- GamepadStateProcess;手柄状态处理
* {6 V; M$ \6 ^6 ] - LDX #$01- `+ U9 ^7 F7 A7 e: K" E
- GamepadStateSave;手柄状态保存
( N) m6 h- `0 n1 } - LDA <Gamepad_0_Value,X$ R& t& y* |& V, D- _3 X1 v
- TAY0 a8 A \, S* O2 M4 W$ k6 [2 V
- EOR <Gamepad_Temp,X3 ~' }0 r+ y9 \
- AND <Gamepad_0_Value,X
9 {5 X- W4 M4 Z" g! ^# A) r' S - STA <Gamepad_Once,X
6 c g% A: L% f) X4 @6 k - STY <Gamepad_Keep,X
$ \. f+ g# C7 ]% C! o - STY <Gamepad_Temp,X
/ n v/ D6 J: I - DEX
+ J9 _; ]( S( i, M - BPL GamepadStateSave
: J# O4 ]0 G& q4 R% A - RTS4 M4 b" {, K7 {, ~
7 T) ]9 N' P$ d0 A0 M6 T- GamepadDatacan;手柄数据扫描6 m& M- k$ q7 d$ ~
- LDX #$01
$ U3 z. X, l3 l/ t: | - STX $4016# q) C, R4 G) ~: n) g( L6 \/ G
- DEX
+ H, s: z( e; }" f& v - STX $4016
! n6 M* _0 w+ s8 T - LDY #$08
3 C# L5 g- F4 [. ~. K- m) n - GamepadPortScan;手柄端口扫描
) U5 S0 T) B. u" ]" D; ~/ J - LDA $4016
- ~+ d) E8 s. V0 @3 @2 O - STA <Gamepad_Port_Value
: v) j* T9 G1 y7 Y# A" {9 O - LSR A; U% B6 \8 t7 E& [ _- L: @
- ORA <Gamepad_Port_Value
) l) M, @( v3 t7 c4 ~ - LSR A
& S1 S" e2 X! T9 x- ` - ROL <Gamepad_0_Value8 ]+ c$ N- l# X
- LDA $40177 b2 j& f6 K& X4 G! Y
- STA <Gamepad_Port_Value, `7 y8 g7 f, ?! h
- LSR A
' @9 {6 C5 w9 o w5 u5 d! w- _ - ORA <Gamepad_Port_Value6 ?; ~' ]" W" B( B
- LSR A
$ C2 `( h) ?# C) ]' s4 F; F - ROL <Gamepad_1_Value& U' t! y! u% z% U( w: L$ m+ ~, D' [6 k
- DEY
. a6 M& n5 I9 i \% G - BNE GamepadPortScan
- S- G' K/ l. | - RTS1 _2 Z, j0 Q2 E! D
-
. G+ B! g& t. Q - ;==================================================
9 l4 f1 s3 A8 G9 D; ? - ;PPU处理
" Y8 P! r" X5 F* Z2 l" J - PPU_Process2 n8 |0 n, E1 y3 q( M; x) k: ]
- LDA #$00, l+ W8 h: t6 ]9 u/ x8 e
- STA PPU_MASK- H0 C9 M1 v5 o
- % }4 Z3 C1 b$ N ~
- BIT PPU_STATUS
6 T, L5 i) M0 d m - LDA #$20
& D9 ` w. _) H: H. ^( W% d7 t - STA PPU_ADDRESS
9 a' s# M; f$ d( [+ L5 p - LDA #$00
1 [$ t) n: L7 t7 u& N - STA PPU_ADDRESS
; z; J% K- O% |- T/ H a -
; u; ?, J8 U' G - STA PPU_SCROLL
% }2 v6 K! I- n( q9 o# d; W - STA PPU_SCROLL
c8 {% A1 ]: D; b# h8 p$ ~# J -
& H& S; R" B( o8 y - LDA PPU_Msak_Buf J, x3 u/ D7 s q/ A
- STA PPU_MASK
* F3 n \+ W9 M+ }- q7 D2 Z; I! ` - / ]) a& K& k# `% G, g
- RTS
$ @! _) C* }# m. h A - * Y6 X8 E) M7 ]7 X4 @; I6 E
- ;==============================
; K% g+ A8 Z9 Y* H# Y. S+ Q9 k - Time_For_Vblank;延时等待
# Q- F$ [9 e& a$ ^ c+ P+ U - LDA PPU_STATUS
, a g) E$ I& S. t5 k3 w$ M: {. d - BPL Time_For_Vblank
* a' @* V- `# q2 B# c - RTS
! ?& `: }, M! l$ Z* X - ) h4 P* E7 d: r5 s2 s! J( r
- ;==============================$ k6 a2 E7 r1 V9 A" W% n
- ;初始化MAPPER19
C$ a/ X( F% _* p8 J - Init_Mapper19
( F7 ]4 M' T* U6 R' r - LDA #$00
: m) y1 M2 _$ e S% N - STA M19_CHR_0000, W: ~1 y1 ?( S& J1 q$ Q# {4 \, a- l
- LDA #$01
. w: _4 @2 j M. m6 t1 ]9 F) k - STA M19_CHR_0400
( L% d7 W" G, Q: K' p - LDA #$021 W- F" X n: R+ E) w
- STA M19_CHR_0800
2 f5 g! l3 f/ V, E } - LDA #$03
@" S4 M9 I- ?- H8 ?5 n, x; v - STA M19_CHR_0C00
1 k: ^* @' N: u! I7 T0 _* s - LDA #$04
H a9 a7 S* v7 [: H7 a, z1 X6 Y4 Z - STA M19_CHR_1000
8 h# T! R7 w- H" a) o% `7 C8 v - LDA #$05
0 T( T. Z% B' Y3 F. @1 ~ - STA M19_CHR_1400
' Z+ s5 N+ P }7 t9 e6 o7 D( Z - LDA #$06
4 [6 i; @: Z. t: X - STA M19_CHR_18004 `# N9 W" h4 p3 t/ {+ c5 ^2 r
- LDA #$073 A$ d4 @. p& {; ]
- STA M19_CHR_1C00
: c+ b6 u4 y3 p& P9 e -
0 P% U* Y! T# ?( e' u - ;禁用IRQ j. X1 I$ O0 D6 v4 e
- LDA M19_IRQ_COUNT_H) ?2 l5 g" A3 K! t& O& y
- AND #$7F% E2 a) M% k) ?3 A0 k0 e' ~
- STA M19_IRQ_COUNT_H
$ Z8 a* [/ [# {9 v, E - ' X2 T# x; K% Q. h% F
- ;命名表& D( o3 M+ R/ w; Z) Q2 Z
- LDA #$E02 U7 R8 n4 Q0 B$ |# K
- STA M19_NT_2000. z; Y& ^! m5 L7 B
- STA M19_NT_2400. m! q0 A5 @9 p7 W3 n0 T
- 4 I" Y2 C3 a4 \/ ~. x# ?& @# e4 x
- ;命名表# a" z5 K1 q2 M' ^9 C! h* Y R6 I! r
- LDA #$E1
: _; I! w- G8 g. ] - STA M19_NT_28000 |' [7 D- @5 }5 d# ?% _
- STA M19_NT_2C00
/ q5 F% Z* s* a! r* S7 q - " [3 `/ E' w# F$ G
- RTS0 s% l! o, [. q. n
-
5 M8 k% M- s" i - ;==================================================
) l- m: H% e8 f( z# h - ;重置中断处理
; l/ G* d( V Q: D - ResetProgram4 Q, s! J# z j& j
- SEI' ~4 A7 r5 _' q1 H/ x3 _
- CLD' r- ^/ o8 W+ W( N4 Y0 L
- LDA #$00
2 q% a7 T" |5 X! ^$ J9 a. j - STA PPU_CTRL- D7 j; H/ x" u f! I. j
- STA PPU_MASK
: E) R# o1 w3 ~4 d& O+ N V - STA PPU_STATUS" `+ K# V1 @1 _# @9 B* |: M
- STA JOY2_FRAME
) c# P! D/ [! E { Y8 O4 u - STA APU_STATUS( A5 K8 [( }1 v/ Z& \+ _/ C+ q
- : Y5 j; a& x5 l+ ^/ X
- LDA #$C0
% j- D9 V$ y4 z5 T - STA JOY2_FRAME+ _% g8 x2 i* C) h
- & [2 Z+ A6 ?# i1 z
- ;等待vblank
0 G- q" t! B2 k. L- A - LDX #$02# u- J2 m) T0 |5 W8 J! V( |
- Vblank_Wait_1: N0 D5 w1 P- G6 g7 v
- BIT PPU_STATUS
7 F# l6 w6 [( P3 V4 N- M' m - BPL Vblank_Wait_1
, _9 \" E, u- d8 q, j* _) y/ a - Vblank_Wait_2
; Z( }% _+ y6 T# X! Z, V7 ~ - BIT PPU_STATUS
' r2 X- _/ K$ @2 f. F& X$ f/ T - BMI Vblank_Wait_2/ S" s( P4 j) V6 F, g
- DEX
" @7 w# F/ |9 q+ q& T/ S - BNE Vblank_Wait_1' t; h0 x" G- G3 d2 Z$ S6 y( I
-
8 t' q2 d: E( b c- }9 p2 n j9 [ - LDX #$FF" E; y1 q3 @6 Q9 M& \9 h, ]4 m
- TXS
0 L4 A6 U+ p) s -
' e4 c9 l, Y0 \. A - ;初始化MAPPER19- n6 R9 E! O' t
- JSR Init_Mapper19 d# b0 W: h! {" }
- + ]) a& M. Y$ u: A7 W/ E
- ;==============================) I0 ?6 i# W4 `4 q) c" [* i
- ;RAM初始化' T7 E" l/ L5 T" u% k9 _$ c! S
- Nes_Ram_Init/ |- k0 W# O7 T- F
- LDY #$003 v5 \6 J& E4 `- v' v2 f
- LDX #$088 D. ~1 X# K% G! g/ w) u
- LDA #$00
& [) |. D7 l0 t# n: T" w6 j - STA <$006 [" Q( }, y: K# z0 r. P& H
- STA <$01
0 d4 F+ Z, ^+ O7 m0 v. Y - Nes_Ram_Init_Write
- m+ c+ @( s: ~5 U% O - STA [$00],Y: F; `3 q0 D) r7 j2 k
- INY# Z) f. N6 i, e) I9 C
- BNE Nes_Ram_Init_Write0 E* }3 g. r8 B3 a$ r8 M
- INC <$01
; n( l0 d6 [& G" @) W7 x2 U - DEX# P$ a1 c. ?: X2 X, M
- BNE Nes_Ram_Init_Write
1 v& \4 f/ C+ R3 P- j6 e9 C, f - ) `1 P% F8 F2 {, p
- ;初始化命名表9 ^( ^! j' l$ O1 e1 @" f7 B8 X) B% H
- JSR Init_Name_Table
+ j7 A s e- k7 z( | - 5 y' X- }8 v. s- p
- ;初始化调色板
, d( H) y; M$ h5 {. D - JSR Init_Palette
3 T9 ` Q5 m" h% Y% `1 _4 Q' C - ) }4 T) M2 H6 {% m8 m+ G5 K
- ;初始化命名表属性
1 g& C7 [' p, L" C% c1 y" ? - JSR Init_NameTable_Attributes
, c3 d, r. N) O+ o( T - + x/ d4 M9 p6 X" i
- ;初始化精灵内存9 b" L2 @5 t0 E* U8 O$ W. X
- JSR Init_OAM_Ram4 Y. f2 `! ]9 h0 Y
-
9 j4 ]. c: R [4 f4 Q - ;在屏幕上写点东西5 _. {% b$ R5 x/ a# Q
- JSR Init_Name_Table_Text
4 K+ l- V5 i3 n0 p/ Q" ]! u - & P& t7 e) t$ T' Y9 j
- JSR Time_For_Vblank; e( ?# { C2 ?2 E! N) X5 t: o
- ;开启PPU控制
1 r Y( i3 v) T! g* o* O - LDA #$A8
' b( |9 S, H+ }; z - STA PPU_Ctrl_Buf' O' m, i8 }* ^8 Y
- STA PPU_CTRL; R/ @3 W& s: d8 H$ P, ~
- ) R, ~( B! v2 a1 |8 k4 s
- ;开启PPU显示
+ E, ^. I9 h% Q - LDA #$1E
) P! ~6 w0 f' a+ X: j x( L2 w1 S' V' d - STA PPU_Msak_Buf, C# i) W/ R0 L, s2 J
-
7 Y; e9 d' ?6 }+ f - CLI
: B: j' _& ` N( O% z - JMP Loop
5 w1 I" s' S6 a -
# G0 u# S0 k, l: {) H f0 y3 e - ;==============================$ P# s7 ^9 m: K
- ;死循环, 等待NMI中断
2 k: m: U8 m A$ L$ g! W - Loop# t8 t/ F5 q: s+ G8 I) U
- JMP Loop, P' j+ V! P, W, B3 V. N3 w
- " o' c! S+ {" ^4 N. |* t7 Z, n1 W
- ;每行扫描线1789772.5Hz / (262 * 59.94) = 113.967
2 X* p5 t8 b" g5 _3 q0 b$ ] - 5 O5 U' Z! K$ m! m9 E
- ;BEGIN_LINE_CYCLES_START = 32768 - ((260 - 240 + 16) * 113.967)9 J, h6 O9 M: N$ q5 N
- BEGIN_LINE_CYCLES_START = 32768 - (4103)+ t# P8 Z' T& q/ U: y) l
- ;==================================================
% X8 O8 s3 w' w) g- ]0 @0 I! Q- P ]. S - ;NMI中断处理% p% G7 J2 g) q9 y" J( F$ k
- NmiProgram5 Y4 H. \5 l3 D% Y7 J9 o
- PHA# g9 ^# M- C, ^. D3 s
- TXA1 Q5 r0 `0 ]% R& F$ G
- PHA
7 ?9 P+ f7 I/ @5 {5 i - TYA( K2 b' V7 l' A5 @: N7 X
- PHA; `6 m, `0 |: D' J, `6 y8 |
- # I& x% I& \9 S
- BIT PPU_STATUS8 O# q" Y6 W: ]2 v% ~ h
-
5 u7 U3 j. Y- w P' }* w - LDA #$00
2 ^% i) [6 r" i" V4 [$ T - STA IRQ_Index
8 H; S0 t. ~2 W! i @% V -
4 a/ x! n1 u1 W - ;Mapper 19 的IRQ是基于CPU周期的, 为了IRQ稳定, 首先开启IRQ, 避免PPU处理周期不稳定导致IRQ抖动6 a8 h: j8 F. k9 ^# u! Z4 e5 R
- LDA #LOW(BEGIN_LINE_CYCLES_START)3 W' ?! O/ t! q; u
- STA M19_IRQ_COUNT_L
+ a1 V6 @; Q8 I# m3 a4 _4 A - LDA #HIGH(BEGIN_LINE_CYCLES_START)0 M7 s9 x9 g+ n9 O! B: e) W) N
- ORA #$80) O$ \! C) C* \9 e0 d
- STA M19_IRQ_COUNT_H9 \: ^! X! o5 U" o- \
- CLI- E. T5 h* j' x6 X& {0 G4 c% J8 e2 b% ^
- 0 _% Q4 o$ j2 O# m
- ;关闭PPU控制6 ~- H8 ~5 s. E, C S
- LDA #$00
; ^$ a' T5 Z1 _& W - STA PPU_CTRL" T2 t0 E6 @& m h; I
-
, p' O9 i* Y" q# k, p3 A6 E - ;处理PPU( a4 Z. @6 N6 Y2 v
- JSR PPU_Process
. ~- i3 U% l0 y$ I4 f$ l/ r - ! x0 Z/ t7 F, w
- ;开启PPU控制
% Q" E$ H p6 ^9 M - LDA PPU_Ctrl_Buf
1 g, ` u4 o, [' v - STA PPU_CTRL
6 P9 M7 b" E' K1 @) @ - + }' g- c6 H! ^9 M
- ;手柄处理
; k, Y. d+ Y0 z, `/ M2 ` - JSR GamepadProcess
( B9 E0 E: u) @4 [ - 9 Z" J* u: y/ s4 _, \: R% h; Z; a
- LDA #$00
6 ~. j! y( I A" c - STA IRQ_Index
7 f- C$ \3 R c' |9 c -
- o e7 K9 B6 B. q2 h9 p - PLA) ^7 x! f0 D7 m6 B0 }
- TAY
8 q3 w- M& K1 e# d - PLA3 k: E: w9 M5 j6 i" R
- TAX
* e8 B0 Z% b& C+ S - PLA
+ g# G3 R! T0 Q l2 r - RTI
! {/ R* l& G9 g1 j# d
1 X) _% P. M; G9 n( P& }- ;每行扫描线113.67. r. C4 N0 t! L% K" A5 k
- ;BEGIN_LINE_CYCLES = 32768 - (16 * 113.967)
5 z; H! t0 W/ K" G# P. L1 f - BEGIN_LINE_CYCLES = 32768 - (1824) + 27 + 7
' Y: u( N9 Z1 F" C; l - ;==================================================
. L% ?* q( o# H( v& L - ;IRQ中断处理5 B- }* ?% D9 q l) J- N
- IrqProgram4 q- m1 p* ]# P+ D. t
- PHA% e3 c! I- m' z
- TXA
; ~+ l0 ]$ A# j1 k7 J, x - PHA
+ R+ L0 L1 k" ?4 m - TYA* W7 m, N+ y3 X( T
- PHA
( b% |2 \" v" H -
) g; N" ]% K6 u- ~# {" ? - ;16条扫描线后触发IRQ
& I' g5 k4 f) B4 O - LDA #LOW(BEGIN_LINE_CYCLES)
" @" h% K: V! [) M& }6 y: b# k - STA M19_IRQ_COUNT_L- ^: u2 ^$ d* w( _5 e* Q
- LDA #HIGH(BEGIN_LINE_CYCLES)6 K! Y" i' t* M
- ORA #$80# G$ y( I( r8 U; W, b7 v
- STA M19_IRQ_COUNT_H) X. j. X5 {& ^: M5 @; Y) T
- : ^" M6 j& W' e5 M, Z4 |
- LDA <IRQ_Index
5 M+ m4 H; v( a/ [5 ^+ {* ?3 T. a - BNE * + 4
$ V" r3 w1 O$ `$ _8 B1 G( _3 }6 T$ G& H - INC <PPU_Scroll_H/ j) J! K. h$ t* ?" \
- 2 d$ H8 H' \- ]. ^: i
- ;设置屏幕滚动
" \% t& r3 y" f# b - LDA <IRQ_Index0 a+ h$ C+ s6 D! O
- AND #$010 [) Z0 g% u+ @4 b3 e0 O4 u v
- BEQ Irq_Scroll_Right
8 Q$ t; e! T+ ]8 z3 R8 t) p
7 H/ {' `* ?' z/ N$ @& G- Irq_Scroll_Left6 ]" s: w9 R8 ^9 G1 E
- BIT PPU_STATUS
- P5 C$ o5 k% @ - LDA <PPU_Scroll_H$ ]) }* z% n5 W! ~. X9 f: V
- STA PPU_SCROLL5 V" O* j. i# W+ E3 j# i
- STA PPU_SCROLL/ A( _+ Y" I7 K; x6 Q
- JMP Irq_Scroll_Over. }& f" Q8 [' G* {9 h" s& j. ? i# x
-
% A/ H" r$ o3 h2 d# T1 T% q# b - Irq_Scroll_Right! _8 z: ^* A g. A" ]. j
- SEC
- \- |8 n/ @1 w9 T1 ^6 @$ H - SBC <PPU_Scroll_H
7 K8 d7 j! w7 _2 w* X - STA PPU_SCROLL! p* t+ m' C* [" ^. L) N+ v
- STA PPU_SCROLL: D9 i$ O8 ^2 d! T; L) o
- Irq_Scroll_Over" T5 r! \8 E& z2 C3 d }* z" C
-
* {$ a3 d/ w$ o# [ - INC <IRQ_Index: J! b* A; y, Y( I
- 5 ^5 _6 K4 v: V8 N4 @) z- L
- LDA <IRQ_Index6 |' e; |" A$ |6 H( f
- CMP #141 b9 A1 `# Y4 Y
- BCC * + 10
" K: a* W' b" O5 }' S - LDA #$00
& I1 [1 _# t, D - STA M19_IRQ_COUNT_L
+ h/ ^# m5 r1 g/ U- W - STA M19_IRQ_COUNT_H
q" c5 r4 T' }3 m -
* q( `: }: `5 ?/ u; ]( O8 G - IrqProgramEnd. e; Q: i9 ^6 k4 }
- PLA
1 d$ Y4 Z" D" J8 q% _ - TAY0 Y: R2 H' q) x5 P. z' ?' o/ e
- PLA
: B; @& P2 [9 r T* o8 T - TAX
" M$ W( N$ i/ |* o* j - PLA: X" L# A, T. K$ F* ?, z! w; T
- RTI8 S+ ^" F: g! Q6 F' O& M
-
/ o( ?. q; `" `) N - ;==================================================
/ f' C9 ^# w! k8 J - ;中断表% Y. b9 b# ~4 _. D
- .ORG $FFFA, o5 |4 `3 Z0 I0 J% k* x' N
- .WORD NmiProgram4 d8 x" e/ r) p' \7 I7 d
- .WORD ResetProgram
/ r0 ]/ s6 s- i3 X - .WORD IrqProgram
复制代码
2 a# R D6 F+ @1 T% Y+ H |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|