卡带名 | Mapper号 |
VRC3 | 73 |
VRC4 | 21,23,25 |
VRC6 | 24 & 26 |
VRC7 | 85 |
MMC3 | 4 |
MMC4 | 10 |
MMC5 | 5 |
Sunsoft FME-7 | 69 |
Namco163 | 19 |
Jaleco SS 88006 | 18 |
RAMBO-1 | 64 |
共计11种Mapper的IRQ操作使用例子
代码内有详细注释, 希望能帮助到感兴趣的人.
;==================================================
;Mapper号
MAPPER_NUMBER = 04
;==================================================
;MMC3 (Mapper 4) 寄存器常量
MAPPER_REG_BANK_CTRL = $8000
MAPPER_REG_BANK_DATA = $8001
MAPPER_REG_MIRRORING = $A000
MAPPER_REG_PRG_RAM_PROTECT = $A001
MAPPER_REG_IRQ_LATCH = $C000
MAPPER_REG_IRQ_RELOAD = $C001
MAPPER_REG_IRQ_DISABLE = $E000
MAPPER_REG_IRQ_ENABLE = $E001
;==================================================
IRQ_SCANLINE_BEGIN = 135
IRQ_SCANLINE_1 = 8
IRQ_SCANLINE_2 = 54
IRQ_SCANLINE_3 = 8
;==================================================
;====================================================================================================
;宏常量
;====================================================================================================
;====================================================================================================
MACRO_MAPPER_INIT .MACRO
;禁用IRQ
STA MAPPER_REG_IRQ_DISABLE
;水平镜像
LDA #$01
STA MAPPER_REG_MIRRORING
;初始化图形bank
LDX #$05
.Init_Chr_Bank
STX MAPPER_REG_BANK_CTRL
LDA .ChrBankData,X
STA MAPPER_REG_BANK_DATA
DEX
BPL .Init_Chr_Bank
JMP .Init_Chr_Bank_End
.ChrBankData
.DB $00,$02,$04,$05,$06,$07
.Init_Chr_Bank_End
;启用SRAM
LDA #$80
STA MAPPER_REG_PRG_RAM_PROTECT
.ENDM
;====================================================================================================
MACRO_MAPPER_SOUND_CLEAR .MACRO
.ENDM
;====================================================================================================
MACRO_SRAM_ENABLE .MACRO
LDA #$80
STA MAPPER_REG_PRG_RAM_PROTECT
.ENDM
;====================================================================================================
MACRO_SWITCH_BANK_8000_A .MACRO
PHA
LDA #$06
STA MAPPER_REG_BANK_CTRL
PLA
STA MAPPER_REG_BANK_DATA
.ENDM
MACRO_SWITCH_BANK_A000_A .MACRO
PHA
LDA #$07
STA MAPPER_REG_BANK_CTRL
PLA
STA MAPPER_REG_BANK_DATA
.ENDM
MACRO_SWITCH_BANK_C000_A .MACRO
.ENDM
MACRO_SWITCH_BANK_E000_A .MACRO
.ENDM
;====================================================================================================
MACRO_TRIGGER_FIRST_IRQ .MACRO
LDA #IRQ_SCANLINE_BEGIN + 1
STA MAPPER_REG_IRQ_LATCH
STA MAPPER_REG_IRQ_RELOAD
STA MAPPER_REG_IRQ_ENABLE
CLI
.ENDM
;====================================================================================================
MACRO_ENABLE_IRQ .MACRO
STA MAPPER_REG_IRQ_ENABLE
.ENDM
;====================================================================================================
MACRO_DISABLE_IRQ .MACRO
LDA #$00
STA MAPPER_REG_IRQ_CTRL
STA MAPPER_REG_IRQ_ACK
.ENDM
;====================================================================================================
MACRO_ACK_IRQ .MACRO
STA MAPPER_REG_IRQ_DISABLE
STA MAPPER_REG_IRQ_ENABLE
.ENDM
;====================================================================================================
MACRO_IRQ_OPERATE .MACRO
;==================================================
;IRQ滚动模式常量
IRQ_SCROLL_MODE_ZERO = 0 ;不滚动
IRQ_SCROLL_MODE_LEFT = 1 ;向左滚动
IRQ_SCROLL_MODE_RIGHT = 2 ;向右滚动
;IRQ扫描线数据
IRQ_Scanline_Data
.DB IRQ_SCANLINE_1
.DB IRQ_SCANLINE_2
.DB IRQ_SCANLINE_3
.DW 00 ;关闭IRQ
;IRQ滚动控制模式
IRQ_Scanline_Mode
.DB IRQ_SCROLL_MODE_RIGHT
.DB IRQ_SCROLL_MODE_LEFT
.DB IRQ_SCROLL_MODE_RIGHT
.DB IRQ_SCROLL_MODE_LEFT
;==================================================
;;IRQ滚动控制
IRQ_Set_Scroll
LDX IRQ_Process_Index
LDA IRQ_Scanline_Mode,X
CMP #IRQ_SCROLL_MODE_LEFT
BEQ IRQ_Set_Scroll_Left
CMP #IRQ_SCROLL_MODE_RIGHT
BEQ IRQ_Set_Scroll_Right
IRQ_Set_Scroll_Zero;不滚动
LDA #$00
STA PPU_SCROLL
STA PPU_SCROLL
RTS
IRQ_Set_Scroll_Left;向左滚动
LDA Scroll_H
STA PPU_SCROLL
STA PPU_SCROLL
RTS
IRQ_Set_Scroll_Right;向右滚动
LDA #$00
SEC
SBC Scroll_H
STA PPU_SCROLL
STA PPU_SCROLL
RTS
;==================================================
;;IRQ滚动控制
IRQ_Set_Ctrl
LDX IRQ_Process_Index
LDA IRQ_Scanline_Data,X
BNE IRQ_Process_Latch
IRQ_Process_Disable;禁用IRQ
STA MAPPER_REG_IRQ_DISABLE
STA IRQ_Process_Index
RTS
IRQ_Process_Latch;设置下次 IRQ 触发扫描线
STA MAPPER_REG_IRQ_LATCH
INC IRQ_Process_Index
RTS
;==================================================
;IRQ处理
IRQ_Process_By_Index
JSR IRQ_Set_Scroll
JSR IRQ_Set_Ctrl
IRQ_Process_End
RTS
.ENDM
公用配置
;[FC][Mapper][IRQ]
;FlameCyclone 20231201
.INCLUDE "[FC][Mapper][MMC3].asm"
;.INCLUDE "[FC][Mapper][MMC5].asm"
;.INCLUDE "[FC][Mapper][Namco163].asm"
;.INCLUDE "[FC][Mapper][VRC2&4].asm"
;.INCLUDE "[FC][Mapper][VRC3].asm"
;.INCLUDE "[FC][Mapper][VRC6].asm"
;.INCLUDE "[FC][Mapper][VRC7].asm"
;.INCLUDE "[FC][Mapper][FME7].asm"
;.INCLUDE "[FC][Mapper][Mapper18].asm"
;.INCLUDE "[FC][Mapper][Mapper64].asm"
;文件头配置
NES_16KB_PRG_SIZE = 2
NES_8KB_CHR_SIZE = 1
BANK_DATA_MASK = NES_16KB_PRG_SIZE * 2 - 1 ;bank号掩码
RESET_BANK = NES_16KB_PRG_SIZE * 2 - 1
;======================================================================
PRG_DATA_BANK_C000 = NES_16KB_PRG_SIZE * 2 - 2
PRG_DATA_BANK_E000 = NES_16KB_PRG_SIZE * 2 - 1
;文件头
;======================================================================
.INESPRG NES_16KB_PRG_SIZE ;16KB PRG 数量
.INESCHR NES_8KB_CHR_SIZE ;8KB CHR 数量
.INESMAP MAPPER_NUMBER
.INESMIR 0 ;命名表镜像 0水平 1垂直
;==================================================
;NES端口常量
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 + 选通
;--------------------------------------------------
PROGRAM_BANK = PRG_DATA_BANK_E000
PROGRAM_ADDR = $E000
;==================================================
;零页内存地址配置
Use_Ram_Begin = $80
.RSSET Use_Ram_Begin
PPU_Ctrl_Buf .RS 1
PPU_Msak_Buf .RS 1
PPU_Scroll_H .RS 1
PPU_Scroll_V .RS 1
FC_Data_L .RS 1
FC_Data_H .RS 1
FC_Data_Buf .RS 1
FC_Data_Index .RS 1
;==================================================
GAMEPAD_MERGE_FLAG = $04
Gamepad_Keep .RS 2
Gamepad_Once .RS 2
Gamepad_Temp .RS 2
Gamepad_0_State .RS 1
Gamepad_1_State .RS 1
Gamepad_0_Value .RS 1
Gamepad_1_Value .RS 1
Gamepad_Port_Value .RS 1
Gamepad_Merge .RS 1
;==================================================
Scroll_H .RS 1
Scroll_V .RS 1
IRQ_Process_Index .RS 1
;==================================================
Prg_Bank_8000 .RS 1
Prg_Bank_A000 .RS 1
Prg_Bank_C000 .RS 1
Prg_Bank_E000 .RS 1
Prg_Bank_8000_Bak .RS 1
Prg_Bank_A000_Bak .RS 1
Prg_Bank_C000_Bak .RS 1
Prg_Bank_E000_Bak .RS 1
;==================================================
Prg_Bank_A_Bak .RS 1
;==================================================
公用主程序代码
[FC][Mapper][IRQ].asm
.INCLUDE "[FC][Mapper][Config].asm"
;CHR图形数据
;======================================================================
.BANK NES_16KB_PRG_SIZE * 2
.INCBIN "chr_bank/chr_data.chr"
.BANK PROGRAM_BANK & BANK_DATA_MASK
.ORG PROGRAM_ADDR
;--------------------------------------------------
Attributes_Data
;命名表属性
.DB $00,$00,$00,$00,$00,$00,$00,$00,$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
.DB $55,$F5,$F5,$F5,$F5,$F5,$F5,$55,$55,$FF,$FF,$FF,$FF,$FF,$FF,$75
.DB $A5,$A5,$A5,$A5,$A5,$A5,$A5,$A5,$AA,$AA,$AA,$AA,$AA,$AA,$AA,$AA
;--------------------------------------------------
;调色板数据
Palette_Data
.DB $0F,$27,$20,$0F,$0F,$23,$20,$0F,$0F,$21,$20,$0F,$0F,$24,$20,$0F
.DB $0F,$21,$24,$25,$0F,$24,$20,$0F,$0F,$24,$20,$0F,$0F,$24,$20,$0F
;--------------------------------------------------
;命名表文本索引
Name_Table_Text_Index
.DW .Name_Table_Text_Data_1
.DW .Name_Table_Text_Data_2
.DW .Name_Table_Text_Data_3
.DW .Name_Table_Text_Data_4
.DW .Name_Table_Text_Data_5
.DW $00;结束标记
.Name_Table_Text_Data_1
.DB $20,$48
.STR "MAPPER IRQ TEST"
.Name_Table_Text_Data_2
.DB $22,$28
.STR "SCROLL RIGHT"
.Name_Table_Text_Data_3
.DB $22,$68
.STR "SCROLL LEFT"
.Name_Table_Text_Data_4
.DB $23,$26
.STR "MADE BY FLAMECYCLONE"
.Name_Table_Text_Data_5
.DB $23,$6B
.STR "2023.12.01"
;==================================================
;命名表初始化
Init_Name_Table
LDA #$20
STA PPU_ADDRESS
LDA #$00
STA PPU_ADDRESS
LDA #$00
LDY #$00
LDX #$10
Init_Name_Table_Write
STA PPU_DATA
INY
BNE Init_Name_Table_Write
DEX
BNE Init_Name_Table_Write
RTS
;==================================================
;调色板初始化
Init_Palette
BIT PPU_STATUS
LDA #$3F
STA PPU_ADDRESS
LDA #$00
STA PPU_ADDRESS
LDX #$00
Init_Palette_Write
LDA Palette_Data,X
STA PPU_DATA
INX
CPX #$20
BCC Init_Palette_Write
RTS
;==================================================
;设置命名表属性
Init_NameTable_Attributes
BIT PPU_STATUS
LDA #$23
STA PPU_ADDRESS
LDA #$C0
STA PPU_ADDRESS
LDX #$00
Init_NameTable_Attributes_Write
LDA Attributes_Data,X
STA PPU_DATA
INX
CPX #$40
BCC Init_NameTable_Attributes_Write
RTS
;==================================================
;初始化命名表文本
Init_Name_Table_Text
BIT PPU_STATUS
BIT $FFFF
LDA #$00
STA <FC_Data_Index
;检查需要写入的文本条目
.Write_Text_Begin
LDA <FC_Data_Index
ASL A
TAY
LDA Name_Table_Text_Index,Y
STA <FC_Data_L
INY
LDA Name_Table_Text_Index,Y
STA <FC_Data_H
;没有文本索引则结束
LDA <FC_Data_L
ORA <FC_Data_H
BEQ .End
JSR .Write_Text_Data
INC <FC_Data_Index
JMP .Write_Text_Begin
.End
RTS
;读取文本数据位置和长度
.Write_Text_Data
LDY #$00
LDA [FC_Data_L],Y
STA PPU_ADDRESS
INY
LDA [FC_Data_L],Y
STA PPU_ADDRESS
INY
LDA [FC_Data_L],Y
TAX
INY
;写入PPU数据
.Write_PPU_Data
LDA [FC_Data_L],Y
STA PPU_DATA
INY
DEX
BNE .Write_PPU_Data
RTS
;==============================
Init_OAM_Ram;初始化精灵内存
LDX #$00
LDA #$00
STA PPU_OAM_ADDR
LDA #$F8
Init_OAM_Ram_Write
STA PPU_OAM_DATA
INX
BNE Init_OAM_Ram_Write
RTS
GamepadProcess;手柄处理
JSR GamepadDatacan
LDA <Gamepad_0_Value
STA <Gamepad_0_State
LDA <Gamepad_1_Value
STA <Gamepad_1_State
JSR GamepadDatacan
LDX #$01
GamepadMergeCheck;合并手柄输入检查
LDA <Gamepad_0_Value,X
CMP <Gamepad_0_State,X
BEQ GamepadMergeInput
LDA <Gamepad_Temp,X
STA <Gamepad_0_Value,X
GamepadMergeInput;合并手柄输入
DEX
BPL GamepadMergeCheck
LDA <Gamepad_Merge
AND #GAMEPAD_MERGE_FLAG
BNE GamepadStateProcess
LDA <Gamepad_0_Value
ORA <Gamepad_1_Value
STA <Gamepad_0_Value
GamepadStateProcess;手柄状态处理
LDX #$01
GamepadStateSave;手柄状态保存
LDA <Gamepad_0_Value,X
TAY
EOR <Gamepad_Temp,X
AND <Gamepad_0_Value,X
STA <Gamepad_Once,X
STY <Gamepad_Keep,X
STY <Gamepad_Temp,X
DEX
BPL GamepadStateSave
RTS
GamepadDatacan;手柄数据扫描
LDX #$01
STX $4016
DEX
STX $4016
LDY #$08
GamepadPortScan;手柄端口扫描
LDA $4016
STA <Gamepad_Port_Value
LSR A
ORA <Gamepad_Port_Value
LSR A
ROL <Gamepad_0_Value
LDA $4017
STA <Gamepad_Port_Value
LSR A
ORA <Gamepad_Port_Value
LSR A
ROL <Gamepad_1_Value
DEY
BNE GamepadPortScan
RTS
;==================================================
;PPU处理, 这里仅重置PPU滚动
PPU_Process
LDA #$00
STA PPU_MASK
BIT PPU_STATUS
LDA #$20
STA PPU_ADDRESS
LDA #$00
STA PPU_ADDRESS
STA PPU_SCROLL
STA PPU_SCROLL
LDA PPU_Msak_Buf
STA PPU_MASK
RTS
;==============================
Time_For_Vblank;延时等待
LDA PPU_STATUS
BPL Time_For_Vblank
RTS
;==================================================
;重置中断处理
ResetProgram
SEI
CLD
LDA #$00
STA PPU_CTRL
STA PPU_MASK
STA PPU_STATUS
STA JOY2_FRAME
STA APU_STATUS
LDA #$C0
STA JOY2_FRAME
;等待vblank
LDX #$02
Vblank_Wait_1
BIT PPU_STATUS
BPL Vblank_Wait_1
Vblank_Wait_2
BIT PPU_STATUS
BMI Vblank_Wait_2
DEX
BNE Vblank_Wait_1
LDX #$FF
TXS
;初始化Mapper
MACRO_MAPPER_INIT
;==============================
;RAM初始化
Nes_Ram_Init
LDY #$00
LDX #$08
LDA #$00
STA <$00
STA <$01
Nes_Ram_Init_Write
STA [$00],Y
INY
BNE Nes_Ram_Init_Write
INC <$01
DEX
BNE Nes_Ram_Init_Write
;初始化命名表
JSR Init_Name_Table
;初始化调色板
JSR Init_Palette
;初始化命名表属性
JSR Init_NameTable_Attributes
;初始化精灵内存
JSR Init_OAM_Ram
;在屏幕上写点东西
JSR Init_Name_Table_Text
JSR Time_For_Vblank
;开启PPU控制
LDA #$A8
STA PPU_Ctrl_Buf
STA PPU_CTRL
;开启PPU显示
LDA #$1E
STA PPU_Msak_Buf
CLI
JMP Loop
;==============================
;死循环, 等待NMI中断
Loop
JMP Loop
;IRQ宏代码定义
MACRO_IRQ_OPERATE
;==================================================
;NMI中断处理
NmiProgram
PHA
TXA
PHA
TYA
PHA
;读取清除Vblank标志, 防止重复进入
BIT PPU_STATUS
;水平滚动值增加
INC Scroll_H
;启动IRQ
MACRO_TRIGGER_FIRST_IRQ
;重置IRQ索引
LDA #$00
STA <IRQ_Process_Index
;关闭PPU控制
LDA #$00
STA PPU_CTRL
;处理PPU
JSR PPU_Process
;开启PPU控制
LDA PPU_Ctrl_Buf
STA PPU_CTRL
;手柄处理
JSR GamepadProcess
PLA
TAY
PLA
TAX
PLA
RTI
;==================================================
;IRQ中断处理
IrqProgram
PHA
TXA
PHA
TYA
PHA
;IRQ确认
MACRO_ACK_IRQ
;IRQ处理
JSR IRQ_Process_By_Index
IrqProgramEnd
PLA
TAY
PLA
TAX
PLA
RTI
;==================================================
;中断表
.ORG $FFFA
.WORD NmiProgram
.WORD ResetProgram
.WORD IrqProgram
FlameCyclone/FC IRQ (gitee.com)
原文地址:https://blog.csdn.net/Flame_Cyclone/article/details/134742174
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_39660.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。