yandagui 发表于 2023-7-11 19:08:59

[FC][音乐播放器][NES + 源码]

本帖最后由 yandagui 于 2023-7-11 21:32 编辑

1.魂斗罗
2.超级魂斗罗
3.赤影战士
4.忍者龙剑传2

http://2006.emu618.org:6180/data/attachment/album/202307/11/190754mmk2ubkz2ekc0u22.pnghttp://2006.emu618.org:6180/data/attachment/album/202307/11/190753i2lxh694b49yhwcx.pnghttp://2006.emu618.org:6180/data/attachment/album/202307/11/190752q1ggn6xynpgcz1yp.png
http://2006.emu618.org:6180/data/attachment/album/202307/11/190750ujh3zch77hgjjzg0.png

源码:
;[播放器模板]
;FlameCyclone 20230710

;文件头
;======================================================================
.INESPRG 4                                              ;16KB PRG 数量
.INESCHR 0                                             ;8KB CHR 数量
.INESMAP 4                                                   ;mapper 4
.INESMIR 1                                 ;命名表镜像 0水平 1垂直

;==================================================
SOUND_BAR_SHOW_ENABLE       = 1
;==================================================
BANK_DATA_MASK            = $07
;==================================================
SOUND_DATA_BANK_0         = $00
SOUND_DATA_BANK_1         = $01
SOUND_DATA_BANK_2         = $02
SOUND_DATA_BANK_C000      = $06

;-------------------------------------------------
CHR_DATA_BANK               = $04
CHR_DATA_ADDR               = $A000
;-------------------------------------------------
PROGRAM_BANK                = $05
PROGRAM_ADDR                = $8000
;-------------------------------------------------
RESET_BANK                  = $07
RESET_ADDR                  = $FE00
;==================================================
Music_Init_Addr             = $DFF0 ;音乐初始化地址
Music_Play_Addr             = $813C ;音乐播放地址
Music_Reset_Addr            = $0000 ;音乐重设数据地址
;==================================================
Music_Song_Total            = 039;全部曲目总数
Music_Start_Song            = 007;初始播放曲目
;==================================================

;==================================================
Title_Text_Pos      = $210D ;标题文本位置
Author_Info_Pos   = $2284 ;作者文本位置
Date_Info_Pos       = $22CB ;日期文本位置
;------------------------------
;------------------------------
.IF SOUND_BAR_SHOW_ENABLE
Play_Index_Pos      = $21B3 ;当前曲目位置
Play_Time_Pos       = $21F3 ;播放时间位置
Play_State_Pos      = $2233 ;播放状态位置
.ELSE

.IF Music_Song_Total > 99
Play_Index_Pos      = $21AC ;当前曲目位置
.ELSE

.IF Music_Song_Total > 9
Play_Index_Pos      = $21AD ;当前曲目位置
.ELSE
Play_Index_Pos      = $21AE ;当前曲目位置
.ENDIF

.ENDIF


Play_Time_Pos       = $21EC ;播放时间位置
Play_State_Pos      = $222C ;播放状态位置
.ENDIF
;------------------------------
Track_Name_Pos      = $216B ;曲目文本位置
Sound_Track_Pos   = $21A5 ;声道文本位置
Sound_Bar_Pos       = $21A9 ;音乐条位置
;==================================================
Scroll_X = $00
Scroll_Y = $06
;==================================================
RAM_Cln_1       = $0100
RAM_Cln_1_Size= $80
RAM_Cln_2       = $00E0
RAM_Cln_2_Size= $20
RAM_Cln_3       = $00E0
RAM_Cln_3_Size= $20

;==================================================
PPU_CTRL                =   $2000   ;PPU控制寄存器
PPU_MASK                =   $2001   ;PPU掩码寄存器
PPU_STATUS            =   $2002   ;PPU状态寄存器:读取后PPU_SCROLL和PPU_ADDRESS被复位,下一个写到PPU_SCROLL的数据是水平的,写到PPU_ADDRESS的数据是高位
PPU_OAM_ADDR            =   $2003   ;精灵RAM地址:用来设置通过PPU_OAM_DATA访问的256字节精灵RAM地址。每次访问PPU_OAM_DATA后该地址增加1
PPU_OAM_DATA            =   $2004   ;精灵RAM数据:用来读/写精灵内存。地址通过PPU_OAM_ADDR来设置,每次访问后地址增加1
PPU_SCROLL            =   $2005   ;屏幕滚动偏移:第一个写的值会进入垂直滚动寄存器(若>239,被忽略)。第二个值出现在水平滚动寄存器
PPU_ADDRESS             =   $2006   ;VRAM地址:设置PPU_DATA访问的VRAM地址。第一个写地址的高6位。第二个写低8位。每次访问PPU_DATA后地址增加
PPU_DATA                =   $2007   ;VRAM数据:用来访问VRAM数据,通过PPU_ADDRESS设置的地址在每次访问之后会增加1或32
OAM_DMA               =   $4014   ;DMA访问精灵RAM:通过写一个值xx到这个端口,引起CPU内存地址为$xx00-$xxFF的区域传送到精灵内存
APU_STATUS            =   $4015   ;声音通道切换
JOY1_FRAME            =   $4016   ;手柄1 + 选通
JOY2_FRAME            =   $4017   ;手柄2 + 选通
;==================================================
MMC3_BANK_CTRL          =   $8000
MMC3_BANK_DATA          =   $8001
MMC3_MIRRORING          =   $A000
MMC3_PRG_RAM_PROTECT    =   $A001
MMC3_IRQ_LATCH          =   $C000
MMC3_IRQ_RELOAD         =   $C001
MMC3_IRQ_DISABLE      =   $E000
MMC3_IRQ_ENABLE         =   $E001

