Sep 29, 2005

Hack Primer (1) 恶魔城-晓月圆舞曲 +Special +全能力

  首先我们需要得工具是:




  • 调试器:no$gba 1。4c

  • 模拟器+rom:vba1。2+晓月中文版

  • 16进制编辑器:UE5。4



  上面得只是我用得,当然可以用其他同样功能得工具。


  我改游戏有个习惯,不喜欢改得很变态。所以改得地方都是一些不影响游戏性得东西(我认为)。游戏里面有个special模式。不过要打穿一次才出现。那我们首先把这个弄出来。我们首先找到关键得地址是2000060h,为3h得时候就有special模式。至于这个地址怎么得到得。建议在修改之前看看ec得作弊码,类似000060h这些就直接在前面加一个2就可以了。


  打开调试器。下断点[2000060h]!。中文版会在08000820h停下(其他版本我没有弄,不知道),当然这里不是。继续080006e4h又停了,当然还是不是。最后在030021d6h停下。这里就是真正得初始化得程序了。至于为什么我知道那里是,自己多看看就明白了。


  不过千万不要在这里(030021d6)改动。因为gba游戏得rom代码得起始地址为08000000h,所以只要小于这个的都不能修改。用单步调试发现这里初始化了不只一个数据(快捷键F7是单步,这个是个很常用的键)。为了不改动到其他的数据,我们干脆在初始化了以后再给02000060h赋值为3h,这样就达到我们的目的了。


  一直F7(这里有个循环,可以用run to cursor,来直接跳出循环)到这段代码返回。返回的地方代码是这样的:



080129CC 6803 ldr r3,[r0]
080129CE 4806 ldr r0,=0E001AF8h
080129D0 2204 mov r2,4h
080129D2 F0C6F9D7 bl 80D8D84h
----------------------
080129D6>1C20 mov r0,r4
080129D8 BC30 pop r4,r5
080129DA BC02 pop r1 这里的几句是我们关心的
080129DC 4708 bx r1
---------------------
080129DE 0000 lsl r0,r0,0h
080129E0 CA78 ldmia [r2]!,r3-r6



  那个>符号就是我们下一步要执行的语句,080129D6>1C20 mov r0,r4上面的代码肯定调用了刚才的那段程序。但是这个和我们无关。那我们要自己写一段给02000060h赋值的语句,所以我们先找到一个空白的地方(一般都是0000)来放我们的代码,我找到的地方是813bc44h,所以我们修改下上面的代码。


  把原来的代码记下来,把上面的代码改成这样:



080129CC 6803 ldr r3,[r0]
080129CE 4806 ldr r0,=0E001AF8h
080129D0 2204 mov r2,4h
080129D2 F0C6F9D7 bl 80D8D84h
--------------
080129D6>B530 push r4,r5,lr
080129D8 F129F934 bl 813BC44h
080129DC 4708 bx r1
--------------
080129DE 0000 lsl r0。r0。0h
080129E0 CA78 ldmia [r2]!。r3-r6



其实写的语句只有两句。好了。跳转语句写好了。让我们跳到813bc44h来写我们的代码吧。



0813BC44>2202 mov r2。2h
0813BC46 0612 lsl r2。r2。18h
0813BC48 3260 add r2。60h
0813BC4A 2103 mov r1。3h
0813BC4C 7011 strb r1。[r2]
0813BC4E BC30 pop r4。r5 <-恢复原来的r4。r5的值
0813BC50 1C20 mov r0。r4 <---这里是我们改代码的时候覆盖的部分
0813BC52 BC30 pop r4。r5
0813BC54 BC02 pop r1
0813BC56 BD00 pop pc



  上面就是我添加的代码。很简单吧。然后用*键重新启动游戏。看看会不会出错。不会的话。就用UE打开rom。修改代码吧。这里只有一点要提醒。高低位要颠倒过来。比如这里我们添加的 2202 0612 。写的时候就要写成 0222 1206。反正4位(16进制的)一组。


  这样。我们的第一个就改好了。 改能力与这个基本相同。我只说不同的。也是关键的部分下断点以后。选择存档的时候会中断。同样是03开头的地址。而且也是多个初始化。我们F7返回到rom的代码。



08011978 1C38 mov r0。r7
0801197A F0C7FA03 bl 80D8D84h
-------------------
0801197E>4917 ldr r1。=0E0001A0h
08011980 1868 add r0。r5。r1
08011982 4642 mov r2。r8
08011984 6811 ldr r1。[r2]
08011986 3194 add r1。094h
08011988 6823 ldr r3。[r4]
0801198A 2220 mov r2。20h
0801198C F12AF966 bl 80D8D84h
------------------
08011990 4913 ldr r1。=0E0001C0h
08011992 1868 add r0。r5。r1



  这里怎么办呢?发现到这里有一个跳转指令。bl 80D8D84h。我们就干脆在这里改吧。同样的。在813BC5Ch找到空白(Konami真好。有那么多空白的地方)。bl 80D8D84h 改为 bl 813BC5Ch 然后在813BC5Ch写我们代码。


  不过看跳转指令上面的代码。有很多有用的值保存在寄存器里面,所以我们干脆把r0到r7都push。保存起来。



0813BC5C>B4FF push r0-r7
0813BC5E 2303 mov r3。3h
0813BC60 21FF mov r1。0FFh
0813BC62 2202 mov r2。2h
0813BC64 0312 lsl r2。r2。0Ch
0813BC66 3213 add r2。13h
0813BC68 0212 lsl r2。r2。8h
0813BC6A 3238 add r2。38h
0813BC6C 0112 lsl r2。r2。4h
0813BC6E 3206 add r2。6h
0813BC70 7011 strb r1。[r2]
0813BC72 3201 add r2。1h
0813BC74 3B01 sub r3。1h
0813BC76 2B00 cmp r3。0h
0813BC78 D1FA bne 813BC70h
0813BC7A 3201 add r2。1h
0813BC7C 213F mov r1。3Fh
0813BC7E 7011 strb r1。[r2]
0813BC80 BCFF pop r0-r7
0813BC82 F79DF87F bl 80D8D84h <-原来要跳转的地方
0813BC86 F6D5FE83 bl 8011990h



  这个就是我们添加的代码了。有人会问。和能力有关的不是只有02013386h到020133883h个地方吗?当然是这样。不过进入游戏以后这些能里没有默认打开。所以在0201338ah。把数据改成3fh(其实就是二进制的6个1)。那么就默认打开了。


  不过这里要提出关键的一点。就是最有一句bl 8011990h。这是原来跳转指令的下面一条指令。为什么在这里要加一句呢?因为在03XXXXXX返回的时候。是按照调用的指令寄存器的值来返回。也就是说。原来的80118c0h F79DF87F bl 80D8D84h。执行这一句前的时候。指令寄存器的地址是80118c0h。所以返回的时候就直接是8011990h(就自动返回到了他的下面一条指令)。但是我们改动了代码。所以调用指令的时候寄存器的值已经改变了。他会回到我们调用的下面一条指令的地址。就是0813BC86。所以我们要手动的让程序跳转到原来的8011990h那里。


  补一句。bl和bx的差别就像是用goto语句和调用函数的差别。函数要返回到原来的下一条指令继续执行。goto就不用。


  好拉。就这样。不知道大家明白没有。Have Fun。

0 comments:

Twitter Delicious Facebook Digg Stumbleupon Favorites More

 
Powered by Blogger