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