;音乐数据块

;======================================================================
.IF SOUND_BAR_SHOW_ENABLE
.BANK SOUND_DATA_BANK_0 & BANK_DATA_MASK
.INCBIN "sound_bank_bar/music_data_0.bank"

.BANK SOUND_DATA_BANK_1 & BANK_DATA_MASK
.INCBIN "sound_bank_bar/music_data_1.bank"

.BANK SOUND_DATA_BANK_2 & BANK_DATA_MASK
.INCBIN "sound_bank_bar/music_data_2.bank"

.BANK SOUND_DATA_BANK_C000& BANK_DATA_MASK
.INCBIN "sound_bank_bar/music_data_3.bank"

.ELSE
.BANK SOUND_DATA_BANK_0 & BANK_DATA_MASK
.INCBIN "sound_bank/music_data_0.bank"

.BANK SOUND_DATA_BANK_1 & BANK_DATA_MASK
.INCBIN "sound_bank/music_data_1.bank"

.BANK SOUND_DATA_BANK_2 & BANK_DATA_MASK
.INCBIN "sound_bank/music_data_2.bank"

.BANK SOUND_DATA_BANK_C000& BANK_DATA_MASK
.INCBIN "sound_bank/music_data_3.bank"
.ENDIF

;CHR图形数据
;======================================================================
.BANK CHR_DATA_BANK
.INCBIN "chr_bank/chr_data.chr"

;==================================================
PPU_Addr      = $0300
Palette_Addr    = $03C0
Sound_Bar       = PPU_Addr+$E0
;==================================================
Palette_Update_Addr   = Palette_Addr+$0D
Palette_Update_Max      = $2C
Palette_Update_Min      = $21
Palette_Update_Interval = 60
;==================================================
Sound_Bar_Cnt       = PPU_Addr+$F0
Screen_State      = Sound_Bar_Cnt+$01
PPU_Cur             = Sound_Bar_Cnt+$02
PPU_Addr_H          = Sound_Bar_Cnt+$03
PPU_Addr_L          = Sound_Bar_Cnt+$04
;==================================================
Data_L            = $70
Data_H            = Data_L + $01
Data_Cnt            = Data_L + $02
Data_Buf            = Data_L + $03
Time_Wait_Cnt       = Data_L + $04
Palette_Wait_Cnt    = Data_L + $05
Palette_Update_Flag = Data_L + $06
Show_Track_Name   = Data_L + $07
;==================================================
Key_Keep            = Show_Track_Name + 1
Key_Once            = Key_Keep+$01
Key_Kemp            = Key_Keep+$02
Key_Temp            = Key_Keep+$03
Key_Getv            = Key_Keep+$04
;==================================================
Music_Cur         = Key_Getv+$01
Music_Last          = Music_Cur+$01
Music_State         = Music_Cur+$02
;==================================================
HEX_Data            = Music_State+$01
DEC_H               = HEX_Data+$01
DEC_T               = HEX_Data+$02
DEC_L               = HEX_Data+$03
;==================================================
Time_S            = DEC_L+$01
Time_M            = Time_S+$01
Time_H            = Time_S+$02
Time_Cnt            = Time_S+$03

;==================================================
Music_Bank_8000 = Time_Cnt + 1
Music_Bank_A000 = Music_Bank_8000 + 1
;==================================================

;======================================================================
.BANK PROGRAM_BANK
.ORG PROGRAM_ADDR

;==================================================
NmiProgramProcess;NMI中断程序处理
;处理PPU图像
JSR PPU_Proc

;启用NMI中断
LDA #$80
STA PPU_CTRL

;更新调色板
JSR Update_Palette_Data

;显示时间(缓冲)
JSR Time_Show

;播放计时
JSR Time_Count

;播放声音
JSR Sound_Play

;切换音乐(手柄触发)
JSR Music_Switch

;音乐显示(缓冲)
.IF SOUND_BAR_SHOW_ENABLE
JSR Music_Vision
.ENDIF

LDA Time_Wait_Cnt
BEQ NmiProgramProcessEnd
DEC Time_Wait_Cnt
NmiProgramProcessEnd
RTS

;==================================================
ProgramBegin;主程序
LDA #$00
STA PPU_CTRL
STA PPU_STATUS
STA PPU_MASK
STA APU_STATUS
STA PPU_SCROLL
STA PPU_SCROLL
LDA #$C0
STA JOY2_FRAME

LDX #$FF
TXS
LDA #$00
STA PPU_CTRL
STA PPU_MASK
STA MMC3_IRQ_DISABLE

