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