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