;==============================
;调色板清空
LDA #$3F
STA PPU_ADDRESS
LDA #$00
STA PPU_ADDRESS
LDA #$0F
Palette_Clear
STA PPU_DATA
INX
CPX #$20
BCC Palette_Clear
LDA #$00
STA APU_STATUS
;==============================
;初始化背景调色板
JSR Set_Palette_Color
JSR Set_NameTable_Attributes

;==============================
;RAM初始化
RAM_Clear_All
LDX #$00
LDA #$00
RAM_Clear_All_Start
STA $00,X
STA $0100,X
STA $0200,X
STA $0300,X
STA $0400,X
STA $0500,X
STA $0600,X
STA $0700,X
INX
BNE RAM_Clear_All_Start

JSR VramInit
JSR Init_Palette_Addr

.IF Music_Reset_Addr
JSR Sound_Reset
.Endif

LDA #Music_Start_Song-$01
STA Music_Cur

JSR Show_Music_Text

.IF SOUND_BAR_SHOW_ENABLE
JSR Sound_Bar_Text_Set
.ENDIF

.IF Track_Name_Pos
JSR Show_Track_Info
.ENDIF

JSR PPU_Proc

LDA #$0E
STA Screen_State

JSR Sund_Bank_Init

JSR Music_Show
JSR Time_Show
JSR Music_Stata_Show
JSR Time_Delay


LDA #$80
STA PPU_CTRL

LDA #$20
STA Time_Wait_Cnt

Wait_Time_Over
LDA Time_Wait_Cnt
BNE Wait_Time_Over

LDA #$1F
STA APU_STATUS
LDA Music_Cur
JSR Sound_Init

JMP MainLoop

;==============================
Time_Delay;延时等待
LDA PPU_STATUS
BPL Time_Delay
RTS

;==============================
VramInit;初始化图形内存
LDA #CHR_DATA_BANK
JSR SwitchBankA000
LDA #LOW(CHR_DATA_ADDR)
STA <Data_L
LDA #HIGH(CHR_DATA_ADDR)
STA <Data_H
LDY #$00
LDX #$20
LDA #$00
STA PPU_ADDRESS
STA PPU_ADDRESS
VramInitWrite
LDA ,Y
STA PPU_DATA
INY
BNE VramInitWrite
INC Data_H
DEX
BNE VramInitWrite
RTS

;==============================
RAM_Clear;RAM清除
LDX #$00
LDA #$00
RAM_Clear_1
STA RAM_Cln_1,X
INX
CPX #RAM_Cln_1_Size
BNE RAM_Clear_1
LDX #$00
RAM_Clear_2
STA RAM_Cln_2,X
INX
CPX #RAM_Cln_2_Size
BNE RAM_Clear_2
LDX #$00
RAM_Clear_3
STA RAM_Cln_3,X
INX
CPX #RAM_Cln_3_Size
BNE RAM_Clear_3
RTS

;==============================
;音乐切换
Music_Switch
JSR Key_Proc
LDA Key_Once
CMP #$10
BNE Music_Start_SongStop
JSR Music_ReSet

;音乐停止
Music_Start_SongStop
LDA Key_Once
CMP #$20
BNE Music_arrow
LDA #$01
STA Music_State
JSR Music_Bar_ReSet
JSR Time_ReSet
JSR RAM_Clear
JSR Sound_Clear
JSR Music_Stata_Show
Music_arrow
LDA Key_Once
AND #$CF
BEQ Music_Switch_End
JSR Music_Number
JSR Music_ReSet
JSR Music_Show
Music_Switch_End
RTS

;==============================
;音乐曲目切换
Music_Number
LDA Music_Cur
STA Music_Last
Music_Decrease
LDA Key_Once
AND #$42
BEQ Music_Increase
LDA Music_Cur
BEQ Music_Increase
DEC Music_Cur
Music_Increase
LDA Key_Once
AND #$81
BEQ Music_Decrease_10
LDA Music_Cur
CMP #Music_Song_Total-01
BCS Music_Decrease_10
INC Music_Cur
Music_Decrease_10
LDA Key_Once
CMP #$04
BNE Music_Increase_10
LDA Music_Cur
CMP #10
BCC Music_Start_Song_Min
LDA Music_Cur
SEC
SBC #10
STA Music_Cur
LDA #$00
BEQ Music_Increase_10
Music_Start_Song_Min
LDA #$00
STA Music_Cur
Music_Increase_10
LDA Key_Once
CMP #$08
BNE Music_Number_End
LDA Music_Cur
CLC
ADC #10
CMP #Music_Song_Total-01
BCS Music_Start_Song_Max
STA Music_Cur
LDA #00
BEQ Music_Number_End
Music_Start_Song_Max
LDA #Music_Song_Total-01
STA Music_Cur
Music_Number_End
RTS

;==============================
;音乐重设
Music_ReSet
JSR RAM_Clear
JSR Sound_Clear
LDA #$1F
STA APU_STATUS
LDA Music_Cur
JSR Sound_Init
RTS

;==============================
;音乐端口清除
Sound_Clear
LDA #$00
STA APU_STATUS
LDX #$00
Sound_Clear_Start
STA $4000,X
INX
CPX #$14
BCC Sound_Clear_Start
RTS

