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