|  | 
 
| 本帖最后由 jiangzhengwenjz 于 2015-2-25 11:37 编辑 
 由于本人还是个改版新手,平时课业繁忙只有寒暑假有空,知识掌握的不够多,也缺乏经验,不足错漏之处恳请指正。由于是手记,不是教程,为防误人子弟,不得转载。
 从上周开始有在学习一些新的技术,现在把它贴出来,可以说是个简单的应用了。这些内存地址仅限于火红。
 
 
 
 背景介绍:
 说到选择性删除,第一点就是“选择”。查阅JPAN关于special的研究可知,special 0x9F可以呼出选择精灵的效果。不仅如此,其还会把得到的值(0~5)存进变量0x8004,而0x8004的内存地址可以用公式计算,所以我们认为这个方案是简单可行的。其值+1即为精灵编号(1~6)。
 
 然后便是“删除”了。依然是根据JPAN的小程序。当然代码的解释我们等会儿再谈。
 当然仅仅这样肯定不够,我们来个简单应用(一段脚本,虽然没有什么实际作用,单纯地选择然后删除精灵):复制代码                .text
                .align 2
                .thumb
                .thumb_func
Delete_func:        Push {r0-r4, lr}
                Ldr r0,  .Var_addr        
                Ldrh r0, [r0, #0x0]
                Cmp r0, #0x5                
                Bgt end                
                Ldr r1, .Party_addr        
                Mov r2, #0x64        
                Mul r2, r0                
                Add r1, r2, r1                
                Add r3, r1, #0x0        
                Add r3, #0x64                
main_loop:        mov r2, #0x0                
                mov r4, #0x0                
                cmp r0, #0x5
                beq delete_loop        
                add r0, #0x1                
copy_loop:        Ldr r4, [r3, #0x0]        
                str r4, [r1, #0x0]        
                add r3, #0x4                
                add r1, #0x4                
                add r2, #0x4                
                cmp r2, #0x64
                beq main_loop
                b copy_loop                                        
delete_loop:        str r4, [r1, #0x0]        
                add r1, #0x4
                add r2, #0x4
                cmp r2, #0x64
                bne delete_loop
end:                pop {r0-r4, pc}
.align 2
.Var_addr: .word 0x020370c0
.Party_addr: .word 0x02024284
 
 
 脚本段:
 其中我把thumb码编译于75D1B0,这从脚本上看应该是显然的。复制代码'---------------
#org @start
msgbox @string1 0x2 '"Select a Pokemon. "
special 0x9F
waitstate
callasm 0x875D1B1
release
end
'---------
' Strings
'---------
#org @string1
= Select a Pokemon. 
值得注意的是waitstate,必不可少。
 
 显然这段脚本有个bug,那就是就算减到1只精灵还可以继续减。这个问题如何解决呢?利用countpokemon命令即可。当然这样得到的值将被存在0x800D中,而且是1~6,不是0~5。
 利用这个命令,配合一些判断和跳转,应该是可以达成一些应用了,这里不多啰嗦了。
 
 然后是对thumb代码的解释了。
 
 
 
 解释:
 Delete_func只会运行一次,首先检测0x8004中的值是不是在0~5之间,否则直接跳转到end,这是佷容易看出来的。
 后面的loop部分也不难看懂,我说说我的理解。
 
 在main_loop,一方面将r4清零,一方面执行检测,看r0是不是5了,如果是,直接删除精灵即可。(跳转到delete_loop)。如果不是,进入copy循环,r2担当计数器的功能,因为每个精灵占有100字节,达成的效果是将后面的精灵数据向前移动。每次r1和r3都会增长4,这样达成的效果是逐次移动,由于有r2的存在,可以确保移动100字节。注意到在main_loop中每次r0不是5时,r0都会+1,因此r0其实也担当了计数器功能,确保移动精灵数量正确。当r0为5时,进入delete_loop,依然是用r2做计数器的老套路,把r1中指向的内存数据逐次写入0即可。在进入copy_loop之后r1的值虽然改变,其实是合理的,本质上是删除重复的那只精灵罢了。
 
 
 
 后记:
 简单归简单,但对我等改版新手来说并不是那么容易,昨天真心花了好久才搞定。不足之处,还请指出探讨。(如果不想在脚本中执行检测,请参考Hackmew的代码。)
 
 
 
 | 
 |