;==============================
;按键处理
Key_Proc
JSR Key_Scan
LDA Key_Keep
STA Key_Temp
JSR Key_Scan
LDA Key_Keep
CMP Key_Temp
BEQ Key_Get_Once
LDA Key_Kemp
STA Key_Keep
Key_Get_Once
TAY
EOR Key_Kemp
AND Key_Keep
STA Key_Once
STY Key_Kemp
RTS
;------------------------------
;按键扫描
Key_Scan
LDX #$01
STX JOY1_FRAME
DEX
STX JOY1_FRAME
LDX #$08
Key_Value
LDA JOY1_FRAME
STA Key_Getv
LSR A
ORA Key_Getv
LSR A
ROL Key_Keep
DEX
BNE Key_Value
RTS

;==============================
.IF SOUND_BAR_SHOW_ENABLE
;音乐条显示
Music_Vision
JSR Music_Animation
JSR PPU_End
RTS
;------------------------------
;音乐条显示处理
Music_Animation
LDX PPU_Cur
LDA #Mode_Line
STA PPU_Addr,X
INX
LDA #HIGH(Sound_Bar_Pos)
STA PPU_Addr,X
INX
LDA #LOW(Sound_Bar_Pos)
STA PPU_Addr,X
INX
LDA Sound_Bar
JSR Volume_Convert
JSR PPU_Return
LDA Sound_Bar+$4
JSR Volume_Convert
JSR PPU_Return
LDA Sound_Bar+$8
JSR Volume_Convert_Ex
JSR PPU_Return
LDA Sound_Bar+$C
JSR Volume_Convert
JSR PPU_Return
LDY #$10
LDA APU_STATUS
AND #$10
BNE Volume_Count
LDY #$00
BEQ Volume_Count
;------------------------------
;音乐条处理
Volume_Convert_Ex
AND #$1F
TAY
BNE Volume_Count
Volume_Convert
AND #$0F
TAY
Volume_Count
LDA #$08
STA Sound_Bar_Cnt
Volume_FILL
DEY
BEQ Volume_Half
BMI Volume_Empty
DEY
Volume_Full
LDA #$16
BNE Volume_PPU
Volume_Half
LDA #$15
BNE Volume_PPU
Volume_Empty
LDA #$14
Volume_PPU
STA PPU_Addr,X
INX
DEC Sound_Bar_Cnt
BNE Volume_FILL
RTS

.ENDIF

;==============================
PPU_Addr_Set;PPU行开始
LDX PPU_Cur
LDA #Mode_Line
STA PPU_Addr,X
INX
RTS

PPU_Return;PPU转行
LDA #Flag_Over
STA PPU_Addr,X
INX
LDA #Mode_Return
STA PPU_Addr,X
INX
RTS

;------------------------------
PPU_End;PPU结束
LDA #Flag_Over
STA PPU_Addr,X
INX
STX PPU_Cur
RTS
;==============================
Mode_Line   = $FD    ;新起行模式
Mode_Return   = $FE    ;转下行模式
Mode_Clear    = $FC    ;行清除
Mode_CntLine= $FB    ;行计数写入
Flag_Over   = $FF    ;行结束标志

;------------------------------
;PPU处理
PPU_Proc
LDX PPU_Cur
LDA #$00
STA PPU_Cur
STA PPU_Addr,X
LDA PPU_Addr
BNE PPU_Proc_Beg
PPU_Proc_Ret
RTS
;------------------------------
PPU_Proc_Beg;处理开始
LDX #$00
STX PPU_MASK
;------------------------------
PPU_Mode_Select;模式选择
LDA PPU_Addr,X
CMP #Mode_Line
BEQ PPU_Mode_Newline
CMP #Mode_Return
BEQ PPU_Mode_Return
CMP #Mode_Clear
BEQ PPU_Proc_Clear
CMP #Mode_CntLine
BEQ PPU_Proc_Cnt_Line
RTS
;------------------------------
PPU_Mode_Return;转下行模式
LDA PPU_Addr_L
CLC
ADC #$20
STA PPU_Addr_L
BCC PPU_Return_End
INC PPU_Addr_H
PPU_Return_End
JMP PPU_Set_Increaser
;------------------------------
PPU_Mode_Newline;新起行模式
INX
LDA PPU_Addr,X
STA PPU_Addr_H
INX
LDA PPU_Addr,X
STA PPU_Addr_L
;------------------------------
PPU_Set_Increaser   ;设置写入地址
LDA PPU_Addr_H
STA PPU_ADDRESS
LDA PPU_Addr_L
STA PPU_ADDRESS
;------------------------------
PPU_Write   ;写入数据
INX
LDA PPU_Addr,X
CMP #Flag_Over
BEQ PPU_Proc_End
STA PPU_DATA
JMP PPU_Write
;------------------------------
PPU_Proc_End;单行写入结束
INX
LDA PPU_Addr,X
BNE PPU_Mode_Select
STA PPU_Addr
JSR Update_Palette_Color
LDA #$00
STA PPU_ADDRESS
STA PPU_ADDRESS
STA Show_Track_Name
LDA #Scroll_X
STA PPU_SCROLL
LDA #Scroll_Y
STA PPU_SCROLL
LDA Screen_State
STA PPU_MASK
RTS

