yandagui 发表于 2017-3-30 20:35:15

[FC教程][最终任务][修改实例]

本帖最后由 yandagui 于 2017-3-30 21:03 编辑

得益于修改思路的进一步优化,原本是通过文件的Trainer在7000-71FF固化程序,让程序的精灵端口跳转到7000执行关卡选择的程序(包括显示STAGE),Trainer在ROM载入时就把Trainer的512字节载入到7000-71FF了,本来想通过按键跳转的切BANK程序里面把原本Trainer的数据复制到7000-71FF,这样ROM就不需要Trainer就可以让7000-71FF充满我写的选关程序了,然而,ROM运行时首先运行的是精灵写入程序,那时候按键程序都还没有开始执行,此时7000-71FF一片空白,跳转到7000只能死机喽.
然而,今天想到一个思路.
1.找一个大约20字节的空间A,把精灵写入指令改为跳转到A写上: 7000-71FF是否已经写有数据(71FF为FE即可),有的话跳转到7000执行,否则执行原来的精灵写入程序后回去.
2.按键部分加上数据复制功能: 判断71FF是否为FE(是的话数据写完了,跳过写入程序,不是就复制数据块)没有复制完数据的话就把Trainer数据块复制到7000-71FE,复制完将71FF写入FE
3.这样一来就可以完美地使用空间6000-7FFF来写更多程序了(数据可以写入到6000-7FFF).


;[最终任务KEY]
button = $04    ;单次按键
flag = $6000    ;功能开关标志
pause = $000E   ;暂停地址

.ORG $8000
LDY #$08    ;自带的按键程序
ADDR8002:
LDA $4016,X
LSR
ROL $0021
LSR
ROL $0029
DEY
BNE $8002
LDA $0021
ORA $0029
STA $0021
LDA $0020
AND $0021
STA $0020
LDA $06,X
EOR $0020
AND $0020
STA $04,X
LDA $0020
STA $06,X
JSR KEY_OPERATE
JSR Function    ;功能调用
JSR Weapon    ;武器切换调用
JSR Power    ;威力调用
JSR BULLET_NUM    ;子弹数目
JSR BULLET    ;副武器类型
RTS



.ORG $8050
Function:    ;功能
WUDI:    ;无敌
LDA $6000,X
AND #$08    ;开关判断
BEQ LIFE
LDA #$05
STA $05DC,X    ;无敌锁定
LIFE:    ;生命
LDA $6000,X
AND #$04    ;开关判断
BEQ FUNRTS
LDA #$05
STA $1C,X    ;生命赋值
FUNRTS:
RTS

Weapon:    ;武器切换
LDA pause    ;暂停状态判断
BNE WEARTS
LDA $04,X
CMP #$20    ;选择键判断
BNE WEARTS
LDA $12,X
CMP #$03    ;武器值判断
BCC WEAINC
LDA #$FF
STA $12,X    ;武器重置
WEAINC:
INC $12,X    ;武器增加

WEARTS:
RTS

Power:    ;威力
LDA pause    ;暂停状态判断
BEQ SPERTS
BUT_LEFT:
LDA $04,X
CMP #$02    ;左按键判断
BNE BUT_RIGHT
LDA $88,X
CMP #$00    ;威力判断
BEQ SPERTS
SPEDEC
LDA $88,X    ;读取武器值
SEC
SBC #$08
STA $88,X    ;威力减小
BUT_RIGHT:
LDA $04,X
CMP #$01    ;右按键判断
BNE SPERTS
LDA $88,X
CMP #$10    ;威力判断
BEQ SPERTS
SPEINC:
LDA $88,X    ;读取武器值
CLC
ADC #$08
STA $88,X    ;威力增大

SPERTS:
RTS

BULLET_NUM:    ;子弹数目
LDA pause    ;暂停状态判断
BEQ BULRTS
CPX #$00    ;主机玩家判断
BNE BULRTS
LDA $04,X    ;主机玩家判断
AND #$80    ;按键A比较
BEQ BULRTS
LDA $87    ;状态判断
BEQ BUL_2
BUL_1:
LDA #$00
STA $87    ;1发子弹
BEQ BULRTS
BUL_2:
LDA #$01
STA $87    ;2发子弹

BULRTS:
RTS


BULLET:
LDA pause    ;判断暂停状态
BEQ BULLETRTS
LDA $04,X
CMP #$40    ;按键B比较
BNE BULLETRTS
LDA $6002,X    ;读取副武器
CMP #$03
BCC BULLETADD
LDA #$FF
STA $6002,X
BULLETADD:
INC $6002,X

