Pokemon Center | 口袋中心 以口袋妖怪为主题并带有其他动漫游戏的讨论

 找回密码
 加入口袋中心
搜索
查看: 3648|回复: 2

【手记】选择性删除携带精灵

[复制链接]

3369

回帖

535

现金

485

勋章券

超级版主

Rank: 26Rank: 26Rank: 26Rank: 26Rank: 26Rank: 26

积分
22138
QQ

时光印记Lv.3挥金如土勋章水中王者勋章Lv3Omega红宝石发售确认纪念章Alpha蓝宝石发售确认纪念章金银好CP-Ho-oh/LUGIA【里】金银好CP-Ho-oh/LUGIA【真·正常向】异化型LUGIA【M超梦版】

发表于 2015-2-17 12:17:17 | 显示全部楼层 |阅读模式
本帖最后由 jiangzhengwenjz 于 2015-2-25 11:37 编辑

由于本人还是个改版新手,平时课业繁忙只有寒暑假有空,知识掌握的不够多,也缺乏经验,不足错漏之处恳请指正。由于是手记,不是教程,为防误人子弟,不得转载。
从上周开始有在学习一些新的技术,现在把它贴出来,可以说是个简单的应用了。这些内存地址仅限于火红。



背景介绍:
说到选择性删除,第一点就是“选择”。查阅JPAN关于special的研究可知,special 0x9F可以呼出选择精灵的效果。不仅如此,其还会把得到的值(0~5)存进变量0x8004,而0x8004的内存地址可以用公式计算,所以我们认为这个方案是简单可行的。其值+1即为精灵编号(1~6)。

然后便是“删除”了。依然是根据JPAN的小程序。当然代码的解释我们等会儿再谈。
  1.                 .text
  2.                 .align 2
  3.                 .thumb
  4.                 .thumb_func
  5. Delete_func:        Push {r0-r4, lr}
  6.                 Ldr r0,  .Var_addr        
  7.                 Ldrh r0, [r0, #0x0]
  8.                 Cmp r0, #0x5               
  9.                 Bgt end               
  10.                 Ldr r1, .Party_addr        
  11.                 Mov r2, #0x64        
  12.                 Mul r2, r0               
  13.                 Add r1, r2, r1               
  14.                 Add r3, r1, #0x0        
  15.                 Add r3, #0x64               
  16. main_loop:        mov r2, #0x0               
  17.                 mov r4, #0x0               
  18.                 cmp r0, #0x5
  19.                 beq delete_loop        
  20.                 add r0, #0x1               
  21. copy_loop:        Ldr r4, [r3, #0x0]        
  22.                 str r4, [r1, #0x0]        
  23.                 add r3, #0x4               
  24.                 add r1, #0x4               
  25.                 add r2, #0x4               
  26.                 cmp r2, #0x64
  27.                 beq main_loop
  28.                 b copy_loop                                       
  29. delete_loop:        str r4, [r1, #0x0]        
  30.                 add r1, #0x4
  31.                 add r2, #0x4
  32.                 cmp r2, #0x64
  33.                 bne delete_loop
  34. end:                pop {r0-r4, pc}
  35. .align 2
  36. .Var_addr: .word 0x020370c0
  37. .Party_addr: .word 0x02024284
复制代码
当然仅仅这样肯定不够,我们来个简单应用(一段脚本,虽然没有什么实际作用,单纯地选择然后删除精灵):



脚本段:
  1. '---------------
  2. #org @start
  3. msgbox @string1 0x2 '"Select a Pokemon. "
  4. special 0x9F
  5. waitstate
  6. callasm 0x875D1B1
  7. release
  8. end


  9. '---------
  10. ' Strings
  11. '---------
  12. #org @string1
  13. = Select a Pokemon.
复制代码
其中我把thumb码编译于75D1B0,这从脚本上看应该是显然的。
值得注意的是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的代码。)


回复

使用道具 举报

263

回帖

379

现金

3

勋章券

摆脱困境的长叹

Rank: 8Rank: 8Rank: 8Rank: 8

积分
696

时光印记Lv.1水中王者勋章Lv1Alpha蓝宝石发售确认纪念章Omega红宝石发售确认纪念章XY系列-爆炸才是男人的浪漫No.252 木守宫

发表于 2015-2-17 18:41:16 | 显示全部楼层
围观聚聚~~~~~
回复 支持 反对

使用道具 举报

227

回帖

3492

现金

1

勋章券

碧蓝大海飞溅的水滴

Rank: 9

积分
769

时光印记Lv.1水中王者勋章Lv1

发表于 2015-2-17 20:00:24 | 显示全部楼层
围观菊苣
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入口袋中心

本版积分规则

手机版|Archiver|Pokemon Center

GMT+8, 2024-11-23 21:34 , Processed in 0.113771 second(s), 48 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表