PPU_Proc_Clear
INX
LDA PPU_Addr,X
STA PPU_ADDRESS
INX
LDA PPU_Addr,X
STA PPU_ADDRESS
INX
LDY PPU_Addr,X
LDA #$00
PPU_Proc_Clear_Write
STA PPU_DATA
DEY
BNE PPU_Proc_Clear_Write
JMP PPU_Proc_End

PPU_Proc_Cnt_Line
INX
LDA PPU_Addr,X
STA PPU_ADDRESS
INX
LDA PPU_Addr,X
STA PPU_ADDRESS
INX
LDY PPU_Addr,X
PPU_Proc_Cnt_Line_Write
INX
LDA PPU_Addr,X
STA PPU_DATA
DEY
BNE PPU_Proc_Cnt_Line_Write
JMP PPU_Proc_End

;==============================
HEX_To_Dec;十六进制转十进制
STA HEX_Data
PHA
TXA
PHA
LDX #$00
LDA #$00
HEX_Cln
STA DEC_H,X
INX
CPX #$03
BCC HEX_Cln
LDA HEX_Data
;------------------------------
HEX_100
CMP #100
BCC HEX_10
SEC
SBC #100
INC DEC_H
BNE HEX_100
;------------------------------
HEX_10
CMP #10
BCC HEX_1
SEC
SBC #10
INC DEC_T
BNE HEX_10
;------------------------------
HEX_1
STA DEC_L
PLA
TAX
PLA
RTS

;==============================
;音乐曲目显示
Music_Show
LDA Music_Cur
CLC
ADC #$01
JSR HEX_To_Dec
LDX PPU_Cur
LDA #$FD
STA PPU_Addr,X
INX
LDA #HIGH(Play_Index_Pos)
STA PPU_Addr,X
INX
LDA #LOW(Play_Index_Pos)
STA PPU_Addr,X
INX

.IF Music_Song_Total > 99
LDA DEC_H
ORA #$30
STA PPU_Addr,X
INX
.ENDIF

.IF Music_Song_Total > 9
LDA DEC_T
ORA #$30
STA PPU_Addr,X
INX
.ENDIF

LDA DEC_L
ORA #$30
STA PPU_Addr,X
INX

LDA #'/'
STA PPU_Addr,X
INX
Music_Show_Total
LDA #Music_Song_Total
JSR HEX_To_Dec

.IF Music_Song_Total > 99
LDA DEC_H
ORA #$30
STA PPU_Addr,X
INX
.ENDIF

.IF Music_Song_Total > 9
LDA DEC_T
ORA #$30
STA PPU_Addr,X
INX
.ENDIF

LDA DEC_L
ORA #$30
STA PPU_Addr,X
INX

JSR PPU_End
Music_Show_End
RTS

;==============================
Time_Show;播放时间显示
JSR PPU_Addr_Set
LDA #HIGH(Play_Time_Pos)
STA PPU_Addr,X
INX
LDA #LOW(Play_Time_Pos)
STA PPU_Addr,X
INX
Time_Show_H
LDA Time_H
JSR HEX_To_Dec
JSR Time_Digit
LDA #':'
STA PPU_Addr,X
INX
Time_Show_M
LDA Time_M
JSR HEX_To_Dec
JSR Time_Digit
LDA #':'
STA PPU_Addr,X
INX
Time_Show_S
LDA Time_S
JSR HEX_To_Dec
JSR Time_Digit
JSR PPU_End
Time_Show_End
RTS

Time_Digit
LDA DEC_T
ORA #$30
STA PPU_Addr,X
INX
LDA DEC_L
ORA #$30
STA PPU_Addr,X
INX
RTS

;==============================
Time_Count;计时
LDA Music_State
ORA Time_Wait_Cnt
BNE Time_Count_End
INC Time_Cnt
LDA Time_Cnt
CMP #60
BCC Time_Count_End
LDA #00
STA Time_Cnt
INC Time_S

Time_S_Cnt
LDA Time_S
CMP #60
BCC Time_Count_End
LDA #00
STA Time_S
INC Time_M

Time_M_Cnt
LDA Time_M
CMP #60
BCC Time_Count_End
LDA #00
STA Time_M
INC Time_H

Time_H_Cnt
LDA Time_H
CMP #24
BCC Time_Count_End
LDA #00
STA Time_H

Time_Count_End
RTS

;==============================
Time_ReSet;播放时间重置
LDA #$00
STA Time_S
STA Time_M
STA Time_H
STA Time_Cnt
RTS

;==============================
Music_Bar_ReSet;音乐条重置
LDA #$00
LDX #$00
Music_Bar_ReSet_Set
STA Sound_Bar,X
INX
CPX #$10
BCC Music_Bar_ReSet_Set
RTS

;==============================
PPU_Data;PPU数据写入
STY Data_L
STX Data_H
LDY #$FF
LDX PPU_Cur
DEX
PPU_Data_Beg
INX
INY
LDA ,Y
STA PPU_Addr,X
BNE PPU_Data_Beg
STX PPU_Cur
PPU_Data_End
RTS

;==============================
Music_Stata_Show;播放状态显示
LDA Music_State
BEQ Music_Stata_Show_Play
Music_Stata_Show_Stop
LDY #LOW(Music_State_Stop)
LDX #HIGH(Music_State_Stop)
JSR PPU_Data
RTS
Music_Stata_Show_Play
LDY #LOW(Music_State_Play)
LDX #HIGH(Music_State_Play)
JSR PPU_Data
RTS