BULLETRTS:
LDA $6002,X
TAY
LDA BULLET_DATA,Y
STA $6004,X    ;写入副武器数据
RTS


BULLET_DATA:
.BYTE $06,$02,$03,$04



KEY_OPERATE:    ;按键开关操作
data_protect:    ;数据保护
PHA
TXA
PHA
TYA
PHA

FLAG_INI:    ;开关标志初始化

LDA $600F
CMP #$01
BEQ pause_cmp
LDA #$00
STA $6000
STA $6001
STA $6002
STA $6003
STA $6004
STA $6005
LDA #$01
STA $600F

pause_cmp:    ;判断暂停状态
LDA pause
CMP #$01    ;判断暂停状态
BEQ button_press
PLA
TAY
PLA
TAX
PLA
RTS

button_press:    ;按压操作
ini_Y:
LDY #$00
button_cmp:
LDA button,X
CMP ora_data,Y
BNE count_Y_cmp
flag_cmp:
LDA flag,X
AND ora_data,Y
BNE flag_and
flag_ora:
LDA flag,X
ORA ora_data,Y
STA flag,X
BNE count_Y_cmp
flag_and:
LDA flag,X
AND and_data,Y
STA flag,X
count_Y_cmp:
INY
CPY #$08
BCC button_cmp

data_extract:    ;数据恢复
PLA
TAY
PLA
TAX
PLA

return:
RTS

ora_data:   ;按键相或数据
.BYTE $08,$04,$02,$01,$80,$40,$20,$10
and_data:   ;按键相与数据
.BYTE $F7,$FB,$FD,$FE,$7F,$BF,$DF,$EF



;FC数据搬移程序 BY FlameCyclone
.ORG $8200
JMP DATA_COPY_PROTECT

ADDR_DATA_TO = $40    ;目的地址
ADDR_FROM_START = $42    ;源开始地址
ADDR_FROM_END = $44    ;源结束地址

ADDR_TO:    ;目的地址
.BYTE $00,$70
ADDR_BEGIN:    ;源开始地址
.BYTE $00,$83
ADDR_END:    ;源结束地址
.BYTE $FE,$84

INT_ADDR = $08    ;中断地址
FLAG_OVER = $71FF    ;完成标志


DATA_COPY_PROTECT:    ;保护数据
PHP
PHA
TXA
PHA
TYA
PHA
LDA ADDR_DATA_TO
PHA
LDA ADDR_DATA_TO+1
PHA
LDA ADDR_FROM_START
PHA
LDA ADDR_FROM_START+1
PHA
LDA ADDR_FROM_END
PHA
LDA ADDR_FROM_END+1
PHA

OFF_INT:   ;屏蔽中断
LDA INT_ADDR
AND #$7F
STA $2000    ;屏蔽中断


SET_DATA_ADDR_START:    ;设置复制起始地址
LDA ADDR_BEGIN
STA ADDR_FROM_START    ;设置复制起始地址低位
LDA ADDR_BEGIN+1
STA ADDR_FROM_START+1    ;设置复制起始地址高位

SET_DATA_ADDR_END:    ;设置复制结束地址
LDA ADDR_END
STA ADDR_FROM_END    ;设置复制结束地址低位
LDA ADDR_END+1
STA ADDR_FROM_END+1    ;设置复制结束地址高位

SET_DATA_COPY_START:   ;设置目的起始地址
LDA ADDR_TO
STA ADDR_DATA_TO   ;设置目的起始地址低位
LDA ADDR_TO+1
STA ADDR_DATA_TO+1   ;设置目的起始地址高位

OVER_COPY_CMP:    ;复制完成比较
LDA FLAG_OVER
CMP #$FE    ;复制完成标志比较
BEQ DATA_COPY_EXACT

INI_XY_COUNT:   ;计数器初始化
LDX #$00
LDY #$00

COPY_OVER_CMP:    ;地址比较
LDA ADDR_FROM_START
CMP ADDR_FROM_END
BNE COPY_START
LDA ADDR_FROM_START+1
CMP ADDR_FROM_END+1
BEQ COPY_OVER

COPY_START:    ;数据复制开始
LDA (ADDR_FROM_START),Y    ;读取源地址
STA (ADDR_DATA_TO),Y    ;写入目的地址
INC ADDR_FROM_START   ;源地址低位递增
INC ADDR_DATA_TO   ;目的地址低位递增
BNE COPY_JMP
INC ADDR_FROM_START+1   ;源地址高位递增
INC ADDR_DATA_TO+1   ;目的地址高位递增

COPY_JMP:   
JMP COPY_OVER_CMP

