zoukankan      html  css  js  c++  java
  • 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

    本文待完善。

  • 相关阅读:
    【Linux_Unix系统编程】Chapter4 文件IO
    【Unix网络编程】chapter6 IO复用:select和poll函数
    【Unix网络编程】 chapter5 TCP客户,服务器程序实例
    【Unix网络编程】chapter3 套接字编程简介
    VS自动编译脚本
    【Python编程:从入门到实践】chapter4 操作列表
    【Python编程:从入门到实践】chapter3 列表简介
    【Python编程:从入门到实践】chapter2 变量和简单数据类型
    【Unix网络编程】chapter2传输层:TCP,UDP和SCTP
    vim配置编辑php
  • 原文地址:https://www.cnblogs.com/leisureeen/p/cjml.html
Copyright © 2011-2022 走看看