.IF SOUND_BAR_SHOW_ENABLE
;==============================
Sound_Bar_Text_Set;标题与音乐条初始化
LDY #LOW(Sound_Bar_Text_Data)
LDX #HIGH(Sound_Bar_Text_Data)
JSR PPU_Data
RTS

.ENDIF

;==============================
Set_NameTable_Attributes;设置命名表属性
LDA PPU_STATUS
LDA #$23
STA PPU_ADDRESS
LDA #$C0
STA PPU_ADDRESS
LDX #$00
Set_NameTable_Attributes_Write
LDA Palette_Attributes,X
STA PPU_DATA
INX
CPX #$40
BCC Set_NameTable_Attributes_Write
RTS

;==============================
Set_Palette_Color;设置调色板数据
LDA PPU_STATUS
LDA #$3F
STA PPU_ADDRESS
LDA #$00
STA PPU_ADDRESS
LDX #$00
Set_Palette_Color_Write
LDA Palette_Data,X
STA PPU_DATA
INX
CPX #$20
BCC Set_Palette_Color_Write
RTS

;==============================
Init_Palette_Addr;初始化调色板数据
LDX #$00
Init_Palette_Addr_Write
LDA Palette_Data,X
STA Palette_Addr,X
INX
CPX #$20
BCC Init_Palette_Addr_Write
RTS

;==============================
Update_Palette_Color;更新调色板颜色
LDA Show_Track_Name
BNE Update_Palette_Color_End
LDA Palette_Update_Flag
BEQ Update_Palette_Color_End
LDA #$3F
STA PPU_ADDRESS
LDA #$00
STA PPU_ADDRESS
LDX #$00
Update_Palette_Color_Write
LDA Palette_Addr,X
STA PPU_DATA
INX
CPX #$20
BCC Update_Palette_Color_Write
LDA #$00
STA Palette_Update_Flag
Update_Palette_Color_End
RTS

;==============================
Update_Palette_Data;更新调色板数据
LDA Show_Track_Name
BNE Update_Palette_Data_End
LDA Music_State
BNE Update_Palette_Data_End
Update_Palette_Data_Check
LDA Palette_Wait_Cnt
BPL Update_Palette_Data_Check_Over
LDA #Palette_Update_Interval
STA Palette_Wait_Cnt
Update_Palette_Data_Check_Over
DEC Palette_Wait_Cnt
BNE Update_Palette_Data_End
INC Palette_Update_Flag
LDA #Palette_Update_Interval
STA Palette_Wait_Cnt
LDA Palette_Update_Addr
CMP #Palette_Update_Max
BNE Update_Palette_Data_Set
LDA #Palette_Update_Min - 1
STA Palette_Update_Addr
Update_Palette_Data_Set
INC Palette_Update_Addr
Update_Palette_Data_End
RTS

;==============================
Show_Music_Text;显示静态文本
LDX #$00
Show_Music_Text_Set
LDA Static_Text_Data,X
STA Data_L
INX
LDA Static_Text_Data,X
STA Data_H
INX
LDY #$00
LDA ,Y
STA Data_Cnt
DEX
DEX
LDA Static_Text_Pos,X
STA PPU_ADDRESS
INX
LDA #$20
SEC
SBC Data_Cnt
LSR A
STA Data_Buf
LDA Static_Text_Pos,X
AND #$E0
CLC
ADC Data_Buf
STA PPU_ADDRESS
INX
Show_Music_Text_Set_Write
INY
LDA ,Y
STA PPU_DATA
DEC Data_Cnt
BNE Show_Music_Text_Set_Write
CPX #Static_Text_Pos_End - Static_Text_Pos
BCC Show_Music_Text_Set
RTS

;==============================
.IF Track_Name_Pos;显示曲目信息
Show_Track_Info
INC Show_Track_Name
Show_Track_Info_Clear
LDX PPU_Cur
LDA #Mode_Clear
STA PPU_Addr,X
INX

LDA Music_Last
JSR Show_Get_Track_Name_Center_Pos
Show_Track_Info_Write_Cur
LDA #Mode_CntLine
STA PPU_Addr,X
INX

LDA Music_Cur
JSR Show_Get_Track_Name_Center_Pos

Show_Track_Info_Write_Cur_Data
INY
LDA ,Y
STA PPU_Addr,X
INX
DEC Data_Cnt
BNE Show_Track_Info_Write_Cur_Data
Show_Track_Info_End
STX PPU_Cur
RTS

;==============================
Show_Get_Track_Name_Center_Pos;获取中间位置
ASL A
TAY
LDA Track_Name_Addr,Y
STA Data_L
INY
LDA Track_Name_Addr,Y
STA Data_H
LDY #$00
LDA ,Y
STA Data_Cnt
LDA #$20
SEC
SBC Data_Cnt
LSR A
STA Data_Buf
LDA #HIGH(Track_Name_Pos)
STA PPU_Addr,X
INX
LDA #LOW(Track_Name_Pos)
AND #$E0
CLC
ADC Data_Buf
STA PPU_Addr,X
INX
LDA Data_Cnt
STA PPU_Addr,X
INX
Show_Get_Pos_Center_End
RTS
.ENDIF