COPY_OVER:    ;复制完成
LDA #$FE
STA FLAG_OVER    ;写入完成标志
FINAL_BYTE:
LDA (ADDR_FROM_START),Y    ;读取最后一个字节
STA (ADDR_DATA_TO),Y    ;写入最后一个字节

DATA_COPY_EXACT:    ;恢复数据
LDA INT_ADDR
STA $2000    ;恢复中断
PLA
STA ADDR_FROM_END+1
PLA
STA ADDR_FROM_END
PLA
STA ADDR_FROM_START+1
PLA
STA ADDR_FROM_START
PLA
STA ADDR_DATA_TO+1
PLA
STA ADDR_DATA_TO
PLA
TAY
PLA
TAX
PLA
PLP



DATA_COPY_RETURN:
RTS

.ORG $C056    ;精灵指令覆盖
JSR $FFB5

.ORG $FFB5    ;
PHA
TXA
PHA
TYA
PHA
LDA $71FF    ;比较7000-71FE数据是否完成复制
CMP #$FE
BNE ADDR_FFCA
PLA
TAY
PLA
TAX
PLA
JSR $7000   ;跳转到自写程序
RTS
ADDR_FFCA:
PLA
TAY
PLA
TAX
PLA
RTS



.ORG $C264    ;自定义的MAPPER2切页程序
PHA
TXA
PHA
LDA $0066
BNE ADDRC280
LDA #$07
LDX #$03
JSR $CD9B    ;自带的切bank方法
PLA
TAX
PLA
JSR $8000
LDA #$06
LDX #$03
JSR $CD9B    ;切回原该切得bank(可以不用)
RTS
ADDRC280:
PLA
TAX
PLA
RTS


;[最终任务PPU]
.ORG $C056    ;跳转到PPU重写程序
JSR $7000

.ORG $CEBF
JSR STAGE_DATA_WRITE    ;跳转到关卡数据写入

.ORG $E460
JSR BULLET_DATA_WRITE    ;跳转到副武器数据写入

.ORG $71F0
STAGE_DATA_WRITE:
LDA $6010
STA $1E    ;关卡写入
LDA #$00
RTS
.ORG $71C0
BULLET_DATA_WRITE:    ;副武器数据写入
CPX #$0E
BCS P2_BUL
P1_BUL:
LDA $6004
JSR $D7D0    ;P1副武器数据写入
RTS
P2_BUL:
LDA $6005
JSR $D7D0    ;P2副武器数据写入
RTS


.ORG $7000

STY $4014    ;补上覆盖的精灵写入指令
PHA
TXA
PHA
TYA
PHA
LDA $0C
CMP #$01    ;比较是否为标题画面
BEQ PPU_STAGE
PLA
TAY
PLA
TAX
PLA
RTS
PPU_STAGE:    ;STAGE显示程序
LDA PPU_ADDR_DATA
STA $2006
LDA PPU_ADDR_DATA+1
STA $2006    ;坐标设置
LDX #$00
PPU_STAGE_WROTE:    ;写入STAGE字模
LDA STAGE_DATA,X
STA $2007
INX
CPX #$06
BCC PPU_STAGE_WROTE
LDA $6010
CMP #$FF    ;关卡数据初始化条件判断
BNE KEY_B
LDA #$00
STA $6010    ;关卡数据初始化
KEY_B:    ;关卡减少
LDA $04
AND #$42    ;按键B或左减关
BEQ KEY_A
LDA $6010
CMP #$00    ;关卡比较
BEQ KEY_A
DEC $6010   ;减关
KEY_A:    ;关卡增加
LDA $04
AND #$81    ;按键A或右加关
BEQ PPU_NUM_WRITE
LDA $6010
CMP #$04    ;关卡比较
BEQ PPU_NUM_WRITE
INC $6010    ;加关
PPU_NUM_WRITE:
LDA $6010
TAX
LDA STAGE_NUM,X    ;写入数字
STA $2007
PPU_RTS:
PLA
TAY
PLA
TAX
PLA
RTS


STAGE_DATA:    ;关卡文字S,T,A,G,E,字模数据
.BYTE $EC,$ED,$DA,$E0,$DE,00
STAGE_NUM:    ;关卡数字1,2,3,4,5字模数据
.BYTE $D1,$D2,$D3,$D4,$D5

PPU_ADDR_DATA:
.BYTE $23,$0C

九月鹰飞 发表于 2017-4-1 14:04:39

旋风又在发布高深游戏文化了 呵呵呵 顶顶顶
页: [1]
查看完整版本: [FC教程][最终任务][修改实例]