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