(接10楼)
解析:做完了“受伤不直接变小”的补丁,自然还想再移植一个来自SMB后期版本的特性,比如吃个花就直接变成可以发子弹的状态

说起来简单,看过代码之后发现,这个修改可不像上次那样改2个字节就完事了(虽然改2个字节达成的效果也并不理想),牵涉太多,肯定要大改。
原始程序对蘑菇和花的处理方式是“一视同仁”的,即不管到底是蘑菇还是花,只看人物当前的状态:小个子变大,大个子变火力花状态,火力花状态什么都不做。现在要想修改这个逻辑,就必须把蘑菇和花分开判断,把“吃蘑菇变大”和“吃花变火力花状态”这两个逻辑给对应起来。
那就这样分开呗,先尝试着小小修改了一下,然后一测试发现——小个子吃到花之后确实可以发子弹了,但还是小个子!上次刚修了这个bug,结果这次又直接把这个bug给写出来了


那再把$0756和$0754这两个内存绑定起来?也不行,“变火力花状态”的程序并没有触发“反转$0754”的程序,改那里也行不通……
看来,只能在“变火力花状态”程序里加个令$0754=0的指令了。但是……刚才的修改只是调整了部分代码的顺序,把一个判断(比较指令)移到了另一个地方,并没有删掉指令,也就没有地方可以加指令了。这可怎么办……
于是再仔细看代码,找找有没有多余的指令。反复观察之后,注意到这样一条指令:LDX $08(而且出现了两次),它是干什么用的呢?根据分析,这应该是从内存$0008读取“敌人编号”的指令,当处理屏幕上的敌人时,需要用到一个偏移值(比如LDA $16,X这样的指令),这个偏移值X就是敌人编号,在处理敌人的程序中,这个编号是暂时保存在内存$0008当中的,这样,如果某段程序需要临时使用寄存器X,就可以放心使用,用完之后再从$0008把X的值读取回来就行了。
那么,这段程序改变过X的值么?然而并没有……事实上,整段程序除了这两句LDX $08,就没有别的指令动过X

——除了那几个调用子程序的JSR指令;实际上,$85F1处的程序确实改变了X的值,所以后面似乎有必要写一个LDX $08来恢复X的值。但是,一定要写在这里么?再看看$D948处的程序,我们会发现,这段程序的最后正好有一句LDX $08!嗯,这么一来,两句LDX $08就都可以删掉了,腾出了4个字节的空间。
不过,只有4个字节么……够用么?先看看各个寄存器当前的取值吧:
A——这里刚刚读取过$0756,用来判断吃花之后是否需要有动作,有动作的$0756取值为0或1;
X——道具类敌人的编号必然是5;
Y——这段程序到目前为止也没用过Y,向前回溯可以知道,最近一次读取到Y的值是敌人ID,道具类敌人的ID=$2E。
好吧,没有一个寄存器正好是0……但是,如果按照常规的写法:LDA #$00 / STA $0754,这样需要5个字节……
等等!有没有别的办法把A变成0的?除以2?(可是6502不是没有除法么

)嗯,是没有除法,但是有移位运算啊。就决定是你了,LSR!正好只需要1个字节!
于是,这就成为了我近年的得意作品
