|
本帖最后由 jiangzhengwenjz 于 2018-2-10 22:44 编辑
由于时间所限,接下来相当长的时间内我都不可能分出精力用在改版上,所以如我之前所说,将会转载一部分国外的优秀教程,当然仅仅是应用的话对改版者的技术要求很低。
不过,虽然都是基础教程,至少也要求读者懂得如何编辑数据,如何使用指针等基础操作,关于这些在教程里都不会多说。如果你阅读这些内容有困难的话,应该先去做一些更简单的尝试以积累经验。当然这些教程不会是对原贴逐句翻译,只是在厘清思路的基础上把各个部分的操作要点讲清楚,这样看起来可能反而更轻松。
此外所转载的教程都由我先测试过,对于其中的一些问题也会加以修正。
原贴:https://www.pokecommunity.com/showthread.php?t=326311
标题:Pokéball hacking guide
作者: Daniils
本帖不得转载,转载英文原贴务必自觉注明网址!
1. 背景介绍
二代和四代、五代特有的精灵球在火红中统统不存在,而之前没有这样一个新增精灵球的帖子。唯一的资料来源是JPAN研究战斗脚本时对球所作的研究。Daniils在此基础上作了修改,现在可以很轻易地做到新增精灵球。
2. 修改步骤
2.1 修改精灵数据加密/解密函数
这一步是为了扩充精灵数据中球数据的空间,这里的做法是把精灵来源数据的一个二进制位让渡给球数据了,这样就不能判别传送自XD/竞技场的精灵。这样修改之后支持球的数量就增加了一倍(准确说不是,因为值0不被使用),或者说可以额外加19个球。
只需在以下地址写入指定数据:- 080400B6 - 80
- 080400B8 - 44
- 080400BE - 0B
- 08040855 - FC
- 0804085A - 1F
- 0804085E - 89
- 08040862 - 7C
复制代码 不过这样修改的话就不能使用原有的存档了,因为这样会造成球数据读取的混乱,重新开档吧。
2.2 修改各球战斗脚本读取方式
这一步是为了修改各个球的丢球脚本读取方式,这样也就不必每次增加球都进行一次扩充了。
先找空位写入这一段源码:- .text
- .align 2
- .thumb
- .thumb_func
- .global ballchecker
- ballcompare:
- mov r0, #0x2C
- mul r0, r1
- mov r10, r1
- ldr r1, itemdata
- add r1, r0, r1
- add r1, #0x1A
- ldrb r0, [r1]
- cmp r0, #0x3
- beq isball
- otherstuffcompare:
- mov r1, r10
- cmp r1, #0x50
- beq dolly
- cmp r1, #0x51
- beq dolly
- mov r0, #0xaf
- lsl r0, r0, #0x1
- cmp r1, r0
- beq flute
- ldr r0, return_addr
- bx r0
- isball:
- ldr r0, somevar
- add r1, #0x1
- ldrb r1, [r1]
- strb r1, [r0]
- ldr r0, ball_script
- cmp r1, #0x11 /*If you want to have a second safari ball like the park ball, place its pokeball index here*/
- beq safari /*Otherwise, remove these two lines*/
- cmp r1, #0x5
- bne preender
- safari:
- add r0, #0x28
- preender:
- b script_ender
- dolly:
- ldr r0, doll_script
- b script_ender
- flute:
- ldr r0, flute_script
- script_ender:
- ldr r1, script_ptr
- str r0, [r1]
- ldr r1, be3_addr
- mov r10, r1
- ldr r0, end_addr
- bx r0
- .align 2
- ball_script: .word 0x081D9A14
- doll_script: .word 0x081D9B7C
- flute_script: .word 0x081D9B86
- script_ptr: .word 0x02023d74
- be3_addr: .word 0x02023be3
- return_addr: .word 0x080164e9
- end_addr: .word 0x0801671f
- itemdata: .word 0x083DB028
- somevar: .word 0x0203fe00
复制代码 其中的几个需要注意的点:
关于这2行- cmp r1, #0x11 /*If you want to have a second safari ball like the park ball, place its pokeball index here*/
- beq safari /*Otherwise, remove these two lines*/
复制代码 是为了四代中的公园球而设定,如果不打算加入的话直接把它们删掉。如果有的话将0x11改为球编号(球编号是在道具数据结构中,后面提到)- itemdata: .word 0x083DB028
复制代码 这是道具表格的地址,如果你有扩充过把它改了就行- somevar: .word 0x0203fe00
复制代码 这是内存空位,不必用JPAN saveblock hack中的内存区域,如果没冲突可以不改。
此外还需要在这些地址写入这个内存指针(看不懂的话只需要看其中的地址就可以):- .org 0x802D500
- .word balltraceloc
- .org 0x802D544
- .word balltraceloc
- .org 0x802D6A0
- .word balltraceloc
- .org 0x802D71C
- .word balltraceloc
- .org 0x802D7B8
- .word balltraceloc
- .org 0x80EF4B4
- .word balltraceloc
- .org 0x80EF4DC
- .word balltraceloc
- .org 0x80EF674
- .word balltraceloc
- .org 0x80EF9AC
- .word balltraceloc
- .org 0x80F0368
- .word balltraceloc
- .org 0x8016B10
- .word balltraceloc
- .org 0x80EF7C8
- .word balltraceloc
- .org 0x800E3C4
- .word balltraceloc
复制代码 接下来在0x8016460写入00 00 00 00 0B 4A 97 46
并在0x8016494写入上面源码的指针(不需要+1)
关于之前所说的球编号,这是在道具数据结构中偏移量为1b的1字节,这里我们从1开始编,比如这个是大师球的数据:- .byte 0x10, 0x39, 0x09, 0x5D, 0x0B, 0x14, 0xFF, 0xBC, 0xBB, 0xC6, 0xC6, 0xFF, 0x00, 0x00 @道具文本内部编码
- .hword 0x0001 @道具编号
- .hword 0x0000 @价钱
- .byte 0x00, 0x00
- .word 0x083D4ECC @介绍文本指针
- .hword 0x0000
- .byte 0x03
- .byte 0x01 @球编号
- .word 0x00000000
- .word 0x00000002
- .word 0x080A1E1D
- .word 0x00000000
复制代码 关于道具数据结构可以看百科:http://bulbapedia.bulbagarden.ne ... e_in_Generation_III
所以对于原有的球,改为和它的道具编号相同,其他球则是每次按+1方式增长。
完善了所有球的数据后,还需要完善所有球的图片、色板。
关于这些内容的地址、数据结构可以参考Ta之境界的这篇帖子中的相关内容:http://tieba.baidu.com/p/3534467013
2.3 写入捕捉率源码
先在802D52C写入FF,之后重定向在802D54C的表格(这是C语言中switch语句所生成)。
可以认为每个指针都是指向一段捕捉率计算代码。Daniils和kearnseyboy6已经基本完成了要添加球的源码,我稍加修改后在这里放出:
loveball- .thumb
- .global loveball_rate
- loveball_rate:
- main:
- mov r4, #10
- bl decrypt
- cmp r0, r4
- beq yes
- pop {r0-r7}
- b ender
- yes:
- pop {r0-r7}
- mov r4, #80
- b ender
- decrypt:
- push {r0-r7}
- ldr r0, wildpokelevel
- mov r1, #0xB
- ldr r2, decryptpoke
- bx r2
- mov r4, r0
- ldr r0, yourpokelevel
- ldr r2, decryptpoke
- bx r2
- ender:
- ldr r0, catchratecalcfunction
- mov pc, r0
- .align 2
- wildpokelevel: .word 0x0202402C
- catchratecalcfunction: .word 0x0802d62a
- decryptpoke: .word 0x0803FBE9
- yourpokelevel: .word 0x02024284
复制代码 friendball- .thumb
- .global friendball_rate
- friendball_rate:
- main:
- mov r4, #10
- bl decrypt
- pop {r0-r7}
- b ender
- ender:
- ldr r0, catchratecalcfunction
- mov pc, r0
- decrypt:
- push {r0-r7}
- ldr r0, wildpoke
- mov r1, #0x20
- ldrb r2, ramoff
- ldr r3, decryptpoke
- bx r3
- .align 2
- catchratecalcfunction: .word 0x0802D62A
- decryptpoke: .word 0x0804037D
- ramoff: .word 0x02024098
- wildpoke: .word 0x0202402C
复制代码 lureball- .thumb
- .global lureball_rate
- lureball_rate:
- main:
- ldr r0, fishingbyte
- ldrb r0, [r0]
- cmp r0, #1
- beq fishing
- mov r4, #10
- b ender
- fishing:
- mov r4, #30
- ender:
- ldr r0, catchratecalcfunction
- mov pc, r0
- .align 2
- fishingbyte: .word 0x02036E38
- catchratecalcfunction: .word 0x0802d62a
复制代码 moonball- .thumb
- .global moonball_rate
- moonball_rate:
- main:
- mov r4, #10
- bl decrypt
- cmp r2, #0x1D
- beq yes
- cmp r2, #0x1E
- beq yes
- cmp r2, #0x1F
- beq yes
- cmp r2, #0x20
- beq yes
- cmp r2, #0x21
- beq yes
- cmp r2, #0x22
- beq yes
- cmp r2, #0x23
- beq yes
- cmp r2, #0x24
- beq yes
- cmp r2, #0x28
- beq yes
- cmp r2, #0x29
- beq yes
- mov r1, #0x13
- lsl r1, #0x4
- add r1, #0xB
- cmp r2, r1
- beq yes
- add r1, #0x1
- cmp r2, r1
- beq yes
- mov r1, #0x23
- lsl r1, #0x4
- add r1, #0xA
- cmp r2, r1
- beq yes
- add r1, #0x1
- cmp r2, r1
- beq yes
- beq yes
- pop {r0-r7}
- b ender
- yes:
- pop {r0-r7}
- mov r4, #40
- b ender
- decrypt:
- push {r0-r7}
- ldr r0, wildpokelevel
- mov r1, #0xB
- ldr r2, decryptpoke
- bx r2
- ender:
- ldr r0, catchratecalcfunction
- mov pc, r0
- .align 2
- wildpokelevel: .word 0x0202402C
- catchratecalcfunction: .word 0x0802d62a
- decryptpoke: .word 0x0803FBE9
复制代码 levelball- .thumb
- .global levelball_rate
- levelball_rate:
- main:
- ldr r0, yourpokelevel
- ldrb r0, [r0]
- ldr r4, wildpokelevel
- ldrb r4, [r4]
- cmp r0, r4
- bhi timestwo
- mov r4, #10
- bne ender
- timestwo:
- lsl r4, r4, #1
- cmp r0, r4
- bhi timesfour
- mov r4, #20
- bne ender
- timesfour:
- lsl r4, r4, #1
- cmp r0, r4
- bhi timeseight
- mov r4, #40
- bne ender
- timeseight:
- mov r4, #80
- ender:
- ldr r0, catchratecalcfunction
- mov pc, r0
- .align 2
- yourpokelevel: .word 0x020242D8
- wildpokelevel: .word 0x02024080
- catchratecalcfunction: .word 0x0802d62a
复制代码 fastball- .global fastball_rate
- .thumb
- fastball_rate:
- main:
- mov r4, #10
- bl decrypt
- ldr r2, pokemondata
- ldr r2, [r2]
- mov r4, #0x1C
- mul r0, r4
- add r0, r2, r0
- ldrb r1, [r0, #0x3]
- cmp r0, #0x64
- bge correct
- pop {r0-r7}
- b ender
- correct:
- pop {r0-r7}
- mov r4, #40
- ender:
- ldr r0, catchratecalcfunction
- mov pc, r0
- decrypt:
- push {r0-r7}
- ldr r0, wildpoke
- mov r1, #0xB
- ldr r2, decryptpoke
- bx r2
- .align 2
- catchratecalcfunction: .word 0x0802D62A
- decryptpoke: .word 0x0803FBE9
- wildpoke: .word 0x0202402C
- pokemondata: .word 0x80001BC
复制代码 heavyball- .thumb
- .global heavyball_rate
- heavyball_rate:
- main:
- ldr r0, pokeindex
- ldrh r0, [r0]
- mov r1, #0x24
- mul r0, r1
- ldr r1, pokedextable
- ldr r1, [r1]
- add r1, r0, r1
- add r1, r1, #0xE
- ldrh r1, [r1]
- mov r2, #0xC8
- lsl r2, #0x1
- cmp r1, r2
- bhi plusforty
- sub r2, r2, #0x64
- cmp r1, r2
- bhi plusthirty
- sub r2, r2, #0x64
- cmp r1, r2
- bhi plustwenty
- b minustwenty
- plusforty:
- add r5, r5, #40
- b ender
- plusthirty:
- add r5, r5, #30
- b ender
- plustwenty:
- add r5, r5, #20
- b ender
- minustwenty:
- sub r5, r5, #20
- ender:
- mov r4, #10
- ldr r0, catchratecalcfunction
- mov pc, r0
- .align 2
- pokeindex: .word 0x0202077E
- pokedextable: .word 0x8088e34 @改为图鉴表格地址
- catchratecalcfunction: .word 0x0802d62a
复制代码 parkball- .thumb
- .global parkball_rate
- parkball_rate:
- main:
- LDR R0, dword_2023FE8
- LDR R0, [R0]
- ADD R0, #0x7C
- LDR R0, [R0]
- LSL R1, R0, #2
- ADD R1, R1, R0
- LSL R0, R1, #8
- SUB R0, R0, R1
- MOV R1, #0x64
- swi 6
- LSL R0, R0, #0x18
- LSR R5, R0, #0x18
- park:
- mov r4, #0xff
- ldr r0, catchratecalcfunction
- mov pc, r0
- .align 2
- catchratecalcfunction: .word 0x0802D62A
- dword_2023FE8: .word 0x02023FE8
复制代码 quickball- .thumb
- .global quickball_rate
- quickball_rate:
- main:
- mov r4, #10
- ldr r0, battleturncounter
- ldrb r0, [r0]
- cmp r0, #0x0
- bne ender
- firstturn:
- add r4, #30
- ender:
- ldr r0, catchratecalcfunction
- mov pc, r0
- .align 2
- battleturncounter: .word 0x03004fa3
- catchratecalcfunction: .word 0x0802d62a
复制代码 healball- .thumb
- .global healball_rate
- healball_rate:
- mov r4, #10
- ldr r0, =0x802D62A
- mov r15, r0
- .ltorg
复制代码 duskball- .thumb
- .global duskball_rate
- duskball_rate:
- main:
- ldr r0, time
- ldrb r0, [r0, #0x0]
- cmp r0, #0x6
- blt night
- cmp r0, #0x15
- bge night
- day:
- mov r4, #10
- ldr r0, maptype
- ldrb r0, [r0]
- cmp r0, #0x4
- bne ender
- night:
- mov r4, #35
- ender:
- ldr r0, catchratecalcfunction
- mov pc, r0
- .align 2
- time: .word 0x03005542
- maptype: .word 0x02036e13
- catchratecalcfunction: .word 0x0802d62a
复制代码 sportball- .thumb
- .global sportball_rate
- sportball_rate:
- mov r4, #15
- ldr r0, =0x802D62A
- mov r15, r0
- .ltorg
复制代码 统统找空位写入将它们的指针加到重定向后表格的末端(无需+1),就像这样:- ball_routine_table:
- .long 0x802D568
- .long 0x802D598
- .long 0x802D5AA
- .long 0x802D5D8
- .long 0x802D608
- .long 0x802D5CA
- .long 0x802D5CA
- .long levelball_rate
- .long moonball_rate
- .long lureball_rate
- .long friendball_rate
- .long loveball_rate
- .long fastball_rate
- .long heavyball_rate
- .long sportball_rate
- .long duskball_rate
- .long healball_rate
- .long quickball_rate
- .long healball_rate
- .long parkball_rate
复制代码 值得注意的一点是,healball和cherishball直接公用同一个源码了,因为他们都没什么实际的捕捉率计算需求...
2.4 扩充扔球动画图片
2.4.1 变更球-素材对应方式
原版用了一个函数来转换,这里直接改为读取表格
在0x80EF53C编译并写入下面源码:- .text
- .align 2
- .thumb
- .thumb_func
- .global ballchecker
- main:
- push {lr}
- ldr r1, throwtablepositionstable
- add r0, r0, r1
- ldrb r0, [r0]
- pop {pc}
- .align 2
- throwtablepositionstable: .word 0x080EF53C
复制代码 应该一共是16字节,那么我们在0x80ef53c(就是紧跟在源码数据后)写入一张转换表。他的结构是类似于:- 00 04 03 01 00 02 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10........
复制代码 前面的不变,后面的按球编号添加。比如加入上面的那些所有球,就应该是:- 00 04 03 01 00 02 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19
复制代码 当然理论上说不按顺序也是可以的,只是这样厘清其他表格的顺序实在有点麻烦,所以一般就按上面的做法就可以。
最后别忘在80EF972和80F02D6分别写入00 00。
2.4.2 表格扩容
826056C是图片表,具体图片该是怎样尺寸可以直接到表格里找图片看。
结构:图片指针4字节+大小2字节(都一样,可以直接抄)+标签2字节(这个我是从0x1300开始给新的图片编标签(0x1300,0x1301,....),注意不要和别的可能同时出现的图片标签重复)
82605CC是色板表
结构:色板指针4字节+标签2字节(简单起见可以直接保持与图片标签一致)+00 00 2字节
82606F4是OBJ模板表
结构:图片标签2字节+色板标签2字节+2C 06 26 08 74 06 26 08 00 00 00 00 E0 06 26 08 D5 AB 04 08(只需每个模板的标签都与之前的图片、色板指针对应)
840BF48特效图片表
结构和之前的图片表相同,同样需要自己指定标签。个人建议这里就不要自己加新的图片了,直接用原版的那一张图就可以(可以看到原版所有的都公用一张图...)
840BFA8特效色板表
结构和之前的色板表相同,同样需要自己指定标签。既然前面的图片公用,色板当然也就公用吧。
840C0A4特效OBJ模板表
结构是图片标签2字节+色板标签2字节+C8 C9 3A 08 50 C0 40 08 00 00 00 00 FC 1C 23 08 0D 76 00 08(同样,要和特效图片、色板标签对应)
840C068特效图片编号表
这个表格也就是指定了哪个球对应了哪个特效图片(这里是指具体的小图):- .balign 4
- .global ball_particle_type
- ball_particle_type:
- .byte 0, 0, 0, 5, 1, 2, 2, 3, 5, 5, 4, 4, 0, 1, 2, 0, 3, 5, 4, 0, 4, 3, 1, 0, 0
复制代码 编译后也就是- 00 00 00 05 01 02 02 03 05 05 04 04 00 01 02 00 03 05 04 00 04 03 01 00 00
复制代码 0=短线 1=星星 2=水泡 3=爱心 4=绿色叉叉 5=小绿色叉叉
840C074特效控制函数表
结构:函数指针4字节
这个编写起来很麻烦,而且多半也不如原版的来的精巧,不如直接抄原版的函数指针来扩充...
2.5 healball及parkball另外的修改
这2个球要起效仅仅靠计算捕捉率是做不到的,所以需要额外源码
2.5.1 healball
这个就是做出回血的特效。- .text
- .align 2
- .thumb
- .thumb_func
- .global afterpoketranscalc
- main:
- push {lr}
- recycle:
- ldr r3, memcpy
- bl bxr3
- calc:
- cmp r7, #0x64
- bne ender
- ldr r3, somevar
- ldrb r3, [r3]
- cmp r3, #14 /*ball index of heal ball here*/
- bne ender
- healstuff:
- ldr r3, poke_quantity
- ldrb r1, [r3]
- mov r10, r1
- mov r1, #1
- strb r1, [r3]
- heal_recycle:
- mov r3, pc
- add r3, #0x1d
- push {r3}
- push {r4-r7}
- mov r7, r10
- mov r6, r9
- mov r5, r8
- push {r5-r7}
- sub sp, sp, #4
- mov r1, #0
- mov r8, r1
- mov r1, r0
- mov r10, r1
- mov r6, sp
- ldr r3, healpoke
- b bxr3
- heal_finish:
- ldr r3, poke_quantity
- mov r1, r10
- strb r1, [r3]
- ender:
- pop {r3}
- bxr3:
- bx r3
- .align 2
- memcpy: .word 0x081e5e78+1
- somevar: .word 0x0203fe00
- partyadr: .word 0x02024284
- poke_quantity: .word 0x02024029
- healpoke: .word 0x080a0076+1
复制代码 修改一下其中的ball index以及之前所指定的内存空位为你所选用的,找空位写入后再8040B08写入00 4B 9F 46 + 源码指针。
2.5.2 parkball- .text
- .align 2
- .thumb
- .thumb_func
- .global keepballcheck
- main:
- mov r5, r3
- ldr r3, returnadr
- cmp r5, #17
- bne bxr3
- add r3, #4
- bxr3:
- bx r3
- .align 2
- returnadr: .word 0x0802D7A2+1
复制代码 找空位写入后在802D6EE写入40 4B 9F 46 12 F0 EB FD 13 F0 49 FA,并在802D7EE写入70 BD + 源码指针。
3 感谢
JPAN, knizz, gogojjtech, Bela, Jambo51, bond697
4 备注
可能会有人想到球的数量提升,背包容量却未提升显得很奇怪。这个只要用上面提到过的Ta之境界扩容技能机器的帖子中的背包扩容方法就可以,感兴趣可以自己试试(我的改版是预留了球和TM两个口袋的内存空间,不具备普遍性,就不拿出来了)。
下面是仅仅提升球容量的方法by kearnseyboy6:
有任何错误请回帖指出
|
|