[FC][MMC5][PCM聲音播放][可選碼率]

;[MMC5][PCM聲音播放][可選碼率][20210303]
;FlameCyclone

;========================================
;歌曲采樣率 = (3048KB * 1024)(字節(jié)) / 時(shí)長(zhǎng)(秒數(shù))
;? ?碼率 = CPU主頻/采樣率? = 寫(xiě)入PCM端口間隔周期
;320kbps = 1789772.5/40000 =? 44.74
;312kbps = 1789772.5/39000 =? 45.89
;304kbps = 1789772.5/38000 =? 47.09
;296kbps = 1789772.5/37000 =? 48.37
;288kbps = 1789772.5/36000 =? 49.71
;280kbps = 1789772.5/35000 =? 51.13
;272kbps = 1789772.5/34000 =? 52.64
;264kbps = 1789772.5/33000 =? 54.23
;256kbps = 1789772.5/32000 =? 55.93
;248kbps = 1789772.5/31000 =? 57.73
;240kbps = 1789772.5/30000 =? 59.65
;232kbps = 1789772.5/29000 =? 61.71
;224kbps = 1789772.5/28000 =? 63.92
;216kbps = 1789772.5/27000 =? 66.28
;208kbps = 1789772.5/26000 =? 68.83
;200kbps = 1789772.5/25000 =? 71.59
;192kbps = 1789772.5/24000 =? 74.57
;184kbps = 1789772.5/23000 =? 77.81
;176kbps = 1789772.5/22000 =? 81.35
;168kbps = 1789772.5/21000 =? 85.22
;160kbps = 1789772.5/20000 =? 89.48
;172kbps = 1789772.5/19000 =? 94.19
;144kbps = 1789772.5/18000 =? 99.43
;136kbps = 1789772.5/17000 = 105.28
;128kbps = 1789772.5/16000 = 111.86
;120kbps = 1789772.5/15000 = 119.31
;112kbps = 1789772.5/14000 = 127.84
;104kbps = 1789772.5/13000 = 137.67
; 96kbps = 1789772.5/12000 = 149.14
; 88kbps = 1789772.5/11000 = 162.70
; 80kbps = 1789772.5/10000 = 178.97
; 72kbps = 1789772.5/09000 = 198.86
; 64kbps = 1789772.5/08000 = 223.72
; 56kbps = 1789772.5/07000 = 255.68
; 48kbps = 1789772.5/06000 = 298.29
; 40kbps = 1789772.5/05000 = 357.95
; 32kbps = 1789772.5/04000 = 447.44
; 24kbps = 1789772.5/03000 = 596.59
; 16kbps = 1789772.5/02000 = 894.88
;? 8kbps = 1789772.5/01000 = 1789.77
;========================================
;比特率設(shè)置(32,40,48,56,64,72,80,96,112,128,144,160,192,224,240,256,320)
KBPS = 72
;========================================
PCM_Data_L = $80? ? ? ? ? ? ? ? ;數(shù)據(jù)低位
PCM_Data_H = PCM_Data_L + $01? ?;數(shù)據(jù)高位
Bank_L = PCM_Data_H + $01? ?;Bank索引低位
Bank_H = Bank_L + $01? ? ? ?;Bank索引高位
Play_Speed = Bank_H + $01? ? ? ?;播放速率
;============================================================
FC_Data_L? ?= Play_Speed + 1? ? ? ? ? ? ? ? ? ? ;數(shù)據(jù)地址低位
FC_Data_H? ?= FC_Data_L+$01? ? ? ? ? ? ? ? ? ? ?;數(shù)據(jù)地址高位
FC_Data_Cnt = FC_Data_H+$01? ? ? ? ? ? ? ? ? ? ? ? ?;數(shù)據(jù)計(jì)數(shù)
;============================================================
FC_PPU_Buffer = $0200? ? ? ? ? ? ? ? ? ? ? ? ? ? ;PPU緩沖地址
FC_PPU_Status = FC_PPU_Buffer+$C0? ? ? ? ? ? ? ? ;PPU顯示狀態(tài)
FC_PPU_Cursor = FC_PPU_Status + $01? ? ? ? ? ;當(dāng)前PPU緩沖位置
FC_PPU_Addr_L = FC_PPU_Cursor + $01? ? ? ? ? ? ? ;PPU地址低位
FC_PPU_Addr_H = FC_PPU_Addr_L + $01? ? ? ? ? ? ? ;PPU地址高位
;========================================
;CPU播放周期
?.IF KBPS == 32
INIT_SPEED = $54
?.ENDIF
?
?.IF KBPS == 40
INIT_SPEED = $42
?.ENDIF
?
?.IF KBPS == 48
INIT_SPEED = $36
?.ENDIF
?
?.IF KBPS == 56
INIT_SPEED = $2E
?.ENDIF
?
?.IF KBPS == 64
INIT_SPEED = $27
?.ENDIF
?
?.IF KBPS == 72
INIT_SPEED = $22
?.ENDIF
?
?.IF KBPS == 80
INIT_SPEED = $1E
?.ENDIF
?
?.IF KBPS == 96
INIT_SPEED = $18
?.ENDIF
?
?.IF KBPS == 112
INIT_SPEED = $14
?.ENDIF
?
?.IF KBPS == 128
INIT_SPEED = $11
?.ENDIF
?
?.IF KBPS == 144
INIT_SPEED = $0E
?.ENDIF
?
?.IF KBPS == 160
INIT_SPEED = $0C
?.ENDIF
?.IF KBPS == 192
INIT_SPEED = $09
?.ENDIF
?.IF KBPS == 224
INIT_SPEED = $07
?.ENDIF
?
?.IF KBPS == 240
INIT_SPEED = $06
?.ENDIF
?
?.IF KBPS == 256
INIT_SPEED = $06
?.ENDIF
?
?.IF KBPS == 320
INIT_SPEED = $03
?.ENDIF
;========================================
;指令延遲
DELAY_2 .MACRO
?NOP
?.ENDM
?
DELAY_3 .MACRO
?LDA $00
?.ENDM
?
DELAY_4 .MACRO
?NOP
?NOP
?.ENDM
?
DELAY_5 .MACRO
?NOP
?LDA $00
?.ENDM
?
DELAY_6 .MACRO
?NOP
?NOP
?NOP
?.ENDM
?
DELAY_7 .MACRO
?NOP
?NOP
?LDA $00
?.ENDM
;========================================
?.ORG $FC00
;========================================
ResetProcess:? ? ? ? ? ? ? ? ? ?;程序開(kāi)始
?SEI
?CLD
?LDX #$FF
?TXS
?LDA #$10
?STA $2000
?LDA #$00
?STA $2001
?LDA #$00
?STA $5010
ResetDelay:
?LDA $2002
?BPL ResetDelay
?LDA $2002
?BMI ResetDelay
?
;========================================
RamInit:? ? ? ? ? ? ? ? ? ? ? ;內(nèi)存初始化
?LDX #$00
?TXA
?STA $00
?STA $01
?LDY #$00
RamInitSet:
?STA ($00),Y
?INY
?BNE RamInitSet
?INC $01
?INX
?CPX #$08
?BCC RamInitSet
?
;========================================
PaletteClear:? ? ? ? ? ? ? ? ?;調(diào)色板清空
?LDA #$3F
?STA $2006
?LDA #$00
?STA $2006
?LDX #$00
PaletteClearSet:
?LDA PaletteData,X
?STA $2007
?INX
?CPX #$20
?BCC PaletteClearSet
;========================================
PortInit:? ? ? ? ? ? ? ? ? ? ?;端口初始化
?LDA #$00
?STA $5105
?LDA #$03
?STA $5100
?LDA #$80
?STA $5114
?LDA #INIT_SPEED
?STA Play_Speed
?
?LDA #$01
?STA $5101
?LDA #$00
?STA $5130
?LDA #$00
?STA $512B
?STA $5127
?LDA #$00
?STA $5130
?LDA #$01
?STA $5123
?LDA #$0E
?STA FC_PPU_Status
?JSR WriteText
;========================================
PrgInit:? ? ? ? ? ? ? ? ? ? ? ?;Prg初始化
?LDA #$00
?STA PCM_Data_L
?LDA #$80
?STA PCM_Data_H
?LDA #$00
?STA Bank_L
?STA Bank_H
?LDY #$00
;========================================
PlayPrgData:? ? ? ? ? ? ? ? ?;播放PRG數(shù)據(jù)
?LDX Play_Speed
PlayPrgDataDelay:
?DEX
?BNE PlayPrgDataDelay
?
?.IF KBPS == 32
?DELAY_3
?.ENDIF
?
?.IF KBPS == 40
?DELAY_4
?.ENDIF
?
?.IF KBPS == 48
?DELAY_4
?.ENDIF
?
?.IF KBPS == 56
?DELAY_2
?.ENDIF
?
?.IF KBPS == 64
?DELAY_5
?.ENDIF
?
?.IF KBPS == 72
?DELAY_5
?.ENDIF
?
?.IF KBPS == 80
?DELAY_5
?.ENDIF
?
?.IF KBPS == 96
?DELAY_5
?.ENDIF
?
?.IF KBPS == 112
?DELAY_4
?.ENDIF
?
?.IF KBPS == 128
?DELAY_3
?.ENDIF
?
?.IF KBPS == 144
?DELAY_5
?.ENDIF
?
?.IF KBPS == 160
?DELAY_5
?.ENDIF
?
?.IF KBPS == 192
?DELAY_6
?.ENDIF
?
?.IF KBPS == 224
?DELAY_5
?.ENDIF
?
?.IF KBPS == 240
?DELAY_6
?.ENDIF
?
?.IF KBPS == 256
?DELAY_2
?.ENDIF
?
?.IF KBPS == 320
?DELAY_6
?.ENDIF
?
?LDA (PCM_Data_L),Y
?STA $5011
PlayPrgDataCount:
?INY
?BNE PlayPrgDataSet
?INC PCM_Data_H
PlayPrgDataSet:
?LDA PCM_Data_H
?CMP #$A0
?BNE PlayPrgData
?INC Bank_L
?LDA Bank_L
?CMP #$7F
?BEQ ChrInit
?ORA #$80
?STA $5114
?LDA #$80
?STA PCM_Data_H
?BNE PlayPrgData
;========================================
ChrInit:? ? ? ? ? ? ? ? ? ? ? ?;Chr初始化
?LDA #$01
?STA Bank_L
?LDA #$00
?STA PCM_Data_H
?STA $2001
?LDA $2002
?LDA #$00
?STA $2006
?STA $2006
?LDA $2007
;========================================
PlayChrData:? ? ? ? ? ? ? ? ?;播放CHR數(shù)據(jù)
?LDX Play_Speed
PlayChrDataDelay:
?DEX
?BNE PlayChrDataDelay
?
?.IF KBPS == 32
?DELAY_4
?.ENDIF
?
?.IF KBPS == 40
?DELAY_5
?.ENDIF
?
?.IF KBPS == 48
?DELAY_5
?.ENDIF
?
?.IF KBPS == 56
?DELAY_3
?.ENDIF
?
?.IF KBPS == 64
?DELAY_6
?.ENDIF
?
?.IF KBPS == 72
?DELAY_6
?.ENDIF
?
?.IF KBPS == 80
?DELAY_6
?.ENDIF
?
?.IF KBPS == 96
?DELAY_6
?.ENDIF
?
?.IF KBPS == 112
?DELAY_5
?.ENDIF
?
?.IF KBPS == 128
?DELAY_4
?.ENDIF
?
?.IF KBPS == 144
?DELAY_6
?.ENDIF
?
?.IF KBPS == 160
?DELAY_6
?.ENDIF
?
?.IF KBPS == 192
?DELAY_7
?.ENDIF
?
?.IF KBPS == 224
?DELAY_6
?.ENDIF
?
?.IF KBPS == 240
?DELAY_7
?.ENDIF
?
?.IF KBPS == 256
?DELAY_3
?.ENDIF
?
?.IF KBPS == 320
?DELAY_7
?.ENDIF
?
?LDA $2007
?STA $5011
PlayChrDataCount:
?INY
?BNE PlayChrDataSet
?INC PCM_Data_H
PlayChrDataSet:
?LDA PCM_Data_H
?CMP #$10
?BNE PlayChrData
?INC Bank_L
?BNE PlayChrDataBankSet
?INC Bank_H
?LDA Bank_H
?CMP #$02
?BEQ PlayOver
PlayChrDataBankSet:
?LDA Bank_H
?STA $5130
?LDA Bank_L
?STA $5123
?LDA #$00
?STA $2006
?STA $2006
?STA PCM_Data_H
?LDA $2002
?LDA $2007
?LDA #$00
?BEQ PlayChrData
;========================================
PlayOver:? ? ? ? ? ? ? ? ? ? ? ?;播放結(jié)束
?JMP ($FFFC)
?
;========================================
MODE_CNTL = $FB? ? ? ? ? ? ? ?;行寫(xiě)入模式
MODE_CNTC = $FC? ? ? ? ? ? ? ?;行清除模式
MODE_CNTN = $FD? ? ? ? ? ? ? ?;行轉(zhuǎn)行模式
MODE_CNTS = $FE? ? ? ? ?;轉(zhuǎn)行空格寫(xiě)入模式
;----------------------------------------
FC_PPU_Process:? ? ? ? ? ? ? ? ? ;PPU處理
?LDA FC_PPU_Buffer
?BEQ FC_PPU_Process_End
?JSR FC_PPU_Process_Beg
FC_PPU_Process_End:
?LDA #$00
?STA FC_PPU_Buffer
?STA $2006
?STA $2006
?STA $2005
?STA $2005
?LDA FC_PPU_Status
?STA $2001
?RTS
;----------------------------------------
FC_PPU_Process_Beg:? ? ? ? ? ? ?;處理開(kāi)始
?LDX FC_PPU_Cursor
?LDA #$00
?STA $2001
?STA FC_PPU_Buffer,X
?STA FC_PPU_Cursor
?LDX #$FF
;----------------------------------------
FC_PPU_Mode_Select:? ? ? ? ? ? ?;模式選擇
?INX
?LDA FC_PPU_Buffer,X
?CMP #MODE_CNTL
?BEQ FC_PPU_Mode_CountLine
?CMP #MODE_CNTC
?BEQ FC_PPU_Mode_CountClear
?CMP #MODE_CNTN
?BEQ FC_PPU_Mode_CountNext
?CMP #MODE_CNTS
?BEQ FC_PPU_Mode_CountSpace
?RTS
;----------------------------------------
FC_PPU_Mode_CountLine:? ? ? ? ;行寫(xiě)入模式
?JSR FC_PPU_Set_Addr
?LDY FC_PPU_Buffer,X
FC_PPU_CountLine_Write:
?INX
?LDA FC_PPU_Buffer,X
?STA $2007
?DEY
?BNE FC_PPU_CountLine_Write
?JMP FC_PPU_Mode_Select
?
;----------------------------------------
FC_PPU_Mode_CountClear:? ? ? ?;行清除模式
?JSR FC_PPU_Write_Addr
?LDY FC_PPU_Buffer,X
?LDA #$00
FC_PPU_CountClear_Write:
?STA $2007
?DEY
?BNE FC_PPU_CountClear_Write
?JMP FC_PPU_Mode_Select
?
;----------------------------------------
FC_PPU_Mode_CountNext:? ? ? ;轉(zhuǎn)行寫(xiě)入模式
?JSR FC_PPU_Set_Next
FC_PPU_CountNext_Write:
?LDA FC_PPU_Addr_H
?STA $2006
?LDA FC_PPU_Addr_L
?STA $2006
?INX
?LDY FC_PPU_Buffer,X
?JMP FC_PPU_CountLine_Write
;----------------------------------------
FC_PPU_Mode_CountSpace: ;? ? 空格寫(xiě)入模式
?INX
?LDA FC_PPU_Addr_L
?AND #$E0
?CLC
?ADC FC_PPU_Buffer,X
?STA FC_PPU_Addr_L
?BCC FC_PPU_Mode_CountSpace_Write
?INC FC_PPU_Addr_H
FC_PPU_Mode_CountSpace_Write:
?LDA FC_PPU_Addr_H
?STA $2006
?LDA FC_PPU_Addr_L
?STA $2006
?INX
?LDY FC_PPU_Buffer,X
?JMP FC_PPU_CountLine_Write
;----------------------------------------
FC_PPU_Set_Addr:? ? ? ? ? ? ? ? ;寫(xiě)入地址
?INX
?LDA FC_PPU_Buffer,X
?STA FC_PPU_Addr_H
?STA $2006
?INX
?LDA FC_PPU_Buffer,X
?STA FC_PPU_Addr_L
?STA $2006
?INX
?RTS
;----------------------------------------
FC_PPU_Write_Addr:? ? ? ? ? ? ? ;寫(xiě)入地址
?INX
?LDA FC_PPU_Buffer,X
?STA $2006
?INX
?LDA FC_PPU_Buffer,X
?STA $2006
?INX
?RTS
;----------------------------------------
FC_PPU_Set_Next:? ? ? ? ? ? ? ? ;地址轉(zhuǎn)行
?LDA FC_PPU_Addr_L
?CLC
?ADC #$20
?STA FC_PPU_Addr_L
?BCC FC_PPU_Set_Next_End
?INC FC_PPU_Addr_H
FC_PPU_Set_Next_End:
?RTS
;==================================================
FC_PPU_Source_Write_Buffer:? ? ? ? ;寫(xiě)入PPU緩沖數(shù)據(jù)
?LDA (FC_Data_L),Y
?STA FC_PPU_Buffer,X
?INX
?INY
?RTS
;========================================
SRC_MODE_NULL? = $FF? ? ? ;無(wú)地址寫(xiě)入模式
;----------------------------------------
FC_PPU_Write_Source:? ? ? ? ? ;源數(shù)據(jù)寫(xiě)入
?PHA
?TXA
?PHA
?TYA
?PHA
?LDX FC_PPU_Cursor
?LDY #$00
?LDA FC_Data_Cnt
?STY FC_Data_Cnt
?INC FC_Data_Cnt
?CMP #SRC_MODE_NULL
?BNE FC_PPU_Write_Line
?JSR FC_PPU_Source_Write_Buffer
?STA FC_Data_Cnt
FC_PPU_Write_Source_Set:
?JSR FC_PPU_Source_Write_Buffer
?DEC FC_Data_Cnt
?BNE FC_PPU_Write_Source_Set
FC_PPU_Write_Line:
?LDA (FC_Data_L),Y
?CMP #MODE_CNTL
?BNE FC_PPU_Write_Next
?JSR FC_PPU_Source_Write_Buffer
?JSR FC_PPU_Source_Write_Buffer
?JSR FC_PPU_Source_Write_Buffer
?JSR FC_PPU_Source_Write_Buffer
?STA FC_Data_Cnt
?BNE FC_PPU_Write_Source_Set
FC_PPU_Write_Next:
?CMP #MODE_CNTN
?BNE FC_PPU_Write_Space
?JSR FC_PPU_Source_Write_Buffer
?JSR FC_PPU_Source_Write_Buffer
?STA FC_Data_Cnt
?BNE FC_PPU_Write_Source_Set
FC_PPU_Write_Space:
?CMP #MODE_CNTS
?BNE FC_PPU_Write_Clear
?JSR FC_PPU_Source_Write_Buffer
?JSR FC_PPU_Source_Write_Buffer
?JSR FC_PPU_Source_Write_Buffer
?STA FC_Data_Cnt
?BNE FC_PPU_Write_Source_Set
FC_PPU_Write_Clear:
?CMP #MODE_CNTC
?BNE FC_PPU_Write_Source_End
?JSR FC_PPU_Source_Write_Buffer
?JSR FC_PPU_Source_Write_Buffer
?BNE FC_PPU_Write_Line
FC_PPU_Write_Source_End:
?STX FC_PPU_Cursor
?LDA #$00
?STA FC_Data_Cnt
?PLA
?TAY
?PLA
?TAX
?PLA
?RTS
;========================================
WriteText:? ? ? ? ? ? ? ? ? ? ? ;寫(xiě)入文本
?LDA #<TtileText
?STA FC_Data_L
?LDA #>TtileText
?STA FC_Data_H
?LDA #$00
?STA FC_Data_Cnt
?JSR FC_PPU_Write_Source
?JSR FC_PPU_Process
?LDA #<WaveInfo
?STA FC_Data_L
?LDA #>WaveInfo
?STA FC_Data_H
?LDA #$00
?STA FC_Data_Cnt
?JSR FC_PPU_Write_Source
?JSR FC_PPU_Process
?RTS
?
;========================================
PaletteData:
?.DB $0F,$24,$24,$24,$0F,$24,$24,$24,$0F,$24,$24,$24,$0F,$24,$24,$24
?.DB $0F,$24,$24,$24,$0F,$24,$24,$24,$0F,$24,$24,$24,$0F,$24,$24,$24
;========================================
TtileText:? ? ? ? ? ? ? ? ? ? ? ;標(biāo)題文字
?.DB MODE_CNTL,$20,$A8
?.STR "WAVE FILE PLAYER"
?.DB MODE_CNTS,$46
?.STR "MAKE BY FLAMECYCLONE"
?.DB MODE_CNTS,$4B
?.STR "2021.03.03"
?.DB $FF
;========================================
WaveInfo:? ? ? ? ? ? ? ? ? ? ? ;標(biāo)題文字
?.DB MODE_CNTL,$21,$C4
?.STR "NAME: ZHUO NI QIU"
?.DB MODE_CNTS,$44
?.STR "YEAR: 1997"
?.DB MODE_CNTS,$44
?.STR "ARTIST: ZHUO YI TING"
?.DB MODE_CNTS,$44
?.STR "DURATION: 02:37"
?.DB MODE_CNTS,$44
?.STR "BIT RATE: 160KBPS"
?.DB $FF
;========================================
?.ORG $FFEF
NmiProcess:
?RTI
?
?.ORG $FFFA
?
NMI:
?.DB <NmiProcess
?.DB >NmiProcess
RESET:
?.DB <ResetProcess
?.DB >ResetProcess
?
IRQ:
?.DB <NmiProcess
?.DB >NmiProcess