[旋风][6502汇编][简洁音乐播放器]

;[FC][简洁音乐播放器][MMC3][20190119]
;FlameCyclone
;=============================================================
Sound_Init_Addr = $BFC8 ;音乐初始化地址
Sound_Play_Addr = $8000 ;音乐播放地址
Sound_Start = 01 ;默认播放曲目
Sound_Sum = 38 ;音乐总曲目
;=============================================================
Title_Addr_H = $21
Title_Addr_L = $A0
Digit_Addr_H = $21
Digit_Addr_L = $EC
;=============================================================
RESET_ADDR = $F000 ;重置中断指针
SP_CHR = $00 ;精灵图形CHR索引
BG_CHR = $00 ;背景图形CHR索引
;=============================================================
FC_PPU_Buffer = $0200 ;PPU缓冲地址
FC_PPU_Cursor = $02E0 ;当前PPU缓冲位置
FC_PPU_Status = FC_PPU_Cursor+$01 ;PPU显示状态
FC_PPU_Count = FC_PPU_Cursor+$02 ;PPU数据计数
Sound_Index = FC_PPU_Cursor + $03 ;当前播放曲目
;=============================================================
Btn_Once = Sound_Index + 1 ;单次按键
Btn_Keep = Btn_Once + 1 ;长按按键
Btn_Buffer = Btn_Once + 2 ;按键缓冲
Btn_Value = Btn_Once + 3 ;按键取值
Btn_Temp = Btn_Once + 4 ;按键临时
Digit_1 = Btn_Temp + $01 ;转换后的个位
Digit_10 = Digit_1+$01 ;转换后的十位
Digit_100 = Digit_1+$02 ;转换后的百位
;=============================================================
CHAR_SPACE = $00 ;空格字符索引
CHAR_DIGIT = $30 ;数字字符起始
CHAR_PER = $2F ;字符'/'
;=============================================================
.ORG RESET_ADDR
ProgramBegin:;程序开始
SEI
CLD
LDA #$10
STA $2000
LDA #$00
STA $2001
STA $E000
LDA #$80
STA $A001
LDA #$06
STA $8000
LDA #$01
STA $8000
;-------------------------
TimeDelayA:;延时A
BIT $2002
BPL TimeDelayA
TimeDelayB:;延时B
BIT $2002
BMI TimeDelayB
;-------------------------
PaletteClear:;调色板清空
LDA #$3F
STA $2006
LDA #$00
STA $2006
LDX #$00
LDA #$0F
PaletteClear_Set:;
STA $2007
INX
CPX #$20
BCC PaletteClear_Set
RAM_Clear:;RAM清空
LDX #$00
LDA #$00
RAM_Clear_Set:
STA $0100,X
STA $0200,X
INX
BNE RAM_Clear_Set
JSR Sound_RAM_Init
;-------------------------
LDX #$FF
TXS
;-------------------------
SetPpuPattern:;设置PPU图形
LDA #$00
STA $A000
SetPpuPatternA:;设置上页图形2KB*2
LDX #$00
LDY #SP_CHR
STX $8000
STY $8001
INX
INY
INY
STX $8000
STY $8001
LDX #$02
LDY #BG_CHR
SetPpuPatternB:;设置下页图形1KB*4
STX $8000
STY $8001
INX
INY
CPX #$06
BCC SetPpuPatternB
;-------------------------
ScreenInitialize:;屏幕初始化
JSR PaletteSetup
JSR PpuClear
LDA #$0E
STA FC_PPU_Status
LDA #Sound_Start - 1
STA Sound_Index
JSR ShowTitle
JSR ShowPlayOrder
JSR Sound_Init
;==================================================
NMI_Loop:;NMI循环
JSR NMI_Delay
JMP NMI_Loop
;==================================================
NMI_Delay:;NMI延时
BIT $2002
BPL NMI_Delay
JSR FC_PPU_Process
JSR Sound_Play_Addr
JSR ButtonProcess
JSR ChangeSound
RTS
;==================================================
PaletteSetup:;背景调色板设置
LDA #$3F
STA $2006
LDA #$00
STA $2006
LDX #$00
PaletteSetup_Set:
LDA Palette_Data,X
STA $2007
INX
CPX #$10
BCC PaletteSetup_Set
RTS
;==================================================
PpuClear:;PPU清空
LDA #$24
STA $2006
LDA #$00
STA $2006
LDX #$00
LDY #$08
LDA #CHAR_SPACE
PpuClear_Set:
STA $2007
INX
BNE PpuClear_Set
DEY
BPL PpuClear_Set
RTS
;========================================
HexToDec:;8位16进制转10进制
LDY #$00
DigitClear:
STY Digit_100
STY Digit_10
STY Digit_1
BCC Count_100
INY
SBC #100
Count_100:
CMP #100
BCC Set_100
SBC #100
INY
BNE Count_100
Set_100:
STY Digit_100
LDY #$00
Count_10:
CMP #10
BCC Set_10
SBC #10
INY
BNE Count_10
Set_10:
STY Digit_10
Set_1:
STA Digit_1
RTS
;========================================
ShowTitle:;显示标题
LDY #$00
LDX FC_PPU_Cursor
LDA #MODE_CNTL
STA FC_PPU_Buffer,X
INX
LDA #Title_Addr_H
STA FC_PPU_Buffer,X
INX
LDA #$01
STA FC_PPU_Count
LDA Title_Text_Data,Y
BIT FC_PPU_Count
BEQ Align_Beg
LDA Title_Text_Data,Y
CLC
ADC #$01
Align_Beg:
LSR
STA FC_PPU_Count
LDA Title_Text_Data,Y
CMP #$07
BCS Align_End
AND #$01
BNE Align_End
INC FC_PPU_Count
Align_End:
LDA #$10
SEC
SBC FC_PPU_Count
CLC
ADC #Title_Addr_L
STA FC_PPU_Buffer,X
INX
LDA Title_Text_Data,Y
STA FC_PPU_Count
STA FC_PPU_Buffer,X
INX
INY
ShowTitle_Write:
LDA Title_Text_Data,Y
STA FC_PPU_Buffer,X
INX
INY
DEC FC_PPU_Count
BNE ShowTitle_Write
STX FC_PPU_Cursor
RTS
;========================================
ShowPlayOrder:;显示播放曲目
LDX FC_PPU_Cursor
LDA #MODE_CNTL
STA FC_PPU_Buffer,X
INX
LDA #Digit_Addr_H
STA FC_PPU_Buffer,X
INX
LDA #Digit_Addr_L
STA FC_PPU_Buffer,X
INX
LDA #$07
STA FC_PPU_Buffer,X
INX
LDA Sound_Index
CLC
ADC #$01
JSR SetDigits
LDA #CHAR_PER
STA FC_PPU_Buffer,X
INX
LDA #Sound_Sum - 1
CLC
ADC #$01
JSR SetDigits
STX FC_PPU_Cursor
RTS
;========================================
ChangeSound:;曲目变更
LDA Btn_Once
AND #$FF
BEQ ChangeSound_End
ChangeToLast:
LDA Btn_Once
AND #$42
BEQ ChangeToNext
JSR PlayLastSound
ChangeToNext:
LDA Btn_Once
AND #$A1
BEQ ChangeToLast10
JSR PlayNextSound
ChangeToLast10:
LDA Btn_Once
CMP #$04
BNE ChangeToNext10
JSR PlayLast10Sound
ChangeToNext10:
LDA Btn_Once
CMP #$08
BNE ChangeRePlay
JSR PlayNext10Sound
ChangeRePlay:
LDA Btn_Once
CMP #$10
BNE ChangeToShowSound
JSR Sound_Init
ChangeToShowSound:
JSR ShowPlayOrder
ChangeSound_End:
RTS
;========================================
PlayLastSound:;上一曲
LDA Sound_Index
BEQ PlayLastSound_End
DEC Sound_Index
JSR Sound_Init
PlayLastSound_End:
RTS
;----------------------------------------
PlayNextSound:;下一曲
LDA Sound_Index
CMP #Sound_Sum - 1
BCS PlayNextSound_End
INC Sound_Index
JSR Sound_Init
PlayNextSound_End:
RTS
;----------------------------------------
PlayLast10Sound:;上10曲
LDA Sound_Index
BEQ PlayLast10Sound_End
SEC
SBC #10
BCS PlayLast10Sound_Beg
LimiteMin:
LDA #00
PlayLast10Sound_Beg:
STA Sound_Index
JSR Sound_Init
PlayLast10Sound_End:
RTS
;----------------------------------------
PlayNext10Sound:;下10曲
LDA Sound_Index
CMP #Sound_Sum - 1
BCS PlayNext10Sound_End
CLC
ADC #10
CMP #Sound_Sum - 1
BCC PlayNext10Sound_Beg
LimiteMax:
LDA #Sound_Sum - 1
PlayNext10Sound_Beg:
STA Sound_Index
JSR Sound_Init
PlayNext10Sound_End:
RTS
;========================================
SetDigits:;写入数字到PPU缓冲
JSR HexToDec
LDA Digit_100
CLC
ADC #CHAR_DIGIT
STA FC_PPU_Buffer,X
INX
LDA Digit_10
ADC #CHAR_DIGIT
STA FC_PPU_Buffer,X
INX
LDA Digit_1
ADC #CHAR_DIGIT
STA FC_PPU_Buffer,X
INX
RTS
;========================================
Sound_RAM_Init:;初始化RAM
LDX #$00
LDA #$00
STA $4015
Sound_Port_Set:
STA $4000,X
INX
CPX #$14
BCC Sound_Port_Set
LDX #$00
LDA #$00
Sound_RAM_Init_Set:
STA $00,X
STA $0300,X
STA $0400,X
STA $0500,X
STA $0600,X
STA $0700,X
INX
BNE Sound_RAM_Init_Set
LDX #$00
LDA #$00
Stack_Init_Set:
STA $0100,X
INX
CPX #$C0
BCC Stack_Init_Set
LDA #$1F
STA $4015
RTS
;==================================================
Sound_Init:
JSR Sound_RAM_Init
LDA Sound_Index
JSR Sound_Init_Addr
RTS
;==================================================
MODE_CNTL = $FB ;带计数行写入模式
MODE_CNTC = $FC ;带计数行清除模式
;--------------------------------------------------
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
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_Set_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_Set_Addr:;写入地址
INX
LDA FC_PPU_Buffer,X
STA $2006
INX
LDA FC_PPU_Buffer,X
STA $2006
INX
RTS
;=============================================================
ButtonProcess:;按键扫描
JSR ButtonScan
LDA Btn_Keep
STA Btn_Temp
JSR ButtonScan
LDA Btn_Keep
CMP Btn_Temp
BEQ ButtonProcess_Set
LDA Btn_Buffer
STA Btn_Keep
ButtonProcess_Set:
TAY
EOR Btn_Buffer
AND Btn_Keep
STA Btn_Once
STY Btn_Buffer
RTS
;--------------------------------------------------
ButtonScan:
LDX #$01
STX $4016
DEX
STX $4016
LDX #$08
ButtonScanValue:
LDA $4016
STA Btn_Value
LSR
ORA Btn_Value
LSR
ROL Btn_Keep
DEX
BNE ButtonScanValue
RTS
;========================================
Palette_Data:;背景调色板数据
.BYTE $0F,$24,$24,$24,$0F,$20,$20,$20,$0F,$27,$27,$27,$0F,$2C,$2C,$2C
Title_Text_Data:;标题文本数据
.STR "RAF WORLD"
.DCB $100,$FF