Leisureeen

导航

FC超级玛丽研究(NES游戏)

理解本文需要6502汇编语言基础,读者可先阅读本人之前的一篇文章6502汇编指令速查表.pdf

为便于理解,本文所有内存地址都用[]表示(如:[00CE]),所有ROM文件地址都用<>表示(如:<00CE>),所有数值都用$前缀或0x前缀表示(如:$CE或0xCE),$CE主要用于表示汇编语言十六进制数,0xCE主要用于表示文字注释十六进制数。

 

定义关卡表示方式

第x大关的第y小关简称x-y,例句:关卡8-4为最后一关。

8-4过去后可进入难度加大版,同样是从1-1关开始,变化主要有:蘑菇怪变铁乌龟,一些敌人步行速度快了,梯子短了,锤子龟爆发容忍时间短了。

 

定义敌人名称

蘑菇怪:最简单的敌人,只能在地上缓慢步行,一踩就死。

乌龟:踩一下静止不动,再碰一下就滑行。

铁乌龟:同乌龟,但不怕火力花。

刺猬:不可踩,但怕火力花。

快乐云:不断放置刺猬,但场景里一般最多出现3个刺猬(内存限制)。

章鱼:在水里出现,斜向上运动或垂直向下运动。

鱼群:在水里出现,或成为飞鱼。

锤子龟:会扔锤子,但怕火力花。此敌人一开始在原地跳跃上下运动且扔锤子,过一段时间(锤子龟爆发容忍时间)后,锤子龟爆发,直接向左走,遇到障碍就跳过去,整个过程都扔锤子。

导弹:可踩,但不怕火力花。

火焰:不可踩(以下和火、库巴有关的均不可踩),一般由库巴喷出。

火串:不断旋转。

火球:从岩浆中向上喷出,到达最高点后降落。

库巴:会喷火(生成不同高度的火焰)和扔锤子。

 

避免在fceux中运行出现0-1关

将<031E>处的8D5F07用EA填充

 

内存地址含义

[0057]玛丽X方向运动速度(矢量,符号位代表方向)

[0058]-[005C]敌人X方向运动速度,最多容纳5个敌人,且出现5个敌人时,其中2个敌人会闪烁

[0086]-[008B]玛丽横坐标和敌人横坐标

[008D]和[008E]火力花横坐标

[00A6]和[00A7]火力花方向(0x04向下方向,0xFD向上弹起)

[00CE]玛丽高度,[00CF]-[00D3]敌人高度,[00D5]火力花高度

[00FA]置1后播放暂停音效关闭背景音乐,置2后播放取消暂停音效打开背景音乐

[00FD]-[00FF]对这3个字节其中的1bit置1可播放对应的音效(bit代表其中一位,一个字节有8位)

[0117]和[0118]得分位置X方向,[011E]和[011F]得分位置Y方向

[075A]生命数,0x00表示剩余可用生命数为0

[075E]真正的金币数量地址

[075F]当前大关,[0760]当前小关(都是从0开始标,即0x0000表示1-1,0x0703表示8-4)

[07DD]连续6字节为分数地址

[07EC]-[07EE]金币数量百位、十位、个位显示

[07F8]-[07FA]时间百位、十位、个位

 

运行时地址(即内存地址)与ROM文件地址对应关系

例:运行时内存地址[C30C]对应于ROM文件地址<431C>

关系:运行时内存地址=ROM文件地址+7FF0

解释:运行游戏时需要将ROM文件里的指令和数据存放到内存中

 

修改ROM文件可实现的效果

<36D7>的A903指令可改火力花初始方向

<3A41>炮台向右导弹速度,<3A42>炮台向左导弹速度

<431C>的0xF8蘑菇怪步行速度、乌龟步行速度、铁乌龟步行速度,<431D>难度加大版对应速度

<4336>锤子龟爆发容忍的时间默认0x80,<4337>难度加大版锤子龟爆发容忍的时间默认0x50

将<4AA8>的内容用EAEAEA填充可使敌人不下落

修改<4C50>的0xE8可变空中导弹速度

<585F>的0x30乌龟滑行速度

将<5B4C>用EAEA填充可不反转

 

判断是否出现食人花
00:98F2:AD.60.07..*LDA.$0760;00:98F5:0D.5F.07..*ORA.$075F;00:98F8:F0.2B.....*BEQ.$9925

