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