nesasm 3.2 入土教程
这是个 nesasm 3.2 入土教程, 感兴趣的可以研究下http://2006.emu618.org:6180/data/attachment/album/202405/13/225814ltk3ez8838hk6lql.png
以下是主框架代码:
;======================================================================
;文件头
NES_16KB_PRG_SIZE = 8 ;16KB PRG大小数量
NES_8KB_CHR_SIZE = 1 ;8KB CHR大小数量
BANK_DATA_MASK = NES_16KB_PRG_SIZE * 2 - 1 ;bank号掩码
;======================================================================
PRG_DATA_BANK_C000 = NES_16KB_PRG_SIZE * 2 - 2
PRG_DATA_BANK_E000 = NES_16KB_PRG_SIZE * 2 - 1
;======================================================================
RESET_BANK = NES_16KB_PRG_SIZE * 2 - 1
RESET_ADDR = $E000 ;主程序起始地址
;======================================================================
.INESPRG NES_16KB_PRG_SIZE ;16KB PRG 数量, $01-$EF8(1-3832),即16-61,312 KB
.INESCHR NES_8KB_CHR_SIZE ;8KB CHR 数量,$01-$EF8(1-3832),即0-30,656 KB
.INESMAP 4 ;Mapper号 (0-4095)
.INESSUBMAP 0 ;子Mapper号 (0-15)
.INESMIR 0 ;命名表镜像 (0: 水平 1: 垂直 2: 四屏)
.INESBAT 0 ;指定是否存在电池备份 (0: 不存在 1: 存在)
.INESPRGRAM 0 ;指定 PRG RAM 大小 (大小 = 64字节 << 计数)
.INESPRGNVRAM 0 ;指定 PRG NVRAM 大小(大小 = 64字节 << 计数)
.INESCHRRAM 0 ;指定 CHR RAM 大小(大小 = 64字节 << 计数)
.INESCHRNVRAM 0 ;指定 CHR NVRAM 大小(大小 = 64字节 << 计数)
.INESTIM 0 ;指定时序 (0: NTSC, 1: PAL, 2: 多区域, 3: Dendy)
;======================================================================
.INCLUDE "fc_demo_config.asm" ;全局配置
.INCLUDE "fc_demo_constant.asm" ;NES常量
;======================================================================
;音乐配置
.IF 0 = MUSIC_THEME
.INCLUDE "data/music/Gremlin 2/config.asm"
.ENDIF
.IF 1 = MUSIC_THEME
.INCLUDE "data/music/Raf World/config.asm"
.ENDIF
.IF 2 = MUSIC_THEME
.INCLUDE "data/music/Ninja Gaiden 3/config.asm"
.ENDIF
;======================================================================
;引用CHR图像数据
.BANK NES_16KB_PRG_SIZE * 2
.ORG $0000
.INCBIN "data/bkg.chr"
.INCBIN "data/sp.chr"
;======================================================================
.BANK PRG_DATA_BANK_E000 & BANK_DATA_MASK;设置程序所在Bank
.ORG RESET_ADDR
;======================================================================
;引用其他源文件
.INCLUDE "fc_demo_ppu.asm" ;PPU处理
.INCLUDE "fc_demo_joysitck.asm" ;手柄处理
.INCLUDE "fc_demo_static_text.asm" ;静态文本处理
;======================================================================
;======================================================================
;等待VBlank到来
Wait_For_VBlank
LDA PPU_STATUS
BPL Wait_For_VBlank
RTS
;======================================================================
;调色板初始化
Palette_Init
LDA #$3F
STA PPU_ADDRESS
LDA #$00
STA PPU_ADDRESS
LDX #$00
LDY #$20
.Write_Data
LDA Palette_Data,X
STA FC_PPU_Pal_Addr,X
INX
DEY
BNE .Write_Data
.End
RTS
;----------------------------------------
;调色板数据
Palette_Data
.HEX 0F 20 32 02 0F 20 32 0F 0F 20 32 26 0F 1B 0F 1B
.HEX 0F 21 27 22 0F 24 24 24 0F 21 21 21 0F 22 22 22
;======================================================================
;命名表清空
Nametable_Clear
LDA #$20
STA PPU_ADDRESS
LDA #$00
STA PPU_ADDRESS
LDA #$00
LDX #$00
LDY #$08
.Write_Data
STA PPU_DATA
INX
BNE .Write_Data
DEY
BNE .Write_Data
.End
RTS
;======================================================================
;音乐曲目切换
Music_Select_Process
.Pre_Music;上一曲
LDA FC_Gamepad_Once
CMP #JOY_KEY_LEFT
BNE .Next_Music
JSR Music_Play_Pre
.Next_Music;下一曲
LDA FC_Gamepad_Once
CMP #JOY_KEY_RIGHT
BNE .Next_10_Music
JSR Music_Play_Next
.Next_10_Music;上10曲
LDA FC_Gamepad_Once
CMP #JOY_KEY_UP
BNE .Pre_10_Music
JSR Music_Play_Next_10
.Pre_10_Music;下10曲
LDA FC_Gamepad_Once
CMP #JOY_KEY_DOWN
BNE .Reset
JSR Music_Play_Pre_10
.Reset;重播当前曲目
LDA FC_Gamepad_Once
CMP #JOY_KEY_START
BNE .End
LDA FC_Music_Index
JSR Music_Init_Process
.End
RTS
;----------------------------------------------------------------------
;播放上一曲
Music_Play_Pre
LDA FC_Music_Index
BEQ .End
DEC FC_Music_Index
LDA FC_Music_Index
JSR Music_Init_Process
.End
RTS
;----------------------------------------------------------------------
;播放下一曲
Music_Play_Next
LDA FC_Music_Index
CMP FC_Music_Max_Index
BCS .End
INC FC_Music_Index
LDA FC_Music_Index
JSR Music_Init_Process
.End
RTS
;----------------------------------------------------------------------
;播放上10曲
Music_Play_Pre_10
LDA FC_Music_Index
BEQ .End
SEC
SBC #10
BCS .Pre_10
LDA #$00
.Pre_10
STA FC_Music_Index
JSR Music_Init_Process
.End
RTS
;----------------------------------------------------------------------
;播放下10曲
Music_Play_Next_10
LDA FC_Music_Index
CMP FC_Music_Max_Index
BCS .End
CLC
ADC #10
CMP FC_Music_Max_Index
BCC .Next_10
LDA FC_Music_Max_Index
.Next_10
STA FC_Music_Index
JSR Music_Init_Process
.End
RTS
;----------------------------------------------------------------------
;8位十六进制转3位十进制制
Hex8ToDec
STA FC_Dec_Data_1
LDA #$00
STA FC_Dec_Data_100
STA FC_Dec_Data_10
LDA FC_Dec_Data_1
.Convert_100
CMP #100
BCC .Convert_10
SEC
SBC #100
INC FC_Dec_Data_100
BNE .Convert_100
.Convert_10
CMP #10
BCC .End
SEC
SBC #10
INC FC_Dec_Data_10
BNE .Convert_10
.End
STA FC_Dec_Data_1
RTS
;----------------------------------------------------------------------
;显示曲目信息
Music_Info_Display
LDX FC_PPU_Buf_Count
LDA #PPU_WRITE_MODE_CNT_LINE
STA Use_PPU_Buffer,X
INX
LDA #>MUSIC_INFO_POS
STA Use_PPU_Buffer,X
INX
;居中
LDA #<(MUSIC_INFO_POS & $E0) + (32 - 5)/2
STA Use_PPU_Buffer,X
INX
LDA #$05
STA Use_PPU_Buffer,X
INX
LDA FC_Music_Index
CLC
ADC #$01
JSR Hex8ToDec
LDA FC_Dec_Data_10
CLC
ADC #'0'
STA Use_PPU_Buffer,X
INX
LDA FC_Dec_Data_1
CLC
ADC #'0'
STA Use_PPU_Buffer,X
INX
LDA #'/'
STA Use_PPU_Buffer,X
INX
LDA FC_Music_Max_Index
CLC
ADC #$01
JSR Hex8ToDec
LDA FC_Dec_Data_10
CLC
ADC #'0'
STA Use_PPU_Buffer,X
INX
LDA FC_Dec_Data_1
CLC
ADC #'0'
STA Use_PPU_Buffer,X
INX
.End
STX FC_PPU_Buf_Count
RTS
;----------------------------------------------------------------------
;音乐曲目初始化处理
Music_Init_Process
PHA
JSR Music_Clear_Process
LDA #$1F
STA $4015
PLA
JSR Music_Init_Addr
JSR Music_Info_Display
RTS
;----------------------------------------------------------------------
;音乐播放处理
Music_Play_Process
JSR Music_Play_Addr
RTS
;----------------------------------------------------------------------
;音乐播放处理
Music_Clear_Process
.IF Music_Clear_Addr
JSR Music_Clear_Addr
RTS
.ELSE
LDA #$1F
STA $4015
LDA #$00
STA $4010
LDX #$00
LDA #$00
.Music_Clear_Zreo_Page_0
STA $00,X
INX
CPX #Use_Zero_Page_Begin
BCC .Music_Clear_Zreo_Page_0
LDX #Use_Zero_Page_Begin + Use_Zero_Page_Size
.Music_Clear_Zreo_Page_1
STA $00,X
INX
BNE .Music_Clear_Zreo_Page_1
Music_Clear_Process_1
STA $0600,X
STA $0700,X
INX
BNE Music_Clear_Process_1
LDA #$10
STA $4000
STA $4004
STA $400C
LDA #$00
STA $4008
LDA #$0F
STA $4015
.ENDIF
RTS
;======================================================================
;重启处理
Reset_Program
SEI
CLD
LDA #$00
STA PPU_CTRL
STA PPU_MASK
STA JOY2_FRAME
STA APU_STATUS
;等待屏幕准备完毕
LDX #$02
.Wait_For_Screen_Ready
LDA PPU_STATUS
BPL .Wait_For_Screen_Ready
DEX
BNE .Wait_For_Screen_Ready
;清空调色板
Palette_Clear
LDA #$3F
STA PPU_ADDRESS
LDA #$00
STA PPU_ADDRESS
LDX #$20
LDA #$0F
.Write_Data
STA PPU_DATA
DEX
BNE .Write_Data
;清除声音 $4000-4013
LDY #$14
LDX #$00
.Sound_Clear
STA $4000,X
INX
DEY
BNE .Sound_Clear
;清除 RAM $0000-07FF
LDA #$00
STA $00
STA $01
TAY
LDX #$08
.Memory_Clear
STA [$00],Y
INY
BNE .Memory_Clear
INC $01
DEX
BNE .Memory_Clear
;精灵缓冲初始化
LDX #$00
LDA #$F8
.OAM_Clear
STA OAM_DMA_Buffer,X
INX
BNE .OAM_Clear
;栈指针初始化
LDX #$FF
TXS
JSR Nametable_Clear;命名表清空
JSR Palette_Init;初始化调色板缓冲
JSR Static_Text_Init;初始化静态文本
LDA #MUSIC_ITEM_TOTAL - 1
STA FC_Music_Max_Index
LDA #$1F
STA APU_STATUS
LDA #MUSIC_BGM - 1
STA FC_Music_Index
JSR Music_Init_Process;音乐播放
;设置屏幕显示状态缓冲(当NMI处理时控制屏幕显示状态)
LDA #$1E
STA FC_PPU_Mask_Buf
;启用NMI处理
LDA #$80
STA PPU_CTRL
;程序循环, 剩余工作交给 NMI 中断处理
.Loop
JMP .Loop
;======================================================================
;不可屏蔽中断处理
Nmi_Program
PHA
TXA
PHA
TYA
PHA
LDA PPU_STATUS;读取使得 PPU状态寄存器复位
JSR FC_PPU_Procrss;PPU处理
;精灵内存更新
LDA #$00
STA PPU_OAM_ADDR
LDA #OAM_DMA_Buffer / $0100
STA OAM_DMA
JSR FC_Gamepad_Process;手柄输入处理
JSR Music_Select_Process;音乐选曲处理
JSR Music_Play_Process;音乐播放处理
PLA
TAY
PLA
TAX
PLA
RTI
;======================================================================
;请求中断处理
Irq_Program
RTI
;======================================================================
;中断向量表
.ORG $FFFA
.DW Nmi_Program ;NMI触发时执行
.DW Reset_Program ;载入ROM时最先执行
.DW Irq_Program ;IRQ触发时执行
https://gitee.com/flame_cyclone/nesasm_3_2
页:
[1]