;------------------------------
;命名表数据
Palette_Attributes
.IF SOUND_BAR_SHOW_ENABLE
.DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
.DB $F0,$F0,$F0,$F0,$F0,$F0,$F0,$F0,$FF,$FF,$FF,$FF,$BB,$AA,$AA,$AA
.DB $0F,$0F,$0F,$0F,$0B,$0A,$0A,$0A,$55,$55,$55,$55,$55,$55,$55,$55
.DB $55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55
.ELSE
.DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
.DB $F0,$F0,$F0,$F0,$F0,$F0,$F0,$F0,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.DB $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$55,$55,$55,$55,$55,$55,$55,$55
.DB $55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55,$55
.ENDIF

;------------------------------
;调色板数据
Palette_Data
.DB $0F,$27,$20,$0F,$0F,$24,$20,$0F,$0F,$21,$20,$0F,$0F,$25,$20,$0F
.DB $0F,$24,$20,$0F,$0F,$24,$20,$0F,$0F,$24,$20,$0F,$0F,$24,$20,$0F

;------------------------------
Static_Text_Data
.WORD Static_Text_Title_Data
.WORD Static_Text_Author_Data
.WORD Static_Text_Date_Data
Static_Text_Data_End

;------------------------------
Static_Text_Pos
.DB HIGH(Title_Text_Pos),LOW(Title_Text_Pos)
.DB HIGH(Author_Info_Pos),LOW(Author_Info_Pos)
.DB HIGH(Date_Info_Pos),LOW(Date_Info_Pos)
Static_Text_Pos_End

;------------------------------
Music_State_Stop
.IF SOUND_BAR_SHOW_ENABLE
.DB $FD,HIGH(Play_State_Pos),LOW(Play_State_Pos),"STOPED ",$FF,$00
ELSE
.DB $FD,HIGH(Play_State_Pos),LOW(Play_State_Pos)," STOPED",$FF,$00
.ENDIF
Music_State_Play
.DB $FD,HIGH(Play_State_Pos),LOW(Play_State_Pos),"PLAYING",$FF,$00

;------------------------------
Sound_Bar_Text_Data;声音类型文本
.DB $FD,HIGH(Sound_Track_Pos),LOW(Sound_Track_Pos)
.DB "SQ1-",$FF
.DB $FE,"SQ2-",$FF
.DB $FE,"TRI-",$FF
.DB $FE,"NOI-",$FF
.DB $FE,"DMC-",$FF,$00

.IF Track_Name_Pos
;------------------------------
Track_Name_Addr;曲目名地址索引
.WORD Trackr_01
.WORD Trackr_02
.WORD Trackr_03
.WORD Trackr_04
.WORD Trackr_05
.WORD Trackr_06
.WORD Trackr_07
.WORD Trackr_08
.WORD Trackr_09
.WORD Trackr_10
.WORD Trackr_11
.WORD Trackr_12
.WORD Trackr_13
.WORD Trackr_14
.WORD Trackr_15
.WORD Trackr_16
.WORD Trackr_17
.WORD Trackr_18
.WORD Trackr_19
.WORD Trackr_20
.WORD Trackr_21
.WORD Trackr_22
.WORD Trackr_23
.WORD Trackr_24
.WORD Trackr_25
.WORD Trackr_26
.WORD Trackr_27
.WORD Trackr_28
.WORD Trackr_29
.WORD Trackr_30
.WORD Trackr_31
.WORD Trackr_32
.WORD Trackr_33
.WORD Trackr_34
.WORD Trackr_35
.WORD Trackr_36
.WORD Trackr_37
.WORD Trackr_38
.WORD Trackr_39

;------------------------------
Trackr_Name_Data
Trackr_01 .DB $05,"BGM 1"
Trackr_02 .DB $05,"BGM 2"
Trackr_03 .DB $05,"BGM 3"
Trackr_04 .DB $05,"BGM 4"
Trackr_05 .DB $05,"BGM 5"
Trackr_06 .DB $05,"BGM 6"
Trackr_07 .DB $05,"BGM 7"
Trackr_08 .DB $05,"GREAT"
Trackr_09 .DB $08,"BOSS BOM"
Trackr_10 .DB $08,"BOSS2BGM"
Trackr_11 .DB $07,"P CLEAR"
Trackr_12 .DB $07,"A CLEAR"
Trackr_13 .DB $04,"OVER"
Trackr_14 .DB $06,"ENDING"
Trackr_15 .DB $04,"SUTA"
Trackr_16 .DB $07,"THUNDER"
Trackr_17 .DB $04,"SHOT"
Trackr_18 .DB $05,"LASER"
Trackr_19 .DB $06,"SPREAD"
Trackr_20 .DB $04,"FIRE"
Trackr_21 .DB $06,"B SHOT"
Trackr_22 .DB $08,"T DAMEGE"
Trackr_23 .DB $07,"HARETSU"
Trackr_24 .DB $05,"T OUT"
Trackr_25 .DB $05,"Z OUT"
Trackr_26 .DB $05,"A OUT"
Trackr_27 .DB $04,"ROLL"
Trackr_28 .DB $06,"APPEAR"
Trackr_29 .DB $05,"POWER"
Trackr_30 .DB $07,"BOKK BK"
Trackr_31 .DB $08,"BAKUHA 1"
Trackr_32 .DB $08,"BAKUHA 2"
Trackr_33 .DB $05,"ARUKU"
Trackr_34 .DB $06,"JIWARE"
Trackr_35 .DB $05,"SILEN"
Trackr_36 .DB $05,"P 1UP"
Trackr_37 .DB $05,"P OUT"
Trackr_38 .DB $05,"B OUT"
Trackr_39 .DB $05,"PAUSE"

