欢迎光临散文网 会员登陆 & 注册

[FC][MMC5][PCM声音播放][可选码率]

2021-03-03 14:55 作者:FlameCyclone  | 我要投稿

;[MMC5][PCM声音播放][可选码率][20210303]

;FlameCyclone

;========================================

;歌曲采样率 = (3048KB * 1024)(字节) / 时长(秒数)

;   码率 = CPU主频/采样率  = 写入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


;========================================

;比特率设置(32,40,48,56,64,72,80,96,112,128,144,160,192,224,240,256,320)

KBPS = 72

;========================================

PCM_Data_L = $80                ;数据低位

PCM_Data_H = PCM_Data_L + $01   ;数据高位

Bank_L = PCM_Data_H + $01   ;Bank索引低位

Bank_H = Bank_L + $01       ;Bank索引高位

Play_Speed = Bank_H + $01       ;播放速率

;============================================================

FC_Data_L   = Play_Speed + 1                    ;数据地址低位

FC_Data_H   = FC_Data_L+$01                     ;数据地址高位

FC_Data_Cnt = FC_Data_H+$01                         ;数据计数

;============================================================

FC_PPU_Buffer = $0200                            ;PPU缓冲地址

FC_PPU_Status = FC_PPU_Buffer+$C0                ;PPU显示状态

FC_PPU_Cursor = FC_PPU_Status + $01          ;当前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:                   ;程序开始

 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:                      ;内存初始化

 LDX #$00

 TXA

 STA $00

 STA $01

 LDY #$00

RamInitSet:

 STA ($00),Y

 INY

 BNE RamInitSet

 INC $01

 INX

 CPX #$08

 BCC RamInitSet

 

;========================================

PaletteClear:                 ;调色板清空

 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数据

 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数据

 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:                       ;播放结束

 JMP ($FFFC)

 

;========================================

MODE_CNTL = $FB               ;行写入模式

MODE_CNTC = $FC               ;行清除模式

MODE_CNTN = $FD               ;行转行模式

MODE_CNTS = $FE         ;转行空格写入模式

;----------------------------------------

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:             ;处理开始

 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:        ;行写入模式

 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:      ;转行写入模式

 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: ;    空格写入模式

 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:                ;写入地址

 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:              ;写入地址

 INX

 LDA FC_PPU_Buffer,X

 STA $2006

 INX

 LDA FC_PPU_Buffer,X

 STA $2006

 INX

 RTS


;----------------------------------------

FC_PPU_Set_Next:                ;地址转行

 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:        ;写入PPU缓冲数据

 LDA (FC_Data_L),Y

 STA FC_PPU_Buffer,X

 INX

 INY

 RTS


;========================================

SRC_MODE_NULL  = $FF      ;无地址写入模式

;----------------------------------------

FC_PPU_Write_Source:          ;源数据写入

 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:                      ;写入文本

 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:                      ;标题文字

 .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:                      ;标题文字

 .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

[FC][MMC5][PCM声音播放][可选码率]的评论 (共 条)

分享到微博请遵守国家法律