注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

疾风之狼博客

 
 
 

日志

 
 

[转载]FC手柄控制与实例分析 作者:zHAOsILi[EGCG](.zZ~~)   

2007-04-14 13:08:50|  分类: NES资料 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

FC手柄控制与实例分析

2005.9.3
作者:zHAOsILi[EGCG](.zZ~~) 转载请注明

关于FC的手柄控制

当FC的程序需要得到手柄的按键状态时,需要写$4016的最低位为1,将手柄按键的状态载入到一个串行的寄存器中,
接着写$4016的最低位为0,载入完成。读取按键状态时,是1位1位读出来的。读$4016为读取手柄1,读$4017为手柄2
,而且值都在最低位。读取的顺序为A,B,SELECT,START,UP,DOWN,LEFT,RIGHT,也就是说在按键状态载入完成
后,第一次读$4016($4017)最低位得到的是手柄1(2) A键的状态(0为没按下,1为按下),第二次读自动变为 B键的状
态,第三次读为SELECT键的状态,以此类推。

实例分析

ROM:Contra Force (U).nes
工具:FCEUXD SP,UltraCompare Professional
目标:将这个游戏改成可以连跳的版本

下$4016写断点,可以得到附近的程序,如下

$FF97:A2 00     LDX #$00
$FF99:20 C8 FF  JSR $FFC8;第一次读按键状态
{
 START:
 $FFC8:A0 01     LDY #$01       
 $FFCA:8C 16 40  STY $4016       ;[4016]=1,载入手柄按键状态
 $FFCD:88        DEY
 $FFCE:8C 16 40  STY $4016       ;[4016]=0,载入结束
 $FFD1:A0 08     LDY #$08        ;循环8次
 ;下面BNE到这里
 $FFD3:AD 16 40  LDA $4016       ;A=[4016]
 $FFD6:85 04     STA $04         ;[04]=A
 $FFD8:4A        LSR A  ;A>>1
 $FFD9:05 04     ORA $04         ;A=A|[04]
 $FFDB:4A        LSR A  ;A>>1
 ;以下C代表C标志位
 ;A=[4016]
 ;C=(A|(A>>1))&1,通过$FFDB处的指令,[4016]的最低位被送到了C标志位
 ;A=(A|(A>>1))>>1
 $FFDC:36 00     ROL $00,X ;9位(加上C标志位)循环左移
     ; 1位 8位        8位   1位
      ;(C _ [00+X])->([00+X] _ C)
 $FFDE:AD 17 40  LDA $4017       ;手柄2
 $FFE1:85 05     STA $05        
 $FFE3:4A        LSR A
 $FFE4:05 05     ORA $05        
 $FFE6:4A        LSR A
 $FFE7:36 01     ROL $01,X
 $FFE9:88        DEY
 $FFEA:D0 E7     BNE $FFD3
 $FFEC:60        RTS
 ;结束[00+X]=0  0  0       0      0   0     0     0
 ;           A, B, SELECT, START, UP, DOWN, LEFT, RIGHT
}
$FF9C:A2 02     LDX #$02
$FF9E:20 C8 FF  JSR $FFC8;第二次读按键状态
$FFA1:A5 00     LDA $00;[00]为手柄1第一次读出的按键状态
$FFA3:C5 02     CMP $02;[02]为手柄1第二次读出的按键状态
$FFA5:D0 1A     BNE $FFC1;跳则说明按键状态不稳定,并让[40]=[41]=0
$FFA7:A5 01     LDA $01
$FFA9:C5 03     CMP $03
$FFAB:D0 14     BNE $FFC1;手柄2
$FFAD:A2 00     LDX #$00
$FFAF:20 B3 FF  JSR $FFB3;手柄1和手柄2的按键状态分别传到[40]和[41]
{
 $FFB2:E8        INX
 $FFB3:B5 00     LDA $00,X
 $FFB5:A8        TAY
 $FFB6:55 FA     EOR $FA,X;此时[FA]为上次调用时手柄的状态
 $FFB8:35 00     AND $00,X
 ;A=(A^[$FA+X])&[00+X]  A的某一位为1仅当对应的按键的状态由0变至1时
 $FFBA:95 40     STA $40,X;  ^
 $FFBC:95 F8     STA $F8,X; -|
 $FFBE:94 FA     STY $FA,X;令[FA+X]为此次调用时,手柄的按键状态
 $FFC0:60        RTS;第一次返回到$FFB2,正好令X加1,这段程序被调用了两次
      ;第一次处理手柄1,第二次处理手柄2
}
$FFC1:A9 00     LDA #$00
$FFC3:85 40     STA $0040
$FFC5:85 41     STA $0041
$FFC7:60        RTS