当[0760]和[075F]均为0时跳过食人花,均为0恰好表示1-1关(下标从0开始),所以只有关卡1-1没有食人花,其余关卡水管均有食人花。

如将0xF0改为0x10可关闭食人花,因为这样就强制跳过布置食人花的指令(当然改为102B并不是强制向后跳转0x2B个字节,只是不为负背景下的等价)。

 

判断时间是否为0,Time up
00:B769:AD.F8.07..*LDA.$07F8;00:B76C:0D.F9.07..*ORA.$07F9;00:B76F:0D.FA.07..*ORA.$07FA;00:B772:F0.26.....*BEQ.$B79A

如果[07F8]连续3个字节均为0则代表时间为0

 

过关结算时间
01:D312:AD.F8.07..*LDA.$07F8;01:D315:0D.F9.07..*ORA.$07F9;01:D318:0D.FA.07..*ORA.$07FA;01:D31B:F0.F1.....*BEQ.$D30E

 

100金币生命数+1
00:BC0C:EE.5E.07..*INC.$075E;00:BC0F:AD.5E.07..*LDA.$075E;00:BC12:C9.64.....*CMP.#$64;00:BC14:D0.0C.....*BNE.$BC22;00:BC16:A9.00.....*LDA.#$00;00:BC18:8D.5E.07..*STA.$075E;00:BC1B:EE.5A.07..*INC.$075A;00:BC1E:A9.40.....*LDA.#$40;00:BC20:85.FE.....*STA.$00FE;00:BC22:A9.02.....*LDA.#$02

这段指令为玛丽吃到金币后的事件指令。首先[075E]自增1,让金币数量加1,然后读取金币数量,和0x64(对应十进制的100)进行比较,如果不等就向后跳转0x0C个字节,吃金币事件就结束了,如果相等就不跳转,将[075E]置0,表示金币数量清零,然后[075A]自增1,表示生命数加1,最后将[00FE]置0x40,表示播放1UP的音效。

 

敌人下落修改高度
00:BFEB:75.CE.....*ADC.$CE,X;00:BFED:95.CE.....*STA.$CE,X

0x75改成0xB5(即LDA),无法实现,因为玛丽也不下降了,将<4AA8>的内容用EAEAEA填充可使敌人不下落

 

喷火速度
01:D204:B5.87.....*LDA.$87,X;01:D206:E9.01.....*SBC.#$01;01:D208:95.87.....*STA.$87,X

火焰横坐标自减一,实现喷火效果,如修改E901为E902则2倍喷火速度。

 

求敌人反转后的X方向运动速度
01:DB36:B5.58.....*LDA.$58,X;01:DB38:49.FF.....*EOR.#$FF;01:DB3A:A8........*TAY;01:DB3B:C8........*INY;01:DB3C:94.58.....*STY.$58,X

首先读取敌人的速度,然后和0xFF异或一下,相当于按位取反,再存到Y里面自增一下,最后存回敌人速度内存区域。

可形成+1和-1互换,+2和-2互换等等。即0x01和0xFF,0x02和0xFE。

 

敌人反转详细汇编指令
01:DB1C:B5.16.....*LDA.$16,X;01:DB1E:C9.0D.....*CMP.#$0D;01:DB20:F0.22.....*BEQ.$DB44;01:DB22:C9.11.....*CMP.#$11;01:DB24:F0.1E.....*BEQ.$DB44;01:DB26:C9.05.....*CMP.#$05;01:DB28:F0.1A.....*BEQ.$DB44;01:DB2A:C9.12.....*CMP.#$12;01:DB2C:F0.08.....*BEQ.$DB36;01:DB2E:C9.0E.....*CMP.#$0E;01:DB30:F0.04.....*BEQ.$DB36;01:DB32:C9.07.....*CMP.#$07;01:DB34:B0.0E.....*BCS.$DB44;01:DB36:B5.58.....*LDA.$58,X;01:DB38:49.FF.....*EOR.#$FF;01:DB3A:A8........*TAY;01:DB3B:C8........*INY;01:DB3C:94.58.....*STY.$58,X;01:DB3E:B5.46.....*LDA.$46,X;01:DB40:49.03.....*EOR.#$03;01:DB42:95.46.....*STA.$46,X

 

本文待完善。

posted on 2021-05-14 16:15  Leisureeen  阅读(1162)  评论(0编辑  收藏  举报

JS