[FC][魂斗罗][最佳可视化]
本帖最后由 yandagui 于 2019-12-4 21:31 编辑[魂斗罗][最佳可视化]
时间:2019.11.30
作者:FlameCyclone
内容:
1.可视化:
(1)暂停时按选择键进入菜单
(2)方向键选择功能: B键开启: A键关闭: 选择键交换,开始键退出
1.1.透明无敌: 透明无敌
1.2.加强无敌: 金身无敌
1.3.生命锁定: 生命锁定3条
1.4.武器锁定: 武器保持不变
1.5.武器切换: 游戏时按选择键切换武器
1.6.无限跳跃: 跳跃无限触发
1.7.快速移动: 行走速度加倍
1.8.皮肤切换: 交换玩家肤色
1.9.公平子弹: 玩家子弹可以与敌人子弹对打
1.10.强力子弹: 子弹打中敌人后继续穿透
1.11.一击必杀: 敌方中弹一发必死
1.12.全屏击杀: 开枪时全屏可击中目标必死
1.13.玩家双控: 两个玩家的任意一方均可同时控制两个玩家
1.14.移除电网: 移除2,4关的电网
1.15.掉坑不死: 掉坑后不会死亡
1.16.跳过关卡: 跳转到下一关
;[魂斗罗][最佳可视化]
;20191129
;程序开始地址
.ORG $9000
;==================================================
;==================================================
;是否双人玩家
FC_IS_DOUBLE_PLAYERS = 1
;==================================================
;PPU缓冲地址配置
FC_PPU_Buffer = $0300
;PPU地址配置
FC_PPU_Cursor = $00
FC_PPU_Status = FC_PPU_Cursor+$01
FC_PPU_Data_Cnt = FC_PPU_Status + $01
FC_Data_Port_A_L = FC_PPU_Data_Cnt + $01
FC_Data_Port_A_H = FC_Data_Port_A_L + $01
FC_Data_Port_B_L = FC_Data_Port_A_H + $01
FC_Data_Port_B_H = FC_Data_Port_B_L + $01
;==================================================
;==================================================
;选择项地址配置
FC_Select_Index = FC_Data_Port_B_H + $01
FC_Select_Temp = FC_Select_Index + $02
;NMI循环计时器
FC_Time_Count = FC_Select_Temp + $01
;==================================================
;==================================================
;光标配置
FC_Cursor_Addr_L = FC_Time_Count + $01
FC_Cursor_Addr_H = FC_Cursor_Addr_L + $01
FC_Cursor_X = FC_Cursor_Addr_H + $01
FC_Cursor_Y = FC_Cursor_X + $01
;----------------------------------------
;光标图形号
FC_CURSOR_TILE = $3E
;光标偏移像素值
FC_CURSOR_OFFSET_X = 12
FC_CURSOR_OFFSET_Y = 1
FC_FUNCTION_OFFSET = 21
FC_ON_TILE = $3D
FC_OFF_TILE = $3C
;==================================================
;==================================================
;翻页配置
FC_Page_Old = FC_Cursor_Y + $01
FC_Page_Cur = FC_Page_Old + $01
FC_Page_Item_Count = FC_Page_Cur + $01
FC_Page_Item_Buffer = FC_Page_Item_Count + $01
;----------------------------------------
;翻页属性
FC_PAGE_SIZE = 10
;PPU单次写入缓冲项数
FC_PAGE_BUF_SIZE = 2
;----------------------------------------
;显示项最大索引属性
FC_ITEM_SUM = 16 - 1
;最大页索引属性
FC_PAGE_MAX = FC_ITEM_SUM/FC_PAGE_SIZE*FC_PAGE_SIZE
;==================================================
;==================================================
;按键配置
Button_Keep = FC_Page_Item_Buffer + $01
Button_Once = Button_Keep+$02
Button_Temp = Button_Once+$02
Button_Buf = Button_Temp+$02
Button_Status = Button_Buf+$02
Button_Auto_Delay = Button_Status+$02
;----------------------------------------
BUTTON_DELAY_MAX = $18
BUTTON_DELAY_SPEED = $08
BTN_UP = $08
BTN_DOWN = $04
BTN_LEFT = $02
BTN_RIGHT = $01
BTN_SELECT = $20
BTN_START = $10
BTN_B = $40
BTN_A = $80
;==================================================
FC_Copy_Addr = Button_Auto_Delay + $01
;----------------------------------------
FC_Clear_Val = FC_Copy_Addr+$00 ;清除模式覆盖值
FC_Cpy_From_L = FC_Copy_Addr+$00 ;复制来源地址低位
FC_Cpy_From_H = FC_Copy_Addr+$01 ;复制来源地址高位
FC_Cpy_To_L = FC_Copy_Addr+$02 ;复制目的地址低位
FC_Cpy_To_H = FC_Copy_Addr+$03 ;复制目的地址高位
FC_Cpy_Count_L = FC_Copy_Addr+$04 ;复制长度低位
FC_Cpy_Count_H = FC_Copy_Addr+$05 ;复制长度高位
FC_Cpy_Port_L = FC_Copy_Addr+$06 ;配置地址低位
FC_Cpy_Port_H = FC_Copy_Addr+$07 ;配置地址高位
;----------------------------------------
FC_MODE_RAM_TO_RAM = $00;复制RAM到RAM模式
FC_MODE_RAM_TO_PPU = $01;复制RAM到PPU模式
FC_MODE_PPU_TO_RAM = $02;复制PPU到RAM模式
FC_MODE_PPU_CLEAR = $03;清除PPU模式
;==================================================
Rom_Nmi_Addr = $FF
Rom_Btn_Once = $F5
Rom_Btn_Keep = $F9
Rom_Pause_Addr = $25
Rom_Pause_Val = $01
Rom_Pal_Addr = $07C0
;----------------------------------------
Save_Zero_Addr = $6200
;==================================================
;==================================================
;程序入口
Enter:
LDA Rom_Pause_Addr
AND #Rom_Pause_Val
BEQ Quit_End
LDA Rom_Btn_Once
CMP #BTN_SELECT
BNE Quit_End
PHA
TXA
PHA
TYA
PHA
JSR Wait_Sound_Stop
JSR Save_Screen
JSR Program_Begin
JSR Load_Screen
LDA #$10
STA Rom_Btn_Keep
LDA #$00
STA Rom_Btn_Once
Quit:
PLA
TAY
PLA
TAX
PLA
Quit_End:
RTS
;==================================================
;等待音乐结束
Wait_Sound_Stop:
Wait_Sound_Stop_Check:
JSR NMI_Wait
JSR $F825
LDA $010A
BNE Wait_Sound_Stop_Check
RTS
;==================================================
;保存屏幕数据
Save_Screen:
JSR Screen_Off
JSR Save_Zero
JSR Save_Ram
JSR Save_Ppu
JSR Ram_Init
JSR Sprites_Init
JSR Clear_Ppu
RTS
;==================================================
;加载屏幕数据
Load_Screen:
LDA #$00
STA $2001
JSR NMI_Wait
LDA #$02
STA $4014
JSR Load_Ram
JSR Load_Ppu
JSR Load_Zero
JSR NMI_Wait
JSR Load_Palette
JSR Screen_On
RTS
;==================================================
;关闭屏幕
Screen_Off:
LDA Rom_Nmi_Addr
AND #$7F
STA $2000
JSR NMI_Wait
LDA #$00
STA $2000
STA $2001
RTS
;==================================================
;开启屏幕
Screen_On:
LDA Rom_Nmi_Addr
STA $2000
RTS
;==================================================
;清空占用RAM
Ram_Init:
LDX #$00
LDA #$00
Ram_Init_Set:
STA $00,X
INX
CPX #$40
BCC Ram_Init_Set
RTS
;==================================================
;清空占用RAM
Sprites_Init:
LDA $2002
LDX #$00
STX $2003
LDA #$F8
Sprites_Init_Set:
STA $2004
INX
BNE Sprites_Init_Set
RTS
;==================================================
;保存零页数据
Save_Zero:
LDX #$00
Save_Zero_Set:
LDA $00,X
STA Save_Zero_Addr,X
INX
BNE Save_Zero_Set
RTS
;==================================================
;加载零页数据
Load_Zero:
LDX #$00
Load_Zero_Set:
LDA Save_Zero_Addr,X
STA $00,X
INX
BNE Load_Zero_Set
RTS
;==================================================
;恢复调色板
Load_Palette:
LDA #$3F
STA $2006
LDA #$00
STA $2006
LDX #$00
Load_Palette_Set:
LDA Rom_Pal_Addr,X
STA $2007
INX
CPX #$20
BCC Load_Palette_Set
RTS
;==================================================
;==================================================
;==================================================
;程序开始
Program_Begin:
;==================================================
;图形设置
JSR CHR_Set
JSR NMI_Wait
JSR Palette_Set
JSR PPU_Data_Page_Show
;==================================================
;开启显示
LDA #$1E
STA FC_PPU_Status
LDA #BTN_SELECT
STA Button_Keep
;==================================================
;模拟NMI循环
NMI_Loop:
JSR NMI_Delay
JSR Button_Process
JSR Button_Auto_Press
JSR Change_Select_Item
JSR Change_Function
LDA Button_Once
CMP #BTN_START
BNE NMI_Loop
RTS
;==================================================
;模拟NMI中断
NMI_Delay:
JSR NMI_Wait
JSR Show_Select_Cursor
JSR FC_PPU_Process
RTS
;==================================================
;等待NMI中断
NMI_Wait:
LDA $2002
BPL NMI_Wait
DEC FC_Time_Count
RTS
;==================================================
;PPU写入模式配置属性
FC_PPU_MODE_CNTL = $FE ;带计数行写入
FC_PPU_MODE_CNTC = $FC ;带计数行清除
;-------------------------------------------------
;PPU处理
FC_PPU_Process:
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
;----------------------------------------
;PPU处理开始
FC_PPU_Process_Beg:
LDX FC_PPU_Cursor
LDA #$00
STA $2001
STA FC_PPU_Buffer,X
STA FC_PPU_Cursor
LDX #$FF
CLV
FC_PPU_Process_Mode_Select:
INX
LDA FC_PPU_Buffer,X
CMP #FC_PPU_MODE_CNTL
BEQ FC_PPU_Process_Mode_CountLine
CMP #FC_PPU_MODE_CNTC
BEQ FC_PPU_Process_Mode_CountClean
RTS
;----------------------------------------
;计数行写入模式
FC_PPU_Process_Mode_CountLine:
JSR FC_PPU_Process_Set_Addr_And_Count
FC_PPU_Process_Mode_CountLine_Write:
INX
LDA FC_PPU_Buffer,X
STA $2007
DEY
BNE FC_PPU_Process_Mode_CountLine_Write
BVC FC_PPU_Process_Mode_Select
;----------------------------------------
;计数行清除模式
FC_PPU_Process_Mode_CountClean:
JSR FC_PPU_Process_Set_Addr_And_Count
LDA #$00
FC_PPU_Process_Mode_CountClean_Write:
STA $2007
DEY
BNE FC_PPU_Process_Mode_CountClean_Write
BVC FC_PPU_Process_Mode_Select
;----------------------------------------
;设置PPU地址和写入计数
FC_PPU_Process_Set_Addr_And_Count:
INX
LDA FC_PPU_Buffer,X
STA $2006
INX
LDA FC_PPU_Buffer,X
STA $2006
INX
LDY FC_PPU_Buffer,X
RTS
;==================================================
;设置CHR图形
CHR_Set:
LDX #$05
CHR_Set_Data:
STX $8000
LDA CHR_Data,x
STA $8001
DEX
BPL CHR_Set_Data
RTS
;----------------------------------------
;CHR图形bank数据
CHR_Data:
.BYTE $00,$00,$00,$00,$00,$00
;==================================================
;背景调色板设置
Palette_Set:
LDA #$3F
STA $2006
LDA #$00
STA $2006
LDX #$00
Palette_Set_Data:
LDA Palette_Data,X
STA $2007
INX
CPX #$20
BCC Palette_Set_Data
RTS
;----------------------------------------
;背景调色板数据
Palette_Data:
.DB $0F,$29,$24,$24,$0F,$20,$20,$20,$0F,$26,$26,$26,$0F,$2A,$2A,$2A
.DB $0F,$20,$26,$16,$0F,$24,$24,$24,$0F,$26,$26,$26,$0F,$2A,$2A,$2A
;==================================================
;按键扫描
Button_Process:
LDX #$01
Button_Process_Beg:
JSR Button_Scan
LDA Button_Keep,X
STA Button_Temp,X
JSR Button_Scan
LDA Button_Keep,X
CMP Button_Temp,X
BEQ Button_Get_Once
LDA Button_Buf,X
STA Button_Keep,X
Button_Get_Once:
TAY
EOR Button_Buf,X
AND Button_Keep,X
STA Button_Once,X
STY Button_Buf,X
DEX
BPL Button_Process_Beg
RTS
;----------------------------------------
Button_Scan:
LDA #$01
STA $4016
LDA #$00
STA $4016
LDY #$08
Button_Value:
LDA $4016,X
STA Button_Status,X
LSR
ORA Button_Status,X
LSR
ROL Button_Keep,X
DEY
BNE Button_Value
RTS
;==================================================
;按键自动按压
Button_Auto_Press:
LDA Button_Keep
ORA Button_Keep + 1
BEQ Button_Auto_Press_End
INC Button_Auto_Delay
LDA Button_Auto_Delay
CMP #BUTTON_DELAY_MAX
BCC Button_Auto_Press_No_Active
LDA Button_Keep
STA Button_Once
LDA Button_Keep + 1
STA Button_Once + 1
LDA Button_Auto_Delay
SEC
SBC #BUTTON_DELAY_SPEED
STA Button_Auto_Delay
Button_Auto_Press_No_Active:
RTS
;----------------------------------------
;未按压按键
Button_Auto_Press_End:
LDA #$00
STA Button_Auto_Delay
RTS
;==================================================
;设置PPU写入模式
Set_PPU_Mode:
LDX FC_PPU_Cursor
STA FC_PPU_Buffer,X
INX
STX FC_PPU_Cursor
RTS
;==================================================
;写入单独一行文本
Set_Select_Addr:
LDX FC_PPU_Cursor
LDA FC_Select_Temp
ASL
TAY
INY
LDA Text_PPU_Addr,Y
STA FC_PPU_Buffer,X
INX
DEY
LDA Text_PPU_Addr,Y
STA FC_PPU_Buffer,X
INX
STX FC_PPU_Cursor
RTS
;==================================================
;写入单独一行文本
Set_Select_Data:
LDA FC_Select_Temp
CLC
ADC FC_Page_Cur
ASL
TAY
INY
LDA Text_Data_Addr,Y
STA FC_Data_Port_A_H
DEY
LDA Text_Data_Addr,Y
STA FC_Data_Port_A_L
RTS
;==================================================
;清除旧文本
Set_Select_Data_Clean:
LDA FC_Select_Temp
CLC
ADC FC_Page_Old
ASL
TAY
INY
LDA Text_Data_Addr,Y
STA FC_Data_Port_A_H
DEY
LDA Text_Data_Addr,Y
STA FC_Data_Port_A_L
RTS
;==================================================
;写入单独一行文本
PPU_Data_Write_Item:
LDA FC_Select_Temp
CLC
ADC FC_Page_Cur
CMP #FC_ITEM_SUM
BEQ PPU_Data_Write_Item_Set
BCS PPU_Data_Write_Item_End
PPU_Data_Write_Item_Set:
LDA #FC_PPU_MODE_CNTL
JSR Set_PPU_Mode
JSR Set_Select_Addr
JSR Set_Select_Data
JSR PPU_Data_Write_Line
PPU_Data_Write_Item_End:
RTS
;==================================================
;清除单独一行文本
PPU_Data_Clean_Item:
LDA FC_Select_Temp
CLC
ADC FC_Page_Old
CMP #FC_ITEM_SUM
BEQ PPU_Data_Clean_Item_Set
BCS PPU_Data_Clean_Item_End
PPU_Data_Clean_Item_Set:
LDA #FC_PPU_MODE_CNTC
JSR Set_PPU_Mode
JSR Set_Select_Addr
JSR Set_Select_Data_Clean
JSR PPU_Data_Clean_Line
PPU_Data_Clean_Item_End:
RTS
;==================================================
;页内容写入
PPU_Data_Page_Show:
LDA #FC_PAGE_SIZE
STA FC_Page_Item_Count
LDA #$00
STA FC_Page_Item_Buffer
STA FC_Select_Temp
PPU_Data_Page_Item_Set:
JSR PPU_Data_Clean_Item
JSR PPU_Data_Write_Item
JSR Function_Status_Clean
JSR Function_Status_Show
INC FC_Select_Temp
INC FC_Page_Item_Buffer
LDA FC_Page_Item_Buffer
CMP #FC_PAGE_BUF_SIZE
BNE PPU_Data_Page_Item_Set_Check
JSR NMI_Delay
LDA #$00
STA FC_Page_Item_Buffer
PPU_Data_Page_Item_Set_Check:
DEC FC_Page_Item_Count
BNE PPU_Data_Page_Item_Set
PPU_Data_Page_Show_End_Check:
LDA FC_Page_Item_Buffer
BEQ PPU_Data_Page_Show_End
JSR NMI_Delay
PPU_Data_Page_Show_End:
RTS
;==================================================
;PPU单行数据写入接口
PPU_Data_Write_Line:
LDX FC_PPU_Cursor
LDY #$00
LDA (FC_Data_Port_A_L),Y
STA FC_PPU_Buffer,X
STA FC_PPU_Data_Cnt
INX
STX FC_PPU_Cursor
INY
PPU_Data_Write_Line_Set:
LDA (FC_Data_Port_A_L),Y
TAX
LDA Char_Rom,X
LDX FC_PPU_Cursor
STA FC_PPU_Buffer,X
INX
STX FC_PPU_Cursor
INY
DEC FC_PPU_Data_Cnt
BNE PPU_Data_Write_Line_Set
STX FC_PPU_Cursor
RTS
;==================================================
;PPU单行数据清空接口
PPU_Data_Clean_Line:
LDX FC_PPU_Cursor
LDY #$00
LDA (FC_Data_Port_A_L),Y
STA FC_PPU_Buffer,X
INX
STX FC_PPU_Cursor
RTS
;==================================================
;更改选择项
Change_Select_Item:
Change_Previous_Page:
LDA Button_Once
ORA Button_Once + 1
AND #$02
BEQ Change_Next_Page
JSR Change_To_Previous_Page
Change_Next_Page:
LDA Button_Once
ORA Button_Once + 1
AND #$01
BEQ Change_Previous_Item
JSR Change_To_Next_Page
Change_Previous_Item:
LDA Button_Once
ORA Button_Once + 1
AND #$08
BEQ Change_Next_Item
JSR Change_To_Previous_Item
Change_Next_Item:
LDA Button_Once
ORA Button_Once + 1
.IF FC_IS_DOUBLE_PLAYERS
AND #$04
.ELSE
AND #$24
.ENDIF
BEQ Change_Select_Item_End
JSR Change_To_Next_Item
Change_Select_Item_End:
RTS
;==================================================
;切换到上一个选项
Change_To_Previous_Item:
LDA FC_Select_Index
BNE Change_To_Previous_Item_Set
;----------------------------------------
;切换到末页最后一项
Change_To_Previous_Item_Set_Last_Page:
JSR Record_Last_Page_Index
LDA #FC_ITEM_SUM
STA FC_Select_Index
LDA #FC_PAGE_MAX
STA FC_Page_Cur
JSR Update_Page_Content
RTS
;----------------------------------------
;切换到上一个
Change_To_Previous_Item_Set:
;检查是否需要换页
LDA FC_Select_Index
CMP FC_Page_Cur
BNE Change_To_Previous_Item_Set_No_Page
;----------------------------------------
;切换到上一个(需换页)
Change_To_Previous_Item_Set_Page:
JSR Record_Last_Page_Index
LDA FC_Page_Cur
SEC
SBC #FC_PAGE_SIZE
STA FC_Page_Cur
DEC FC_Select_Index
JSR Update_Page_Content
RTS
;----------------------------------------
;切换到上一个(无换页)
Change_To_Previous_Item_Set_No_Page:
DEC FC_Select_Index
RTS
;==================================================
;切换到下一个选项
Change_To_Next_Item:
LDA FC_Select_Index
CMP #FC_ITEM_SUM
BNE Change_To_Next_Item_Set
;----------------------------------------
;切换到起始页第一个
Change_To_Next_Item_Set_Begin_Page:
JSR Record_Last_Page_Index
LDA #$00
STA FC_Select_Index
STA FC_Page_Cur
JSR Update_Page_Content
RTS
;----------------------------------------
;切换到下一个
Change_To_Next_Item_Set:
INC FC_Select_Index
LDA FC_Page_Cur
CLC
ADC #FC_PAGE_SIZE
CMP FC_Select_Index
BNE Change_To_Next_Item_Set_End
;----------------------------------------
;切换到下一个(需换页)
Change_To_Next_Item_Set_Page
JSR Record_Last_Page_Index
LDA FC_Page_Cur
CLC
ADC #FC_PAGE_SIZE
STA FC_Page_Cur
JSR Update_Page_Content
Change_To_Next_Item_Set_End:
RTS
;==================================================
;切换到上一页
Change_To_Previous_Page:
LDA FC_Page_Cur
BEQ Change_To_Previous_Page_Set_Last_Page
JSR Record_Last_Page_Index
LDA FC_Page_Cur
SEC
SBC #FC_PAGE_SIZE
STA FC_Page_Cur
LDA FC_Select_Index
SEC
SBC #FC_PAGE_SIZE
STA FC_Select_Index
JSR Update_Page_Content
Change_Select_Last_Page_End:
RTS
;----------------------------------------
;切换到最后一页
Change_To_Previous_Page_Set_Last_Page:
LDA #FC_PAGE_MAX
BEQ Change_To_Previous_Page_Set_Begin_Item
JSR Record_Last_Page_Index
LDA FC_Select_Index
SEC
SBC FC_Page_Cur
CLC
ADC #FC_PAGE_MAX
STA FC_Select_Index
LDA #FC_PAGE_MAX
STA FC_Page_Cur
LDA FC_Select_Index
CMP #FC_ITEM_SUM
BCC Change_To_Previous_Page_Set_Last_Page_End
;----------------------------------------
;切换到最后一项
Change_To_Previous_Page_Set_Last_Item
LDA #FC_ITEM_SUM
STA FC_Select_Index
Change_To_Previous_Page_Set_Last_Page_End:
JSR Update_Page_Content
RTS
;----------------------------------------
;切换到起始项(最大页只有一页时)
Change_To_Previous_Page_Set_Begin_Item:
LDA #$00
STA FC_Select_Index
RTS
;==================================================
;切换到下一页
Change_To_Next_Page:
LDA #FC_PAGE_MAX
BEQ Change_To_Next_Page_Set_Last_Item
LDA FC_Page_Cur
CMP #FC_PAGE_MAX
BEQ Change_To_Next_Page_Set_Begin_Page
;----------------------------------------
;切换到下一页
Change_To_Next_Page_Set:
JSR Record_Last_Page_Index
LDA FC_Page_Cur
CLC
ADC #FC_PAGE_SIZE
STA FC_Page_Cur
LDA FC_Select_Index
CLC
ADC #FC_PAGE_SIZE
STA FC_Select_Index
LDA FC_Select_Index
CMP #FC_ITEM_SUM
BCC Change_To_Next_Page_Set_End
;----------------------------------------
;切换到最后一项
LDA #FC_ITEM_SUM
STA FC_Select_Index
Change_To_Next_Page_Set_End:
JSR Update_Page_Content
RTS
;----------------------------------------
;切换到起始页
Change_To_Next_Page_Set_Begin_Page:
JSR Record_Last_Page_Index
LDA FC_Select_Index
SEC
SBC FC_Page_Cur
STA FC_Select_Index
LDA #$00
STA FC_Page_Cur
JSR Update_Page_Content
RTS
;----------------------------------------
;切换到最后一项(最大页只有一页时)
Change_To_Next_Page_Set_Last_Item:
LDA #FC_ITEM_SUM
STA FC_Select_Index
JSR Update_Page_Content
RTS
;==================================================
;更新页面内容
Update_Page_Content:
LDA FC_Page_Cur
CMP FC_Page_Old
BEQ Change_Update_Page_End
JSR PPU_Data_Page_Show
Change_Update_Page_End:
RTS
;==================================================
;记录上次页索引
Record_Last_Page_Index
LDA FC_Page_Cur
STA FC_Page_Old
RTS
;==================================================
;显示当前选择项光标
Show_Select_Cursor:
LDA FC_Select_Index
SEC
SBC FC_Page_Cur
ASL
TAY
INY
LDA Text_PPU_Addr,Y
AND #$03
STA FC_Cursor_Addr_H
INX
DEY
LDA Text_PPU_Addr,Y
STA FC_Cursor_Addr_L
;----------------------------------------
;计算光标X坐标
Show_Select_Cursor_Set_X:
LDA FC_Cursor_Addr_L
AND #$1F
ASL
ASL
ASL
STA FC_Cursor_X
LDA FC_Cursor_Addr_L
AND #$E0
STA FC_Cursor_Addr_L
;----------------------------------------
;计算光标Y坐标
Show_Select_Cursor_Set_Y:
LDX #$05
ROR FC_Cursor_Addr_H
ROR FC_Cursor_Addr_L
ROR FC_Cursor_Addr_H
ROR FC_Cursor_Addr_L
LDA FC_Cursor_Addr_L
STA FC_Cursor_Y
;----------------------------------------
;写入光标
Show_Select_Cursor_Set:
LDA #$00
STA $2003
LDA FC_Cursor_Y
SEC
SBC #FC_CURSOR_OFFSET_Y
STA $2004
LDA #FC_CURSOR_TILE
STA $2004
LDA #$00
STA $2004
LDA FC_Cursor_X
SEC
SBC #FC_CURSOR_OFFSET_X
STA $2004
RTS
;==================================================
;切换功能
Change_Function:
;----------------------------------------
;开启功能A
Change_Function_On_A:
LDA Button_Once
CMP #$40
BNE Change_Function_On_B
JSR Change_Function_To_On_A
JSR Function_Status_Update
;----------------------------------------
;关闭功能B
Change_Function_On_B:
.IF FC_IS_DOUBLE_PLAYERS
LDA Button_Once + 1
CMP #$40
BNE Change_Function_Off_A
JSR Change_Function_To_On_B
JSR Function_Status_Update
.ENDIF
;----------------------------------------
;关闭功能A
Change_Function_Off_A:
LDA Button_Once
CMP #$80
BNE Change_Function_Off_B
JSR Change_Function_To_Off_A
JSR Function_Status_Update
;----------------------------------------
;关闭功能B
Change_Function_Off_B:
.IF FC_IS_DOUBLE_PLAYERS
LDA Button_Once + 1
CMP #$80
BNE Change_Function_Swap
JSR Change_Function_To_Off_B
JSR Function_Status_Update
.ENDIF
;==================================================
;交换开关
Change_Function_Swap:
.IF FC_IS_DOUBLE_PLAYERS
LDA Button_Once
ORA Button_Once + 1
CMP #$20
BNE Change_Function_End
JSR Change_Function_To_Swap
JSR Function_Status_Update
.ENDIF
Change_Function_End:
RTS
;==================================================
;交换开关状态
Change_Function_To_Swap:
.IF FC_IS_DOUBLE_PLAYERS
LDA FC_Select_Index
SEC
SBC FC_Page_Cur
STA FC_Select_Temp
JSR Set_Function_Port
LDY #$00
LDX FC_Select_Index
LDA (FC_Data_Port_A_L),Y
EOR (FC_Data_Port_B_L),Y
AND Function_Check,X
BEQ Change_Function_To_Swap_End
LDA (FC_Data_Port_A_L),Y
EOR Function_Check,X
STA (FC_Data_Port_A_L),Y
LDA (FC_Data_Port_B_L),Y
EOR Function_Check,X
STA (FC_Data_Port_B_L),Y
Change_Function_To_Swap_End:
RTS
.ENDIF
;==================================================
;更新功能状态
Function_Status_Update:
LDA FC_Select_Index
SEC
SBC FC_Page_Cur
STA FC_Select_Temp
JSR Function_Status_Show
RTS
;==================================================
;设置功能地址端口
Set_Function_Port:
LDA FC_Select_Temp
CLC
ADC FC_Page_Cur
ASL
TAY
INY
LDA Function_Addr_A,Y
STA FC_Data_Port_A_H
.IF FC_IS_DOUBLE_PLAYERS
LDA Function_Addr_B,Y
STA FC_Data_Port_B_H
.ENDIF
DEY
LDA Function_Addr_A,Y
STA FC_Data_Port_A_L
.IF FC_IS_DOUBLE_PLAYERS
LDA Function_Addr_B,Y
STA FC_Data_Port_B_L
.ENDIF
RTS
;==================================================
;设置功能临时索引
Set_Function_Temp_Index:
LDA FC_Select_Index
SEC
SBC FC_Page_Cur
STA FC_Select_Temp
RTS
;==================================================
;开启功能A
Change_Function_To_On_A:
JSR Set_Function_Temp_Index
JSR Set_Function_Port
LDX FC_Select_Index
LDY #$00
LDA (FC_Data_Port_A_L),Y
ORA Function_Check,X
STA (FC_Data_Port_A_L),Y
RTS
;----------------------------------------
;开启功能B
.IF FC_IS_DOUBLE_PLAYERS
Change_Function_To_On_B:
JSR Set_Function_Temp_Index
JSR Set_Function_Port
LDX FC_Select_Index
LDY #$00
LDA (FC_Data_Port_B_L),Y
ORA Function_Check,X
STA (FC_Data_Port_B_L),Y
RTS
.ENDIF
;----------------------------------------
;关闭功能A
Change_Function_To_Off_A:
JSR Set_Function_Temp_Index
JSR Set_Function_Port
LDX FC_Select_Index
LDY #$00
LDA Function_Check,X
EOR #$FF
AND (FC_Data_Port_A_L),Y
STA (FC_Data_Port_A_L),Y
RTS
;----------------------------------------
;关闭功能B
.IF FC_IS_DOUBLE_PLAYERS
Change_Function_To_Off_B:
JSR Set_Function_Temp_Index
JSR Set_Function_Port
LDX FC_Select_Index
LDY #$00
LDA Function_Check,X
EOR #$FF
AND (FC_Data_Port_B_L),Y
STA (FC_Data_Port_B_L),Y
RTS
.ENDIF
;==================================================
;设置功能状态PPU地址
Set_Function_Status_Addr:
LDX FC_PPU_Cursor
LDA FC_Select_Temp
ASL
TAY
INY
LDA Text_PPU_Addr,Y
STA FC_PPU_Buffer,X
INX
DEY
LDA Text_PPU_Addr,Y
CLC
ADC #FC_FUNCTION_OFFSET
STA FC_PPU_Buffer,X
INX
.IF FC_IS_DOUBLE_PLAYERS
LDA #$02
.ELSE
LDA #$01
.ENDIF
STA FC_PPU_Buffer,X
INX
STX FC_PPU_Cursor
RTS
;==================================================
;获取当前选择索引
Get_Select_Index:
LDA FC_Select_Temp
CLC
ADC FC_Page_Cur
TAX
RTS
;==================================================
;清除状态文本
Function_Status_Clean:
LDA #FC_PPU_MODE_CNTC
JSR Set_PPU_Mode
JSR Set_Function_Status_Addr
RTS
;==================================================
;显示开关状态
Function_Status_Show:
JSR Get_Select_Index
CPX #FC_ITEM_SUM
BEQ Function_Status_Show_Set
BCS Function_Status_Show_End
Function_Status_Show_Set:
LDA #FC_PPU_MODE_CNTL
JSR Set_PPU_Mode
JSR Get_Select_Index
JSR Set_Function_Status_Addr
JSR Set_Function_Port
JSR Function_Status_Show_Check_A
.IF FC_IS_DOUBLE_PLAYERS
JSR Function_Status_Show_Check_B
.ENDIF
Function_Status_Show_End:
RTS
;----------------------------------------
;检查功能A状态
Function_Status_Show_Check_A:
JSR Get_Select_Index
LDY #$00
LDA (FC_Data_Port_A_L),Y
AND Function_Check,X
BEQ Show_Function_Status_Off
JSR Show_Function_Status_On
RTS
;----------------------------------------
;检查功能B状态
.IF FC_IS_DOUBLE_PLAYERS
Function_Status_Show_Check_B:
JSR Get_Select_Index
LDY #$00
LDA (FC_Data_Port_B_L),Y
AND Function_Check,X
BEQ Show_Function_Status_Off
JSR Show_Function_Status_On
RTS
.ENDIF
;----------------------------------------
;显示功能开启状态
Show_Function_Status_On:
LDX FC_PPU_Cursor
LDA #FC_ON_TILE
STA FC_PPU_Buffer,X
INX
STX FC_PPU_Cursor
RTS
;----------------------------------------
;显示功能关闭状态
Show_Function_Status_Off:
LDX FC_PPU_Cursor
LDA #FC_OFF_TILE
STA FC_PPU_Buffer,X
INX
STX FC_PPU_Cursor
RTS
;-------------------------------------------------------------
FC_Data_Copy: ;数据拷贝参数设置
STX FC_Cpy_Port_L
STY FC_Cpy_Port_H
LDY #$00
LDX #$06
FC_Data_Copy_Addr_Set: ;从指定地址读入参数
LDA (FC_Cpy_Port_L),Y
STA FC_Cpy_From_L,Y
INY
DEX
BNE FC_Data_Copy_Addr_Set
LDA (FC_Cpy_Port_L),Y
CLV
LDY #$00
;----------------------------------
FC_Data_Copy_Mode: ;复制模式校验
CMP #FC_MODE_RAM_TO_RAM
BEQ FC_Ram_To_Ram_Mode
CMP #FC_MODE_RAM_TO_PPU
BEQ FC_Ram_To_Ppu_Mode
CMP #FC_MODE_PPU_TO_RAM
BEQ FC_Ppu_To_Ram_Mode
CMP #FC_MODE_PPU_CLEAR
BEQ FC_Ppu_Clear_Mode
RTS
;----------------------------------------
FC_Ram_To_Ram_Mode: ;复制RAM到RAM模式
LDX FC_Cpy_Count_L
INX
FC_Ram_To_Ram_Count: ;剩余计数检查
DEX
BNE FC_Ram_To_Ram_Copy
DEC FC_Cpy_Count_H
BMI FC_Ram_To_Ram_Over
FC_Ram_To_Ram_Copy: ;开始复制数据
LDA (FC_Cpy_From_L),Y
STA (FC_Cpy_To_L),Y
FC_Ram_To_Ram_From_Set: ;源地址递增
INY
BNE FC_Ram_To_Ram_Count
INC FC_Cpy_To_H
INC FC_Cpy_From_H
BVC FC_Ram_To_Ram_Count
FC_Ram_To_Ram_Over: ;结束数据复制
RTS
;----------------------------------------
FC_Ram_To_Ppu_Mode: ;复制RAM到PPU模式
LDA FC_Cpy_To_H
STA $2006
LDA FC_Cpy_To_L
STA $2006
LDX FC_Cpy_Count_L
INX
FC_Ram_To_Ppu_Count: ;剩余计数检查
DEX
BNE FC_Ram_To_Ppu_Copy
DEC FC_Cpy_Count_H
BMI FC_Ram_To_Ppu_Over
FC_Ram_To_Ppu_Copy: ;开始复制数据
LDA (FC_Cpy_From_L),Y
STA $2007
FC_Ram_To_Ppu_From_Set: ;源地址递增
INY
BNE FC_Ram_To_Ppu_Count
INC FC_Cpy_From_H
BVC FC_Ram_To_Ppu_Count
FC_Ram_To_Ppu_Over: ;结束数据复制
RTS
;----------------------------------------
FC_Ppu_To_Ram_Mode: ;复制PPU到RAM模式
LDA FC_Cpy_From_H
STA $2006
LDA FC_Cpy_From_L
STA $2006
LDA $2007
LDX FC_Cpy_Count_L
INX
FC_Ppu_To_Ram_Count: ;剩余计数检查
DEX
BNE FC_Ppu_To_Ram_Copy
DEC FC_Cpy_Count_H
BMI FC_Ppu_To_Ram_Over
FC_Ppu_To_Ram_Copy: ;开始复制数据
LDA $2007
STA (FC_Cpy_To_L),Y
FC_Ppu_To_Ram_To_Set: ;目的地址递增
INY
BNE FC_Ppu_To_Ram_Count
INC FC_Cpy_To_H
BVC FC_Ppu_To_Ram_Count
FC_Ppu_To_Ram_Over: ;结束数据复制
RTS
;----------------------------------------
FC_Ppu_Clear_Mode: ;清除PPU模式
LDA FC_Cpy_To_H
STA $2006
LDA FC_Cpy_To_L
STA $2006
LDX FC_Cpy_Count_H
LDY FC_Cpy_Count_L
LDA FC_Clear_Val
FC_Ppu_Clear_Count: ;剩余计数检查
BNE FC_Ppu_Clear_Copy
DEX
BMI FC_Ppu_Clear_Over
FC_Ppu_Clear_Copy: ;开始清除PPU
STA $2007
DEY
BVC FC_Ppu_Clear_Count
FC_Ppu_Clear_Over: ;结束数据复制
RTS
;==================================================
;保存RAM数据
Save_Ram:
LDX #<Save_Ram_Data
LDY #>Save_Ram_Data
JSR FC_Data_Copy
RTS
;加载RAM数据
Load_Ram:
LDX #<Load_Ram_Data
LDY #>Load_Ram_Data
JSR FC_Data_Copy
RTS
;保存PPU数据
Save_Ppu:
LDX #<Save_PPU_Data
LDY #>Save_PPU_Data
JSR FC_Data_Copy
RTS
;加载PPU数据
Load_Ppu:
LDX #<Load_PPU_Data
LDY #>Load_PPU_Data
JSR FC_Data_Copy
RTS
;清空PPU数据
Clear_Ppu:
LDX #<Cln_PPU_Data
LDY #>Cln_PPU_Data
JSR FC_Data_Copy
RTS
;==================================================
;数据配置
Save_Ram_Data:
.DB $00,$03,$00,$63,$00,$01,FC_MODE_RAM_TO_RAM
Load_Ram_Data:
.DB $00,$63,$00,$03,$00,$01,FC_MODE_RAM_TO_RAM
Save_PPU_Data:
.DB $00,$20,$00,$64,$00,$04,FC_MODE_PPU_TO_RAM
Load_PPU_Data:
.DB $00,$64,$00,$20,$00,$04,FC_MODE_RAM_TO_PPU
Cln_PPU_Data:
.DB $00,$00,$00,$20,$00,$04,FC_MODE_PPU_CLEAR
;==================================================
;文本数据PPU显示地址
Text_PPU_Addr:
.WORD $20C5
.WORD $2105
.WORD $2145
.WORD $2185
.WORD $21C5
.WORD $2205
.WORD $2245
.WORD $2285
.WORD $22C5
.WORD $2305
.WORD $2345
;==================================================
;文本数据PPU数据地址
Text_Data_Addr:
.WORD Text_Data_01
.WORD Text_Data_02
.WORD Text_Data_03
.WORD Text_Data_04
.WORD Text_Data_05
.WORD Text_Data_06
.WORD Text_Data_07
.WORD Text_Data_08
.WORD Text_Data_09
.WORD Text_Data_10
.WORD Text_Data_11
.WORD Text_Data_12
.WORD Text_Data_13
.WORD Text_Data_14
.WORD Text_Data_15
.WORD Text_Data_16
;==================================================
;文本数据
Text_Data:
Text_Data_01:
.STR "01.INVINCIBLE"
Text_Data_02:
.STR "02.INVINCIBLE PLUS"
Text_Data_03:
.STR "03.LOCK LIFE"
Text_Data_04:
.STR "04.LOCK WEAPON"
Text_Data_05:
.STR "05.SEL CHANGE WEAPON"
Text_Data_06:
.STR "06.UNLIMITED JUMP"
Text_Data_07:
.STR "07.MOVE FAST"
Text_Data_08:
.STR "08.SWAP SKIN"
Text_Data_09:
.STR "09.EQUAL BULLET"
Text_Data_10:
.STR "10.STRONG BULLET"
Text_Data_11:
.STR "11.KILL BY ONCE"
Text_Data_12:
.STR "12.FULL SCREEN KILL"
Text_Data_13:
.STR "13.DOUBLE CONTROL"
Text_Data_14:
.STR "14.REMOVE E-GRID"
Text_Data_15:
.STR "15.FALL INVINCIBLE"
Text_Data_16:
.STR "16.NEXT STAGE"
;==================================================
;功能开关检查地址
Function_Addr_A:
.WORD $01C0
.WORD $01C0
.WORD $01C0
.WORD $01C0
.WORD $01C0
.WORD $01C0
.WORD $01C0
.WORD $01C0
.WORD $01C4
.WORD $01C4
.WORD $01C4
.WORD $01C4
.WORD $01C4
.WORD $01C4
.WORD $01C2
.WORD $01C4
;功能开关检查地址
Function_Addr_B:
.WORD $01C1
.WORD $01C1
.WORD $01C1
.WORD $01C1
.WORD $01C1
.WORD $01C1
.WORD $01C1
.WORD $01C1
.WORD $01C4
.WORD $01C4
.WORD $01C4
.WORD $01C4
.WORD $01C4
.WORD $01C4
.WORD $01C3
.WORD $01C4
;==================================================
;功能开关检查数据
Function_Check:
.DB $01
.DB $02
.DB $04
.DB $08
.DB $10
.DB $20
.DB $40
.DB $80
.DB $01
.DB $02
.DB $04
.DB $08
.DB $10
.DB $20
.DB $40
.DB $80
Char_Rom:
.DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
.DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00
.DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$3B,$25,$00
.DB $01,$02,$03,$04,$05,$06,$07,$08,$09,$0A,$00,$00,$00,$00,$00,$00
.DB $00,$0B,$0C,$0D,$0E,$0F,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19
.DB $1A,$1B,$1C,$1D,$1E,$1F,$20,$21,$22,$23,$24,$00,$00,$00,$00,$00
**** Hidden Message *****
flamecyclone.ys168.com
www.nesbbs.com 支持楼主,非常丰富的修改选项! 顶楼主啦..希望楼主多发精品好帖啦..... 改的挺多,支持! 重新制作, 修复已经发现的bug 666666666666666666666 楼主威武 感谢大神分享!可视化修改非常棒! 多谢你的分享 感谢楼主分享 感谢{:4_92:}分享 增加烧录支持(其实是之前遗漏了兼容性) 樓主的修改一定支持, 魂斗羅是喜欢的系列.
多谢楼主分享 漏了一个下载。现在魂斗罗2部都齐了。谢谢楼主无私的付出。 感谢楼主分享 这个牛叉大了 不错不错 谢谢楼主了 谢谢老板啊
Tec.PNG (8.05 KB, 下载次数: 0)
下载附件保存到相册
2020-3-13 13:33 上传
得到的文件解压后放在任何FC模拟器即可玩。NES上最优秀的篮球游戏!1 _8 G6 w! F: Z^" u7 _) S
修改内容:
1)游戏时按START键可以开启或关闭怎样射球都进篮,全场照进!- t9 S2 d" W3 p& \s
4 N# A* oK& S. i2 c
不过开启了是双方面的,看到电脑拿着球赶快关闭!(有声音提示)。" p1 M) ?$ I+ `) P* f2
页:
[1]
2