下$FA读断点,可以来到

$BFEE:A2 01     LDX #$01
$BFF0:B5 FA     LDA $FA,X
$BFF2:A8        TAY
$BFF3:3D 71 03  AND $0371,X
$BFF6:95 42     STA $42,X;按键状态被传到了[42+X]
$BFF8:98        TYA
$BFF9:9D 71 03  STA $0371,X
$BFFC:CA        DEX
$BFFD:10 F1     BPL $BFF0
$BFFF:60        RTS

下$42读断点可以来到

$A302:B5 42     LDA $42,X
$A304:29 0F     AND #$0F
$A306:A8        TAY
$A307:20 38 F3  JSR $F338
$A30A:85 00     STA $00
$A30C:B5 42     LDA $42,X
$A30E:15 40     ORA $40,X
$A310:29 F0     AND #$F0;
$A312:85 01     STA $01;
$A314:20 78 91  JSR $9178
$A317:F0 1D     BEQ $A336
$A319:A5 00     LDA $00
$A31B:29 0F     AND #$0F
$A31D:D0 08     BNE $A327
$A31F:BD AA 07  LDA $07AA,X
$A322:29 70     AND #$70
$A324:4C 30 A3  JMP $A330
.很
.长 硬看会郁闷的。。。
.的
$A4D6:A5 42     LDA $42
$A4D8:05 43     ORA $43
$A4DA:29 10     AND #$10;手柄1或手柄2按了START键?
$A4DC:F0 02     BEQ $A4E0
$A4DE:E6 5B     INC $5B
$A4E0:60        RTS

但应该是这段程序中的某一个跳转决定了是否可以继续往上跳跃,修改只要知道程序走向就可以了,没必要硬看。
对$42下条件读断点,条件为$42==#80,等角色站着时,按A键,就会中断,用Trace Logger,选Browse,存为1.txt,
Start Logging,把$42读条件断点禁用了,然后对$A302下条件执行断点,条件为$42==#0,执行,等再次中断时,点Stop
Logging,将$A302断点也给禁用了。
将角色跳到空中,等角色处于下落阶段时,将$A302条件执行断点启用,用Hex Editor,将$42写80,Trace Logger中,
选Browse,存为2.txt,Start Logging,执行,等再次中断时,点Stop Logging。
用UltraCompare Professional比较1.txt,和2.txt,会发现程序流程的几处不同,其中

$A3A6:95 CD     STA $CD,X
$A3A8:A9 20     LDA #$20
$A3AA:1D AA 07  ORA $07AA,X
$A3AD:9D AA 07  STA $07AA,X
$A3B0:29 40     AND #$40
$A3B2:D0 27     BNE $A3DB;这个就是关键跳转,如果跳到A3DB的话,就不能连续跳跃了,故NOP掉
$A3B4:B5 CD     LDA $CD,X
$A3B6:29 02     AND #$02
$A3B8:D0 16     BNE $A3D0
$A3BA:A5 01     LDA $01
$A3BC:29 80     AND #$80

让程序在$A302处中断,切换到Hex Editor,找到A3B2,右击,选Go Here In Rom File,然后把D0 27修改为EA EA,点File,选
Save Rom,修改完成。

  评论这张
 
阅读(249)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017