.ENDIF

;------------------------------
Static_Text_Title_Data;静态文本数据
.DB 12
.DB "SUPER CONTRA"
Static_Text_Author_Data
.DB 23
.DB "EXTRACT BY FLAMECYCLONE"
Static_Text_Date_Data
.DB 10
.DB "2023.07.11"

.BANK RESET_BANK & BANK_DATA_MASK
.ORG RESET_ADDR


;==================================================
;切到主程序bank
SwitchMainBank
LDA #PROGRAM_BANK & BANK_DATA_MASK
JSR SwitchBank8000
RTS

;==================================================
SwitchBank8000;切换bank到8000-9FFF
PHA
LDA #$06
STA MMC3_BANK_CTRL
PLA
STA MMC3_BANK_DATA
RTS

;==================================================
SwitchBankA000;切换bank到A000-BFFF
PHA
LDA #$07
STA MMC3_BANK_CTRL
PLA
STA MMC3_BANK_DATA
RTS

;==================================================
Sund_Bank_Init;音乐bamk初始化
LDA #SOUND_DATA_BANK_0 & BANK_DATA_MASK
STA Music_Bank_8000
LDA #SOUND_DATA_BANK_1 & BANK_DATA_MASK
STA Music_Bank_A000
RTS

;==================================================
Sund_Bank_Set;切换音乐bank
LDA Music_Bank_8000
JSR SwitchBank8000
LDA Music_Bank_A000
JSR SwitchBankA000
RTS

;==================================================
Sound_Init;音乐初始化
PHA
JSR Sund_Bank_Set
PLA
JSR Music_Init_Addr
JSR SwitchMainBank

JSR Music_Bar_ReSet
JSR Time_ReSet
LDA #$00
STA Music_State
JSR Music_Stata_Show
.IF Track_Name_Pos
JSR Show_Track_Info
.ENDIF

RTS

;==================================================
Sound_Play;音乐播放
PHA
JSR Sund_Bank_Set
PLA
LDA Music_State
BNE Sound_Play_End
JSR Music_Play_Addr
Sound_Play_End
JSR SwitchMainBank
RTS

;==================================================
.IF Music_Reset_Addr
Sound_Reset;音乐重设(如果有的话)
JSR Sund_Bank_Set
JSR Music_Reset_Addr
JSR SwitchMainBank
RTS
.ENDIF

;==================================================
MainLoop;死循环
JMP MainLoop

;==================================================
NmiProgram;Nmi中断处理
PHA
TXA
PHA
TYA
PHA

LDA PPU_STATUS
LDA #$00
STA PPU_CTRL

;切换主程序bank
JSR SwitchMainBank

;NMI处理
JSR NmiProgramProcess

Nmi_Proc_End
PLA
TAY
PLA
TAX
PLA

RTI

;==================================================
ResetProgram;重置中断处理
SEI
CLD
LDA #$00
STA PPU_CTRL
STA PPU_MASK

JSR SwitchMainBank
JMP ProgramBegin

;==================================================
IrqProgram;Irq中断处理
RTI

.IF SOUND_BAR_SHOW_ENABLE
.ORG $FF80
STA $4000,X
STA Sound_Bar + $00,X
RTS

.ORG $FF88
STA $4000,Y
STA Sound_Bar + $00,Y
RTS

.ORG $FF90
STA $4004,X
STA Sound_Bar + $04,X
RTS

.ORG $FF98
STA $4004,Y
STA Sound_Bar + $04,Y
RTS

.ORG $FFA0
STA $4008,X
STA Sound_Bar + $08,X
RTS

.ORG $FFA8
STA $4008,Y
STA Sound_Bar + $08,Y
RTS

.ORG $FFB0
STA $400C,X
STA Sound_Bar + $0C,X
RTS

.ORG $FFB8
STA $400C,Y
STA Sound_Bar + $0C,Y
RTS

.ORG $FFC0
STA $4000
STA Sound_Bar + $00
RTS

.ORG $FFC8
STA $4004
STA Sound_Bar + $04
RTS

.ORG $FFD0
STA $4008
STA Sound_Bar + $08
RTS

.ORG $FFD8
STA $400C
STA Sound_Bar + $0C
RTS

.ENDIF

.ORG $FFFA
.WORD NmiProgram
.WORD ResetProgram
.WORD IrqProgram

**** Hidden Message *****

fragranse 发表于 2023-7-13 16:43:54

很赞啊!

leshui 发表于 2023-8-5 12:44:16

必须支持
页: [1]
查看完整版本: [FC][音乐播放器][NES + 源码]